xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_opipe.c (revision 66b505f139af4f5c796430bb95355707fc3f9212)
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 2011-2021 Tintri by DDN, 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 *
smb_opipe_alloc(smb_request_t * sr)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
smb_opipe_dealloc(smb_opipe_t * opipe)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
smb_opipe_cancel(smb_request_t * sr)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
smb_opipe_connect(smb_request_t * sr,smb_opipe_t * opipe)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
smb_opipe_exists(char * name)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
smb_opipe_send_userinfo(smb_request_t * sr,smb_opipe_t * opipe,smb_error_t * errp)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 	/*
217 	 * Prepare for cancellable send/recv.
218 	 */
219 	mutex_enter(&sr->sr_mutex);
220 	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
221 		mutex_exit(&sr->sr_mutex);
222 		errp->status = NT_STATUS_CANCELLED;
223 		goto out;
224 	}
225 	sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
226 	sr->cancel_method = smb_opipe_cancel;
227 	sr->cancel_arg2 = opipe->p_socket;
228 	mutex_exit(&sr->sr_mutex);
229 
230 	rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
231 	    &iocnt, sr->user_cr);
232 	if (rc == 0 && iocnt != buflen)
233 		rc = EIO;
234 	if (rc == 0)
235 		rc = ksocket_recv(opipe->p_socket, &status, sizeof (status),
236 		    0, &iocnt, sr->user_cr);
237 	if (rc == 0 && iocnt != sizeof (status))
238 		rc = EIO;
239 
240 	/*
241 	 * Did the send/recv. complete or was it cancelled?
242 	 */
243 	mutex_enter(&sr->sr_mutex);
244 switch_state:
245 	switch (sr->sr_state) {
246 	case SMB_REQ_STATE_WAITING_PIPE:
247 		/* Normal wakeup.  Keep rc from above. */
248 		sr->sr_state = SMB_REQ_STATE_ACTIVE;
249 		break;
250 	case SMB_REQ_STATE_CANCEL_PENDING:
251 		/* cancel_method running. wait. */
252 		cv_wait(&sr->sr_st_cv, &sr->sr_mutex);
253 		goto switch_state;
254 	case SMB_REQ_STATE_CANCELLED:
255 		rc = EINTR;
256 		break;
257 	default:
258 		/* keep rc from above */
259 		break;
260 	}
261 	sr->cancel_method = NULL;
262 	sr->cancel_arg2 = NULL;
263 	mutex_exit(&sr->sr_mutex);
264 
265 	/*
266 	 * Return the status we read from the pipe service,
267 	 * normally NT_STATUS_SUCCESS, but could be something
268 	 * else like NT_STATUS_ACCESS_DENIED.
269 	 */
270 	switch (rc) {
271 	case 0:
272 		errp->status = status;
273 		break;
274 	case EINTR:
275 		errp->status = NT_STATUS_CANCELLED;
276 		break;
277 	/*
278 	 * If we fail sending the netuserinfo or recv'ing the
279 	 * status reponse, we have probably run into the limit
280 	 * on the number of open pipes.  That's this status:
281 	 */
282 	default:
283 		errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
284 		break;
285 	}
286 
287 out:
288 	xdr_destroy(&xdrs);
289 	kmem_free(buf, buflen);
290 	smb_user_netinfo_fini(&nui);
291 }
292 
293 /*
294  * smb_opipe_open
295  *
296  * Open an RPC named pipe. This routine should be called if
297  * a file open is requested on a share of type STYPE_IPC.
298  * If we recognize the pipe, we setup a new ofile.
299  *
300  * Returns 0 on success, Otherwise an NT status code.
301  */
302 int
smb_opipe_open(smb_request_t * sr,smb_ofile_t * ofile)303 smb_opipe_open(smb_request_t *sr, smb_ofile_t *ofile)
304 {
305 	smb_arg_open_t	*op = &sr->sr_open;
306 	smb_attr_t *ap = &op->fqi.fq_fattr;
307 	smb_opipe_t *opipe;
308 	smb_error_t err;
309 
310 	opipe = smb_opipe_alloc(sr);
311 	if (opipe == NULL)
312 		return (NT_STATUS_INTERNAL_ERROR);
313 
314 	if (smb_opipe_connect(sr, opipe) != 0) {
315 		smb_opipe_dealloc(opipe);
316 		return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
317 	}
318 
319 	smb_opipe_send_userinfo(sr, opipe, &err);
320 	if (err.status != 0) {
321 		smb_opipe_dealloc(opipe);
322 		return (err.status);
323 	}
324 
325 	/*
326 	 * We might have blocked in smb_opipe_connect long enough so
327 	 * a tree disconnect might have happened.  In that case, we
328 	 * would be adding an ofile to a tree that's disconnecting,
329 	 * which would interfere with tear-down.
330 	 */
331 	if (!smb_tree_is_connected(sr->tid_tree)) {
332 		smb_opipe_dealloc(opipe);
333 		return (NT_STATUS_NETWORK_NAME_DELETED);
334 	}
335 
336 	/*
337 	 * Note: The new opipe is given to smb_ofile_open
338 	 * via op->pipe
339 	 */
340 	op->pipe = opipe;
341 	smb_ofile_open(sr, op, ofile);
342 	op->pipe = NULL;
343 
344 	/* An "up" pointer, for debug. */
345 	opipe->p_ofile = ofile;
346 
347 	/*
348 	 * Caller expects attributes in op->fqi
349 	 */
350 	(void) smb_opipe_getattr(ofile, &op->fqi.fq_fattr);
351 
352 	op->dsize = 0;
353 	op->dattr = ap->sa_dosattr;
354 	op->fileid = ap->sa_vattr.va_nodeid;
355 	op->ftype = SMB_FTYPE_MESG_PIPE;
356 	op->action_taken = SMB_OACT_OPLOCK | SMB_OACT_OPENED;
357 	op->devstate = SMB_PIPE_READMODE_MESSAGE
358 	    | SMB_PIPE_TYPE_MESSAGE
359 	    | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
360 
361 	sr->smb_fid = ofile->f_fid;
362 	sr->fid_ofile = ofile;
363 
364 	return (NT_STATUS_SUCCESS);
365 }
366 
367 /*
368  * smb_opipe_close
369  *
370  * Called by smb_ofile_close for pipes.
371  *
372  * Note: ksocket_close may block while waiting for
373  * any I/O threads with a hold to get out.
374  */
375 void
smb_opipe_close(smb_ofile_t * of)376 smb_opipe_close(smb_ofile_t *of)
377 {
378 	smb_opipe_t *opipe;
379 	ksocket_t sock;
380 
381 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
382 	ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
383 	opipe = of->f_pipe;
384 	SMB_OPIPE_VALID(opipe);
385 
386 	mutex_enter(&opipe->p_mutex);
387 	sock = opipe->p_socket;
388 	opipe->p_socket = NULL;
389 	mutex_exit(&opipe->p_mutex);
390 
391 	(void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr);
392 	(void) ksocket_close(sock, of->f_cr);
393 }
394 
395 /*
396  * smb_opipe_write
397  *
398  * Write RPC request data to the pipe.  The client should call smb_opipe_read
399  * to complete the exchange and obtain the RPC response.
400  *
401  * Returns 0 on success or an errno on failure.
402  */
403 int
smb_opipe_write(smb_request_t * sr,struct uio * uio)404 smb_opipe_write(smb_request_t *sr, struct uio *uio)
405 {
406 	struct nmsghdr msghdr;
407 	smb_ofile_t *ofile;
408 	smb_opipe_t *opipe;
409 	ksocket_t sock;
410 	size_t sent = 0;
411 	int rc = 0;
412 
413 	ofile = sr->fid_ofile;
414 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
415 	opipe = ofile->f_pipe;
416 	SMB_OPIPE_VALID(opipe);
417 
418 	mutex_enter(&opipe->p_mutex);
419 	sock = opipe->p_socket;
420 	if (sock != NULL)
421 		ksocket_hold(sock);
422 	mutex_exit(&opipe->p_mutex);
423 	if (sock == NULL)
424 		return (EBADF);
425 
426 	bzero(&msghdr, sizeof (msghdr));
427 	msghdr.msg_iov = uio->uio_iov;
428 	msghdr.msg_iovlen = uio->uio_iovcnt;
429 
430 	/*
431 	 * This should block until we've sent it all,
432 	 * or given up due to errors (pipe closed).
433 	 */
434 	while (uio->uio_resid > 0) {
435 		rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr);
436 		if (rc != 0)
437 			break;
438 		uio->uio_resid -= sent;
439 	}
440 
441 	ksocket_rele(sock);
442 
443 	return (rc);
444 }
445 
446 /*
447  * smb_opipe_read
448  *
449  * This interface may be called from smb_opipe_transact (write, read)
450  * or from smb_read / smb2_read to get the rest of an RPC response.
451  * The response data (and length) are returned via the uio.
452  */
453 int
smb_opipe_read(smb_request_t * sr,struct uio * uio)454 smb_opipe_read(smb_request_t *sr, struct uio *uio)
455 {
456 	struct nmsghdr msghdr;
457 	smb_ofile_t *ofile;
458 	smb_opipe_t *opipe;
459 	ksocket_t sock;
460 	size_t recvcnt = 0;
461 	int rc;
462 
463 	ofile = sr->fid_ofile;
464 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
465 	opipe = ofile->f_pipe;
466 	SMB_OPIPE_VALID(opipe);
467 
468 	mutex_enter(&opipe->p_mutex);
469 	sock = opipe->p_socket;
470 	if (sock != NULL)
471 		ksocket_hold(sock);
472 	mutex_exit(&opipe->p_mutex);
473 	if (sock == NULL)
474 		return (EBADF);
475 
476 	/*
477 	 * Prepare for cancellable recvmsg.
478 	 */
479 	mutex_enter(&sr->sr_mutex);
480 	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
481 		mutex_exit(&sr->sr_mutex);
482 		rc = EINTR;
483 		goto out;
484 	}
485 	sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
486 	sr->cancel_method = smb_opipe_cancel;
487 	sr->cancel_arg2 = sock;
488 	mutex_exit(&sr->sr_mutex);
489 
490 	/*
491 	 * This should block only if there's no data.
492 	 * A single call to recvmsg does just that.
493 	 * (Intentionaly no recv loop here.)
494 	 */
495 	bzero(&msghdr, sizeof (msghdr));
496 	msghdr.msg_iov = uio->uio_iov;
497 	msghdr.msg_iovlen = uio->uio_iovcnt;
498 	rc = ksocket_recvmsg(sock, &msghdr, 0,
499 	    &recvcnt, ofile->f_cr);
500 
501 	/*
502 	 * Did the recvmsg complete or was it cancelled?
503 	 */
504 	mutex_enter(&sr->sr_mutex);
505 switch_state:
506 	switch (sr->sr_state) {
507 	case SMB_REQ_STATE_WAITING_PIPE:
508 		/* Normal wakeup.  Keep rc from above. */
509 		sr->sr_state = SMB_REQ_STATE_ACTIVE;
510 		break;
511 	case SMB_REQ_STATE_CANCEL_PENDING:
512 		/* cancel_method running. wait. */
513 		cv_wait(&sr->sr_st_cv, &sr->sr_mutex);
514 		goto switch_state;
515 	case SMB_REQ_STATE_CANCELLED:
516 		rc = EINTR;
517 		break;
518 	default:
519 		/* keep rc from above */
520 		break;
521 	}
522 	sr->cancel_method = NULL;
523 	sr->cancel_arg2 = NULL;
524 	mutex_exit(&sr->sr_mutex);
525 
526 	if (rc != 0)
527 		goto out;
528 
529 	if (recvcnt == 0) {
530 		/* Other side closed. */
531 		rc = EPIPE;
532 		goto out;
533 	}
534 	uio->uio_resid -= recvcnt;
535 
536 out:
537 	ksocket_rele(sock);
538 
539 	return (rc);
540 }
541 
542 int
smb_opipe_ioctl(smb_request_t * sr,int cmd,void * arg,int * rvalp)543 smb_opipe_ioctl(smb_request_t *sr, int cmd, void *arg, int *rvalp)
544 {
545 	smb_ofile_t *ofile;
546 	smb_opipe_t *opipe;
547 	ksocket_t sock;
548 	int rc;
549 
550 	ofile = sr->fid_ofile;
551 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
552 	opipe = ofile->f_pipe;
553 	SMB_OPIPE_VALID(opipe);
554 
555 	mutex_enter(&opipe->p_mutex);
556 	sock = opipe->p_socket;
557 	if (sock != NULL)
558 		ksocket_hold(sock);
559 	mutex_exit(&opipe->p_mutex);
560 	if (sock == NULL)
561 		return (EBADF);
562 
563 	rc = ksocket_ioctl(sock, cmd, (intptr_t)arg, rvalp, ofile->f_cr);
564 
565 	ksocket_rele(sock);
566 
567 	return (rc);
568 }
569 
570 /*
571  * Get the smb_attr_t for a named pipe.
572  * Caller has already cleared to zero.
573  */
574 int
smb_opipe_getattr(smb_ofile_t * of,smb_attr_t * ap)575 smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
576 {
577 
578 	if (of->f_pipe == NULL)
579 		return (EINVAL);
580 
581 	ap->sa_vattr.va_type = VFIFO;
582 	ap->sa_vattr.va_nlink = 1;
583 	ap->sa_vattr.va_nodeid = (uintptr_t)of->f_pipe;
584 	ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
585 	ap->sa_allocsz = SMB_PIPE_MAX_MSGSIZE;
586 
587 	return (0);
588 }
589 
590 int
smb_opipe_getname(smb_ofile_t * of,char * buf,size_t buflen)591 smb_opipe_getname(smb_ofile_t *of, char *buf, size_t buflen)
592 {
593 	smb_opipe_t *opipe;
594 
595 	if ((opipe = of->f_pipe) == NULL)
596 		return (EINVAL);
597 
598 	(void) snprintf(buf, buflen, "\\%s", opipe->p_name);
599 	return (0);
600 }
601 
602 /*
603  * Handle device type FILE_DEVICE_NAMED_PIPE
604  * for smb2_ioctl
605  */
606 /* ARGSUSED */
607 uint32_t
smb_opipe_fsctl(smb_request_t * sr,smb_fsctl_t * fsctl)608 smb_opipe_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
609 {
610 	uint32_t status;
611 
612 	if (!STYPE_ISIPC(sr->tid_tree->t_res_type))
613 		return (NT_STATUS_INVALID_DEVICE_REQUEST);
614 
615 	switch (fsctl->CtlCode) {
616 	case FSCTL_PIPE_TRANSCEIVE:
617 		status = smb_opipe_transceive(sr, fsctl);
618 		break;
619 
620 	case FSCTL_PIPE_PEEK:
621 		status = NT_STATUS_INVALID_DEVICE_REQUEST;
622 		break;
623 
624 	case FSCTL_PIPE_WAIT:
625 		status = smb_opipe_wait(sr, fsctl);
626 		break;
627 
628 	default:
629 		ASSERT(!"CtlCode");
630 		status = NT_STATUS_INTERNAL_ERROR;
631 		break;
632 	}
633 
634 	return (status);
635 }
636 
637 uint32_t
smb_opipe_transceive(smb_request_t * sr,smb_fsctl_t * fsctl)638 smb_opipe_transceive(smb_request_t *sr, smb_fsctl_t *fsctl)
639 {
640 	smb_vdb_t	*vdb;
641 	smb_ofile_t	*ofile;
642 	struct mbuf	*mb;
643 	uint32_t	status;
644 	int		len, rc;
645 
646 	/*
647 	 * Caller checked that this is the IPC$ share,
648 	 * and that this call has a valid open handle.
649 	 * Just check the type.
650 	 */
651 	ofile = sr->fid_ofile;
652 	if (ofile->f_ftype != SMB_FTYPE_MESG_PIPE)
653 		return (NT_STATUS_INVALID_HANDLE);
654 
655 	/*
656 	 * The VDB is a bit large.  Allocate.
657 	 * This is automatically free'd with the SR
658 	 */
659 	vdb = smb_srm_zalloc(sr, sizeof (*vdb));
660 	rc = smb_mbc_decodef(fsctl->in_mbc, "#B",
661 	    fsctl->InputCount, vdb);
662 	if (rc != 0) {
663 		/* Not enough data sent. */
664 		return (NT_STATUS_INVALID_PARAMETER);
665 	}
666 
667 	rc = smb_opipe_write(sr, &vdb->vdb_uio);
668 	if (rc != 0)
669 		return (smb_errno2status(rc));
670 
671 	vdb->vdb_tag = 0;
672 	vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
673 	vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
674 	vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
675 	vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
676 	vdb->vdb_uio.uio_loffset = (offset_t)0;
677 	vdb->vdb_uio.uio_resid = fsctl->MaxOutputResp;
678 	mb = smb_mbuf_allocate(&vdb->vdb_uio);
679 
680 	rc = smb_opipe_read(sr, &vdb->vdb_uio);
681 	if (rc != 0) {
682 		m_freem(mb);
683 		return (smb_errno2status(rc));
684 	}
685 
686 	len = fsctl->MaxOutputResp - vdb->vdb_uio.uio_resid;
687 	smb_mbuf_trim(mb, len);
688 	MBC_ATTACH_MBUF(fsctl->out_mbc, mb);
689 
690 	/*
691 	 * If the output buffer holds a partial pipe message,
692 	 * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
693 	 * As we don't have message boundary markers, the best
694 	 * we can do is return that status when we have ALL of:
695 	 *	Output buffer was < SMB_PIPE_MAX_MSGSIZE
696 	 *	We filled the output buffer (resid==0)
697 	 *	There's more data (ioctl FIONREAD)
698 	 */
699 	status = NT_STATUS_SUCCESS;
700 	if (fsctl->MaxOutputResp < SMB_PIPE_MAX_MSGSIZE &&
701 	    vdb->vdb_uio.uio_resid == 0) {
702 		int nread = 0, trval;
703 		rc = smb_opipe_ioctl(sr, FIONREAD, &nread, &trval);
704 		if (rc == 0 && nread != 0)
705 			status = NT_STATUS_BUFFER_OVERFLOW;
706 	}
707 
708 	return (status);
709 }
710 
711 static uint32_t
smb_opipe_wait(smb_request_t * sr,smb_fsctl_t * fsctl)712 smb_opipe_wait(smb_request_t *sr, smb_fsctl_t *fsctl)
713 {
714 	char		*name;
715 	uint64_t	timeout;
716 	uint32_t	namelen;
717 	int		rc;
718 	uint8_t		tflag;
719 
720 	rc = smb_mbc_decodef(fsctl->in_mbc, "qlb.",
721 	    &timeout,	/* q */
722 	    &namelen,	/* l */
723 	    &tflag);	/* b */
724 	if (rc != 0)
725 		return (NT_STATUS_INVALID_PARAMETER);
726 	rc = smb_mbc_decodef(fsctl->in_mbc, "%#U",
727 	    sr,		/* % */
728 	    namelen,	/* # */
729 	    &name);	/* U */
730 	if (rc != 0)
731 		return (NT_STATUS_INVALID_PARAMETER);
732 
733 	rc = smb_opipe_exists(name);
734 	if (rc != 0)
735 		return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
736 
737 	/*
738 	 * At this point we know the pipe exists.
739 	 *
740 	 * If the tflag is set, we're supposed to wait for up to
741 	 * timeout (100s of milliseconds) for a pipe "instance"
742 	 * to become "available" (so pipe open would work).
743 	 * However, this implementation has no need to wait,
744 	 * so just take a short delay instead.
745 	 */
746 	if (tflag != 0) {
747 		clock_t ticks = MSEC_TO_TICK(timeout * 100);
748 		if (ticks > MSEC_TO_TICK(100))
749 			ticks = MSEC_TO_TICK(100);
750 		delay(ticks);
751 	}
752 
753 	return (0);
754 }
755