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. 23*68b2bbf2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 243db3f65cSamw */ 253db3f65cSamw 263db3f65cSamw /* 273db3f65cSamw * This module provides the interface to NDR RPC. 283db3f65cSamw */ 293db3f65cSamw 303db3f65cSamw #include <sys/stat.h> 313db3f65cSamw #include <sys/uio.h> 323db3f65cSamw #include <sys/ksynch.h> 33*68b2bbf2SGordon Ross #include <sys/stropts.h> 34*68b2bbf2SGordon Ross #include <sys/socket.h> 35*68b2bbf2SGordon Ross #include <sys/filio.h> 36bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 373db3f65cSamw #include <smbsrv/smb_xdr.h> 383db3f65cSamw 39*68b2bbf2SGordon Ross /* 40*68b2bbf2SGordon Ross * Allocate a new opipe and return it, or NULL, in which case 41*68b2bbf2SGordon Ross * the caller will report "internal error". 42*68b2bbf2SGordon Ross */ 43*68b2bbf2SGordon Ross static smb_opipe_t * 44*68b2bbf2SGordon Ross smb_opipe_alloc(smb_request_t *sr) 459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 46*68b2bbf2SGordon Ross smb_server_t *sv = sr->sr_server; 479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_t *opipe; 48*68b2bbf2SGordon Ross ksocket_t sock; 49*68b2bbf2SGordon Ross 50*68b2bbf2SGordon Ross if (ksocket_socket(&sock, AF_UNIX, SOCK_STREAM, 0, 51*68b2bbf2SGordon Ross KSOCKET_SLEEP, sr->user_cr) != 0) 52*68b2bbf2SGordon Ross return (NULL); 539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 548622ec45SGordon Ross opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP); 559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(opipe, sizeof (smb_opipe_t)); 579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL); 589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL); 599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_magic = SMB_OPIPE_MAGIC; 609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_server = sv; 61*68b2bbf2SGordon Ross opipe->p_refcnt = 1; 62*68b2bbf2SGordon Ross opipe->p_socket = sock; 639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (opipe); 659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 67*68b2bbf2SGordon Ross /* 68*68b2bbf2SGordon Ross * Destroy an opipe. This is normally called from smb_ofile_delete 69*68b2bbf2SGordon Ross * when the ofile has no more references and is about to be free'd. 70*68b2bbf2SGordon Ross * This is also called here in error handling code paths, before 71*68b2bbf2SGordon Ross * the opipe is installed under an ofile. 72*68b2bbf2SGordon Ross */ 739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_dealloc(smb_opipe_t *opipe) 759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_t *sv; 779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States sv = opipe->p_server; 809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_SERVER_VALID(sv); 819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 82*68b2bbf2SGordon Ross /* 83*68b2bbf2SGordon Ross * This is called in the error path when opening, 84*68b2bbf2SGordon Ross * in which case we close the socket here. 85*68b2bbf2SGordon Ross */ 86*68b2bbf2SGordon Ross if (opipe->p_socket != NULL) 87*68b2bbf2SGordon Ross (void) ksocket_close(opipe->p_socket, zone_kcred()); 889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC; 909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States cv_destroy(&opipe->p_cv); 919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_destroy(&opipe->p_mutex); 929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 938622ec45SGordon Ross kmem_cache_free(smb_cache_opipe, opipe); 949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 963db3f65cSamw /* 97*68b2bbf2SGordon Ross * Helper for open: build pipe name and connect. 98*68b2bbf2SGordon Ross */ 99*68b2bbf2SGordon Ross static int 100*68b2bbf2SGordon Ross smb_opipe_connect(smb_request_t *sr, smb_opipe_t *opipe) 101*68b2bbf2SGordon Ross { 102*68b2bbf2SGordon Ross struct sockaddr_un saddr; 103*68b2bbf2SGordon Ross smb_arg_open_t *op = &sr->sr_open; 104*68b2bbf2SGordon Ross const char *name; 105*68b2bbf2SGordon Ross int rc; 106*68b2bbf2SGordon Ross 107*68b2bbf2SGordon Ross name = op->fqi.fq_path.pn_path; 108*68b2bbf2SGordon Ross name += strspn(name, "\\"); 109*68b2bbf2SGordon Ross if (smb_strcasecmp(name, "PIPE", 4) == 0) { 110*68b2bbf2SGordon Ross name += 4; 111*68b2bbf2SGordon Ross name += strspn(name, "\\"); 112*68b2bbf2SGordon Ross } 113*68b2bbf2SGordon Ross (void) strlcpy(opipe->p_name, name, SMB_OPIPE_MAXNAME); 114*68b2bbf2SGordon Ross (void) smb_strlwr(opipe->p_name); 115*68b2bbf2SGordon Ross 116*68b2bbf2SGordon Ross bzero(&saddr, sizeof (saddr)); 117*68b2bbf2SGordon Ross saddr.sun_family = AF_UNIX; 118*68b2bbf2SGordon Ross (void) snprintf(saddr.sun_path, sizeof (saddr.sun_path), 119*68b2bbf2SGordon Ross "%s/%s", SMB_PIPE_DIR, opipe->p_name); 120*68b2bbf2SGordon Ross rc = ksocket_connect(opipe->p_socket, (struct sockaddr *)&saddr, 121*68b2bbf2SGordon Ross sizeof (saddr), sr->user_cr); 122*68b2bbf2SGordon Ross 123*68b2bbf2SGordon Ross return (rc); 124*68b2bbf2SGordon Ross } 125*68b2bbf2SGordon Ross 126*68b2bbf2SGordon Ross /* 127*68b2bbf2SGordon Ross * Helper for open: encode and send the user info. 128*68b2bbf2SGordon Ross * 129*68b2bbf2SGordon Ross * We send information about this client + user to the 130*68b2bbf2SGordon Ross * pipe service so it can use it for access checks. 131*68b2bbf2SGordon Ross * The service MAY deny the open based on this info, 132*68b2bbf2SGordon Ross * (i.e. anonymous session trying to open a pipe that 133*68b2bbf2SGordon Ross * requires authentication) in which case we will read 134*68b2bbf2SGordon Ross * an error status from the service and return that. 135*68b2bbf2SGordon Ross */ 136*68b2bbf2SGordon Ross static void 137*68b2bbf2SGordon Ross smb_opipe_send_userinfo(smb_request_t *sr, smb_opipe_t *opipe, 138*68b2bbf2SGordon Ross smb_error_t *errp) 139*68b2bbf2SGordon Ross { 140*68b2bbf2SGordon Ross XDR xdrs; 141*68b2bbf2SGordon Ross smb_netuserinfo_t nui; 142*68b2bbf2SGordon Ross smb_pipehdr_t phdr; 143*68b2bbf2SGordon Ross char *buf; 144*68b2bbf2SGordon Ross uint32_t buflen; 145*68b2bbf2SGordon Ross uint32_t status; 146*68b2bbf2SGordon Ross size_t iocnt = 0; 147*68b2bbf2SGordon Ross int rc; 148*68b2bbf2SGordon Ross 149*68b2bbf2SGordon Ross /* 150*68b2bbf2SGordon Ross * Any errors building the XDR message etc. 151*68b2bbf2SGordon Ross */ 152*68b2bbf2SGordon Ross errp->status = NT_STATUS_INTERNAL_ERROR; 153*68b2bbf2SGordon Ross 154*68b2bbf2SGordon Ross smb_user_netinfo_init(sr->uid_user, &nui); 155*68b2bbf2SGordon Ross phdr.ph_magic = SMB_PIPE_HDR_MAGIC; 156*68b2bbf2SGordon Ross phdr.ph_uilen = xdr_sizeof(smb_netuserinfo_xdr, &nui); 157*68b2bbf2SGordon Ross 158*68b2bbf2SGordon Ross buflen = sizeof (phdr) + phdr.ph_uilen; 159*68b2bbf2SGordon Ross buf = kmem_alloc(buflen, KM_SLEEP); 160*68b2bbf2SGordon Ross 161*68b2bbf2SGordon Ross bcopy(&phdr, buf, sizeof (phdr)); 162*68b2bbf2SGordon Ross xdrmem_create(&xdrs, buf + sizeof (phdr), 163*68b2bbf2SGordon Ross buflen - (sizeof (phdr)), XDR_ENCODE); 164*68b2bbf2SGordon Ross if (!smb_netuserinfo_xdr(&xdrs, &nui)) 165*68b2bbf2SGordon Ross goto out; 166*68b2bbf2SGordon Ross 167*68b2bbf2SGordon Ross /* 168*68b2bbf2SGordon Ross * If we fail sending the netuserinfo or recv'ing the 169*68b2bbf2SGordon Ross * status reponse, we have probably run into the limit 170*68b2bbf2SGordon Ross * on the number of open pipes. That's this status: 171*68b2bbf2SGordon Ross */ 172*68b2bbf2SGordon Ross errp->status = NT_STATUS_PIPE_NOT_AVAILABLE; 173*68b2bbf2SGordon Ross 174*68b2bbf2SGordon Ross rc = ksocket_send(opipe->p_socket, buf, buflen, 0, 175*68b2bbf2SGordon Ross &iocnt, sr->user_cr); 176*68b2bbf2SGordon Ross if (rc == 0 && iocnt != buflen) 177*68b2bbf2SGordon Ross rc = EIO; 178*68b2bbf2SGordon Ross if (rc != 0) 179*68b2bbf2SGordon Ross goto out; 180*68b2bbf2SGordon Ross 181*68b2bbf2SGordon Ross rc = ksocket_recv(opipe->p_socket, &status, sizeof (status), 0, 182*68b2bbf2SGordon Ross &iocnt, sr->user_cr); 183*68b2bbf2SGordon Ross if (rc != 0 || iocnt != sizeof (status)) 184*68b2bbf2SGordon Ross goto out; 185*68b2bbf2SGordon Ross 186*68b2bbf2SGordon Ross /* 187*68b2bbf2SGordon Ross * Return the status we read from the pipe service, 188*68b2bbf2SGordon Ross * normally NT_STATUS_SUCCESS, but could be something 189*68b2bbf2SGordon Ross * else like NT_STATUS_ACCESS_DENIED. 190*68b2bbf2SGordon Ross */ 191*68b2bbf2SGordon Ross errp->status = status; 192*68b2bbf2SGordon Ross 193*68b2bbf2SGordon Ross out: 194*68b2bbf2SGordon Ross xdr_destroy(&xdrs); 195*68b2bbf2SGordon Ross kmem_free(buf, buflen); 196*68b2bbf2SGordon Ross smb_user_netinfo_fini(&nui); 197*68b2bbf2SGordon Ross } 198*68b2bbf2SGordon Ross 199*68b2bbf2SGordon Ross /* 2003db3f65cSamw * smb_opipe_open 2013db3f65cSamw * 202*68b2bbf2SGordon Ross * Open an RPC named pipe. This routine should be called if 2033db3f65cSamw * a file open is requested on a share of type STYPE_IPC. 2043db3f65cSamw * If we recognize the pipe, we setup a new ofile. 2053db3f65cSamw * 206*68b2bbf2SGordon Ross * Returns 0 on success, Otherwise an NT status code. 2073db3f65cSamw */ 2083db3f65cSamw int 209*68b2bbf2SGordon Ross smb_opipe_open(smb_request_t *sr, uint32_t uniqid) 2103db3f65cSamw { 211148c5f43SAlan Wright smb_arg_open_t *op = &sr->sr_open; 212*68b2bbf2SGordon Ross smb_ofile_t *ofile; 2133db3f65cSamw smb_opipe_t *opipe; 2143db3f65cSamw smb_error_t err; 2153db3f65cSamw 216*68b2bbf2SGordon Ross opipe = smb_opipe_alloc(sr); 217*68b2bbf2SGordon Ross if (opipe == NULL) 218*68b2bbf2SGordon Ross return (NT_STATUS_INTERNAL_ERROR); 2193db3f65cSamw 220*68b2bbf2SGordon Ross if (smb_opipe_connect(sr, opipe) != 0) { 221*68b2bbf2SGordon Ross smb_opipe_dealloc(opipe); 2228b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 2238b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 2248b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 225*68b2bbf2SGordon Ross smb_opipe_send_userinfo(sr, opipe, &err); 226*68b2bbf2SGordon Ross if (err.status != 0) { 227*68b2bbf2SGordon Ross smb_opipe_dealloc(opipe); 228*68b2bbf2SGordon Ross return (err.status); 229*68b2bbf2SGordon Ross } 230*68b2bbf2SGordon Ross 231*68b2bbf2SGordon Ross /* 232*68b2bbf2SGordon Ross * Note: If smb_ofile_open succeeds, the new ofile is 233*68b2bbf2SGordon Ross * in the FID lists can can be used by I/O requests. 234*68b2bbf2SGordon Ross */ 235*68b2bbf2SGordon Ross op->create_options = 0; 236*68b2bbf2SGordon Ross op->pipe = opipe; 237*68b2bbf2SGordon Ross ofile = smb_ofile_open(sr, NULL, op, 238*68b2bbf2SGordon Ross SMB_FTYPE_MESG_PIPE, uniqid, &err); 239*68b2bbf2SGordon Ross op->pipe = NULL; 240*68b2bbf2SGordon Ross if (ofile == NULL) { 241*68b2bbf2SGordon Ross smb_opipe_dealloc(opipe); 242*68b2bbf2SGordon Ross return (err.status); 243*68b2bbf2SGordon Ross } 244*68b2bbf2SGordon Ross 245*68b2bbf2SGordon Ross /* An "up" pointer, for debug. */ 246*68b2bbf2SGordon Ross opipe->p_ofile = ofile; 247*68b2bbf2SGordon Ross 2483db3f65cSamw op->dsize = 0x01000; 2493db3f65cSamw op->dattr = FILE_ATTRIBUTE_NORMAL; 2503db3f65cSamw op->ftype = SMB_FTYPE_MESG_PIPE; 2513db3f65cSamw op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */ 2523db3f65cSamw op->devstate = SMB_PIPE_READMODE_MESSAGE 2533db3f65cSamw | SMB_PIPE_TYPE_MESSAGE 2543db3f65cSamw | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */ 255*68b2bbf2SGordon Ross op->fileid = ofile->f_fid; 2563db3f65cSamw 257*68b2bbf2SGordon Ross sr->smb_fid = ofile->f_fid; 258*68b2bbf2SGordon Ross sr->fid_ofile = ofile; 2593db3f65cSamw 2603db3f65cSamw return (NT_STATUS_SUCCESS); 2613db3f65cSamw } 2623db3f65cSamw 2633db3f65cSamw /* 2643db3f65cSamw * smb_opipe_close 2653db3f65cSamw * 266*68b2bbf2SGordon Ross * Called by smb_ofile_close for pipes. 267*68b2bbf2SGordon Ross * 268*68b2bbf2SGordon Ross * Note: ksocket_close may block while waiting for 269*68b2bbf2SGordon Ross * any I/O threads with a hold to get out. 2703db3f65cSamw */ 2713db3f65cSamw void 2723db3f65cSamw smb_opipe_close(smb_ofile_t *of) 2733db3f65cSamw { 2743db3f65cSamw smb_opipe_t *opipe; 275*68b2bbf2SGordon Ross ksocket_t sock; 2763db3f65cSamw 277*68b2bbf2SGordon Ross ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING); 2783db3f65cSamw ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE); 2793db3f65cSamw opipe = of->f_pipe; 2809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 2819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 282*68b2bbf2SGordon Ross mutex_enter(&opipe->p_mutex); 283*68b2bbf2SGordon Ross sock = opipe->p_socket; 284*68b2bbf2SGordon Ross opipe->p_socket = NULL; 285*68b2bbf2SGordon Ross mutex_exit(&opipe->p_mutex); 2863db3f65cSamw 287*68b2bbf2SGordon Ross (void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr); 288*68b2bbf2SGordon Ross (void) ksocket_close(sock, of->f_cr); 2893db3f65cSamw } 2903db3f65cSamw 2913db3f65cSamw /* 2923db3f65cSamw * smb_opipe_write 2933db3f65cSamw * 2943db3f65cSamw * Write RPC request data to the pipe. The client should call smb_opipe_read 2953db3f65cSamw * to complete the exchange and obtain the RPC response. 2963db3f65cSamw * 2973db3f65cSamw * Returns 0 on success or an errno on failure. 2983db3f65cSamw */ 2993db3f65cSamw int 3003db3f65cSamw smb_opipe_write(smb_request_t *sr, struct uio *uio) 3013db3f65cSamw { 302*68b2bbf2SGordon Ross struct nmsghdr msghdr; 303*68b2bbf2SGordon Ross smb_ofile_t *ofile; 3043db3f65cSamw smb_opipe_t *opipe; 305*68b2bbf2SGordon Ross ksocket_t sock; 306*68b2bbf2SGordon Ross size_t sent = 0; 307*68b2bbf2SGordon Ross int rc = 0; 3083db3f65cSamw 309*68b2bbf2SGordon Ross ofile = sr->fid_ofile; 310*68b2bbf2SGordon Ross ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 311*68b2bbf2SGordon Ross opipe = ofile->f_pipe; 3129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 3133db3f65cSamw 314*68b2bbf2SGordon Ross mutex_enter(&opipe->p_mutex); 315*68b2bbf2SGordon Ross sock = opipe->p_socket; 316*68b2bbf2SGordon Ross if (sock != NULL) 317*68b2bbf2SGordon Ross ksocket_hold(sock); 318*68b2bbf2SGordon Ross mutex_exit(&opipe->p_mutex); 319*68b2bbf2SGordon Ross if (sock == NULL) 3203db3f65cSamw return (EBADF); 321*68b2bbf2SGordon Ross 322*68b2bbf2SGordon Ross bzero(&msghdr, sizeof (msghdr)); 323*68b2bbf2SGordon Ross msghdr.msg_iov = uio->uio_iov; 324*68b2bbf2SGordon Ross msghdr.msg_iovlen = uio->uio_iovcnt; 325*68b2bbf2SGordon Ross 326*68b2bbf2SGordon Ross /* 327*68b2bbf2SGordon Ross * This should block until we've sent it all, 328*68b2bbf2SGordon Ross * or given up due to errors (pipe closed). 329*68b2bbf2SGordon Ross */ 330*68b2bbf2SGordon Ross while (uio->uio_resid > 0) { 331*68b2bbf2SGordon Ross rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr); 332*68b2bbf2SGordon Ross if (rc != 0) 333*68b2bbf2SGordon Ross break; 334*68b2bbf2SGordon Ross uio->uio_resid -= sent; 3353db3f65cSamw } 3363db3f65cSamw 337*68b2bbf2SGordon Ross ksocket_rele(sock); 3383db3f65cSamw 339*68b2bbf2SGordon Ross return (rc); 3403db3f65cSamw } 3413db3f65cSamw 3423db3f65cSamw /* 3433db3f65cSamw * smb_opipe_read 3443db3f65cSamw * 345*68b2bbf2SGordon Ross * This interface may be called from smb_opipe_transact (write, read) 346*68b2bbf2SGordon Ross * or from smb_read / smb2_read to get the rest of an RPC response. 347*68b2bbf2SGordon Ross * The response data (and length) are returned via the uio. 3483db3f65cSamw */ 3493db3f65cSamw int 3503db3f65cSamw smb_opipe_read(smb_request_t *sr, struct uio *uio) 3513db3f65cSamw { 352*68b2bbf2SGordon Ross struct nmsghdr msghdr; 353*68b2bbf2SGordon Ross smb_ofile_t *ofile; 3543db3f65cSamw smb_opipe_t *opipe; 355*68b2bbf2SGordon Ross ksocket_t sock; 356*68b2bbf2SGordon Ross size_t recvcnt = 0; 3573db3f65cSamw int rc; 3583db3f65cSamw 359*68b2bbf2SGordon Ross ofile = sr->fid_ofile; 360*68b2bbf2SGordon Ross ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 361*68b2bbf2SGordon Ross opipe = ofile->f_pipe; 3629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 3639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 364*68b2bbf2SGordon Ross mutex_enter(&opipe->p_mutex); 365*68b2bbf2SGordon Ross sock = opipe->p_socket; 366*68b2bbf2SGordon Ross if (sock != NULL) 367*68b2bbf2SGordon Ross ksocket_hold(sock); 368*68b2bbf2SGordon Ross mutex_exit(&opipe->p_mutex); 369*68b2bbf2SGordon Ross if (sock == NULL) 3703db3f65cSamw return (EBADF); 3713db3f65cSamw 372*68b2bbf2SGordon Ross bzero(&msghdr, sizeof (msghdr)); 373*68b2bbf2SGordon Ross msghdr.msg_iov = uio->uio_iov; 374*68b2bbf2SGordon Ross msghdr.msg_iovlen = uio->uio_iovcnt; 3759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 3763db3f65cSamw /* 377*68b2bbf2SGordon Ross * This should block only if there's no data. 378*68b2bbf2SGordon Ross * A single call to recvmsg does just that. 379*68b2bbf2SGordon Ross * (Intentionaly no recv loop here.) 3803db3f65cSamw */ 381*68b2bbf2SGordon Ross rc = ksocket_recvmsg(sock, &msghdr, 0, 382*68b2bbf2SGordon Ross &recvcnt, ofile->f_cr); 383*68b2bbf2SGordon Ross if (rc != 0) 384*68b2bbf2SGordon Ross goto out; 3853db3f65cSamw 386*68b2bbf2SGordon Ross if (recvcnt == 0) { 387*68b2bbf2SGordon Ross /* Other side closed. */ 388*68b2bbf2SGordon Ross rc = EPIPE; 389*68b2bbf2SGordon Ross goto out; 3903db3f65cSamw } 391*68b2bbf2SGordon Ross uio->uio_resid -= recvcnt; 3923db3f65cSamw 3939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* 394*68b2bbf2SGordon Ross * If we filled the user's buffer, 395*68b2bbf2SGordon Ross * find out if there's more data. 3969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */ 397*68b2bbf2SGordon Ross if (uio->uio_resid == 0) { 398*68b2bbf2SGordon Ross int rc2, nread, trval; 399*68b2bbf2SGordon Ross rc2 = ksocket_ioctl(sock, FIONREAD, (intptr_t)&nread, 400*68b2bbf2SGordon Ross &trval, ofile->f_cr); 401*68b2bbf2SGordon Ross if (rc2 == 0 && nread != 0) 402*68b2bbf2SGordon Ross rc = E2BIG; /* more data */ 403*68b2bbf2SGordon Ross } 404*68b2bbf2SGordon Ross 405*68b2bbf2SGordon Ross out: 406*68b2bbf2SGordon Ross ksocket_rele(sock); 407*68b2bbf2SGordon Ross 408*68b2bbf2SGordon Ross return (rc); 4093db3f65cSamw } 410