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