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