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 /* 22*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 233db3f65cSamw * Use is subject to license terms. 243db3f65cSamw */ 253db3f65cSamw 263db3f65cSamw /* 273db3f65cSamw * This module provides the interface to NDR RPC. 283db3f65cSamw */ 293db3f65cSamw 303db3f65cSamw #include <sys/stat.h> 313db3f65cSamw #include <sys/door.h> 323db3f65cSamw #include <sys/door_data.h> 333db3f65cSamw #include <sys/uio.h> 343db3f65cSamw #include <sys/ksynch.h> 35bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 363db3f65cSamw #include <smbsrv/smb_xdr.h> 373db3f65cSamw 383db3f65cSamw #define SMB_OPIPE_ISOPEN(OPIPE) \ 39*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (((OPIPE)->p_hdr.dh_magic == SMB_OPIPE_HDR_MAGIC) && \ 40*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ((OPIPE)->p_hdr.dh_fid)) 413db3f65cSamw 423db3f65cSamw extern volatile uint32_t smb_fids; 433db3f65cSamw 443db3f65cSamw static int smb_opipe_do_open(smb_request_t *, smb_opipe_t *); 45*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static char *smb_opipe_lookup(const char *); 46*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_opipe_sethdr(smb_opipe_t *, uint32_t, uint32_t); 47*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_opipe_exec(smb_opipe_t *); 483db3f65cSamw static void smb_opipe_enter(smb_opipe_t *); 493db3f65cSamw static void smb_opipe_exit(smb_opipe_t *); 503db3f65cSamw 513db3f65cSamw static door_handle_t smb_opipe_door_hd = NULL; 523db3f65cSamw static int smb_opipe_door_id = -1; 533db3f65cSamw static uint64_t smb_opipe_door_ncall = 0; 543db3f65cSamw static kmutex_t smb_opipe_door_mutex; 553db3f65cSamw static kcondvar_t smb_opipe_door_cv; 563db3f65cSamw 573db3f65cSamw static int smb_opipe_door_call(smb_opipe_t *); 583db3f65cSamw static int smb_opipe_door_upcall(smb_opipe_t *); 593db3f65cSamw 60*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_t * 61*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_alloc(smb_server_t *sv) 62*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 63*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_t *opipe; 64*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 65*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe = kmem_cache_alloc(sv->si_cache_opipe, KM_SLEEP); 66*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 67*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(opipe, sizeof (smb_opipe_t)); 68*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL); 69*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL); 70*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_magic = SMB_OPIPE_MAGIC; 71*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_server = sv; 72*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 73*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_enter(&sv->sv_opipe_list, RW_WRITER); 74*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_insert_tail(&sv->sv_opipe_list, opipe); 75*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(&sv->sv_opipe_list); 76*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 77*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (opipe); 78*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 79*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 80*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 81*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_dealloc(smb_opipe_t *opipe) 82*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 83*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_t *sv; 84*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 85*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 86*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States sv = opipe->p_server; 87*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_SERVER_VALID(sv); 88*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 89*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_enter(&sv->sv_opipe_list, RW_WRITER); 90*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_remove(&sv->sv_opipe_list, opipe); 91*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(&sv->sv_opipe_list); 92*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 93*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC; 94*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_destroy(opipe->p_event); 95*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States cv_destroy(&opipe->p_cv); 96*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_destroy(&opipe->p_mutex); 97*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 98*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States kmem_cache_free(sv->si_cache_opipe, opipe); 99*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 100*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1013db3f65cSamw /* 1023db3f65cSamw * smb_opipe_open 1033db3f65cSamw * 1043db3f65cSamw * Open a well-known RPC named pipe. This routine should be called if 1053db3f65cSamw * a file open is requested on a share of type STYPE_IPC. 1063db3f65cSamw * If we recognize the pipe, we setup a new ofile. 1073db3f65cSamw * 1083db3f65cSamw * Returns 0 on success, Otherwise an NT status is returned to indicate 1093db3f65cSamw * an error. 1103db3f65cSamw */ 1113db3f65cSamw int 1123db3f65cSamw smb_opipe_open(smb_request_t *sr) 1133db3f65cSamw { 1148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States open_param_t *op = &sr->arg.open; 1153db3f65cSamw smb_ofile_t *of; 1163db3f65cSamw smb_opipe_t *opipe; 117*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_doorhdr_t hdr; 1183db3f65cSamw smb_error_t err; 1193db3f65cSamw char *pipe_name; 1203db3f65cSamw 121eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States if ((pipe_name = smb_opipe_lookup(op->fqi.fq_path.pn_path)) == NULL) 1223db3f65cSamw return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 1233db3f65cSamw 124c8ec8eeaSjose borrego op->create_options = 0; 125c8ec8eeaSjose borrego 126c8ec8eeaSjose borrego of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op, 1273db3f65cSamw SMB_FTYPE_MESG_PIPE, SMB_UNIQ_FID(), &err); 1288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 1293db3f65cSamw if (of == NULL) 1303db3f65cSamw return (err.status); 1313db3f65cSamw 1328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (!smb_tree_is_connected(sr->tid_tree)) { 1338b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_ofile_close(of, 0); 1348b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_ofile_release(of); 1358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 1368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 1378b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 1383db3f65cSamw op->dsize = 0x01000; 1393db3f65cSamw op->dattr = FILE_ATTRIBUTE_NORMAL; 1403db3f65cSamw op->ftype = SMB_FTYPE_MESG_PIPE; 1413db3f65cSamw op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */ 1423db3f65cSamw op->devstate = SMB_PIPE_READMODE_MESSAGE 1433db3f65cSamw | SMB_PIPE_TYPE_MESSAGE 1443db3f65cSamw | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */ 1453db3f65cSamw op->fileid = of->f_fid; 1463db3f65cSamw 1473db3f65cSamw sr->smb_fid = of->f_fid; 1483db3f65cSamw sr->fid_ofile = of; 1493db3f65cSamw 1503db3f65cSamw opipe = of->f_pipe; 1513db3f65cSamw smb_opipe_enter(opipe); 1523db3f65cSamw 153*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_server = of->f_server; 1543db3f65cSamw opipe->p_name = pipe_name; 1553db3f65cSamw opipe->p_doorbuf = kmem_zalloc(SMB_OPIPE_DOOR_BUFSIZE, KM_SLEEP); 1563db3f65cSamw 1573db3f65cSamw /* 1583db3f65cSamw * p_data points to the offset within p_doorbuf at which 1593db3f65cSamw * data will be written or read. 1603db3f65cSamw */ 161*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_data = opipe->p_doorbuf + xdr_sizeof(smb_doorhdr_xdr, &hdr); 1623db3f65cSamw 1633db3f65cSamw if (smb_opipe_do_open(sr, opipe) != 0) { 1643db3f65cSamw /* 1653db3f65cSamw * On error, reset the header to clear the fid, 1663db3f65cSamw * which avoids confusion when smb_opipe_close() is 1673db3f65cSamw * called by smb_ofile_close(). 1683db3f65cSamw */ 169*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 1703db3f65cSamw kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 1713db3f65cSamw smb_opipe_exit(opipe); 172c8ec8eeaSjose borrego smb_ofile_close(of, 0); 1733db3f65cSamw return (NT_STATUS_NO_MEMORY); 1743db3f65cSamw } 1753db3f65cSamw smb_opipe_exit(opipe); 1763db3f65cSamw return (NT_STATUS_SUCCESS); 1773db3f65cSamw } 1783db3f65cSamw 1793db3f65cSamw /* 1803db3f65cSamw * smb_opipe_lookup 1813db3f65cSamw * 1823db3f65cSamw * Lookup a path to see if it's a well-known RPC named pipe that we support. 1833db3f65cSamw * The full pipe path will be in the form \\PIPE\\SERVICE. The first part 1843db3f65cSamw * can be assumed, so all we need here are the service names. 1853db3f65cSamw * 1861fcced4cSJordan Brown * Returns a pointer to the pipe name (without any leading \'s) on success. 1873db3f65cSamw * Otherwise returns a null pointer. 1883db3f65cSamw */ 1893db3f65cSamw static char * 1903db3f65cSamw smb_opipe_lookup(const char *path) 1913db3f65cSamw { 1923db3f65cSamw static char *named_pipes[] = { 1931fcced4cSJordan Brown "lsass", 1943db3f65cSamw "LSARPC", 1953db3f65cSamw "NETLOGON", 1963db3f65cSamw "SAMR", 1973db3f65cSamw "SPOOLSS", 1983db3f65cSamw "SRVSVC", 1993db3f65cSamw "SVCCTL", 2003db3f65cSamw "WINREG", 2013db3f65cSamw "WKSSVC", 202*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States "EVENTLOG", 203*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States "NETDFS" 2043db3f65cSamw }; 2053db3f65cSamw 2063db3f65cSamw const char *name; 2073db3f65cSamw int i; 2083db3f65cSamw 2093db3f65cSamw if (path == NULL) 2103db3f65cSamw return (NULL); 2113db3f65cSamw 2123db3f65cSamw name = path; 2133db3f65cSamw name += strspn(name, "\\"); 214bbf6f00cSJordan Brown if (smb_strcasecmp(name, "PIPE", 4) == 0) { 2153db3f65cSamw path += 4; 2163db3f65cSamw name += strspn(name, "\\"); 2173db3f65cSamw } 2183db3f65cSamw 2193db3f65cSamw for (i = 0; i < sizeof (named_pipes) / sizeof (named_pipes[0]); ++i) { 220bbf6f00cSJordan Brown if (smb_strcasecmp(name, named_pipes[i], 0) == 0) 2213db3f65cSamw return (named_pipes[i]); 2223db3f65cSamw } 2233db3f65cSamw 2243db3f65cSamw return (NULL); 2253db3f65cSamw } 2263db3f65cSamw 2273db3f65cSamw /* 2283db3f65cSamw * Initialize the opipe header and context, and make the door call. 2293db3f65cSamw */ 2303db3f65cSamw static int 2313db3f65cSamw smb_opipe_do_open(smb_request_t *sr, smb_opipe_t *opipe) 2323db3f65cSamw { 2331fcced4cSJordan Brown smb_netuserinfo_t *userinfo = &opipe->p_user; 2343db3f65cSamw smb_user_t *user = sr->uid_user; 2353db3f65cSamw uint8_t *buf = opipe->p_doorbuf; 2363db3f65cSamw uint32_t buflen = SMB_OPIPE_DOOR_BUFSIZE; 2373db3f65cSamw uint32_t len; 2383db3f65cSamw 239*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((opipe->p_event = smb_event_create()) == NULL) 240*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (-1); 241*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2421fcced4cSJordan Brown smb_user_netinfo_init(user, userinfo); 2431fcced4cSJordan Brown len = xdr_sizeof(smb_netuserinfo_xdr, userinfo); 2443db3f65cSamw 245*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 246*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_magic = SMB_OPIPE_HDR_MAGIC; 247*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_flags = SMB_DF_SYSSPACE; 248*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_fid = smb_event_txid(opipe->p_event); 2493db3f65cSamw 250*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_opipe_sethdr(opipe, SMB_OPIPE_OPEN, len) == -1) 2513db3f65cSamw return (-1); 2523db3f65cSamw 253*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 2543db3f65cSamw buf += len; 2553db3f65cSamw buflen -= len; 2563db3f65cSamw 2571fcced4cSJordan Brown if (smb_netuserinfo_encode(userinfo, buf, buflen, NULL) == -1) 2583db3f65cSamw return (-1); 2593db3f65cSamw 2603db3f65cSamw return (smb_opipe_door_call(opipe)); 2613db3f65cSamw } 2623db3f65cSamw 2633db3f65cSamw /* 2643db3f65cSamw * smb_opipe_close 2653db3f65cSamw * 2663db3f65cSamw * Called whenever an IPC file/pipe is closed. 2673db3f65cSamw */ 2683db3f65cSamw void 2693db3f65cSamw smb_opipe_close(smb_ofile_t *of) 2703db3f65cSamw { 2713db3f65cSamw smb_opipe_t *opipe; 2723db3f65cSamw 2733db3f65cSamw ASSERT(of); 2743db3f65cSamw ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE); 2753db3f65cSamw 2763db3f65cSamw opipe = of->f_pipe; 277*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 278*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 279*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_server_cancel_event(opipe->p_hdr.dh_fid); 2803db3f65cSamw smb_opipe_enter(opipe); 2813db3f65cSamw 2823db3f65cSamw if (SMB_OPIPE_ISOPEN(opipe)) { 283*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_opipe_sethdr(opipe, SMB_OPIPE_CLOSE, 0); 2843db3f65cSamw (void) smb_opipe_door_call(opipe); 285*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 2863db3f65cSamw kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 2873db3f65cSamw } 2883db3f65cSamw 2891fcced4cSJordan Brown smb_user_netinfo_fini(&opipe->p_user); 2903db3f65cSamw smb_opipe_exit(opipe); 2913db3f65cSamw } 2923db3f65cSamw 2933db3f65cSamw static int 294*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_sethdr(smb_opipe_t *opipe, uint32_t cmd, uint32_t datalen) 2953db3f65cSamw { 296*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_op = cmd; 297*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_txid = opipe->p_hdr.dh_fid; 298*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_datalen = datalen; 299*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_resid = 0; 300*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_door_rc = EINVAL; 3013db3f65cSamw 302*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (smb_doorhdr_encode(&opipe->p_hdr, opipe->p_doorbuf, 3033db3f65cSamw SMB_OPIPE_DOOR_BUFSIZE)); 3043db3f65cSamw } 3053db3f65cSamw 3063db3f65cSamw /* 3073db3f65cSamw * smb_opipe_transact 3083db3f65cSamw * 3093db3f65cSamw * This is the entry point for RPC bind and request transactions. 3103db3f65cSamw * The fid is an arbitrary id used to associate RPC requests with a 3113db3f65cSamw * particular binding handle. 3123db3f65cSamw * 3133db3f65cSamw * If the data to be returned is larger than the client expects, we 3143db3f65cSamw * return as much as the client can handle and report a buffer overflow 3153db3f65cSamw * warning, which informs the client that we have more data to return. 3163db3f65cSamw * The residual data remains in the pipe until the client claims it or 3173db3f65cSamw * closes the pipe. 3183db3f65cSamw */ 3193db3f65cSamw smb_sdrc_t 3203db3f65cSamw smb_opipe_transact(smb_request_t *sr, struct uio *uio) 3213db3f65cSamw { 3223db3f65cSamw smb_xa_t *xa; 3233db3f65cSamw smb_opipe_t *opipe; 3243db3f65cSamw struct mbuf *mhead; 3253db3f65cSamw int mdrcnt; 3263db3f65cSamw int nbytes; 3273db3f65cSamw int rc; 3283db3f65cSamw 3293db3f65cSamw if ((rc = smb_opipe_write(sr, uio)) != 0) { 3303db3f65cSamw if (rc == EBADF) 3313db3f65cSamw smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 3323db3f65cSamw ERRDOS, ERROR_INVALID_HANDLE); 3333db3f65cSamw else 3343db3f65cSamw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 3353db3f65cSamw ERRDOS, ERROR_INTERNAL_ERROR); 3363db3f65cSamw return (SDRC_ERROR); 3373db3f65cSamw } 3383db3f65cSamw 339*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe = sr->fid_ofile->f_pipe; 340*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 341*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((rc = smb_opipe_exec(opipe)) != 0) { 342*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 343*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ERRDOS, ERROR_INTERNAL_ERROR); 344*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (SDRC_ERROR); 345*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 346*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 3473db3f65cSamw xa = sr->r_xa; 3483db3f65cSamw mdrcnt = xa->smb_mdrcnt; 3493db3f65cSamw smb_opipe_enter(opipe); 3503db3f65cSamw 351*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, mdrcnt) == -1) { 3523db3f65cSamw smb_opipe_exit(opipe); 3533db3f65cSamw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 3543db3f65cSamw ERRDOS, ERROR_INTERNAL_ERROR); 3553db3f65cSamw return (SDRC_ERROR); 3563db3f65cSamw } 3573db3f65cSamw 3583db3f65cSamw rc = smb_opipe_door_call(opipe); 359*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States nbytes = opipe->p_hdr.dh_datalen; 3603db3f65cSamw 3613db3f65cSamw if (rc != 0) { 3623db3f65cSamw smb_opipe_exit(opipe); 3633db3f65cSamw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 3643db3f65cSamw ERRDOS, ERROR_INTERNAL_ERROR); 3653db3f65cSamw return (SDRC_ERROR); 3663db3f65cSamw } 3673db3f65cSamw 3683db3f65cSamw if (nbytes) { 3693db3f65cSamw mhead = smb_mbuf_get(opipe->p_data, nbytes); 3703db3f65cSamw xa->rep_data_mb.max_bytes = nbytes; 3713db3f65cSamw MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead); 3723db3f65cSamw } 3733db3f65cSamw 374*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (opipe->p_hdr.dh_resid) { 3753db3f65cSamw /* 3763db3f65cSamw * The pipe contains more data than mdrcnt, warn the 3773db3f65cSamw * client that there is more data in the pipe. 3783db3f65cSamw * Typically, the client will call SmbReadX, which 3793db3f65cSamw * will call smb_opipe_read, to get the data. 3803db3f65cSamw */ 3813db3f65cSamw smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW, 3823db3f65cSamw ERRDOS, ERROR_MORE_DATA); 3833db3f65cSamw } 3843db3f65cSamw 3853db3f65cSamw smb_opipe_exit(opipe); 3863db3f65cSamw return (SDRC_SUCCESS); 3873db3f65cSamw } 3883db3f65cSamw 3893db3f65cSamw /* 3903db3f65cSamw * smb_opipe_write 3913db3f65cSamw * 3923db3f65cSamw * Write RPC request data to the pipe. The client should call smb_opipe_read 3933db3f65cSamw * to complete the exchange and obtain the RPC response. 3943db3f65cSamw * 3953db3f65cSamw * Returns 0 on success or an errno on failure. 3963db3f65cSamw */ 3973db3f65cSamw int 3983db3f65cSamw smb_opipe_write(smb_request_t *sr, struct uio *uio) 3993db3f65cSamw { 4003db3f65cSamw smb_opipe_t *opipe; 4013db3f65cSamw uint32_t buflen; 4023db3f65cSamw uint32_t len; 4033db3f65cSamw int rc; 4043db3f65cSamw 4053db3f65cSamw ASSERT(sr->fid_ofile); 4063db3f65cSamw ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 4073db3f65cSamw 4083db3f65cSamw opipe = sr->fid_ofile->f_pipe; 409*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 4103db3f65cSamw smb_opipe_enter(opipe); 4113db3f65cSamw 4123db3f65cSamw if (!SMB_OPIPE_ISOPEN(opipe)) { 4133db3f65cSamw smb_opipe_exit(opipe); 4143db3f65cSamw return (EBADF); 4153db3f65cSamw } 4163db3f65cSamw 417*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_opipe_sethdr(opipe, SMB_OPIPE_WRITE, uio->uio_resid); 418*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 4193db3f65cSamw if (rc == -1 || len == 0) { 4203db3f65cSamw smb_opipe_exit(opipe); 4213db3f65cSamw return (ENOMEM); 4223db3f65cSamw } 4233db3f65cSamw 4243db3f65cSamw buflen = SMB_OPIPE_DOOR_BUFSIZE - len; 4253db3f65cSamw (void) uiomove((caddr_t)opipe->p_data, buflen, UIO_WRITE, uio); 4263db3f65cSamw 4273db3f65cSamw rc = smb_opipe_door_call(opipe); 4283db3f65cSamw 4293db3f65cSamw smb_opipe_exit(opipe); 4303db3f65cSamw return ((rc == 0) ? 0 : EIO); 4313db3f65cSamw } 4323db3f65cSamw 4333db3f65cSamw /* 4343db3f65cSamw * smb_opipe_read 4353db3f65cSamw * 4363db3f65cSamw * This interface may be called because smb_opipe_transact could not return 4373db3f65cSamw * all of the data in the original transaction or to form the second half 4383db3f65cSamw * of a transaction set up using smb_opipe_write. Either way, we just need 4393db3f65cSamw * to read data from the pipe and return it. 4403db3f65cSamw * 4413db3f65cSamw * The response data is encoded into raw_data as required by the smb_read 4423db3f65cSamw * functions. The uio_resid value indicates the number of bytes read. 4433db3f65cSamw */ 4443db3f65cSamw int 4453db3f65cSamw smb_opipe_read(smb_request_t *sr, struct uio *uio) 4463db3f65cSamw { 4473db3f65cSamw smb_opipe_t *opipe; 4483db3f65cSamw struct mbuf *mhead; 4493db3f65cSamw uint32_t nbytes; 4503db3f65cSamw int rc; 4513db3f65cSamw 4523db3f65cSamw ASSERT(sr->fid_ofile); 4533db3f65cSamw ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 4543db3f65cSamw 4553db3f65cSamw opipe = sr->fid_ofile->f_pipe; 456*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 457*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 458*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((rc = smb_opipe_exec(opipe)) != 0) 459*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (EIO); 460*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 4613db3f65cSamw smb_opipe_enter(opipe); 4623db3f65cSamw 4633db3f65cSamw if (!SMB_OPIPE_ISOPEN(opipe)) { 4643db3f65cSamw smb_opipe_exit(opipe); 4653db3f65cSamw return (EBADF); 4663db3f65cSamw } 4673db3f65cSamw 468*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, uio->uio_resid) == -1) { 4693db3f65cSamw smb_opipe_exit(opipe); 4703db3f65cSamw return (ENOMEM); 4713db3f65cSamw } 4723db3f65cSamw 4733db3f65cSamw rc = smb_opipe_door_call(opipe); 474*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States nbytes = opipe->p_hdr.dh_datalen; 4753db3f65cSamw 4763db3f65cSamw if (rc != 0 || nbytes > uio->uio_resid) { 4773db3f65cSamw smb_opipe_exit(opipe); 4783db3f65cSamw return (EIO); 4793db3f65cSamw } 4803db3f65cSamw 4813db3f65cSamw if (nbytes) { 4823db3f65cSamw mhead = smb_mbuf_get(opipe->p_data, nbytes); 4833db3f65cSamw MBC_SETUP(&sr->raw_data, nbytes); 4843db3f65cSamw MBC_ATTACH_MBUF(&sr->raw_data, mhead); 4853db3f65cSamw uio->uio_resid -= nbytes; 4863db3f65cSamw } 4873db3f65cSamw 4883db3f65cSamw smb_opipe_exit(opipe); 4893db3f65cSamw return (rc); 4903db3f65cSamw } 4913db3f65cSamw 492*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int 493*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_exec(smb_opipe_t *opipe) 494*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 495*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uint32_t len; 496*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int rc; 497*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 498*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_enter(opipe); 499*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 500*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_opipe_sethdr(opipe, SMB_OPIPE_EXEC, 0); 501*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 502*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (rc == -1 || len == 0) { 503*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_exit(opipe); 504*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (ENOMEM); 505*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 506*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 507*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((rc = smb_opipe_door_call(opipe)) == 0) 508*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_event_wait(opipe->p_event); 509*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 510*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_exit(opipe); 511*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (rc); 512*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 513*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 5143db3f65cSamw /* 5153db3f65cSamw * Named pipe I/O is serialized per fid to ensure that each request 5163db3f65cSamw * has exclusive opipe access for the duration of the request. 5173db3f65cSamw */ 5183db3f65cSamw static void 5193db3f65cSamw smb_opipe_enter(smb_opipe_t *opipe) 5203db3f65cSamw { 5213db3f65cSamw mutex_enter(&opipe->p_mutex); 5223db3f65cSamw 5233db3f65cSamw while (opipe->p_busy) 5243db3f65cSamw cv_wait(&opipe->p_cv, &opipe->p_mutex); 5253db3f65cSamw 5263db3f65cSamw opipe->p_busy = 1; 5273db3f65cSamw mutex_exit(&opipe->p_mutex); 5283db3f65cSamw } 5293db3f65cSamw 530*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* 531*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Exit busy state. If we have exec'd an RPC, we may have 532*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * to wait for notification that processing has completed. 533*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */ 5343db3f65cSamw static void 5353db3f65cSamw smb_opipe_exit(smb_opipe_t *opipe) 5363db3f65cSamw { 5373db3f65cSamw mutex_enter(&opipe->p_mutex); 5383db3f65cSamw opipe->p_busy = 0; 5393db3f65cSamw cv_signal(&opipe->p_cv); 5403db3f65cSamw mutex_exit(&opipe->p_mutex); 5413db3f65cSamw } 5423db3f65cSamw 5433db3f65cSamw /* 5443db3f65cSamw * opipe door client (to user space door server). 5453db3f65cSamw */ 5463db3f65cSamw void 5473db3f65cSamw smb_opipe_door_init(void) 5483db3f65cSamw { 5493db3f65cSamw mutex_init(&smb_opipe_door_mutex, NULL, MUTEX_DEFAULT, NULL); 5503db3f65cSamw cv_init(&smb_opipe_door_cv, NULL, CV_DEFAULT, NULL); 5513db3f65cSamw } 5523db3f65cSamw 5533db3f65cSamw void 5543db3f65cSamw smb_opipe_door_fini(void) 5553db3f65cSamw { 5563db3f65cSamw smb_opipe_door_close(); 5573db3f65cSamw cv_destroy(&smb_opipe_door_cv); 5583db3f65cSamw mutex_destroy(&smb_opipe_door_mutex); 5593db3f65cSamw } 5603db3f65cSamw 5613db3f65cSamw /* 5623db3f65cSamw * Open the (user space) door. If the door is already open, 5633db3f65cSamw * close it first because the door-id has probably changed. 5643db3f65cSamw */ 5653db3f65cSamw int 5663db3f65cSamw smb_opipe_door_open(int door_id) 5673db3f65cSamw { 5683db3f65cSamw smb_opipe_door_close(); 5693db3f65cSamw 5703db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 5713db3f65cSamw smb_opipe_door_ncall = 0; 5723db3f65cSamw 5733db3f65cSamw if (smb_opipe_door_hd == NULL) { 5743db3f65cSamw smb_opipe_door_id = door_id; 5753db3f65cSamw smb_opipe_door_hd = door_ki_lookup(door_id); 5763db3f65cSamw } 5773db3f65cSamw 5783db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 5793db3f65cSamw return ((smb_opipe_door_hd == NULL) ? -1 : 0); 5803db3f65cSamw } 5813db3f65cSamw 5823db3f65cSamw /* 5833db3f65cSamw * Close the (user space) door. 5843db3f65cSamw */ 5853db3f65cSamw void 5863db3f65cSamw smb_opipe_door_close(void) 5873db3f65cSamw { 5883db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 5893db3f65cSamw 5903db3f65cSamw if (smb_opipe_door_hd != NULL) { 5913db3f65cSamw while (smb_opipe_door_ncall > 0) 5923db3f65cSamw cv_wait(&smb_opipe_door_cv, &smb_opipe_door_mutex); 5933db3f65cSamw 5943db3f65cSamw door_ki_rele(smb_opipe_door_hd); 5953db3f65cSamw smb_opipe_door_hd = NULL; 5963db3f65cSamw } 5973db3f65cSamw 5983db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 5993db3f65cSamw } 6003db3f65cSamw 6013db3f65cSamw /* 6023db3f65cSamw * opipe door call interface. 6033db3f65cSamw * Door serialization and call reference accounting is handled here. 6043db3f65cSamw */ 6053db3f65cSamw static int 6063db3f65cSamw smb_opipe_door_call(smb_opipe_t *opipe) 6073db3f65cSamw { 6083db3f65cSamw int rc; 6093db3f65cSamw 6103db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 6113db3f65cSamw 6123db3f65cSamw if (smb_opipe_door_hd == NULL) { 6133db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 6143db3f65cSamw 6153db3f65cSamw if (smb_opipe_door_open(smb_opipe_door_id) != 0) 6163db3f65cSamw return (-1); 6173db3f65cSamw 6183db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 6193db3f65cSamw } 6203db3f65cSamw 6213db3f65cSamw ++smb_opipe_door_ncall; 6223db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 6233db3f65cSamw 6243db3f65cSamw rc = smb_opipe_door_upcall(opipe); 6253db3f65cSamw 6263db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 627*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((--smb_opipe_door_ncall) == 0) 6283db3f65cSamw cv_signal(&smb_opipe_door_cv); 6293db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 6303db3f65cSamw return (rc); 6313db3f65cSamw } 6323db3f65cSamw 6333db3f65cSamw /* 6343db3f65cSamw * Door upcall wrapper - handles data marshalling. 6353db3f65cSamw * This function should only be called by smb_opipe_door_call. 6363db3f65cSamw */ 6373db3f65cSamw static int 6383db3f65cSamw smb_opipe_door_upcall(smb_opipe_t *opipe) 6393db3f65cSamw { 6403db3f65cSamw door_arg_t da; 641*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_doorhdr_t hdr; 6423db3f65cSamw int i; 6433db3f65cSamw int rc; 6443db3f65cSamw 6453db3f65cSamw da.data_ptr = (char *)opipe->p_doorbuf; 6463db3f65cSamw da.data_size = SMB_OPIPE_DOOR_BUFSIZE; 6473db3f65cSamw da.desc_ptr = NULL; 6483db3f65cSamw da.desc_num = 0; 6493db3f65cSamw da.rbuf = (char *)opipe->p_doorbuf; 6503db3f65cSamw da.rsize = SMB_OPIPE_DOOR_BUFSIZE; 6513db3f65cSamw 6523db3f65cSamw for (i = 0; i < 3; ++i) { 653*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_server_is_stopping()) 654*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (-1); 655*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 6563db3f65cSamw if ((rc = door_ki_upcall_limited(smb_opipe_door_hd, &da, 6573db3f65cSamw NULL, SIZE_MAX, 0)) == 0) 6583db3f65cSamw break; 6593db3f65cSamw 6603db3f65cSamw if (rc != EAGAIN && rc != EINTR) 6613db3f65cSamw return (-1); 6623db3f65cSamw } 6633db3f65cSamw 664*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* Check for door_return(NULL, 0, NULL, 0) */ 665*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (rc != 0 || da.data_size == 0 || da.rsize == 0) 6663db3f65cSamw return (-1); 6673db3f65cSamw 668*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_doorhdr_decode(&hdr, (uint8_t *)da.data_ptr, da.rsize) == -1) 6693db3f65cSamw return (-1); 6703db3f65cSamw 671*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) || 672*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (hdr.dh_fid != opipe->p_hdr.dh_fid) || 673*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (hdr.dh_op != opipe->p_hdr.dh_op) || 674*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (hdr.dh_door_rc != 0) || 675*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)) { 6763db3f65cSamw return (-1); 6773db3f65cSamw } 6783db3f65cSamw 679*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_datalen = hdr.dh_datalen; 680*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_resid = hdr.dh_resid; 6813db3f65cSamw return (0); 6823db3f65cSamw } 683