16771Sjb150015 /* 26771Sjb150015 * CDDL HEADER START 36771Sjb150015 * 46771Sjb150015 * The contents of this file are subject to the terms of the 56771Sjb150015 * Common Development and Distribution License (the "License"). 66771Sjb150015 * You may not use this file except in compliance with the License. 76771Sjb150015 * 86771Sjb150015 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96771Sjb150015 * or http://www.opensolaris.org/os/licensing. 106771Sjb150015 * See the License for the specific language governing permissions 116771Sjb150015 * and limitations under the License. 126771Sjb150015 * 136771Sjb150015 * When distributing Covered Code, include this CDDL HEADER in each 146771Sjb150015 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156771Sjb150015 * If applicable, add the following below this CDDL HEADER, with the 166771Sjb150015 * fields enclosed by brackets "[]" replaced with your own identifying 176771Sjb150015 * information: Portions Copyright [yyyy] [name of copyright owner] 186771Sjb150015 * 196771Sjb150015 * CDDL HEADER END 206771Sjb150015 */ 216771Sjb150015 /* 22*12065SKeyur.Desai@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 236771Sjb150015 */ 246771Sjb150015 256771Sjb150015 /* 266771Sjb150015 * Kernel door client for LanMan share management. 276771Sjb150015 */ 286771Sjb150015 296771Sjb150015 #include <sys/ddi.h> 306771Sjb150015 #include <sys/sunddi.h> 316771Sjb150015 #include <sys/cmn_err.h> 326771Sjb150015 #include <sys/door.h> 336771Sjb150015 #include <smbsrv/lmerr.h> 347052Samw #include <smbsrv/smb_share.h> 3511963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_door.h> 366771Sjb150015 #include <smbsrv/smbinfo.h> 376771Sjb150015 386771Sjb150015 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *); 396771Sjb150015 406771Sjb150015 /* 416771Sjb150015 * smb_kshare_init 426771Sjb150015 * 436771Sjb150015 * This function is not MultiThread safe. The caller has to make sure only one 446771Sjb150015 * thread calls this function. 456771Sjb150015 */ 466771Sjb150015 door_handle_t 476771Sjb150015 smb_kshare_init(int door_id) 486771Sjb150015 { 496771Sjb150015 return (door_ki_lookup(door_id)); 506771Sjb150015 } 516771Sjb150015 526771Sjb150015 /* 536771Sjb150015 * smb_kshare_fini 546771Sjb150015 * 556771Sjb150015 * This function is not MultiThread safe. The caller has to make sure only one 566771Sjb150015 * thread calls this function. 576771Sjb150015 */ 586771Sjb150015 void 596771Sjb150015 smb_kshare_fini(door_handle_t dhdl) 606771Sjb150015 { 616771Sjb150015 if (dhdl) 626771Sjb150015 door_ki_rele(dhdl); 636771Sjb150015 } 646771Sjb150015 656771Sjb150015 uint32_t 667961SNatalie.Li@Sun.COM smb_kshare_getinfo(door_handle_t dhdl, char *share_name, smb_share_t *si, 678670SJose.Borrego@Sun.COM smb_inaddr_t *ipaddr) 686771Sjb150015 { 696771Sjb150015 door_arg_t arg; 706771Sjb150015 char *buf; 716771Sjb150015 unsigned int used; 726771Sjb150015 smb_dr_ctx_t *dec_ctx; 736771Sjb150015 smb_dr_ctx_t *enc_ctx; 746771Sjb150015 uint32_t rc; 757052Samw int opcode = SMB_SHROP_GETINFO; 766771Sjb150015 777052Samw buf = kmem_alloc(SMB_SHARE_DSIZE, KM_SLEEP); 786771Sjb150015 797052Samw enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE); 806771Sjb150015 smb_dr_put_uint32(enc_ctx, opcode); 816771Sjb150015 smb_dr_put_string(enc_ctx, share_name); 828670SJose.Borrego@Sun.COM smb_dr_put_buf(enc_ctx, (uchar_t *)ipaddr, sizeof (smb_inaddr_t)); 836771Sjb150015 847961SNatalie.Li@Sun.COM if (smb_dr_encode_finish(enc_ctx, &used) != 0) { 857052Samw kmem_free(buf, SMB_SHARE_DSIZE); 866771Sjb150015 return (NERR_InternalError); 876771Sjb150015 } 886771Sjb150015 896771Sjb150015 arg.data_ptr = buf; 906771Sjb150015 arg.data_size = used; 916771Sjb150015 arg.desc_ptr = NULL; 926771Sjb150015 arg.desc_num = 0; 936771Sjb150015 arg.rbuf = buf; 947052Samw arg.rsize = SMB_SHARE_DSIZE; 956771Sjb150015 966997Sjwadams if (door_ki_upcall_limited(dhdl, &arg, NULL, SIZE_MAX, 0) != 0) { 977052Samw kmem_free(buf, SMB_SHARE_DSIZE); 986771Sjb150015 return (NERR_InternalError); 996771Sjb150015 } 1006771Sjb150015 1016771Sjb150015 dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); 1026771Sjb150015 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 1037052Samw kmem_free(buf, SMB_SHARE_DSIZE); 1046771Sjb150015 return (NERR_InternalError); 1056771Sjb150015 } 1066771Sjb150015 1076771Sjb150015 rc = smb_dr_get_uint32(dec_ctx); 1087052Samw smb_dr_get_share(dec_ctx, si); 1097961SNatalie.Li@Sun.COM if (smb_dr_decode_finish(dec_ctx) != 0) 1106771Sjb150015 rc = NERR_InternalError; 1116771Sjb150015 1127052Samw kmem_free(buf, SMB_SHARE_DSIZE); 1136771Sjb150015 return (rc); 1146771Sjb150015 } 1156771Sjb150015 1166771Sjb150015 uint32_t 1176771Sjb150015 smb_kshare_enum(door_handle_t dhdl, smb_enumshare_info_t *enuminfo) 1186771Sjb150015 { 1196771Sjb150015 door_arg_t arg; 1206771Sjb150015 char *door_buf; 1216771Sjb150015 int door_bufsz; 1226771Sjb150015 unsigned int used; 1236771Sjb150015 smb_dr_ctx_t *dec_ctx; 1246771Sjb150015 smb_dr_ctx_t *enc_ctx; 1256771Sjb150015 uint32_t rc; 1267052Samw int opcode = SMB_SHROP_ENUM; 1276771Sjb150015 1286771Sjb150015 enuminfo->es_ntotal = enuminfo->es_nsent = 0; 1296771Sjb150015 130*12065SKeyur.Desai@Sun.COM door_bufsz = enuminfo->es_bufsize + sizeof (smb_enumshare_info_t); 1316771Sjb150015 door_buf = kmem_alloc(door_bufsz, KM_SLEEP); 1326771Sjb150015 1336771Sjb150015 enc_ctx = smb_dr_encode_start(door_buf, door_bufsz); 1346771Sjb150015 smb_dr_put_uint32(enc_ctx, opcode); 1356771Sjb150015 smb_dr_put_ushort(enc_ctx, enuminfo->es_bufsize); 136*12065SKeyur.Desai@Sun.COM smb_dr_put_uint32(enc_ctx, enuminfo->es_posix_uid); 1376771Sjb150015 1387961SNatalie.Li@Sun.COM if (smb_dr_encode_finish(enc_ctx, &used) != 0) { 1396771Sjb150015 kmem_free(door_buf, door_bufsz); 1406771Sjb150015 return (NERR_InternalError); 1416771Sjb150015 } 1426771Sjb150015 1436771Sjb150015 arg.data_ptr = door_buf; 1446771Sjb150015 arg.data_size = used; 1456771Sjb150015 arg.desc_ptr = NULL; 1466771Sjb150015 arg.desc_num = 0; 1476771Sjb150015 arg.rbuf = door_buf; 1486771Sjb150015 arg.rsize = door_bufsz; 1496771Sjb150015 1506997Sjwadams if (door_ki_upcall_limited(dhdl, &arg, NULL, SIZE_MAX, 0) != 0) { 1516771Sjb150015 kmem_free(door_buf, door_bufsz); 1526771Sjb150015 return (NERR_InternalError); 1536771Sjb150015 } 1546771Sjb150015 1556771Sjb150015 dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); 1566771Sjb150015 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 1576771Sjb150015 kmem_free(door_buf, door_bufsz); 1586771Sjb150015 return (NERR_InternalError); 1596771Sjb150015 } 1606771Sjb150015 1616771Sjb150015 rc = smb_dr_get_uint32(dec_ctx); 1626771Sjb150015 if (rc == NERR_Success) { 1636771Sjb150015 enuminfo->es_ntotal = smb_dr_get_ushort(dec_ctx); 1646771Sjb150015 enuminfo->es_nsent = smb_dr_get_ushort(dec_ctx); 1656771Sjb150015 enuminfo->es_datasize = smb_dr_get_ushort(dec_ctx); 1666771Sjb150015 (void) smb_dr_get_buf(dec_ctx, 1676771Sjb150015 (unsigned char *)enuminfo->es_buf, 1686771Sjb150015 enuminfo->es_bufsize); 1696771Sjb150015 } 1706771Sjb150015 1717961SNatalie.Li@Sun.COM if (smb_dr_decode_finish(dec_ctx) != 0) 1726771Sjb150015 rc = NERR_InternalError; 1736771Sjb150015 1746771Sjb150015 kmem_free(door_buf, door_bufsz); 1756771Sjb150015 return (rc); 1766771Sjb150015 } 1776771Sjb150015 1786771Sjb150015 /* 1799832Samw@Sun.COM * Executes map and unmap command for shares. 1809832Samw@Sun.COM */ 1819832Samw@Sun.COM uint32_t 1829832Samw@Sun.COM smb_kshare_exec(door_handle_t dhdl, char *sharename, smb_execsub_info_t *subs, 1839832Samw@Sun.COM int exec_type) 1849832Samw@Sun.COM { 1859832Samw@Sun.COM door_arg_t arg; 1869832Samw@Sun.COM char *buf; 1879832Samw@Sun.COM int bufsz; 1889832Samw@Sun.COM unsigned int used; 1899832Samw@Sun.COM smb_dr_ctx_t *dec_ctx; 1909832Samw@Sun.COM smb_dr_ctx_t *enc_ctx; 1919832Samw@Sun.COM uint32_t rc; 1929832Samw@Sun.COM int opcode = SMB_SHROP_EXEC; 1939832Samw@Sun.COM 1949832Samw@Sun.COM bufsz = (2 * sizeof (int)) + strlen(sharename) + strlen(subs->e_winname) 1959832Samw@Sun.COM + strlen(subs->e_userdom) + strlen(subs->e_cli_netbiosname) + 1969832Samw@Sun.COM (2 * sizeof (smb_inaddr_t)) + sizeof (uid_t) + 1979832Samw@Sun.COM sizeof (smb_execsub_info_t); 1989832Samw@Sun.COM 1999832Samw@Sun.COM buf = kmem_alloc(bufsz, KM_SLEEP); 2009832Samw@Sun.COM 2019832Samw@Sun.COM enc_ctx = smb_dr_encode_start(buf, bufsz); 2029832Samw@Sun.COM smb_dr_put_uint32(enc_ctx, opcode); 2039832Samw@Sun.COM smb_dr_put_string(enc_ctx, sharename); 2049832Samw@Sun.COM smb_dr_put_string(enc_ctx, subs->e_winname); 2059832Samw@Sun.COM smb_dr_put_string(enc_ctx, subs->e_userdom); 2069832Samw@Sun.COM smb_dr_put_buf(enc_ctx, (uchar_t *)&subs->e_srv_ipaddr, 2079832Samw@Sun.COM sizeof (smb_inaddr_t)); 2089832Samw@Sun.COM smb_dr_put_buf(enc_ctx, (uchar_t *)&subs->e_cli_ipaddr, 2099832Samw@Sun.COM sizeof (smb_inaddr_t)); 2109832Samw@Sun.COM smb_dr_put_string(enc_ctx, subs->e_cli_netbiosname); 2119832Samw@Sun.COM smb_dr_put_int32(enc_ctx, subs->e_uid); 2129832Samw@Sun.COM smb_dr_put_int32(enc_ctx, exec_type); 2139832Samw@Sun.COM 2149832Samw@Sun.COM if (smb_dr_encode_finish(enc_ctx, &used) != 0) { 2159832Samw@Sun.COM kmem_free(buf, bufsz); 2169832Samw@Sun.COM return (NERR_InternalError); 2179832Samw@Sun.COM } 2189832Samw@Sun.COM 2199832Samw@Sun.COM arg.data_ptr = buf; 2209832Samw@Sun.COM arg.data_size = used; 2219832Samw@Sun.COM arg.desc_ptr = NULL; 2229832Samw@Sun.COM arg.desc_num = 0; 2239832Samw@Sun.COM arg.rbuf = buf; 2249832Samw@Sun.COM arg.rsize = bufsz; 2259832Samw@Sun.COM 2269832Samw@Sun.COM if (door_ki_upcall_limited(dhdl, &arg, NULL, SIZE_MAX, 0) != 0) { 2279832Samw@Sun.COM kmem_free(buf, bufsz); 2289832Samw@Sun.COM return (NERR_InternalError); 2299832Samw@Sun.COM } 2309832Samw@Sun.COM 2319832Samw@Sun.COM dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); 2329832Samw@Sun.COM if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 2339832Samw@Sun.COM kmem_free(buf, bufsz); 2349832Samw@Sun.COM return (NERR_InternalError); 2359832Samw@Sun.COM } 2369832Samw@Sun.COM 2379832Samw@Sun.COM rc = smb_dr_get_uint32(dec_ctx); 2389832Samw@Sun.COM if (smb_dr_decode_finish(dec_ctx) != 0) 2399832Samw@Sun.COM rc = NERR_InternalError; 2409832Samw@Sun.COM 2419832Samw@Sun.COM kmem_free(buf, bufsz); 2429832Samw@Sun.COM return (rc); 2439832Samw@Sun.COM } 2449832Samw@Sun.COM 2459832Samw@Sun.COM /* 2466771Sjb150015 * This is a special interface that will be utilized by ZFS to cause 2476771Sjb150015 * a share to be added/removed 2486771Sjb150015 * 2497052Samw * arg is either a smb_share_t or share_name from userspace. 2507052Samw * It will need to be copied into the kernel. It is smb_share_t 2516771Sjb150015 * for add operations and share_name for delete operations. 2526771Sjb150015 */ 2536771Sjb150015 int 2546771Sjb150015 smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share) 2556771Sjb150015 { 2566771Sjb150015 door_arg_t doorarg = { 0 }; 2576771Sjb150015 char *buf = NULL; 2586771Sjb150015 char *str = NULL; 2596771Sjb150015 int error; 2606771Sjb150015 int rc; 2616771Sjb150015 unsigned int used; 2626771Sjb150015 smb_dr_ctx_t *dec_ctx; 2636771Sjb150015 smb_dr_ctx_t *enc_ctx; 2647052Samw smb_share_t *lmshare = NULL; 2656771Sjb150015 int opcode; 2666771Sjb150015 2677052Samw opcode = (add_share) ? SMB_SHROP_ADD : SMB_SHROP_DELETE; 2686771Sjb150015 2697052Samw buf = kmem_alloc(SMB_SHARE_DSIZE, KM_SLEEP); 2707052Samw enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE); 2716771Sjb150015 smb_dr_put_uint32(enc_ctx, opcode); 2726771Sjb150015 2736771Sjb150015 switch (opcode) { 2747052Samw case SMB_SHROP_ADD: 2757052Samw lmshare = kmem_alloc(sizeof (smb_share_t), KM_SLEEP); 2767052Samw if (error = xcopyin(arg, lmshare, sizeof (smb_share_t))) { 2777052Samw kmem_free(lmshare, sizeof (smb_share_t)); 2787052Samw kmem_free(buf, SMB_SHARE_DSIZE); 2796771Sjb150015 return (error); 2806771Sjb150015 } 2817052Samw smb_dr_put_share(enc_ctx, lmshare); 2826771Sjb150015 break; 2836771Sjb150015 2847052Samw case SMB_SHROP_DELETE: 2856771Sjb150015 str = kmem_alloc(MAXPATHLEN, KM_SLEEP); 2866771Sjb150015 if (error = copyinstr(arg, str, MAXPATHLEN, NULL)) { 2876771Sjb150015 kmem_free(str, MAXPATHLEN); 2887052Samw kmem_free(buf, SMB_SHARE_DSIZE); 2896771Sjb150015 return (error); 2906771Sjb150015 } 2916771Sjb150015 smb_dr_put_string(enc_ctx, str); 2926771Sjb150015 kmem_free(str, MAXPATHLEN); 2936771Sjb150015 break; 2946771Sjb150015 } 2956771Sjb150015 2966771Sjb150015 if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) { 2977052Samw kmem_free(buf, SMB_SHARE_DSIZE); 2986771Sjb150015 if (lmshare) 2997052Samw kmem_free(lmshare, sizeof (smb_share_t)); 3006771Sjb150015 return (NERR_InternalError); 3016771Sjb150015 } 3026771Sjb150015 3036771Sjb150015 doorarg.data_ptr = buf; 3046771Sjb150015 doorarg.data_size = used; 3056771Sjb150015 doorarg.rbuf = buf; 3067052Samw doorarg.rsize = SMB_SHARE_DSIZE; 3076771Sjb150015 3086997Sjwadams error = door_ki_upcall_limited(dhdl, &doorarg, NULL, SIZE_MAX, 0); 3096771Sjb150015 3106771Sjb150015 if (error) { 3117052Samw kmem_free(buf, SMB_SHARE_DSIZE); 3126771Sjb150015 if (lmshare) 3137052Samw kmem_free(lmshare, sizeof (smb_share_t)); 3146771Sjb150015 return (error); 3156771Sjb150015 } 3166771Sjb150015 3176771Sjb150015 dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size); 3186771Sjb150015 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) { 3197052Samw kmem_free(buf, SMB_SHARE_DSIZE); 3206771Sjb150015 if (lmshare) 3217052Samw kmem_free(lmshare, sizeof (smb_share_t)); 3226771Sjb150015 return (NERR_InternalError); 3236771Sjb150015 } 3246771Sjb150015 3256771Sjb150015 rc = smb_dr_get_uint32(dec_ctx); 3267052Samw if (opcode == SMB_SHROP_ADD) 3277052Samw smb_dr_get_share(dec_ctx, lmshare); 3286771Sjb150015 3296771Sjb150015 if (smb_dr_decode_finish(dec_ctx)) 3306771Sjb150015 rc = NERR_InternalError; 3316771Sjb150015 3327052Samw kmem_free(buf, SMB_SHARE_DSIZE); 3336771Sjb150015 if (lmshare) 3347052Samw kmem_free(lmshare, sizeof (smb_share_t)); 3356771Sjb150015 3366771Sjb150015 return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc); 3376771Sjb150015 } 3386771Sjb150015 3396771Sjb150015 /* 3406771Sjb150015 * Return 0 upon success. Otherwise > 0 3416771Sjb150015 */ 3426771Sjb150015 static int 3436771Sjb150015 smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx) 3446771Sjb150015 { 3456771Sjb150015 int status = smb_dr_get_int32(dec_ctx); 3466771Sjb150015 int err; 3476771Sjb150015 3486771Sjb150015 switch (status) { 3497052Samw case SMB_SHARE_DSUCCESS: 3506771Sjb150015 return (0); 3516771Sjb150015 3527052Samw case SMB_SHARE_DERROR: 3536771Sjb150015 err = smb_dr_get_uint32(dec_ctx); 3546771Sjb150015 cmn_err(CE_WARN, "%d: Encountered door server error %d", 3556771Sjb150015 opcode, err); 3566771Sjb150015 (void) smb_dr_decode_finish(dec_ctx); 3576771Sjb150015 return (err); 3586771Sjb150015 } 3596771Sjb150015 3606771Sjb150015 ASSERT(0); 3616771Sjb150015 return (EINVAL); 3626771Sjb150015 } 363