1*6139Sjb150015 /* 2*6139Sjb150015 * CDDL HEADER START 3*6139Sjb150015 * 4*6139Sjb150015 * The contents of this file are subject to the terms of the 5*6139Sjb150015 * Common Development and Distribution License (the "License"). 6*6139Sjb150015 * You may not use this file except in compliance with the License. 7*6139Sjb150015 * 8*6139Sjb150015 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6139Sjb150015 * or http://www.opensolaris.org/os/licensing. 10*6139Sjb150015 * See the License for the specific language governing permissions 11*6139Sjb150015 * and limitations under the License. 12*6139Sjb150015 * 13*6139Sjb150015 * When distributing Covered Code, include this CDDL HEADER in each 14*6139Sjb150015 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6139Sjb150015 * If applicable, add the following below this CDDL HEADER, with the 16*6139Sjb150015 * fields enclosed by brackets "[]" replaced with your own identifying 17*6139Sjb150015 * information: Portions Copyright [yyyy] [name of copyright owner] 18*6139Sjb150015 * 19*6139Sjb150015 * CDDL HEADER END 20*6139Sjb150015 */ 21*6139Sjb150015 /* 22*6139Sjb150015 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*6139Sjb150015 * Use is subject to license terms. 24*6139Sjb150015 */ 25*6139Sjb150015 26*6139Sjb150015 #pragma ident "%Z%%M% %I% %E% SMI" 27*6139Sjb150015 28*6139Sjb150015 /* 29*6139Sjb150015 * General Structures Layout 30*6139Sjb150015 * ------------------------- 31*6139Sjb150015 * 32*6139Sjb150015 * This is a simplified diagram showing the relationship between most of the 33*6139Sjb150015 * main structures. 34*6139Sjb150015 * 35*6139Sjb150015 * +-------------------+ 36*6139Sjb150015 * | SMB_SERVER | 37*6139Sjb150015 * +-------------------+ 38*6139Sjb150015 * | 39*6139Sjb150015 * | 40*6139Sjb150015 * v 41*6139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 42*6139Sjb150015 * | SESSION |<----->| SESSION |......| SESSION | 43*6139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 44*6139Sjb150015 * | 45*6139Sjb150015 * | 46*6139Sjb150015 * v 47*6139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 48*6139Sjb150015 * | USER |<----->| USER |......| USER | 49*6139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 50*6139Sjb150015 * | 51*6139Sjb150015 * | 52*6139Sjb150015 * v 53*6139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 54*6139Sjb150015 * | TREE |<----->| TREE |......| TREE | 55*6139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 56*6139Sjb150015 * | | 57*6139Sjb150015 * | | 58*6139Sjb150015 * | v 59*6139Sjb150015 * | +-------+ +-------+ +-------+ 60*6139Sjb150015 * | | OFILE |<----->| OFILE |......| OFILE | 61*6139Sjb150015 * | +-------+ +-------+ +-------+ 62*6139Sjb150015 * | 63*6139Sjb150015 * | 64*6139Sjb150015 * v 65*6139Sjb150015 * +-------+ +------+ +------+ 66*6139Sjb150015 * | ODIR |<----->| ODIR |......| ODIR | 67*6139Sjb150015 * +-------+ +------+ +------+ 68*6139Sjb150015 * 69*6139Sjb150015 * 70*6139Sjb150015 * Module Interface Overview 71*6139Sjb150015 * ------------------------- 72*6139Sjb150015 * 73*6139Sjb150015 * 74*6139Sjb150015 * +===================================+ 75*6139Sjb150015 * | smbd daemon | 76*6139Sjb150015 * +===================================+ 77*6139Sjb150015 * | | ^ 78*6139Sjb150015 * | | | 79*6139Sjb150015 * User | | | 80*6139Sjb150015 * -----------|--------------|----------------|-------------------------------- 81*6139Sjb150015 * Kernel | | | 82*6139Sjb150015 * | | | 83*6139Sjb150015 * | | | 84*6139Sjb150015 * +=========|==============|================|=================+ 85*6139Sjb150015 * | v v | | 86*6139Sjb150015 * | +-----------+ +--------------------+ +------------------+ | 87*6139Sjb150015 * | | IO | | Kernel Door Server | | User Door Servers| | 88*6139Sjb150015 * | | Interface | | Interface | | Interface | | 89*6139Sjb150015 * | +-----------+ +--------------------+ +------------------+ | 90*6139Sjb150015 * | | | ^ ^ | 91*6139Sjb150015 * | v v | | | +=========+ 92*6139Sjb150015 * | +-----------------------------------+ | | | | 93*6139Sjb150015 * | + SMB Server Management (this file) |<------------------| ZFS | 94*6139Sjb150015 * | +-----------------------------------+ | | | | 95*6139Sjb150015 * | | | | Module | 96*6139Sjb150015 * | +-----------------------------------+ | | | | 97*6139Sjb150015 * | + SMB Server Internal Layers |------+ | +=========+ 98*6139Sjb150015 * | +-----------------------------------+ | 99*6139Sjb150015 * | | 100*6139Sjb150015 * | | 101*6139Sjb150015 * +===========================================================+ 102*6139Sjb150015 * 103*6139Sjb150015 * 104*6139Sjb150015 * Server State Machine 105*6139Sjb150015 * -------------------- 106*6139Sjb150015 * | 107*6139Sjb150015 * | T0 108*6139Sjb150015 * | 109*6139Sjb150015 * v 110*6139Sjb150015 * +-----------------------------+ 111*6139Sjb150015 * | SMB_SERVER_STATE_CREATED | 112*6139Sjb150015 * +-----------------------------+ 113*6139Sjb150015 * | 114*6139Sjb150015 * | T1 115*6139Sjb150015 * | 116*6139Sjb150015 * v 117*6139Sjb150015 * +-----------------------------+ 118*6139Sjb150015 * | SMB_SERVER_STATE_CONFIGURED | 119*6139Sjb150015 * +-----------------------------+ 120*6139Sjb150015 * | 121*6139Sjb150015 * | T2 122*6139Sjb150015 * | 123*6139Sjb150015 * v 124*6139Sjb150015 * +-----------------------------+ 125*6139Sjb150015 * | SMB_SERVER_STATE_RUNNING | 126*6139Sjb150015 * +-----------------------------+ 127*6139Sjb150015 * | 128*6139Sjb150015 * | T3 129*6139Sjb150015 * | 130*6139Sjb150015 * v 131*6139Sjb150015 * +-----------------------------+ 132*6139Sjb150015 * | SMB_SERVER_STATE_DELETING | 133*6139Sjb150015 * +-----------------------------+ 134*6139Sjb150015 * | 135*6139Sjb150015 * | 136*6139Sjb150015 * | 137*6139Sjb150015 * v 138*6139Sjb150015 * 139*6139Sjb150015 * States 140*6139Sjb150015 * ------ 141*6139Sjb150015 * 142*6139Sjb150015 * SMB_SERVER_STATE_CREATED 143*6139Sjb150015 * 144*6139Sjb150015 * This is the state of the server just after creation. 145*6139Sjb150015 * 146*6139Sjb150015 * SMB_SERVER_STATE_CONFIGURED 147*6139Sjb150015 * 148*6139Sjb150015 * The server has been configured. 149*6139Sjb150015 * 150*6139Sjb150015 * SMB_SERVER_STATE_RUNNING 151*6139Sjb150015 * 152*6139Sjb150015 * The server has been started. While in this state the threads listening on 153*6139Sjb150015 * the sockets car be started. The smbd daemon does so through an Ioctl: 154*6139Sjb150015 * 155*6139Sjb150015 * smb_drv_ioctl(SMB_IOC_NBT_LISTEN) --> smb_server_nbt_listen() 156*6139Sjb150015 * smb_drv_ioctl(SMB_IOC_TCP_LISTEN) --> smb_server_nbt_listen() 157*6139Sjb150015 * 158*6139Sjb150015 * When a client establishes a connection the thread listening leaves 159*6139Sjb150015 * temporarily the kernel. While in user space it creates a thread for the 160*6139Sjb150015 * new session. It then returns to kernel with the result of the thread 161*6139Sjb150015 * creation. If the creation failed the new session context is destroyed 162*6139Sjb150015 * before returning listening. 163*6139Sjb150015 * 164*6139Sjb150015 * The new created thread enters the kernel though an Ioctl: 165*6139Sjb150015 * 166*6139Sjb150015 * smb_drv_ioctl(SMB_IOC_NBT_RECEIVE) --> smb_server_nbt_receive() 167*6139Sjb150015 * smb_drv_ioctl(SMB_IOC_TCP_RECEIVE) --> smb_server_tcp_receive() 168*6139Sjb150015 * 169*6139Sjb150015 * SMB_SERVER_STATE_STOPPING 170*6139Sjb150015 * 171*6139Sjb150015 * The threads listening on the NBT and TCP sockets are being terminated. 172*6139Sjb150015 * 173*6139Sjb150015 * 174*6139Sjb150015 * Transitions 175*6139Sjb150015 * ----------- 176*6139Sjb150015 * 177*6139Sjb150015 * Transition T0 178*6139Sjb150015 * 179*6139Sjb150015 * The daemon smbd triggers its creation by opening the smbsrv device. If 180*6139Sjb150015 * the zone where the daemon lives doesn't have an smb server yet it is 181*6139Sjb150015 * created. 182*6139Sjb150015 * 183*6139Sjb150015 * smb_drv_open() --> smb_server_create() 184*6139Sjb150015 * 185*6139Sjb150015 * Transition T1 186*6139Sjb150015 * 187*6139Sjb150015 * This transition occurs in smb_server_configure(). It is triggered by the 188*6139Sjb150015 * daemon through an Ioctl. 189*6139Sjb150015 * 190*6139Sjb150015 * smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure() 191*6139Sjb150015 * 192*6139Sjb150015 * Transition T2 193*6139Sjb150015 * 194*6139Sjb150015 * This transition occurs in smb_server_start(). It is triggered by the 195*6139Sjb150015 * daemon through an Ioctl. 196*6139Sjb150015 * 197*6139Sjb150015 * smb_drv_ioctl(SMB_IOC_START) --> smb_server_start() 198*6139Sjb150015 * 199*6139Sjb150015 * Transition T3 200*6139Sjb150015 * 201*6139Sjb150015 * This transition occurs in smb_server_delete(). It is triggered by the 202*6139Sjb150015 * daemon when closing the smbsrv device 203*6139Sjb150015 * 204*6139Sjb150015 * smb_drv_close() --> smb_server_delete() 205*6139Sjb150015 * 206*6139Sjb150015 * Comments 207*6139Sjb150015 * -------- 208*6139Sjb150015 * 209*6139Sjb150015 * This files assumes that there will one SMB server per zone. For now the 210*6139Sjb150015 * smb server works only in global zone. There's nothing in this file preventing 211*6139Sjb150015 * an smb server from being created in a non global zone. That limitation is 212*6139Sjb150015 * enforced in user space. 213*6139Sjb150015 */ 214*6139Sjb150015 215*6139Sjb150015 #include <sys/strsubr.h> 216*6139Sjb150015 #include <sys/cmn_err.h> 217*6139Sjb150015 #include <sys/priv.h> 218*6139Sjb150015 #include <sys/socketvar.h> 219*6139Sjb150015 #include <sys/zone.h> 220*6139Sjb150015 #include <smbsrv/smb_kproto.h> 221*6139Sjb150015 #include <smbsrv/netbios.h> 222*6139Sjb150015 #include <smbsrv/smb_incl.h> 223*6139Sjb150015 #include <smbsrv/cifs.h> 224*6139Sjb150015 #include <smbsrv/smb_fsops.h> 225*6139Sjb150015 #include <smbsrv/lmshare.h> 226*6139Sjb150015 #include <smbsrv/smb_door_svc.h> 227*6139Sjb150015 228*6139Sjb150015 extern void smb_dispatch_kstat_init(void); 229*6139Sjb150015 extern void smb_dispatch_kstat_fini(void); 230*6139Sjb150015 extern void smb_reply_notify_change_request(smb_request_t *); 231*6139Sjb150015 232*6139Sjb150015 static int smb_server_kstat_init(smb_server_t *); 233*6139Sjb150015 static void smb_server_kstat_fini(smb_server_t *); 234*6139Sjb150015 static int smb_server_kstat_update_info(kstat_t *, int); 235*6139Sjb150015 static void smb_server_timers(smb_thread_t *, void *); 236*6139Sjb150015 static int smb_server_listen(smb_server_t *, smb_listener_daemon_t *, 237*6139Sjb150015 in_port_t, int); 238*6139Sjb150015 static int smb_server_lookup(smb_server_t **); 239*6139Sjb150015 static void smb_server_release(smb_server_t *); 240*6139Sjb150015 static int smb_server_ulist_geti(smb_session_list_t *, int, smb_dr_user_ctx_t *, 241*6139Sjb150015 int); 242*6139Sjb150015 static void smb_server_store_cfg(smb_server_t *, smb_kmod_cfg_t *); 243*6139Sjb150015 static void smb_server_stop(smb_server_t *); 244*6139Sjb150015 static int smb_server_fsop_start(smb_server_t *); 245*6139Sjb150015 static void smb_server_fsop_stop(smb_server_t *); 246*6139Sjb150015 247*6139Sjb150015 static smb_llist_t smb_servers; 248*6139Sjb150015 249*6139Sjb150015 /* 250*6139Sjb150015 * ***************************************************************************** 251*6139Sjb150015 * **************** Functions called from the device interface ***************** 252*6139Sjb150015 * ***************************************************************************** 253*6139Sjb150015 * 254*6139Sjb150015 * These functions determine the relevant smb server to which the call apply. 255*6139Sjb150015 */ 256*6139Sjb150015 257*6139Sjb150015 /* 258*6139Sjb150015 * smb_server_svc_init 259*6139Sjb150015 * 260*6139Sjb150015 * This function must called from smb_drv_attach(). 261*6139Sjb150015 */ 262*6139Sjb150015 int 263*6139Sjb150015 smb_server_svc_init(void) 264*6139Sjb150015 { 265*6139Sjb150015 int rc = 0; 266*6139Sjb150015 267*6139Sjb150015 while (rc == 0) { 268*6139Sjb150015 if (rc = smb_vop_init()) 269*6139Sjb150015 continue; 270*6139Sjb150015 if (rc = smb_node_init()) 271*6139Sjb150015 break; 272*6139Sjb150015 if (rc = smb_fem_init()) 273*6139Sjb150015 break; 274*6139Sjb150015 if (rc = smb_notify_init()) 275*6139Sjb150015 break; 276*6139Sjb150015 if (rc = smb_kdoor_srv_start()) 277*6139Sjb150015 break; 278*6139Sjb150015 smb_llist_constructor(&smb_servers, sizeof (smb_server_t), 279*6139Sjb150015 offsetof(smb_server_t, sv_lnd)); 280*6139Sjb150015 return (0); 281*6139Sjb150015 } 282*6139Sjb150015 smb_notify_fini(); 283*6139Sjb150015 smb_fem_fini(); 284*6139Sjb150015 smb_node_fini(); 285*6139Sjb150015 smb_vop_fini(); 286*6139Sjb150015 return (rc); 287*6139Sjb150015 } 288*6139Sjb150015 289*6139Sjb150015 /* 290*6139Sjb150015 * smb_server_svc_fini 291*6139Sjb150015 * 292*6139Sjb150015 * This function must called from smb_drv_detach(). It will fail if servers 293*6139Sjb150015 * still exist. 294*6139Sjb150015 */ 295*6139Sjb150015 int 296*6139Sjb150015 smb_server_svc_fini(void) 297*6139Sjb150015 { 298*6139Sjb150015 int rc = EBUSY; 299*6139Sjb150015 300*6139Sjb150015 if (smb_llist_get_count(&smb_servers) == 0) { 301*6139Sjb150015 smb_kdoor_srv_stop(); 302*6139Sjb150015 smb_notify_fini(); 303*6139Sjb150015 smb_fem_fini(); 304*6139Sjb150015 smb_node_fini(); 305*6139Sjb150015 smb_vop_fini(); 306*6139Sjb150015 smb_llist_destructor(&smb_servers); 307*6139Sjb150015 rc = 0; 308*6139Sjb150015 } 309*6139Sjb150015 return (rc); 310*6139Sjb150015 } 311*6139Sjb150015 312*6139Sjb150015 /* 313*6139Sjb150015 * smb_server_create 314*6139Sjb150015 * 315*6139Sjb150015 * This function will fail if there's already a server associated with the 316*6139Sjb150015 * caller's zone. 317*6139Sjb150015 */ 318*6139Sjb150015 int 319*6139Sjb150015 smb_server_create(void) 320*6139Sjb150015 { 321*6139Sjb150015 zoneid_t zid; 322*6139Sjb150015 smb_server_t *sv; 323*6139Sjb150015 324*6139Sjb150015 zid = getzoneid(); 325*6139Sjb150015 326*6139Sjb150015 smb_llist_enter(&smb_servers, RW_WRITER); 327*6139Sjb150015 sv = smb_llist_head(&smb_servers); 328*6139Sjb150015 while (sv) { 329*6139Sjb150015 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 330*6139Sjb150015 if (sv->sv_zid == zid) { 331*6139Sjb150015 smb_llist_exit(&smb_servers); 332*6139Sjb150015 return (EEXIST); 333*6139Sjb150015 } 334*6139Sjb150015 sv = smb_llist_next(&smb_servers, sv); 335*6139Sjb150015 } 336*6139Sjb150015 337*6139Sjb150015 sv = kmem_zalloc(sizeof (smb_server_t), KM_NOSLEEP); 338*6139Sjb150015 if (sv == NULL) { 339*6139Sjb150015 smb_llist_exit(&smb_servers); 340*6139Sjb150015 return (ENOMEM); 341*6139Sjb150015 } 342*6139Sjb150015 343*6139Sjb150015 smb_llist_constructor(&sv->sv_vfs_list, sizeof (smb_vfs_t), 344*6139Sjb150015 offsetof(smb_vfs_t, sv_lnd)); 345*6139Sjb150015 346*6139Sjb150015 smb_session_list_constructor(&sv->sv_nbt_daemon.ld_session_list); 347*6139Sjb150015 smb_session_list_constructor(&sv->sv_tcp_daemon.ld_session_list); 348*6139Sjb150015 349*6139Sjb150015 sv->si_cache_vfs = kmem_cache_create("smb_vfs_cache", 350*6139Sjb150015 sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 351*6139Sjb150015 sv->si_cache_request = kmem_cache_create("smb_request_cache", 352*6139Sjb150015 sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 353*6139Sjb150015 sv->si_cache_session = kmem_cache_create("smb_session_cache", 354*6139Sjb150015 sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 355*6139Sjb150015 sv->si_cache_user = kmem_cache_create("smb_user_cache", 356*6139Sjb150015 sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 357*6139Sjb150015 sv->si_cache_tree = kmem_cache_create("smb_tree_cache", 358*6139Sjb150015 sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 359*6139Sjb150015 sv->si_cache_ofile = kmem_cache_create("smb_ofile_cache", 360*6139Sjb150015 sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 361*6139Sjb150015 sv->si_cache_odir = kmem_cache_create("smb_odir_cache", 362*6139Sjb150015 sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 363*6139Sjb150015 sv->si_cache_node = kmem_cache_create("smb_node_cache", 364*6139Sjb150015 sizeof (smb_node_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 365*6139Sjb150015 366*6139Sjb150015 smb_thread_init(&sv->si_thread_timers, 367*6139Sjb150015 "smb_timers", smb_server_timers, sv, 368*6139Sjb150015 NULL, NULL); 369*6139Sjb150015 370*6139Sjb150015 sv->sv_proc = curproc; 371*6139Sjb150015 372*6139Sjb150015 smb_winpipe_init(); 373*6139Sjb150015 (void) smb_server_kstat_init(sv); 374*6139Sjb150015 375*6139Sjb150015 mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL); 376*6139Sjb150015 cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL); 377*6139Sjb150015 sv->sv_state = SMB_SERVER_STATE_CREATED; 378*6139Sjb150015 sv->sv_magic = SMB_SERVER_MAGIC; 379*6139Sjb150015 sv->sv_zid = zid; 380*6139Sjb150015 381*6139Sjb150015 smb_llist_insert_tail(&smb_servers, sv); 382*6139Sjb150015 smb_llist_exit(&smb_servers); 383*6139Sjb150015 return (0); 384*6139Sjb150015 } 385*6139Sjb150015 386*6139Sjb150015 /* 387*6139Sjb150015 * smb_server_delete 388*6139Sjb150015 * 389*6139Sjb150015 * This function will delete the server passed in. It will make sure that all 390*6139Sjb150015 * activity associated that server has ceased before destroying it. 391*6139Sjb150015 */ 392*6139Sjb150015 int 393*6139Sjb150015 smb_server_delete(void) 394*6139Sjb150015 { 395*6139Sjb150015 smb_server_t *sv; 396*6139Sjb150015 int rc; 397*6139Sjb150015 398*6139Sjb150015 rc = smb_server_lookup(&sv); 399*6139Sjb150015 if (rc != 0) 400*6139Sjb150015 return (rc); 401*6139Sjb150015 402*6139Sjb150015 mutex_enter(&sv->sv_mutex); 403*6139Sjb150015 switch (sv->sv_state) { 404*6139Sjb150015 case SMB_SERVER_STATE_RUNNING: 405*6139Sjb150015 { 406*6139Sjb150015 boolean_t nbt = B_FALSE; 407*6139Sjb150015 boolean_t tcp = B_FALSE; 408*6139Sjb150015 409*6139Sjb150015 if (sv->sv_nbt_daemon.ld_kth) { 410*6139Sjb150015 tsignal(sv->sv_nbt_daemon.ld_kth, SIGINT); 411*6139Sjb150015 nbt = B_TRUE; 412*6139Sjb150015 } 413*6139Sjb150015 if (sv->sv_tcp_daemon.ld_kth) { 414*6139Sjb150015 tsignal(sv->sv_tcp_daemon.ld_kth, SIGINT); 415*6139Sjb150015 tcp = B_TRUE; 416*6139Sjb150015 } 417*6139Sjb150015 sv->sv_state = SMB_SERVER_STATE_DELETING; 418*6139Sjb150015 mutex_exit(&sv->sv_mutex); 419*6139Sjb150015 if (nbt) 420*6139Sjb150015 thread_join(sv->sv_nbt_daemon.ld_ktdid); 421*6139Sjb150015 if (tcp) 422*6139Sjb150015 thread_join(sv->sv_tcp_daemon.ld_ktdid); 423*6139Sjb150015 mutex_enter(&sv->sv_mutex); 424*6139Sjb150015 break; 425*6139Sjb150015 } 426*6139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 427*6139Sjb150015 case SMB_SERVER_STATE_CREATED: 428*6139Sjb150015 sv->sv_state = SMB_SERVER_STATE_DELETING; 429*6139Sjb150015 break; 430*6139Sjb150015 default: 431*6139Sjb150015 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 432*6139Sjb150015 mutex_exit(&sv->sv_mutex); 433*6139Sjb150015 smb_server_release(sv); 434*6139Sjb150015 return (ENOTTY); 435*6139Sjb150015 } 436*6139Sjb150015 437*6139Sjb150015 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 438*6139Sjb150015 439*6139Sjb150015 sv->sv_refcnt--; 440*6139Sjb150015 while (sv->sv_refcnt) 441*6139Sjb150015 cv_wait(&sv->sv_cv, &sv->sv_mutex); 442*6139Sjb150015 443*6139Sjb150015 mutex_exit(&sv->sv_mutex); 444*6139Sjb150015 445*6139Sjb150015 smb_llist_enter(&smb_servers, RW_WRITER); 446*6139Sjb150015 smb_llist_remove(&smb_servers, sv); 447*6139Sjb150015 smb_llist_exit(&smb_servers); 448*6139Sjb150015 449*6139Sjb150015 smb_server_stop(sv); 450*6139Sjb150015 rw_destroy(&sv->sv_cfg_lock); 451*6139Sjb150015 smb_winpipe_fini(); 452*6139Sjb150015 smb_server_kstat_fini(sv); 453*6139Sjb150015 smb_llist_destructor(&sv->sv_vfs_list); 454*6139Sjb150015 kmem_cache_destroy(sv->si_cache_vfs); 455*6139Sjb150015 kmem_cache_destroy(sv->si_cache_request); 456*6139Sjb150015 kmem_cache_destroy(sv->si_cache_session); 457*6139Sjb150015 kmem_cache_destroy(sv->si_cache_user); 458*6139Sjb150015 kmem_cache_destroy(sv->si_cache_tree); 459*6139Sjb150015 kmem_cache_destroy(sv->si_cache_ofile); 460*6139Sjb150015 kmem_cache_destroy(sv->si_cache_odir); 461*6139Sjb150015 kmem_cache_destroy(sv->si_cache_node); 462*6139Sjb150015 463*6139Sjb150015 taskq_destroy(sv->sv_thread_pool); 464*6139Sjb150015 smb_thread_destroy(&sv->si_thread_timers); 465*6139Sjb150015 mutex_destroy(&sv->sv_mutex); 466*6139Sjb150015 cv_destroy(&sv->sv_cv); 467*6139Sjb150015 sv->sv_magic = 0; 468*6139Sjb150015 kmem_free(sv, sizeof (smb_server_t)); 469*6139Sjb150015 470*6139Sjb150015 return (0); 471*6139Sjb150015 } 472*6139Sjb150015 473*6139Sjb150015 /* 474*6139Sjb150015 * smb_server_configure 475*6139Sjb150015 */ 476*6139Sjb150015 int 477*6139Sjb150015 smb_server_configure(smb_kmod_cfg_t *cfg) 478*6139Sjb150015 { 479*6139Sjb150015 int rc = 0; 480*6139Sjb150015 smb_server_t *sv; 481*6139Sjb150015 482*6139Sjb150015 rc = smb_server_lookup(&sv); 483*6139Sjb150015 if (rc) 484*6139Sjb150015 return (rc); 485*6139Sjb150015 486*6139Sjb150015 mutex_enter(&sv->sv_mutex); 487*6139Sjb150015 switch (sv->sv_state) { 488*6139Sjb150015 case SMB_SERVER_STATE_CREATED: 489*6139Sjb150015 smb_server_store_cfg(sv, cfg); 490*6139Sjb150015 sv->sv_state = SMB_SERVER_STATE_CONFIGURED; 491*6139Sjb150015 break; 492*6139Sjb150015 493*6139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 494*6139Sjb150015 smb_server_store_cfg(sv, cfg); 495*6139Sjb150015 break; 496*6139Sjb150015 497*6139Sjb150015 case SMB_SERVER_STATE_RUNNING: 498*6139Sjb150015 rw_enter(&sv->sv_cfg_lock, RW_WRITER); 499*6139Sjb150015 smb_server_store_cfg(sv, cfg); 500*6139Sjb150015 rw_exit(&sv->sv_cfg_lock); 501*6139Sjb150015 break; 502*6139Sjb150015 503*6139Sjb150015 default: 504*6139Sjb150015 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 505*6139Sjb150015 rc = EFAULT; 506*6139Sjb150015 break; 507*6139Sjb150015 } 508*6139Sjb150015 mutex_exit(&sv->sv_mutex); 509*6139Sjb150015 510*6139Sjb150015 smb_server_release(sv); 511*6139Sjb150015 512*6139Sjb150015 return (rc); 513*6139Sjb150015 } 514*6139Sjb150015 515*6139Sjb150015 /* 516*6139Sjb150015 * smb_server_start 517*6139Sjb150015 */ 518*6139Sjb150015 int 519*6139Sjb150015 smb_server_start(struct smb_io_start *io_start) 520*6139Sjb150015 { 521*6139Sjb150015 int rc = 0; 522*6139Sjb150015 smb_server_t *sv; 523*6139Sjb150015 524*6139Sjb150015 rc = smb_server_lookup(&sv); 525*6139Sjb150015 if (rc) 526*6139Sjb150015 return (rc); 527*6139Sjb150015 528*6139Sjb150015 mutex_enter(&sv->sv_mutex); 529*6139Sjb150015 switch (sv->sv_state) { 530*6139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 531*6139Sjb150015 532*6139Sjb150015 sv->sv_thread_pool = taskq_create("smb_workers", 533*6139Sjb150015 sv->sv_cfg.skc_maxworkers, SMB_WORKER_PRIORITY, 534*6139Sjb150015 sv->sv_cfg.skc_maxworkers, INT_MAX, 535*6139Sjb150015 TASKQ_DYNAMIC|TASKQ_PREPOPULATE); 536*6139Sjb150015 537*6139Sjb150015 sv->sv_session = smb_session_create(NULL, 0, sv); 538*6139Sjb150015 if (sv->sv_session == NULL) { 539*6139Sjb150015 rc = ENOMEM; 540*6139Sjb150015 break; 541*6139Sjb150015 } 542*6139Sjb150015 543*6139Sjb150015 if (rc = smb_server_fsop_start(sv)) 544*6139Sjb150015 break; 545*6139Sjb150015 ASSERT(sv->sv_lmshrd == NULL); 546*6139Sjb150015 sv->sv_lmshrd = lmshrd_kclient_init(io_start->lmshrd); 547*6139Sjb150015 if (sv->sv_lmshrd == NULL) 548*6139Sjb150015 break; 549*6139Sjb150015 if (rc = smb_kdoor_clnt_start(io_start->udoor)) 550*6139Sjb150015 break; 551*6139Sjb150015 if (rc = smb_kdoor_srv_set_dwncall()) 552*6139Sjb150015 break; 553*6139Sjb150015 if (rc = smb_thread_start(&sv->si_thread_timers)) 554*6139Sjb150015 break; 555*6139Sjb150015 /* 556*6139Sjb150015 * XXX We give up the NET_MAC_AWARE privilege because it keeps 557*6139Sjb150015 * us from re-opening the connection when there are leftover TCP 558*6139Sjb150015 * connections in TCPS_TIME_WAIT state. There seem to be some 559*6139Sjb150015 * security ramifications around reestablishing a connection 560*6139Sjb150015 * while possessing the NET_MAC_AWARE privilege. 561*6139Sjb150015 * 562*6139Sjb150015 * This approach may cause problems when we try to support 563*6139Sjb150015 * zones. An alternative would be to retry the connection setup 564*6139Sjb150015 * for a fixed period of time until the stale connections clear 565*6139Sjb150015 * up but that implies we would be offline for a couple minutes 566*6139Sjb150015 * every time the service is restarted with active connections. 567*6139Sjb150015 */ 568*6139Sjb150015 rc = setpflags(NET_MAC_AWARE, 0, CRED()); 569*6139Sjb150015 if (rc) { 570*6139Sjb150015 cmn_err(CE_WARN, 571*6139Sjb150015 "Cannot remove NET_MAC_AWARE privilege"); 572*6139Sjb150015 break; 573*6139Sjb150015 } 574*6139Sjb150015 if (rc = smb_winpipe_open(io_start->winpipe)) { 575*6139Sjb150015 cmn_err(CE_WARN, "Cannot open winpipe door"); 576*6139Sjb150015 break; 577*6139Sjb150015 } 578*6139Sjb150015 sv->sv_state = SMB_SERVER_STATE_RUNNING; 579*6139Sjb150015 mutex_exit(&sv->sv_mutex); 580*6139Sjb150015 smb_server_release(sv); 581*6139Sjb150015 return (0); 582*6139Sjb150015 default: 583*6139Sjb150015 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 584*6139Sjb150015 (sv->sv_state == SMB_SERVER_STATE_RUNNING) || 585*6139Sjb150015 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 586*6139Sjb150015 mutex_exit(&sv->sv_mutex); 587*6139Sjb150015 smb_server_release(sv); 588*6139Sjb150015 return (ENOTTY); 589*6139Sjb150015 } 590*6139Sjb150015 591*6139Sjb150015 smb_server_stop(sv); 592*6139Sjb150015 mutex_exit(&sv->sv_mutex); 593*6139Sjb150015 smb_server_release(sv); 594*6139Sjb150015 return (rc); 595*6139Sjb150015 } 596*6139Sjb150015 597*6139Sjb150015 /* 598*6139Sjb150015 * smb_server_nbt_listen: SMB-over-NetBIOS service 599*6139Sjb150015 * 600*6139Sjb150015 * Traditional SMB service over NetBIOS (port 139), which requires 601*6139Sjb150015 * that a NetBIOS session be established. 602*6139Sjb150015 */ 603*6139Sjb150015 int 604*6139Sjb150015 smb_server_nbt_listen(int error) 605*6139Sjb150015 { 606*6139Sjb150015 smb_server_t *sv; 607*6139Sjb150015 int rc; 608*6139Sjb150015 609*6139Sjb150015 rc = smb_server_lookup(&sv); 610*6139Sjb150015 if (rc) 611*6139Sjb150015 return (rc); 612*6139Sjb150015 613*6139Sjb150015 mutex_enter(&sv->sv_mutex); 614*6139Sjb150015 switch (sv->sv_state) { 615*6139Sjb150015 case SMB_SERVER_STATE_RUNNING: 616*6139Sjb150015 if ((sv->sv_nbt_daemon.ld_kth != NULL) && 617*6139Sjb150015 (sv->sv_nbt_daemon.ld_kth != curthread)) { 618*6139Sjb150015 mutex_exit(&sv->sv_mutex); 619*6139Sjb150015 return (EACCES); 620*6139Sjb150015 } else { 621*6139Sjb150015 sv->sv_nbt_daemon.ld_kth = curthread; 622*6139Sjb150015 sv->sv_nbt_daemon.ld_ktdid = curthread->t_did; 623*6139Sjb150015 } 624*6139Sjb150015 break; 625*6139Sjb150015 default: 626*6139Sjb150015 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 627*6139Sjb150015 (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) || 628*6139Sjb150015 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 629*6139Sjb150015 mutex_exit(&sv->sv_mutex); 630*6139Sjb150015 smb_server_release(sv); 631*6139Sjb150015 return (EFAULT); 632*6139Sjb150015 } 633*6139Sjb150015 mutex_exit(&sv->sv_mutex); 634*6139Sjb150015 635*6139Sjb150015 rc = smb_server_listen(sv, &sv->sv_nbt_daemon, SSN_SRVC_TCP_PORT, 636*6139Sjb150015 error); 637*6139Sjb150015 638*6139Sjb150015 if (rc) { 639*6139Sjb150015 mutex_enter(&sv->sv_mutex); 640*6139Sjb150015 sv->sv_nbt_daemon.ld_kth = NULL; 641*6139Sjb150015 mutex_exit(&sv->sv_mutex); 642*6139Sjb150015 } 643*6139Sjb150015 644*6139Sjb150015 smb_server_release(sv); 645*6139Sjb150015 646*6139Sjb150015 return (rc); 647*6139Sjb150015 } 648*6139Sjb150015 649*6139Sjb150015 int 650*6139Sjb150015 smb_server_tcp_listen(int error) 651*6139Sjb150015 { 652*6139Sjb150015 smb_server_t *sv; 653*6139Sjb150015 int rc; 654*6139Sjb150015 655*6139Sjb150015 rc = smb_server_lookup(&sv); 656*6139Sjb150015 if (rc) 657*6139Sjb150015 return (rc); 658*6139Sjb150015 659*6139Sjb150015 mutex_enter(&sv->sv_mutex); 660*6139Sjb150015 switch (sv->sv_state) { 661*6139Sjb150015 case SMB_SERVER_STATE_RUNNING: 662*6139Sjb150015 if ((sv->sv_tcp_daemon.ld_kth) && 663*6139Sjb150015 (sv->sv_tcp_daemon.ld_kth != curthread)) { 664*6139Sjb150015 mutex_exit(&sv->sv_mutex); 665*6139Sjb150015 return (EACCES); 666*6139Sjb150015 } else { 667*6139Sjb150015 sv->sv_tcp_daemon.ld_kth = curthread; 668*6139Sjb150015 sv->sv_tcp_daemon.ld_ktdid = curthread->t_did; 669*6139Sjb150015 } 670*6139Sjb150015 break; 671*6139Sjb150015 default: 672*6139Sjb150015 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 673*6139Sjb150015 (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) || 674*6139Sjb150015 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 675*6139Sjb150015 mutex_exit(&sv->sv_mutex); 676*6139Sjb150015 return (EFAULT); 677*6139Sjb150015 } 678*6139Sjb150015 mutex_exit(&sv->sv_mutex); 679*6139Sjb150015 680*6139Sjb150015 rc = smb_server_listen(sv, &sv->sv_tcp_daemon, SMB_SRVC_TCP_PORT, 681*6139Sjb150015 error); 682*6139Sjb150015 683*6139Sjb150015 if (rc) { 684*6139Sjb150015 mutex_enter(&sv->sv_mutex); 685*6139Sjb150015 sv->sv_tcp_daemon.ld_kth = NULL; 686*6139Sjb150015 mutex_exit(&sv->sv_mutex); 687*6139Sjb150015 } 688*6139Sjb150015 689*6139Sjb150015 smb_server_release(sv); 690*6139Sjb150015 691*6139Sjb150015 return (rc); 692*6139Sjb150015 } 693*6139Sjb150015 694*6139Sjb150015 /* 695*6139Sjb150015 * smb_server_nbt_receive 696*6139Sjb150015 */ 697*6139Sjb150015 int 698*6139Sjb150015 smb_server_nbt_receive(void) 699*6139Sjb150015 { 700*6139Sjb150015 int rc; 701*6139Sjb150015 smb_server_t *sv; 702*6139Sjb150015 703*6139Sjb150015 rc = smb_server_lookup(&sv); 704*6139Sjb150015 if (rc) 705*6139Sjb150015 return (rc); 706*6139Sjb150015 707*6139Sjb150015 rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list); 708*6139Sjb150015 709*6139Sjb150015 smb_server_release(sv); 710*6139Sjb150015 711*6139Sjb150015 return (rc); 712*6139Sjb150015 } 713*6139Sjb150015 714*6139Sjb150015 /* 715*6139Sjb150015 * smb_server_tcp_receive 716*6139Sjb150015 */ 717*6139Sjb150015 int 718*6139Sjb150015 smb_server_tcp_receive(void) 719*6139Sjb150015 { 720*6139Sjb150015 int rc; 721*6139Sjb150015 smb_server_t *sv; 722*6139Sjb150015 723*6139Sjb150015 rc = smb_server_lookup(&sv); 724*6139Sjb150015 if (rc) 725*6139Sjb150015 return (rc); 726*6139Sjb150015 727*6139Sjb150015 rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list); 728*6139Sjb150015 729*6139Sjb150015 smb_server_release(sv); 730*6139Sjb150015 731*6139Sjb150015 return (rc); 732*6139Sjb150015 } 733*6139Sjb150015 734*6139Sjb150015 int 735*6139Sjb150015 smb_server_set_gmtoff(uint32_t goff) 736*6139Sjb150015 { 737*6139Sjb150015 int rc; 738*6139Sjb150015 smb_server_t *sv; 739*6139Sjb150015 740*6139Sjb150015 741*6139Sjb150015 rc = smb_server_lookup(&sv); 742*6139Sjb150015 if (rc) 743*6139Sjb150015 return (rc); 744*6139Sjb150015 745*6139Sjb150015 sv->si_gmtoff = goff; 746*6139Sjb150015 747*6139Sjb150015 smb_server_release(sv); 748*6139Sjb150015 749*6139Sjb150015 return (rc); 750*6139Sjb150015 } 751*6139Sjb150015 752*6139Sjb150015 /* 753*6139Sjb150015 * ***************************************************************************** 754*6139Sjb150015 * ****************** Functions called from the door interface ***************** 755*6139Sjb150015 * ***************************************************************************** 756*6139Sjb150015 * 757*6139Sjb150015 * These functions determine the relevant smb server to which the call apply. 758*6139Sjb150015 */ 759*6139Sjb150015 760*6139Sjb150015 uint32_t 761*6139Sjb150015 smb_server_get_user_count(void) 762*6139Sjb150015 { 763*6139Sjb150015 smb_server_t *sv; 764*6139Sjb150015 uint32_t counter = 0; 765*6139Sjb150015 766*6139Sjb150015 if (smb_server_lookup(&sv)) 767*6139Sjb150015 return (0); 768*6139Sjb150015 769*6139Sjb150015 counter = (uint32_t)sv->sv_open_users; 770*6139Sjb150015 771*6139Sjb150015 smb_server_release(sv); 772*6139Sjb150015 773*6139Sjb150015 return (counter); 774*6139Sjb150015 } 775*6139Sjb150015 776*6139Sjb150015 uint32_t 777*6139Sjb150015 smb_server_get_session_count(void) 778*6139Sjb150015 { 779*6139Sjb150015 smb_server_t *sv; 780*6139Sjb150015 uint32_t counter = 0; 781*6139Sjb150015 782*6139Sjb150015 if (smb_server_lookup(&sv)) 783*6139Sjb150015 return (0); 784*6139Sjb150015 785*6139Sjb150015 rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER); 786*6139Sjb150015 counter = sv->sv_nbt_daemon.ld_session_list.se_act.count; 787*6139Sjb150015 rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock); 788*6139Sjb150015 rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER); 789*6139Sjb150015 counter += sv->sv_tcp_daemon.ld_session_list.se_act.count; 790*6139Sjb150015 rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock); 791*6139Sjb150015 792*6139Sjb150015 smb_server_release(sv); 793*6139Sjb150015 794*6139Sjb150015 return (counter); 795*6139Sjb150015 } 796*6139Sjb150015 797*6139Sjb150015 /* 798*6139Sjb150015 * smb_session_disconnect_share 799*6139Sjb150015 * 800*6139Sjb150015 * Disconnects the specified share. This function should be called after the 801*6139Sjb150015 * share passed in has been made unavailable by the "share manager". 802*6139Sjb150015 */ 803*6139Sjb150015 void 804*6139Sjb150015 smb_server_disconnect_share(char *sharename) 805*6139Sjb150015 { 806*6139Sjb150015 smb_server_t *sv; 807*6139Sjb150015 808*6139Sjb150015 if (smb_server_lookup(&sv)) 809*6139Sjb150015 return; 810*6139Sjb150015 811*6139Sjb150015 smb_session_disconnect_share(&sv->sv_nbt_daemon.ld_session_list, 812*6139Sjb150015 sharename); 813*6139Sjb150015 smb_session_disconnect_share(&sv->sv_tcp_daemon.ld_session_list, 814*6139Sjb150015 sharename); 815*6139Sjb150015 816*6139Sjb150015 smb_server_release(sv); 817*6139Sjb150015 } 818*6139Sjb150015 819*6139Sjb150015 void 820*6139Sjb150015 smb_server_disconnect_volume(fs_desc_t *fsd) 821*6139Sjb150015 { 822*6139Sjb150015 smb_server_t *sv; 823*6139Sjb150015 824*6139Sjb150015 if (smb_server_lookup(&sv)) 825*6139Sjb150015 return; 826*6139Sjb150015 827*6139Sjb150015 smb_session_disconnect_volume(&sv->sv_nbt_daemon.ld_session_list, fsd); 828*6139Sjb150015 smb_session_disconnect_volume(&sv->sv_tcp_daemon.ld_session_list, fsd); 829*6139Sjb150015 830*6139Sjb150015 smb_server_release(sv); 831*6139Sjb150015 } 832*6139Sjb150015 833*6139Sjb150015 int 834*6139Sjb150015 smb_server_dr_ulist_get(int offset, smb_dr_ulist_t *dr_ulist, int max_cnt) 835*6139Sjb150015 { 836*6139Sjb150015 smb_server_t *sv; 837*6139Sjb150015 838*6139Sjb150015 if (!dr_ulist) 839*6139Sjb150015 return (-1); 840*6139Sjb150015 841*6139Sjb150015 if (smb_server_lookup(&sv)) 842*6139Sjb150015 return (-1); 843*6139Sjb150015 844*6139Sjb150015 dr_ulist->dul_cnt = 845*6139Sjb150015 smb_server_ulist_geti(&sv->sv_nbt_daemon.ld_session_list, 846*6139Sjb150015 offset, dr_ulist->dul_users, max_cnt); 847*6139Sjb150015 dr_ulist->dul_cnt += 848*6139Sjb150015 smb_server_ulist_geti(&sv->sv_tcp_daemon.ld_session_list, 849*6139Sjb150015 offset - dr_ulist->dul_cnt, &dr_ulist->dul_users[dr_ulist->dul_cnt], 850*6139Sjb150015 max_cnt); 851*6139Sjb150015 852*6139Sjb150015 return (dr_ulist->dul_cnt); 853*6139Sjb150015 } 854*6139Sjb150015 855*6139Sjb150015 /* 856*6139Sjb150015 * smb_server_share_export() 857*6139Sjb150015 * 858*6139Sjb150015 * This function handles kernel processing at share enable time. 859*6139Sjb150015 * 860*6139Sjb150015 * At share-enable time (LMSHRD_ADD), the file system corresponding to 861*6139Sjb150015 * the share is checked for characteristics that are required for SMB 862*6139Sjb150015 * sharing. If this check passes, then a hold is taken on the root vnode 863*6139Sjb150015 * of the file system (or a reference count on the corresponding smb_vfs_t 864*6139Sjb150015 * is bumped), preventing an unmount. (See smb_vfs_hold()). 865*6139Sjb150015 */ 866*6139Sjb150015 867*6139Sjb150015 int 868*6139Sjb150015 smb_server_share_export(char *path) 869*6139Sjb150015 { 870*6139Sjb150015 smb_server_t *sv; 871*6139Sjb150015 int error; 872*6139Sjb150015 smb_node_t *fnode = NULL; 873*6139Sjb150015 smb_node_t *dnode; 874*6139Sjb150015 smb_attr_t ret_attr; 875*6139Sjb150015 char last_comp[MAXNAMELEN]; 876*6139Sjb150015 smb_request_t *sr; 877*6139Sjb150015 878*6139Sjb150015 if (smb_server_lookup(&sv)) 879*6139Sjb150015 return (EINVAL); 880*6139Sjb150015 881*6139Sjb150015 sr = smb_request_alloc(sv->sv_session, 0); 882*6139Sjb150015 if (sr == NULL) { 883*6139Sjb150015 smb_server_release(sv); 884*6139Sjb150015 return (ENOMEM); 885*6139Sjb150015 } 886*6139Sjb150015 887*6139Sjb150015 sr->user_cr = kcred; 888*6139Sjb150015 889*6139Sjb150015 error = smb_pathname_reduce(sr, kcred, path, NULL, NULL, &dnode, 890*6139Sjb150015 last_comp); 891*6139Sjb150015 892*6139Sjb150015 if (error) { 893*6139Sjb150015 smb_request_free(sr); 894*6139Sjb150015 smb_server_release(sv); 895*6139Sjb150015 return (error); 896*6139Sjb150015 } 897*6139Sjb150015 898*6139Sjb150015 error = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, NULL, dnode, 899*6139Sjb150015 last_comp, &fnode, &ret_attr, NULL, NULL); 900*6139Sjb150015 901*6139Sjb150015 smb_node_release(dnode); 902*6139Sjb150015 903*6139Sjb150015 if (error) { 904*6139Sjb150015 smb_request_free(sr); 905*6139Sjb150015 smb_server_release(sv); 906*6139Sjb150015 return (error); 907*6139Sjb150015 } 908*6139Sjb150015 909*6139Sjb150015 ASSERT(fnode->vp && fnode->vp->v_vfsp); 910*6139Sjb150015 911*6139Sjb150015 #ifdef SMB_ENFORCE_NODEV 912*6139Sjb150015 if (vfs_optionisset(fnode->vp->v_vfsp, MNTOPT_NODEVICES, NULL) == 0) 913*6139Sjb150015 return (EINVAL); 914*6139Sjb150015 #endif /* SMB_ENFORCE_NODEV */ 915*6139Sjb150015 916*6139Sjb150015 if (!smb_vfs_hold(sv, fnode->vp->v_vfsp)) { 917*6139Sjb150015 smb_node_release(fnode); 918*6139Sjb150015 smb_request_free(sr); 919*6139Sjb150015 smb_server_release(sv); 920*6139Sjb150015 return (ENOMEM); 921*6139Sjb150015 } 922*6139Sjb150015 923*6139Sjb150015 /* 924*6139Sjb150015 * The refcount on the smb_vfs has been incremented. 925*6139Sjb150015 * If it wasn't already, a hold has also been taken 926*6139Sjb150015 * on the root vnode of the file system. 927*6139Sjb150015 */ 928*6139Sjb150015 929*6139Sjb150015 smb_node_release(fnode); 930*6139Sjb150015 smb_request_free(sr); 931*6139Sjb150015 smb_server_release(sv); 932*6139Sjb150015 return (0); 933*6139Sjb150015 } 934*6139Sjb150015 935*6139Sjb150015 936*6139Sjb150015 937*6139Sjb150015 /* 938*6139Sjb150015 * smb_server_share_unexport() 939*6139Sjb150015 * 940*6139Sjb150015 * This function handles kernel processing at share disable time. 941*6139Sjb150015 * 942*6139Sjb150015 * At share-disable time (LMSHRD_DELETE), the reference count on the 943*6139Sjb150015 * corresponding smb_vfs_t is decremented. If this is the last share 944*6139Sjb150015 * on the file system, the hold on the root vnode of the file system 945*6139Sjb150015 * will be released. (See smb_vfs_rele().) 946*6139Sjb150015 */ 947*6139Sjb150015 948*6139Sjb150015 int 949*6139Sjb150015 smb_server_share_unexport(char *path, char *sharename) 950*6139Sjb150015 { 951*6139Sjb150015 smb_server_t *sv; 952*6139Sjb150015 int error; 953*6139Sjb150015 smb_node_t *fnode = NULL; 954*6139Sjb150015 smb_node_t *dnode; 955*6139Sjb150015 smb_attr_t ret_attr; 956*6139Sjb150015 char last_comp[MAXNAMELEN]; 957*6139Sjb150015 smb_request_t *sr; 958*6139Sjb150015 959*6139Sjb150015 if (smb_server_lookup(&sv)) 960*6139Sjb150015 return (EINVAL); 961*6139Sjb150015 962*6139Sjb150015 sr = smb_request_alloc(sv->sv_session, 0); 963*6139Sjb150015 if (sr == NULL) { 964*6139Sjb150015 smb_server_release(sv); 965*6139Sjb150015 return (ENOMEM); 966*6139Sjb150015 } 967*6139Sjb150015 sr->user_cr = kcred; 968*6139Sjb150015 969*6139Sjb150015 error = smb_pathname_reduce(sr, kcred, path, NULL, NULL, &dnode, 970*6139Sjb150015 last_comp); 971*6139Sjb150015 972*6139Sjb150015 if (error) { 973*6139Sjb150015 smb_request_free(sr); 974*6139Sjb150015 smb_server_release(sv); 975*6139Sjb150015 return (error); 976*6139Sjb150015 } 977*6139Sjb150015 978*6139Sjb150015 error = smb_fsop_lookup(sr, kcred, SMB_FOLLOW_LINKS, NULL, dnode, 979*6139Sjb150015 last_comp, &fnode, &ret_attr, NULL, NULL); 980*6139Sjb150015 981*6139Sjb150015 smb_node_release(dnode); 982*6139Sjb150015 983*6139Sjb150015 if (error) { 984*6139Sjb150015 smb_request_free(sr); 985*6139Sjb150015 smb_server_release(sv); 986*6139Sjb150015 return (error); 987*6139Sjb150015 } 988*6139Sjb150015 989*6139Sjb150015 ASSERT(fnode->vp && fnode->vp->v_vfsp); 990*6139Sjb150015 991*6139Sjb150015 smb_session_disconnect_share(&sv->sv_nbt_daemon.ld_session_list, 992*6139Sjb150015 sharename); 993*6139Sjb150015 smb_session_disconnect_share(&sv->sv_tcp_daemon.ld_session_list, 994*6139Sjb150015 sharename); 995*6139Sjb150015 smb_vfs_rele(sv, fnode->vp->v_vfsp); 996*6139Sjb150015 smb_node_release(fnode); 997*6139Sjb150015 smb_request_free(sr); 998*6139Sjb150015 smb_server_release(sv); 999*6139Sjb150015 return (0); 1000*6139Sjb150015 } 1001*6139Sjb150015 1002*6139Sjb150015 /* 1003*6139Sjb150015 * This is a special interface that will be utilized by ZFS to cause a share to 1004*6139Sjb150015 * be added/removed. 1005*6139Sjb150015 * 1006*6139Sjb150015 * arg is either a lmshare_info_t or share_name from userspace. 1007*6139Sjb150015 * It will need to be copied into the kernel. It is lmshare_info_t 1008*6139Sjb150015 * for add operations and share_name for delete operations. 1009*6139Sjb150015 */ 1010*6139Sjb150015 int 1011*6139Sjb150015 smb_server_share(void *arg, boolean_t add_share) 1012*6139Sjb150015 { 1013*6139Sjb150015 smb_server_t *sv; 1014*6139Sjb150015 int rc; 1015*6139Sjb150015 1016*6139Sjb150015 rc = smb_server_lookup(&sv); 1017*6139Sjb150015 if (rc == 0) { 1018*6139Sjb150015 mutex_enter(&sv->sv_mutex); 1019*6139Sjb150015 if (sv->sv_state == SMB_SERVER_STATE_RUNNING) { 1020*6139Sjb150015 mutex_exit(&sv->sv_mutex); 1021*6139Sjb150015 rc = lmshrd_share_upcall(sv->sv_lmshrd, arg, add_share); 1022*6139Sjb150015 } else { 1023*6139Sjb150015 mutex_exit(&sv->sv_mutex); 1024*6139Sjb150015 rc = EPERM; 1025*6139Sjb150015 } 1026*6139Sjb150015 smb_server_release(sv); 1027*6139Sjb150015 } 1028*6139Sjb150015 return (rc); 1029*6139Sjb150015 } 1030*6139Sjb150015 1031*6139Sjb150015 /* 1032*6139Sjb150015 * ***************************************************************************** 1033*6139Sjb150015 * **************** Functions called from the internal layers ****************** 1034*6139Sjb150015 * ***************************************************************************** 1035*6139Sjb150015 * 1036*6139Sjb150015 * These functions are provided the relevant smb server by the caller. 1037*6139Sjb150015 */ 1038*6139Sjb150015 1039*6139Sjb150015 void 1040*6139Sjb150015 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session) 1041*6139Sjb150015 { 1042*6139Sjb150015 ASSERT(sv == session->s_server); 1043*6139Sjb150015 1044*6139Sjb150015 smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list, 1045*6139Sjb150015 session); 1046*6139Sjb150015 smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list, 1047*6139Sjb150015 session); 1048*6139Sjb150015 } 1049*6139Sjb150015 1050*6139Sjb150015 void 1051*6139Sjb150015 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1052*6139Sjb150015 { 1053*6139Sjb150015 rw_enter(&sv->sv_cfg_lock, RW_READER); 1054*6139Sjb150015 bcopy(&sv->sv_cfg, cfg, sizeof (*cfg)); 1055*6139Sjb150015 rw_exit(&sv->sv_cfg_lock); 1056*6139Sjb150015 } 1057*6139Sjb150015 1058*6139Sjb150015 /* 1059*6139Sjb150015 * ***************************************************************************** 1060*6139Sjb150015 * *************************** Static Functions ******************************** 1061*6139Sjb150015 * ***************************************************************************** 1062*6139Sjb150015 */ 1063*6139Sjb150015 1064*6139Sjb150015 static void 1065*6139Sjb150015 smb_server_timers(smb_thread_t *thread, void *arg) 1066*6139Sjb150015 { 1067*6139Sjb150015 smb_server_t *sv = (smb_server_t *)arg; 1068*6139Sjb150015 1069*6139Sjb150015 ASSERT(sv != NULL); 1070*6139Sjb150015 1071*6139Sjb150015 while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) { 1072*6139Sjb150015 smb_session_timers(&sv->sv_nbt_daemon.ld_session_list); 1073*6139Sjb150015 smb_session_timers(&sv->sv_tcp_daemon.ld_session_list); 1074*6139Sjb150015 } 1075*6139Sjb150015 } 1076*6139Sjb150015 1077*6139Sjb150015 /* 1078*6139Sjb150015 * smb_server_kstat_init 1079*6139Sjb150015 */ 1080*6139Sjb150015 static int 1081*6139Sjb150015 smb_server_kstat_init(smb_server_t *sv) 1082*6139Sjb150015 { 1083*6139Sjb150015 (void) snprintf(sv->sv_ksp_name, sizeof (sv->sv_ksp_name), 1084*6139Sjb150015 "smb_server%d", sv->sv_zid); 1085*6139Sjb150015 1086*6139Sjb150015 sv->sv_ksp = kstat_create("smbsrv", sv->sv_zid, sv->sv_ksp_name, "net", 1087*6139Sjb150015 KSTAT_TYPE_NAMED, sizeof (sv->sv_ks_data) / sizeof (kstat_named_t), 1088*6139Sjb150015 KSTAT_FLAG_VIRTUAL); 1089*6139Sjb150015 1090*6139Sjb150015 if (sv->sv_ksp) { 1091*6139Sjb150015 (void) strlcpy(sv->sv_ks_data.state.name, "state", 1092*6139Sjb150015 sizeof (sv->sv_ks_data.state.name)); 1093*6139Sjb150015 sv->sv_ks_data.state.data_type = KSTAT_DATA_UINT32; 1094*6139Sjb150015 (void) strlcpy(sv->sv_ks_data.open_files.name, "open_files", 1095*6139Sjb150015 sizeof (sv->sv_ks_data.open_files.name)); 1096*6139Sjb150015 sv->sv_ks_data.open_files.data_type = KSTAT_DATA_UINT32; 1097*6139Sjb150015 (void) strlcpy(sv->sv_ks_data.open_trees.name, "connections", 1098*6139Sjb150015 sizeof (sv->sv_ks_data.open_trees.name)); 1099*6139Sjb150015 sv->sv_ks_data.open_trees.data_type = KSTAT_DATA_UINT32; 1100*6139Sjb150015 (void) strlcpy(sv->sv_ks_data.open_users.name, "sessions", 1101*6139Sjb150015 sizeof (sv->sv_ks_data.open_users.name)); 1102*6139Sjb150015 sv->sv_ks_data.open_users.data_type = KSTAT_DATA_UINT32; 1103*6139Sjb150015 1104*6139Sjb150015 mutex_init(&sv->sv_ksp_mutex, NULL, MUTEX_DEFAULT, NULL); 1105*6139Sjb150015 sv->sv_ksp->ks_lock = &sv->sv_ksp_mutex; 1106*6139Sjb150015 sv->sv_ksp->ks_data = (void *)&sv->sv_ks_data; 1107*6139Sjb150015 sv->sv_ksp->ks_update = smb_server_kstat_update_info; 1108*6139Sjb150015 kstat_install(sv->sv_ksp); 1109*6139Sjb150015 } 1110*6139Sjb150015 1111*6139Sjb150015 /* create and initialize smb kstats - smb_dispatch stats */ 1112*6139Sjb150015 smb_dispatch_kstat_init(); 1113*6139Sjb150015 1114*6139Sjb150015 return (0); 1115*6139Sjb150015 } 1116*6139Sjb150015 1117*6139Sjb150015 /* 1118*6139Sjb150015 * smb_server_kstat_fini 1119*6139Sjb150015 */ 1120*6139Sjb150015 static void 1121*6139Sjb150015 smb_server_kstat_fini(smb_server_t *sv) 1122*6139Sjb150015 { 1123*6139Sjb150015 if (sv->sv_ksp) { 1124*6139Sjb150015 kstat_delete(sv->sv_ksp); 1125*6139Sjb150015 mutex_destroy(&sv->sv_ksp_mutex); 1126*6139Sjb150015 sv->sv_ksp = NULL; 1127*6139Sjb150015 } 1128*6139Sjb150015 smb_dispatch_kstat_fini(); 1129*6139Sjb150015 } 1130*6139Sjb150015 1131*6139Sjb150015 /* ARGSUSED */ 1132*6139Sjb150015 static int 1133*6139Sjb150015 smb_server_kstat_update_info(kstat_t *ksp, int rw) 1134*6139Sjb150015 { 1135*6139Sjb150015 smb_server_t *sv; 1136*6139Sjb150015 1137*6139Sjb150015 if (rw == KSTAT_WRITE) { 1138*6139Sjb150015 return (EACCES); 1139*6139Sjb150015 } else { 1140*6139Sjb150015 ASSERT(MUTEX_HELD(ksp->ks_lock)); 1141*6139Sjb150015 1142*6139Sjb150015 _NOTE(LINTED("pointer cast may result in improper alignment")) 1143*6139Sjb150015 sv = (smb_server_t *)((uint8_t *)(ksp->ks_data) - 1144*6139Sjb150015 offsetof(smb_server_t, sv_ks_data)); 1145*6139Sjb150015 1146*6139Sjb150015 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1147*6139Sjb150015 1148*6139Sjb150015 sv->sv_ks_data.state.value.ui32 = sv->sv_state; 1149*6139Sjb150015 sv->sv_ks_data.open_files.value.ui32 = sv->sv_open_files; 1150*6139Sjb150015 sv->sv_ks_data.open_trees.value.ui32 = sv->sv_open_trees; 1151*6139Sjb150015 sv->sv_ks_data.open_users.value.ui32 = sv->sv_open_users; 1152*6139Sjb150015 } 1153*6139Sjb150015 return (0); 1154*6139Sjb150015 } 1155*6139Sjb150015 1156*6139Sjb150015 /* 1157*6139Sjb150015 * smb_server_stop 1158*6139Sjb150015 * 1159*6139Sjb150015 * The mutex of the server must have been entered before calling this function. 1160*6139Sjb150015 */ 1161*6139Sjb150015 static void 1162*6139Sjb150015 smb_server_stop(smb_server_t *sv) 1163*6139Sjb150015 { 1164*6139Sjb150015 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1165*6139Sjb150015 1166*6139Sjb150015 smb_winpipe_close(); 1167*6139Sjb150015 smb_thread_stop(&sv->si_thread_timers); 1168*6139Sjb150015 smb_kdoor_clnt_stop(); 1169*6139Sjb150015 lmshrd_kclient_fini(sv->sv_lmshrd); 1170*6139Sjb150015 smb_server_fsop_stop(sv); 1171*6139Sjb150015 if (sv->sv_session) { 1172*6139Sjb150015 smb_session_delete(sv->sv_session); 1173*6139Sjb150015 sv->sv_session = NULL; 1174*6139Sjb150015 } 1175*6139Sjb150015 } 1176*6139Sjb150015 1177*6139Sjb150015 static int 1178*6139Sjb150015 smb_server_listen( 1179*6139Sjb150015 smb_server_t *sv, 1180*6139Sjb150015 smb_listener_daemon_t *ld, 1181*6139Sjb150015 in_port_t port, 1182*6139Sjb150015 int pthread_create_error) 1183*6139Sjb150015 { 1184*6139Sjb150015 int rc; 1185*6139Sjb150015 struct sonode *s_so; 1186*6139Sjb150015 uint32_t on = 1; 1187*6139Sjb150015 smb_session_t *session; 1188*6139Sjb150015 1189*6139Sjb150015 if (pthread_create_error) { 1190*6139Sjb150015 /* 1191*6139Sjb150015 * Delete the last session created. The user space thread 1192*6139Sjb150015 * creation failed. 1193*6139Sjb150015 */ 1194*6139Sjb150015 smb_session_list_delete_tail(&ld->ld_session_list); 1195*6139Sjb150015 } 1196*6139Sjb150015 1197*6139Sjb150015 if (ld->ld_so == NULL) { 1198*6139Sjb150015 /* First time listener */ 1199*6139Sjb150015 ld->ld_sin.sin_family = AF_INET; 1200*6139Sjb150015 ld->ld_sin.sin_port = htons(port); 1201*6139Sjb150015 ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY); 1202*6139Sjb150015 ld->ld_so = smb_socreate(AF_INET, SOCK_STREAM, 0); 1203*6139Sjb150015 1204*6139Sjb150015 if (ld->ld_so) { 1205*6139Sjb150015 1206*6139Sjb150015 (void) sosetsockopt(ld->ld_so, SOL_SOCKET, 1207*6139Sjb150015 SO_REUSEADDR, (const void *)&on, sizeof (on)); 1208*6139Sjb150015 1209*6139Sjb150015 rc = sobind(ld->ld_so, (struct sockaddr *)&ld->ld_sin, 1210*6139Sjb150015 sizeof (ld->ld_sin), 0, 0); 1211*6139Sjb150015 1212*6139Sjb150015 if (rc == 0) { 1213*6139Sjb150015 rc = solisten(ld->ld_so, 20); 1214*6139Sjb150015 if (rc < 0) { 1215*6139Sjb150015 cmn_err(CE_WARN, 1216*6139Sjb150015 "Port %d: listen failed", port); 1217*6139Sjb150015 smb_soshutdown(ld->ld_so); 1218*6139Sjb150015 smb_sodestroy(ld->ld_so); 1219*6139Sjb150015 ld->ld_so = NULL; 1220*6139Sjb150015 return (rc); 1221*6139Sjb150015 } 1222*6139Sjb150015 } else { 1223*6139Sjb150015 cmn_err(CE_WARN, 1224*6139Sjb150015 "Port %d: bind failed", port); 1225*6139Sjb150015 smb_soshutdown(ld->ld_so); 1226*6139Sjb150015 smb_sodestroy(ld->ld_so); 1227*6139Sjb150015 ld->ld_so = NULL; 1228*6139Sjb150015 return (rc); 1229*6139Sjb150015 } 1230*6139Sjb150015 } else { 1231*6139Sjb150015 cmn_err(CE_WARN, 1232*6139Sjb150015 "Port %d: socket create failed", port); 1233*6139Sjb150015 return (ENOMEM); 1234*6139Sjb150015 } 1235*6139Sjb150015 } 1236*6139Sjb150015 1237*6139Sjb150015 DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so); 1238*6139Sjb150015 1239*6139Sjb150015 for (;;) { 1240*6139Sjb150015 rc = soaccept(ld->ld_so, 0, &s_so); 1241*6139Sjb150015 if (rc == 0) { 1242*6139Sjb150015 uint32_t txbuf_size = 128*1024; 1243*6139Sjb150015 uint32_t on = 1; 1244*6139Sjb150015 1245*6139Sjb150015 DTRACE_PROBE1(so__accept, struct sonode *, s_so); 1246*6139Sjb150015 1247*6139Sjb150015 (void) sosetsockopt(s_so, IPPROTO_TCP, TCP_NODELAY, 1248*6139Sjb150015 (const void *)&on, sizeof (on)); 1249*6139Sjb150015 (void) sosetsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE, 1250*6139Sjb150015 (const void *)&on, sizeof (on)); 1251*6139Sjb150015 (void) sosetsockopt(s_so, SOL_SOCKET, SO_SNDBUF, 1252*6139Sjb150015 (const void *)&txbuf_size, sizeof (txbuf_size)); 1253*6139Sjb150015 /* 1254*6139Sjb150015 * Create a session for this connection. 1255*6139Sjb150015 */ 1256*6139Sjb150015 session = smb_session_create(s_so, port, sv); 1257*6139Sjb150015 if (session) { 1258*6139Sjb150015 smb_session_list_append(&ld->ld_session_list, 1259*6139Sjb150015 session); 1260*6139Sjb150015 break; 1261*6139Sjb150015 } else { 1262*6139Sjb150015 smb_soshutdown(s_so); 1263*6139Sjb150015 smb_sodestroy(s_so); 1264*6139Sjb150015 } 1265*6139Sjb150015 continue; 1266*6139Sjb150015 } 1267*6139Sjb150015 smb_session_list_signal(&ld->ld_session_list); 1268*6139Sjb150015 smb_soshutdown(ld->ld_so); 1269*6139Sjb150015 smb_sodestroy(ld->ld_so); 1270*6139Sjb150015 ld->ld_so = NULL; 1271*6139Sjb150015 break; 1272*6139Sjb150015 } 1273*6139Sjb150015 1274*6139Sjb150015 return (rc); 1275*6139Sjb150015 } 1276*6139Sjb150015 1277*6139Sjb150015 /* 1278*6139Sjb150015 * smb_server_lookup 1279*6139Sjb150015 * 1280*6139Sjb150015 * This function tries to find the server associated with the zone of the 1281*6139Sjb150015 * caller. 1282*6139Sjb150015 */ 1283*6139Sjb150015 static int 1284*6139Sjb150015 smb_server_lookup(smb_server_t **psv) 1285*6139Sjb150015 { 1286*6139Sjb150015 zoneid_t zid; 1287*6139Sjb150015 smb_server_t *sv; 1288*6139Sjb150015 1289*6139Sjb150015 zid = getzoneid(); 1290*6139Sjb150015 1291*6139Sjb150015 smb_llist_enter(&smb_servers, RW_READER); 1292*6139Sjb150015 sv = smb_llist_head(&smb_servers); 1293*6139Sjb150015 while (sv) { 1294*6139Sjb150015 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1295*6139Sjb150015 if (sv->sv_zid == zid) { 1296*6139Sjb150015 mutex_enter(&sv->sv_mutex); 1297*6139Sjb150015 if (sv->sv_state != SMB_SERVER_STATE_DELETING) { 1298*6139Sjb150015 sv->sv_refcnt++; 1299*6139Sjb150015 mutex_exit(&sv->sv_mutex); 1300*6139Sjb150015 smb_llist_exit(&smb_servers); 1301*6139Sjb150015 *psv = sv; 1302*6139Sjb150015 return (0); 1303*6139Sjb150015 } 1304*6139Sjb150015 mutex_exit(&sv->sv_mutex); 1305*6139Sjb150015 break; 1306*6139Sjb150015 } 1307*6139Sjb150015 sv = smb_llist_next(&smb_servers, sv); 1308*6139Sjb150015 } 1309*6139Sjb150015 smb_llist_exit(&smb_servers); 1310*6139Sjb150015 return (EPERM); 1311*6139Sjb150015 } 1312*6139Sjb150015 1313*6139Sjb150015 /* 1314*6139Sjb150015 * smb_server_release 1315*6139Sjb150015 * 1316*6139Sjb150015 * This function decrements the reference count of the server and signals its 1317*6139Sjb150015 * condition variable if the state of the server is SMB_SERVER_STATE_DELETING. 1318*6139Sjb150015 */ 1319*6139Sjb150015 static void 1320*6139Sjb150015 smb_server_release(smb_server_t *sv) 1321*6139Sjb150015 { 1322*6139Sjb150015 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1323*6139Sjb150015 1324*6139Sjb150015 mutex_enter(&sv->sv_mutex); 1325*6139Sjb150015 ASSERT(sv->sv_refcnt); 1326*6139Sjb150015 sv->sv_refcnt--; 1327*6139Sjb150015 if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING)) 1328*6139Sjb150015 cv_signal(&sv->sv_cv); 1329*6139Sjb150015 mutex_exit(&sv->sv_mutex); 1330*6139Sjb150015 } 1331*6139Sjb150015 1332*6139Sjb150015 static int 1333*6139Sjb150015 smb_server_ulist_geti( 1334*6139Sjb150015 smb_session_list_t *se, 1335*6139Sjb150015 int offset, 1336*6139Sjb150015 smb_dr_user_ctx_t *uinfo, 1337*6139Sjb150015 int max_cnt) 1338*6139Sjb150015 { 1339*6139Sjb150015 smb_session_t *sn = NULL; 1340*6139Sjb150015 smb_user_t *user; 1341*6139Sjb150015 smb_llist_t *ulist; 1342*6139Sjb150015 int cnt = 0, skip = 0; 1343*6139Sjb150015 1344*6139Sjb150015 rw_enter(&se->se_lock, RW_READER); 1345*6139Sjb150015 sn = list_head(&se->se_act.lst); 1346*6139Sjb150015 while (sn && (cnt < max_cnt)) { 1347*6139Sjb150015 ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 1348*6139Sjb150015 ulist = &sn->s_user_list; 1349*6139Sjb150015 smb_llist_enter(ulist, RW_READER); 1350*6139Sjb150015 user = smb_llist_head(ulist); 1351*6139Sjb150015 while (user && (cnt < max_cnt)) { 1352*6139Sjb150015 ASSERT(user->u_magic == SMB_USER_MAGIC); 1353*6139Sjb150015 mutex_enter(&user->u_mutex); 1354*6139Sjb150015 if (user->u_state == SMB_USER_STATE_LOGGED_IN) { 1355*6139Sjb150015 if (skip++ < offset) { 1356*6139Sjb150015 mutex_exit(&user->u_mutex); 1357*6139Sjb150015 user = smb_llist_next(ulist, user); 1358*6139Sjb150015 continue; 1359*6139Sjb150015 } 1360*6139Sjb150015 1361*6139Sjb150015 if (smb_dr_user_create(uinfo, sn->s_kid, 1362*6139Sjb150015 user->u_uid, user->u_domain, user->u_name, 1363*6139Sjb150015 sn->workstation, sn->ipaddr, sn->native_os, 1364*6139Sjb150015 user->u_logon_time, user->u_flags) != 0) { 1365*6139Sjb150015 mutex_exit(&user->u_mutex); 1366*6139Sjb150015 user = smb_llist_next(ulist, user); 1367*6139Sjb150015 continue; 1368*6139Sjb150015 } 1369*6139Sjb150015 uinfo++; 1370*6139Sjb150015 cnt++; 1371*6139Sjb150015 } 1372*6139Sjb150015 mutex_exit(&user->u_mutex); 1373*6139Sjb150015 user = smb_llist_next(ulist, user); 1374*6139Sjb150015 } 1375*6139Sjb150015 smb_llist_exit(ulist); 1376*6139Sjb150015 } 1377*6139Sjb150015 rw_exit(&se->se_lock); 1378*6139Sjb150015 return (cnt); 1379*6139Sjb150015 } 1380*6139Sjb150015 1381*6139Sjb150015 static void 1382*6139Sjb150015 smb_server_store_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1383*6139Sjb150015 { 1384*6139Sjb150015 if (cfg->skc_maxconnections == 0) 1385*6139Sjb150015 cfg->skc_maxconnections = 0xFFFFFFFF; 1386*6139Sjb150015 1387*6139Sjb150015 /* 1388*6139Sjb150015 * XXX should not override configuration. 1389*6139Sjb150015 * For now, this disables server side 1390*6139Sjb150015 * signing regardless of configuration. 1391*6139Sjb150015 */ 1392*6139Sjb150015 cfg->skc_signing_enable = 0; 1393*6139Sjb150015 cfg->skc_signing_required = 0; 1394*6139Sjb150015 cfg->skc_signing_check = 0; 1395*6139Sjb150015 1396*6139Sjb150015 smb_session_correct_keep_alive_values( 1397*6139Sjb150015 &sv->sv_nbt_daemon.ld_session_list, cfg->skc_keepalive); 1398*6139Sjb150015 smb_session_correct_keep_alive_values( 1399*6139Sjb150015 &sv->sv_tcp_daemon.ld_session_list, cfg->skc_keepalive); 1400*6139Sjb150015 1401*6139Sjb150015 /* 1402*6139Sjb150015 * XXX The following code was pulled from smb_oplock_init. 1403*6139Sjb150015 * It should be combined with with the config process if 1404*6139Sjb150015 * this info will be stored with the configuration or with 1405*6139Sjb150015 * the smb_fsop_start function if the data will be stored 1406*6139Sjb150015 * in the root of the fs. 1407*6139Sjb150015 */ 1408*6139Sjb150015 1409*6139Sjb150015 /* 1410*6139Sjb150015 * XXX oplock enable flag. 1411*6139Sjb150015 * Should be stored in extended attribute in root of fs 1412*6139Sjb150015 * or a ZFS user-defined property. 1413*6139Sjb150015 */ 1414*6139Sjb150015 if (cfg->skc_oplock_enable == 0) { 1415*6139Sjb150015 cmn_err(CE_NOTE, "SmbOplocks: disabled"); 1416*6139Sjb150015 } 1417*6139Sjb150015 1418*6139Sjb150015 bcopy(cfg, &sv->sv_cfg, sizeof (sv->sv_cfg)); 1419*6139Sjb150015 } 1420*6139Sjb150015 1421*6139Sjb150015 static int 1422*6139Sjb150015 smb_server_fsop_start(smb_server_t *sv) 1423*6139Sjb150015 { 1424*6139Sjb150015 int error; 1425*6139Sjb150015 1426*6139Sjb150015 error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node); 1427*6139Sjb150015 if (error != 0) 1428*6139Sjb150015 sv->si_root_smb_node = NULL; 1429*6139Sjb150015 1430*6139Sjb150015 return (error); 1431*6139Sjb150015 } 1432*6139Sjb150015 1433*6139Sjb150015 static void 1434*6139Sjb150015 smb_server_fsop_stop(smb_server_t *sv) 1435*6139Sjb150015 { 1436*6139Sjb150015 if (sv->si_root_smb_node != NULL) { 1437*6139Sjb150015 smb_vfs_rele_all(sv); 1438*6139Sjb150015 smb_node_release(sv->si_root_smb_node); 1439*6139Sjb150015 sv->si_root_smb_node = NULL; 1440*6139Sjb150015 } 1441*6139Sjb150015 } 1442