13db3f65cSamw /*
23db3f65cSamw * CDDL HEADER START
33db3f65cSamw *
43db3f65cSamw * The contents of this file are subject to the terms of the
53db3f65cSamw * Common Development and Distribution License (the "License").
63db3f65cSamw * You may not use this file except in compliance with the License.
73db3f65cSamw *
83db3f65cSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93db3f65cSamw * or http://www.opensolaris.org/os/licensing.
103db3f65cSamw * See the License for the specific language governing permissions
113db3f65cSamw * and limitations under the License.
123db3f65cSamw *
133db3f65cSamw * When distributing Covered Code, include this CDDL HEADER in each
143db3f65cSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153db3f65cSamw * If applicable, add the following below this CDDL HEADER, with the
163db3f65cSamw * fields enclosed by brackets "[]" replaced with your own identifying
173db3f65cSamw * information: Portions Copyright [yyyy] [name of copyright owner]
183db3f65cSamw *
193db3f65cSamw * CDDL HEADER END
203db3f65cSamw */
213db3f65cSamw /*
22148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23c0e62236SGordon Ross * Copyright 2011-2021 Tintri by DDN, Inc. All rights reserved.
24268cac54SGordon Ross * Copyright 2022 RackTop Systems, Inc.
253db3f65cSamw */
263db3f65cSamw
273db3f65cSamw /*
283db3f65cSamw * This module provides the interface to NDR RPC.
293db3f65cSamw */
303db3f65cSamw
313db3f65cSamw #include <sys/stat.h>
323db3f65cSamw #include <sys/uio.h>
333db3f65cSamw #include <sys/ksynch.h>
3468b2bbf2SGordon Ross #include <sys/stropts.h>
3568b2bbf2SGordon Ross #include <sys/socket.h>
3668b2bbf2SGordon Ross #include <sys/filio.h>
37bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
383db3f65cSamw #include <smbsrv/smb_xdr.h>
39adee6784SGordon Ross #include <smb/winioctl.h>
40a90cf9f2SGordon Ross
41268cac54SGordon Ross static uint32_t smb_opipe_wait(smb_request_t *, smb_fsctl_t *);
42268cac54SGordon Ross
4368b2bbf2SGordon Ross /*
4468b2bbf2SGordon Ross * Allocate a new opipe and return it, or NULL, in which case
4568b2bbf2SGordon Ross * the caller will report "internal error".
4668b2bbf2SGordon Ross */
4768b2bbf2SGordon Ross static smb_opipe_t *
smb_opipe_alloc(smb_request_t * sr)4868b2bbf2SGordon Ross smb_opipe_alloc(smb_request_t *sr)
499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
5068b2bbf2SGordon Ross smb_server_t *sv = sr->sr_server;
519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_t *opipe;
5268b2bbf2SGordon Ross ksocket_t sock;
5368b2bbf2SGordon Ross
5468b2bbf2SGordon Ross if (ksocket_socket(&sock, AF_UNIX, SOCK_STREAM, 0,
5568b2bbf2SGordon Ross KSOCKET_SLEEP, sr->user_cr) != 0)
5668b2bbf2SGordon Ross return (NULL);
579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
588622ec45SGordon Ross opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP);
599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(opipe, sizeof (smb_opipe_t));
619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL);
629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL);
639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_magic = SMB_OPIPE_MAGIC;
649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_server = sv;
6568b2bbf2SGordon Ross opipe->p_refcnt = 1;
6668b2bbf2SGordon Ross opipe->p_socket = sock;
679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (opipe);
699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
7168b2bbf2SGordon Ross /*
7268b2bbf2SGordon Ross * Destroy an opipe. This is normally called from smb_ofile_delete
7368b2bbf2SGordon Ross * when the ofile has no more references and is about to be free'd.
7468b2bbf2SGordon Ross * This is also called here in error handling code paths, before
7568b2bbf2SGordon Ross * the opipe is installed under an ofile.
7668b2bbf2SGordon Ross */
779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_opipe_dealloc(smb_opipe_t * opipe)789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_dealloc(smb_opipe_t *opipe)
799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_t *sv;
819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe);
839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States sv = opipe->p_server;
849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_SERVER_VALID(sv);
859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
8668b2bbf2SGordon Ross /*
8768b2bbf2SGordon Ross * This is called in the error path when opening,
8868b2bbf2SGordon Ross * in which case we close the socket here.
8968b2bbf2SGordon Ross */
9068b2bbf2SGordon Ross if (opipe->p_socket != NULL)
9168b2bbf2SGordon Ross (void) ksocket_close(opipe->p_socket, zone_kcred());
929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC;
949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States cv_destroy(&opipe->p_cv);
959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_destroy(&opipe->p_mutex);
969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
978622ec45SGordon Ross kmem_cache_free(smb_cache_opipe, opipe);
989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
100b210fedeSGordon Ross /*
101b210fedeSGordon Ross * Unblock a request that might be blocked reading some
102b210fedeSGordon Ross * pipe (AF_UNIX socket). We don't have an easy way to
103b210fedeSGordon Ross * interrupt just the thread servicing this request, so
104b210fedeSGordon Ross * we shutdown(3socket) the socket, waking all readers.
105b210fedeSGordon Ross * That's a bit heavy-handed, making the socket unusable
106b210fedeSGordon Ross * after this, so we do this only when disconnecting a
107b210fedeSGordon Ross * session (i.e. stopping the SMB service), and not when
108b210fedeSGordon Ross * handling an SMB2_cancel or SMB_nt_cancel request.
109b210fedeSGordon Ross */
110b210fedeSGordon Ross static void
smb_opipe_cancel(smb_request_t * sr)111b210fedeSGordon Ross smb_opipe_cancel(smb_request_t *sr)
112b210fedeSGordon Ross {
113b210fedeSGordon Ross ksocket_t so;
114b210fedeSGordon Ross
115811599a4SMatt Barden switch (sr->session->s_state) {
116811599a4SMatt Barden case SMB_SESSION_STATE_DISCONNECTED:
117811599a4SMatt Barden case SMB_SESSION_STATE_TERMINATED:
118811599a4SMatt Barden if ((so = sr->cancel_arg2) != NULL)
119811599a4SMatt Barden (void) ksocket_shutdown(so, SHUT_RDWR, sr->user_cr);
120811599a4SMatt Barden break;
121b210fedeSGordon Ross }
122b210fedeSGordon Ross }
123b210fedeSGordon Ross
1243db3f65cSamw /*
12568b2bbf2SGordon Ross * Helper for open: build pipe name and connect.
1263db3f65cSamw */
12768b2bbf2SGordon Ross static int
smb_opipe_connect(smb_request_t * sr,smb_opipe_t * opipe)12868b2bbf2SGordon Ross smb_opipe_connect(smb_request_t *sr, smb_opipe_t *opipe)
1293db3f65cSamw {
13068b2bbf2SGordon Ross struct sockaddr_un saddr;
131148c5f43SAlan Wright smb_arg_open_t *op = &sr->sr_open;
13268b2bbf2SGordon Ross const char *name;
13368b2bbf2SGordon Ross int rc;
1343db3f65cSamw
13568b2bbf2SGordon Ross name = op->fqi.fq_path.pn_path;
13668b2bbf2SGordon Ross name += strspn(name, "\\");
13768b2bbf2SGordon Ross if (smb_strcasecmp(name, "PIPE", 4) == 0) {
13868b2bbf2SGordon Ross name += 4;
13968b2bbf2SGordon Ross name += strspn(name, "\\");
14068b2bbf2SGordon Ross }
14168b2bbf2SGordon Ross (void) strlcpy(opipe->p_name, name, SMB_OPIPE_MAXNAME);
14268b2bbf2SGordon Ross (void) smb_strlwr(opipe->p_name);
1433db3f65cSamw
14468b2bbf2SGordon Ross bzero(&saddr, sizeof (saddr));
14568b2bbf2SGordon Ross saddr.sun_family = AF_UNIX;
14668b2bbf2SGordon Ross (void) snprintf(saddr.sun_path, sizeof (saddr.sun_path),
14768b2bbf2SGordon Ross "%s/%s", SMB_PIPE_DIR, opipe->p_name);
14868b2bbf2SGordon Ross rc = ksocket_connect(opipe->p_socket, (struct sockaddr *)&saddr,
14968b2bbf2SGordon Ross sizeof (saddr), sr->user_cr);
150b7301bf5SGordon Ross
15168b2bbf2SGordon Ross return (rc);
15268b2bbf2SGordon Ross }
153c8ec8eeaSjose borrego
154268cac54SGordon Ross static int
smb_opipe_exists(char * name)155268cac54SGordon Ross smb_opipe_exists(char *name)
156268cac54SGordon Ross {
157268cac54SGordon Ross struct sockaddr_un saddr;
158268cac54SGordon Ross vnode_t *vp; /* Underlying filesystem vnode */
159268cac54SGordon Ross int err;
160268cac54SGordon Ross
161268cac54SGordon Ross bzero(&saddr, sizeof (saddr));
162268cac54SGordon Ross saddr.sun_family = AF_UNIX;
163268cac54SGordon Ross (void) snprintf(saddr.sun_path, sizeof (saddr.sun_path),
164268cac54SGordon Ross "%s/%s", SMB_PIPE_DIR, name);
165268cac54SGordon Ross
166268cac54SGordon Ross err = lookupname(saddr.sun_path, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp);
167268cac54SGordon Ross if (err == 0) {
168268cac54SGordon Ross VN_RELE(vp); /* release hold from lookup */
169268cac54SGordon Ross }
170268cac54SGordon Ross
171268cac54SGordon Ross return (err);
172268cac54SGordon Ross }
173268cac54SGordon Ross
174268cac54SGordon Ross
17568b2bbf2SGordon Ross /*
17668b2bbf2SGordon Ross * Helper for open: encode and send the user info.
17768b2bbf2SGordon Ross *
17868b2bbf2SGordon Ross * We send information about this client + user to the
17968b2bbf2SGordon Ross * pipe service so it can use it for access checks.
18068b2bbf2SGordon Ross * The service MAY deny the open based on this info,
18168b2bbf2SGordon Ross * (i.e. anonymous session trying to open a pipe that
18268b2bbf2SGordon Ross * requires authentication) in which case we will read
18368b2bbf2SGordon Ross * an error status from the service and return that.
18468b2bbf2SGordon Ross */
18568b2bbf2SGordon Ross static void
smb_opipe_send_userinfo(smb_request_t * sr,smb_opipe_t * opipe,smb_error_t * errp)18668b2bbf2SGordon Ross smb_opipe_send_userinfo(smb_request_t *sr, smb_opipe_t *opipe,
18768b2bbf2SGordon Ross smb_error_t *errp)
18868b2bbf2SGordon Ross {
18968b2bbf2SGordon Ross XDR xdrs;
19068b2bbf2SGordon Ross smb_netuserinfo_t nui;
19168b2bbf2SGordon Ross smb_pipehdr_t phdr;
19268b2bbf2SGordon Ross char *buf;
19368b2bbf2SGordon Ross uint32_t buflen;
19468b2bbf2SGordon Ross uint32_t status;
19568b2bbf2SGordon Ross size_t iocnt = 0;
19668b2bbf2SGordon Ross int rc;
1978b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
19868b2bbf2SGordon Ross /*
19968b2bbf2SGordon Ross * Any errors building the XDR message etc.
20068b2bbf2SGordon Ross */
20168b2bbf2SGordon Ross errp->status = NT_STATUS_INTERNAL_ERROR;
2023db3f65cSamw
20368b2bbf2SGordon Ross smb_user_netinfo_init(sr->uid_user, &nui);
20468b2bbf2SGordon Ross phdr.ph_magic = SMB_PIPE_HDR_MAGIC;
20568b2bbf2SGordon Ross phdr.ph_uilen = xdr_sizeof(smb_netuserinfo_xdr, &nui);
2068b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
20768b2bbf2SGordon Ross buflen = sizeof (phdr) + phdr.ph_uilen;
20868b2bbf2SGordon Ross buf = kmem_alloc(buflen, KM_SLEEP);
2093db3f65cSamw
21068b2bbf2SGordon Ross bcopy(&phdr, buf, sizeof (phdr));
21168b2bbf2SGordon Ross xdrmem_create(&xdrs, buf + sizeof (phdr),
21268b2bbf2SGordon Ross buflen - (sizeof (phdr)), XDR_ENCODE);
21368b2bbf2SGordon Ross if (!smb_netuserinfo_xdr(&xdrs, &nui))
21468b2bbf2SGordon Ross goto out;
2153db3f65cSamw
216*66b505f1SGordon Ross /*
217*66b505f1SGordon Ross * Prepare for cancellable send/recv.
218*66b505f1SGordon Ross */
219b210fedeSGordon Ross mutex_enter(&sr->sr_mutex);
220b210fedeSGordon Ross if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
221b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
222b210fedeSGordon Ross errp->status = NT_STATUS_CANCELLED;
223b210fedeSGordon Ross goto out;
224b210fedeSGordon Ross }
225b210fedeSGordon Ross sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
226b210fedeSGordon Ross sr->cancel_method = smb_opipe_cancel;
227b210fedeSGordon Ross sr->cancel_arg2 = opipe->p_socket;
228b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
22968b2bbf2SGordon Ross
23068b2bbf2SGordon Ross rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
23168b2bbf2SGordon Ross &iocnt, sr->user_cr);
23268b2bbf2SGordon Ross if (rc == 0 && iocnt != buflen)
23368b2bbf2SGordon Ross rc = EIO;
234b210fedeSGordon Ross if (rc == 0)
235b210fedeSGordon Ross rc = ksocket_recv(opipe->p_socket, &status, sizeof (status),
236b210fedeSGordon Ross 0, &iocnt, sr->user_cr);
237b210fedeSGordon Ross if (rc == 0 && iocnt != sizeof (status))
238b210fedeSGordon Ross rc = EIO;
239b210fedeSGordon Ross
240*66b505f1SGordon Ross /*
241*66b505f1SGordon Ross * Did the send/recv. complete or was it cancelled?
242*66b505f1SGordon Ross */
243b210fedeSGordon Ross mutex_enter(&sr->sr_mutex);
244*66b505f1SGordon Ross switch_state:
245b210fedeSGordon Ross switch (sr->sr_state) {
246b210fedeSGordon Ross case SMB_REQ_STATE_WAITING_PIPE:
247*66b505f1SGordon Ross /* Normal wakeup. Keep rc from above. */
248b210fedeSGordon Ross sr->sr_state = SMB_REQ_STATE_ACTIVE;
249b210fedeSGordon Ross break;
250b210fedeSGordon Ross case SMB_REQ_STATE_CANCEL_PENDING:
251*66b505f1SGordon Ross /* cancel_method running. wait. */
252*66b505f1SGordon Ross cv_wait(&sr->sr_st_cv, &sr->sr_mutex);
253*66b505f1SGordon Ross goto switch_state;
254*66b505f1SGordon Ross case SMB_REQ_STATE_CANCELLED:
255b210fedeSGordon Ross rc = EINTR;
256b210fedeSGordon Ross break;
257b210fedeSGordon Ross default:
258b210fedeSGordon Ross /* keep rc from above */
259b210fedeSGordon Ross break;
260b210fedeSGordon Ross }
261*66b505f1SGordon Ross sr->cancel_method = NULL;
262*66b505f1SGordon Ross sr->cancel_arg2 = NULL;
263b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
2643db3f65cSamw
2653db3f65cSamw /*
26668b2bbf2SGordon Ross * Return the status we read from the pipe service,
26768b2bbf2SGordon Ross * normally NT_STATUS_SUCCESS, but could be something
26868b2bbf2SGordon Ross * else like NT_STATUS_ACCESS_DENIED.
2693db3f65cSamw */
270b210fedeSGordon Ross switch (rc) {
271b210fedeSGordon Ross case 0:
272b210fedeSGordon Ross errp->status = status;
273b210fedeSGordon Ross break;
274b210fedeSGordon Ross case EINTR:
275b210fedeSGordon Ross errp->status = NT_STATUS_CANCELLED;
276b210fedeSGordon Ross break;
277b210fedeSGordon Ross /*
278b210fedeSGordon Ross * If we fail sending the netuserinfo or recv'ing the
279b210fedeSGordon Ross * status reponse, we have probably run into the limit
280b210fedeSGordon Ross * on the number of open pipes. That's this status:
281b210fedeSGordon Ross */
282b210fedeSGordon Ross default:
283b210fedeSGordon Ross errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
284b210fedeSGordon Ross break;
285b210fedeSGordon Ross }
28668b2bbf2SGordon Ross
28768b2bbf2SGordon Ross out:
28868b2bbf2SGordon Ross xdr_destroy(&xdrs);
28968b2bbf2SGordon Ross kmem_free(buf, buflen);
29068b2bbf2SGordon Ross smb_user_netinfo_fini(&nui);
2913db3f65cSamw }
2923db3f65cSamw
2933db3f65cSamw /*
29468b2bbf2SGordon Ross * smb_opipe_open
2953db3f65cSamw *
29668b2bbf2SGordon Ross * Open an RPC named pipe. This routine should be called if
29768b2bbf2SGordon Ross * a file open is requested on a share of type STYPE_IPC.
29868b2bbf2SGordon Ross * If we recognize the pipe, we setup a new ofile.
2993db3f65cSamw *
30068b2bbf2SGordon Ross * Returns 0 on success, Otherwise an NT status code.
3013db3f65cSamw */
30268b2bbf2SGordon Ross int
smb_opipe_open(smb_request_t * sr,smb_ofile_t * ofile)30394047d49SGordon Ross smb_opipe_open(smb_request_t *sr, smb_ofile_t *ofile)
3043db3f65cSamw {
30568b2bbf2SGordon Ross smb_arg_open_t *op = &sr->sr_open;
306c5f48fa5SGordon Ross smb_attr_t *ap = &op->fqi.fq_fattr;
30768b2bbf2SGordon Ross smb_opipe_t *opipe;
30868b2bbf2SGordon Ross smb_error_t err;
3093db3f65cSamw
31068b2bbf2SGordon Ross opipe = smb_opipe_alloc(sr);
31168b2bbf2SGordon Ross if (opipe == NULL)
31268b2bbf2SGordon Ross return (NT_STATUS_INTERNAL_ERROR);
3133db3f65cSamw
31468b2bbf2SGordon Ross if (smb_opipe_connect(sr, opipe) != 0) {
31568b2bbf2SGordon Ross smb_opipe_dealloc(opipe);
31668b2bbf2SGordon Ross return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
3173db3f65cSamw }
3183db3f65cSamw
31968b2bbf2SGordon Ross smb_opipe_send_userinfo(sr, opipe, &err);
32068b2bbf2SGordon Ross if (err.status != 0) {
32168b2bbf2SGordon Ross smb_opipe_dealloc(opipe);
32268b2bbf2SGordon Ross return (err.status);
3233db3f65cSamw }
3243db3f65cSamw
32568b2bbf2SGordon Ross /*
32694047d49SGordon Ross * We might have blocked in smb_opipe_connect long enough so
32794047d49SGordon Ross * a tree disconnect might have happened. In that case, we
32894047d49SGordon Ross * would be adding an ofile to a tree that's disconnecting,
32994047d49SGordon Ross * which would interfere with tear-down.
33068b2bbf2SGordon Ross */
33194047d49SGordon Ross if (!smb_tree_is_connected(sr->tid_tree)) {
33268b2bbf2SGordon Ross smb_opipe_dealloc(opipe);
33394047d49SGordon Ross return (NT_STATUS_NETWORK_NAME_DELETED);
33468b2bbf2SGordon Ross }
3353db3f65cSamw
33694047d49SGordon Ross /*
33794047d49SGordon Ross * Note: The new opipe is given to smb_ofile_open
33894047d49SGordon Ross * via op->pipe
33994047d49SGordon Ross */
34094047d49SGordon Ross op->pipe = opipe;
34194047d49SGordon Ross smb_ofile_open(sr, op, ofile);
34294047d49SGordon Ross op->pipe = NULL;
34394047d49SGordon Ross
34468b2bbf2SGordon Ross /* An "up" pointer, for debug. */
34568b2bbf2SGordon Ross opipe->p_ofile = ofile;
3463db3f65cSamw
347c5f48fa5SGordon Ross /*
348c5f48fa5SGordon Ross * Caller expects attributes in op->fqi
349c5f48fa5SGordon Ross */
350c5f48fa5SGordon Ross (void) smb_opipe_getattr(ofile, &op->fqi.fq_fattr);
351c5f48fa5SGordon Ross
352c5f48fa5SGordon Ross op->dsize = 0;
353c5f48fa5SGordon Ross op->dattr = ap->sa_dosattr;
354c5f48fa5SGordon Ross op->fileid = ap->sa_vattr.va_nodeid;
35568b2bbf2SGordon Ross op->ftype = SMB_FTYPE_MESG_PIPE;
356c5f48fa5SGordon Ross op->action_taken = SMB_OACT_OPLOCK | SMB_OACT_OPENED;
35768b2bbf2SGordon Ross op->devstate = SMB_PIPE_READMODE_MESSAGE
35868b2bbf2SGordon Ross | SMB_PIPE_TYPE_MESSAGE
35968b2bbf2SGordon Ross | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
3603db3f65cSamw
36168b2bbf2SGordon Ross sr->smb_fid = ofile->f_fid;
36268b2bbf2SGordon Ross sr->fid_ofile = ofile;
3633db3f65cSamw
36468b2bbf2SGordon Ross return (NT_STATUS_SUCCESS);
3653db3f65cSamw }
3663db3f65cSamw
3673db3f65cSamw /*
3683db3f65cSamw * smb_opipe_close
3693db3f65cSamw *
37068b2bbf2SGordon Ross * Called by smb_ofile_close for pipes.
37168b2bbf2SGordon Ross *
37268b2bbf2SGordon Ross * Note: ksocket_close may block while waiting for
37368b2bbf2SGordon Ross * any I/O threads with a hold to get out.
3743db3f65cSamw */
3753db3f65cSamw void
smb_opipe_close(smb_ofile_t * of)3763db3f65cSamw smb_opipe_close(smb_ofile_t *of)
3773db3f65cSamw {
3783db3f65cSamw smb_opipe_t *opipe;
37968b2bbf2SGordon Ross ksocket_t sock;
3803db3f65cSamw
38168b2bbf2SGordon Ross ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
3823db3f65cSamw ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
3833db3f65cSamw opipe = of->f_pipe;
3849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe);
3859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
38668b2bbf2SGordon Ross mutex_enter(&opipe->p_mutex);
38768b2bbf2SGordon Ross sock = opipe->p_socket;
38868b2bbf2SGordon Ross opipe->p_socket = NULL;
38968b2bbf2SGordon Ross mutex_exit(&opipe->p_mutex);
3903db3f65cSamw
39168b2bbf2SGordon Ross (void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr);
39268b2bbf2SGordon Ross (void) ksocket_close(sock, of->f_cr);
3933db3f65cSamw }
3943db3f65cSamw
3953db3f65cSamw /*
3963db3f65cSamw * smb_opipe_write
3973db3f65cSamw *
3983db3f65cSamw * Write RPC request data to the pipe. The client should call smb_opipe_read
3993db3f65cSamw * to complete the exchange and obtain the RPC response.
4003db3f65cSamw *
4013db3f65cSamw * Returns 0 on success or an errno on failure.
4023db3f65cSamw */
4033db3f65cSamw int
smb_opipe_write(smb_request_t * sr,struct uio * uio)4043db3f65cSamw smb_opipe_write(smb_request_t *sr, struct uio *uio)
4053db3f65cSamw {
40668b2bbf2SGordon Ross struct nmsghdr msghdr;
40768b2bbf2SGordon Ross smb_ofile_t *ofile;
4083db3f65cSamw smb_opipe_t *opipe;
40968b2bbf2SGordon Ross ksocket_t sock;
41068b2bbf2SGordon Ross size_t sent = 0;
41168b2bbf2SGordon Ross int rc = 0;
4123db3f65cSamw
41368b2bbf2SGordon Ross ofile = sr->fid_ofile;
41468b2bbf2SGordon Ross ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
41568b2bbf2SGordon Ross opipe = ofile->f_pipe;
4169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe);
4173db3f65cSamw
41868b2bbf2SGordon Ross mutex_enter(&opipe->p_mutex);
41968b2bbf2SGordon Ross sock = opipe->p_socket;
42068b2bbf2SGordon Ross if (sock != NULL)
42168b2bbf2SGordon Ross ksocket_hold(sock);
42268b2bbf2SGordon Ross mutex_exit(&opipe->p_mutex);
42368b2bbf2SGordon Ross if (sock == NULL)
4243db3f65cSamw return (EBADF);
4253db3f65cSamw
42668b2bbf2SGordon Ross bzero(&msghdr, sizeof (msghdr));
42768b2bbf2SGordon Ross msghdr.msg_iov = uio->uio_iov;
42868b2bbf2SGordon Ross msghdr.msg_iovlen = uio->uio_iovcnt;
4293db3f65cSamw
43068b2bbf2SGordon Ross /*
43168b2bbf2SGordon Ross * This should block until we've sent it all,
43268b2bbf2SGordon Ross * or given up due to errors (pipe closed).
43368b2bbf2SGordon Ross */
43468b2bbf2SGordon Ross while (uio->uio_resid > 0) {
43568b2bbf2SGordon Ross rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr);
43668b2bbf2SGordon Ross if (rc != 0)
43768b2bbf2SGordon Ross break;
43868b2bbf2SGordon Ross uio->uio_resid -= sent;
43968b2bbf2SGordon Ross }
4403db3f65cSamw
44168b2bbf2SGordon Ross ksocket_rele(sock);
4423db3f65cSamw
44368b2bbf2SGordon Ross return (rc);
4443db3f65cSamw }
4453db3f65cSamw
4463db3f65cSamw /*
4473db3f65cSamw * smb_opipe_read
4483db3f65cSamw *
44968b2bbf2SGordon Ross * This interface may be called from smb_opipe_transact (write, read)
45068b2bbf2SGordon Ross * or from smb_read / smb2_read to get the rest of an RPC response.
45168b2bbf2SGordon Ross * The response data (and length) are returned via the uio.
4523db3f65cSamw */
4533db3f65cSamw int
smb_opipe_read(smb_request_t * sr,struct uio * uio)4543db3f65cSamw smb_opipe_read(smb_request_t *sr, struct uio *uio)
4553db3f65cSamw {
45668b2bbf2SGordon Ross struct nmsghdr msghdr;
45768b2bbf2SGordon Ross smb_ofile_t *ofile;
4583db3f65cSamw smb_opipe_t *opipe;
45968b2bbf2SGordon Ross ksocket_t sock;
46068b2bbf2SGordon Ross size_t recvcnt = 0;
4613db3f65cSamw int rc;
4623db3f65cSamw
46368b2bbf2SGordon Ross ofile = sr->fid_ofile;
46468b2bbf2SGordon Ross ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
46568b2bbf2SGordon Ross opipe = ofile->f_pipe;
4669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe);
4679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
46868b2bbf2SGordon Ross mutex_enter(&opipe->p_mutex);
46968b2bbf2SGordon Ross sock = opipe->p_socket;
47068b2bbf2SGordon Ross if (sock != NULL)
47168b2bbf2SGordon Ross ksocket_hold(sock);
47268b2bbf2SGordon Ross mutex_exit(&opipe->p_mutex);
47368b2bbf2SGordon Ross if (sock == NULL)
4743db3f65cSamw return (EBADF);
4753db3f65cSamw
476*66b505f1SGordon Ross /*
477*66b505f1SGordon Ross * Prepare for cancellable recvmsg.
478*66b505f1SGordon Ross */
479b210fedeSGordon Ross mutex_enter(&sr->sr_mutex);
480b210fedeSGordon Ross if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
481b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
482b210fedeSGordon Ross rc = EINTR;
483b210fedeSGordon Ross goto out;
484b210fedeSGordon Ross }
485b210fedeSGordon Ross sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
486b210fedeSGordon Ross sr->cancel_method = smb_opipe_cancel;
487b210fedeSGordon Ross sr->cancel_arg2 = sock;
488b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
4893db3f65cSamw
49068b2bbf2SGordon Ross /*
49168b2bbf2SGordon Ross * This should block only if there's no data.
49268b2bbf2SGordon Ross * A single call to recvmsg does just that.
49368b2bbf2SGordon Ross * (Intentionaly no recv loop here.)
49468b2bbf2SGordon Ross */
495b210fedeSGordon Ross bzero(&msghdr, sizeof (msghdr));
496b210fedeSGordon Ross msghdr.msg_iov = uio->uio_iov;
497b210fedeSGordon Ross msghdr.msg_iovlen = uio->uio_iovcnt;
49868b2bbf2SGordon Ross rc = ksocket_recvmsg(sock, &msghdr, 0,
49968b2bbf2SGordon Ross &recvcnt, ofile->f_cr);
500b210fedeSGordon Ross
501*66b505f1SGordon Ross /*
502*66b505f1SGordon Ross * Did the recvmsg complete or was it cancelled?
503*66b505f1SGordon Ross */
504b210fedeSGordon Ross mutex_enter(&sr->sr_mutex);
505*66b505f1SGordon Ross switch_state:
506b210fedeSGordon Ross switch (sr->sr_state) {
507b210fedeSGordon Ross case SMB_REQ_STATE_WAITING_PIPE:
508*66b505f1SGordon Ross /* Normal wakeup. Keep rc from above. */
509b210fedeSGordon Ross sr->sr_state = SMB_REQ_STATE_ACTIVE;
510b210fedeSGordon Ross break;
511b210fedeSGordon Ross case SMB_REQ_STATE_CANCEL_PENDING:
512*66b505f1SGordon Ross /* cancel_method running. wait. */
513*66b505f1SGordon Ross cv_wait(&sr->sr_st_cv, &sr->sr_mutex);
514*66b505f1SGordon Ross goto switch_state;
515*66b505f1SGordon Ross case SMB_REQ_STATE_CANCELLED:
516b210fedeSGordon Ross rc = EINTR;
517b210fedeSGordon Ross break;
518b210fedeSGordon Ross default:
519b210fedeSGordon Ross /* keep rc from above */
520b210fedeSGordon Ross break;
521b210fedeSGordon Ross }
522*66b505f1SGordon Ross sr->cancel_method = NULL;
523*66b505f1SGordon Ross sr->cancel_arg2 = NULL;
524b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
525b210fedeSGordon Ross
52668b2bbf2SGordon Ross if (rc != 0)
52768b2bbf2SGordon Ross goto out;
52868b2bbf2SGordon Ross
52968b2bbf2SGordon Ross if (recvcnt == 0) {
53068b2bbf2SGordon Ross /* Other side closed. */
53168b2bbf2SGordon Ross rc = EPIPE;
53268b2bbf2SGordon Ross goto out;
5333db3f65cSamw }
53468b2bbf2SGordon Ross uio->uio_resid -= recvcnt;
5353db3f65cSamw
53668b2bbf2SGordon Ross out:
53768b2bbf2SGordon Ross ksocket_rele(sock);
5389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
5399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (rc);
5409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
541bce01b59SGordon Ross
542bce01b59SGordon Ross int
smb_opipe_ioctl(smb_request_t * sr,int cmd,void * arg,int * rvalp)543a90cf9f2SGordon Ross smb_opipe_ioctl(smb_request_t *sr, int cmd, void *arg, int *rvalp)
544bce01b59SGordon Ross {
545bce01b59SGordon Ross smb_ofile_t *ofile;
546bce01b59SGordon Ross smb_opipe_t *opipe;
547bce01b59SGordon Ross ksocket_t sock;
548a90cf9f2SGordon Ross int rc;
549bce01b59SGordon Ross
550bce01b59SGordon Ross ofile = sr->fid_ofile;
551bce01b59SGordon Ross ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
552bce01b59SGordon Ross opipe = ofile->f_pipe;
553bce01b59SGordon Ross SMB_OPIPE_VALID(opipe);
554bce01b59SGordon Ross
555bce01b59SGordon Ross mutex_enter(&opipe->p_mutex);
556bce01b59SGordon Ross sock = opipe->p_socket;
557bce01b59SGordon Ross if (sock != NULL)
558bce01b59SGordon Ross ksocket_hold(sock);
559bce01b59SGordon Ross mutex_exit(&opipe->p_mutex);
560bce01b59SGordon Ross if (sock == NULL)
561bce01b59SGordon Ross return (EBADF);
562bce01b59SGordon Ross
563a90cf9f2SGordon Ross rc = ksocket_ioctl(sock, cmd, (intptr_t)arg, rvalp, ofile->f_cr);
564bce01b59SGordon Ross
565bce01b59SGordon Ross ksocket_rele(sock);
566bce01b59SGordon Ross
567bce01b59SGordon Ross return (rc);
568bce01b59SGordon Ross }
569a90cf9f2SGordon Ross
570a90cf9f2SGordon Ross /*
571a90cf9f2SGordon Ross * Get the smb_attr_t for a named pipe.
572a90cf9f2SGordon Ross * Caller has already cleared to zero.
573a90cf9f2SGordon Ross */
574a90cf9f2SGordon Ross int
smb_opipe_getattr(smb_ofile_t * of,smb_attr_t * ap)575a90cf9f2SGordon Ross smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
576a90cf9f2SGordon Ross {
577a90cf9f2SGordon Ross
578a90cf9f2SGordon Ross if (of->f_pipe == NULL)
579a90cf9f2SGordon Ross return (EINVAL);
580a90cf9f2SGordon Ross
581a90cf9f2SGordon Ross ap->sa_vattr.va_type = VFIFO;
582a90cf9f2SGordon Ross ap->sa_vattr.va_nlink = 1;
583c5f48fa5SGordon Ross ap->sa_vattr.va_nodeid = (uintptr_t)of->f_pipe;
584a90cf9f2SGordon Ross ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
585c5f48fa5SGordon Ross ap->sa_allocsz = SMB_PIPE_MAX_MSGSIZE;
586a90cf9f2SGordon Ross
587a90cf9f2SGordon Ross return (0);
588a90cf9f2SGordon Ross }
589a90cf9f2SGordon Ross
590a90cf9f2SGordon Ross int
smb_opipe_getname(smb_ofile_t * of,char * buf,size_t buflen)591a90cf9f2SGordon Ross smb_opipe_getname(smb_ofile_t *of, char *buf, size_t buflen)
592a90cf9f2SGordon Ross {
593a90cf9f2SGordon Ross smb_opipe_t *opipe;
594a90cf9f2SGordon Ross
595a90cf9f2SGordon Ross if ((opipe = of->f_pipe) == NULL)
596a90cf9f2SGordon Ross return (EINVAL);
597a90cf9f2SGordon Ross
598a90cf9f2SGordon Ross (void) snprintf(buf, buflen, "\\%s", opipe->p_name);
599a90cf9f2SGordon Ross return (0);
600a90cf9f2SGordon Ross }
601a90cf9f2SGordon Ross
602a90cf9f2SGordon Ross /*
60355f0a249SGordon Ross * Handle device type FILE_DEVICE_NAMED_PIPE
60455f0a249SGordon Ross * for smb2_ioctl
605a90cf9f2SGordon Ross */
606a90cf9f2SGordon Ross /* ARGSUSED */
607a90cf9f2SGordon Ross uint32_t
smb_opipe_fsctl(smb_request_t * sr,smb_fsctl_t * fsctl)608a90cf9f2SGordon Ross smb_opipe_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
609a90cf9f2SGordon Ross {
610a90cf9f2SGordon Ross uint32_t status;
611a90cf9f2SGordon Ross
61255f0a249SGordon Ross if (!STYPE_ISIPC(sr->tid_tree->t_res_type))
61355f0a249SGordon Ross return (NT_STATUS_INVALID_DEVICE_REQUEST);
61455f0a249SGordon Ross
615a90cf9f2SGordon Ross switch (fsctl->CtlCode) {
616a90cf9f2SGordon Ross case FSCTL_PIPE_TRANSCEIVE:
617a90cf9f2SGordon Ross status = smb_opipe_transceive(sr, fsctl);
618a90cf9f2SGordon Ross break;
619a90cf9f2SGordon Ross
620a90cf9f2SGordon Ross case FSCTL_PIPE_PEEK:
621268cac54SGordon Ross status = NT_STATUS_INVALID_DEVICE_REQUEST;
622268cac54SGordon Ross break;
623268cac54SGordon Ross
624a90cf9f2SGordon Ross case FSCTL_PIPE_WAIT:
625268cac54SGordon Ross status = smb_opipe_wait(sr, fsctl);
626a90cf9f2SGordon Ross break;
627a90cf9f2SGordon Ross
628a90cf9f2SGordon Ross default:
629a90cf9f2SGordon Ross ASSERT(!"CtlCode");
630a90cf9f2SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
631a90cf9f2SGordon Ross break;
632a90cf9f2SGordon Ross }
633a90cf9f2SGordon Ross
634a90cf9f2SGordon Ross return (status);
635a90cf9f2SGordon Ross }
636a90cf9f2SGordon Ross
63755f0a249SGordon Ross uint32_t
smb_opipe_transceive(smb_request_t * sr,smb_fsctl_t * fsctl)638a90cf9f2SGordon Ross smb_opipe_transceive(smb_request_t *sr, smb_fsctl_t *fsctl)
639a90cf9f2SGordon Ross {
640c0e62236SGordon Ross smb_vdb_t *vdb;
641a90cf9f2SGordon Ross smb_ofile_t *ofile;
642a90cf9f2SGordon Ross struct mbuf *mb;
643a90cf9f2SGordon Ross uint32_t status;
644a90cf9f2SGordon Ross int len, rc;
645a90cf9f2SGordon Ross
646a90cf9f2SGordon Ross /*
647a90cf9f2SGordon Ross * Caller checked that this is the IPC$ share,
648a90cf9f2SGordon Ross * and that this call has a valid open handle.
649a90cf9f2SGordon Ross * Just check the type.
650a90cf9f2SGordon Ross */
651a90cf9f2SGordon Ross ofile = sr->fid_ofile;
652a90cf9f2SGordon Ross if (ofile->f_ftype != SMB_FTYPE_MESG_PIPE)
653a90cf9f2SGordon Ross return (NT_STATUS_INVALID_HANDLE);
654a90cf9f2SGordon Ross
655c0e62236SGordon Ross /*
656c0e62236SGordon Ross * The VDB is a bit large. Allocate.
657c0e62236SGordon Ross * This is automatically free'd with the SR
658c0e62236SGordon Ross */
659c0e62236SGordon Ross vdb = smb_srm_zalloc(sr, sizeof (*vdb));
660a90cf9f2SGordon Ross rc = smb_mbc_decodef(fsctl->in_mbc, "#B",
661c0e62236SGordon Ross fsctl->InputCount, vdb);
662a90cf9f2SGordon Ross if (rc != 0) {
663a90cf9f2SGordon Ross /* Not enough data sent. */
664a90cf9f2SGordon Ross return (NT_STATUS_INVALID_PARAMETER);
665a90cf9f2SGordon Ross }
666a90cf9f2SGordon Ross
667c0e62236SGordon Ross rc = smb_opipe_write(sr, &vdb->vdb_uio);
668a90cf9f2SGordon Ross if (rc != 0)
669a90cf9f2SGordon Ross return (smb_errno2status(rc));
670a90cf9f2SGordon Ross
671c0e62236SGordon Ross vdb->vdb_tag = 0;
672c0e62236SGordon Ross vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
673c0e62236SGordon Ross vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
674c0e62236SGordon Ross vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
675c0e62236SGordon Ross vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
676c0e62236SGordon Ross vdb->vdb_uio.uio_loffset = (offset_t)0;
677c0e62236SGordon Ross vdb->vdb_uio.uio_resid = fsctl->MaxOutputResp;
678c0e62236SGordon Ross mb = smb_mbuf_allocate(&vdb->vdb_uio);
679a90cf9f2SGordon Ross
680c0e62236SGordon Ross rc = smb_opipe_read(sr, &vdb->vdb_uio);
681a90cf9f2SGordon Ross if (rc != 0) {
682a90cf9f2SGordon Ross m_freem(mb);
683a90cf9f2SGordon Ross return (smb_errno2status(rc));
684a90cf9f2SGordon Ross }
685a90cf9f2SGordon Ross
686c0e62236SGordon Ross len = fsctl->MaxOutputResp - vdb->vdb_uio.uio_resid;
687a90cf9f2SGordon Ross smb_mbuf_trim(mb, len);
688a90cf9f2SGordon Ross MBC_ATTACH_MBUF(fsctl->out_mbc, mb);
689a90cf9f2SGordon Ross
690a90cf9f2SGordon Ross /*
691a90cf9f2SGordon Ross * If the output buffer holds a partial pipe message,
692a90cf9f2SGordon Ross * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
693a90cf9f2SGordon Ross * As we don't have message boundary markers, the best
694a90cf9f2SGordon Ross * we can do is return that status when we have ALL of:
695a90cf9f2SGordon Ross * Output buffer was < SMB_PIPE_MAX_MSGSIZE
696a90cf9f2SGordon Ross * We filled the output buffer (resid==0)
697a90cf9f2SGordon Ross * There's more data (ioctl FIONREAD)
698a90cf9f2SGordon Ross */
699a90cf9f2SGordon Ross status = NT_STATUS_SUCCESS;
700a90cf9f2SGordon Ross if (fsctl->MaxOutputResp < SMB_PIPE_MAX_MSGSIZE &&
701c0e62236SGordon Ross vdb->vdb_uio.uio_resid == 0) {
702a90cf9f2SGordon Ross int nread = 0, trval;
703a90cf9f2SGordon Ross rc = smb_opipe_ioctl(sr, FIONREAD, &nread, &trval);
704a90cf9f2SGordon Ross if (rc == 0 && nread != 0)
705a90cf9f2SGordon Ross status = NT_STATUS_BUFFER_OVERFLOW;
706a90cf9f2SGordon Ross }
707a90cf9f2SGordon Ross
708a90cf9f2SGordon Ross return (status);
709a90cf9f2SGordon Ross }
710268cac54SGordon Ross
711268cac54SGordon Ross static uint32_t
smb_opipe_wait(smb_request_t * sr,smb_fsctl_t * fsctl)712268cac54SGordon Ross smb_opipe_wait(smb_request_t *sr, smb_fsctl_t *fsctl)
713268cac54SGordon Ross {
714268cac54SGordon Ross char *name;
715268cac54SGordon Ross uint64_t timeout;
716268cac54SGordon Ross uint32_t namelen;
717268cac54SGordon Ross int rc;
718268cac54SGordon Ross uint8_t tflag;
719268cac54SGordon Ross
720268cac54SGordon Ross rc = smb_mbc_decodef(fsctl->in_mbc, "qlb.",
721268cac54SGordon Ross &timeout, /* q */
722268cac54SGordon Ross &namelen, /* l */
723268cac54SGordon Ross &tflag); /* b */
724268cac54SGordon Ross if (rc != 0)
725268cac54SGordon Ross return (NT_STATUS_INVALID_PARAMETER);
726268cac54SGordon Ross rc = smb_mbc_decodef(fsctl->in_mbc, "%#U",
727268cac54SGordon Ross sr, /* % */
728268cac54SGordon Ross namelen, /* # */
729268cac54SGordon Ross &name); /* U */
730268cac54SGordon Ross if (rc != 0)
731268cac54SGordon Ross return (NT_STATUS_INVALID_PARAMETER);
732268cac54SGordon Ross
733268cac54SGordon Ross rc = smb_opipe_exists(name);
734268cac54SGordon Ross if (rc != 0)
735268cac54SGordon Ross return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
736268cac54SGordon Ross
737268cac54SGordon Ross /*
738268cac54SGordon Ross * At this point we know the pipe exists.
739268cac54SGordon Ross *
740268cac54SGordon Ross * If the tflag is set, we're supposed to wait for up to
741268cac54SGordon Ross * timeout (100s of milliseconds) for a pipe "instance"
742268cac54SGordon Ross * to become "available" (so pipe open would work).
743268cac54SGordon Ross * However, this implementation has no need to wait,
744268cac54SGordon Ross * so just take a short delay instead.
745268cac54SGordon Ross */
746268cac54SGordon Ross if (tflag != 0) {
747268cac54SGordon Ross clock_t ticks = MSEC_TO_TICK(timeout * 100);
748268cac54SGordon Ross if (ticks > MSEC_TO_TICK(100))
749268cac54SGordon Ross ticks = MSEC_TO_TICK(100);
750268cac54SGordon Ross delay(ticks);
751268cac54SGordon Ross }
752268cac54SGordon Ross
753268cac54SGordon Ross return (0);
754268cac54SGordon Ross }
755