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.
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.
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]
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 #include <smbsrv/smb_door.h>
28 #include <smbsrv/smb_kproto.h>
29 #include <smbsrv/smb_ktypes.h>
31 typedef struct smb_unshare
{
33 char us_sharename
[MAXNAMELEN
];
36 static kmem_cache_t
*smb_kshare_cache_share
;
37 static kmem_cache_t
*smb_kshare_cache_unexport
;
38 kmem_cache_t
*smb_kshare_cache_vfs
;
40 static int smb_kshare_cmp(const void *, const void *);
41 static void smb_kshare_hold(const void *);
42 static boolean_t
smb_kshare_rele(const void *);
43 static void smb_kshare_destroy(void *);
44 static char *smb_kshare_oemname(const char *);
45 static int smb_kshare_is_special(const char *);
46 static boolean_t
smb_kshare_is_admin(const char *);
47 static smb_kshare_t
*smb_kshare_decode(nvlist_t
*);
48 static uint32_t smb_kshare_decode_bool(nvlist_t
*, const char *, uint32_t);
49 static void smb_kshare_unexport_thread(smb_thread_t
*, void *);
50 static int smb_kshare_export(smb_server_t
*, smb_kshare_t
*);
51 static int smb_kshare_unexport(smb_server_t
*, const char *);
52 static int smb_kshare_export_trans(smb_server_t
*, char *, char *, char *);
53 static void smb_kshare_csc_flags(smb_kshare_t
*, const char *);
55 static boolean_t
smb_export_isready(smb_server_t
*);
58 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t
*);
61 static const smb_avl_nops_t smb_kshare_avlops
= {
70 * This function is not MultiThread safe. The caller has to make sure only one
71 * thread calls this function.
74 smb_kshare_door_init(int door_id
)
76 return (door_ki_lookup(door_id
));
80 * This function is not MultiThread safe. The caller has to make sure only one
81 * thread calls this function.
84 smb_kshare_door_fini(door_handle_t dhdl
)
91 * This is a special interface that will be utilized by ZFS to cause
92 * a share to be added/removed
94 * arg is either a smb_share_t or share_name from userspace.
95 * It will need to be copied into the kernel. It is smb_share_t
96 * for add operations and share_name for delete operations.
99 smb_kshare_upcall(door_handle_t dhdl
, void *arg
, boolean_t add_share
)
101 door_arg_t doorarg
= { 0 };
107 smb_dr_ctx_t
*dec_ctx
;
108 smb_dr_ctx_t
*enc_ctx
;
109 smb_share_t
*lmshare
= NULL
;
112 opcode
= (add_share
) ? SMB_SHROP_ADD
: SMB_SHROP_DELETE
;
114 buf
= kmem_alloc(SMB_SHARE_DSIZE
, KM_SLEEP
);
115 enc_ctx
= smb_dr_encode_start(buf
, SMB_SHARE_DSIZE
);
116 smb_dr_put_uint32(enc_ctx
, opcode
);
120 lmshare
= kmem_alloc(sizeof (smb_share_t
), KM_SLEEP
);
121 error
= xcopyin(arg
, lmshare
, sizeof (smb_share_t
));
123 kmem_free(lmshare
, sizeof (smb_share_t
));
124 kmem_free(buf
, SMB_SHARE_DSIZE
);
127 smb_dr_put_share(enc_ctx
, lmshare
);
130 case SMB_SHROP_DELETE
:
131 str
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
132 error
= copyinstr(arg
, str
, MAXPATHLEN
, NULL
);
134 kmem_free(str
, MAXPATHLEN
);
135 kmem_free(buf
, SMB_SHARE_DSIZE
);
138 smb_dr_put_string(enc_ctx
, str
);
139 kmem_free(str
, MAXPATHLEN
);
143 if ((error
= smb_dr_encode_finish(enc_ctx
, &used
)) != 0) {
144 kmem_free(buf
, SMB_SHARE_DSIZE
);
146 kmem_free(lmshare
, sizeof (smb_share_t
));
147 return (NERR_InternalError
);
150 doorarg
.data_ptr
= buf
;
151 doorarg
.data_size
= used
;
153 doorarg
.rsize
= SMB_SHARE_DSIZE
;
155 error
= door_ki_upcall_limited(dhdl
, &doorarg
, NULL
, SIZE_MAX
, 0);
158 kmem_free(buf
, SMB_SHARE_DSIZE
);
160 kmem_free(lmshare
, sizeof (smb_share_t
));
164 dec_ctx
= smb_dr_decode_start(doorarg
.data_ptr
, doorarg
.data_size
);
165 if (smb_kshare_chk_dsrv_status(opcode
, dec_ctx
) != 0) {
166 kmem_free(buf
, SMB_SHARE_DSIZE
);
168 kmem_free(lmshare
, sizeof (smb_share_t
));
169 return (NERR_InternalError
);
172 rc
= smb_dr_get_uint32(dec_ctx
);
173 if (opcode
== SMB_SHROP_ADD
)
174 smb_dr_get_share(dec_ctx
, lmshare
);
176 if (smb_dr_decode_finish(dec_ctx
))
177 rc
= NERR_InternalError
;
179 kmem_free(buf
, SMB_SHARE_DSIZE
);
181 kmem_free(lmshare
, sizeof (smb_share_t
));
183 return ((rc
== NERR_DuplicateShare
&& add_share
) ? 0 : rc
);
188 * Executes map and unmap command for shares.
191 smb_kshare_exec(smb_server_t
*sv
, smb_shr_execinfo_t
*execinfo
)
195 (void) smb_kdoor_upcall(sv
, SMB_DR_SHR_EXEC
,
196 execinfo
, smb_shr_execinfo_xdr
, &exec_rc
, xdr_int
);
202 * Obtains any host access restriction on the specified
203 * share for the given host (ipaddr) by calling smbd
206 smb_kshare_hostaccess(smb_kshare_t
*shr
, smb_session_t
*session
)
208 smb_shr_hostaccess_query_t req
;
209 smb_inaddr_t
*ipaddr
= &session
->ipaddr
;
210 uint32_t host_access
= SMB_SHRF_ACC_OPEN
;
211 uint32_t flag
= SMB_SHRF_ACC_OPEN
;
214 if (smb_inet_iszero(ipaddr
))
215 return (ACE_ALL_PERMS
);
217 if ((shr
->shr_access_none
== NULL
|| *shr
->shr_access_none
== '\0') &&
218 (shr
->shr_access_ro
== NULL
|| *shr
->shr_access_ro
== '\0') &&
219 (shr
->shr_access_rw
== NULL
|| *shr
->shr_access_rw
== '\0'))
220 return (ACE_ALL_PERMS
);
222 if (shr
->shr_access_none
!= NULL
)
223 flag
|= SMB_SHRF_ACC_NONE
;
224 if (shr
->shr_access_ro
!= NULL
)
225 flag
|= SMB_SHRF_ACC_RO
;
226 if (shr
->shr_access_rw
!= NULL
)
227 flag
|= SMB_SHRF_ACC_RW
;
229 req
.shq_none
= shr
->shr_access_none
;
230 req
.shq_ro
= shr
->shr_access_ro
;
231 req
.shq_rw
= shr
->shr_access_rw
;
233 req
.shq_ipaddr
= *ipaddr
;
235 (void) smb_kdoor_upcall(session
->s_server
, SMB_DR_SHR_HOSTACCESS
,
236 &req
, smb_shr_hostaccess_query_xdr
, &host_access
, xdr_uint32_t
);
238 switch (host_access
) {
239 case SMB_SHRF_ACC_RO
:
240 access
= ACE_ALL_PERMS
& ~ACE_ALL_WRITE_PERMS
;
242 case SMB_SHRF_ACC_OPEN
:
243 case SMB_SHRF_ACC_RW
:
244 access
= ACE_ALL_PERMS
;
246 case SMB_SHRF_ACC_NONE
:
255 * This function is called when smb_server_t is
256 * created which means smb/service is ready for
257 * exporting SMB shares
260 smb_export_start(smb_server_t
*sv
)
262 mutex_enter(&sv
->sv_export
.e_mutex
);
263 if (sv
->sv_export
.e_ready
) {
264 mutex_exit(&sv
->sv_export
.e_mutex
);
268 sv
->sv_export
.e_ready
= B_TRUE
;
269 mutex_exit(&sv
->sv_export
.e_mutex
);
271 smb_avl_create(&sv
->sv_export
.e_share_avl
, sizeof (smb_kshare_t
),
272 offsetof(smb_kshare_t
, shr_link
), &smb_kshare_avlops
);
274 (void) smb_kshare_export_trans(sv
, "IPC$", "IPC$", "Remote IPC");
275 (void) smb_kshare_export_trans(sv
, "c$", SMB_CVOL
, "Default Share");
276 (void) smb_kshare_export_trans(sv
, "vss$", SMB_VSS
, "VSS");
280 * This function is called when smb_server_t goes
281 * away which means SMB shares should not be made
282 * available to clients
285 smb_export_stop(smb_server_t
*sv
)
287 mutex_enter(&sv
->sv_export
.e_mutex
);
288 if (!sv
->sv_export
.e_ready
) {
289 mutex_exit(&sv
->sv_export
.e_mutex
);
292 sv
->sv_export
.e_ready
= B_FALSE
;
293 mutex_exit(&sv
->sv_export
.e_mutex
);
295 smb_avl_destroy(&sv
->sv_export
.e_share_avl
);
296 smb_vfs_rele_all(&sv
->sv_export
);
300 smb_kshare_g_init(void)
302 smb_kshare_cache_share
= kmem_cache_create("smb_share_cache",
303 sizeof (smb_kshare_t
), 8, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
305 smb_kshare_cache_unexport
= kmem_cache_create("smb_unexport_cache",
306 sizeof (smb_unshare_t
), 8, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
308 smb_kshare_cache_vfs
= kmem_cache_create("smb_vfs_cache",
309 sizeof (smb_vfs_t
), 8, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
313 smb_kshare_init(smb_server_t
*sv
)
316 smb_llist_constructor(&sv
->sv_export
.e_vfs_list
, sizeof (smb_vfs_t
),
317 offsetof(smb_vfs_t
, sv_lnd
));
319 smb_slist_constructor(&sv
->sv_export
.e_unexport_list
,
320 sizeof (smb_unshare_t
), offsetof(smb_unshare_t
, us_lnd
));
324 smb_kshare_start(smb_server_t
*sv
)
326 smb_thread_init(&sv
->sv_export
.e_unexport_thread
, "smb_thread_unexport",
327 smb_kshare_unexport_thread
, sv
, smbsrv_base_pri
);
329 return (smb_thread_start(&sv
->sv_export
.e_unexport_thread
));
333 smb_kshare_stop(smb_server_t
*sv
)
335 smb_thread_stop(&sv
->sv_export
.e_unexport_thread
);
336 smb_thread_destroy(&sv
->sv_export
.e_unexport_thread
);
340 smb_kshare_fini(smb_server_t
*sv
)
344 while ((ux
= list_head(&sv
->sv_export
.e_unexport_list
.sl_list
))
346 smb_slist_remove(&sv
->sv_export
.e_unexport_list
, ux
);
347 kmem_cache_free(smb_kshare_cache_unexport
, ux
);
349 smb_slist_destructor(&sv
->sv_export
.e_unexport_list
);
351 smb_vfs_rele_all(&sv
->sv_export
);
353 smb_llist_destructor(&sv
->sv_export
.e_vfs_list
);
357 smb_kshare_g_fini(void)
359 kmem_cache_destroy(smb_kshare_cache_unexport
);
360 kmem_cache_destroy(smb_kshare_cache_share
);
361 kmem_cache_destroy(smb_kshare_cache_vfs
);
365 * A list of shares in nvlist format can be sent down
366 * from userspace thourgh the IOCTL interface. The nvlist
367 * is unpacked here and all the shares in the list will
371 smb_kshare_export_list(smb_ioc_share_t
*ioc
)
373 smb_server_t
*sv
= NULL
;
374 nvlist_t
*shrlist
= NULL
;
381 if ((rc
= smb_server_lookup(&sv
)) != 0)
384 if (!smb_export_isready(sv
)) {
389 rc
= nvlist_unpack(ioc
->shr
, ioc
->shrlen
, &shrlist
, KM_SLEEP
);
393 for (nvp
= nvlist_next_nvpair(shrlist
, NULL
); nvp
!= NULL
;
394 nvp
= nvlist_next_nvpair(shrlist
, nvp
)) {
397 * Since this loop can run for a while we want to exit
398 * as soon as the server state is anything but RUNNING
399 * to allow shutdown to proceed.
401 if (sv
->sv_state
!= SMB_SERVER_STATE_RUNNING
)
404 if (nvpair_type(nvp
) != DATA_TYPE_NVLIST
)
407 shrname
= nvpair_name(nvp
);
410 if ((rc
= nvpair_value_nvlist(nvp
, &share
)) != 0) {
411 cmn_err(CE_WARN
, "export[%s]: failed accessing",
416 if ((shr
= smb_kshare_decode(share
)) == NULL
) {
417 cmn_err(CE_WARN
, "export[%s]: failed decoding",
422 /* smb_kshare_export consumes shr so it's not leaked */
423 if ((rc
= smb_kshare_export(sv
, shr
)) != 0) {
424 smb_kshare_destroy(shr
);
432 nvlist_free(shrlist
);
433 smb_server_release(sv
);
438 * This function is invoked when a share is disabled to disconnect trees
439 * and close files. Cleaning up may involve VOP and/or VFS calls, which
440 * may conflict/deadlock with stuck threads if something is amiss with the
441 * file system. Queueing the request for asynchronous processing allows the
442 * call to return immediately so that, if the unshare is being done in the
443 * context of a forced unmount, the forced unmount will always be able to
444 * proceed (unblocking stuck I/O and eventually allowing all blocked unshare
445 * processes to complete).
447 * The path lookup to find the root vnode of the VFS in question and the
448 * release of this vnode are done synchronously prior to any associated
449 * unmount. Doing these asynchronous to an associated unmount could run
450 * the risk of a spurious EBUSY for a standard unmount or an EIO during
451 * the path lookup due to a forced unmount finishing first.
454 smb_kshare_unexport_list(smb_ioc_share_t
*ioc
)
456 smb_server_t
*sv
= NULL
;
458 nvlist_t
*shrlist
= NULL
;
460 boolean_t unexport
= B_FALSE
;
464 if ((rc
= smb_server_lookup(&sv
)) != 0)
467 if ((rc
= nvlist_unpack(ioc
->shr
, ioc
->shrlen
, &shrlist
, 0)) != 0)
470 for (nvp
= nvlist_next_nvpair(shrlist
, NULL
); nvp
!= NULL
;
471 nvp
= nvlist_next_nvpair(shrlist
, nvp
)) {
472 if (nvpair_type(nvp
) != DATA_TYPE_NVLIST
)
475 shrname
= nvpair_name(nvp
);
478 if ((rc
= smb_kshare_unexport(sv
, shrname
)) != 0)
481 ux
= kmem_cache_alloc(smb_kshare_cache_unexport
, KM_SLEEP
);
482 (void) strlcpy(ux
->us_sharename
, shrname
, MAXNAMELEN
);
484 smb_slist_insert_tail(&sv
->sv_export
.e_unexport_list
, ux
);
489 smb_thread_signal(&sv
->sv_export
.e_unexport_thread
);
494 nvlist_free(shrlist
);
495 smb_server_release(sv
);
500 * Get properties (currently only shortname enablement)
501 * of specified share.
504 smb_kshare_info(smb_ioc_shareinfo_t
*ioc
)
506 ioc
->shortnames
= smb_shortnames
;
511 * This function builds a response for a NetShareEnum RAP request.
512 * List of shares is scanned twice. In the first round the total number
513 * of shares which their OEM name is shorter than 13 chars (esi->es_ntotal)
514 * and also the number of shares that fit in the given buffer are calculated.
515 * In the second round the shares data are encoded in the buffer.
517 * The data associated with each share has two parts, a fixed size part and
518 * a variable size part which is share's comment. The outline of the response
519 * buffer is so that fixed part for all the shares will appear first and follows
520 * with the comments for all those shares and that's why the data cannot be
521 * encoded in one round without unnecessarily complicating the code.
524 smb_kshare_enum(smb_server_t
*sv
, smb_enumshare_info_t
*esi
)
526 smb_avl_t
*share_avl
;
527 smb_avl_cursor_t cursor
;
530 uint16_t infolen
= 0;
531 uint16_t cmntlen
= 0;
535 smb_msgbuf_t info_mb
;
536 smb_msgbuf_t cmnt_mb
;
537 boolean_t autohome_added
= B_FALSE
;
539 if (!smb_export_isready(sv
)) {
540 esi
->es_ntotal
= esi
->es_nsent
= 0;
541 esi
->es_datasize
= 0;
545 esi
->es_ntotal
= esi
->es_nsent
= 0;
546 remained
= esi
->es_bufsize
;
547 share_avl
= &sv
->sv_export
.e_share_avl
;
549 /* Do the necessary calculations in the first round */
550 smb_avl_iterinit(share_avl
, &cursor
);
552 while ((shr
= smb_avl_iterate(share_avl
, &cursor
)) != NULL
) {
553 if (shr
->shr_oemname
== NULL
) {
554 smb_avl_release(share_avl
, shr
);
558 if ((shr
->shr_flags
& SMB_SHRF_AUTOHOME
) && !autohome_added
) {
559 if (esi
->es_posix_uid
== shr
->shr_uid
) {
560 autohome_added
= B_TRUE
;
562 smb_avl_release(share_avl
, shr
);
570 smb_avl_release(share_avl
, shr
);
574 clen
= strlen(shr
->shr_cmnt
) + 1;
575 sharelen
= SHARE_INFO_1_SIZE
+ clen
;
577 if (sharelen
<= remained
) {
578 infolen
+= SHARE_INFO_1_SIZE
;
582 remained
-= sharelen
;
583 smb_avl_release(share_avl
, shr
);
586 esi
->es_datasize
= infolen
+ cmntlen
;
588 smb_msgbuf_init(&info_mb
, (uint8_t *)esi
->es_buf
, infolen
, 0);
589 smb_msgbuf_init(&cmnt_mb
, (uint8_t *)esi
->es_buf
+ infolen
, cmntlen
, 0);
592 /* Encode the data in the second round */
593 smb_avl_iterinit(share_avl
, &cursor
);
594 autohome_added
= B_FALSE
;
596 while ((shr
= smb_avl_iterate(share_avl
, &cursor
)) != NULL
) {
597 if (shr
->shr_oemname
== NULL
) {
598 smb_avl_release(share_avl
, shr
);
602 if ((shr
->shr_flags
& SMB_SHRF_AUTOHOME
) && !autohome_added
) {
603 if (esi
->es_posix_uid
== shr
->shr_uid
) {
604 autohome_added
= B_TRUE
;
606 smb_avl_release(share_avl
, shr
);
611 if (smb_msgbuf_encode(&info_mb
, "13c.wl",
612 shr
->shr_oemname
, shr
->shr_type
, cmnt_offs
) < 0) {
613 smb_avl_release(share_avl
, shr
);
617 if (smb_msgbuf_encode(&cmnt_mb
, "s", shr
->shr_cmnt
) < 0) {
618 smb_avl_release(share_avl
, shr
);
622 cmnt_offs
+= strlen(shr
->shr_cmnt
) + 1;
625 smb_avl_release(share_avl
, shr
);
628 smb_msgbuf_term(&info_mb
);
629 smb_msgbuf_term(&cmnt_mb
);
633 * Looks up the given share and returns a pointer
634 * to its definition if it's found. A hold on the
635 * object is taken before the pointer is returned
636 * in which case the caller MUST always call
637 * smb_kshare_release().
640 smb_kshare_lookup(smb_server_t
*sv
, const char *shrname
)
647 if (!smb_export_isready(sv
))
650 key
.shr_name
= (char *)shrname
;
651 shr
= smb_avl_lookup(&sv
->sv_export
.e_share_avl
, &key
);
656 * Releases the hold taken on the specified share object
659 smb_kshare_release(smb_server_t
*sv
, smb_kshare_t
*shr
)
662 ASSERT(shr
->shr_magic
== SMB_SHARE_MAGIC
);
664 smb_avl_release(&sv
->sv_export
.e_share_avl
, shr
);
668 * Add the given share in the specified server.
669 * If the share is a disk share, smb_vfs_hold() is
670 * invoked to ensure that there is a hold on the
671 * corresponding file system before the share is
672 * added to shares AVL.
674 * If the share is an Autohome share and it is
675 * already in the AVL only a reference count for
676 * that share is incremented.
679 smb_kshare_export(smb_server_t
*sv
, smb_kshare_t
*shr
)
681 smb_avl_t
*share_avl
;
682 smb_kshare_t
*auto_shr
;
686 share_avl
= &sv
->sv_export
.e_share_avl
;
688 if (!STYPE_ISDSK(shr
->shr_type
)) {
689 if ((rc
= smb_avl_add(share_avl
, shr
)) != 0) {
690 cmn_err(CE_WARN
, "export[%s]: failed caching (%d)",
697 if ((auto_shr
= smb_avl_lookup(share_avl
, shr
)) != NULL
) {
698 if ((auto_shr
->shr_flags
& SMB_SHRF_AUTOHOME
) == 0) {
699 smb_avl_release(share_avl
, auto_shr
);
703 mutex_enter(&auto_shr
->shr_mutex
);
704 auto_shr
->shr_autocnt
++;
705 mutex_exit(&auto_shr
->shr_mutex
);
706 smb_avl_release(share_avl
, auto_shr
);
710 if ((rc
= smb_server_sharevp(sv
, shr
->shr_path
, &vp
)) != 0) {
711 cmn_err(CE_WARN
, "export[%s(%s)]: failed obtaining vnode (%d)",
712 shr
->shr_name
, shr
->shr_path
, rc
);
716 if ((rc
= smb_vfs_hold(&sv
->sv_export
, vp
->v_vfsp
)) == 0) {
717 if ((rc
= smb_avl_add(share_avl
, shr
)) != 0) {
718 cmn_err(CE_WARN
, "export[%s]: failed caching (%d)",
720 smb_vfs_rele(&sv
->sv_export
, vp
->v_vfsp
);
723 cmn_err(CE_WARN
, "export[%s(%s)]: failed holding VFS (%d)",
724 shr
->shr_name
, shr
->shr_path
, rc
);
732 * Removes the share specified by 'shrname' from the AVL
733 * tree of the given server if it's there.
735 * If the share is an Autohome share, the autohome count
736 * is decremented and the share is only removed if the
737 * count goes to zero.
739 * If the share is a disk share, the hold on the corresponding
740 * file system is released before removing the share from
744 smb_kshare_unexport(smb_server_t
*sv
, const char *shrname
)
746 smb_avl_t
*share_avl
;
751 boolean_t auto_unexport
;
753 share_avl
= &sv
->sv_export
.e_share_avl
;
755 key
.shr_name
= (char *)shrname
;
756 if ((shr
= smb_avl_lookup(share_avl
, &key
)) == NULL
)
759 if ((shr
->shr_flags
& SMB_SHRF_AUTOHOME
) != 0) {
760 mutex_enter(&shr
->shr_mutex
);
762 auto_unexport
= (shr
->shr_autocnt
== 0);
763 mutex_exit(&shr
->shr_mutex
);
764 if (!auto_unexport
) {
765 smb_avl_release(share_avl
, shr
);
770 if (STYPE_ISDSK(shr
->shr_type
)) {
771 if ((rc
= smb_server_sharevp(sv
, shr
->shr_path
, &vp
)) != 0) {
772 smb_avl_release(share_avl
, shr
);
773 cmn_err(CE_WARN
, "unexport[%s]: failed obtaining vnode"
774 " (%d)", shrname
, rc
);
778 smb_vfs_rele(&sv
->sv_export
, vp
->v_vfsp
);
782 smb_avl_remove(share_avl
, shr
);
783 smb_avl_release(share_avl
, shr
);
789 * Exports IPC$ or Admin shares
792 smb_kshare_export_trans(smb_server_t
*sv
, char *name
, char *path
, char *cmnt
)
799 shr
= kmem_cache_alloc(smb_kshare_cache_share
, KM_SLEEP
);
800 bzero(shr
, sizeof (smb_kshare_t
));
802 shr
->shr_magic
= SMB_SHARE_MAGIC
;
804 shr
->shr_flags
= SMB_SHRF_TRANS
| smb_kshare_is_admin(shr
->shr_name
);
805 if (strcasecmp(name
, "IPC$") == 0)
806 shr
->shr_type
= STYPE_IPC
;
808 shr
->shr_type
= STYPE_DISKTREE
;
810 shr
->shr_type
|= smb_kshare_is_special(shr
->shr_name
);
812 shr
->shr_name
= smb_mem_strdup(name
);
814 shr
->shr_path
= smb_mem_strdup(path
);
816 shr
->shr_cmnt
= smb_mem_strdup(cmnt
);
817 shr
->shr_oemname
= smb_kshare_oemname(name
);
819 return (smb_kshare_export(sv
, shr
));
823 * Decodes share information in an nvlist format into a smb_kshare_t
826 * This is a temporary function and will be replaced by functions
827 * provided by libsharev2 code after it's available.
829 static smb_kshare_t
*
830 smb_kshare_decode(nvlist_t
*share
)
835 char *csc_name
= NULL
;
840 bzero(&tmp
, sizeof (smb_kshare_t
));
842 rc
= nvlist_lookup_string(share
, "name", &tmp
.shr_name
);
843 rc
|= nvlist_lookup_string(share
, "path", &tmp
.shr_path
);
844 (void) nvlist_lookup_string(share
, "desc", &tmp
.shr_cmnt
);
846 ASSERT(tmp
.shr_name
&& tmp
.shr_path
);
848 rc
|= nvlist_lookup_nvlist(share
, "smb", &smb
);
850 cmn_err(CE_WARN
, "kshare: failed looking up SMB properties"
855 rc
= nvlist_lookup_uint32(smb
, "type", &tmp
.shr_type
);
857 cmn_err(CE_WARN
, "kshare[%s]: failed getting the share type"
858 " (%d)", tmp
.shr_name
, rc
);
862 (void) nvlist_lookup_string(smb
, SHOPT_AD_CONTAINER
,
864 (void) nvlist_lookup_string(smb
, SHOPT_NONE
, &tmp
.shr_access_none
);
865 (void) nvlist_lookup_string(smb
, SHOPT_RO
, &tmp
.shr_access_ro
);
866 (void) nvlist_lookup_string(smb
, SHOPT_RW
, &tmp
.shr_access_rw
);
868 tmp
.shr_flags
|= smb_kshare_decode_bool(smb
, SHOPT_ABE
, SMB_SHRF_ABE
);
869 tmp
.shr_flags
|= smb_kshare_decode_bool(smb
, SHOPT_CATIA
,
871 tmp
.shr_flags
|= smb_kshare_decode_bool(smb
, SHOPT_GUEST
,
873 tmp
.shr_flags
|= smb_kshare_decode_bool(smb
, SHOPT_DFSROOT
,
875 tmp
.shr_flags
|= smb_kshare_decode_bool(smb
, "Autohome",
878 if ((tmp
.shr_flags
& SMB_SHRF_AUTOHOME
) == SMB_SHRF_AUTOHOME
) {
879 rc
= nvlist_lookup_uint32(smb
, "uid", &tmp
.shr_uid
);
880 rc
|= nvlist_lookup_uint32(smb
, "gid", &tmp
.shr_gid
);
882 cmn_err(CE_WARN
, "kshare: failed looking up uid/gid"
888 (void) nvlist_lookup_string(smb
, SHOPT_CSC
, &csc_name
);
889 smb_kshare_csc_flags(&tmp
, csc_name
);
891 shr
= kmem_cache_alloc(smb_kshare_cache_share
, KM_SLEEP
);
892 bzero(shr
, sizeof (smb_kshare_t
));
894 shr
->shr_magic
= SMB_SHARE_MAGIC
;
897 shr
->shr_name
= smb_mem_strdup(tmp
.shr_name
);
898 shr
->shr_path
= smb_mem_strdup(tmp
.shr_path
);
900 shr
->shr_cmnt
= smb_mem_strdup(tmp
.shr_cmnt
);
901 if (tmp
.shr_container
)
902 shr
->shr_container
= smb_mem_strdup(tmp
.shr_container
);
903 if (tmp
.shr_access_none
)
904 shr
->shr_access_none
= smb_mem_strdup(tmp
.shr_access_none
);
905 if (tmp
.shr_access_ro
)
906 shr
->shr_access_ro
= smb_mem_strdup(tmp
.shr_access_ro
);
907 if (tmp
.shr_access_rw
)
908 shr
->shr_access_rw
= smb_mem_strdup(tmp
.shr_access_rw
);
910 shr
->shr_oemname
= smb_kshare_oemname(shr
->shr_name
);
911 shr
->shr_flags
= tmp
.shr_flags
| smb_kshare_is_admin(shr
->shr_name
);
912 shr
->shr_type
= tmp
.shr_type
| smb_kshare_is_special(shr
->shr_name
);
914 shr
->shr_uid
= tmp
.shr_uid
;
915 shr
->shr_gid
= tmp
.shr_gid
;
917 if ((shr
->shr_flags
& SMB_SHRF_AUTOHOME
) == SMB_SHRF_AUTOHOME
)
918 shr
->shr_autocnt
= 1;
925 smb_kshare_log(smb_kshare_t
*shr
)
927 cmn_err(CE_NOTE
, "Share info:");
928 cmn_err(CE_NOTE
, "\tname: %s", (shr
->shr_name
) ? shr
->shr_name
: "");
929 cmn_err(CE_NOTE
, "\tpath: %s", (shr
->shr_path
) ? shr
->shr_path
: "");
930 cmn_err(CE_NOTE
, "\tcmnt: (%s)",
931 (shr
->shr_cmnt
) ? shr
->shr_cmnt
: "NULL");
932 cmn_err(CE_NOTE
, "\toemname: (%s)",
933 (shr
->shr_oemname
) ? shr
->shr_oemname
: "NULL");
934 cmn_err(CE_NOTE
, "\tflags: %X", shr
->shr_flags
);
935 cmn_err(CE_NOTE
, "\ttype: %d", shr
->shr_type
);
940 * Compare function used by shares AVL
943 smb_kshare_cmp(const void *p1
, const void *p2
)
945 smb_kshare_t
*shr1
= (smb_kshare_t
*)p1
;
946 smb_kshare_t
*shr2
= (smb_kshare_t
*)p2
;
950 ASSERT(shr1
->shr_name
);
953 ASSERT(shr2
->shr_name
);
955 rc
= smb_strcasecmp(shr1
->shr_name
, shr2
->shr_name
, 0);
967 * This function is called by smb_avl routines whenever
968 * there is a need to take a hold on a share structure
972 smb_kshare_hold(const void *p
)
974 smb_kshare_t
*shr
= (smb_kshare_t
*)p
;
977 ASSERT(shr
->shr_magic
== SMB_SHARE_MAGIC
);
979 mutex_enter(&shr
->shr_mutex
);
981 mutex_exit(&shr
->shr_mutex
);
985 * This function must be called by smb_avl routines whenever
986 * smb_kshare_hold is called and the hold needs to be released.
989 smb_kshare_rele(const void *p
)
991 smb_kshare_t
*shr
= (smb_kshare_t
*)p
;
995 ASSERT(shr
->shr_magic
== SMB_SHARE_MAGIC
);
997 mutex_enter(&shr
->shr_mutex
);
998 ASSERT(shr
->shr_refcnt
> 0);
1000 destroy
= (shr
->shr_refcnt
== 0);
1001 mutex_exit(&shr
->shr_mutex
);
1007 * Frees all the memory allocated for the given
1008 * share structure. It also removes the structure
1009 * from the share cache.
1012 smb_kshare_destroy(void *p
)
1014 smb_kshare_t
*shr
= (smb_kshare_t
*)p
;
1017 ASSERT(shr
->shr_magic
== SMB_SHARE_MAGIC
);
1019 smb_mem_free(shr
->shr_name
);
1020 smb_mem_free(shr
->shr_path
);
1021 smb_mem_free(shr
->shr_cmnt
);
1022 smb_mem_free(shr
->shr_container
);
1023 smb_mem_free(shr
->shr_oemname
);
1024 smb_mem_free(shr
->shr_access_none
);
1025 smb_mem_free(shr
->shr_access_ro
);
1026 smb_mem_free(shr
->shr_access_rw
);
1028 kmem_cache_free(smb_kshare_cache_share
, shr
);
1033 * Generate an OEM name for the given share name. If the name is
1034 * shorter than 13 bytes the oemname will be returned; otherwise NULL
1038 smb_kshare_oemname(const char *shrname
)
1040 smb_wchar_t
*unibuf
;
1044 length
= strlen(shrname
) + 1;
1046 oem_name
= smb_mem_alloc(length
);
1047 unibuf
= smb_mem_alloc(length
* sizeof (smb_wchar_t
));
1049 (void) smb_mbstowcs(unibuf
, shrname
, length
);
1051 if (ucstooem(oem_name
, unibuf
, length
, OEM_CPG_850
) == 0)
1052 (void) strcpy(oem_name
, shrname
);
1054 smb_mem_free(unibuf
);
1056 if (strlen(oem_name
) + 1 > SMB_SHARE_OEMNAME_MAX
) {
1057 smb_mem_free(oem_name
);
1065 * Special share reserved for interprocess communication (IPC$) or
1066 * remote administration of the server (ADMIN$). Can also refer to
1067 * administrative shares such as C$, D$, E$, and so forth.
1070 smb_kshare_is_special(const char *sharename
)
1074 if (sharename
== NULL
)
1077 if ((len
= strlen(sharename
)) == 0)
1080 if (sharename
[len
- 1] == '$')
1081 return (STYPE_SPECIAL
);
1087 * Check whether or not this is a default admin share: C$, D$ etc.
1090 smb_kshare_is_admin(const char *sharename
)
1092 if (sharename
== NULL
)
1095 if (strlen(sharename
) == 2 &&
1096 smb_isalpha(sharename
[0]) && sharename
[1] == '$') {
1104 * Decodes the given boolean share option.
1105 * If the option is present in the nvlist and it's value is true
1106 * returns the corresponding flag value, otherwise returns 0.
1109 smb_kshare_decode_bool(nvlist_t
*nvl
, const char *propname
, uint32_t flag
)
1113 if (nvlist_lookup_string(nvl
, propname
, &boolp
) == 0)
1114 if (strcasecmp(boolp
, "true") == 0)
1121 * Map a client-side caching (CSC) option to the appropriate share
1122 * flag. Only one option is allowed; an error will be logged if
1123 * multiple options have been specified. We don't need to do anything
1124 * about multiple values here because the SRVSVC will not recognize
1125 * a value containing multiple flags and will return the default value.
1127 * If the option value is not recognized, it will be ignored: invalid
1128 * values will typically be caught and rejected by sharemgr.
1131 smb_kshare_csc_flags(smb_kshare_t
*shr
, const char *value
)
1138 { "disabled", SMB_SHRF_CSC_DISABLED
},
1139 { "manual", SMB_SHRF_CSC_MANUAL
},
1140 { "auto", SMB_SHRF_CSC_AUTO
},
1141 { "vdo", SMB_SHRF_CSC_VDO
}
1147 for (i
= 0; i
< (sizeof (cscopt
) / sizeof (cscopt
[0])); ++i
) {
1148 if (strcasecmp(value
, cscopt
[i
].value
) == 0) {
1149 shr
->shr_flags
|= cscopt
[i
].flag
;
1154 switch (shr
->shr_flags
& SMB_SHRF_CSC_MASK
) {
1156 case SMB_SHRF_CSC_DISABLED
:
1157 case SMB_SHRF_CSC_MANUAL
:
1158 case SMB_SHRF_CSC_AUTO
:
1159 case SMB_SHRF_CSC_VDO
:
1163 cmn_err(CE_NOTE
, "csc option conflict: 0x%08x",
1164 shr
->shr_flags
& SMB_SHRF_CSC_MASK
);
1170 * This function processes the unexport event list and disconnects shares
1171 * asynchronously. The function executes as a zone-specific thread.
1173 * The server arg passed in is safe to use without a reference count, because
1174 * the server cannot be deleted until smb_thread_stop()/destroy() return,
1175 * which is also when the thread exits.
1179 smb_kshare_unexport_thread(smb_thread_t
*thread
, void *arg
)
1181 smb_server_t
*sv
= arg
;
1184 while (smb_thread_continue(thread
)) {
1185 while ((ux
= list_head(&sv
->sv_export
.e_unexport_list
.sl_list
))
1187 smb_slist_remove(&sv
->sv_export
.e_unexport_list
, ux
);
1188 (void) smb_server_unshare(ux
->us_sharename
);
1189 kmem_cache_free(smb_kshare_cache_unexport
, ux
);
1195 smb_export_isready(smb_server_t
*sv
)
1199 mutex_enter(&sv
->sv_export
.e_mutex
);
1200 ready
= sv
->sv_export
.e_ready
;
1201 mutex_exit(&sv
->sv_export
.e_mutex
);
1208 * Return 0 upon success. Otherwise > 0
1211 smb_kshare_chk_dsrv_status(int opcode
, smb_dr_ctx_t
*dec_ctx
)
1213 int status
= smb_dr_get_int32(dec_ctx
);
1217 case SMB_SHARE_DSUCCESS
:
1220 case SMB_SHARE_DERROR
:
1221 err
= smb_dr_get_uint32(dec_ctx
);
1222 cmn_err(CE_WARN
, "%d: Encountered door server error %d",
1224 (void) smb_dr_decode_finish(dec_ctx
);
1231 #endif /* _KERNEL */