1*b819cea2SGordon Ross /* 2*b819cea2SGordon Ross * CDDL HEADER START 3*b819cea2SGordon Ross * 4*b819cea2SGordon Ross * The contents of this file are subject to the terms of the 5*b819cea2SGordon Ross * Common Development and Distribution License (the "License"). 6*b819cea2SGordon Ross * You may not use this file except in compliance with the License. 7*b819cea2SGordon Ross * 8*b819cea2SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*b819cea2SGordon Ross * or http://www.opensolaris.org/os/licensing. 10*b819cea2SGordon Ross * See the License for the specific language governing permissions 11*b819cea2SGordon Ross * and limitations under the License. 12*b819cea2SGordon Ross * 13*b819cea2SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14*b819cea2SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*b819cea2SGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16*b819cea2SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17*b819cea2SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18*b819cea2SGordon Ross * 19*b819cea2SGordon Ross * CDDL HEADER END 20*b819cea2SGordon Ross */ 21*b819cea2SGordon Ross /* 22*b819cea2SGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23*b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 24*b819cea2SGordon Ross */ 25*b819cea2SGordon Ross 26*b819cea2SGordon Ross #include <sys/list.h> 27*b819cea2SGordon Ross #include <assert.h> 28*b819cea2SGordon Ross #include <alloca.h> 29*b819cea2SGordon Ross #include <door.h> 30*b819cea2SGordon Ross #include <errno.h> 31*b819cea2SGordon Ross #include <syslog.h> 32*b819cea2SGordon Ross #include <unistd.h> 33*b819cea2SGordon Ross #include <stdio.h> 34*b819cea2SGordon Ross #include <synch.h> 35*b819cea2SGordon Ross #include <string.h> 36*b819cea2SGordon Ross #include <stdlib.h> 37*b819cea2SGordon Ross #include <sys/stat.h> 38*b819cea2SGordon Ross #include <fcntl.h> 39*b819cea2SGordon Ross #include <pthread.h> 40*b819cea2SGordon Ross #include <strings.h> 41*b819cea2SGordon Ross #include <umem.h> 42*b819cea2SGordon Ross 43*b819cea2SGordon Ross #include <smbsrv/smb_door.h> 44*b819cea2SGordon Ross #include <smbsrv/smb_xdr.h> 45*b819cea2SGordon Ross #include <smbsrv/smb_token.h> 46*b819cea2SGordon Ross #include <smbsrv/libmlsvc.h> 47*b819cea2SGordon Ross #include <smbsrv/libsmbns.h> 48*b819cea2SGordon Ross #include "smbd.h" 49*b819cea2SGordon Ross 50*b819cea2SGordon Ross 51*b819cea2SGordon Ross /* 52*b819cea2SGordon Ross * Special version of smb_door_dispatch() for the 53*b819cea2SGordon Ross * "fake" smbsrv (running in user space). 54*b819cea2SGordon Ross * 55*b819cea2SGordon Ross * This is called via function pointer from 56*b819cea2SGordon Ross * smbsrv: smb_kdoor_upcall() 57*b819cea2SGordon Ross * 58*b819cea2SGordon Ross * The args and response go RPC encoded, just so we can 59*b819cea2SGordon Ross * borrow some of the common doorsvc code, even though 60*b819cea2SGordon Ross * there's no need for RPC encoding in this scenario. 61*b819cea2SGordon Ross */ 62*b819cea2SGordon Ross int 63*b819cea2SGordon Ross fksmbd_door_dispatch(smb_doorarg_t *da) 64*b819cea2SGordon Ross { 65*b819cea2SGordon Ross 66*b819cea2SGordon Ross smbd_arg_t dop_arg; 67*b819cea2SGordon Ross smb_doorhdr_t *hdr; 68*b819cea2SGordon Ross char *rbuf = NULL; 69*b819cea2SGordon Ross char *argp = da->da_arg.data_ptr; 70*b819cea2SGordon Ross size_t arg_size = da->da_arg.data_size; 71*b819cea2SGordon Ross size_t hdr_size, rsize; 72*b819cea2SGordon Ross 73*b819cea2SGordon Ross /* 74*b819cea2SGordon Ross * Decode 75*b819cea2SGordon Ross * 76*b819cea2SGordon Ross * da->da_arg.data_ptr = (arg data, xdr encoded) 77*b819cea2SGordon Ross * da->da_arg.data_size = (arg data len) 78*b819cea2SGordon Ross */ 79*b819cea2SGordon Ross 80*b819cea2SGordon Ross bzero(&dop_arg, sizeof (smbd_arg_t)); 81*b819cea2SGordon Ross hdr = &dop_arg.hdr; 82*b819cea2SGordon Ross hdr_size = xdr_sizeof(smb_doorhdr_xdr, hdr); 83*b819cea2SGordon Ross 84*b819cea2SGordon Ross if ((argp == NULL) || (arg_size < hdr_size)) { 85*b819cea2SGordon Ross syslog(LOG_DEBUG, "fksmbd_door_dispatch: bad args"); 86*b819cea2SGordon Ross return (-1); 87*b819cea2SGordon Ross } 88*b819cea2SGordon Ross 89*b819cea2SGordon Ross if (smb_doorhdr_decode(hdr, (uint8_t *)argp, hdr_size) == -1) { 90*b819cea2SGordon Ross syslog(LOG_DEBUG, "smbd_door_dispatch: header decode failed"); 91*b819cea2SGordon Ross return (-1); 92*b819cea2SGordon Ross } 93*b819cea2SGordon Ross 94*b819cea2SGordon Ross if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) || 95*b819cea2SGordon Ross (hdr->dh_flags != SMB_DF_FAKE_KERNEL)) { 96*b819cea2SGordon Ross syslog(LOG_DEBUG, "fksmbd_door_dispatch: invalid header"); 97*b819cea2SGordon Ross return (-1); 98*b819cea2SGordon Ross } 99*b819cea2SGordon Ross 100*b819cea2SGordon Ross dop_arg.opname = smb_doorhdr_opname(hdr->dh_op); 101*b819cea2SGordon Ross dop_arg.data = argp + hdr_size; 102*b819cea2SGordon Ross dop_arg.datalen = hdr->dh_datalen; 103*b819cea2SGordon Ross 104*b819cea2SGordon Ross if (hdr->dh_op == SMB_DR_ASYNC_RESPONSE) { 105*b819cea2SGordon Ross /* 106*b819cea2SGordon Ross * ASYNC_RESPONSE is not used here. 107*b819cea2SGordon Ross */ 108*b819cea2SGordon Ross syslog(LOG_DEBUG, "fksmbd_door_dispatch: ASYNC?"); 109*b819cea2SGordon Ross return (-1); 110*b819cea2SGordon Ross } 111*b819cea2SGordon Ross 112*b819cea2SGordon Ross /* 113*b819cea2SGordon Ross * Dispatch 114*b819cea2SGordon Ross * 115*b819cea2SGordon Ross * Call the common smbd_doorsvc.c code. 116*b819cea2SGordon Ross */ 117*b819cea2SGordon Ross (void) smbd_door_dispatch_op(&dop_arg); 118*b819cea2SGordon Ross 119*b819cea2SGordon Ross /* 120*b819cea2SGordon Ross * Encode 121*b819cea2SGordon Ross * 122*b819cea2SGordon Ross * da->da_arg.rbuf = (return data buf) 123*b819cea2SGordon Ross * da->da_arg.rsize = (return data size) 124*b819cea2SGordon Ross * 125*b819cea2SGordon Ross * Note that the return data buffer initially 126*b819cea2SGordon Ross * points to the same buffer as the args. 127*b819cea2SGordon Ross * If that's not large enough, umem_alloc. 128*b819cea2SGordon Ross */ 129*b819cea2SGordon Ross 130*b819cea2SGordon Ross rsize = dop_arg.rsize + hdr_size; 131*b819cea2SGordon Ross rbuf = umem_alloc(rsize, UMEM_DEFAULT); 132*b819cea2SGordon Ross if (rbuf == NULL) { 133*b819cea2SGordon Ross syslog(LOG_DEBUG, "fksmbd_door_dispatch[%s]: alloc %m", 134*b819cea2SGordon Ross dop_arg.opname); 135*b819cea2SGordon Ross return (-1); 136*b819cea2SGordon Ross } 137*b819cea2SGordon Ross 138*b819cea2SGordon Ross /* Copy caller's return data after the header. */ 139*b819cea2SGordon Ross if (dop_arg.rbuf != NULL) { 140*b819cea2SGordon Ross (void) memcpy(rbuf + hdr_size, dop_arg.rbuf, dop_arg.rsize); 141*b819cea2SGordon Ross free(dop_arg.rbuf); 142*b819cea2SGordon Ross } 143*b819cea2SGordon Ross 144*b819cea2SGordon Ross hdr->dh_datalen = dop_arg.rsize; 145*b819cea2SGordon Ross (void) smb_doorhdr_encode(hdr, (uint8_t *)rbuf, hdr_size); 146*b819cea2SGordon Ross 147*b819cea2SGordon Ross /* Let's update da->da_hdr too. */ 148*b819cea2SGordon Ross da->da_hdr = *hdr; 149*b819cea2SGordon Ross 150*b819cea2SGordon Ross /* 151*b819cea2SGordon Ross * Was door_return() 152*b819cea2SGordon Ross * NB: The "fake kernel" smbsrv code will umem_free rbuf. 153*b819cea2SGordon Ross */ 154*b819cea2SGordon Ross da->da_arg.rbuf = rbuf; 155*b819cea2SGordon Ross da->da_arg.rsize = rsize; 156*b819cea2SGordon Ross 157*b819cea2SGordon Ross return (0); 158*b819cea2SGordon Ross } 159