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*148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 233db3f65cSamw */ 243db3f65cSamw 253db3f65cSamw /* 263db3f65cSamw * This module provides the interface to NDR RPC. 273db3f65cSamw */ 283db3f65cSamw 293db3f65cSamw #include <sys/stat.h> 303db3f65cSamw #include <sys/door.h> 313db3f65cSamw #include <sys/door_data.h> 323db3f65cSamw #include <sys/uio.h> 333db3f65cSamw #include <sys/ksynch.h> 34bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 353db3f65cSamw #include <smbsrv/smb_xdr.h> 363db3f65cSamw 373db3f65cSamw #define SMB_OPIPE_ISOPEN(OPIPE) \ 389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (((OPIPE)->p_hdr.dh_magic == SMB_OPIPE_HDR_MAGIC) && \ 399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ((OPIPE)->p_hdr.dh_fid)) 403db3f65cSamw 413db3f65cSamw extern volatile uint32_t smb_fids; 423db3f65cSamw 433db3f65cSamw static int smb_opipe_do_open(smb_request_t *, smb_opipe_t *); 449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static char *smb_opipe_lookup(const char *); 459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_opipe_sethdr(smb_opipe_t *, uint32_t, uint32_t); 469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_opipe_exec(smb_opipe_t *); 473db3f65cSamw static void smb_opipe_enter(smb_opipe_t *); 483db3f65cSamw static void smb_opipe_exit(smb_opipe_t *); 493db3f65cSamw 503db3f65cSamw static door_handle_t smb_opipe_door_hd = NULL; 513db3f65cSamw static int smb_opipe_door_id = -1; 523db3f65cSamw static uint64_t smb_opipe_door_ncall = 0; 533db3f65cSamw static kmutex_t smb_opipe_door_mutex; 543db3f65cSamw static kcondvar_t smb_opipe_door_cv; 553db3f65cSamw 563db3f65cSamw static int smb_opipe_door_call(smb_opipe_t *); 573db3f65cSamw static int smb_opipe_door_upcall(smb_opipe_t *); 583db3f65cSamw 599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_t * 609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_alloc(smb_server_t *sv) 619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_t *opipe; 639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe = kmem_cache_alloc(sv->si_cache_opipe, KM_SLEEP); 659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(opipe, sizeof (smb_opipe_t)); 679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL); 689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL); 699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_magic = SMB_OPIPE_MAGIC; 709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_server = sv; 719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_enter(&sv->sv_opipe_list, RW_WRITER); 739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_insert_tail(&sv->sv_opipe_list, opipe); 749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(&sv->sv_opipe_list); 759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (opipe); 779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_dealloc(smb_opipe_t *opipe) 819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_server_t *sv; 839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States sv = opipe->p_server; 869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_SERVER_VALID(sv); 879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_enter(&sv->sv_opipe_list, RW_WRITER); 899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_remove(&sv->sv_opipe_list, opipe); 909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(&sv->sv_opipe_list); 919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC; 939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_event_destroy(opipe->p_event); 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 979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States kmem_cache_free(sv->si_cache_opipe, opipe); 989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1003db3f65cSamw /* 1013db3f65cSamw * smb_opipe_open 1023db3f65cSamw * 1033db3f65cSamw * Open a well-known RPC named pipe. This routine should be called if 1043db3f65cSamw * a file open is requested on a share of type STYPE_IPC. 1053db3f65cSamw * If we recognize the pipe, we setup a new ofile. 1063db3f65cSamw * 1073db3f65cSamw * Returns 0 on success, Otherwise an NT status is returned to indicate 1083db3f65cSamw * an error. 1093db3f65cSamw */ 1103db3f65cSamw int 1113db3f65cSamw smb_opipe_open(smb_request_t *sr) 1123db3f65cSamw { 113*148c5f43SAlan Wright smb_arg_open_t *op = &sr->sr_open; 1143db3f65cSamw smb_ofile_t *of; 1153db3f65cSamw smb_opipe_t *opipe; 1169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_doorhdr_t hdr; 1173db3f65cSamw smb_error_t err; 1183db3f65cSamw char *pipe_name; 1193db3f65cSamw 120eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States if ((pipe_name = smb_opipe_lookup(op->fqi.fq_path.pn_path)) == NULL) 1213db3f65cSamw return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 1223db3f65cSamw 123c8ec8eeaSjose borrego op->create_options = 0; 124c8ec8eeaSjose borrego 125c8ec8eeaSjose borrego of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op, 1263db3f65cSamw SMB_FTYPE_MESG_PIPE, SMB_UNIQ_FID(), &err); 1278b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 1283db3f65cSamw if (of == NULL) 1293db3f65cSamw return (err.status); 1303db3f65cSamw 1318b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (!smb_tree_is_connected(sr->tid_tree)) { 1328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_ofile_close(of, 0); 1338b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_ofile_release(of); 1348b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 1358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 1368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 1373db3f65cSamw op->dsize = 0x01000; 1383db3f65cSamw op->dattr = FILE_ATTRIBUTE_NORMAL; 1393db3f65cSamw op->ftype = SMB_FTYPE_MESG_PIPE; 1403db3f65cSamw op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */ 1413db3f65cSamw op->devstate = SMB_PIPE_READMODE_MESSAGE 1423db3f65cSamw | SMB_PIPE_TYPE_MESSAGE 1433db3f65cSamw | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */ 1443db3f65cSamw op->fileid = of->f_fid; 1453db3f65cSamw 1463db3f65cSamw sr->smb_fid = of->f_fid; 1473db3f65cSamw sr->fid_ofile = of; 1483db3f65cSamw 1493db3f65cSamw opipe = of->f_pipe; 1503db3f65cSamw smb_opipe_enter(opipe); 1513db3f65cSamw 1529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_server = of->f_server; 1533db3f65cSamw opipe->p_name = pipe_name; 1543db3f65cSamw opipe->p_doorbuf = kmem_zalloc(SMB_OPIPE_DOOR_BUFSIZE, KM_SLEEP); 1553db3f65cSamw 1563db3f65cSamw /* 1573db3f65cSamw * p_data points to the offset within p_doorbuf at which 1583db3f65cSamw * data will be written or read. 1593db3f65cSamw */ 1609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_data = opipe->p_doorbuf + xdr_sizeof(smb_doorhdr_xdr, &hdr); 1613db3f65cSamw 1623db3f65cSamw if (smb_opipe_do_open(sr, opipe) != 0) { 1633db3f65cSamw /* 1643db3f65cSamw * On error, reset the header to clear the fid, 1653db3f65cSamw * which avoids confusion when smb_opipe_close() is 1663db3f65cSamw * called by smb_ofile_close(). 1673db3f65cSamw */ 1689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 1693db3f65cSamw kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 1703db3f65cSamw smb_opipe_exit(opipe); 171c8ec8eeaSjose borrego smb_ofile_close(of, 0); 1723db3f65cSamw return (NT_STATUS_NO_MEMORY); 1733db3f65cSamw } 1743db3f65cSamw smb_opipe_exit(opipe); 1753db3f65cSamw return (NT_STATUS_SUCCESS); 1763db3f65cSamw } 1773db3f65cSamw 1783db3f65cSamw /* 1793db3f65cSamw * smb_opipe_lookup 1803db3f65cSamw * 1813db3f65cSamw * Lookup a path to see if it's a well-known RPC named pipe that we support. 1823db3f65cSamw * The full pipe path will be in the form \\PIPE\\SERVICE. The first part 1833db3f65cSamw * can be assumed, so all we need here are the service names. 1843db3f65cSamw * 1851fcced4cSJordan Brown * Returns a pointer to the pipe name (without any leading \'s) on success. 1863db3f65cSamw * Otherwise returns a null pointer. 1873db3f65cSamw */ 1883db3f65cSamw static char * 1893db3f65cSamw smb_opipe_lookup(const char *path) 1903db3f65cSamw { 1913db3f65cSamw static char *named_pipes[] = { 1921fcced4cSJordan Brown "lsass", 1933db3f65cSamw "LSARPC", 1943db3f65cSamw "NETLOGON", 1953db3f65cSamw "SAMR", 1963db3f65cSamw "SPOOLSS", 1973db3f65cSamw "SRVSVC", 1983db3f65cSamw "SVCCTL", 1993db3f65cSamw "WINREG", 2003db3f65cSamw "WKSSVC", 2019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States "EVENTLOG", 2029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States "NETDFS" 2033db3f65cSamw }; 2043db3f65cSamw 2053db3f65cSamw const char *name; 2063db3f65cSamw int i; 2073db3f65cSamw 2083db3f65cSamw if (path == NULL) 2093db3f65cSamw return (NULL); 2103db3f65cSamw 2113db3f65cSamw name = path; 2123db3f65cSamw name += strspn(name, "\\"); 213bbf6f00cSJordan Brown if (smb_strcasecmp(name, "PIPE", 4) == 0) { 2143db3f65cSamw path += 4; 2153db3f65cSamw name += strspn(name, "\\"); 2163db3f65cSamw } 2173db3f65cSamw 2183db3f65cSamw for (i = 0; i < sizeof (named_pipes) / sizeof (named_pipes[0]); ++i) { 219bbf6f00cSJordan Brown if (smb_strcasecmp(name, named_pipes[i], 0) == 0) 2203db3f65cSamw return (named_pipes[i]); 2213db3f65cSamw } 2223db3f65cSamw 2233db3f65cSamw return (NULL); 2243db3f65cSamw } 2253db3f65cSamw 2263db3f65cSamw /* 2273db3f65cSamw * Initialize the opipe header and context, and make the door call. 2283db3f65cSamw */ 2293db3f65cSamw static int 2303db3f65cSamw smb_opipe_do_open(smb_request_t *sr, smb_opipe_t *opipe) 2313db3f65cSamw { 2321fcced4cSJordan Brown smb_netuserinfo_t *userinfo = &opipe->p_user; 2333db3f65cSamw smb_user_t *user = sr->uid_user; 2343db3f65cSamw uint8_t *buf = opipe->p_doorbuf; 2353db3f65cSamw uint32_t buflen = SMB_OPIPE_DOOR_BUFSIZE; 2363db3f65cSamw uint32_t len; 2373db3f65cSamw 2389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((opipe->p_event = smb_event_create()) == NULL) 2399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (-1); 2409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2411fcced4cSJordan Brown smb_user_netinfo_init(user, userinfo); 2421fcced4cSJordan Brown len = xdr_sizeof(smb_netuserinfo_xdr, userinfo); 2433db3f65cSamw 2449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 2459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_magic = SMB_OPIPE_HDR_MAGIC; 2469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_flags = SMB_DF_SYSSPACE; 2479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_fid = smb_event_txid(opipe->p_event); 2483db3f65cSamw 2499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_opipe_sethdr(opipe, SMB_OPIPE_OPEN, len) == -1) 2503db3f65cSamw return (-1); 2513db3f65cSamw 2529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 2533db3f65cSamw buf += len; 2543db3f65cSamw buflen -= len; 2553db3f65cSamw 2561fcced4cSJordan Brown if (smb_netuserinfo_encode(userinfo, buf, buflen, NULL) == -1) 2573db3f65cSamw return (-1); 2583db3f65cSamw 2593db3f65cSamw return (smb_opipe_door_call(opipe)); 2603db3f65cSamw } 2613db3f65cSamw 2623db3f65cSamw /* 2633db3f65cSamw * smb_opipe_close 2643db3f65cSamw * 2653db3f65cSamw * Called whenever an IPC file/pipe is closed. 2663db3f65cSamw */ 2673db3f65cSamw void 2683db3f65cSamw smb_opipe_close(smb_ofile_t *of) 2693db3f65cSamw { 2703db3f65cSamw smb_opipe_t *opipe; 2713db3f65cSamw 2723db3f65cSamw ASSERT(of); 2733db3f65cSamw ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE); 2743db3f65cSamw 2753db3f65cSamw opipe = of->f_pipe; 2769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 2779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_server_cancel_event(opipe->p_hdr.dh_fid); 2793db3f65cSamw smb_opipe_enter(opipe); 2803db3f65cSamw 2813db3f65cSamw if (SMB_OPIPE_ISOPEN(opipe)) { 2829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_opipe_sethdr(opipe, SMB_OPIPE_CLOSE, 0); 2833db3f65cSamw (void) smb_opipe_door_call(opipe); 2849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 2853db3f65cSamw kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 2863db3f65cSamw } 2873db3f65cSamw 2881fcced4cSJordan Brown smb_user_netinfo_fini(&opipe->p_user); 2893db3f65cSamw smb_opipe_exit(opipe); 2903db3f65cSamw } 2913db3f65cSamw 2923db3f65cSamw static int 2939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_sethdr(smb_opipe_t *opipe, uint32_t cmd, uint32_t datalen) 2943db3f65cSamw { 2959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_op = cmd; 2969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_txid = opipe->p_hdr.dh_fid; 2979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_datalen = datalen; 2989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_resid = 0; 2999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_door_rc = EINVAL; 3003db3f65cSamw 3019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (smb_doorhdr_encode(&opipe->p_hdr, opipe->p_doorbuf, 3023db3f65cSamw SMB_OPIPE_DOOR_BUFSIZE)); 3033db3f65cSamw } 3043db3f65cSamw 3053db3f65cSamw /* 3063db3f65cSamw * smb_opipe_transact 3073db3f65cSamw * 3083db3f65cSamw * This is the entry point for RPC bind and request transactions. 3093db3f65cSamw * The fid is an arbitrary id used to associate RPC requests with a 3103db3f65cSamw * particular binding handle. 3113db3f65cSamw * 3123db3f65cSamw * If the data to be returned is larger than the client expects, we 3133db3f65cSamw * return as much as the client can handle and report a buffer overflow 3143db3f65cSamw * warning, which informs the client that we have more data to return. 3153db3f65cSamw * The residual data remains in the pipe until the client claims it or 3163db3f65cSamw * closes the pipe. 3173db3f65cSamw */ 3183db3f65cSamw smb_sdrc_t 3193db3f65cSamw smb_opipe_transact(smb_request_t *sr, struct uio *uio) 3203db3f65cSamw { 3213db3f65cSamw smb_xa_t *xa; 3223db3f65cSamw smb_opipe_t *opipe; 3233db3f65cSamw struct mbuf *mhead; 3243db3f65cSamw int mdrcnt; 3253db3f65cSamw int nbytes; 3263db3f65cSamw int rc; 3273db3f65cSamw 3283db3f65cSamw if ((rc = smb_opipe_write(sr, uio)) != 0) { 3293db3f65cSamw if (rc == EBADF) 3303db3f65cSamw smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 3313db3f65cSamw ERRDOS, ERROR_INVALID_HANDLE); 3323db3f65cSamw else 3333db3f65cSamw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 3343db3f65cSamw ERRDOS, ERROR_INTERNAL_ERROR); 3353db3f65cSamw return (SDRC_ERROR); 3363db3f65cSamw } 3373db3f65cSamw 3389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe = sr->fid_ofile->f_pipe; 3399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 3409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((rc = smb_opipe_exec(opipe)) != 0) { 3419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 3429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ERRDOS, ERROR_INTERNAL_ERROR); 3439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (SDRC_ERROR); 3449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 3459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 3463db3f65cSamw xa = sr->r_xa; 3473db3f65cSamw mdrcnt = xa->smb_mdrcnt; 3483db3f65cSamw smb_opipe_enter(opipe); 3493db3f65cSamw 3509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, mdrcnt) == -1) { 3513db3f65cSamw smb_opipe_exit(opipe); 3523db3f65cSamw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 3533db3f65cSamw ERRDOS, ERROR_INTERNAL_ERROR); 3543db3f65cSamw return (SDRC_ERROR); 3553db3f65cSamw } 3563db3f65cSamw 3573db3f65cSamw rc = smb_opipe_door_call(opipe); 3589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States nbytes = opipe->p_hdr.dh_datalen; 3593db3f65cSamw 3603db3f65cSamw if (rc != 0) { 3613db3f65cSamw smb_opipe_exit(opipe); 3623db3f65cSamw smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 3633db3f65cSamw ERRDOS, ERROR_INTERNAL_ERROR); 3643db3f65cSamw return (SDRC_ERROR); 3653db3f65cSamw } 3663db3f65cSamw 3673db3f65cSamw if (nbytes) { 3683db3f65cSamw mhead = smb_mbuf_get(opipe->p_data, nbytes); 3693db3f65cSamw xa->rep_data_mb.max_bytes = nbytes; 3703db3f65cSamw MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead); 3713db3f65cSamw } 3723db3f65cSamw 3739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (opipe->p_hdr.dh_resid) { 3743db3f65cSamw /* 3753db3f65cSamw * The pipe contains more data than mdrcnt, warn the 3763db3f65cSamw * client that there is more data in the pipe. 3773db3f65cSamw * Typically, the client will call SmbReadX, which 3783db3f65cSamw * will call smb_opipe_read, to get the data. 3793db3f65cSamw */ 3803db3f65cSamw smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW, 3813db3f65cSamw ERRDOS, ERROR_MORE_DATA); 3823db3f65cSamw } 3833db3f65cSamw 3843db3f65cSamw smb_opipe_exit(opipe); 3853db3f65cSamw return (SDRC_SUCCESS); 3863db3f65cSamw } 3873db3f65cSamw 3883db3f65cSamw /* 3893db3f65cSamw * smb_opipe_write 3903db3f65cSamw * 3913db3f65cSamw * Write RPC request data to the pipe. The client should call smb_opipe_read 3923db3f65cSamw * to complete the exchange and obtain the RPC response. 3933db3f65cSamw * 3943db3f65cSamw * Returns 0 on success or an errno on failure. 3953db3f65cSamw */ 3963db3f65cSamw int 3973db3f65cSamw smb_opipe_write(smb_request_t *sr, struct uio *uio) 3983db3f65cSamw { 3993db3f65cSamw smb_opipe_t *opipe; 4003db3f65cSamw uint32_t buflen; 4013db3f65cSamw uint32_t len; 4023db3f65cSamw int rc; 4033db3f65cSamw 4043db3f65cSamw ASSERT(sr->fid_ofile); 4053db3f65cSamw ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 4063db3f65cSamw 4073db3f65cSamw opipe = sr->fid_ofile->f_pipe; 4089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 4093db3f65cSamw smb_opipe_enter(opipe); 4103db3f65cSamw 4113db3f65cSamw if (!SMB_OPIPE_ISOPEN(opipe)) { 4123db3f65cSamw smb_opipe_exit(opipe); 4133db3f65cSamw return (EBADF); 4143db3f65cSamw } 4153db3f65cSamw 4169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_opipe_sethdr(opipe, SMB_OPIPE_WRITE, uio->uio_resid); 4179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 4183db3f65cSamw if (rc == -1 || len == 0) { 4193db3f65cSamw smb_opipe_exit(opipe); 4203db3f65cSamw return (ENOMEM); 4213db3f65cSamw } 4223db3f65cSamw 4233db3f65cSamw buflen = SMB_OPIPE_DOOR_BUFSIZE - len; 4243db3f65cSamw (void) uiomove((caddr_t)opipe->p_data, buflen, UIO_WRITE, uio); 4253db3f65cSamw 4263db3f65cSamw rc = smb_opipe_door_call(opipe); 4273db3f65cSamw 4283db3f65cSamw smb_opipe_exit(opipe); 4293db3f65cSamw return ((rc == 0) ? 0 : EIO); 4303db3f65cSamw } 4313db3f65cSamw 4323db3f65cSamw /* 4333db3f65cSamw * smb_opipe_read 4343db3f65cSamw * 4353db3f65cSamw * This interface may be called because smb_opipe_transact could not return 4363db3f65cSamw * all of the data in the original transaction or to form the second half 4373db3f65cSamw * of a transaction set up using smb_opipe_write. Either way, we just need 4383db3f65cSamw * to read data from the pipe and return it. 4393db3f65cSamw * 4403db3f65cSamw * The response data is encoded into raw_data as required by the smb_read 4413db3f65cSamw * functions. The uio_resid value indicates the number of bytes read. 4423db3f65cSamw */ 4433db3f65cSamw int 4443db3f65cSamw smb_opipe_read(smb_request_t *sr, struct uio *uio) 4453db3f65cSamw { 4463db3f65cSamw smb_opipe_t *opipe; 4473db3f65cSamw struct mbuf *mhead; 4483db3f65cSamw uint32_t nbytes; 4493db3f65cSamw int rc; 4503db3f65cSamw 4513db3f65cSamw ASSERT(sr->fid_ofile); 4523db3f65cSamw ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 4533db3f65cSamw 4543db3f65cSamw opipe = sr->fid_ofile->f_pipe; 4559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_OPIPE_VALID(opipe); 4569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 4579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((rc = smb_opipe_exec(opipe)) != 0) 4589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (EIO); 4599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 4603db3f65cSamw smb_opipe_enter(opipe); 4613db3f65cSamw 4623db3f65cSamw if (!SMB_OPIPE_ISOPEN(opipe)) { 4633db3f65cSamw smb_opipe_exit(opipe); 4643db3f65cSamw return (EBADF); 4653db3f65cSamw } 4663db3f65cSamw 4679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, uio->uio_resid) == -1) { 4683db3f65cSamw smb_opipe_exit(opipe); 4693db3f65cSamw return (ENOMEM); 4703db3f65cSamw } 4713db3f65cSamw 4723db3f65cSamw rc = smb_opipe_door_call(opipe); 4739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States nbytes = opipe->p_hdr.dh_datalen; 4743db3f65cSamw 4753db3f65cSamw if (rc != 0 || nbytes > uio->uio_resid) { 4763db3f65cSamw smb_opipe_exit(opipe); 4773db3f65cSamw return (EIO); 4783db3f65cSamw } 4793db3f65cSamw 4803db3f65cSamw if (nbytes) { 4813db3f65cSamw mhead = smb_mbuf_get(opipe->p_data, nbytes); 4823db3f65cSamw MBC_SETUP(&sr->raw_data, nbytes); 4833db3f65cSamw MBC_ATTACH_MBUF(&sr->raw_data, mhead); 4843db3f65cSamw uio->uio_resid -= nbytes; 4853db3f65cSamw } 4863db3f65cSamw 4873db3f65cSamw smb_opipe_exit(opipe); 4883db3f65cSamw return (rc); 4893db3f65cSamw } 4903db3f65cSamw 4919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int 4929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_exec(smb_opipe_t *opipe) 4939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 4949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uint32_t len; 4959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int rc; 4969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 4979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_enter(opipe); 4989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 4999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_opipe_sethdr(opipe, SMB_OPIPE_EXEC, 0); 5009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 5019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (rc == -1 || len == 0) { 5029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_exit(opipe); 5039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (ENOMEM); 5049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 5059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 5069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((rc = smb_opipe_door_call(opipe)) == 0) 5079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_event_wait(opipe->p_event); 5089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 5099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_opipe_exit(opipe); 5109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (rc); 5119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 5129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 5133db3f65cSamw /* 5143db3f65cSamw * Named pipe I/O is serialized per fid to ensure that each request 5153db3f65cSamw * has exclusive opipe access for the duration of the request. 5163db3f65cSamw */ 5173db3f65cSamw static void 5183db3f65cSamw smb_opipe_enter(smb_opipe_t *opipe) 5193db3f65cSamw { 5203db3f65cSamw mutex_enter(&opipe->p_mutex); 5213db3f65cSamw 5223db3f65cSamw while (opipe->p_busy) 5233db3f65cSamw cv_wait(&opipe->p_cv, &opipe->p_mutex); 5243db3f65cSamw 5253db3f65cSamw opipe->p_busy = 1; 5263db3f65cSamw mutex_exit(&opipe->p_mutex); 5273db3f65cSamw } 5283db3f65cSamw 5299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* 5309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Exit busy state. If we have exec'd an RPC, we may have 5319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * to wait for notification that processing has completed. 5329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */ 5333db3f65cSamw static void 5343db3f65cSamw smb_opipe_exit(smb_opipe_t *opipe) 5353db3f65cSamw { 5363db3f65cSamw mutex_enter(&opipe->p_mutex); 5373db3f65cSamw opipe->p_busy = 0; 5383db3f65cSamw cv_signal(&opipe->p_cv); 5393db3f65cSamw mutex_exit(&opipe->p_mutex); 5403db3f65cSamw } 5413db3f65cSamw 5423db3f65cSamw /* 5433db3f65cSamw * opipe door client (to user space door server). 5443db3f65cSamw */ 5453db3f65cSamw void 5463db3f65cSamw smb_opipe_door_init(void) 5473db3f65cSamw { 5483db3f65cSamw mutex_init(&smb_opipe_door_mutex, NULL, MUTEX_DEFAULT, NULL); 5493db3f65cSamw cv_init(&smb_opipe_door_cv, NULL, CV_DEFAULT, NULL); 5503db3f65cSamw } 5513db3f65cSamw 5523db3f65cSamw void 5533db3f65cSamw smb_opipe_door_fini(void) 5543db3f65cSamw { 5553db3f65cSamw smb_opipe_door_close(); 5563db3f65cSamw cv_destroy(&smb_opipe_door_cv); 5573db3f65cSamw mutex_destroy(&smb_opipe_door_mutex); 5583db3f65cSamw } 5593db3f65cSamw 5603db3f65cSamw /* 5613db3f65cSamw * Open the (user space) door. If the door is already open, 5623db3f65cSamw * close it first because the door-id has probably changed. 5633db3f65cSamw */ 5643db3f65cSamw int 5653db3f65cSamw smb_opipe_door_open(int door_id) 5663db3f65cSamw { 5673db3f65cSamw smb_opipe_door_close(); 5683db3f65cSamw 5693db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 5703db3f65cSamw smb_opipe_door_ncall = 0; 5713db3f65cSamw 5723db3f65cSamw if (smb_opipe_door_hd == NULL) { 5733db3f65cSamw smb_opipe_door_id = door_id; 5743db3f65cSamw smb_opipe_door_hd = door_ki_lookup(door_id); 5753db3f65cSamw } 5763db3f65cSamw 5773db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 5783db3f65cSamw return ((smb_opipe_door_hd == NULL) ? -1 : 0); 5793db3f65cSamw } 5803db3f65cSamw 5813db3f65cSamw /* 5823db3f65cSamw * Close the (user space) door. 5833db3f65cSamw */ 5843db3f65cSamw void 5853db3f65cSamw smb_opipe_door_close(void) 5863db3f65cSamw { 5873db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 5883db3f65cSamw 5893db3f65cSamw if (smb_opipe_door_hd != NULL) { 5903db3f65cSamw while (smb_opipe_door_ncall > 0) 5913db3f65cSamw cv_wait(&smb_opipe_door_cv, &smb_opipe_door_mutex); 5923db3f65cSamw 5933db3f65cSamw door_ki_rele(smb_opipe_door_hd); 5943db3f65cSamw smb_opipe_door_hd = NULL; 5953db3f65cSamw } 5963db3f65cSamw 5973db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 5983db3f65cSamw } 5993db3f65cSamw 6003db3f65cSamw /* 6013db3f65cSamw * opipe door call interface. 6023db3f65cSamw * Door serialization and call reference accounting is handled here. 6033db3f65cSamw */ 6043db3f65cSamw static int 6053db3f65cSamw smb_opipe_door_call(smb_opipe_t *opipe) 6063db3f65cSamw { 6073db3f65cSamw int rc; 6083db3f65cSamw 6093db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 6103db3f65cSamw 6113db3f65cSamw if (smb_opipe_door_hd == NULL) { 6123db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 6133db3f65cSamw 6143db3f65cSamw if (smb_opipe_door_open(smb_opipe_door_id) != 0) 6153db3f65cSamw return (-1); 6163db3f65cSamw 6173db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 6183db3f65cSamw } 6193db3f65cSamw 6203db3f65cSamw ++smb_opipe_door_ncall; 6213db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 6223db3f65cSamw 6233db3f65cSamw rc = smb_opipe_door_upcall(opipe); 6243db3f65cSamw 6253db3f65cSamw mutex_enter(&smb_opipe_door_mutex); 6269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((--smb_opipe_door_ncall) == 0) 6279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States cv_signal(&smb_opipe_door_cv); 6283db3f65cSamw mutex_exit(&smb_opipe_door_mutex); 6293db3f65cSamw return (rc); 6303db3f65cSamw } 6313db3f65cSamw 6323db3f65cSamw /* 6333db3f65cSamw * Door upcall wrapper - handles data marshalling. 6343db3f65cSamw * This function should only be called by smb_opipe_door_call. 6353db3f65cSamw */ 6363db3f65cSamw static int 6373db3f65cSamw smb_opipe_door_upcall(smb_opipe_t *opipe) 6383db3f65cSamw { 6393db3f65cSamw door_arg_t da; 6409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_doorhdr_t hdr; 6413db3f65cSamw int i; 6423db3f65cSamw int rc; 6433db3f65cSamw 6443db3f65cSamw da.data_ptr = (char *)opipe->p_doorbuf; 6453db3f65cSamw da.data_size = SMB_OPIPE_DOOR_BUFSIZE; 6463db3f65cSamw da.desc_ptr = NULL; 6473db3f65cSamw da.desc_num = 0; 6483db3f65cSamw da.rbuf = (char *)opipe->p_doorbuf; 6493db3f65cSamw da.rsize = SMB_OPIPE_DOOR_BUFSIZE; 6503db3f65cSamw 6513db3f65cSamw for (i = 0; i < 3; ++i) { 6529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_server_is_stopping()) 6539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (-1); 6549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 6553db3f65cSamw if ((rc = door_ki_upcall_limited(smb_opipe_door_hd, &da, 6563db3f65cSamw NULL, SIZE_MAX, 0)) == 0) 6573db3f65cSamw break; 6583db3f65cSamw 6593db3f65cSamw if (rc != EAGAIN && rc != EINTR) 6603db3f65cSamw return (-1); 6613db3f65cSamw } 6623db3f65cSamw 6639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* Check for door_return(NULL, 0, NULL, 0) */ 6649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (rc != 0 || da.data_size == 0 || da.rsize == 0) 6653db3f65cSamw return (-1); 6663db3f65cSamw 6679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_doorhdr_decode(&hdr, (uint8_t *)da.data_ptr, da.rsize) == -1) 6683db3f65cSamw return (-1); 6693db3f65cSamw 6709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) || 6719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (hdr.dh_fid != opipe->p_hdr.dh_fid) || 6729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (hdr.dh_op != opipe->p_hdr.dh_op) || 6739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (hdr.dh_door_rc != 0) || 6749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)) { 6753db3f65cSamw return (-1); 6763db3f65cSamw } 6773db3f65cSamw 6789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_datalen = hdr.dh_datalen; 6799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States opipe->p_hdr.dh_resid = hdr.dh_resid; 6803db3f65cSamw return (0); 6813db3f65cSamw } 682