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 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright 2017 Joyent, Inc.
  26  */
  27 
  28 #include <smbsrv/smb_door.h>
  29 #include <smbsrv/smb_ktypes.h>
  30 #include <smbsrv/smb2_kproto.h>
  31 #include <smbsrv/smb_kstat.h>
  32 
  33 typedef struct smb_unshare {
  34         list_node_t     us_lnd;
  35         char            us_sharename[MAXNAMELEN];
  36 } smb_unshare_t;
  37 
  38 static kmem_cache_t     *smb_kshare_cache_share;
  39 static kmem_cache_t     *smb_kshare_cache_unexport;
  40 
  41 static int smb_kshare_cmp(const void *, const void *);
  42 static void smb_kshare_hold(const void *);
  43 static boolean_t smb_kshare_rele(const void *);
  44 static void smb_kshare_destroy(void *);
  45 static char *smb_kshare_oemname(const char *);
  46 static int smb_kshare_is_special(const char *);
  47 static boolean_t smb_kshare_is_admin(const char *);
  48 static smb_kshare_t *smb_kshare_decode(nvlist_t *);
  49 static uint32_t smb_kshare_decode_bool(nvlist_t *, const char *, uint32_t);
  50 static void smb_kshare_unexport_thread(smb_thread_t *, void *);
  51 static int smb_kshare_export(smb_server_t *, smb_kshare_t *);
  52 static int smb_kshare_unexport(smb_server_t *, const char *);
  53 static int smb_kshare_export_trans(smb_server_t *, char *, char *, char *);
  54 static void smb_kshare_csc_flags(smb_kshare_t *, const char *);
  55 static int smb_named_kstat_update(kstat_t *ks, int rw);
  56 static int smb_kshare_kstat_update(kstat_t *, int);
  57 void kshare_stats_init(smb_server_t *, smb_kshare_t *);
  58 void kshare_stats_fini(smb_kshare_t *);
  59 
  60 static boolean_t smb_export_isready(smb_server_t *);
  61 
  62 #ifdef  _KERNEL
  63 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
  64 #endif  /* _KERNEL */
  65 
  66 static const smb_avl_nops_t smb_kshare_avlops = {
  67         smb_kshare_cmp,
  68         smb_kshare_hold,
  69         smb_kshare_rele,
  70         smb_kshare_destroy
  71 };
  72 
  73 #ifdef  _KERNEL
  74 /*
  75  * This function is not MultiThread safe. The caller has to make sure only one
  76  * thread calls this function.
  77  */
  78 door_handle_t
  79 smb_kshare_door_init(int door_id)
  80 {
  81         return (door_ki_lookup(door_id));
  82 }
  83 
  84 /*
  85  * This function is not MultiThread safe. The caller has to make sure only one
  86  * thread calls this function.
  87  */
  88 void
  89 smb_kshare_door_fini(door_handle_t dhdl)
  90 {
  91         if (dhdl)
  92                 door_ki_rele(dhdl);
  93 }
  94 
  95 /*
  96  * This is a special interface that will be utilized by ZFS to cause
  97  * a share to be added/removed
  98  *
  99  * arg is either a smb_share_t or share_name from userspace.
 100  * It will need to be copied into the kernel.   It is smb_share_t
 101  * for add operations and share_name for delete operations.
 102  */
 103 int
 104 smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
 105 {
 106         door_arg_t      doorarg = { 0 };
 107         char            *buf = NULL;
 108         char            *str = NULL;
 109         int             error;
 110         int             rc;
 111         unsigned int    used;
 112         smb_dr_ctx_t    *dec_ctx;
 113         smb_dr_ctx_t    *enc_ctx;
 114         smb_share_t     *lmshare = NULL;
 115         int             opcode;
 116 
 117         opcode = (add_share) ? SMB_SHROP_ADD : SMB_SHROP_DELETE;
 118 
 119         buf = kmem_alloc(SMB_SHARE_DSIZE, KM_SLEEP);
 120         enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE);
 121         smb_dr_put_uint32(enc_ctx, opcode);
 122 
 123         switch (opcode) {
 124         case SMB_SHROP_ADD:
 125                 lmshare = kmem_alloc(sizeof (smb_share_t), KM_SLEEP);
 126                 error = xcopyin(arg, lmshare, sizeof (smb_share_t));
 127                 if (error != 0) {
 128                         kmem_free(lmshare, sizeof (smb_share_t));
 129                         kmem_free(buf, SMB_SHARE_DSIZE);
 130                         return (error);
 131                 }
 132                 smb_dr_put_share(enc_ctx, lmshare);
 133                 break;
 134 
 135         case SMB_SHROP_DELETE:
 136                 str = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 137                 error = copyinstr(arg, str, MAXPATHLEN, NULL);
 138                 if (error != 0) {
 139                         kmem_free(str, MAXPATHLEN);
 140                         kmem_free(buf, SMB_SHARE_DSIZE);
 141                         return (error);
 142                 }
 143                 smb_dr_put_string(enc_ctx, str);
 144                 kmem_free(str, MAXPATHLEN);
 145                 break;
 146         }
 147 
 148         if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
 149                 kmem_free(buf, SMB_SHARE_DSIZE);
 150                 if (lmshare)
 151                         kmem_free(lmshare, sizeof (smb_share_t));
 152                 return (NERR_InternalError);
 153         }
 154 
 155         doorarg.data_ptr = buf;
 156         doorarg.data_size = used;
 157         doorarg.rbuf = buf;
 158         doorarg.rsize = SMB_SHARE_DSIZE;
 159 
 160         error = door_ki_upcall_limited(dhdl, &doorarg, NULL, SIZE_MAX, 0);
 161 
 162         if (error) {
 163                 kmem_free(buf, SMB_SHARE_DSIZE);
 164                 if (lmshare)
 165                         kmem_free(lmshare, sizeof (smb_share_t));
 166                 return (error);
 167         }
 168 
 169         dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size);
 170         if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
 171                 kmem_free(buf, SMB_SHARE_DSIZE);
 172                 if (lmshare)
 173                         kmem_free(lmshare, sizeof (smb_share_t));
 174                 return (NERR_InternalError);
 175         }
 176 
 177         rc = smb_dr_get_uint32(dec_ctx);
 178         if (opcode == SMB_SHROP_ADD)
 179                 smb_dr_get_share(dec_ctx, lmshare);
 180 
 181         if (smb_dr_decode_finish(dec_ctx))
 182                 rc = NERR_InternalError;
 183 
 184         kmem_free(buf, SMB_SHARE_DSIZE);
 185         if (lmshare)
 186                 kmem_free(lmshare, sizeof (smb_share_t));
 187 
 188         return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc);
 189 }
 190 #endif  /* _KERNEL */
 191 
 192 /*
 193  * Executes map and unmap command for shares.
 194  */
 195 int
 196 smb_kshare_exec(smb_server_t *sv, smb_shr_execinfo_t *execinfo)
 197 {
 198         int exec_rc = 0;
 199 
 200         (void) smb_kdoor_upcall(sv, SMB_DR_SHR_EXEC,
 201             execinfo, smb_shr_execinfo_xdr, &exec_rc, xdr_int);
 202 
 203         return (exec_rc);
 204 }
 205 
 206 /*
 207  * Obtains any host access restriction on the specified
 208  * share for the given host (ipaddr) by calling smbd
 209  */
 210 uint32_t
 211 smb_kshare_hostaccess(smb_kshare_t *shr, smb_session_t *session)
 212 {
 213         smb_shr_hostaccess_query_t req;
 214         smb_inaddr_t *ipaddr = &session->ipaddr;
 215         uint32_t host_access = SMB_SHRF_ACC_OPEN;
 216         uint32_t flag = SMB_SHRF_ACC_OPEN;
 217         uint32_t access;
 218 
 219         if (smb_inet_iszero(ipaddr))
 220                 return (ACE_ALL_PERMS);
 221 
 222         if ((shr->shr_access_none == NULL || *shr->shr_access_none == '\0') &&
 223             (shr->shr_access_ro == NULL || *shr->shr_access_ro == '\0') &&
 224             (shr->shr_access_rw == NULL || *shr->shr_access_rw == '\0'))
 225                 return (ACE_ALL_PERMS);
 226 
 227         if (shr->shr_access_none != NULL)
 228                 flag |= SMB_SHRF_ACC_NONE;
 229         if (shr->shr_access_ro != NULL)
 230                 flag |= SMB_SHRF_ACC_RO;
 231         if (shr->shr_access_rw != NULL)
 232                 flag |= SMB_SHRF_ACC_RW;
 233 
 234         req.shq_none = shr->shr_access_none;
 235         req.shq_ro = shr->shr_access_ro;
 236         req.shq_rw = shr->shr_access_rw;
 237         req.shq_flag = flag;
 238         req.shq_ipaddr = *ipaddr;
 239 
 240         (void) smb_kdoor_upcall(session->s_server, SMB_DR_SHR_HOSTACCESS,
 241             &req, smb_shr_hostaccess_query_xdr, &host_access, xdr_uint32_t);
 242 
 243         switch (host_access) {
 244         case SMB_SHRF_ACC_RO:
 245                 access = ACE_ALL_PERMS & ~ACE_ALL_WRITE_PERMS;
 246                 break;
 247         case SMB_SHRF_ACC_OPEN:
 248         case SMB_SHRF_ACC_RW:
 249                 access = ACE_ALL_PERMS;
 250                 break;
 251         case SMB_SHRF_ACC_NONE:
 252         default:
 253                 access = 0;
 254         }
 255 
 256         return (access);
 257 }
 258 
 259 /*
 260  * This function is called when smb_server_t is
 261  * created which means smb/service is ready for
 262  * exporting SMB shares
 263  */
 264 void
 265 smb_export_start(smb_server_t *sv)
 266 {
 267         mutex_enter(&sv->sv_export.e_mutex);
 268         if (sv->sv_export.e_ready) {
 269                 mutex_exit(&sv->sv_export.e_mutex);
 270                 return;
 271         }
 272 
 273         sv->sv_export.e_ready = B_TRUE;
 274         mutex_exit(&sv->sv_export.e_mutex);
 275 
 276         smb_avl_create(&sv->sv_export.e_share_avl, sizeof (smb_kshare_t),
 277             offsetof(smb_kshare_t, shr_link), &smb_kshare_avlops);
 278 
 279         (void) smb_kshare_export_trans(sv, "IPC$", "IPC$", "Remote IPC");
 280         (void) smb_kshare_export_trans(sv, "c$", SMB_CVOL, "Default Share");
 281         (void) smb_kshare_export_trans(sv, "vss$", SMB_VSS, "VSS");
 282 }
 283 
 284 /*
 285  * This function is called when smb_server_t goes
 286  * away which means SMB shares should not be made
 287  * available to clients
 288  */
 289 void
 290 smb_export_stop(smb_server_t *sv)
 291 {
 292         mutex_enter(&sv->sv_export.e_mutex);
 293         if (!sv->sv_export.e_ready) {
 294                 mutex_exit(&sv->sv_export.e_mutex);
 295                 return;
 296         }
 297         sv->sv_export.e_ready = B_FALSE;
 298         mutex_exit(&sv->sv_export.e_mutex);
 299 
 300         smb_avl_destroy(&sv->sv_export.e_share_avl);
 301 }
 302 
 303 void
 304 smb_kshare_g_init(void)
 305 {
 306         smb_kshare_cache_share = kmem_cache_create("smb_share_cache",
 307             sizeof (smb_kshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
 308 
 309         smb_kshare_cache_unexport = kmem_cache_create("smb_unexport_cache",
 310             sizeof (smb_unshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
 311 }
 312 
 313 void
 314 smb_kshare_init(smb_server_t *sv)
 315 {
 316 
 317         smb_slist_constructor(&sv->sv_export.e_unexport_list,
 318             sizeof (smb_unshare_t), offsetof(smb_unshare_t, us_lnd));
 319 }
 320 
 321 int
 322 smb_kshare_start(smb_server_t *sv)
 323 {
 324         smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_kshare_unexport",
 325             smb_kshare_unexport_thread, sv, smbsrv_base_pri);
 326 
 327         return (smb_thread_start(&sv->sv_export.e_unexport_thread));
 328 }
 329 
 330 void
 331 smb_kshare_stop(smb_server_t *sv)
 332 {
 333         smb_thread_stop(&sv->sv_export.e_unexport_thread);
 334         smb_thread_destroy(&sv->sv_export.e_unexport_thread);
 335 }
 336 
 337 void
 338 smb_kshare_fini(smb_server_t *sv)
 339 {
 340         smb_unshare_t *ux;
 341 
 342         while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list))
 343             != NULL) {
 344                 smb_slist_remove(&sv->sv_export.e_unexport_list, ux);
 345                 kmem_cache_free(smb_kshare_cache_unexport, ux);
 346         }
 347         smb_slist_destructor(&sv->sv_export.e_unexport_list);
 348 }
 349 
 350 void
 351 smb_kshare_g_fini(void)
 352 {
 353         kmem_cache_destroy(smb_kshare_cache_unexport);
 354         kmem_cache_destroy(smb_kshare_cache_share);
 355 }
 356 
 357 /*
 358  * A list of shares in nvlist format can be sent down
 359  * from userspace thourgh the IOCTL interface. The nvlist
 360  * is unpacked here and all the shares in the list will
 361  * be exported.
 362  */
 363 int
 364 smb_kshare_export_list(smb_ioc_share_t *ioc)
 365 {
 366         smb_server_t    *sv = NULL;
 367         nvlist_t        *shrlist = NULL;
 368         nvlist_t         *share;
 369         nvpair_t         *nvp;
 370         smb_kshare_t     *shr;
 371         char            *shrname;
 372         int             rc;
 373 
 374         if ((rc = smb_server_lookup(&sv)) != 0)
 375                 return (rc);
 376 
 377         if (!smb_export_isready(sv)) {
 378                 rc = ENOTACTIVE;
 379                 goto out;
 380         }
 381 
 382         /*
 383          * Reality check that the nvlist's reported length doesn't exceed the
 384          * ioctl's total length.  We then assume the nvlist_unpack() will
 385          * sanity check the nvlist itself.
 386          */
 387         if ((ioc->shrlen + offsetof(smb_ioc_share_t, shr)) > ioc->hdr.len) {
 388                 rc = EINVAL;
 389                 goto out;
 390         }
 391         rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, KM_SLEEP);
 392         if (rc != 0)
 393                 goto out;
 394 
 395         for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL;
 396             nvp = nvlist_next_nvpair(shrlist, nvp)) {
 397 
 398                 /*
 399                  * Since this loop can run for a while we want to exit
 400                  * as soon as the server state is anything but RUNNING
 401                  * to allow shutdown to proceed.
 402                  */
 403                 if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
 404                         goto out;
 405 
 406                 if (nvpair_type(nvp) != DATA_TYPE_NVLIST)
 407                         continue;
 408 
 409                 shrname = nvpair_name(nvp);
 410                 ASSERT(shrname);
 411 
 412                 if ((rc = nvpair_value_nvlist(nvp, &share)) != 0) {
 413                         cmn_err(CE_WARN, "export[%s]: failed accessing",
 414                             shrname);
 415                         continue;
 416                 }
 417 
 418                 if ((shr = smb_kshare_decode(share)) == NULL) {
 419                         cmn_err(CE_WARN, "export[%s]: failed decoding",
 420                             shrname);
 421                         continue;
 422                 }
 423 
 424                 /* smb_kshare_export consumes shr so it's not leaked */
 425                 if ((rc = smb_kshare_export(sv, shr)) != 0) {
 426                         smb_kshare_destroy(shr);
 427                         continue;
 428                 }
 429         }
 430         rc = 0;
 431 
 432 out:
 433         nvlist_free(shrlist);
 434         smb_server_release(sv);
 435         return (rc);
 436 }
 437 
 438 /*
 439  * This function is invoked when a share is disabled to disconnect trees
 440  * and close files.  Cleaning up may involve VOP and/or VFS calls, which
 441  * may conflict/deadlock with stuck threads if something is amiss with the
 442  * file system.  Queueing the request for asynchronous processing allows the
 443  * call to return immediately so that, if the unshare is being done in the
 444  * context of a forced unmount, the forced unmount will always be able to
 445  * proceed (unblocking stuck I/O and eventually allowing all blocked unshare
 446  * processes to complete).
 447  *
 448  * The path lookup to find the root vnode of the VFS in question and the
 449  * release of this vnode are done synchronously prior to any associated
 450  * unmount.  Doing these asynchronous to an associated unmount could run
 451  * the risk of a spurious EBUSY for a standard unmount or an EIO during
 452  * the path lookup due to a forced unmount finishing first.
 453  */
 454 int
 455 smb_kshare_unexport_list(smb_ioc_share_t *ioc)
 456 {
 457         smb_server_t    *sv = NULL;
 458         smb_unshare_t   *ux;
 459         nvlist_t        *shrlist = NULL;
 460         nvpair_t        *nvp;
 461         boolean_t       unexport = B_FALSE;
 462         char            *shrname;
 463         int             rc;
 464 
 465         if ((rc = smb_server_lookup(&sv)) != 0)
 466                 return (rc);
 467 
 468         /*
 469          * Reality check that the nvlist's reported length doesn't exceed the
 470          * ioctl's total length.  We then assume the nvlist_unpack() will
 471          * sanity check the nvlist itself.
 472          */
 473         if ((ioc->shrlen + offsetof(smb_ioc_share_t, shr)) > ioc->hdr.len) {
 474                 rc = EINVAL;
 475                 goto out;
 476         }
 477         if ((rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, 0)) != 0)
 478                 goto out;
 479 
 480         for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL;
 481             nvp = nvlist_next_nvpair(shrlist, nvp)) {
 482                 if (nvpair_type(nvp) != DATA_TYPE_NVLIST)
 483                         continue;
 484 
 485                 shrname = nvpair_name(nvp);
 486                 ASSERT(shrname);
 487 
 488                 if ((rc = smb_kshare_unexport(sv, shrname)) != 0)
 489                         continue;
 490 
 491                 ux = kmem_cache_alloc(smb_kshare_cache_unexport, KM_SLEEP);
 492                 (void) strlcpy(ux->us_sharename, shrname, MAXNAMELEN);
 493 
 494                 smb_slist_insert_tail(&sv->sv_export.e_unexport_list, ux);
 495                 unexport = B_TRUE;
 496         }
 497 
 498         if (unexport)
 499                 smb_thread_signal(&sv->sv_export.e_unexport_thread);
 500         rc = 0;
 501 
 502 out:
 503         nvlist_free(shrlist);
 504         smb_server_release(sv);
 505         return (rc);
 506 }
 507 
 508 /*
 509  * Get properties (currently only shortname enablement)
 510  * of specified share.
 511  */
 512 int
 513 smb_kshare_info(smb_ioc_shareinfo_t *ioc)
 514 {
 515         ioc->shortnames = smb_shortnames;
 516         return (0);
 517 }
 518 
 519 /*
 520  * This function builds a response for a NetShareEnum RAP request.
 521  * List of shares is scanned twice. In the first round the total number
 522  * of shares which their OEM name is shorter than 13 chars (esi->es_ntotal)
 523  * and also the number of shares that fit in the given buffer are calculated.
 524  * In the second round the shares data are encoded in the buffer.
 525  *
 526  * The data associated with each share has two parts, a fixed size part and
 527  * a variable size part which is share's comment. The outline of the response
 528  * buffer is so that fixed part for all the shares will appear first and follows
 529  * with the comments for all those shares and that's why the data cannot be
 530  * encoded in one round without unnecessarily complicating the code.
 531  */
 532 void
 533 smb_kshare_enum(smb_server_t *sv, smb_enumshare_info_t *esi)
 534 {
 535         smb_avl_t *share_avl;
 536         smb_avl_cursor_t cursor;
 537         smb_kshare_t *shr;
 538         int remained;
 539         uint16_t infolen = 0;
 540         uint16_t cmntlen = 0;
 541         uint16_t sharelen;
 542         uint16_t clen;
 543         uint32_t cmnt_offs;
 544         smb_msgbuf_t info_mb;
 545         smb_msgbuf_t cmnt_mb;
 546         boolean_t autohome_added = B_FALSE;
 547 
 548         if (!smb_export_isready(sv)) {
 549                 esi->es_ntotal = esi->es_nsent = 0;
 550                 esi->es_datasize = 0;
 551                 return;
 552         }
 553 
 554         esi->es_ntotal = esi->es_nsent = 0;
 555         remained = esi->es_bufsize;
 556         share_avl = &sv->sv_export.e_share_avl;
 557 
 558         /* Do the necessary calculations in the first round */
 559         smb_avl_iterinit(share_avl, &cursor);
 560 
 561         while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) {
 562                 if (shr->shr_oemname == NULL) {
 563                         smb_avl_release(share_avl, shr);
 564                         continue;
 565                 }
 566 
 567                 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) {
 568                         if (esi->es_posix_uid == shr->shr_uid) {
 569                                 autohome_added = B_TRUE;
 570                         } else {
 571                                 smb_avl_release(share_avl, shr);
 572                                 continue;
 573                         }
 574                 }
 575 
 576                 esi->es_ntotal++;
 577 
 578                 if (remained <= 0) {
 579                         smb_avl_release(share_avl, shr);
 580                         continue;
 581                 }
 582 
 583                 clen = strlen(shr->shr_cmnt) + 1;
 584                 sharelen = SHARE_INFO_1_SIZE + clen;
 585 
 586                 if (sharelen <= remained) {
 587                         infolen += SHARE_INFO_1_SIZE;
 588                         cmntlen += clen;
 589                 }
 590 
 591                 remained -= sharelen;
 592                 smb_avl_release(share_avl, shr);
 593         }
 594 
 595         esi->es_datasize = infolen + cmntlen;
 596 
 597         smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0);
 598         smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0);
 599         cmnt_offs = infolen;
 600 
 601         /* Encode the data in the second round */
 602         smb_avl_iterinit(share_avl, &cursor);
 603         autohome_added = B_FALSE;
 604 
 605         while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) {
 606                 if (shr->shr_oemname == NULL) {
 607                         smb_avl_release(share_avl, shr);
 608                         continue;
 609                 }
 610 
 611                 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) {
 612                         if (esi->es_posix_uid == shr->shr_uid) {
 613                                 autohome_added = B_TRUE;
 614                         } else {
 615                                 smb_avl_release(share_avl, shr);
 616                                 continue;
 617                         }
 618                 }
 619 
 620                 if (smb_msgbuf_encode(&info_mb, "13c.wl",
 621                     shr->shr_oemname, shr->shr_type, cmnt_offs) < 0) {
 622                         smb_avl_release(share_avl, shr);
 623                         break;
 624                 }
 625 
 626                 if (smb_msgbuf_encode(&cmnt_mb, "s", shr->shr_cmnt) < 0) {
 627                         smb_avl_release(share_avl, shr);
 628                         break;
 629                 }
 630 
 631                 cmnt_offs += strlen(shr->shr_cmnt) + 1;
 632                 esi->es_nsent++;
 633 
 634                 smb_avl_release(share_avl, shr);
 635         }
 636 
 637         smb_msgbuf_term(&info_mb);
 638         smb_msgbuf_term(&cmnt_mb);
 639 }
 640 
 641 /*
 642  * Looks up the given share and returns a pointer
 643  * to its definition if it's found. A hold on the
 644  * object is taken before the pointer is returned
 645  * in which case the caller MUST always call
 646  * smb_kshare_release().
 647  */
 648 smb_kshare_t *
 649 smb_kshare_lookup(smb_server_t *sv, const char *shrname)
 650 {
 651         smb_kshare_t key;
 652         smb_kshare_t *shr;
 653 
 654         ASSERT(shrname);
 655 
 656         if (!smb_export_isready(sv))
 657                 return (NULL);
 658 
 659         key.shr_name = (char *)shrname;
 660         shr = smb_avl_lookup(&sv->sv_export.e_share_avl, &key);
 661         return (shr);
 662 }
 663 
 664 /*
 665  * Releases the hold taken on the specified share object
 666  */
 667 void
 668 smb_kshare_release(smb_server_t *sv, smb_kshare_t *shr)
 669 {
 670         ASSERT(shr);
 671         ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
 672 
 673         smb_avl_release(&sv->sv_export.e_share_avl, shr);
 674 }
 675 
 676 /*
 677  * Add the given share in the specified server.
 678  * If the share is a disk share, lookup the share path
 679  * and hold the smb_node_t for the share root.
 680  *
 681  * If the share is an Autohome share and it is
 682  * already in the AVL only a reference count for
 683  * that share is incremented.
 684  */
 685 static int
 686 smb_kshare_export(smb_server_t *sv, smb_kshare_t *shr)
 687 {
 688         smb_avl_t       *share_avl;
 689         smb_kshare_t    *auto_shr;
 690         smb_node_t      *snode = NULL;
 691         int             rc = 0;
 692 
 693         share_avl = &sv->sv_export.e_share_avl;
 694 
 695         if (!STYPE_ISDSK(shr->shr_type)) {
 696                 if ((rc = smb_avl_add(share_avl, shr)) != 0) {
 697                         cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
 698                             shr->shr_name, rc);
 699                 }
 700 
 701                 return (rc);
 702         }
 703 
 704         if ((auto_shr = smb_avl_lookup(share_avl, shr)) != NULL) {
 705                 rc = EEXIST;
 706                 if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
 707                         mutex_enter(&auto_shr->shr_mutex);
 708                         auto_shr->shr_autocnt++;
 709                         mutex_exit(&auto_shr->shr_mutex);
 710                         rc = 0;
 711                 }
 712                 smb_avl_release(share_avl, auto_shr);
 713                 return (rc);
 714         }
 715 
 716         /*
 717          * Get the root smb_node_t for this share, held.
 718          * This hold is normally released during AVL destroy,
 719          * via the element destructor:  smb_kshare_destroy
 720          */
 721         rc = smb_server_share_lookup(sv, shr->shr_path, &snode);
 722         if (rc != 0) {
 723                 cmn_err(CE_WARN, "export[%s(%s)]: lookup failed (%d)",
 724                     shr->shr_name, shr->shr_path, rc);
 725                 return (rc);
 726         }
 727 
 728         shr->shr_root_node = snode;
 729         if ((rc = smb_avl_add(share_avl, shr)) != 0) {
 730                 cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
 731                     shr->shr_name, rc);
 732                 shr->shr_root_node = NULL;
 733                 smb_node_release(snode);
 734                 return (rc);
 735         }
 736 
 737         kshare_stats_init(sv, shr);
 738 
 739         /*
 740          * For CA shares, find or create the CA handle dir,
 741          * and (if restarted) import persistent handles.
 742          */
 743         if ((shr->shr_flags & SMB_SHRF_CA) != 0) {
 744                 rc = smb2_dh_new_ca_share(sv, shr);
 745                 if (rc != 0) {
 746                         /* Just make it a non-CA share. */
 747                         mutex_enter(&shr->shr_mutex);
 748                         shr->shr_flags &= ~SMB_SHRF_CA;
 749                         mutex_exit(&shr->shr_mutex);
 750                         rc = 0;
 751                 }
 752         }
 753 
 754         return (rc);
 755 }
 756 
 757 
 758 /*
 759  * Following a pattern somewhat similar to smb_server_kstat_init,
 760  * but organized a little differently.
 761  */
 762 void
 763 kshare_stats_init(smb_server_t *sv, smb_kshare_t *ks)
 764 {
 765         static const char       *kr_names[] = SMBSRV_CLSH__NAMES;
 766         char                    ks_name[KSTAT_STRLEN];
 767         smbsrv_clsh_kstats_t    *ksr;
 768         int                     idx;
 769         smb_named_stats_t       *smbnsp;
 770         kstat_t                 *kstat = NULL;
 771         int                     namelen;
 772 
 773         /*
 774          * Most share names are short, and we'd like to allow consumers like
 775          * the smbstat command to compose the kstat names for short share names
 776          * directly.  In the (rare) case where we have longer share names, we
 777          * need an indirection scheme to get around the limited (31 chars) size
 778          * of kstat names. So for share names 24 chars or shorter, we compose
 779          * the kstat name directly as "smbsrv:0:sh/sharename" and when the share
 780          * name is longer, compose the kstat name using an arbitrary
 781          * (but unique) identifier like: "smbsrv:0:sh/:ffffff0009560a98".  To
 782          * find the unique identifier given a (long) share name, the consumer
 783          * has to enumerate the (fake) "smbsrvshr" kstat module, looking for the
 784          * kstat with the sharename element matching the one they want.  Both
 785          * direct and indirect names are instantiated under the "smbsrvshr"
 786          * module, so a consumer that wants all the share kstats could always
 787          * lookup the kstat names using the indirection scheme if that's easier.
 788          * (Nothing forces the consumer to directly compose kstat names when the
 789          * share name happens to be short -- they can always enumerate to find
 790          * it.)
 791          *
 792          * SMB share names are not allowed to contain a colon.  The naming
 793          * scheme here uses a colon at the beginning of what would otherwise be
 794          * the share name part of the kstat name to indicate that this name uses
 795          * the "indirection" scheme.  With indirection, the part after the colon
 796          * is an arbitrary (but unique per share) identifier of some other
 797          * kstat, and a consumer needs to fetch that kstat to get the real share
 798          * name.
 799          */
 800         namelen = strlen(ks->shr_name);
 801         if (namelen <= 24) {
 802                 (void) snprintf(ks_name, sizeof (ks_name), "sh/%s",
 803                     ks->shr_name);
 804 
 805                 kstat = kstat_hold_byname("smbsrvshr", 0, ks_name, sv->sv_zid);
 806         }
 807 
 808         if (namelen > 24 || kstat != NULL) {
 809                 (void) snprintf(ks_name, sizeof (ks_name), "sh/:%p",
 810                     (void *)ks);
 811 
 812                 if (kstat != NULL)
 813                         kstat_rele(kstat);
 814         }
 815 
 816         ks->shr_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
 817             ks_name, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
 818             sizeof (smbsrv_clsh_kstats_t), 0, sv->sv_zid);
 819 
 820         if (ks->shr_ksp == NULL)
 821                 return;
 822 
 823         ks->stats.ksns = kstat_create_zone("smbsrvshr", 0,
 824             ks_name, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
 825             0, KSTAT_FLAG_VIRTUAL, sv->sv_zid);
 826 
 827         if (ks->stats.ksns == NULL) {
 828                 kstat_delete(ks->shr_ksp);
 829                 ks->shr_ksp = NULL;
 830                 return;
 831         }
 832 
 833         ks->shr_ksp->ks_update = smb_kshare_kstat_update;
 834         ks->shr_ksp->ks_private = ks;
 835 
 836         /*
 837          * In-line equivalent of smb_dispatch_stats_init
 838          */
 839         ksr = (smbsrv_clsh_kstats_t *)ks->shr_ksp->ks_data;
 840         for (idx = 0; idx < SMBSRV_CLSH__NREQ; idx++) {
 841                 smb_latency_init(&ks->shr_stats[idx].sdt_lat);
 842                 (void) strlcpy(ksr->ks_clsh[idx].kr_name, kr_names[idx],
 843                     KSTAT_STRLEN);
 844         }
 845 
 846         /*
 847          * SMB named kstats setup for > KSTAT_STRLEN name to short name mapping.
 848          */
 849         smbnsp = &ks->stats.ks_data;
 850         ks->stats.ksns->ks_data = &ks->stats.ks_data;
 851         ks->stats.ksns->ks_data_size = sizeof (ks->stats.ks_data);
 852         ks->stats.ksns->ks_ndata = 1;
 853         kstat_named_init(smbnsp->kn, "share name",
 854             KSTAT_DATA_STRING);
 855         ks->stats.ksns->ks_update = smb_named_kstat_update;
 856         ks->stats.ksns->ks_private = (void *)ks;
 857 
 858         kstat_install(ks->shr_ksp);
 859         kstat_install(ks->stats.ksns);
 860 }
 861 
 862 void
 863 kshare_stats_fini(smb_kshare_t *ks)
 864 {
 865         int idx;
 866 
 867         for (idx = 0; idx < SMBSRV_CLSH__NREQ; idx++)
 868                 smb_latency_destroy(&ks->shr_stats[idx].sdt_lat);
 869 }
 870 
 871 static int
 872 smb_named_kstat_update(kstat_t *ks, int rw)
 873 {
 874         smb_kshare_t            *smbksp = (smb_kshare_t *)ks->ks_private;
 875         smb_named_stats_t       *smbnsp = &smbksp->stats.ks_data;
 876 
 877         if (rw == KSTAT_READ) {
 878                 (void) strlcpy(smbnsp->name, smbksp->shr_name,
 879                     sizeof (smbnsp->name));
 880 
 881                 kstat_named_setstr(&smbnsp->kn[0],
 882                     (const char *)smbksp->shr_name);
 883         }
 884         return (0);
 885 }
 886 
 887 /*
 888  * Update the kstat data from our private stats.
 889  */
 890 static int
 891 smb_kshare_kstat_update(kstat_t *ksp, int rw)
 892 {
 893         smb_kshare_t *kshare;
 894         smb_disp_stats_t *sds;
 895         smbsrv_clsh_kstats_t    *clsh;
 896         smb_kstat_req_t *ksr;
 897         int i;
 898 
 899         if (rw == KSTAT_WRITE)
 900                 return (EACCES);
 901 
 902         kshare = ksp->ks_private;
 903         ASSERT(kshare->shr_magic == SMB_SHARE_MAGIC);
 904         sds = kshare->shr_stats;
 905 
 906         clsh = (smbsrv_clsh_kstats_t *)ksp->ks_data;
 907         ksr = clsh->ks_clsh;
 908 
 909         for (i = 0; i < SMBSRV_CLSH__NREQ; i++, ksr++, sds++) {
 910                 ksr->kr_rxb = sds->sdt_rxb;
 911                 ksr->kr_txb = sds->sdt_txb;
 912                 mutex_enter(&sds->sdt_lat.ly_mutex);
 913                 ksr->kr_nreq = sds->sdt_lat.ly_a_nreq;
 914                 ksr->kr_sum = sds->sdt_lat.ly_a_sum;
 915                 ksr->kr_a_mean = sds->sdt_lat.ly_a_mean;
 916                 ksr->kr_a_stddev = sds->sdt_lat.ly_a_stddev;
 917                 ksr->kr_d_mean = sds->sdt_lat.ly_d_mean;
 918                 ksr->kr_d_stddev = sds->sdt_lat.ly_d_stddev;
 919                 sds->sdt_lat.ly_d_mean = 0;
 920                 sds->sdt_lat.ly_d_nreq = 0;
 921                 sds->sdt_lat.ly_d_stddev = 0;
 922                 sds->sdt_lat.ly_d_sum = 0;
 923                 mutex_exit(&sds->sdt_lat.ly_mutex);
 924         }
 925 
 926         return (0);
 927 }
 928 
 929 /*
 930  * Removes the share specified by 'shrname' from the AVL
 931  * tree of the given server if it's there.
 932  *
 933  * If the share is an Autohome share, the autohome count
 934  * is decremented and the share is only removed if the
 935  * count goes to zero.
 936  *
 937  * If the share is a disk share, the hold on the corresponding
 938  * file system is released before removing the share from
 939  * the AVL tree.
 940  */
 941 static int
 942 smb_kshare_unexport(smb_server_t *sv, const char *shrname)
 943 {
 944         smb_avl_t       *share_avl;
 945         smb_kshare_t    key;
 946         smb_kshare_t    *shr;
 947         boolean_t       auto_unexport;
 948 
 949         share_avl = &sv->sv_export.e_share_avl;
 950 
 951         key.shr_name = (char *)shrname;
 952         if ((shr = smb_avl_lookup(share_avl, &key)) == NULL)
 953                 return (ENOENT);
 954 
 955         if ((shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
 956                 mutex_enter(&shr->shr_mutex);
 957                 shr->shr_autocnt--;
 958                 auto_unexport = (shr->shr_autocnt == 0);
 959                 mutex_exit(&shr->shr_mutex);
 960                 if (!auto_unexport) {
 961                         smb_avl_release(share_avl, shr);
 962                         return (0);
 963                 }
 964         }
 965 
 966         smb_avl_remove(share_avl, shr);
 967 
 968         mutex_enter(&shr->shr_mutex);
 969         shr->shr_flags |= SMB_SHRF_REMOVED;
 970         mutex_exit(&shr->shr_mutex);
 971 
 972         smb_avl_release(share_avl, shr);
 973 
 974         return (0);
 975 }
 976 
 977 /*
 978  * Exports IPC$ or Admin shares
 979  */
 980 static int
 981 smb_kshare_export_trans(smb_server_t *sv, char *name, char *path, char *cmnt)
 982 {
 983         smb_kshare_t *shr;
 984 
 985         ASSERT(name);
 986         ASSERT(path);
 987 
 988         shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
 989         bzero(shr, sizeof (smb_kshare_t));
 990 
 991         shr->shr_magic = SMB_SHARE_MAGIC;
 992         shr->shr_refcnt = 1;
 993         shr->shr_flags = SMB_SHRF_TRANS | smb_kshare_is_admin(shr->shr_name);
 994         if (strcasecmp(name, "IPC$") == 0)
 995                 shr->shr_type = STYPE_IPC;
 996         else
 997                 shr->shr_type = STYPE_DISKTREE;
 998 
 999         shr->shr_type |= smb_kshare_is_special(shr->shr_name);
1000 
1001         shr->shr_name = smb_mem_strdup(name);
1002         if (path)
1003                 shr->shr_path = smb_mem_strdup(path);
1004         if (cmnt)
1005                 shr->shr_cmnt = smb_mem_strdup(cmnt);
1006         shr->shr_oemname = smb_kshare_oemname(name);
1007 
1008         return (smb_kshare_export(sv, shr));
1009 }
1010 
1011 /*
1012  * Decodes share information in an nvlist format into a smb_kshare_t
1013  * structure.
1014  *
1015  * This is a temporary function and will be replaced by functions
1016  * provided by libsharev2 code after it's available.
1017  */
1018 static smb_kshare_t *
1019 smb_kshare_decode(nvlist_t *share)
1020 {
1021         smb_kshare_t tmp;
1022         smb_kshare_t *shr;
1023         nvlist_t *smb;
1024         char *csc_name = NULL, *strbuf = NULL;
1025         int rc;
1026 
1027         ASSERT(share);
1028 
1029         bzero(&tmp, sizeof (smb_kshare_t));
1030 
1031         rc = nvlist_lookup_string(share, "name", &tmp.shr_name);
1032         rc |= nvlist_lookup_string(share, "path", &tmp.shr_path);
1033         (void) nvlist_lookup_string(share, "desc", &tmp.shr_cmnt);
1034 
1035         ASSERT(tmp.shr_name && tmp.shr_path);
1036 
1037         rc |= nvlist_lookup_nvlist(share, "smb", &smb);
1038         if (rc != 0) {
1039                 cmn_err(CE_WARN, "kshare: failed looking up SMB properties"
1040                     " (%d)", rc);
1041                 return (NULL);
1042         }
1043 
1044         rc = nvlist_lookup_uint32(smb, "type", &tmp.shr_type);
1045         if (rc != 0) {
1046                 cmn_err(CE_WARN, "kshare[%s]: failed getting the share type"
1047                     " (%d)", tmp.shr_name, rc);
1048                 return (NULL);
1049         }
1050 
1051         (void) nvlist_lookup_string(smb, SHOPT_AD_CONTAINER,
1052             &tmp.shr_container);
1053         (void) nvlist_lookup_string(smb, SHOPT_NONE, &tmp.shr_access_none);
1054         (void) nvlist_lookup_string(smb, SHOPT_RO, &tmp.shr_access_ro);
1055         (void) nvlist_lookup_string(smb, SHOPT_RW, &tmp.shr_access_rw);
1056 
1057         tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_ABE, SMB_SHRF_ABE);
1058         tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CATIA,
1059             SMB_SHRF_CATIA);
1060         tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_GUEST,
1061             SMB_SHRF_GUEST_OK);
1062         tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT,
1063             SMB_SHRF_DFSROOT);
1064         tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_QUOTAS,
1065             SMB_SHRF_QUOTAS);
1066         tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CA, SMB_SHRF_CA);
1067         tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_FSO, SMB_SHRF_FSO);
1068         tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_AUTOHOME,
1069             SMB_SHRF_AUTOHOME);
1070 
1071         if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) {
1072                 rc = nvlist_lookup_uint32(smb, "uid", &tmp.shr_uid);
1073                 rc |= nvlist_lookup_uint32(smb, "gid", &tmp.shr_gid);
1074                 if (rc != 0) {
1075                         cmn_err(CE_WARN, "kshare: failed looking up uid/gid"
1076                             " (%d)", rc);
1077                         return (NULL);
1078                 }
1079         }
1080 
1081         (void) nvlist_lookup_string(smb, SHOPT_ENCRYPT, &strbuf);
1082         smb_cfg_set_require(strbuf, &tmp.shr_encrypt);
1083 
1084         (void) nvlist_lookup_string(smb, SHOPT_CSC, &csc_name);
1085         smb_kshare_csc_flags(&tmp, csc_name);
1086 
1087         shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
1088         bzero(shr, sizeof (smb_kshare_t));
1089 
1090         shr->shr_magic = SMB_SHARE_MAGIC;
1091         shr->shr_refcnt = 1;
1092 
1093         shr->shr_name = smb_mem_strdup(tmp.shr_name);
1094         shr->shr_path = smb_mem_strdup(tmp.shr_path);
1095         if (tmp.shr_cmnt)
1096                 shr->shr_cmnt = smb_mem_strdup(tmp.shr_cmnt);
1097         if (tmp.shr_container)
1098                 shr->shr_container = smb_mem_strdup(tmp.shr_container);
1099         if (tmp.shr_access_none)
1100                 shr->shr_access_none = smb_mem_strdup(tmp.shr_access_none);
1101         if (tmp.shr_access_ro)
1102                 shr->shr_access_ro = smb_mem_strdup(tmp.shr_access_ro);
1103         if (tmp.shr_access_rw)
1104                 shr->shr_access_rw = smb_mem_strdup(tmp.shr_access_rw);
1105 
1106         shr->shr_oemname = smb_kshare_oemname(shr->shr_name);
1107         shr->shr_flags = tmp.shr_flags | smb_kshare_is_admin(shr->shr_name);
1108         shr->shr_type = tmp.shr_type | smb_kshare_is_special(shr->shr_name);
1109         shr->shr_encrypt = tmp.shr_encrypt;
1110 
1111         shr->shr_uid = tmp.shr_uid;
1112         shr->shr_gid = tmp.shr_gid;
1113 
1114         if ((shr->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME)
1115                 shr->shr_autocnt = 1;
1116         return (shr);
1117 }
1118 
1119 #if 0
1120 static void
1121 smb_kshare_log(smb_kshare_t *shr)
1122 {
1123         cmn_err(CE_NOTE, "Share info:");
1124         cmn_err(CE_NOTE, "\tname: %s", (shr->shr_name) ? shr->shr_name : "");
1125         cmn_err(CE_NOTE, "\tpath: %s", (shr->shr_path) ? shr->shr_path : "");
1126         cmn_err(CE_NOTE, "\tcmnt: (%s)",
1127             (shr->shr_cmnt) ? shr->shr_cmnt : "NULL");
1128         cmn_err(CE_NOTE, "\toemname: (%s)",
1129             (shr->shr_oemname) ? shr->shr_oemname : "NULL");
1130         cmn_err(CE_NOTE, "\tflags: %X", shr->shr_flags);
1131         cmn_err(CE_NOTE, "\ttype: %d", shr->shr_type);
1132 }
1133 #endif
1134 
1135 /*
1136  * Compare function used by shares AVL
1137  */
1138 static int
1139 smb_kshare_cmp(const void *p1, const void *p2)
1140 {
1141         smb_kshare_t *shr1 = (smb_kshare_t *)p1;
1142         smb_kshare_t *shr2 = (smb_kshare_t *)p2;
1143         int rc;
1144 
1145         ASSERT(shr1);
1146         ASSERT(shr1->shr_name);
1147 
1148         ASSERT(shr2);
1149         ASSERT(shr2->shr_name);
1150 
1151         rc = smb_strcasecmp(shr1->shr_name, shr2->shr_name, 0);
1152 
1153         if (rc < 0)
1154                 return (-1);
1155 
1156         if (rc > 0)
1157                 return (1);
1158 
1159         return (0);
1160 }
1161 
1162 /*
1163  * This function is called by smb_avl routines whenever
1164  * there is a need to take a hold on a share structure
1165  * inside AVL
1166  */
1167 static void
1168 smb_kshare_hold(const void *p)
1169 {
1170         smb_kshare_t *shr = (smb_kshare_t *)p;
1171 
1172         ASSERT(shr);
1173         ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
1174 
1175         mutex_enter(&shr->shr_mutex);
1176         shr->shr_refcnt++;
1177         mutex_exit(&shr->shr_mutex);
1178 }
1179 
1180 /*
1181  * This function must be called by smb_avl routines whenever
1182  * smb_kshare_hold is called and the hold needs to be released.
1183  */
1184 static boolean_t
1185 smb_kshare_rele(const void *p)
1186 {
1187         smb_kshare_t *shr = (smb_kshare_t *)p;
1188         boolean_t destroy;
1189 
1190         ASSERT(shr);
1191         ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
1192 
1193         mutex_enter(&shr->shr_mutex);
1194         ASSERT(shr->shr_refcnt > 0);
1195         shr->shr_refcnt--;
1196         destroy = (shr->shr_refcnt == 0);
1197         mutex_exit(&shr->shr_mutex);
1198 
1199         return (destroy);
1200 }
1201 
1202 /*
1203  * Frees all the memory allocated for the given
1204  * share structure. It also removes the structure
1205  * from the share cache.
1206  */
1207 static void
1208 smb_kshare_destroy(void *p)
1209 {
1210         smb_kshare_t *shr = (smb_kshare_t *)p;
1211 
1212         ASSERT(shr);
1213         ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
1214 
1215         if (shr->shr_ksp != NULL) {
1216                 kstat_delete(shr->shr_ksp);
1217                 shr->shr_ksp = NULL;
1218                 kshare_stats_fini(shr);
1219         }
1220 
1221         if (shr->stats.ksns != NULL) {
1222                 kstat_delete(shr->stats.ksns);
1223         }
1224 
1225         if (shr->shr_ca_dir != NULL)
1226                 smb_node_release(shr->shr_ca_dir);
1227         if (shr->shr_root_node)
1228                 smb_node_release(shr->shr_root_node);
1229 
1230         smb_mem_free(shr->shr_name);
1231         smb_mem_free(shr->shr_path);
1232         smb_mem_free(shr->shr_cmnt);
1233         smb_mem_free(shr->shr_container);
1234         smb_mem_free(shr->shr_oemname);
1235         smb_mem_free(shr->shr_access_none);
1236         smb_mem_free(shr->shr_access_ro);
1237         smb_mem_free(shr->shr_access_rw);
1238 
1239         kmem_cache_free(smb_kshare_cache_share, shr);
1240 }
1241 
1242 
1243 /*
1244  * Generate an OEM name for the given share name.  If the name is
1245  * shorter than 13 bytes the oemname will be returned; otherwise NULL
1246  * is returned.
1247  */
1248 static char *
1249 smb_kshare_oemname(const char *shrname)
1250 {
1251         smb_wchar_t *unibuf;
1252         char *oem_name;
1253         int length;
1254 
1255         length = strlen(shrname) + 1;
1256 
1257         oem_name = smb_mem_alloc(length);
1258         unibuf = smb_mem_alloc(length * sizeof (smb_wchar_t));
1259 
1260         (void) smb_mbstowcs(unibuf, shrname, length);
1261 
1262         if (ucstooem(oem_name, unibuf, length, OEM_CPG_850) == 0)
1263                 (void) strcpy(oem_name, shrname);
1264 
1265         smb_mem_free(unibuf);
1266 
1267         if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) {
1268                 smb_mem_free(oem_name);
1269                 return (NULL);
1270         }
1271 
1272         return (oem_name);
1273 }
1274 
1275 /*
1276  * Special share reserved for interprocess communication (IPC$) or
1277  * remote administration of the server (ADMIN$). Can also refer to
1278  * administrative shares such as C$, D$, E$, and so forth.
1279  */
1280 static int
1281 smb_kshare_is_special(const char *sharename)
1282 {
1283         int len;
1284 
1285         if (sharename == NULL)
1286                 return (0);
1287 
1288         if ((len = strlen(sharename)) == 0)
1289                 return (0);
1290 
1291         if (sharename[len - 1] == '$')
1292                 return (STYPE_SPECIAL);
1293 
1294         return (0);
1295 }
1296 
1297 /*
1298  * Check whether or not this is a default admin share: C$, D$ etc.
1299  */
1300 static boolean_t
1301 smb_kshare_is_admin(const char *sharename)
1302 {
1303         if (sharename == NULL)
1304                 return (B_FALSE);
1305 
1306         if (strlen(sharename) == 2 &&
1307             smb_isalpha(sharename[0]) && sharename[1] == '$') {
1308                 return (B_TRUE);
1309         }
1310 
1311         return (B_FALSE);
1312 }
1313 
1314 /*
1315  * Decodes the given boolean share option.
1316  * If the option is present in the nvlist and it's value is true
1317  * returns the corresponding flag value, otherwise returns 0.
1318  */
1319 static uint32_t
1320 smb_kshare_decode_bool(nvlist_t *nvl, const char *propname, uint32_t flag)
1321 {
1322         char *boolp;
1323 
1324         if (nvlist_lookup_string(nvl, propname, &boolp) == 0)
1325                 if (strcasecmp(boolp, "true") == 0)
1326                         return (flag);
1327 
1328         return (0);
1329 }
1330 
1331 /*
1332  * Map a client-side caching (CSC) option to the appropriate share
1333  * flag.  Only one option is allowed; an error will be logged if
1334  * multiple options have been specified.  We don't need to do anything
1335  * about multiple values here because the SRVSVC will not recognize
1336  * a value containing multiple flags and will return the default value.
1337  *
1338  * If the option value is not recognized, it will be ignored: invalid
1339  * values will typically be caught and rejected by sharemgr.
1340  */
1341 static void
1342 smb_kshare_csc_flags(smb_kshare_t *shr, const char *value)
1343 {
1344         int i;
1345         static struct {
1346                 char *value;
1347                 uint32_t flag;
1348         } cscopt[] = {
1349                 { "disabled",   SMB_SHRF_CSC_DISABLED },
1350                 { "manual",     SMB_SHRF_CSC_MANUAL },
1351                 { "auto",       SMB_SHRF_CSC_AUTO },
1352                 { "vdo",        SMB_SHRF_CSC_VDO }
1353         };
1354 
1355         if (value == NULL)
1356                 return;
1357 
1358         for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1359                 if (strcasecmp(value, cscopt[i].value) == 0) {
1360                         shr->shr_flags |= cscopt[i].flag;
1361                         break;
1362                 }
1363         }
1364 
1365         switch (shr->shr_flags & SMB_SHRF_CSC_MASK) {
1366         case 0:
1367         case SMB_SHRF_CSC_DISABLED:
1368         case SMB_SHRF_CSC_MANUAL:
1369         case SMB_SHRF_CSC_AUTO:
1370         case SMB_SHRF_CSC_VDO:
1371                 break;
1372 
1373         default:
1374                 cmn_err(CE_NOTE, "csc option conflict: 0x%08x",
1375                     shr->shr_flags & SMB_SHRF_CSC_MASK);
1376                 break;
1377         }
1378 }
1379 
1380 /*
1381  * This function processes the unexport event list and disconnects shares
1382  * asynchronously.  The function executes as a zone-specific thread.
1383  *
1384  * The server arg passed in is safe to use without a reference count, because
1385  * the server cannot be deleted until smb_thread_stop()/destroy() return,
1386  * which is also when the thread exits.
1387  */
1388 /*ARGSUSED*/
1389 static void
1390 smb_kshare_unexport_thread(smb_thread_t *thread, void *arg)
1391 {
1392         smb_server_t    *sv = arg;
1393         smb_unshare_t   *ux;
1394 
1395         while (smb_thread_continue(thread)) {
1396                 while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list))
1397                     != NULL) {
1398                         smb_slist_remove(&sv->sv_export.e_unexport_list, ux);
1399                         (void) smb_server_unshare(ux->us_sharename);
1400                         kmem_cache_free(smb_kshare_cache_unexport, ux);
1401                 }
1402         }
1403 }
1404 
1405 static boolean_t
1406 smb_export_isready(smb_server_t *sv)
1407 {
1408         boolean_t ready;
1409 
1410         mutex_enter(&sv->sv_export.e_mutex);
1411         ready = sv->sv_export.e_ready;
1412         mutex_exit(&sv->sv_export.e_mutex);
1413 
1414         return (ready);
1415 }
1416 
1417 #ifdef  _KERNEL
1418 /*
1419  * Return 0 upon success. Otherwise > 0
1420  */
1421 static int
1422 smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx)
1423 {
1424         int status = smb_dr_get_int32(dec_ctx);
1425         int err;
1426 
1427         switch (status) {
1428         case SMB_SHARE_DSUCCESS:
1429                 return (0);
1430 
1431         case SMB_SHARE_DERROR:
1432                 err = smb_dr_get_uint32(dec_ctx);
1433                 cmn_err(CE_WARN, "%d: Encountered door server error %d",
1434                     opcode, err);
1435                 (void) smb_dr_decode_finish(dec_ctx);
1436                 return (err);
1437         }
1438 
1439         ASSERT(0);
1440         return (EINVAL);
1441 }
1442 #endif  /* _KERNEL */