1*3ad684d6Sjb150015 /* 2*3ad684d6Sjb150015 * CDDL HEADER START 3*3ad684d6Sjb150015 * 4*3ad684d6Sjb150015 * The contents of this file are subject to the terms of the 5*3ad684d6Sjb150015 * Common Development and Distribution License (the "License"). 6*3ad684d6Sjb150015 * You may not use this file except in compliance with the License. 7*3ad684d6Sjb150015 * 8*3ad684d6Sjb150015 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3ad684d6Sjb150015 * or http://www.opensolaris.org/os/licensing. 10*3ad684d6Sjb150015 * See the License for the specific language governing permissions 11*3ad684d6Sjb150015 * and limitations under the License. 12*3ad684d6Sjb150015 * 13*3ad684d6Sjb150015 * When distributing Covered Code, include this CDDL HEADER in each 14*3ad684d6Sjb150015 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3ad684d6Sjb150015 * If applicable, add the following below this CDDL HEADER, with the 16*3ad684d6Sjb150015 * fields enclosed by brackets "[]" replaced with your own identifying 17*3ad684d6Sjb150015 * information: Portions Copyright [yyyy] [name of copyright owner] 18*3ad684d6Sjb150015 * 19*3ad684d6Sjb150015 * CDDL HEADER END 20*3ad684d6Sjb150015 */ 21*3ad684d6Sjb150015 /* 22*3ad684d6Sjb150015 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*3ad684d6Sjb150015 * Use is subject to license terms. 24*3ad684d6Sjb150015 */ 25*3ad684d6Sjb150015 26*3ad684d6Sjb150015 #pragma ident "%Z%%M% %I% %E% SMI" 27*3ad684d6Sjb150015 28*3ad684d6Sjb150015 /* 29*3ad684d6Sjb150015 * Kernel door client for LanMan share management. 30*3ad684d6Sjb150015 */ 31*3ad684d6Sjb150015 32*3ad684d6Sjb150015 #include <sys/ddi.h> 33*3ad684d6Sjb150015 #include <sys/sunddi.h> 34*3ad684d6Sjb150015 #include <sys/cmn_err.h> 35*3ad684d6Sjb150015 #include <sys/door.h> 36*3ad684d6Sjb150015 #include <smbsrv/lmshare.h> 37*3ad684d6Sjb150015 #include <smbsrv/lmerr.h> 38*3ad684d6Sjb150015 #include <smbsrv/smb_common_door.h> 39*3ad684d6Sjb150015 #include <smbsrv/lmshare_door.h> 40*3ad684d6Sjb150015 #include <smbsrv/smbinfo.h> 41*3ad684d6Sjb150015 42*3ad684d6Sjb150015 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *); 43*3ad684d6Sjb150015 44*3ad684d6Sjb150015 /* 45*3ad684d6Sjb150015 * smb_kshare_init 46*3ad684d6Sjb150015 * 47*3ad684d6Sjb150015 * This function is not MultiThread safe. The caller has to make sure only one 48*3ad684d6Sjb150015 * thread calls this function. 49*3ad684d6Sjb150015 */ 50*3ad684d6Sjb150015 door_handle_t 51*3ad684d6Sjb150015 smb_kshare_init(int door_id) 52*3ad684d6Sjb150015 { 53*3ad684d6Sjb150015 return (door_ki_lookup(door_id)); 54*3ad684d6Sjb150015 } 55*3ad684d6Sjb150015 56*3ad684d6Sjb150015 /* 57*3ad684d6Sjb150015 * smb_kshare_fini 58*3ad684d6Sjb150015 * 59*3ad684d6Sjb150015 * This function is not MultiThread safe. The caller has to make sure only one 60*3ad684d6Sjb150015 * thread calls this function. 61*3ad684d6Sjb150015 */ 62*3ad684d6Sjb150015 void 63*3ad684d6Sjb150015 smb_kshare_fini(door_handle_t dhdl) 64*3ad684d6Sjb150015 { 65*3ad684d6Sjb150015 ASSERT(dhdl != NULL); 66*3ad684d6Sjb150015 if (dhdl) 67*3ad684d6Sjb150015 door_ki_rele(dhdl); 68*3ad684d6Sjb150015 } 69*3ad684d6Sjb150015 70*3ad684d6Sjb150015 uint32_t 71*3ad684d6Sjb150015 smb_kshare_getinfo(door_handle_t dhdl, char *share_name, lmshare_info_t *si) 72*3ad684d6Sjb150015 { 73*3ad684d6Sjb150015 door_arg_t arg; 74*3ad684d6Sjb150015 char *buf; 75*3ad684d6Sjb150015 unsigned int used; 76*3ad684d6Sjb150015 smb_dr_ctx_t *dec_ctx; 77*3ad684d6Sjb150015 smb_dr_ctx_t *enc_ctx; 78*3ad684d6Sjb150015 int status; 79*3ad684d6Sjb150015 uint32_t rc; 80*3ad684d6Sjb150015 int opcode = LMSHR_DOOR_GETINFO; 81*3ad684d6Sjb150015 82*3ad684d6Sjb150015 buf = kmem_alloc(LMSHR_DOOR_SIZE, KM_SLEEP); 83*3ad684d6Sjb150015 84*3ad684d6Sjb150015 enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); 85*3ad684d6Sjb150015 smb_dr_put_uint32(enc_ctx, opcode); 86*3ad684d6Sjb150015 smb_dr_put_string(enc_ctx, share_name); 87*3ad684d6Sjb150015 88*3ad684d6Sjb150015 if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { 89*3ad684d6Sjb150015 cmn_err(CE_WARN, "smb_kshare_getinfo: Encode error %d", 90*3ad684d6Sjb150015 status); 91*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 92*3ad684d6Sjb150015 return (NERR_InternalError); 93*3ad684d6Sjb150015 } 94*3ad684d6Sjb150015 95*3ad684d6Sjb150015 arg.data_ptr = buf; 96*3ad684d6Sjb150015 arg.data_size = used; 97*3ad684d6Sjb150015 arg.desc_ptr = NULL; 98*3ad684d6Sjb150015 arg.desc_num = 0; 99*3ad684d6Sjb150015 arg.rbuf = buf; 100*3ad684d6Sjb150015 arg.rsize = LMSHR_DOOR_SIZE; 101*3ad684d6Sjb150015 102*3ad684d6Sjb150015 if (door_ki_upcall(dhdl, &arg) != 0) { 103*3ad684d6Sjb150015 cmn_err(CE_WARN, "smb_kshare_getinfo: Door call failed"); 104*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 105*3ad684d6Sjb150015 return (NERR_InternalError); 106*3ad684d6Sjb150015 } 107*3ad684d6Sjb150015 108*3ad684d6Sjb150015 dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); 109*3ad684d6Sjb150015 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 110*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 111*3ad684d6Sjb150015 return (NERR_InternalError); 112*3ad684d6Sjb150015 } 113*3ad684d6Sjb150015 114*3ad684d6Sjb150015 rc = smb_dr_get_uint32(dec_ctx); 115*3ad684d6Sjb150015 smb_dr_get_lmshare(dec_ctx, si); 116*3ad684d6Sjb150015 if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { 117*3ad684d6Sjb150015 cmn_err(CE_WARN, "smb_kshare_getinfo: Decode error %d", 118*3ad684d6Sjb150015 status); 119*3ad684d6Sjb150015 rc = NERR_InternalError; 120*3ad684d6Sjb150015 } 121*3ad684d6Sjb150015 122*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 123*3ad684d6Sjb150015 return (rc); 124*3ad684d6Sjb150015 } 125*3ad684d6Sjb150015 126*3ad684d6Sjb150015 uint32_t 127*3ad684d6Sjb150015 smb_kshare_enum(door_handle_t dhdl, smb_enumshare_info_t *enuminfo) 128*3ad684d6Sjb150015 { 129*3ad684d6Sjb150015 door_arg_t arg; 130*3ad684d6Sjb150015 char *door_buf; 131*3ad684d6Sjb150015 int door_bufsz; 132*3ad684d6Sjb150015 unsigned int used; 133*3ad684d6Sjb150015 smb_dr_ctx_t *dec_ctx; 134*3ad684d6Sjb150015 smb_dr_ctx_t *enc_ctx; 135*3ad684d6Sjb150015 int status; 136*3ad684d6Sjb150015 uint32_t rc; 137*3ad684d6Sjb150015 int opcode = LMSHR_DOOR_ENUM; 138*3ad684d6Sjb150015 139*3ad684d6Sjb150015 enuminfo->es_ntotal = enuminfo->es_nsent = 0; 140*3ad684d6Sjb150015 141*3ad684d6Sjb150015 door_bufsz = enuminfo->es_bufsize + strlen(enuminfo->es_username) 142*3ad684d6Sjb150015 + sizeof (smb_enumshare_info_t); 143*3ad684d6Sjb150015 door_buf = kmem_alloc(door_bufsz, KM_SLEEP); 144*3ad684d6Sjb150015 145*3ad684d6Sjb150015 enc_ctx = smb_dr_encode_start(door_buf, door_bufsz); 146*3ad684d6Sjb150015 smb_dr_put_uint32(enc_ctx, opcode); 147*3ad684d6Sjb150015 smb_dr_put_ushort(enc_ctx, enuminfo->es_bufsize); 148*3ad684d6Sjb150015 smb_dr_put_string(enc_ctx, enuminfo->es_username); 149*3ad684d6Sjb150015 150*3ad684d6Sjb150015 if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { 151*3ad684d6Sjb150015 cmn_err(CE_WARN, "smb_kshare_enum: Encode error %d", status); 152*3ad684d6Sjb150015 kmem_free(door_buf, door_bufsz); 153*3ad684d6Sjb150015 return (NERR_InternalError); 154*3ad684d6Sjb150015 } 155*3ad684d6Sjb150015 156*3ad684d6Sjb150015 arg.data_ptr = door_buf; 157*3ad684d6Sjb150015 arg.data_size = used; 158*3ad684d6Sjb150015 arg.desc_ptr = NULL; 159*3ad684d6Sjb150015 arg.desc_num = 0; 160*3ad684d6Sjb150015 arg.rbuf = door_buf; 161*3ad684d6Sjb150015 arg.rsize = door_bufsz; 162*3ad684d6Sjb150015 163*3ad684d6Sjb150015 if (door_ki_upcall(dhdl, &arg) != 0) { 164*3ad684d6Sjb150015 cmn_err(CE_WARN, "smb_kshare_enum: Door call failed"); 165*3ad684d6Sjb150015 kmem_free(door_buf, door_bufsz); 166*3ad684d6Sjb150015 return (NERR_InternalError); 167*3ad684d6Sjb150015 } 168*3ad684d6Sjb150015 169*3ad684d6Sjb150015 dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); 170*3ad684d6Sjb150015 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 171*3ad684d6Sjb150015 kmem_free(door_buf, door_bufsz); 172*3ad684d6Sjb150015 return (NERR_InternalError); 173*3ad684d6Sjb150015 } 174*3ad684d6Sjb150015 175*3ad684d6Sjb150015 rc = smb_dr_get_uint32(dec_ctx); 176*3ad684d6Sjb150015 if (rc == NERR_Success) { 177*3ad684d6Sjb150015 enuminfo->es_ntotal = smb_dr_get_ushort(dec_ctx); 178*3ad684d6Sjb150015 enuminfo->es_nsent = smb_dr_get_ushort(dec_ctx); 179*3ad684d6Sjb150015 enuminfo->es_datasize = smb_dr_get_ushort(dec_ctx); 180*3ad684d6Sjb150015 (void) smb_dr_get_buf(dec_ctx, 181*3ad684d6Sjb150015 (unsigned char *)enuminfo->es_buf, 182*3ad684d6Sjb150015 enuminfo->es_bufsize); 183*3ad684d6Sjb150015 } 184*3ad684d6Sjb150015 185*3ad684d6Sjb150015 if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { 186*3ad684d6Sjb150015 cmn_err(CE_WARN, "smb_kshare_enum: Decode error %d", status); 187*3ad684d6Sjb150015 rc = NERR_InternalError; 188*3ad684d6Sjb150015 } 189*3ad684d6Sjb150015 190*3ad684d6Sjb150015 kmem_free(door_buf, door_bufsz); 191*3ad684d6Sjb150015 return (rc); 192*3ad684d6Sjb150015 } 193*3ad684d6Sjb150015 194*3ad684d6Sjb150015 /* 195*3ad684d6Sjb150015 * This is a special interface that will be utilized by ZFS to cause 196*3ad684d6Sjb150015 * a share to be added/removed 197*3ad684d6Sjb150015 * 198*3ad684d6Sjb150015 * arg is either a lmshare_info_t or share_name from userspace. 199*3ad684d6Sjb150015 * It will need to be copied into the kernel. It is lmshare_info_t 200*3ad684d6Sjb150015 * for add operations and share_name for delete operations. 201*3ad684d6Sjb150015 */ 202*3ad684d6Sjb150015 int 203*3ad684d6Sjb150015 smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share) 204*3ad684d6Sjb150015 { 205*3ad684d6Sjb150015 door_arg_t doorarg = { 0 }; 206*3ad684d6Sjb150015 char *buf = NULL; 207*3ad684d6Sjb150015 char *str = NULL; 208*3ad684d6Sjb150015 int error; 209*3ad684d6Sjb150015 int rc; 210*3ad684d6Sjb150015 unsigned int used; 211*3ad684d6Sjb150015 smb_dr_ctx_t *dec_ctx; 212*3ad684d6Sjb150015 smb_dr_ctx_t *enc_ctx; 213*3ad684d6Sjb150015 lmshare_info_t *lmshare = NULL; 214*3ad684d6Sjb150015 int opcode; 215*3ad684d6Sjb150015 216*3ad684d6Sjb150015 opcode = add_share == B_TRUE ? LMSHR_DOOR_ADD : LMSHR_DOOR_DELETE; 217*3ad684d6Sjb150015 218*3ad684d6Sjb150015 buf = kmem_alloc(LMSHR_DOOR_SIZE, KM_SLEEP); 219*3ad684d6Sjb150015 enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); 220*3ad684d6Sjb150015 smb_dr_put_uint32(enc_ctx, opcode); 221*3ad684d6Sjb150015 222*3ad684d6Sjb150015 switch (opcode) { 223*3ad684d6Sjb150015 case LMSHR_DOOR_ADD: 224*3ad684d6Sjb150015 lmshare = kmem_alloc(sizeof (lmshare_info_t), KM_SLEEP); 225*3ad684d6Sjb150015 if (error = xcopyin(arg, lmshare, sizeof (lmshare_info_t))) { 226*3ad684d6Sjb150015 kmem_free(lmshare, sizeof (lmshare_info_t)); 227*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 228*3ad684d6Sjb150015 return (error); 229*3ad684d6Sjb150015 } 230*3ad684d6Sjb150015 smb_dr_put_lmshare(enc_ctx, lmshare); 231*3ad684d6Sjb150015 break; 232*3ad684d6Sjb150015 233*3ad684d6Sjb150015 case LMSHR_DOOR_DELETE: 234*3ad684d6Sjb150015 str = kmem_alloc(MAXPATHLEN, KM_SLEEP); 235*3ad684d6Sjb150015 if (error = copyinstr(arg, str, MAXPATHLEN, NULL)) { 236*3ad684d6Sjb150015 kmem_free(str, MAXPATHLEN); 237*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 238*3ad684d6Sjb150015 return (error); 239*3ad684d6Sjb150015 } 240*3ad684d6Sjb150015 smb_dr_put_string(enc_ctx, str); 241*3ad684d6Sjb150015 kmem_free(str, MAXPATHLEN); 242*3ad684d6Sjb150015 break; 243*3ad684d6Sjb150015 } 244*3ad684d6Sjb150015 245*3ad684d6Sjb150015 if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) { 246*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 247*3ad684d6Sjb150015 if (lmshare) 248*3ad684d6Sjb150015 kmem_free(lmshare, sizeof (lmshare_info_t)); 249*3ad684d6Sjb150015 return (NERR_InternalError); 250*3ad684d6Sjb150015 } 251*3ad684d6Sjb150015 252*3ad684d6Sjb150015 doorarg.data_ptr = buf; 253*3ad684d6Sjb150015 doorarg.data_size = used; 254*3ad684d6Sjb150015 doorarg.rbuf = buf; 255*3ad684d6Sjb150015 doorarg.rsize = LMSHR_DOOR_SIZE; 256*3ad684d6Sjb150015 257*3ad684d6Sjb150015 error = door_ki_upcall(dhdl, &doorarg); 258*3ad684d6Sjb150015 259*3ad684d6Sjb150015 if (error) { 260*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 261*3ad684d6Sjb150015 if (lmshare) 262*3ad684d6Sjb150015 kmem_free(lmshare, sizeof (lmshare_info_t)); 263*3ad684d6Sjb150015 return (error); 264*3ad684d6Sjb150015 } 265*3ad684d6Sjb150015 266*3ad684d6Sjb150015 dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size); 267*3ad684d6Sjb150015 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 268*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 269*3ad684d6Sjb150015 if (lmshare) 270*3ad684d6Sjb150015 kmem_free(lmshare, sizeof (lmshare_info_t)); 271*3ad684d6Sjb150015 return (NERR_InternalError); 272*3ad684d6Sjb150015 } 273*3ad684d6Sjb150015 274*3ad684d6Sjb150015 rc = smb_dr_get_uint32(dec_ctx); 275*3ad684d6Sjb150015 if (opcode == LMSHR_DOOR_ADD) 276*3ad684d6Sjb150015 smb_dr_get_lmshare(dec_ctx, lmshare); 277*3ad684d6Sjb150015 278*3ad684d6Sjb150015 if (smb_dr_decode_finish(dec_ctx)) 279*3ad684d6Sjb150015 rc = NERR_InternalError; 280*3ad684d6Sjb150015 281*3ad684d6Sjb150015 kmem_free(buf, LMSHR_DOOR_SIZE); 282*3ad684d6Sjb150015 if (lmshare) 283*3ad684d6Sjb150015 kmem_free(lmshare, sizeof (lmshare_info_t)); 284*3ad684d6Sjb150015 285*3ad684d6Sjb150015 return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc); 286*3ad684d6Sjb150015 } 287*3ad684d6Sjb150015 288*3ad684d6Sjb150015 /* 289*3ad684d6Sjb150015 * Return 0 upon success. Otherwise > 0 290*3ad684d6Sjb150015 */ 291*3ad684d6Sjb150015 static int 292*3ad684d6Sjb150015 smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx) 293*3ad684d6Sjb150015 { 294*3ad684d6Sjb150015 int status = smb_dr_get_int32(dec_ctx); 295*3ad684d6Sjb150015 int err; 296*3ad684d6Sjb150015 297*3ad684d6Sjb150015 switch (status) { 298*3ad684d6Sjb150015 case LMSHR_DOOR_SRV_SUCCESS: 299*3ad684d6Sjb150015 return (0); 300*3ad684d6Sjb150015 301*3ad684d6Sjb150015 case LMSHR_DOOR_SRV_ERROR: 302*3ad684d6Sjb150015 err = smb_dr_get_uint32(dec_ctx); 303*3ad684d6Sjb150015 cmn_err(CE_WARN, "%d: Encountered door server error %d", 304*3ad684d6Sjb150015 opcode, err); 305*3ad684d6Sjb150015 (void) smb_dr_decode_finish(dec_ctx); 306*3ad684d6Sjb150015 return (err); 307*3ad684d6Sjb150015 } 308*3ad684d6Sjb150015 309*3ad684d6Sjb150015 ASSERT(0); 310*3ad684d6Sjb150015 return (EINVAL); 311*3ad684d6Sjb150015 } 312