1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 /*
27  * This module provides the interface to NDR RPC.
28  */
29 
30 #include <sys/stat.h>
31 #include <sys/uio.h>
32 #include <sys/ksynch.h>
33 #include <sys/stropts.h>
34 #include <sys/socket.h>
35 #include <sys/filio.h>
36 #include <smbsrv/smb_kproto.h>
37 #include <smbsrv/smb_xdr.h>
38 #include <smb/winioctl.h>
39 
40 /*
41  * Allocate a new opipe and return it, or NULL, in which case
42  * the caller will report "internal error".
43  */
44 static smb_opipe_t *
smb_opipe_alloc(smb_request_t * sr)45 smb_opipe_alloc(smb_request_t *sr)
46 {
47 	smb_server_t	*sv = sr->sr_server;
48 	smb_opipe_t	*opipe;
49 	ksocket_t	sock;
50 
51 	if (ksocket_socket(&sock, AF_UNIX, SOCK_STREAM, 0,
52 	    KSOCKET_SLEEP, sr->user_cr) != 0)
53 		return (NULL);
54 
55 	opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP);
56 
57 	bzero(opipe, sizeof (smb_opipe_t));
58 	mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL);
59 	cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL);
60 	opipe->p_magic = SMB_OPIPE_MAGIC;
61 	opipe->p_server = sv;
62 	opipe->p_refcnt = 1;
63 	opipe->p_socket = sock;
64 
65 	return (opipe);
66 }
67 
68 /*
69  * Destroy an opipe.  This is normally called from smb_ofile_delete
70  * when the ofile has no more references and is about to be free'd.
71  * This is also called here in error handling code paths, before
72  * the opipe is installed under an ofile.
73  */
74 void
smb_opipe_dealloc(smb_opipe_t * opipe)75 smb_opipe_dealloc(smb_opipe_t *opipe)
76 {
77 	smb_server_t *sv;
78 
79 	SMB_OPIPE_VALID(opipe);
80 	sv = opipe->p_server;
81 	SMB_SERVER_VALID(sv);
82 
83 	/*
84 	 * This is called in the error path when opening,
85 	 * in which case we close the socket here.
86 	 */
87 	if (opipe->p_socket != NULL)
88 		(void) ksocket_close(opipe->p_socket, zone_kcred());
89 
90 	opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC;
91 	cv_destroy(&opipe->p_cv);
92 	mutex_destroy(&opipe->p_mutex);
93 
94 	kmem_cache_free(smb_cache_opipe, opipe);
95 }
96 
97 /*
98  * Unblock a request that might be blocked reading some
99  * pipe (AF_UNIX socket).  We don't have an easy way to
100  * interrupt just the thread servicing this request, so
101  * we shutdown(3socket) the socket, waking all readers.
102  * That's a bit heavy-handed, making the socket unusable
103  * after this, so we do this only when disconnecting a
104  * session (i.e. stopping the SMB service), and not when
105  * handling an SMB2_cancel or SMB_nt_cancel request.
106  */
107 static void
smb_opipe_cancel(smb_request_t * sr)108 smb_opipe_cancel(smb_request_t *sr)
109 {
110 	ksocket_t so;
111 
112 	switch (sr->session->s_state) {
113 	case SMB_SESSION_STATE_DISCONNECTED:
114 	case SMB_SESSION_STATE_TERMINATED:
115 		if ((so = sr->cancel_arg2) != NULL)
116 			(void) ksocket_shutdown(so, SHUT_RDWR, sr->user_cr);
117 		break;
118 	}
119 }
120 
121 /*
122  * Helper for open: build pipe name and connect.
123  */
124 static int
smb_opipe_connect(smb_request_t * sr,smb_opipe_t * opipe)125 smb_opipe_connect(smb_request_t *sr, smb_opipe_t *opipe)
126 {
127 	struct sockaddr_un saddr;
128 	smb_arg_open_t	*op = &sr->sr_open;
129 	const char *name;
130 	int rc;
131 
132 	name = op->fqi.fq_path.pn_path;
133 	name += strspn(name, "\\");
134 	if (smb_strcasecmp(name, "PIPE", 4) == 0) {
135 		name += 4;
136 		name += strspn(name, "\\");
137 	}
138 	(void) strlcpy(opipe->p_name, name, SMB_OPIPE_MAXNAME);
139 	(void) smb_strlwr(opipe->p_name);
140 
141 	bzero(&saddr, sizeof (saddr));
142 	saddr.sun_family = AF_UNIX;
143 	(void) snprintf(saddr.sun_path, sizeof (saddr.sun_path),
144 	    "%s/%s", SMB_PIPE_DIR, opipe->p_name);
145 	rc = ksocket_connect(opipe->p_socket, (struct sockaddr *)&saddr,
146 	    sizeof (saddr), sr->user_cr);
147 
148 	return (rc);
149 }
150 
151 /*
152  * Helper for open: encode and send the user info.
153  *
154  * We send information about this client + user to the
155  * pipe service so it can use it for access checks.
156  * The service MAY deny the open based on this info,
157  * (i.e. anonymous session trying to open a pipe that
158  * requires authentication) in which case we will read
159  * an error status from the service and return that.
160  */
161 static void
smb_opipe_send_userinfo(smb_request_t * sr,smb_opipe_t * opipe,smb_error_t * errp)162 smb_opipe_send_userinfo(smb_request_t *sr, smb_opipe_t *opipe,
163     smb_error_t *errp)
164 {
165 	XDR xdrs;
166 	smb_netuserinfo_t nui;
167 	smb_pipehdr_t phdr;
168 	char *buf;
169 	uint32_t buflen;
170 	uint32_t status;
171 	size_t iocnt = 0;
172 	int rc;
173 
174 	/*
175 	 * Any errors building the XDR message etc.
176 	 */
177 	errp->status = NT_STATUS_INTERNAL_ERROR;
178 
179 	smb_user_netinfo_init(sr->uid_user, &nui);
180 	phdr.ph_magic = SMB_PIPE_HDR_MAGIC;
181 	phdr.ph_uilen = xdr_sizeof(smb_netuserinfo_xdr, &nui);
182 
183 	buflen = sizeof (phdr) + phdr.ph_uilen;
184 	buf = kmem_alloc(buflen, KM_SLEEP);
185 
186 	bcopy(&phdr, buf, sizeof (phdr));
187 	xdrmem_create(&xdrs, buf + sizeof (phdr),
188 	    buflen - (sizeof (phdr)), XDR_ENCODE);
189 	if (!smb_netuserinfo_xdr(&xdrs, &nui))
190 		goto out;
191 
192 	mutex_enter(&sr->sr_mutex);
193 	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
194 		mutex_exit(&sr->sr_mutex);
195 		errp->status = NT_STATUS_CANCELLED;
196 		goto out;
197 	}
198 	sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
199 	sr->cancel_method = smb_opipe_cancel;
200 	sr->cancel_arg2 = opipe->p_socket;
201 	mutex_exit(&sr->sr_mutex);
202 
203 	rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
204 	    &iocnt, sr->user_cr);
205 	if (rc == 0 && iocnt != buflen)
206 		rc = EIO;
207 	if (rc == 0)
208 		rc = ksocket_recv(opipe->p_socket, &status, sizeof (status),
209 		    0, &iocnt, sr->user_cr);
210 	if (rc == 0 && iocnt != sizeof (status))
211 		rc = EIO;
212 
213 	mutex_enter(&sr->sr_mutex);
214 	sr->cancel_method = NULL;
215 	sr->cancel_arg2 = NULL;
216 	switch (sr->sr_state) {
217 	case SMB_REQ_STATE_WAITING_PIPE:
218 		sr->sr_state = SMB_REQ_STATE_ACTIVE;
219 		break;
220 	case SMB_REQ_STATE_CANCEL_PENDING:
221 		sr->sr_state = SMB_REQ_STATE_CANCELLED;
222 		rc = EINTR;
223 		break;
224 	default:
225 		/* keep rc from above */
226 		break;
227 	}
228 	mutex_exit(&sr->sr_mutex);
229 
230 
231 	/*
232 	 * Return the status we read from the pipe service,
233 	 * normally NT_STATUS_SUCCESS, but could be something
234 	 * else like NT_STATUS_ACCESS_DENIED.
235 	 */
236 	switch (rc) {
237 	case 0:
238 		errp->status = status;
239 		break;
240 	case EINTR:
241 		errp->status = NT_STATUS_CANCELLED;
242 		break;
243 	/*
244 	 * If we fail sending the netuserinfo or recv'ing the
245 	 * status reponse, we have probably run into the limit
246 	 * on the number of open pipes.  That's this status:
247 	 */
248 	default:
249 		errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
250 		break;
251 	}
252 
253 out:
254 	xdr_destroy(&xdrs);
255 	kmem_free(buf, buflen);
256 	smb_user_netinfo_fini(&nui);
257 }
258 
259 /*
260  * smb_opipe_open
261  *
262  * Open an RPC named pipe. This routine should be called if
263  * a file open is requested on a share of type STYPE_IPC.
264  * If we recognize the pipe, we setup a new ofile.
265  *
266  * Returns 0 on success, Otherwise an NT status code.
267  */
268 int
smb_opipe_open(smb_request_t * sr,smb_ofile_t * ofile)269 smb_opipe_open(smb_request_t *sr, smb_ofile_t *ofile)
270 {
271 	smb_arg_open_t	*op = &sr->sr_open;
272 	smb_attr_t *ap = &op->fqi.fq_fattr;
273 	smb_opipe_t *opipe;
274 	smb_error_t err;
275 
276 	opipe = smb_opipe_alloc(sr);
277 	if (opipe == NULL)
278 		return (NT_STATUS_INTERNAL_ERROR);
279 
280 	if (smb_opipe_connect(sr, opipe) != 0) {
281 		smb_opipe_dealloc(opipe);
282 		return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
283 	}
284 
285 	smb_opipe_send_userinfo(sr, opipe, &err);
286 	if (err.status != 0) {
287 		smb_opipe_dealloc(opipe);
288 		return (err.status);
289 	}
290 
291 	/*
292 	 * We might have blocked in smb_opipe_connect long enough so
293 	 * a tree disconnect might have happened.  In that case, we
294 	 * would be adding an ofile to a tree that's disconnecting,
295 	 * which would interfere with tear-down.
296 	 */
297 	if (!smb_tree_is_connected(sr->tid_tree)) {
298 		smb_opipe_dealloc(opipe);
299 		return (NT_STATUS_NETWORK_NAME_DELETED);
300 	}
301 
302 	/*
303 	 * Note: The new opipe is given to smb_ofile_open
304 	 * via op->pipe
305 	 */
306 	op->pipe = opipe;
307 	smb_ofile_open(sr, op, ofile);
308 	op->pipe = NULL;
309 
310 	/* An "up" pointer, for debug. */
311 	opipe->p_ofile = ofile;
312 
313 	/*
314 	 * Caller expects attributes in op->fqi
315 	 */
316 	(void) smb_opipe_getattr(ofile, &op->fqi.fq_fattr);
317 
318 	op->dsize = 0;
319 	op->dattr = ap->sa_dosattr;
320 	op->fileid = ap->sa_vattr.va_nodeid;
321 	op->ftype = SMB_FTYPE_MESG_PIPE;
322 	op->action_taken = SMB_OACT_OPLOCK | SMB_OACT_OPENED;
323 	op->devstate = SMB_PIPE_READMODE_MESSAGE
324 	    | SMB_PIPE_TYPE_MESSAGE
325 	    | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
326 
327 	sr->smb_fid = ofile->f_fid;
328 	sr->fid_ofile = ofile;
329 
330 	return (NT_STATUS_SUCCESS);
331 }
332 
333 /*
334  * smb_opipe_close
335  *
336  * Called by smb_ofile_close for pipes.
337  *
338  * Note: ksocket_close may block while waiting for
339  * any I/O threads with a hold to get out.
340  */
341 void
smb_opipe_close(smb_ofile_t * of)342 smb_opipe_close(smb_ofile_t *of)
343 {
344 	smb_opipe_t *opipe;
345 	ksocket_t sock;
346 
347 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
348 	ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
349 	opipe = of->f_pipe;
350 	SMB_OPIPE_VALID(opipe);
351 
352 	mutex_enter(&opipe->p_mutex);
353 	sock = opipe->p_socket;
354 	opipe->p_socket = NULL;
355 	mutex_exit(&opipe->p_mutex);
356 
357 	(void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr);
358 	(void) ksocket_close(sock, of->f_cr);
359 }
360 
361 /*
362  * smb_opipe_write
363  *
364  * Write RPC request data to the pipe.  The client should call smb_opipe_read
365  * to complete the exchange and obtain the RPC response.
366  *
367  * Returns 0 on success or an errno on failure.
368  */
369 int
smb_opipe_write(smb_request_t * sr,struct uio * uio)370 smb_opipe_write(smb_request_t *sr, struct uio *uio)
371 {
372 	struct nmsghdr msghdr;
373 	smb_ofile_t *ofile;
374 	smb_opipe_t *opipe;
375 	ksocket_t sock;
376 	size_t sent = 0;
377 	int rc = 0;
378 
379 	ofile = sr->fid_ofile;
380 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
381 	opipe = ofile->f_pipe;
382 	SMB_OPIPE_VALID(opipe);
383 
384 	mutex_enter(&opipe->p_mutex);
385 	sock = opipe->p_socket;
386 	if (sock != NULL)
387 		ksocket_hold(sock);
388 	mutex_exit(&opipe->p_mutex);
389 	if (sock == NULL)
390 		return (EBADF);
391 
392 	bzero(&msghdr, sizeof (msghdr));
393 	msghdr.msg_iov = uio->uio_iov;
394 	msghdr.msg_iovlen = uio->uio_iovcnt;
395 
396 	/*
397 	 * This should block until we've sent it all,
398 	 * or given up due to errors (pipe closed).
399 	 */
400 	while (uio->uio_resid > 0) {
401 		rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr);
402 		if (rc != 0)
403 			break;
404 		uio->uio_resid -= sent;
405 	}
406 
407 	ksocket_rele(sock);
408 
409 	return (rc);
410 }
411 
412 /*
413  * smb_opipe_read
414  *
415  * This interface may be called from smb_opipe_transact (write, read)
416  * or from smb_read / smb2_read to get the rest of an RPC response.
417  * The response data (and length) are returned via the uio.
418  */
419 int
smb_opipe_read(smb_request_t * sr,struct uio * uio)420 smb_opipe_read(smb_request_t *sr, struct uio *uio)
421 {
422 	struct nmsghdr msghdr;
423 	smb_ofile_t *ofile;
424 	smb_opipe_t *opipe;
425 	ksocket_t sock;
426 	size_t recvcnt = 0;
427 	int rc;
428 
429 	ofile = sr->fid_ofile;
430 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
431 	opipe = ofile->f_pipe;
432 	SMB_OPIPE_VALID(opipe);
433 
434 	mutex_enter(&opipe->p_mutex);
435 	sock = opipe->p_socket;
436 	if (sock != NULL)
437 		ksocket_hold(sock);
438 	mutex_exit(&opipe->p_mutex);
439 	if (sock == NULL)
440 		return (EBADF);
441 
442 	mutex_enter(&sr->sr_mutex);
443 	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
444 		mutex_exit(&sr->sr_mutex);
445 		rc = EINTR;
446 		goto out;
447 	}
448 	sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
449 	sr->cancel_method = smb_opipe_cancel;
450 	sr->cancel_arg2 = sock;
451 	mutex_exit(&sr->sr_mutex);
452 
453 	/*
454 	 * This should block only if there's no data.
455 	 * A single call to recvmsg does just that.
456 	 * (Intentionaly no recv loop here.)
457 	 */
458 	bzero(&msghdr, sizeof (msghdr));
459 	msghdr.msg_iov = uio->uio_iov;
460 	msghdr.msg_iovlen = uio->uio_iovcnt;
461 	rc = ksocket_recvmsg(sock, &msghdr, 0,
462 	    &recvcnt, ofile->f_cr);
463 
464 	mutex_enter(&sr->sr_mutex);
465 	sr->cancel_method = NULL;
466 	sr->cancel_arg2 = NULL;
467 	switch (sr->sr_state) {
468 	case SMB_REQ_STATE_WAITING_PIPE:
469 		sr->sr_state = SMB_REQ_STATE_ACTIVE;
470 		break;
471 	case SMB_REQ_STATE_CANCEL_PENDING:
472 		sr->sr_state = SMB_REQ_STATE_CANCELLED;
473 		rc = EINTR;
474 		break;
475 	default:
476 		/* keep rc from above */
477 		break;
478 	}
479 	mutex_exit(&sr->sr_mutex);
480 
481 	if (rc != 0)
482 		goto out;
483 
484 	if (recvcnt == 0) {
485 		/* Other side closed. */
486 		rc = EPIPE;
487 		goto out;
488 	}
489 	uio->uio_resid -= recvcnt;
490 
491 out:
492 	ksocket_rele(sock);
493 
494 	return (rc);
495 }
496 
497 int
smb_opipe_ioctl(smb_request_t * sr,int cmd,void * arg,int * rvalp)498 smb_opipe_ioctl(smb_request_t *sr, int cmd, void *arg, int *rvalp)
499 {
500 	smb_ofile_t *ofile;
501 	smb_opipe_t *opipe;
502 	ksocket_t sock;
503 	int rc;
504 
505 	ofile = sr->fid_ofile;
506 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
507 	opipe = ofile->f_pipe;
508 	SMB_OPIPE_VALID(opipe);
509 
510 	mutex_enter(&opipe->p_mutex);
511 	sock = opipe->p_socket;
512 	if (sock != NULL)
513 		ksocket_hold(sock);
514 	mutex_exit(&opipe->p_mutex);
515 	if (sock == NULL)
516 		return (EBADF);
517 
518 	rc = ksocket_ioctl(sock, cmd, (intptr_t)arg, rvalp, ofile->f_cr);
519 
520 	ksocket_rele(sock);
521 
522 	return (rc);
523 }
524 
525 /*
526  * Get the smb_attr_t for a named pipe.
527  * Caller has already cleared to zero.
528  */
529 int
smb_opipe_getattr(smb_ofile_t * of,smb_attr_t * ap)530 smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
531 {
532 
533 	if (of->f_pipe == NULL)
534 		return (EINVAL);
535 
536 	ap->sa_vattr.va_type = VFIFO;
537 	ap->sa_vattr.va_nlink = 1;
538 	ap->sa_vattr.va_nodeid = (uintptr_t)of->f_pipe;
539 	ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
540 	ap->sa_allocsz = SMB_PIPE_MAX_MSGSIZE;
541 
542 	return (0);
543 }
544 
545 int
smb_opipe_getname(smb_ofile_t * of,char * buf,size_t buflen)546 smb_opipe_getname(smb_ofile_t *of, char *buf, size_t buflen)
547 {
548 	smb_opipe_t *opipe;
549 
550 	if ((opipe = of->f_pipe) == NULL)
551 		return (EINVAL);
552 
553 	(void) snprintf(buf, buflen, "\\%s", opipe->p_name);
554 	return (0);
555 }
556 
557 /*
558  * Handle device type FILE_DEVICE_NAMED_PIPE
559  * for smb2_ioctl
560  */
561 /* ARGSUSED */
562 uint32_t
smb_opipe_fsctl(smb_request_t * sr,smb_fsctl_t * fsctl)563 smb_opipe_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
564 {
565 	uint32_t status;
566 
567 	if (!STYPE_ISIPC(sr->tid_tree->t_res_type))
568 		return (NT_STATUS_INVALID_DEVICE_REQUEST);
569 
570 	switch (fsctl->CtlCode) {
571 	case FSCTL_PIPE_TRANSCEIVE:
572 		status = smb_opipe_transceive(sr, fsctl);
573 		break;
574 
575 	case FSCTL_PIPE_PEEK:
576 	case FSCTL_PIPE_WAIT:
577 		/* XXX todo */
578 		status = NT_STATUS_NOT_SUPPORTED;
579 		break;
580 
581 	default:
582 		ASSERT(!"CtlCode");
583 		status = NT_STATUS_INTERNAL_ERROR;
584 		break;
585 	}
586 
587 	return (status);
588 }
589 
590 uint32_t
smb_opipe_transceive(smb_request_t * sr,smb_fsctl_t * fsctl)591 smb_opipe_transceive(smb_request_t *sr, smb_fsctl_t *fsctl)
592 {
593 	smb_vdb_t	vdb;
594 	smb_ofile_t	*ofile;
595 	struct mbuf	*mb;
596 	uint32_t	status;
597 	int		len, rc;
598 
599 	/*
600 	 * Caller checked that this is the IPC$ share,
601 	 * and that this call has a valid open handle.
602 	 * Just check the type.
603 	 */
604 	ofile = sr->fid_ofile;
605 	if (ofile->f_ftype != SMB_FTYPE_MESG_PIPE)
606 		return (NT_STATUS_INVALID_HANDLE);
607 
608 	rc = smb_mbc_decodef(fsctl->in_mbc, "#B",
609 	    fsctl->InputCount, &vdb);
610 	if (rc != 0) {
611 		/* Not enough data sent. */
612 		return (NT_STATUS_INVALID_PARAMETER);
613 	}
614 
615 	rc = smb_opipe_write(sr, &vdb.vdb_uio);
616 	if (rc != 0)
617 		return (smb_errno2status(rc));
618 
619 	vdb.vdb_tag = 0;
620 	vdb.vdb_uio.uio_iov = &vdb.vdb_iovec[0];
621 	vdb.vdb_uio.uio_iovcnt = MAX_IOVEC;
622 	vdb.vdb_uio.uio_segflg = UIO_SYSSPACE;
623 	vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
624 	vdb.vdb_uio.uio_loffset = (offset_t)0;
625 	vdb.vdb_uio.uio_resid = fsctl->MaxOutputResp;
626 	mb = smb_mbuf_allocate(&vdb.vdb_uio);
627 
628 	rc = smb_opipe_read(sr, &vdb.vdb_uio);
629 	if (rc != 0) {
630 		m_freem(mb);
631 		return (smb_errno2status(rc));
632 	}
633 
634 	len = fsctl->MaxOutputResp - vdb.vdb_uio.uio_resid;
635 	smb_mbuf_trim(mb, len);
636 	MBC_ATTACH_MBUF(fsctl->out_mbc, mb);
637 
638 	/*
639 	 * If the output buffer holds a partial pipe message,
640 	 * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
641 	 * As we don't have message boundary markers, the best
642 	 * we can do is return that status when we have ALL of:
643 	 *	Output buffer was < SMB_PIPE_MAX_MSGSIZE
644 	 *	We filled the output buffer (resid==0)
645 	 *	There's more data (ioctl FIONREAD)
646 	 */
647 	status = NT_STATUS_SUCCESS;
648 	if (fsctl->MaxOutputResp < SMB_PIPE_MAX_MSGSIZE &&
649 	    vdb.vdb_uio.uio_resid == 0) {
650 		int nread = 0, trval;
651 		rc = smb_opipe_ioctl(sr, FIONREAD, &nread, &trval);
652 		if (rc == 0 && nread != 0)
653 			status = NT_STATUS_BUFFER_OVERFLOW;
654 	}
655 
656 	return (status);
657 }
658