Home | History | Annotate | Download | only in smbsrv
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * General Structures Layout
     28  * -------------------------
     29  *
     30  * This is a simplified diagram showing the relationship between most of the
     31  * main structures.
     32  *
     33  * +-------------------+
     34  * |     SMB_SERVER    |
     35  * +-------------------+
     36  *          |
     37  *          |
     38  *          v
     39  * +-------------------+       +-------------------+      +-------------------+
     40  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
     41  * +-------------------+       +-------------------+      +-------------------+
     42  *          |
     43  *          |
     44  *          v
     45  * +-------------------+       +-------------------+      +-------------------+
     46  * |       USER        |<----->|       USER        |......|       USER        |
     47  * +-------------------+       +-------------------+      +-------------------+
     48  *          |
     49  *          |
     50  *          v
     51  * +-------------------+       +-------------------+      +-------------------+
     52  * |       TREE        |<----->|       TREE        |......|       TREE        |
     53  * +-------------------+       +-------------------+      +-------------------+
     54  *      |         |
     55  *      |         |
     56  *      |         v
     57  *      |     +-------+       +-------+      +-------+
     58  *      |     | OFILE |<----->| OFILE |......| OFILE |
     59  *      |     +-------+       +-------+      +-------+
     60  *      |
     61  *      |
     62  *      v
     63  *  +-------+       +------+      +------+
     64  *  | ODIR  |<----->| ODIR |......| ODIR |
     65  *  +-------+       +------+      +------+
     66  *
     67  *
     68  * Module Interface Overview
     69  * -------------------------
     70  *
     71  *
     72  *	    +===================================+
     73  *	    |		 smbd daemon		|
     74  *	    +===================================+
     75  *	      |		     |		      ^
     76  *	      |		     |		      |
     77  * User	      |		     |		      |
     78  * -----------|--------------|----------------|--------------------------------
     79  * Kernel     |		     |		      |
     80  *            |		     |		      |
     81  *	      |		     |		      |
     82  *  +=========|==============|================|=================+
     83  *  |	      v		     v		      |			|
     84  *  | +-----------+ +--------------------+ +------------------+ |
     85  *  | |     IO    | | Kernel Door Server | | User Door Servers|	|
     86  *  | | Interface | |     Interface      | |   Interface      | |
     87  *  | +-----------+ +--------------------+ +------------------+ |
     88  *  |		|	     |		      ^		^	|
     89  *  |		v	     v		      |		|	|    +=========+
     90  *  |	     +-----------------------------------+	|	|    |	       |
     91  *  |	     + SMB Server Management (this file) |<------------------|	 ZFS   |
     92  *  |	     +-----------------------------------+	|	|    |	       |
     93  *  |							|	|    |  Module |
     94  *  |	     +-----------------------------------+	|	|    |	       |
     95  *  |	     +     SMB Server Internal Layers    |------+	|    +=========+
     96  *  |	     +-----------------------------------+		|
     97  *  |								|
     98  *  |								|
     99  *  +===========================================================+
    100  *
    101  *
    102  * Server State Machine
    103  * --------------------
    104  *                                  |
    105  *                                  | T0
    106  *                                  |
    107  *                                  v
    108  *                    +-----------------------------+
    109  *		      |   SMB_SERVER_STATE_CREATED  |
    110  *		      +-----------------------------+
    111  *				    |
    112  *				    | T1
    113  *				    |
    114  *				    v
    115  *		      +-----------------------------+
    116  *		      | SMB_SERVER_STATE_CONFIGURED |
    117  *		      +-----------------------------+
    118  *				    |
    119  *				    | T2
    120  *				    |
    121  *				    v
    122  *		      +-----------------------------+
    123  *		      |  SMB_SERVER_STATE_RUNNING   |
    124  *		      +-----------------------------+
    125  *				    |
    126  *				    | T3
    127  *				    |
    128  *				    v
    129  *		      +-----------------------------+
    130  *		      |  SMB_SERVER_STATE_DELETING  |
    131  *                    +-----------------------------+
    132  *				    |
    133  *				    |
    134  *				    |
    135  *				    v
    136  *
    137  * States
    138  * ------
    139  *
    140  * SMB_SERVER_STATE_CREATED
    141  *
    142  *    This is the state of the server just after creation.
    143  *
    144  * SMB_SERVER_STATE_CONFIGURED
    145  *
    146  *    The server has been configured.
    147  *
    148  * SMB_SERVER_STATE_RUNNING
    149  *
    150  *    The server has been started. While in this state the threads listening on
    151  *    the sockets car be started. The smbd daemon does so through an Ioctl:
    152  *
    153  *	smb_drv_ioctl(SMB_IOC_NBT_LISTEN) --> smb_server_nbt_listen()
    154  *	smb_drv_ioctl(SMB_IOC_TCP_LISTEN) --> smb_server_nbt_listen()
    155  *
    156  *    When a client establishes a connection the thread listening leaves
    157  *    temporarily the kernel. While in user space it creates a thread for the
    158  *    new session. It then returns to kernel with the result of the thread
    159  *    creation. If the creation failed the new session context is destroyed
    160  *    before returning listening.
    161  *
    162  *    The new created thread enters the kernel though an Ioctl:
    163  *
    164  *	smb_drv_ioctl(SMB_IOC_NBT_RECEIVE) --> smb_server_nbt_receive()
    165  *	smb_drv_ioctl(SMB_IOC_TCP_RECEIVE) --> smb_server_tcp_receive()
    166  *
    167  * SMB_SERVER_STATE_STOPPING
    168  *
    169  *    The threads listening on the NBT and TCP sockets are being terminated.
    170  *
    171  *
    172  * Transitions
    173  * -----------
    174  *
    175  * Transition T0
    176  *
    177  *    The daemon smbd triggers its creation by opening the smbsrv device. If
    178  *    the zone where the daemon lives doesn't have an smb server yet it is
    179  *    created.
    180  *
    181  *		smb_drv_open() --> smb_server_create()
    182  *
    183  * Transition T1
    184  *
    185  *    This transition occurs in smb_server_configure(). It is triggered by the
    186  *    daemon through an Ioctl.
    187  *
    188  *	smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure()
    189  *
    190  * Transition T2
    191  *
    192  *    This transition occurs in smb_server_start(). It is triggered by the
    193  *    daemon through an Ioctl.
    194  *
    195  *	smb_drv_ioctl(SMB_IOC_START) --> smb_server_start()
    196  *
    197  * Transition T3
    198  *
    199  *    This transition occurs in smb_server_delete(). It is triggered by the
    200  *    daemon when closing the smbsrv device
    201  *
    202  *		smb_drv_close() --> smb_server_delete()
    203  *
    204  * Comments
    205  * --------
    206  *
    207  * This files assumes that there will one SMB server per zone. For now the
    208  * smb server works only in global zone. There's nothing in this file preventing
    209  * an smb server from being created in a non global zone. That limitation is
    210  * enforced in user space.
    211  */
    212 
    213 #include <sys/strsubr.h>
    214 #include <sys/cmn_err.h>
    215 #include <sys/priv.h>
    216 #include <sys/socketvar.h>
    217 #include <sys/zone.h>
    218 #include <netinet/in.h>
    219 #include <netinet/in_systm.h>
    220 #include <netinet/ip.h>
    221 #include <netinet/ip_icmp.h>
    222 #include <netinet/ip_var.h>
    223 #include <netinet/tcp.h>
    224 #include <smbsrv/smb_kproto.h>
    225 #include <smbsrv/string.h>
    226 #include <smbsrv/netbios.h>
    227 #include <smbsrv/smb_fsops.h>
    228 #include <smbsrv/smb_share.h>
    229 #include <smbsrv/smb_door_svc.h>
    230 #include <smbsrv/smb_kstat.h>
    231 
    232 extern void smb_dispatch_kstat_init(void);
    233 extern void smb_dispatch_kstat_fini(void);
    234 extern void smb_reply_notify_change_request(smb_request_t *);
    235 
    236 static int smb_server_kstat_init(smb_server_t *);
    237 static void smb_server_kstat_fini(smb_server_t *);
    238 static int smb_server_kstat_update_info(kstat_t *, int);
    239 static void smb_server_timers(smb_thread_t *, void *);
    240 static int smb_server_listen(smb_server_t *, smb_listener_daemon_t *,
    241     in_port_t, int, int);
    242 static int smb_server_lookup(smb_server_t **);
    243 static void smb_server_release(smb_server_t *);
    244 static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *);
    245 static void smb_server_stop(smb_server_t *);
    246 static int smb_server_fsop_start(smb_server_t *);
    247 static void smb_server_fsop_stop(smb_server_t *);
    248 
    249 static void smb_server_disconnect_share(char *, smb_server_t *);
    250 static void smb_server_thread_unexport(smb_thread_t *, void *);
    251 
    252 static void smb_server_enum_private(smb_session_list_t *, smb_svcenum_t *);
    253 static int smb_server_sesion_disconnect(smb_session_list_t *, const char *,
    254     const char *);
    255 static int smb_server_fclose(smb_session_list_t *, uint32_t);
    256 
    257 static smb_llist_t	smb_servers;
    258 
    259 /*
    260  * *****************************************************************************
    261  * **************** Functions called from the device interface *****************
    262  * *****************************************************************************
    263  *
    264  * These functions typically have to determine the relevant smb server
    265  * to which the call applies.
    266  */
    267 
    268 /*
    269  * smb_server_svc_init
    270  *
    271  * This function must be called from smb_drv_attach().
    272  */
    273 int
    274 smb_server_svc_init(void)
    275 {
    276 	int	rc = 0;
    277 
    278 	while (rc == 0) {
    279 		if (rc = smb_mbc_init())
    280 			continue;
    281 		if (rc = smb_vop_init())
    282 			continue;
    283 		if (rc = smb_node_init())
    284 			continue;
    285 		if (rc = smb_fem_init())
    286 			continue;
    287 		if (rc = smb_user_init())
    288 			continue;
    289 		if (rc = smb_notify_init())
    290 			continue;
    291 		if (rc = smb_net_init())
    292 			continue;
    293 		smb_llist_constructor(&smb_servers, sizeof (smb_server_t),
    294 		    offsetof(smb_server_t, sv_lnd));
    295 		return (0);
    296 	}
    297 	smb_net_fini();
    298 	smb_notify_fini();
    299 	smb_user_fini();
    300 	smb_fem_fini();
    301 	smb_node_fini();
    302 	smb_vop_fini();
    303 	smb_mbc_fini();
    304 	return (rc);
    305 }
    306 
    307 /*
    308  * smb_server_svc_fini
    309  *
    310  * This function must called from smb_drv_detach(). It will fail if servers
    311  * still exist.
    312  */
    313 int
    314 smb_server_svc_fini(void)
    315 {
    316 	int	rc = EBUSY;
    317 
    318 	if (smb_llist_get_count(&smb_servers) == 0) {
    319 		smb_net_fini();
    320 		smb_notify_fini();
    321 		smb_user_fini();
    322 		smb_fem_fini();
    323 		smb_node_fini();
    324 		smb_vop_fini();
    325 		smb_mbc_fini();
    326 		smb_llist_destructor(&smb_servers);
    327 		rc = 0;
    328 	}
    329 	return (rc);
    330 }
    331 
    332 /*
    333  * smb_server_create
    334  *
    335  * This function will fail if there's already a server associated with the
    336  * caller's zone.
    337  */
    338 int
    339 smb_server_create(void)
    340 {
    341 	zoneid_t	zid;
    342 	smb_server_t	*sv;
    343 
    344 	zid = getzoneid();
    345 
    346 	smb_llist_enter(&smb_servers, RW_WRITER);
    347 	sv = smb_llist_head(&smb_servers);
    348 	while (sv) {
    349 		ASSERT(sv->sv_magic == SMB_SERVER_MAGIC);
    350 		if (sv->sv_zid == zid) {
    351 			smb_llist_exit(&smb_servers);
    352 			return (EPERM);
    353 		}
    354 		sv = smb_llist_next(&smb_servers, sv);
    355 	}
    356 
    357 	sv = kmem_zalloc(sizeof (smb_server_t), KM_NOSLEEP);
    358 	if (sv == NULL) {
    359 		smb_llist_exit(&smb_servers);
    360 		return (ENOMEM);
    361 	}
    362 
    363 	smb_llist_constructor(&sv->sv_vfs_list, sizeof (smb_vfs_t),
    364 	    offsetof(smb_vfs_t, sv_lnd));
    365 
    366 	smb_slist_constructor(&sv->sv_unexport_list, sizeof (smb_unexport_t),
    367 	    offsetof(smb_unexport_t, ux_lnd));
    368 
    369 	smb_session_list_constructor(&sv->sv_nbt_daemon.ld_session_list);
    370 	smb_session_list_constructor(&sv->sv_tcp_daemon.ld_session_list);
    371 
    372 	sv->si_cache_unexport = kmem_cache_create("smb_unexport_cache",
    373 	    sizeof (smb_unexport_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
    374 	sv->si_cache_vfs = kmem_cache_create("smb_vfs_cache",
    375 	    sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
    376 	sv->si_cache_request = kmem_cache_create("smb_request_cache",
    377 	    sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
    378 	sv->si_cache_session = kmem_cache_create("smb_session_cache",
    379 	    sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
    380 	sv->si_cache_user = kmem_cache_create("smb_user_cache",
    381 	    sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
    382 	sv->si_cache_tree = kmem_cache_create("smb_tree_cache",
    383 	    sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
    384 	sv->si_cache_ofile = kmem_cache_create("smb_ofile_cache",
    385 	    sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
    386 	sv->si_cache_odir = kmem_cache_create("smb_odir_cache",
    387 	    sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
    388 
    389 	smb_thread_init(&sv->si_thread_timers,
    390 	    "smb_timers", smb_server_timers, sv,
    391 	    NULL, NULL);
    392 
    393 	smb_thread_init(&sv->si_thread_unexport, "smb_thread_unexport",
    394 	    smb_server_thread_unexport, sv, NULL, NULL);
    395 
    396 	sv->sv_pid = curproc->p_pid;
    397 
    398 	smb_kdoor_clnt_init();
    399 	smb_opipe_door_init();
    400 	(void) smb_server_kstat_init(sv);
    401 
    402 	mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL);
    403 	cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL);
    404 	sv->sv_state = SMB_SERVER_STATE_CREATED;
    405 	sv->sv_magic = SMB_SERVER_MAGIC;
    406 	sv->sv_zid = zid;
    407 
    408 	smb_llist_insert_tail(&smb_servers, sv);
    409 	smb_llist_exit(&smb_servers);
    410 	return (0);
    411 }
    412 
    413 /*
    414  * smb_server_delete
    415  *
    416  * This function will delete the server passed in. It will make sure that all
    417  * activity associated that server has ceased before destroying it.
    418  */
    419 int
    420 smb_server_delete(void)
    421 {
    422 	smb_server_t	*sv;
    423 	smb_unexport_t	*ux;
    424 	int		rc;
    425 
    426 	rc = smb_server_lookup(&sv);
    427 	if (rc != 0)
    428 		return (rc);
    429 
    430 	mutex_enter(&sv->sv_mutex);
    431 	switch (sv->sv_state) {
    432 	case SMB_SERVER_STATE_RUNNING:
    433 	{
    434 		boolean_t	nbt = B_FALSE;
    435 		boolean_t	tcp = B_FALSE;
    436 
    437 		if (sv->sv_nbt_daemon.ld_kth) {
    438 			tsignal(sv->sv_nbt_daemon.ld_kth, SIGINT);
    439 			nbt = B_TRUE;
    440 		}
    441 		if (sv->sv_tcp_daemon.ld_kth) {
    442 			tsignal(sv->sv_tcp_daemon.ld_kth, SIGINT);
    443 			tcp = B_TRUE;
    444 		}
    445 		sv->sv_state = SMB_SERVER_STATE_DELETING;
    446 		mutex_exit(&sv->sv_mutex);
    447 		if (nbt)
    448 			thread_join(sv->sv_nbt_daemon.ld_ktdid);
    449 		if (tcp)
    450 			thread_join(sv->sv_tcp_daemon.ld_ktdid);
    451 		mutex_enter(&sv->sv_mutex);
    452 		break;
    453 	}
    454 	case SMB_SERVER_STATE_CONFIGURED:
    455 	case SMB_SERVER_STATE_CREATED:
    456 		sv->sv_state = SMB_SERVER_STATE_DELETING;
    457 		break;
    458 	default:
    459 		ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
    460 		mutex_exit(&sv->sv_mutex);
    461 		smb_server_release(sv);
    462 		return (ENOTTY);
    463 	}
    464 
    465 	ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
    466 
    467 	sv->sv_refcnt--;
    468 	while (sv->sv_refcnt)
    469 		cv_wait(&sv->sv_cv, &sv->sv_mutex);
    470 
    471 	mutex_exit(&sv->sv_mutex);
    472 
    473 	smb_llist_enter(&smb_servers, RW_WRITER);
    474 	smb_llist_remove(&smb_servers, sv);
    475 	smb_llist_exit(&smb_servers);
    476 
    477 	smb_server_stop(sv);
    478 	rw_destroy(&sv->sv_cfg_lock);
    479 	smb_opipe_door_fini();
    480 	smb_kdoor_clnt_fini();
    481 	smb_server_kstat_fini(sv);
    482 	smb_llist_destructor(&sv->sv_vfs_list);
    483 
    484 	while ((ux = list_head(&sv->sv_unexport_list.sl_list)) != NULL) {
    485 		smb_slist_remove(&sv->sv_unexport_list, ux);
    486 		kmem_cache_free(sv->si_cache_unexport, ux);
    487 	}
    488 	smb_slist_destructor(&sv->sv_unexport_list);
    489 
    490 	kmem_cache_destroy(sv->si_cache_unexport);
    491 	kmem_cache_destroy(sv->si_cache_vfs);
    492 	kmem_cache_destroy(sv->si_cache_request);
    493 	kmem_cache_destroy(sv->si_cache_session);
    494 	kmem_cache_destroy(sv->si_cache_user);
    495 	kmem_cache_destroy(sv->si_cache_tree);
    496 	kmem_cache_destroy(sv->si_cache_ofile);
    497 	kmem_cache_destroy(sv->si_cache_odir);
    498 
    499 	smb_thread_destroy(&sv->si_thread_timers);
    500 	smb_thread_destroy(&sv->si_thread_unexport);
    501 	mutex_destroy(&sv->sv_mutex);
    502 	cv_destroy(&sv->sv_cv);
    503 	sv->sv_magic = 0;
    504 	kmem_free(sv, sizeof (smb_server_t));
    505 
    506 	return (0);
    507 }
    508 
    509 /*
    510  * smb_server_configure
    511  */
    512 int
    513 smb_server_configure(smb_ioc_cfg_t *ioc)
    514 {
    515 	int		rc = 0;
    516 	smb_server_t	*sv;
    517 
    518 	rc = smb_server_lookup(&sv);
    519 	if (rc)
    520 		return (rc);
    521 
    522 	mutex_enter(&sv->sv_mutex);
    523 	switch (sv->sv_state) {
    524 	case SMB_SERVER_STATE_CREATED:
    525 		smb_server_store_cfg(sv, ioc);
    526 		sv->sv_state = SMB_SERVER_STATE_CONFIGURED;
    527 		break;
    528 
    529 	case SMB_SERVER_STATE_CONFIGURED:
    530 		smb_server_store_cfg(sv, ioc);
    531 		break;
    532 
    533 	case SMB_SERVER_STATE_RUNNING:
    534 		rw_enter(&sv->sv_cfg_lock, RW_WRITER);
    535 		smb_server_store_cfg(sv, ioc);
    536 		rw_exit(&sv->sv_cfg_lock);
    537 		break;
    538 
    539 	default:
    540 		ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING);
    541 		rc = EFAULT;
    542 		break;
    543 	}
    544 	mutex_exit(&sv->sv_mutex);
    545 
    546 	smb_server_release(sv);
    547 
    548 	return (rc);
    549 }
    550 
    551 /*
    552  * smb_server_start
    553  */
    554 int
    555 smb_server_start(smb_ioc_start_t *ioc)
    556 {
    557 	int		rc = 0;
    558 	smb_server_t	*sv;
    559 
    560 	rc = smb_server_lookup(&sv);
    561 	if (rc)
    562 		return (rc);
    563 
    564 	mutex_enter(&sv->sv_mutex);
    565 	switch (sv->sv_state) {
    566 	case SMB_SERVER_STATE_CONFIGURED:
    567 		smb_codepage_init();
    568 
    569 		sv->sv_thread_pool = taskq_create("smb_workers",
    570 		    sv->sv_cfg.skc_maxworkers, SMB_WORKER_PRIORITY,
    571 		    sv->sv_cfg.skc_maxworkers, INT_MAX,
    572 		    TASKQ_DYNAMIC|TASKQ_PREPOPULATE);
    573 
    574 		sv->sv_session = smb_session_create(NULL, 0, sv, 0);
    575 
    576 		if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) {
    577 			rc = ENOMEM;
    578 			break;
    579 		}
    580 
    581 		if (rc = smb_server_fsop_start(sv))
    582 			break;
    583 		ASSERT(sv->sv_lmshrd == NULL);
    584 		sv->sv_lmshrd = smb_kshare_init(ioc->lmshrd);
    585 		if (sv->sv_lmshrd == NULL)
    586 			break;
    587 		if (rc = smb_kdoor_clnt_open(ioc->udoor))
    588 			break;
    589 		if (rc = smb_thread_start(&sv->si_thread_timers))
    590 			break;
    591 		if (rc = smb_thread_start(&sv->si_thread_unexport))
    592 			break;
    593 		if (rc = smb_opipe_door_open(ioc->opipe)) {
    594 			cmn_err(CE_WARN, "Cannot open opipe door");
    595 			break;
    596 		}
    597 
    598 		sv->sv_state = SMB_SERVER_STATE_RUNNING;
    599 		mutex_exit(&sv->sv_mutex);
    600 		smb_server_release(sv);
    601 		return (0);
    602 	default:
    603 		ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) ||
    604 		    (sv->sv_state == SMB_SERVER_STATE_RUNNING) ||
    605 		    (sv->sv_state == SMB_SERVER_STATE_DELETING));
    606 		mutex_exit(&sv->sv_mutex);
    607 		smb_server_release(sv);
    608 		return (ENOTTY);
    609 	}
    610 
    611 	smb_server_stop(sv);
    612 	mutex_exit(&sv->sv_mutex);
    613 	smb_server_release(sv);
    614 	return (rc);
    615 }
    616 
    617 /*
    618  * smb_server_nbt_listen: SMB-over-NetBIOS service
    619  *
    620  * Traditional SMB service over NetBIOS (port 139), which requires
    621  * that a NetBIOS session be established.
    622  */
    623 int
    624 smb_server_nbt_listen(smb_ioc_listen_t *ioc)
    625 {
    626 	smb_server_t	*sv;
    627 	int		rc;
    628 
    629 	rc = smb_server_lookup(&sv);
    630 	if (rc)
    631 		return (rc);
    632 
    633 	mutex_enter(&sv->sv_mutex);
    634 	switch (sv->sv_state) {
    635 	case SMB_SERVER_STATE_RUNNING:
    636 		if ((sv->sv_nbt_daemon.ld_kth != NULL) &&
    637 		    (sv->sv_nbt_daemon.ld_kth != curthread)) {
    638 			mutex_exit(&sv->sv_mutex);
    639 			smb_server_release(sv);
    640 			return (EACCES);
    641 		} else {
    642 			sv->sv_nbt_daemon.ld_kth = curthread;
    643 			sv->sv_nbt_daemon.ld_ktdid = curthread->t_did;
    644 		}
    645 		break;
    646 	default:
    647 		ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) ||
    648 		    (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) ||
    649 		    (sv->sv_state == SMB_SERVER_STATE_DELETING));
    650 		mutex_exit(&sv->sv_mutex);
    651 		smb_server_release(sv);
    652 		return (EFAULT);
    653 	}
    654 	mutex_exit(&sv->sv_mutex);
    655 
    656 	/*
    657 	 * netbios must be ipv4
    658 	 */
    659 	rc = smb_server_listen(sv, &sv->sv_nbt_daemon, IPPORT_NETBIOS_SSN,
    660 	    AF_INET, ioc->error);
    661 
    662 	if (rc) {
    663 		mutex_enter(&sv->sv_mutex);
    664 		sv->sv_nbt_daemon.ld_kth = NULL;
    665 		mutex_exit(&sv->sv_mutex);
    666 	}
    667 
    668 	smb_server_release(sv);
    669 	return (rc);
    670 }
    671 
    672 int
    673 smb_server_tcp_listen(smb_ioc_listen_t *ioc)
    674 {
    675 	smb_server_t	*sv;
    676 	int		rc;
    677 
    678 	rc = smb_server_lookup(&sv);
    679 	if (rc)
    680 		return (rc);
    681 
    682 	mutex_enter(&sv->sv_mutex);
    683 	switch (sv->sv_state) {
    684 	case SMB_SERVER_STATE_RUNNING:
    685 		if ((sv->sv_tcp_daemon.ld_kth) &&
    686 		    (sv->sv_tcp_daemon.ld_kth != curthread)) {
    687 			mutex_exit(&sv->sv_mutex);
    688 			smb_server_release(sv);
    689 			return (EACCES);
    690 		} else {
    691 			sv->sv_tcp_daemon.ld_kth = curthread;
    692 			sv->sv_tcp_daemon.ld_ktdid = curthread->t_did;
    693 		}
    694 		break;
    695 	default:
    696 		ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) ||
    697 		    (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) ||
    698 		    (sv->sv_state == SMB_SERVER_STATE_DELETING));
    699 		mutex_exit(&sv->sv_mutex);
    700 		smb_server_release(sv);
    701 		return (EFAULT);
    702 	}
    703 	mutex_exit(&sv->sv_mutex);
    704 
    705 	if (sv->sv_cfg.skc_ipv6_enable)
    706 		rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
    707 		    IPPORT_SMB, AF_INET6, ioc->error);
    708 	else
    709 		rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
    710 		    IPPORT_SMB, AF_INET, ioc->error);
    711 	if (rc) {
    712 		mutex_enter(&sv->sv_mutex);
    713 		sv->sv_tcp_daemon.ld_kth = NULL;
    714 		mutex_exit(&sv->sv_mutex);
    715 	}
    716 
    717 	smb_server_release(sv);
    718 	return (rc);
    719 }
    720 
    721 /*
    722  * smb_server_nbt_receive
    723  */
    724 int
    725 smb_server_nbt_receive(void)
    726 {
    727 	int		rc;
    728 	smb_server_t	*sv;
    729 
    730 	if ((rc = smb_server_lookup(&sv)) == 0) {
    731 		rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list);
    732 		smb_server_release(sv);
    733 	}
    734 
    735 	return (rc);
    736 }
    737 
    738 /*
    739  * smb_server_tcp_receive
    740  */
    741 int
    742 smb_server_tcp_receive(void)
    743 {
    744 	int		rc;
    745 	smb_server_t	*sv;
    746 
    747 	if ((rc = smb_server_lookup(&sv)) == 0) {
    748 		rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list);
    749 		smb_server_release(sv);
    750 	}
    751 
    752 	return (rc);
    753 }
    754 
    755 int
    756 smb_server_set_gmtoff(smb_ioc_gmt_t *ioc)
    757 {
    758 	int		rc;
    759 	smb_server_t	*sv;
    760 
    761 	if ((rc = smb_server_lookup(&sv)) == 0) {
    762 		sv->si_gmtoff = ioc->offset;
    763 		smb_server_release(sv);
    764 	}
    765 
    766 	return (rc);
    767 }
    768 
    769 int
    770 smb_server_numopen(smb_ioc_opennum_t *ioc)
    771 {
    772 	smb_server_t	*sv;
    773 	int		rc;
    774 
    775 	if ((rc = smb_server_lookup(&sv)) == 0) {
    776 		ioc->open_users = sv->sv_open_users;
    777 		ioc->open_trees = sv->sv_open_trees;
    778 		ioc->open_files = sv->sv_open_files;
    779 		smb_server_release(sv);
    780 	}
    781 	return (rc);
    782 }
    783 
    784 /*
    785  * Enumerate objects within the server.  The svcenum provides the
    786  * enumeration context, i.e. what the caller want to get back.
    787  */
    788 int
    789 smb_server_enum(smb_ioc_svcenum_t *ioc)
    790 {
    791 	smb_svcenum_t		*svcenum = &ioc->svcenum;
    792 	smb_server_t		*sv;
    793 	smb_session_list_t	*se;
    794 	int			rc;
    795 
    796 	switch (svcenum->se_type) {
    797 	case SMB_SVCENUM_TYPE_USER:
    798 	case SMB_SVCENUM_TYPE_TREE:
    799 	case SMB_SVCENUM_TYPE_FILE:
    800 		break;
    801 	default:
    802 		return (EINVAL);
    803 	}
    804 
    805 	if ((rc = smb_server_lookup(&sv)) != 0)
    806 		return (rc);
    807 
    808 	svcenum->se_bavail = svcenum->se_buflen;
    809 	svcenum->se_bused = 0;
    810 	svcenum->se_nitems = 0;
    811 
    812 	se = &sv->sv_nbt_daemon.ld_session_list;
    813 	smb_server_enum_private(se, svcenum);
    814 
    815 	se = &sv->sv_tcp_daemon.ld_session_list;
    816 	smb_server_enum_private(se, svcenum);
    817 
    818 	smb_server_release(sv);
    819 	return (0);
    820 }
    821 
    822 /*
    823  * Look for sessions to disconnect by client and user name.
    824  */
    825 int
    826 smb_server_session_close(smb_ioc_session_t *ioc)
    827 {
    828 	smb_session_list_t	*se;
    829 	smb_server_t		*sv;
    830 	int			nbt_cnt;
    831 	int			tcp_cnt;
    832 	int			rc;
    833 
    834 	if ((rc = smb_server_lookup(&sv)) != 0)
    835 		return (rc);
    836 
    837 	se = &sv->sv_nbt_daemon.ld_session_list;
    838 	nbt_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username);
    839 
    840 	se = &sv->sv_tcp_daemon.ld_session_list;
    841 	tcp_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username);
    842 
    843 	smb_server_release(sv);
    844 
    845 	if ((nbt_cnt == 0) && (tcp_cnt == 0))
    846 		return (ENOENT);
    847 	return (0);
    848 }
    849 
    850 /*
    851  * Close a file by uniqid.
    852  */
    853 int
    854 smb_server_file_close(smb_ioc_fileid_t *ioc)
    855 {
    856 	uint32_t		uniqid = ioc->uniqid;
    857 	smb_session_list_t	*se;
    858 	smb_server_t		*sv;
    859 	int			rc;
    860 
    861 	if ((rc = smb_server_lookup(&sv)) != 0)
    862 		return (rc);
    863 
    864 	se = &sv->sv_nbt_daemon.ld_session_list;
    865 	rc = smb_server_fclose(se, uniqid);
    866 
    867 	if (rc == ENOENT) {
    868 		se = &sv->sv_tcp_daemon.ld_session_list;
    869 		rc = smb_server_fclose(se, uniqid);
    870 	}
    871 
    872 	smb_server_release(sv);
    873 	return (rc);
    874 }
    875 
    876 /*
    877  * These functions determine the relevant smb server to which the call apply.
    878  */
    879 
    880 uint32_t
    881 smb_server_get_session_count(void)
    882 {
    883 	smb_server_t	*sv;
    884 	uint32_t	counter = 0;
    885 
    886 	if (smb_server_lookup(&sv))
    887 		return (0);
    888 
    889 	rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER);
    890 	counter = sv->sv_nbt_daemon.ld_session_list.se_act.count;
    891 	rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock);
    892 	rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER);
    893 	counter += sv->sv_tcp_daemon.ld_session_list.se_act.count;
    894 	rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock);
    895 
    896 	smb_server_release(sv);
    897 
    898 	return (counter);
    899 }
    900 
    901 /*
    902  * smb_server_disconnect_share
    903  *
    904  * Disconnects the specified share. This function should be called after the
    905  * share passed in has been made unavailable by the "share manager".
    906  */
    907 static void
    908 smb_server_disconnect_share(char *sharename, smb_server_t *sv)
    909 {
    910 	smb_session_disconnect_share(&sv->sv_nbt_daemon.ld_session_list,
    911 	    sharename);
    912 	smb_session_disconnect_share(&sv->sv_tcp_daemon.ld_session_list,
    913 	    sharename);
    914 }
    915 
    916 /*
    917  * smb_server_share_export()
    918  *
    919  * This function handles kernel processing at share enable time.
    920  *
    921  * At share-enable time (LMSHRD_ADD), the file system corresponding to
    922  * the share is checked for characteristics that are required for SMB
    923  * sharing.  If this check passes, then a hold is taken on the root vnode
    924  * of the file system (or a reference count on the corresponding smb_vfs_t
    925  * is bumped), preventing an unmount.  (See smb_vfs_hold()).
    926  */
    927 
    928 int
    929 smb_server_share_export(smb_ioc_share_t *ioc)
    930 {
    931 	smb_server_t	*sv;
    932 	int		error = 0;
    933 	smb_node_t	*fnode = NULL;
    934 	smb_node_t	*dnode;
    935 	char		last_comp[MAXNAMELEN];
    936 	smb_request_t	*sr;
    937 
    938 	if (smb_server_lookup(&sv))
    939 		return (EINVAL);
    940 
    941 	mutex_enter(&sv->sv_mutex);
    942 	switch (sv->sv_state) {
    943 	case SMB_SERVER_STATE_RUNNING:
    944 		break;
    945 	default:
    946 		mutex_exit(&sv->sv_mutex);
    947 		return (ENOTACTIVE);
    948 	}
    949 	mutex_exit(&sv->sv_mutex);
    950 
    951 	sr = smb_request_alloc(sv->sv_session, 0);
    952 	if (sr == NULL) {
    953 		smb_server_release(sv);
    954 		return (ENOMEM);
    955 	}
    956 
    957 	sr->user_cr = kcred;
    958 
    959 	error = smb_pathname_reduce(sr, kcred, ioc->path,
    960 	    NULL, NULL, &dnode, last_comp);
    961 
    962 	if (error) {
    963 		smb_request_free(sr);
    964 		smb_server_release(sv);
    965 		return (error);
    966 	}
    967 
    968 	error = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
    969 	    sv->si_root_smb_node, dnode, last_comp, &fnode);
    970 
    971 	smb_node_release(dnode);
    972 
    973 	if (error) {
    974 		smb_request_free(sr);
    975 		smb_server_release(sv);
    976 		return (error);
    977 	}
    978 
    979 	ASSERT(fnode->vp && fnode->vp->v_vfsp);
    980 
    981 #ifdef SMB_ENFORCE_NODEV
    982 	if (vfs_optionisset(fnode->vp->v_vfsp, MNTOPT_NODEVICES, NULL) == 0) {
    983 		smb_node_release(fnode);
    984 		smb_request_free(sr);
    985 		smb_server_release(sv);
    986 		return (EINVAL);
    987 	}
    988 #endif /* SMB_ENFORCE_NODEV */
    989 
    990 	if (!smb_vfs_hold(sv, fnode->vp->v_vfsp))
    991 		error = ENOMEM;
    992 
    993 	/*
    994 	 * The refcount on the smb_vfs has been incremented.
    995 	 * If it wasn't already, a hold has also been taken
    996 	 * on the root vnode of the file system.
    997 	 */
    998 
    999 	smb_node_release(fnode);
   1000 	smb_request_free(sr);
   1001 	smb_server_release(sv);
   1002 	return (error);
   1003 }
   1004 
   1005 /*
   1006  * smb_server_share_unexport()
   1007  *
   1008  * This function is invoked when a share is disabled to disconnect trees
   1009  * and close files.  Cleaning up may involve VOP and/or VFS calls, which
   1010  * may conflict/deadlock with stuck threads if something is amiss with the
   1011  * file system.  Queueing the request for asynchronous processing allows the
   1012  * call to return immediately so that, if the unshare is being done in the
   1013  * context of a forced unmount, the forced unmount will always be able to
   1014  * proceed (unblocking stuck I/O and eventually allowing all blocked unshare
   1015  * processes to complete).
   1016  *
   1017  * The path lookup to find the root vnode of the VFS in question and the
   1018  * release of this vnode are done synchronously prior to any associated
   1019  * unmount.  Doing these asynchronous to an associated unmount could run
   1020  * the risk of a spurious EBUSY for a standard unmount or an EIO during
   1021  * the path lookup due to a forced unmount finishing first.
   1022  */
   1023 
   1024 int
   1025 smb_server_share_unexport(smb_ioc_share_t *ioc)
   1026 {
   1027 	smb_server_t	*sv;
   1028 	smb_request_t	*sr;
   1029 	smb_unexport_t	*ux;
   1030 	smb_node_t	*fnode = NULL;
   1031 	smb_node_t	*dnode;
   1032 	char		last_comp[MAXNAMELEN];
   1033 	int		rc;
   1034 
   1035 	if ((rc = smb_server_lookup(&sv)))
   1036 		return (rc);
   1037 
   1038 	mutex_enter(&sv->sv_mutex);
   1039 	switch (sv->sv_state) {
   1040 	case SMB_SERVER_STATE_RUNNING:
   1041 		break;
   1042 	default:
   1043 		mutex_exit(&sv->sv_mutex);
   1044 		return (ENOTACTIVE);
   1045 	}
   1046 	mutex_exit(&sv->sv_mutex);
   1047 
   1048 	sr = smb_request_alloc(sv->sv_session, 0);
   1049 
   1050 	if (sr == NULL) {
   1051 		smb_server_release(sv);
   1052 		return (ENOMEM);
   1053 	}
   1054 
   1055 	sr->user_cr = kcred;
   1056 
   1057 	rc = smb_pathname_reduce(sr, kcred, ioc->path, NULL, NULL,
   1058 	    &dnode, last_comp);
   1059 
   1060 	if (rc) {
   1061 		smb_request_free(sr);
   1062 		smb_server_release(sv);
   1063 		return (rc);
   1064 	}
   1065 
   1066 	rc = smb_fsop_lookup(sr, kcred, SMB_FOLLOW_LINKS, sv->si_root_smb_node,
   1067 	    dnode, last_comp, &fnode);
   1068 
   1069 	smb_node_release(dnode);
   1070 	smb_request_free(sr);
   1071 
   1072 	if (rc) {
   1073 		smb_server_release(sv);
   1074 		return (rc);
   1075 	}
   1076 
   1077 	ASSERT(fnode->vp && fnode->vp->v_vfsp);
   1078 
   1079 	smb_vfs_rele(sv, fnode->vp->v_vfsp);
   1080 
   1081 	smb_node_release(fnode);
   1082 
   1083 	ux = kmem_cache_alloc(sv->si_cache_unexport, KM_SLEEP);
   1084 
   1085 	(void) strlcpy(ux->ux_sharename, ioc->name, MAXNAMELEN);
   1086 
   1087 	smb_slist_insert_tail(&sv->sv_unexport_list, ux);
   1088 	smb_thread_signal(&sv->si_thread_unexport);
   1089 
   1090 	smb_server_release(sv);
   1091 	return (0);
   1092 }
   1093 
   1094 /*
   1095  * smb_server_thread_unexport
   1096  *
   1097  * This function processes the unexport event list and disconnects shares
   1098  * asynchronously.  The function executes as a zone-specific thread.
   1099  *
   1100  * The server arg passed in is safe to use without a reference count, because
   1101  * the server cannot be deleted until smb_thread_stop()/destroy() return,
   1102  * which is also when the thread exits.
   1103  */
   1104 
   1105 static void
   1106 smb_server_thread_unexport(smb_thread_t *thread, void *arg)
   1107 {
   1108 	smb_server_t *sv = (smb_server_t *)arg;
   1109 	smb_unexport_t	*ux;
   1110 
   1111 	while (smb_thread_continue(thread)) {
   1112 		while ((ux = list_head(&sv->sv_unexport_list.sl_list))
   1113 		    != NULL) {
   1114 			smb_slist_remove(&sv->sv_unexport_list, ux);
   1115 			smb_server_disconnect_share(ux->ux_sharename, sv);
   1116 			kmem_cache_free(sv->si_cache_unexport, ux);
   1117 		}
   1118 	}
   1119 }
   1120 
   1121 /*
   1122  * This is a special interface that will be utilized by ZFS to cause a share to
   1123  * be added/removed.
   1124  *
   1125  * arg is either a lmshare_info_t or share_name from userspace.
   1126  * It will need to be copied into the kernel.   It is lmshare_info_t
   1127  * for add operations and share_name for delete operations.
   1128  */
   1129 int
   1130 smb_server_share(void *arg, boolean_t add_share)
   1131 {
   1132 	smb_server_t	*sv;
   1133 	int		rc;
   1134 
   1135 	rc = smb_server_lookup(&sv);
   1136 	if (rc == 0) {
   1137 		mutex_enter(&sv->sv_mutex);
   1138 		switch (sv->sv_state) {
   1139 		case SMB_SERVER_STATE_RUNNING:
   1140 			mutex_exit(&sv->sv_mutex);
   1141 			(void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share);
   1142 			break;
   1143 		default:
   1144 			mutex_exit(&sv->sv_mutex);
   1145 			break;
   1146 		}
   1147 		smb_server_release(sv);
   1148 	}
   1149 	return (0);
   1150 }
   1151 
   1152 /*
   1153  * *****************************************************************************
   1154  * **************** Functions called from the internal layers ******************
   1155  * *****************************************************************************
   1156  *
   1157  * These functions are provided the relevant smb server by the caller.
   1158  */
   1159 
   1160 void
   1161 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session)
   1162 {
   1163 	ASSERT(sv == session->s_server);
   1164 
   1165 	smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list,
   1166 	    session);
   1167 	smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list,
   1168 	    session);
   1169 }
   1170 
   1171 void
   1172 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg)
   1173 {
   1174 	rw_enter(&sv->sv_cfg_lock, RW_READER);
   1175 	bcopy(&sv->sv_cfg, cfg, sizeof (*cfg));
   1176 	rw_exit(&sv->sv_cfg_lock);
   1177 }
   1178 
   1179 /*
   1180  * *****************************************************************************
   1181  * *************************** Static Functions ********************************
   1182  * *****************************************************************************
   1183  */
   1184 
   1185 static void
   1186 smb_server_timers(smb_thread_t *thread, void *arg)
   1187 {
   1188 	smb_server_t	*sv = (smb_server_t *)arg;
   1189 
   1190 	ASSERT(sv != NULL);
   1191 
   1192 	while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) {
   1193 		smb_session_timers(&sv->sv_nbt_daemon.ld_session_list);
   1194 		smb_session_timers(&sv->sv_tcp_daemon.ld_session_list);
   1195 	}
   1196 }
   1197 
   1198 /*
   1199  * smb_server_kstat_init
   1200  */
   1201 static int
   1202 smb_server_kstat_init(smb_server_t *sv)
   1203 {
   1204 	(void) snprintf(sv->sv_ksp_name, sizeof (sv->sv_ksp_name), "%s%d",
   1205 	    SMBSRV_KSTAT_NAME, sv->sv_zid);
   1206 
   1207 	sv->sv_ksp = kstat_create(SMBSRV_KSTAT_MODULE, 0, sv->sv_ksp_name,
   1208 	    SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
   1209 	    sizeof (sv->sv_ks_data) / sizeof (kstat_named_t),
   1210 	    KSTAT_FLAG_VIRTUAL);
   1211 
   1212 	if (sv->sv_ksp) {
   1213 		(void) strlcpy(sv->sv_ks_data.open_files.name, "open_files",
   1214 		    sizeof (sv->sv_ks_data.open_files.name));
   1215 		sv->sv_ks_data.open_files.data_type = KSTAT_DATA_UINT32;
   1216 		(void) strlcpy(sv->sv_ks_data.open_trees.name, "connections",
   1217 		    sizeof (sv->sv_ks_data.open_trees.name));
   1218 		sv->sv_ks_data.open_trees.data_type = KSTAT_DATA_UINT32;
   1219 		(void) strlcpy(sv->sv_ks_data.open_users.name, "sessions",
   1220 		    sizeof (sv->sv_ks_data.open_users.name));
   1221 		sv->sv_ks_data.open_users.data_type = KSTAT_DATA_UINT32;
   1222 
   1223 		mutex_init(&sv->sv_ksp_mutex, NULL, MUTEX_DEFAULT, NULL);
   1224 		sv->sv_ksp->ks_lock = &sv->sv_ksp_mutex;
   1225 		sv->sv_ksp->ks_data = (void *)&sv->sv_ks_data;
   1226 		sv->sv_ksp->ks_update = smb_server_kstat_update_info;
   1227 		kstat_install(sv->sv_ksp);
   1228 	}
   1229 
   1230 	/* create and initialize smb kstats - smb_dispatch stats */
   1231 	smb_dispatch_kstat_init();
   1232 
   1233 	return (0);
   1234 }
   1235 
   1236 /*
   1237  * smb_server_kstat_fini
   1238  */
   1239 static void
   1240 smb_server_kstat_fini(smb_server_t *sv)
   1241 {
   1242 	if (sv->sv_ksp) {
   1243 		kstat_delete(sv->sv_ksp);
   1244 		mutex_destroy(&sv->sv_ksp_mutex);
   1245 		sv->sv_ksp = NULL;
   1246 	}
   1247 	smb_dispatch_kstat_fini();
   1248 }
   1249 
   1250 /* ARGSUSED */
   1251 static int
   1252 smb_server_kstat_update_info(kstat_t *ksp, int rw)
   1253 {
   1254 	smb_server_t	*sv;
   1255 
   1256 	if (rw == KSTAT_WRITE) {
   1257 		return (EACCES);
   1258 	} else {
   1259 		ASSERT(MUTEX_HELD(ksp->ks_lock));
   1260 
   1261 		_NOTE(LINTED("pointer cast may result in improper alignment"))
   1262 		sv = (smb_server_t *)((uint8_t *)(ksp->ks_data) -
   1263 		    offsetof(smb_server_t, sv_ks_data));
   1264 
   1265 		ASSERT(sv->sv_magic == SMB_SERVER_MAGIC);
   1266 
   1267 		sv->sv_ks_data.open_files.value.ui32 = sv->sv_open_files;
   1268 		sv->sv_ks_data.open_trees.value.ui32 = sv->sv_open_trees;
   1269 		sv->sv_ks_data.open_users.value.ui32 = sv->sv_open_users;
   1270 	}
   1271 	return (0);
   1272 }
   1273 
   1274 /*
   1275  * smb_server_stop
   1276  *
   1277  * The mutex of the server must have been entered before calling this function.
   1278  */
   1279 static void
   1280 smb_server_stop(smb_server_t *sv)
   1281 {
   1282 	ASSERT(sv->sv_magic == SMB_SERVER_MAGIC);
   1283 
   1284 	smb_opipe_door_close();
   1285 	smb_thread_stop(&sv->si_thread_timers);
   1286 	smb_thread_stop(&sv->si_thread_unexport);
   1287 	smb_kdoor_clnt_close();
   1288 	smb_kshare_fini(sv->sv_lmshrd);
   1289 	sv->sv_lmshrd = NULL;
   1290 	smb_server_fsop_stop(sv);
   1291 
   1292 	if (sv->sv_session) {
   1293 		smb_session_delete(sv->sv_session);
   1294 		sv->sv_session = NULL;
   1295 	}
   1296 
   1297 	if (sv->sv_thread_pool) {
   1298 		taskq_destroy(sv->sv_thread_pool);
   1299 		sv->sv_thread_pool = NULL;
   1300 	}
   1301 }
   1302 
   1303 static int
   1304 smb_server_listen(
   1305     smb_server_t		*sv,
   1306     smb_listener_daemon_t	*ld,
   1307     in_port_t			port,
   1308     int				family,
   1309     int				pthread_create_error)
   1310 {
   1311 	int			rc;
   1312 	ksocket_t		s_so;
   1313 	const uint32_t		on = 1;
   1314 	const uint32_t		off = 0;
   1315 	smb_session_t		*session;
   1316 
   1317 	if (pthread_create_error) {
   1318 		/*
   1319 		 * Delete the last session created. The user space thread
   1320 		 * creation failed.
   1321 		 */
   1322 		smb_session_list_delete_tail(&ld->ld_session_list);
   1323 	}
   1324 
   1325 	if (ld->ld_so == NULL) {
   1326 		/* First time listener */
   1327 		if (family == AF_INET) {
   1328 			ld->ld_sin.sin_family = (uint32_t)family;
   1329 			ld->ld_sin.sin_port = htons(port);
   1330 			ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
   1331 		} else {
   1332 			ld->ld_sin6.sin6_family = (uint32_t)family;
   1333 			ld->ld_sin6.sin6_port = htons(port);
   1334 			(void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0,
   1335 			    sizeof (ld->ld_sin6.sin6_addr.s6_addr));
   1336 		}
   1337 		ld->ld_so = smb_socreate(family, SOCK_STREAM, 0);
   1338 		if (ld->ld_so) {
   1339 
   1340 			(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
   1341 			    SO_MAC_EXEMPT, &off, sizeof (off), CRED());
   1342 			(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
   1343 			    SO_REUSEADDR, &on, sizeof (on), CRED());
   1344 
   1345 			if (family == AF_INET) {
   1346 				rc = ksocket_bind(ld->ld_so,
   1347 				    (struct sockaddr *)&ld->ld_sin,
   1348 				    sizeof (ld->ld_sin), CRED());
   1349 			} else {
   1350 				rc = ksocket_bind(ld->ld_so,
   1351 				    (struct sockaddr *)&ld->ld_sin6,
   1352 				    sizeof (ld->ld_sin6), CRED());
   1353 			}
   1354 			if (rc == 0) {
   1355 				rc =  ksocket_listen(ld->ld_so, 20, CRED());
   1356 				if (rc < 0) {
   1357 					cmn_err(CE_WARN,
   1358 					    "Port %d: listen failed", port);
   1359 					smb_soshutdown(ld->ld_so);
   1360 					smb_sodestroy(ld->ld_so);
   1361 					ld->ld_so = NULL;
   1362 					return (rc);
   1363 				}
   1364 			} else {
   1365 				cmn_err(CE_WARN,
   1366 				    "Port %d: bind failed", port);
   1367 				smb_soshutdown(ld->ld_so);
   1368 				smb_sodestroy(ld->ld_so);
   1369 				ld->ld_so = NULL;
   1370 				return (rc);
   1371 			}
   1372 		} else {
   1373 			cmn_err(CE_WARN,
   1374 			    "Port %d: socket create failed", port);
   1375 			return (ENOMEM);
   1376 		}
   1377 	}
   1378 
   1379 	DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so);
   1380 
   1381 	for (;;) {
   1382 		rc = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED());
   1383 		if (rc == 0) {
   1384 			uint32_t	txbuf_size = 128*1024;
   1385 			uint32_t	on = 1;
   1386 
   1387 			DTRACE_PROBE1(so__accept, struct sonode *, s_so);
   1388 
   1389 			(void) ksocket_setsockopt(s_so, IPPROTO_TCP,
   1390 			    TCP_NODELAY, &on, sizeof (on), CRED());
   1391 			(void) ksocket_setsockopt(s_so, SOL_SOCKET,
   1392 			    SO_KEEPALIVE, &on, sizeof (on), CRED());
   1393 			(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
   1394 			    (const void *)&txbuf_size, sizeof (txbuf_size),
   1395 			    CRED());
   1396 			/*
   1397 			 * Create a session for this connection.
   1398 			 */
   1399 			session = smb_session_create(s_so, port, sv, family);
   1400 			if (session) {
   1401 				smb_session_list_append(&ld->ld_session_list,
   1402 				    session);
   1403 				break;
   1404 			} else {
   1405 				smb_soshutdown(s_so);
   1406 				smb_sodestroy(s_so);
   1407 			}
   1408 			continue;
   1409 		}
   1410 		smb_session_list_signal(&ld->ld_session_list);
   1411 		smb_soshutdown(ld->ld_so);
   1412 		smb_sodestroy(ld->ld_so);
   1413 		ld->ld_so = NULL;
   1414 		break;
   1415 	}
   1416 
   1417 	return (rc);
   1418 }
   1419 
   1420 /*
   1421  * smb_server_lookup
   1422  *
   1423  * This function tries to find the server associated with the zone of the
   1424  * caller.
   1425  */
   1426 static int
   1427 smb_server_lookup(smb_server_t **psv)
   1428 {
   1429 	zoneid_t	zid;
   1430 	smb_server_t	*sv;
   1431 
   1432 	zid = getzoneid();
   1433 
   1434 	smb_llist_enter(&smb_servers, RW_READER);
   1435 	sv = smb_llist_head(&smb_servers);
   1436 	while (sv) {
   1437 		ASSERT(sv->sv_magic == SMB_SERVER_MAGIC);
   1438 		if (sv->sv_zid == zid) {
   1439 			mutex_enter(&sv->sv_mutex);
   1440 			if (sv->sv_state != SMB_SERVER_STATE_DELETING) {
   1441 				sv->sv_refcnt++;
   1442 				mutex_exit(&sv->sv_mutex);
   1443 				smb_llist_exit(&smb_servers);
   1444 				*psv = sv;
   1445 				return (0);
   1446 			}
   1447 			mutex_exit(&sv->sv_mutex);
   1448 			break;
   1449 		}
   1450 		sv = smb_llist_next(&smb_servers, sv);
   1451 	}
   1452 	smb_llist_exit(&smb_servers);
   1453 	return (EPERM);
   1454 }
   1455 
   1456 /*
   1457  * smb_server_release
   1458  *
   1459  * This function decrements the reference count of the server and signals its
   1460  * condition variable if the state of the server is SMB_SERVER_STATE_DELETING.
   1461  */
   1462 static void
   1463 smb_server_release(smb_server_t *sv)
   1464 {
   1465 	ASSERT(sv->sv_magic == SMB_SERVER_MAGIC);
   1466 
   1467 	mutex_enter(&sv->sv_mutex);
   1468 	ASSERT(sv->sv_refcnt);
   1469 	sv->sv_refcnt--;
   1470 	if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING))
   1471 		cv_signal(&sv->sv_cv);
   1472 	mutex_exit(&sv->sv_mutex);
   1473 }
   1474 
   1475 /*
   1476  * Enumerate the users associated with a session list.
   1477  */
   1478 static void
   1479 smb_server_enum_private(smb_session_list_t *se, smb_svcenum_t *svcenum)
   1480 {
   1481 	smb_session_t	*sn;
   1482 	smb_llist_t	*ulist;
   1483 	smb_user_t	*user;
   1484 	int		rc = 0;
   1485 
   1486 	rw_enter(&se->se_lock, RW_READER);
   1487 	sn = list_head(&se->se_act.lst);
   1488 
   1489 	while (sn != NULL) {
   1490 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
   1491 		ulist = &sn->s_user_list;
   1492 		smb_llist_enter(ulist, RW_READER);
   1493 		user = smb_llist_head(ulist);
   1494 
   1495 		while (user != NULL) {
   1496 			if (smb_user_hold(user)) {
   1497 				rc = smb_user_enum(user, svcenum);
   1498 				smb_user_release(user);
   1499 			}
   1500 
   1501 			user = smb_llist_next(ulist, user);
   1502 		}
   1503 
   1504 		smb_llist_exit(ulist);
   1505 
   1506 		if (rc != 0)
   1507 			break;
   1508 
   1509 		sn = list_next(&se->se_act.lst, sn);
   1510 	}
   1511 
   1512 	rw_exit(&se->se_lock);
   1513 }
   1514 
   1515 /*
   1516  * Disconnect sessions associated with the specified client and username.
   1517  * Empty strings are treated as wildcards.
   1518  */
   1519 static int
   1520 smb_server_sesion_disconnect(smb_session_list_t *se,
   1521     const char *client, const char *name)
   1522 {
   1523 	smb_session_t	*sn;
   1524 	smb_llist_t	*ulist;
   1525 	smb_user_t	*user;
   1526 	boolean_t	match;
   1527 	int		count = 0;
   1528 
   1529 	rw_enter(&se->se_lock, RW_READER);
   1530 	sn = list_head(&se->se_act.lst);
   1531 
   1532 	while (sn != NULL) {
   1533 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
   1534 
   1535 		if ((*client != '\0') && (!smb_session_isclient(sn, client))) {
   1536 			sn = list_next(&se->se_act.lst, sn);
   1537 			continue;
   1538 		}
   1539 
   1540 		ulist = &sn->s_user_list;
   1541 		smb_llist_enter(ulist, RW_READER);
   1542 		user = smb_llist_head(ulist);
   1543 
   1544 		while (user != NULL) {
   1545 			if (smb_user_hold(user)) {
   1546 				match = (*name == '\0');
   1547 				if (!match)
   1548 					match = smb_user_namecmp(user, name);
   1549 
   1550 				if (match) {
   1551 					smb_llist_exit(ulist);
   1552 					smb_user_logoff(user);
   1553 					++count;
   1554 					smb_user_release(user);
   1555 					smb_llist_enter(ulist, RW_READER);
   1556 					user = smb_llist_head(ulist);
   1557 					continue;
   1558 				}
   1559 
   1560 				smb_user_release(user);
   1561 			}
   1562 
   1563 			user = smb_llist_next(ulist, user);
   1564 		}
   1565 
   1566 		smb_llist_exit(ulist);
   1567 		sn = list_next(&se->se_act.lst, sn);
   1568 	}
   1569 
   1570 	rw_exit(&se->se_lock);
   1571 	return (count);
   1572 }
   1573 
   1574 /*
   1575  * Close a file by its unique id.
   1576  */
   1577 static int
   1578 smb_server_fclose(smb_session_list_t *se, uint32_t uniqid)
   1579 {
   1580 	smb_session_t	*sn;
   1581 	smb_llist_t	*ulist;
   1582 	smb_user_t	*user;
   1583 	int		rc = ENOENT;
   1584 
   1585 	rw_enter(&se->se_lock, RW_READER);
   1586 	sn = list_head(&se->se_act.lst);
   1587 
   1588 	while ((sn != NULL) && (rc == ENOENT)) {
   1589 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
   1590 		ulist = &sn->s_user_list;
   1591 		smb_llist_enter(ulist, RW_READER);
   1592 		user = smb_llist_head(ulist);
   1593 
   1594 		while ((user != NULL) && (rc == ENOENT)) {
   1595 			if (smb_user_hold(user)) {
   1596 				rc = smb_user_fclose(user, uniqid);
   1597 				smb_user_release(user);
   1598 			}
   1599 
   1600 			user = smb_llist_next(ulist, user);
   1601 		}
   1602 
   1603 		smb_llist_exit(ulist);
   1604 		sn = list_next(&se->se_act.lst, sn);
   1605 	}
   1606 
   1607 	rw_exit(&se->se_lock);
   1608 	return (rc);
   1609 }
   1610 
   1611 static void
   1612 smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc)
   1613 {
   1614 	if (ioc->maxconnections == 0)
   1615 		ioc->maxconnections = 0xFFFFFFFF;
   1616 
   1617 	smb_session_correct_keep_alive_values(
   1618 	    &sv->sv_nbt_daemon.ld_session_list, ioc->keepalive);
   1619 	smb_session_correct_keep_alive_values(
   1620 	    &sv->sv_tcp_daemon.ld_session_list, ioc->keepalive);
   1621 
   1622 	sv->sv_cfg.skc_maxworkers = ioc->maxworkers;
   1623 	sv->sv_cfg.skc_maxconnections = ioc->maxconnections;
   1624 	sv->sv_cfg.skc_keepalive = ioc->keepalive;
   1625 	sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon;
   1626 	sv->sv_cfg.skc_signing_enable = ioc->signing_enable;
   1627 	sv->sv_cfg.skc_signing_required = ioc->signing_required;
   1628 	sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable;
   1629 	sv->sv_cfg.skc_sync_enable = ioc->sync_enable;
   1630 	sv->sv_cfg.skc_secmode = ioc->secmode;
   1631 	sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
   1632 	(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
   1633 	    sizeof (sv->sv_cfg.skc_nbdomain));
   1634 	(void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn,
   1635 	    sizeof (sv->sv_cfg.skc_fqdn));
   1636 	(void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname,
   1637 	    sizeof (sv->sv_cfg.skc_hostname));
   1638 	(void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment,
   1639 	    sizeof (sv->sv_cfg.skc_system_comment));
   1640 }
   1641 
   1642 static int
   1643 smb_server_fsop_start(smb_server_t *sv)
   1644 {
   1645 	int	error;
   1646 
   1647 	error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node);
   1648 	if (error != 0)
   1649 		sv->si_root_smb_node = NULL;
   1650 
   1651 	return (error);
   1652 }
   1653 
   1654 static void
   1655 smb_server_fsop_stop(smb_server_t *sv)
   1656 {
   1657 	if (sv->si_root_smb_node != NULL) {
   1658 		smb_vfs_rele_all(sv);
   1659 		smb_node_release(sv->si_root_smb_node);
   1660 		sv->si_root_smb_node = NULL;
   1661 	}
   1662 }
   1663