16139Sjb150015 /* 26139Sjb150015 * CDDL HEADER START 36139Sjb150015 * 46139Sjb150015 * The contents of this file are subject to the terms of the 56139Sjb150015 * Common Development and Distribution License (the "License"). 66139Sjb150015 * You may not use this file except in compliance with the License. 76139Sjb150015 * 86139Sjb150015 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96139Sjb150015 * or http://www.opensolaris.org/os/licensing. 106139Sjb150015 * See the License for the specific language governing permissions 116139Sjb150015 * and limitations under the License. 126139Sjb150015 * 136139Sjb150015 * When distributing Covered Code, include this CDDL HEADER in each 146139Sjb150015 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156139Sjb150015 * If applicable, add the following below this CDDL HEADER, with the 166139Sjb150015 * fields enclosed by brackets "[]" replaced with your own identifying 176139Sjb150015 * information: Portions Copyright [yyyy] [name of copyright owner] 186139Sjb150015 * 196139Sjb150015 * CDDL HEADER END 206139Sjb150015 */ 216139Sjb150015 /* 22*11963SAfshin.Ardakani@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 236139Sjb150015 * Use is subject to license terms. 246139Sjb150015 */ 256139Sjb150015 266139Sjb150015 /* 276139Sjb150015 * General Structures Layout 286139Sjb150015 * ------------------------- 296139Sjb150015 * 306139Sjb150015 * This is a simplified diagram showing the relationship between most of the 316139Sjb150015 * main structures. 326139Sjb150015 * 336139Sjb150015 * +-------------------+ 346139Sjb150015 * | SMB_SERVER | 356139Sjb150015 * +-------------------+ 366139Sjb150015 * | 376139Sjb150015 * | 386139Sjb150015 * v 396139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 406139Sjb150015 * | SESSION |<----->| SESSION |......| SESSION | 416139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 426139Sjb150015 * | 436139Sjb150015 * | 446139Sjb150015 * v 456139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 466139Sjb150015 * | USER |<----->| USER |......| USER | 476139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 486139Sjb150015 * | 496139Sjb150015 * | 506139Sjb150015 * v 516139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 526139Sjb150015 * | TREE |<----->| TREE |......| TREE | 536139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 546139Sjb150015 * | | 556139Sjb150015 * | | 566139Sjb150015 * | v 576139Sjb150015 * | +-------+ +-------+ +-------+ 586139Sjb150015 * | | OFILE |<----->| OFILE |......| OFILE | 596139Sjb150015 * | +-------+ +-------+ +-------+ 606139Sjb150015 * | 616139Sjb150015 * | 626139Sjb150015 * v 636139Sjb150015 * +-------+ +------+ +------+ 646139Sjb150015 * | ODIR |<----->| ODIR |......| ODIR | 656139Sjb150015 * +-------+ +------+ +------+ 666139Sjb150015 * 676139Sjb150015 * 686139Sjb150015 * Module Interface Overview 696139Sjb150015 * ------------------------- 706139Sjb150015 * 716139Sjb150015 * 726139Sjb150015 * +===================================+ 736139Sjb150015 * | smbd daemon | 746139Sjb150015 * +===================================+ 756139Sjb150015 * | | ^ 766139Sjb150015 * | | | 776139Sjb150015 * User | | | 786139Sjb150015 * -----------|--------------|----------------|-------------------------------- 796139Sjb150015 * Kernel | | | 806139Sjb150015 * | | | 816139Sjb150015 * | | | 826139Sjb150015 * +=========|==============|================|=================+ 836139Sjb150015 * | v v | | 846139Sjb150015 * | +-----------+ +--------------------+ +------------------+ | 856139Sjb150015 * | | IO | | Kernel Door Server | | User Door Servers| | 866139Sjb150015 * | | Interface | | Interface | | Interface | | 876139Sjb150015 * | +-----------+ +--------------------+ +------------------+ | 886139Sjb150015 * | | | ^ ^ | 896139Sjb150015 * | v v | | | +=========+ 906139Sjb150015 * | +-----------------------------------+ | | | | 916139Sjb150015 * | + SMB Server Management (this file) |<------------------| ZFS | 926139Sjb150015 * | +-----------------------------------+ | | | | 936139Sjb150015 * | | | | Module | 946139Sjb150015 * | +-----------------------------------+ | | | | 956139Sjb150015 * | + SMB Server Internal Layers |------+ | +=========+ 966139Sjb150015 * | +-----------------------------------+ | 976139Sjb150015 * | | 986139Sjb150015 * | | 996139Sjb150015 * +===========================================================+ 1006139Sjb150015 * 1016139Sjb150015 * 1026139Sjb150015 * Server State Machine 1036139Sjb150015 * -------------------- 1046139Sjb150015 * | 1056139Sjb150015 * | T0 1066139Sjb150015 * | 1076139Sjb150015 * v 1086139Sjb150015 * +-----------------------------+ 1096139Sjb150015 * | SMB_SERVER_STATE_CREATED | 1106139Sjb150015 * +-----------------------------+ 1116139Sjb150015 * | 1126139Sjb150015 * | T1 1136139Sjb150015 * | 1146139Sjb150015 * v 1156139Sjb150015 * +-----------------------------+ 1166139Sjb150015 * | SMB_SERVER_STATE_CONFIGURED | 1176139Sjb150015 * +-----------------------------+ 1186139Sjb150015 * | 1196139Sjb150015 * | T2 1206139Sjb150015 * | 1216139Sjb150015 * v 1226139Sjb150015 * +-----------------------------+ 123*11963SAfshin.Ardakani@Sun.COM * | SMB_SERVER_STATE_RUNNING / | 124*11963SAfshin.Ardakani@Sun.COM * | SMB_SERVER_STATE_STOPPING | 1256139Sjb150015 * +-----------------------------+ 1266139Sjb150015 * | 1276139Sjb150015 * | T3 1286139Sjb150015 * | 1296139Sjb150015 * v 1306139Sjb150015 * +-----------------------------+ 1316139Sjb150015 * | SMB_SERVER_STATE_DELETING | 1326139Sjb150015 * +-----------------------------+ 1336139Sjb150015 * | 1346139Sjb150015 * | 1356139Sjb150015 * | 1366139Sjb150015 * v 1376139Sjb150015 * 1386139Sjb150015 * States 1396139Sjb150015 * ------ 1406139Sjb150015 * 1416139Sjb150015 * SMB_SERVER_STATE_CREATED 1426139Sjb150015 * 1436139Sjb150015 * This is the state of the server just after creation. 1446139Sjb150015 * 1456139Sjb150015 * SMB_SERVER_STATE_CONFIGURED 1466139Sjb150015 * 1476139Sjb150015 * The server has been configured. 1486139Sjb150015 * 1496139Sjb150015 * SMB_SERVER_STATE_RUNNING 1506139Sjb150015 * 1516139Sjb150015 * The server has been started. While in this state the threads listening on 1526139Sjb150015 * the sockets car be started. The smbd daemon does so through an Ioctl: 1536139Sjb150015 * 1546139Sjb150015 * smb_drv_ioctl(SMB_IOC_NBT_LISTEN) --> smb_server_nbt_listen() 1556139Sjb150015 * smb_drv_ioctl(SMB_IOC_TCP_LISTEN) --> smb_server_nbt_listen() 1566139Sjb150015 * 1576139Sjb150015 * When a client establishes a connection the thread listening leaves 1586139Sjb150015 * temporarily the kernel. While in user space it creates a thread for the 1596139Sjb150015 * new session. It then returns to kernel with the result of the thread 1606139Sjb150015 * creation. If the creation failed the new session context is destroyed 1616139Sjb150015 * before returning listening. 1626139Sjb150015 * 1636139Sjb150015 * The new created thread enters the kernel though an Ioctl: 1646139Sjb150015 * 1656139Sjb150015 * smb_drv_ioctl(SMB_IOC_NBT_RECEIVE) --> smb_server_nbt_receive() 1666139Sjb150015 * smb_drv_ioctl(SMB_IOC_TCP_RECEIVE) --> smb_server_tcp_receive() 1676139Sjb150015 * 1686139Sjb150015 * SMB_SERVER_STATE_STOPPING 1696139Sjb150015 * 1706139Sjb150015 * The threads listening on the NBT and TCP sockets are being terminated. 1716139Sjb150015 * 1726139Sjb150015 * 1736139Sjb150015 * Transitions 1746139Sjb150015 * ----------- 1756139Sjb150015 * 1766139Sjb150015 * Transition T0 1776139Sjb150015 * 1786139Sjb150015 * The daemon smbd triggers its creation by opening the smbsrv device. If 1796139Sjb150015 * the zone where the daemon lives doesn't have an smb server yet it is 1806139Sjb150015 * created. 1816139Sjb150015 * 1826139Sjb150015 * smb_drv_open() --> smb_server_create() 1836139Sjb150015 * 1846139Sjb150015 * Transition T1 1856139Sjb150015 * 1866139Sjb150015 * This transition occurs in smb_server_configure(). It is triggered by the 1876139Sjb150015 * daemon through an Ioctl. 1886139Sjb150015 * 1896139Sjb150015 * smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure() 1906139Sjb150015 * 1916139Sjb150015 * Transition T2 1926139Sjb150015 * 1936139Sjb150015 * This transition occurs in smb_server_start(). It is triggered by the 1946139Sjb150015 * daemon through an Ioctl. 1956139Sjb150015 * 1966139Sjb150015 * smb_drv_ioctl(SMB_IOC_START) --> smb_server_start() 1976139Sjb150015 * 1986139Sjb150015 * Transition T3 1996139Sjb150015 * 2006139Sjb150015 * This transition occurs in smb_server_delete(). It is triggered by the 2016139Sjb150015 * daemon when closing the smbsrv device 2026139Sjb150015 * 2036139Sjb150015 * smb_drv_close() --> smb_server_delete() 2046139Sjb150015 * 2056139Sjb150015 * Comments 2066139Sjb150015 * -------- 2076139Sjb150015 * 2086139Sjb150015 * This files assumes that there will one SMB server per zone. For now the 2096139Sjb150015 * smb server works only in global zone. There's nothing in this file preventing 2106139Sjb150015 * an smb server from being created in a non global zone. That limitation is 2116139Sjb150015 * enforced in user space. 2126139Sjb150015 */ 2136139Sjb150015 2146139Sjb150015 #include <sys/strsubr.h> 2156139Sjb150015 #include <sys/cmn_err.h> 2166139Sjb150015 #include <sys/priv.h> 2176139Sjb150015 #include <sys/socketvar.h> 2186139Sjb150015 #include <sys/zone.h> 21910966SJordan.Brown@Sun.COM #include <netinet/in.h> 22010966SJordan.Brown@Sun.COM #include <netinet/in_systm.h> 22110966SJordan.Brown@Sun.COM #include <netinet/ip.h> 22210966SJordan.Brown@Sun.COM #include <netinet/ip_icmp.h> 22310966SJordan.Brown@Sun.COM #include <netinet/ip_var.h> 22410966SJordan.Brown@Sun.COM #include <netinet/tcp.h> 2256139Sjb150015 #include <smbsrv/smb_kproto.h> 22610966SJordan.Brown@Sun.COM #include <smbsrv/string.h> 2276139Sjb150015 #include <smbsrv/netbios.h> 2286139Sjb150015 #include <smbsrv/smb_fsops.h> 2297052Samw #include <smbsrv/smb_share.h> 230*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_door.h> 2316432Sas200622 #include <smbsrv/smb_kstat.h> 2326139Sjb150015 233*11963SAfshin.Ardakani@Sun.COM #define SMB_EVENT_TIMEOUT 45 /* seconds */ 234*11963SAfshin.Ardakani@Sun.COM 235*11963SAfshin.Ardakani@Sun.COM #define SMB_REAPER_RATE_DEFAULT 4 236*11963SAfshin.Ardakani@Sun.COM 2376139Sjb150015 extern void smb_dispatch_kstat_init(void); 2386139Sjb150015 extern void smb_dispatch_kstat_fini(void); 2396139Sjb150015 extern void smb_reply_notify_change_request(smb_request_t *); 2406139Sjb150015 2416139Sjb150015 static int smb_server_kstat_init(smb_server_t *); 2426139Sjb150015 static void smb_server_kstat_fini(smb_server_t *); 2436139Sjb150015 static int smb_server_kstat_update_info(kstat_t *, int); 2446139Sjb150015 static void smb_server_timers(smb_thread_t *, void *); 2456139Sjb150015 static int smb_server_listen(smb_server_t *, smb_listener_daemon_t *, 2468670SJose.Borrego@Sun.COM in_port_t, int, int); 247*11963SAfshin.Ardakani@Sun.COM static void smb_server_listen_fini(smb_listener_daemon_t *); 248*11963SAfshin.Ardakani@Sun.COM static kt_did_t smb_server_listener_tid(smb_listener_daemon_t *); 2496139Sjb150015 static int smb_server_lookup(smb_server_t **); 2506139Sjb150015 static void smb_server_release(smb_server_t *); 2519832Samw@Sun.COM static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *); 252*11963SAfshin.Ardakani@Sun.COM static void smb_server_shutdown(smb_server_t *); 2536139Sjb150015 static int smb_server_fsop_start(smb_server_t *); 2546139Sjb150015 static void smb_server_fsop_stop(smb_server_t *); 255*11963SAfshin.Ardakani@Sun.COM static void smb_server_signal_listeners(smb_server_t *); 256*11963SAfshin.Ardakani@Sun.COM static void smb_event_cancel(smb_server_t *, uint32_t); 257*11963SAfshin.Ardakani@Sun.COM static void smb_event_notify(smb_server_t *, uint32_t); 258*11963SAfshin.Ardakani@Sun.COM static uint32_t smb_event_alloc_txid(void); 2596139Sjb150015 260*11963SAfshin.Ardakani@Sun.COM static void smb_server_disconnect_share(smb_session_list_t *, const char *); 2617619SJose.Borrego@Sun.COM static void smb_server_thread_unexport(smb_thread_t *, void *); 26210122SJordan.Brown@Sun.COM static void smb_server_enum_private(smb_session_list_t *, smb_svcenum_t *); 26310122SJordan.Brown@Sun.COM static int smb_server_sesion_disconnect(smb_session_list_t *, const char *, 26410122SJordan.Brown@Sun.COM const char *); 26510122SJordan.Brown@Sun.COM static int smb_server_fclose(smb_session_list_t *, uint32_t); 26610122SJordan.Brown@Sun.COM 267*11963SAfshin.Ardakani@Sun.COM int smb_event_debug = 0; 268*11963SAfshin.Ardakani@Sun.COM 2696139Sjb150015 static smb_llist_t smb_servers; 2706139Sjb150015 2716139Sjb150015 /* 2726139Sjb150015 * ***************************************************************************** 2736139Sjb150015 * **************** Functions called from the device interface ***************** 2746139Sjb150015 * ***************************************************************************** 2756139Sjb150015 * 27610122SJordan.Brown@Sun.COM * These functions typically have to determine the relevant smb server 27710122SJordan.Brown@Sun.COM * to which the call applies. 2786139Sjb150015 */ 2796139Sjb150015 2806139Sjb150015 /* 2816139Sjb150015 * smb_server_svc_init 2826139Sjb150015 * 2837348SJose.Borrego@Sun.COM * This function must be called from smb_drv_attach(). 2846139Sjb150015 */ 2856139Sjb150015 int 2866139Sjb150015 smb_server_svc_init(void) 2876139Sjb150015 { 2886139Sjb150015 int rc = 0; 2896139Sjb150015 2906139Sjb150015 while (rc == 0) { 2918934SJose.Borrego@Sun.COM if (rc = smb_mbc_init()) 2928934SJose.Borrego@Sun.COM continue; 2936139Sjb150015 if (rc = smb_vop_init()) 2946139Sjb150015 continue; 2956139Sjb150015 if (rc = smb_node_init()) 2966496Sjb150015 continue; 2976139Sjb150015 if (rc = smb_fem_init()) 2986496Sjb150015 continue; 2997348SJose.Borrego@Sun.COM if (rc = smb_user_init()) 3007348SJose.Borrego@Sun.COM continue; 3016139Sjb150015 if (rc = smb_notify_init()) 3026496Sjb150015 continue; 3036496Sjb150015 if (rc = smb_net_init()) 3046496Sjb150015 continue; 305*11963SAfshin.Ardakani@Sun.COM smb_llist_init(); 3066139Sjb150015 smb_llist_constructor(&smb_servers, sizeof (smb_server_t), 3076139Sjb150015 offsetof(smb_server_t, sv_lnd)); 3086139Sjb150015 return (0); 3096139Sjb150015 } 310*11963SAfshin.Ardakani@Sun.COM 311*11963SAfshin.Ardakani@Sun.COM smb_llist_fini(); 3126496Sjb150015 smb_net_fini(); 3136139Sjb150015 smb_notify_fini(); 3147348SJose.Borrego@Sun.COM smb_user_fini(); 3156139Sjb150015 smb_fem_fini(); 3166139Sjb150015 smb_node_fini(); 3176139Sjb150015 smb_vop_fini(); 3188934SJose.Borrego@Sun.COM smb_mbc_fini(); 3196139Sjb150015 return (rc); 3206139Sjb150015 } 3216139Sjb150015 3226139Sjb150015 /* 3236139Sjb150015 * smb_server_svc_fini 3246139Sjb150015 * 3256139Sjb150015 * This function must called from smb_drv_detach(). It will fail if servers 3266139Sjb150015 * still exist. 3276139Sjb150015 */ 3286139Sjb150015 int 3296139Sjb150015 smb_server_svc_fini(void) 3306139Sjb150015 { 3316139Sjb150015 int rc = EBUSY; 3326139Sjb150015 3336139Sjb150015 if (smb_llist_get_count(&smb_servers) == 0) { 334*11963SAfshin.Ardakani@Sun.COM smb_llist_fini(); 3356496Sjb150015 smb_net_fini(); 3366139Sjb150015 smb_notify_fini(); 3377348SJose.Borrego@Sun.COM smb_user_fini(); 3386139Sjb150015 smb_fem_fini(); 3396139Sjb150015 smb_node_fini(); 3406139Sjb150015 smb_vop_fini(); 3418934SJose.Borrego@Sun.COM smb_mbc_fini(); 3426139Sjb150015 smb_llist_destructor(&smb_servers); 3436139Sjb150015 rc = 0; 3446139Sjb150015 } 3456139Sjb150015 return (rc); 3466139Sjb150015 } 3476139Sjb150015 3486139Sjb150015 /* 3496139Sjb150015 * smb_server_create 3506139Sjb150015 * 3516139Sjb150015 * This function will fail if there's already a server associated with the 3526139Sjb150015 * caller's zone. 3536139Sjb150015 */ 3546139Sjb150015 int 3556139Sjb150015 smb_server_create(void) 3566139Sjb150015 { 3576139Sjb150015 zoneid_t zid; 3586139Sjb150015 smb_server_t *sv; 3596139Sjb150015 3606139Sjb150015 zid = getzoneid(); 3616139Sjb150015 3626139Sjb150015 smb_llist_enter(&smb_servers, RW_WRITER); 3636139Sjb150015 sv = smb_llist_head(&smb_servers); 3646139Sjb150015 while (sv) { 365*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 3666139Sjb150015 if (sv->sv_zid == zid) { 3676139Sjb150015 smb_llist_exit(&smb_servers); 3688167Samw@Sun.COM return (EPERM); 3696139Sjb150015 } 3706139Sjb150015 sv = smb_llist_next(&smb_servers, sv); 3716139Sjb150015 } 3726139Sjb150015 3736139Sjb150015 sv = kmem_zalloc(sizeof (smb_server_t), KM_NOSLEEP); 3746139Sjb150015 if (sv == NULL) { 3756139Sjb150015 smb_llist_exit(&smb_servers); 3766139Sjb150015 return (ENOMEM); 3776139Sjb150015 } 3786139Sjb150015 3796139Sjb150015 smb_llist_constructor(&sv->sv_vfs_list, sizeof (smb_vfs_t), 3806139Sjb150015 offsetof(smb_vfs_t, sv_lnd)); 3816139Sjb150015 382*11963SAfshin.Ardakani@Sun.COM smb_llist_constructor(&sv->sv_opipe_list, sizeof (smb_opipe_t), 383*11963SAfshin.Ardakani@Sun.COM offsetof(smb_opipe_t, p_lnd)); 384*11963SAfshin.Ardakani@Sun.COM 385*11963SAfshin.Ardakani@Sun.COM smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t), 386*11963SAfshin.Ardakani@Sun.COM offsetof(smb_event_t, se_lnd)); 387*11963SAfshin.Ardakani@Sun.COM 3887619SJose.Borrego@Sun.COM smb_slist_constructor(&sv->sv_unexport_list, sizeof (smb_unexport_t), 3897619SJose.Borrego@Sun.COM offsetof(smb_unexport_t, ux_lnd)); 3907619SJose.Borrego@Sun.COM 3916139Sjb150015 smb_session_list_constructor(&sv->sv_nbt_daemon.ld_session_list); 3926139Sjb150015 smb_session_list_constructor(&sv->sv_tcp_daemon.ld_session_list); 3936139Sjb150015 3947619SJose.Borrego@Sun.COM sv->si_cache_unexport = kmem_cache_create("smb_unexport_cache", 3957619SJose.Borrego@Sun.COM sizeof (smb_unexport_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3966139Sjb150015 sv->si_cache_vfs = kmem_cache_create("smb_vfs_cache", 3976139Sjb150015 sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3986139Sjb150015 sv->si_cache_request = kmem_cache_create("smb_request_cache", 3996139Sjb150015 sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 4006139Sjb150015 sv->si_cache_session = kmem_cache_create("smb_session_cache", 4016139Sjb150015 sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 4026139Sjb150015 sv->si_cache_user = kmem_cache_create("smb_user_cache", 4036139Sjb150015 sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 4046139Sjb150015 sv->si_cache_tree = kmem_cache_create("smb_tree_cache", 4056139Sjb150015 sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 4066139Sjb150015 sv->si_cache_ofile = kmem_cache_create("smb_ofile_cache", 4076139Sjb150015 sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 4086139Sjb150015 sv->si_cache_odir = kmem_cache_create("smb_odir_cache", 4096139Sjb150015 sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 410*11963SAfshin.Ardakani@Sun.COM sv->si_cache_opipe = kmem_cache_create("smb_opipe_cache", 411*11963SAfshin.Ardakani@Sun.COM sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 412*11963SAfshin.Ardakani@Sun.COM sv->si_cache_event = kmem_cache_create("smb_event_cache", 413*11963SAfshin.Ardakani@Sun.COM sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 4146139Sjb150015 4156139Sjb150015 smb_thread_init(&sv->si_thread_timers, 4166139Sjb150015 "smb_timers", smb_server_timers, sv, 4176139Sjb150015 NULL, NULL); 4186139Sjb150015 4197619SJose.Borrego@Sun.COM smb_thread_init(&sv->si_thread_unexport, "smb_thread_unexport", 4207619SJose.Borrego@Sun.COM smb_server_thread_unexport, sv, NULL, NULL); 4217619SJose.Borrego@Sun.COM 4226432Sas200622 sv->sv_pid = curproc->p_pid; 4236139Sjb150015 424*11963SAfshin.Ardakani@Sun.COM smb_kdoor_init(); 4257052Samw smb_opipe_door_init(); 4266139Sjb150015 (void) smb_server_kstat_init(sv); 4276139Sjb150015 4286139Sjb150015 mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL); 4296139Sjb150015 cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL); 4306139Sjb150015 sv->sv_state = SMB_SERVER_STATE_CREATED; 4316139Sjb150015 sv->sv_magic = SMB_SERVER_MAGIC; 4326139Sjb150015 sv->sv_zid = zid; 4336139Sjb150015 4346139Sjb150015 smb_llist_insert_tail(&smb_servers, sv); 4356139Sjb150015 smb_llist_exit(&smb_servers); 4366139Sjb150015 return (0); 4376139Sjb150015 } 4386139Sjb150015 4396139Sjb150015 /* 4406139Sjb150015 * smb_server_delete 4416139Sjb150015 * 4426139Sjb150015 * This function will delete the server passed in. It will make sure that all 4436139Sjb150015 * activity associated that server has ceased before destroying it. 4446139Sjb150015 */ 4456139Sjb150015 int 4466139Sjb150015 smb_server_delete(void) 4476139Sjb150015 { 4486139Sjb150015 smb_server_t *sv; 4497619SJose.Borrego@Sun.COM smb_unexport_t *ux; 450*11963SAfshin.Ardakani@Sun.COM kt_did_t nbt_tid; 451*11963SAfshin.Ardakani@Sun.COM kt_did_t tcp_tid; 4526139Sjb150015 int rc; 4536139Sjb150015 4546139Sjb150015 rc = smb_server_lookup(&sv); 4556139Sjb150015 if (rc != 0) 4566139Sjb150015 return (rc); 4576139Sjb150015 4586139Sjb150015 mutex_enter(&sv->sv_mutex); 4596139Sjb150015 switch (sv->sv_state) { 4606139Sjb150015 case SMB_SERVER_STATE_RUNNING: 461*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 462*11963SAfshin.Ardakani@Sun.COM sv->sv_state = SMB_SERVER_STATE_STOPPING; 463*11963SAfshin.Ardakani@Sun.COM smb_server_signal_listeners(sv); 464*11963SAfshin.Ardakani@Sun.COM nbt_tid = smb_server_listener_tid(&sv->sv_nbt_daemon); 465*11963SAfshin.Ardakani@Sun.COM tcp_tid = smb_server_listener_tid(&sv->sv_tcp_daemon); 4666139Sjb150015 4676139Sjb150015 sv->sv_state = SMB_SERVER_STATE_DELETING; 4686139Sjb150015 mutex_exit(&sv->sv_mutex); 469*11963SAfshin.Ardakani@Sun.COM 470*11963SAfshin.Ardakani@Sun.COM if (nbt_tid != 0) 471*11963SAfshin.Ardakani@Sun.COM thread_join(nbt_tid); 472*11963SAfshin.Ardakani@Sun.COM if (tcp_tid != 0) 473*11963SAfshin.Ardakani@Sun.COM thread_join(tcp_tid); 474*11963SAfshin.Ardakani@Sun.COM 475*11963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(&sv->sv_nbt_daemon); 476*11963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(&sv->sv_tcp_daemon); 4776139Sjb150015 mutex_enter(&sv->sv_mutex); 4786139Sjb150015 break; 4796139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 4806139Sjb150015 case SMB_SERVER_STATE_CREATED: 4816139Sjb150015 sv->sv_state = SMB_SERVER_STATE_DELETING; 4826139Sjb150015 break; 4836139Sjb150015 default: 484*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 4856139Sjb150015 mutex_exit(&sv->sv_mutex); 4866139Sjb150015 smb_server_release(sv); 4876139Sjb150015 return (ENOTTY); 4886139Sjb150015 } 4896139Sjb150015 4906139Sjb150015 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 4916139Sjb150015 4926139Sjb150015 sv->sv_refcnt--; 4936139Sjb150015 while (sv->sv_refcnt) 4946139Sjb150015 cv_wait(&sv->sv_cv, &sv->sv_mutex); 4956139Sjb150015 4966139Sjb150015 mutex_exit(&sv->sv_mutex); 4976139Sjb150015 4986139Sjb150015 smb_llist_enter(&smb_servers, RW_WRITER); 4996139Sjb150015 smb_llist_remove(&smb_servers, sv); 5006139Sjb150015 smb_llist_exit(&smb_servers); 5016139Sjb150015 502*11963SAfshin.Ardakani@Sun.COM smb_server_shutdown(sv); 5036139Sjb150015 rw_destroy(&sv->sv_cfg_lock); 5047052Samw smb_opipe_door_fini(); 505*11963SAfshin.Ardakani@Sun.COM smb_kdoor_fini(); 5066139Sjb150015 smb_server_kstat_fini(sv); 5076139Sjb150015 smb_llist_destructor(&sv->sv_vfs_list); 508*11963SAfshin.Ardakani@Sun.COM smb_llist_destructor(&sv->sv_opipe_list); 509*11963SAfshin.Ardakani@Sun.COM smb_llist_destructor(&sv->sv_event_list); 5107619SJose.Borrego@Sun.COM 5117619SJose.Borrego@Sun.COM while ((ux = list_head(&sv->sv_unexport_list.sl_list)) != NULL) { 5127619SJose.Borrego@Sun.COM smb_slist_remove(&sv->sv_unexport_list, ux); 5137619SJose.Borrego@Sun.COM kmem_cache_free(sv->si_cache_unexport, ux); 5147619SJose.Borrego@Sun.COM } 5157619SJose.Borrego@Sun.COM smb_slist_destructor(&sv->sv_unexport_list); 5167619SJose.Borrego@Sun.COM 5177619SJose.Borrego@Sun.COM kmem_cache_destroy(sv->si_cache_unexport); 5186139Sjb150015 kmem_cache_destroy(sv->si_cache_vfs); 5196139Sjb150015 kmem_cache_destroy(sv->si_cache_request); 5206139Sjb150015 kmem_cache_destroy(sv->si_cache_session); 5216139Sjb150015 kmem_cache_destroy(sv->si_cache_user); 5226139Sjb150015 kmem_cache_destroy(sv->si_cache_tree); 5236139Sjb150015 kmem_cache_destroy(sv->si_cache_ofile); 5246139Sjb150015 kmem_cache_destroy(sv->si_cache_odir); 525*11963SAfshin.Ardakani@Sun.COM kmem_cache_destroy(sv->si_cache_opipe); 526*11963SAfshin.Ardakani@Sun.COM kmem_cache_destroy(sv->si_cache_event); 5276139Sjb150015 5286139Sjb150015 smb_thread_destroy(&sv->si_thread_timers); 5297619SJose.Borrego@Sun.COM smb_thread_destroy(&sv->si_thread_unexport); 5306139Sjb150015 mutex_destroy(&sv->sv_mutex); 5316139Sjb150015 cv_destroy(&sv->sv_cv); 5326139Sjb150015 sv->sv_magic = 0; 5336139Sjb150015 kmem_free(sv, sizeof (smb_server_t)); 5346139Sjb150015 5356139Sjb150015 return (0); 5366139Sjb150015 } 5376139Sjb150015 5386139Sjb150015 /* 5396139Sjb150015 * smb_server_configure 5406139Sjb150015 */ 5416139Sjb150015 int 5429832Samw@Sun.COM smb_server_configure(smb_ioc_cfg_t *ioc) 5436139Sjb150015 { 5446139Sjb150015 int rc = 0; 5456139Sjb150015 smb_server_t *sv; 5466139Sjb150015 5476139Sjb150015 rc = smb_server_lookup(&sv); 5486139Sjb150015 if (rc) 5496139Sjb150015 return (rc); 5506139Sjb150015 5516139Sjb150015 mutex_enter(&sv->sv_mutex); 5526139Sjb150015 switch (sv->sv_state) { 5536139Sjb150015 case SMB_SERVER_STATE_CREATED: 5549832Samw@Sun.COM smb_server_store_cfg(sv, ioc); 5556139Sjb150015 sv->sv_state = SMB_SERVER_STATE_CONFIGURED; 5566139Sjb150015 break; 5576139Sjb150015 5586139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 5599832Samw@Sun.COM smb_server_store_cfg(sv, ioc); 5606139Sjb150015 break; 5616139Sjb150015 5626139Sjb150015 case SMB_SERVER_STATE_RUNNING: 563*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 5646139Sjb150015 rw_enter(&sv->sv_cfg_lock, RW_WRITER); 5659832Samw@Sun.COM smb_server_store_cfg(sv, ioc); 5666139Sjb150015 rw_exit(&sv->sv_cfg_lock); 5676139Sjb150015 break; 5686139Sjb150015 5696139Sjb150015 default: 570*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 5716139Sjb150015 rc = EFAULT; 5726139Sjb150015 break; 5736139Sjb150015 } 5746139Sjb150015 mutex_exit(&sv->sv_mutex); 5756139Sjb150015 5766139Sjb150015 smb_server_release(sv); 5776139Sjb150015 5786139Sjb150015 return (rc); 5796139Sjb150015 } 5806139Sjb150015 5816139Sjb150015 /* 5826139Sjb150015 * smb_server_start 5836139Sjb150015 */ 5846139Sjb150015 int 5859832Samw@Sun.COM smb_server_start(smb_ioc_start_t *ioc) 5866139Sjb150015 { 5876139Sjb150015 int rc = 0; 5886139Sjb150015 smb_server_t *sv; 5896139Sjb150015 5906139Sjb150015 rc = smb_server_lookup(&sv); 5916139Sjb150015 if (rc) 5926139Sjb150015 return (rc); 5936139Sjb150015 5946139Sjb150015 mutex_enter(&sv->sv_mutex); 5956139Sjb150015 switch (sv->sv_state) { 5966139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 59710966SJordan.Brown@Sun.COM smb_codepage_init(); 5986139Sjb150015 5996139Sjb150015 sv->sv_thread_pool = taskq_create("smb_workers", 6006139Sjb150015 sv->sv_cfg.skc_maxworkers, SMB_WORKER_PRIORITY, 6016139Sjb150015 sv->sv_cfg.skc_maxworkers, INT_MAX, 6026139Sjb150015 TASKQ_DYNAMIC|TASKQ_PREPOPULATE); 6036139Sjb150015 6048670SJose.Borrego@Sun.COM sv->sv_session = smb_session_create(NULL, 0, sv, 0); 6057588Samw@Sun.COM 6067588Samw@Sun.COM if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) { 6076139Sjb150015 rc = ENOMEM; 6086139Sjb150015 break; 6096139Sjb150015 } 6106139Sjb150015 6116139Sjb150015 if (rc = smb_server_fsop_start(sv)) 6126139Sjb150015 break; 6136139Sjb150015 ASSERT(sv->sv_lmshrd == NULL); 6149832Samw@Sun.COM sv->sv_lmshrd = smb_kshare_init(ioc->lmshrd); 6156139Sjb150015 if (sv->sv_lmshrd == NULL) 6166139Sjb150015 break; 617*11963SAfshin.Ardakani@Sun.COM if (rc = smb_kdoor_open(ioc->udoor)) { 618*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "Cannot open smbd door"); 6196139Sjb150015 break; 620*11963SAfshin.Ardakani@Sun.COM } 621*11963SAfshin.Ardakani@Sun.COM if (rc = smb_opipe_door_open(ioc->opipe)) { 622*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "Cannot open opipe door"); 623*11963SAfshin.Ardakani@Sun.COM break; 624*11963SAfshin.Ardakani@Sun.COM } 6256139Sjb150015 if (rc = smb_thread_start(&sv->si_thread_timers)) 6266139Sjb150015 break; 6277619SJose.Borrego@Sun.COM if (rc = smb_thread_start(&sv->si_thread_unexport)) 6287619SJose.Borrego@Sun.COM break; 6296139Sjb150015 sv->sv_state = SMB_SERVER_STATE_RUNNING; 6306139Sjb150015 mutex_exit(&sv->sv_mutex); 6316139Sjb150015 smb_server_release(sv); 6326139Sjb150015 return (0); 6336139Sjb150015 default: 634*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 6356139Sjb150015 mutex_exit(&sv->sv_mutex); 6366139Sjb150015 smb_server_release(sv); 6376139Sjb150015 return (ENOTTY); 6386139Sjb150015 } 6396139Sjb150015 640*11963SAfshin.Ardakani@Sun.COM smb_server_shutdown(sv); 6416139Sjb150015 mutex_exit(&sv->sv_mutex); 6426139Sjb150015 smb_server_release(sv); 6436139Sjb150015 return (rc); 6446139Sjb150015 } 6456139Sjb150015 6466139Sjb150015 /* 647*11963SAfshin.Ardakani@Sun.COM * An smbd is shutting down. 648*11963SAfshin.Ardakani@Sun.COM */ 649*11963SAfshin.Ardakani@Sun.COM int 650*11963SAfshin.Ardakani@Sun.COM smb_server_stop(void) 651*11963SAfshin.Ardakani@Sun.COM { 652*11963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 653*11963SAfshin.Ardakani@Sun.COM int rc; 654*11963SAfshin.Ardakani@Sun.COM 655*11963SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) != 0) 656*11963SAfshin.Ardakani@Sun.COM return (rc); 657*11963SAfshin.Ardakani@Sun.COM 658*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sv->sv_mutex); 659*11963SAfshin.Ardakani@Sun.COM switch (sv->sv_state) { 660*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_RUNNING: 661*11963SAfshin.Ardakani@Sun.COM sv->sv_state = SMB_SERVER_STATE_STOPPING; 662*11963SAfshin.Ardakani@Sun.COM smb_server_signal_listeners(sv); 663*11963SAfshin.Ardakani@Sun.COM break; 664*11963SAfshin.Ardakani@Sun.COM default: 665*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 666*11963SAfshin.Ardakani@Sun.COM break; 667*11963SAfshin.Ardakani@Sun.COM } 668*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 669*11963SAfshin.Ardakani@Sun.COM 670*11963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 671*11963SAfshin.Ardakani@Sun.COM return (0); 672*11963SAfshin.Ardakani@Sun.COM } 673*11963SAfshin.Ardakani@Sun.COM 674*11963SAfshin.Ardakani@Sun.COM boolean_t 675*11963SAfshin.Ardakani@Sun.COM smb_server_is_stopping(void) 676*11963SAfshin.Ardakani@Sun.COM { 677*11963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 678*11963SAfshin.Ardakani@Sun.COM boolean_t status; 679*11963SAfshin.Ardakani@Sun.COM 680*11963SAfshin.Ardakani@Sun.COM if (smb_server_lookup(&sv) != 0) 681*11963SAfshin.Ardakani@Sun.COM return (B_TRUE); 682*11963SAfshin.Ardakani@Sun.COM 683*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 684*11963SAfshin.Ardakani@Sun.COM 685*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sv->sv_mutex); 686*11963SAfshin.Ardakani@Sun.COM 687*11963SAfshin.Ardakani@Sun.COM switch (sv->sv_state) { 688*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 689*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_DELETING: 690*11963SAfshin.Ardakani@Sun.COM status = B_TRUE; 691*11963SAfshin.Ardakani@Sun.COM break; 692*11963SAfshin.Ardakani@Sun.COM default: 693*11963SAfshin.Ardakani@Sun.COM status = B_FALSE; 694*11963SAfshin.Ardakani@Sun.COM break; 695*11963SAfshin.Ardakani@Sun.COM } 696*11963SAfshin.Ardakani@Sun.COM 697*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 698*11963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 699*11963SAfshin.Ardakani@Sun.COM return (status); 700*11963SAfshin.Ardakani@Sun.COM } 701*11963SAfshin.Ardakani@Sun.COM 702*11963SAfshin.Ardakani@Sun.COM int 703*11963SAfshin.Ardakani@Sun.COM smb_server_cancel_event(uint32_t txid) 704*11963SAfshin.Ardakani@Sun.COM { 705*11963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 706*11963SAfshin.Ardakani@Sun.COM int rc; 707*11963SAfshin.Ardakani@Sun.COM 708*11963SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 709*11963SAfshin.Ardakani@Sun.COM smb_event_cancel(sv, txid); 710*11963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 711*11963SAfshin.Ardakani@Sun.COM } 712*11963SAfshin.Ardakani@Sun.COM 713*11963SAfshin.Ardakani@Sun.COM return (rc); 714*11963SAfshin.Ardakani@Sun.COM } 715*11963SAfshin.Ardakani@Sun.COM 716*11963SAfshin.Ardakani@Sun.COM int 717*11963SAfshin.Ardakani@Sun.COM smb_server_notify_event(smb_ioc_event_t *ioc) 718*11963SAfshin.Ardakani@Sun.COM { 719*11963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 720*11963SAfshin.Ardakani@Sun.COM int rc; 721*11963SAfshin.Ardakani@Sun.COM 722*11963SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 723*11963SAfshin.Ardakani@Sun.COM smb_event_notify(sv, ioc->txid); 724*11963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 725*11963SAfshin.Ardakani@Sun.COM } 726*11963SAfshin.Ardakani@Sun.COM 727*11963SAfshin.Ardakani@Sun.COM return (rc); 728*11963SAfshin.Ardakani@Sun.COM } 729*11963SAfshin.Ardakani@Sun.COM 730*11963SAfshin.Ardakani@Sun.COM /* 731*11963SAfshin.Ardakani@Sun.COM * SMB-over-NetBIOS (port 139) 7326139Sjb150015 * 733*11963SAfshin.Ardakani@Sun.COM * Traditional SMB service over NetBIOS, which requires that a NetBIOS 734*11963SAfshin.Ardakani@Sun.COM * session be established. 7356139Sjb150015 */ 7366139Sjb150015 int 7379832Samw@Sun.COM smb_server_nbt_listen(smb_ioc_listen_t *ioc) 7386139Sjb150015 { 7396139Sjb150015 smb_server_t *sv; 7406139Sjb150015 int rc; 7416139Sjb150015 7426139Sjb150015 rc = smb_server_lookup(&sv); 7436139Sjb150015 if (rc) 7446139Sjb150015 return (rc); 7456139Sjb150015 7466139Sjb150015 mutex_enter(&sv->sv_mutex); 7476139Sjb150015 switch (sv->sv_state) { 7486139Sjb150015 case SMB_SERVER_STATE_RUNNING: 7496139Sjb150015 if ((sv->sv_nbt_daemon.ld_kth != NULL) && 7506139Sjb150015 (sv->sv_nbt_daemon.ld_kth != curthread)) { 7516139Sjb150015 mutex_exit(&sv->sv_mutex); 7529422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 7536139Sjb150015 return (EACCES); 7546139Sjb150015 } else { 7556139Sjb150015 sv->sv_nbt_daemon.ld_kth = curthread; 7566139Sjb150015 sv->sv_nbt_daemon.ld_ktdid = curthread->t_did; 7576139Sjb150015 } 7586139Sjb150015 break; 759*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 760*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 761*11963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 762*11963SAfshin.Ardakani@Sun.COM return (ECANCELED); 7636139Sjb150015 default: 764*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 7656139Sjb150015 mutex_exit(&sv->sv_mutex); 7666139Sjb150015 smb_server_release(sv); 7676139Sjb150015 return (EFAULT); 7686139Sjb150015 } 7696139Sjb150015 mutex_exit(&sv->sv_mutex); 7706139Sjb150015 7718670SJose.Borrego@Sun.COM /* 7728670SJose.Borrego@Sun.COM * netbios must be ipv4 7738670SJose.Borrego@Sun.COM */ 77410717Samw@Sun.COM rc = smb_server_listen(sv, &sv->sv_nbt_daemon, IPPORT_NETBIOS_SSN, 7759832Samw@Sun.COM AF_INET, ioc->error); 7766139Sjb150015 777*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sv->sv_mutex); 778*11963SAfshin.Ardakani@Sun.COM sv->sv_nbt_daemon.ld_kth = NULL; 779*11963SAfshin.Ardakani@Sun.COM 780*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 7816139Sjb150015 7826139Sjb150015 smb_server_release(sv); 7836139Sjb150015 return (rc); 7846139Sjb150015 } 7856139Sjb150015 786*11963SAfshin.Ardakani@Sun.COM /* 787*11963SAfshin.Ardakani@Sun.COM * SMB-over-TCP (port 445) 788*11963SAfshin.Ardakani@Sun.COM */ 7896139Sjb150015 int 7909832Samw@Sun.COM smb_server_tcp_listen(smb_ioc_listen_t *ioc) 7916139Sjb150015 { 7926139Sjb150015 smb_server_t *sv; 7936139Sjb150015 int rc; 7946139Sjb150015 7956139Sjb150015 rc = smb_server_lookup(&sv); 7966139Sjb150015 if (rc) 7976139Sjb150015 return (rc); 7986139Sjb150015 7996139Sjb150015 mutex_enter(&sv->sv_mutex); 8006139Sjb150015 switch (sv->sv_state) { 8016139Sjb150015 case SMB_SERVER_STATE_RUNNING: 802*11963SAfshin.Ardakani@Sun.COM if ((sv->sv_tcp_daemon.ld_kth != NULL) && 8036139Sjb150015 (sv->sv_tcp_daemon.ld_kth != curthread)) { 8046139Sjb150015 mutex_exit(&sv->sv_mutex); 8059422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 8066139Sjb150015 return (EACCES); 8076139Sjb150015 } else { 8086139Sjb150015 sv->sv_tcp_daemon.ld_kth = curthread; 8096139Sjb150015 sv->sv_tcp_daemon.ld_ktdid = curthread->t_did; 8106139Sjb150015 } 8116139Sjb150015 break; 812*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 813*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 814*11963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 815*11963SAfshin.Ardakani@Sun.COM return (ECANCELED); 8166139Sjb150015 default: 817*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 8186139Sjb150015 mutex_exit(&sv->sv_mutex); 8199422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 8206139Sjb150015 return (EFAULT); 8216139Sjb150015 } 8226139Sjb150015 mutex_exit(&sv->sv_mutex); 8236139Sjb150015 8248670SJose.Borrego@Sun.COM if (sv->sv_cfg.skc_ipv6_enable) 8258670SJose.Borrego@Sun.COM rc = smb_server_listen(sv, &sv->sv_tcp_daemon, 82610717Samw@Sun.COM IPPORT_SMB, AF_INET6, ioc->error); 8278670SJose.Borrego@Sun.COM else 8288670SJose.Borrego@Sun.COM rc = smb_server_listen(sv, &sv->sv_tcp_daemon, 82910717Samw@Sun.COM IPPORT_SMB, AF_INET, ioc->error); 830*11963SAfshin.Ardakani@Sun.COM 831*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sv->sv_mutex); 832*11963SAfshin.Ardakani@Sun.COM sv->sv_tcp_daemon.ld_kth = NULL; 833*11963SAfshin.Ardakani@Sun.COM 834*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 8356139Sjb150015 8366139Sjb150015 smb_server_release(sv); 8376139Sjb150015 return (rc); 8386139Sjb150015 } 8396139Sjb150015 8406139Sjb150015 /* 8416139Sjb150015 * smb_server_nbt_receive 8426139Sjb150015 */ 8436139Sjb150015 int 8446139Sjb150015 smb_server_nbt_receive(void) 8456139Sjb150015 { 8466139Sjb150015 int rc; 8476139Sjb150015 smb_server_t *sv; 8486139Sjb150015 8499422SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 8509422SAfshin.Ardakani@Sun.COM rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list); 8519422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 8529422SAfshin.Ardakani@Sun.COM } 8536139Sjb150015 8546139Sjb150015 return (rc); 8556139Sjb150015 } 8566139Sjb150015 8576139Sjb150015 /* 8586139Sjb150015 * smb_server_tcp_receive 8596139Sjb150015 */ 8606139Sjb150015 int 8616139Sjb150015 smb_server_tcp_receive(void) 8626139Sjb150015 { 8636139Sjb150015 int rc; 8646139Sjb150015 smb_server_t *sv; 8656139Sjb150015 8669422SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 8679422SAfshin.Ardakani@Sun.COM rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list); 8689422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 8699422SAfshin.Ardakani@Sun.COM } 8706139Sjb150015 8716139Sjb150015 return (rc); 8726139Sjb150015 } 8736139Sjb150015 8746139Sjb150015 int 8759832Samw@Sun.COM smb_server_set_gmtoff(smb_ioc_gmt_t *ioc) 8766139Sjb150015 { 8776139Sjb150015 int rc; 8786139Sjb150015 smb_server_t *sv; 8796139Sjb150015 8809422SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 8819832Samw@Sun.COM sv->si_gmtoff = ioc->offset; 8829422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 8839422SAfshin.Ardakani@Sun.COM } 8846139Sjb150015 8856139Sjb150015 return (rc); 8866139Sjb150015 } 8876139Sjb150015 8889832Samw@Sun.COM int 88910122SJordan.Brown@Sun.COM smb_server_numopen(smb_ioc_opennum_t *ioc) 8909832Samw@Sun.COM { 8919832Samw@Sun.COM smb_server_t *sv; 8929832Samw@Sun.COM int rc; 8939832Samw@Sun.COM 8949832Samw@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 89510122SJordan.Brown@Sun.COM ioc->open_users = sv->sv_open_users; 89610122SJordan.Brown@Sun.COM ioc->open_trees = sv->sv_open_trees; 89710122SJordan.Brown@Sun.COM ioc->open_files = sv->sv_open_files; 8989832Samw@Sun.COM smb_server_release(sv); 8999832Samw@Sun.COM } 9009832Samw@Sun.COM return (rc); 9019832Samw@Sun.COM } 9029832Samw@Sun.COM 9036139Sjb150015 /* 90410122SJordan.Brown@Sun.COM * Enumerate objects within the server. The svcenum provides the 90510122SJordan.Brown@Sun.COM * enumeration context, i.e. what the caller want to get back. 90610122SJordan.Brown@Sun.COM */ 90710122SJordan.Brown@Sun.COM int 90810122SJordan.Brown@Sun.COM smb_server_enum(smb_ioc_svcenum_t *ioc) 90910122SJordan.Brown@Sun.COM { 91010122SJordan.Brown@Sun.COM smb_svcenum_t *svcenum = &ioc->svcenum; 91110122SJordan.Brown@Sun.COM smb_server_t *sv; 91210122SJordan.Brown@Sun.COM smb_session_list_t *se; 91310122SJordan.Brown@Sun.COM int rc; 91410122SJordan.Brown@Sun.COM 91510122SJordan.Brown@Sun.COM switch (svcenum->se_type) { 91610122SJordan.Brown@Sun.COM case SMB_SVCENUM_TYPE_USER: 91710122SJordan.Brown@Sun.COM case SMB_SVCENUM_TYPE_TREE: 91810122SJordan.Brown@Sun.COM case SMB_SVCENUM_TYPE_FILE: 91910122SJordan.Brown@Sun.COM break; 92010122SJordan.Brown@Sun.COM default: 92110122SJordan.Brown@Sun.COM return (EINVAL); 92210122SJordan.Brown@Sun.COM } 92310122SJordan.Brown@Sun.COM 92410122SJordan.Brown@Sun.COM if ((rc = smb_server_lookup(&sv)) != 0) 92510122SJordan.Brown@Sun.COM return (rc); 92610122SJordan.Brown@Sun.COM 92710122SJordan.Brown@Sun.COM svcenum->se_bavail = svcenum->se_buflen; 92810122SJordan.Brown@Sun.COM svcenum->se_bused = 0; 92910122SJordan.Brown@Sun.COM svcenum->se_nitems = 0; 93010122SJordan.Brown@Sun.COM 93110122SJordan.Brown@Sun.COM se = &sv->sv_nbt_daemon.ld_session_list; 93210122SJordan.Brown@Sun.COM smb_server_enum_private(se, svcenum); 93310122SJordan.Brown@Sun.COM 93410122SJordan.Brown@Sun.COM se = &sv->sv_tcp_daemon.ld_session_list; 93510122SJordan.Brown@Sun.COM smb_server_enum_private(se, svcenum); 93610122SJordan.Brown@Sun.COM 93710122SJordan.Brown@Sun.COM smb_server_release(sv); 93810122SJordan.Brown@Sun.COM return (0); 93910122SJordan.Brown@Sun.COM } 94010122SJordan.Brown@Sun.COM 94110122SJordan.Brown@Sun.COM /* 94210122SJordan.Brown@Sun.COM * Look for sessions to disconnect by client and user name. 94310122SJordan.Brown@Sun.COM */ 94410122SJordan.Brown@Sun.COM int 94510122SJordan.Brown@Sun.COM smb_server_session_close(smb_ioc_session_t *ioc) 94610122SJordan.Brown@Sun.COM { 94710122SJordan.Brown@Sun.COM smb_session_list_t *se; 94810122SJordan.Brown@Sun.COM smb_server_t *sv; 94910122SJordan.Brown@Sun.COM int nbt_cnt; 95010122SJordan.Brown@Sun.COM int tcp_cnt; 95110122SJordan.Brown@Sun.COM int rc; 95210122SJordan.Brown@Sun.COM 95310122SJordan.Brown@Sun.COM if ((rc = smb_server_lookup(&sv)) != 0) 95410122SJordan.Brown@Sun.COM return (rc); 95510122SJordan.Brown@Sun.COM 95610122SJordan.Brown@Sun.COM se = &sv->sv_nbt_daemon.ld_session_list; 95710122SJordan.Brown@Sun.COM nbt_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username); 95810122SJordan.Brown@Sun.COM 95910122SJordan.Brown@Sun.COM se = &sv->sv_tcp_daemon.ld_session_list; 96010122SJordan.Brown@Sun.COM tcp_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username); 96110122SJordan.Brown@Sun.COM 96210122SJordan.Brown@Sun.COM smb_server_release(sv); 96310122SJordan.Brown@Sun.COM 96410122SJordan.Brown@Sun.COM if ((nbt_cnt == 0) && (tcp_cnt == 0)) 96510122SJordan.Brown@Sun.COM return (ENOENT); 96610122SJordan.Brown@Sun.COM return (0); 96710122SJordan.Brown@Sun.COM } 96810122SJordan.Brown@Sun.COM 96910122SJordan.Brown@Sun.COM /* 97010122SJordan.Brown@Sun.COM * Close a file by uniqid. 97110122SJordan.Brown@Sun.COM */ 97210122SJordan.Brown@Sun.COM int 97310122SJordan.Brown@Sun.COM smb_server_file_close(smb_ioc_fileid_t *ioc) 97410122SJordan.Brown@Sun.COM { 97510122SJordan.Brown@Sun.COM uint32_t uniqid = ioc->uniqid; 97610122SJordan.Brown@Sun.COM smb_session_list_t *se; 97710122SJordan.Brown@Sun.COM smb_server_t *sv; 97810122SJordan.Brown@Sun.COM int rc; 97910122SJordan.Brown@Sun.COM 98010122SJordan.Brown@Sun.COM if ((rc = smb_server_lookup(&sv)) != 0) 98110122SJordan.Brown@Sun.COM return (rc); 98210122SJordan.Brown@Sun.COM 98310122SJordan.Brown@Sun.COM se = &sv->sv_nbt_daemon.ld_session_list; 98410122SJordan.Brown@Sun.COM rc = smb_server_fclose(se, uniqid); 98510122SJordan.Brown@Sun.COM 98610122SJordan.Brown@Sun.COM if (rc == ENOENT) { 98710122SJordan.Brown@Sun.COM se = &sv->sv_tcp_daemon.ld_session_list; 98810122SJordan.Brown@Sun.COM rc = smb_server_fclose(se, uniqid); 98910122SJordan.Brown@Sun.COM } 99010122SJordan.Brown@Sun.COM 99110122SJordan.Brown@Sun.COM smb_server_release(sv); 99210122SJordan.Brown@Sun.COM return (rc); 99310122SJordan.Brown@Sun.COM } 99410122SJordan.Brown@Sun.COM 99510122SJordan.Brown@Sun.COM /* 9966139Sjb150015 * These functions determine the relevant smb server to which the call apply. 9976139Sjb150015 */ 9986139Sjb150015 9996139Sjb150015 uint32_t 10006139Sjb150015 smb_server_get_session_count(void) 10016139Sjb150015 { 10026139Sjb150015 smb_server_t *sv; 10036139Sjb150015 uint32_t counter = 0; 10046139Sjb150015 10056139Sjb150015 if (smb_server_lookup(&sv)) 10066139Sjb150015 return (0); 10076139Sjb150015 10086139Sjb150015 rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER); 10096139Sjb150015 counter = sv->sv_nbt_daemon.ld_session_list.se_act.count; 10106139Sjb150015 rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock); 10116139Sjb150015 rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER); 10126139Sjb150015 counter += sv->sv_tcp_daemon.ld_session_list.se_act.count; 10136139Sjb150015 rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock); 10146139Sjb150015 10156139Sjb150015 smb_server_release(sv); 10166139Sjb150015 10176139Sjb150015 return (counter); 10186139Sjb150015 } 10196139Sjb150015 10206139Sjb150015 /* 1021*11963SAfshin.Ardakani@Sun.COM * Disconnect the specified share. 1022*11963SAfshin.Ardakani@Sun.COM * Typically called when a share has been removed. 10236139Sjb150015 */ 10247619SJose.Borrego@Sun.COM static void 1025*11963SAfshin.Ardakani@Sun.COM smb_server_disconnect_share(smb_session_list_t *slist, const char *sharename) 10266139Sjb150015 { 1027*11963SAfshin.Ardakani@Sun.COM smb_session_t *session; 1028*11963SAfshin.Ardakani@Sun.COM 1029*11963SAfshin.Ardakani@Sun.COM rw_enter(&slist->se_lock, RW_READER); 1030*11963SAfshin.Ardakani@Sun.COM 1031*11963SAfshin.Ardakani@Sun.COM session = list_head(&slist->se_act.lst); 1032*11963SAfshin.Ardakani@Sun.COM while (session) { 1033*11963SAfshin.Ardakani@Sun.COM ASSERT(session->s_magic == SMB_SESSION_MAGIC); 1034*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwenter(&session->s_lock, RW_READER); 1035*11963SAfshin.Ardakani@Sun.COM switch (session->s_state) { 1036*11963SAfshin.Ardakani@Sun.COM case SMB_SESSION_STATE_NEGOTIATED: 1037*11963SAfshin.Ardakani@Sun.COM case SMB_SESSION_STATE_OPLOCK_BREAKING: 1038*11963SAfshin.Ardakani@Sun.COM case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: 1039*11963SAfshin.Ardakani@Sun.COM smb_session_disconnect_share(session, sharename); 1040*11963SAfshin.Ardakani@Sun.COM break; 1041*11963SAfshin.Ardakani@Sun.COM default: 1042*11963SAfshin.Ardakani@Sun.COM break; 1043*11963SAfshin.Ardakani@Sun.COM } 1044*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwexit(&session->s_lock); 1045*11963SAfshin.Ardakani@Sun.COM session = list_next(&slist->se_act.lst, session); 1046*11963SAfshin.Ardakani@Sun.COM } 1047*11963SAfshin.Ardakani@Sun.COM 1048*11963SAfshin.Ardakani@Sun.COM rw_exit(&slist->se_lock); 10496139Sjb150015 } 10506139Sjb150015 10516139Sjb150015 /* 10526139Sjb150015 * smb_server_share_export() 10536139Sjb150015 * 10546139Sjb150015 * This function handles kernel processing at share enable time. 10556139Sjb150015 * 10566139Sjb150015 * At share-enable time (LMSHRD_ADD), the file system corresponding to 10576139Sjb150015 * the share is checked for characteristics that are required for SMB 10586139Sjb150015 * sharing. If this check passes, then a hold is taken on the root vnode 10596139Sjb150015 * of the file system (or a reference count on the corresponding smb_vfs_t 10606139Sjb150015 * is bumped), preventing an unmount. (See smb_vfs_hold()). 10616139Sjb150015 */ 10626139Sjb150015 10636139Sjb150015 int 10649832Samw@Sun.COM smb_server_share_export(smb_ioc_share_t *ioc) 10656139Sjb150015 { 10666139Sjb150015 smb_server_t *sv; 10679422SAfshin.Ardakani@Sun.COM int error = 0; 10686139Sjb150015 smb_node_t *fnode = NULL; 10696139Sjb150015 smb_node_t *dnode; 10706139Sjb150015 char last_comp[MAXNAMELEN]; 10716139Sjb150015 smb_request_t *sr; 10726139Sjb150015 10736139Sjb150015 if (smb_server_lookup(&sv)) 10746139Sjb150015 return (EINVAL); 10756139Sjb150015 10769832Samw@Sun.COM mutex_enter(&sv->sv_mutex); 10779832Samw@Sun.COM switch (sv->sv_state) { 10789832Samw@Sun.COM case SMB_SERVER_STATE_RUNNING: 1079*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 10809832Samw@Sun.COM break; 10819832Samw@Sun.COM default: 10829832Samw@Sun.COM mutex_exit(&sv->sv_mutex); 10839832Samw@Sun.COM return (ENOTACTIVE); 10849832Samw@Sun.COM } 10859832Samw@Sun.COM mutex_exit(&sv->sv_mutex); 10869832Samw@Sun.COM 10876139Sjb150015 sr = smb_request_alloc(sv->sv_session, 0); 10886139Sjb150015 if (sr == NULL) { 10896139Sjb150015 smb_server_release(sv); 10906139Sjb150015 return (ENOMEM); 10916139Sjb150015 } 10926139Sjb150015 10936139Sjb150015 sr->user_cr = kcred; 10946139Sjb150015 10959832Samw@Sun.COM error = smb_pathname_reduce(sr, kcred, ioc->path, 10969832Samw@Sun.COM NULL, NULL, &dnode, last_comp); 10976139Sjb150015 10986139Sjb150015 if (error) { 10996139Sjb150015 smb_request_free(sr); 11006139Sjb150015 smb_server_release(sv); 11016139Sjb150015 return (error); 11026139Sjb150015 } 11036139Sjb150015 11049231SAfshin.Ardakani@Sun.COM error = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, 110510001SJoyce.McIntosh@Sun.COM sv->si_root_smb_node, dnode, last_comp, &fnode); 11066139Sjb150015 11076139Sjb150015 smb_node_release(dnode); 11086139Sjb150015 11096139Sjb150015 if (error) { 11106139Sjb150015 smb_request_free(sr); 11116139Sjb150015 smb_server_release(sv); 11126139Sjb150015 return (error); 11136139Sjb150015 } 11146139Sjb150015 11156139Sjb150015 ASSERT(fnode->vp && fnode->vp->v_vfsp); 11166139Sjb150015 11176139Sjb150015 #ifdef SMB_ENFORCE_NODEV 11189422SAfshin.Ardakani@Sun.COM if (vfs_optionisset(fnode->vp->v_vfsp, MNTOPT_NODEVICES, NULL) == 0) { 11196139Sjb150015 smb_node_release(fnode); 11206139Sjb150015 smb_request_free(sr); 11216139Sjb150015 smb_server_release(sv); 11229422SAfshin.Ardakani@Sun.COM return (EINVAL); 11236139Sjb150015 } 11249422SAfshin.Ardakani@Sun.COM #endif /* SMB_ENFORCE_NODEV */ 11259422SAfshin.Ardakani@Sun.COM 11269422SAfshin.Ardakani@Sun.COM if (!smb_vfs_hold(sv, fnode->vp->v_vfsp)) 11279422SAfshin.Ardakani@Sun.COM error = ENOMEM; 11286139Sjb150015 11296139Sjb150015 /* 11306139Sjb150015 * The refcount on the smb_vfs has been incremented. 11316139Sjb150015 * If it wasn't already, a hold has also been taken 11326139Sjb150015 * on the root vnode of the file system. 11336139Sjb150015 */ 11346139Sjb150015 11356139Sjb150015 smb_node_release(fnode); 11366139Sjb150015 smb_request_free(sr); 11376139Sjb150015 smb_server_release(sv); 11389422SAfshin.Ardakani@Sun.COM return (error); 11396139Sjb150015 } 11406139Sjb150015 11416139Sjb150015 /* 11426139Sjb150015 * smb_server_share_unexport() 11436139Sjb150015 * 11447619SJose.Borrego@Sun.COM * This function is invoked when a share is disabled to disconnect trees 11457619SJose.Borrego@Sun.COM * and close files. Cleaning up may involve VOP and/or VFS calls, which 11467619SJose.Borrego@Sun.COM * may conflict/deadlock with stuck threads if something is amiss with the 11477619SJose.Borrego@Sun.COM * file system. Queueing the request for asynchronous processing allows the 11487619SJose.Borrego@Sun.COM * call to return immediately so that, if the unshare is being done in the 11497619SJose.Borrego@Sun.COM * context of a forced unmount, the forced unmount will always be able to 11507619SJose.Borrego@Sun.COM * proceed (unblocking stuck I/O and eventually allowing all blocked unshare 11517619SJose.Borrego@Sun.COM * processes to complete). 11526139Sjb150015 * 11537619SJose.Borrego@Sun.COM * The path lookup to find the root vnode of the VFS in question and the 11547619SJose.Borrego@Sun.COM * release of this vnode are done synchronously prior to any associated 11557619SJose.Borrego@Sun.COM * unmount. Doing these asynchronous to an associated unmount could run 11567619SJose.Borrego@Sun.COM * the risk of a spurious EBUSY for a standard unmount or an EIO during 11577619SJose.Borrego@Sun.COM * the path lookup due to a forced unmount finishing first. 11586139Sjb150015 */ 11596139Sjb150015 11606139Sjb150015 int 11619832Samw@Sun.COM smb_server_share_unexport(smb_ioc_share_t *ioc) 11626139Sjb150015 { 11636139Sjb150015 smb_server_t *sv; 11647619SJose.Borrego@Sun.COM smb_request_t *sr; 11657619SJose.Borrego@Sun.COM smb_unexport_t *ux; 11666139Sjb150015 smb_node_t *fnode = NULL; 11676139Sjb150015 smb_node_t *dnode; 11686139Sjb150015 char last_comp[MAXNAMELEN]; 11697619SJose.Borrego@Sun.COM int rc; 11706139Sjb150015 11717619SJose.Borrego@Sun.COM if ((rc = smb_server_lookup(&sv))) 11727619SJose.Borrego@Sun.COM return (rc); 11736139Sjb150015 11749832Samw@Sun.COM mutex_enter(&sv->sv_mutex); 11759832Samw@Sun.COM switch (sv->sv_state) { 11769832Samw@Sun.COM case SMB_SERVER_STATE_RUNNING: 1177*11963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 11789832Samw@Sun.COM break; 11799832Samw@Sun.COM default: 11809832Samw@Sun.COM mutex_exit(&sv->sv_mutex); 11819832Samw@Sun.COM return (ENOTACTIVE); 11829832Samw@Sun.COM } 11839832Samw@Sun.COM mutex_exit(&sv->sv_mutex); 11849832Samw@Sun.COM 11856139Sjb150015 sr = smb_request_alloc(sv->sv_session, 0); 11867619SJose.Borrego@Sun.COM 11876139Sjb150015 if (sr == NULL) { 11886139Sjb150015 smb_server_release(sv); 11896139Sjb150015 return (ENOMEM); 11906139Sjb150015 } 11917619SJose.Borrego@Sun.COM 11926139Sjb150015 sr->user_cr = kcred; 11936139Sjb150015 11949832Samw@Sun.COM rc = smb_pathname_reduce(sr, kcred, ioc->path, NULL, NULL, 11959832Samw@Sun.COM &dnode, last_comp); 11966139Sjb150015 11977619SJose.Borrego@Sun.COM if (rc) { 11986139Sjb150015 smb_request_free(sr); 11996139Sjb150015 smb_server_release(sv); 12007619SJose.Borrego@Sun.COM return (rc); 12016139Sjb150015 } 12026139Sjb150015 12039231SAfshin.Ardakani@Sun.COM rc = smb_fsop_lookup(sr, kcred, SMB_FOLLOW_LINKS, sv->si_root_smb_node, 120410001SJoyce.McIntosh@Sun.COM dnode, last_comp, &fnode); 12056139Sjb150015 12066139Sjb150015 smb_node_release(dnode); 12077619SJose.Borrego@Sun.COM smb_request_free(sr); 12086139Sjb150015 12097619SJose.Borrego@Sun.COM if (rc) { 12106139Sjb150015 smb_server_release(sv); 12117619SJose.Borrego@Sun.COM return (rc); 12126139Sjb150015 } 12136139Sjb150015 12146139Sjb150015 ASSERT(fnode->vp && fnode->vp->v_vfsp); 12156139Sjb150015 12166139Sjb150015 smb_vfs_rele(sv, fnode->vp->v_vfsp); 12177619SJose.Borrego@Sun.COM 12186139Sjb150015 smb_node_release(fnode); 12197619SJose.Borrego@Sun.COM 12207619SJose.Borrego@Sun.COM ux = kmem_cache_alloc(sv->si_cache_unexport, KM_SLEEP); 12217619SJose.Borrego@Sun.COM 12229832Samw@Sun.COM (void) strlcpy(ux->ux_sharename, ioc->name, MAXNAMELEN); 12237619SJose.Borrego@Sun.COM 12247619SJose.Borrego@Sun.COM smb_slist_insert_tail(&sv->sv_unexport_list, ux); 12257619SJose.Borrego@Sun.COM smb_thread_signal(&sv->si_thread_unexport); 12267619SJose.Borrego@Sun.COM 12276139Sjb150015 smb_server_release(sv); 12286139Sjb150015 return (0); 12296139Sjb150015 } 12306139Sjb150015 12316139Sjb150015 /* 12327619SJose.Borrego@Sun.COM * smb_server_thread_unexport 12337619SJose.Borrego@Sun.COM * 12347619SJose.Borrego@Sun.COM * This function processes the unexport event list and disconnects shares 12357619SJose.Borrego@Sun.COM * asynchronously. The function executes as a zone-specific thread. 12367619SJose.Borrego@Sun.COM * 12377619SJose.Borrego@Sun.COM * The server arg passed in is safe to use without a reference count, because 12387619SJose.Borrego@Sun.COM * the server cannot be deleted until smb_thread_stop()/destroy() return, 12397619SJose.Borrego@Sun.COM * which is also when the thread exits. 12407619SJose.Borrego@Sun.COM */ 12417619SJose.Borrego@Sun.COM 12427619SJose.Borrego@Sun.COM static void 12437619SJose.Borrego@Sun.COM smb_server_thread_unexport(smb_thread_t *thread, void *arg) 12447619SJose.Borrego@Sun.COM { 1245*11963SAfshin.Ardakani@Sun.COM smb_server_t *sv = (smb_server_t *)arg; 1246*11963SAfshin.Ardakani@Sun.COM smb_unexport_t *ux; 1247*11963SAfshin.Ardakani@Sun.COM smb_session_list_t *slist; 12487619SJose.Borrego@Sun.COM 12497619SJose.Borrego@Sun.COM while (smb_thread_continue(thread)) { 12507619SJose.Borrego@Sun.COM while ((ux = list_head(&sv->sv_unexport_list.sl_list)) 12517619SJose.Borrego@Sun.COM != NULL) { 12527619SJose.Borrego@Sun.COM smb_slist_remove(&sv->sv_unexport_list, ux); 1253*11963SAfshin.Ardakani@Sun.COM 1254*11963SAfshin.Ardakani@Sun.COM slist = &sv->sv_nbt_daemon.ld_session_list; 1255*11963SAfshin.Ardakani@Sun.COM smb_server_disconnect_share(slist, ux->ux_sharename); 1256*11963SAfshin.Ardakani@Sun.COM 1257*11963SAfshin.Ardakani@Sun.COM slist = &sv->sv_tcp_daemon.ld_session_list; 1258*11963SAfshin.Ardakani@Sun.COM smb_server_disconnect_share(slist, ux->ux_sharename); 1259*11963SAfshin.Ardakani@Sun.COM 12607619SJose.Borrego@Sun.COM kmem_cache_free(sv->si_cache_unexport, ux); 12617619SJose.Borrego@Sun.COM } 12627619SJose.Borrego@Sun.COM } 12637619SJose.Borrego@Sun.COM } 12647619SJose.Borrego@Sun.COM 12657619SJose.Borrego@Sun.COM /* 12666139Sjb150015 * This is a special interface that will be utilized by ZFS to cause a share to 12676139Sjb150015 * be added/removed. 12686139Sjb150015 * 12696139Sjb150015 * arg is either a lmshare_info_t or share_name from userspace. 12706139Sjb150015 * It will need to be copied into the kernel. It is lmshare_info_t 12716139Sjb150015 * for add operations and share_name for delete operations. 12726139Sjb150015 */ 12736139Sjb150015 int 12746139Sjb150015 smb_server_share(void *arg, boolean_t add_share) 12756139Sjb150015 { 12766139Sjb150015 smb_server_t *sv; 12776139Sjb150015 int rc; 12786139Sjb150015 12796139Sjb150015 rc = smb_server_lookup(&sv); 12806139Sjb150015 if (rc == 0) { 12816139Sjb150015 mutex_enter(&sv->sv_mutex); 12829832Samw@Sun.COM switch (sv->sv_state) { 12839832Samw@Sun.COM case SMB_SERVER_STATE_RUNNING: 12846139Sjb150015 mutex_exit(&sv->sv_mutex); 12859832Samw@Sun.COM (void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share); 12869832Samw@Sun.COM break; 12879832Samw@Sun.COM default: 12886139Sjb150015 mutex_exit(&sv->sv_mutex); 12899832Samw@Sun.COM break; 12906139Sjb150015 } 12916139Sjb150015 smb_server_release(sv); 12926139Sjb150015 } 12939832Samw@Sun.COM return (0); 12946139Sjb150015 } 12956139Sjb150015 12966139Sjb150015 /* 12976139Sjb150015 * ***************************************************************************** 12986139Sjb150015 * **************** Functions called from the internal layers ****************** 12996139Sjb150015 * ***************************************************************************** 13006139Sjb150015 * 13016139Sjb150015 * These functions are provided the relevant smb server by the caller. 13026139Sjb150015 */ 13036139Sjb150015 13046139Sjb150015 void 13056139Sjb150015 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session) 13066139Sjb150015 { 13076139Sjb150015 ASSERT(sv == session->s_server); 13086139Sjb150015 13096139Sjb150015 smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list, 13106139Sjb150015 session); 13116139Sjb150015 smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list, 13126139Sjb150015 session); 13136139Sjb150015 } 13146139Sjb150015 13156139Sjb150015 void 13166139Sjb150015 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 13176139Sjb150015 { 13186139Sjb150015 rw_enter(&sv->sv_cfg_lock, RW_READER); 13196139Sjb150015 bcopy(&sv->sv_cfg, cfg, sizeof (*cfg)); 13206139Sjb150015 rw_exit(&sv->sv_cfg_lock); 13216139Sjb150015 } 13226139Sjb150015 13236139Sjb150015 /* 13246139Sjb150015 * ***************************************************************************** 13256139Sjb150015 * *************************** Static Functions ******************************** 13266139Sjb150015 * ***************************************************************************** 13276139Sjb150015 */ 13286139Sjb150015 13296139Sjb150015 static void 13306139Sjb150015 smb_server_timers(smb_thread_t *thread, void *arg) 13316139Sjb150015 { 13326139Sjb150015 smb_server_t *sv = (smb_server_t *)arg; 13336139Sjb150015 13346139Sjb150015 ASSERT(sv != NULL); 13356139Sjb150015 13366139Sjb150015 while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) { 13376139Sjb150015 smb_session_timers(&sv->sv_nbt_daemon.ld_session_list); 13386139Sjb150015 smb_session_timers(&sv->sv_tcp_daemon.ld_session_list); 13396139Sjb150015 } 13406139Sjb150015 } 13416139Sjb150015 13426139Sjb150015 /* 13436139Sjb150015 * smb_server_kstat_init 13446139Sjb150015 */ 13456139Sjb150015 static int 13466139Sjb150015 smb_server_kstat_init(smb_server_t *sv) 13476139Sjb150015 { 13486432Sas200622 (void) snprintf(sv->sv_ksp_name, sizeof (sv->sv_ksp_name), "%s%d", 13496432Sas200622 SMBSRV_KSTAT_NAME, sv->sv_zid); 13506139Sjb150015 13516432Sas200622 sv->sv_ksp = kstat_create(SMBSRV_KSTAT_MODULE, 0, sv->sv_ksp_name, 13526432Sas200622 SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED, 13536432Sas200622 sizeof (sv->sv_ks_data) / sizeof (kstat_named_t), 13546139Sjb150015 KSTAT_FLAG_VIRTUAL); 13556139Sjb150015 13566139Sjb150015 if (sv->sv_ksp) { 13576139Sjb150015 (void) strlcpy(sv->sv_ks_data.open_files.name, "open_files", 13586139Sjb150015 sizeof (sv->sv_ks_data.open_files.name)); 13596139Sjb150015 sv->sv_ks_data.open_files.data_type = KSTAT_DATA_UINT32; 13606139Sjb150015 (void) strlcpy(sv->sv_ks_data.open_trees.name, "connections", 13616139Sjb150015 sizeof (sv->sv_ks_data.open_trees.name)); 13626139Sjb150015 sv->sv_ks_data.open_trees.data_type = KSTAT_DATA_UINT32; 13636139Sjb150015 (void) strlcpy(sv->sv_ks_data.open_users.name, "sessions", 13646139Sjb150015 sizeof (sv->sv_ks_data.open_users.name)); 13656139Sjb150015 sv->sv_ks_data.open_users.data_type = KSTAT_DATA_UINT32; 13666139Sjb150015 13676139Sjb150015 mutex_init(&sv->sv_ksp_mutex, NULL, MUTEX_DEFAULT, NULL); 13686139Sjb150015 sv->sv_ksp->ks_lock = &sv->sv_ksp_mutex; 13696139Sjb150015 sv->sv_ksp->ks_data = (void *)&sv->sv_ks_data; 13706139Sjb150015 sv->sv_ksp->ks_update = smb_server_kstat_update_info; 13716139Sjb150015 kstat_install(sv->sv_ksp); 13726139Sjb150015 } 13736139Sjb150015 13746139Sjb150015 /* create and initialize smb kstats - smb_dispatch stats */ 13756139Sjb150015 smb_dispatch_kstat_init(); 13766139Sjb150015 13776139Sjb150015 return (0); 13786139Sjb150015 } 13796139Sjb150015 13806139Sjb150015 /* 13816139Sjb150015 * smb_server_kstat_fini 13826139Sjb150015 */ 13836139Sjb150015 static void 13846139Sjb150015 smb_server_kstat_fini(smb_server_t *sv) 13856139Sjb150015 { 13866139Sjb150015 if (sv->sv_ksp) { 13876139Sjb150015 kstat_delete(sv->sv_ksp); 13886139Sjb150015 mutex_destroy(&sv->sv_ksp_mutex); 13896139Sjb150015 sv->sv_ksp = NULL; 13906139Sjb150015 } 13916139Sjb150015 smb_dispatch_kstat_fini(); 13926139Sjb150015 } 13936139Sjb150015 13946139Sjb150015 /* ARGSUSED */ 13956139Sjb150015 static int 13966139Sjb150015 smb_server_kstat_update_info(kstat_t *ksp, int rw) 13976139Sjb150015 { 13986139Sjb150015 smb_server_t *sv; 13996139Sjb150015 14006139Sjb150015 if (rw == KSTAT_WRITE) { 14016139Sjb150015 return (EACCES); 14026139Sjb150015 } else { 14036139Sjb150015 ASSERT(MUTEX_HELD(ksp->ks_lock)); 14046139Sjb150015 14056139Sjb150015 _NOTE(LINTED("pointer cast may result in improper alignment")) 14066139Sjb150015 sv = (smb_server_t *)((uint8_t *)(ksp->ks_data) - 14076139Sjb150015 offsetof(smb_server_t, sv_ks_data)); 14086139Sjb150015 1409*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 14106139Sjb150015 14116139Sjb150015 sv->sv_ks_data.open_files.value.ui32 = sv->sv_open_files; 14126139Sjb150015 sv->sv_ks_data.open_trees.value.ui32 = sv->sv_open_trees; 14136139Sjb150015 sv->sv_ks_data.open_users.value.ui32 = sv->sv_open_users; 14146139Sjb150015 } 14156139Sjb150015 return (0); 14166139Sjb150015 } 14176139Sjb150015 14186139Sjb150015 /* 14196139Sjb150015 * The mutex of the server must have been entered before calling this function. 14206139Sjb150015 */ 14216139Sjb150015 static void 1422*11963SAfshin.Ardakani@Sun.COM smb_server_shutdown(smb_server_t *sv) 14236139Sjb150015 { 1424*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 14256139Sjb150015 14267052Samw smb_opipe_door_close(); 14276139Sjb150015 smb_thread_stop(&sv->si_thread_timers); 14287619SJose.Borrego@Sun.COM smb_thread_stop(&sv->si_thread_unexport); 1429*11963SAfshin.Ardakani@Sun.COM smb_kdoor_close(); 14306771Sjb150015 smb_kshare_fini(sv->sv_lmshrd); 14316849Sjb150015 sv->sv_lmshrd = NULL; 14326139Sjb150015 smb_server_fsop_stop(sv); 14337588Samw@Sun.COM 14346139Sjb150015 if (sv->sv_session) { 14356139Sjb150015 smb_session_delete(sv->sv_session); 14366139Sjb150015 sv->sv_session = NULL; 14376139Sjb150015 } 14387588Samw@Sun.COM 14397588Samw@Sun.COM if (sv->sv_thread_pool) { 14407588Samw@Sun.COM taskq_destroy(sv->sv_thread_pool); 14417588Samw@Sun.COM sv->sv_thread_pool = NULL; 14427588Samw@Sun.COM } 14436139Sjb150015 } 14446139Sjb150015 14456139Sjb150015 static int 14466139Sjb150015 smb_server_listen( 14476139Sjb150015 smb_server_t *sv, 14486139Sjb150015 smb_listener_daemon_t *ld, 14496139Sjb150015 in_port_t port, 14508670SJose.Borrego@Sun.COM int family, 14516139Sjb150015 int pthread_create_error) 14526139Sjb150015 { 1453*11963SAfshin.Ardakani@Sun.COM int rc = 0; 14548348SEric.Yu@Sun.COM ksocket_t s_so; 1455*11963SAfshin.Ardakani@Sun.COM uint32_t on; 1456*11963SAfshin.Ardakani@Sun.COM uint32_t off; 1457*11963SAfshin.Ardakani@Sun.COM uint32_t txbuf_size; 14586139Sjb150015 smb_session_t *session; 14596139Sjb150015 14606139Sjb150015 if (pthread_create_error) { 14616139Sjb150015 /* 14626139Sjb150015 * Delete the last session created. The user space thread 14636139Sjb150015 * creation failed. 14646139Sjb150015 */ 14656139Sjb150015 smb_session_list_delete_tail(&ld->ld_session_list); 14666139Sjb150015 } 14676139Sjb150015 14686139Sjb150015 if (ld->ld_so == NULL) { 14696139Sjb150015 /* First time listener */ 14708670SJose.Borrego@Sun.COM if (family == AF_INET) { 14718670SJose.Borrego@Sun.COM ld->ld_sin.sin_family = (uint32_t)family; 14728670SJose.Borrego@Sun.COM ld->ld_sin.sin_port = htons(port); 14738670SJose.Borrego@Sun.COM ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY); 14748670SJose.Borrego@Sun.COM } else { 14758670SJose.Borrego@Sun.COM ld->ld_sin6.sin6_family = (uint32_t)family; 14768670SJose.Borrego@Sun.COM ld->ld_sin6.sin6_port = htons(port); 14778670SJose.Borrego@Sun.COM (void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0, 14788670SJose.Borrego@Sun.COM sizeof (ld->ld_sin6.sin6_addr.s6_addr)); 14798670SJose.Borrego@Sun.COM } 1480*11963SAfshin.Ardakani@Sun.COM 14818670SJose.Borrego@Sun.COM ld->ld_so = smb_socreate(family, SOCK_STREAM, 0); 1482*11963SAfshin.Ardakani@Sun.COM if (ld->ld_so == NULL) { 1483*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "port %d: socket create failed", port); 1484*11963SAfshin.Ardakani@Sun.COM return (ENOMEM); 1485*11963SAfshin.Ardakani@Sun.COM } 14866139Sjb150015 1487*11963SAfshin.Ardakani@Sun.COM off = 0; 1488*11963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 1489*11963SAfshin.Ardakani@Sun.COM SO_MAC_EXEMPT, &off, sizeof (off), CRED()); 1490*11963SAfshin.Ardakani@Sun.COM 1491*11963SAfshin.Ardakani@Sun.COM on = 1; 1492*11963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 1493*11963SAfshin.Ardakani@Sun.COM SO_REUSEADDR, &on, sizeof (on), CRED()); 14949021Samw@Sun.COM 1495*11963SAfshin.Ardakani@Sun.COM if (family == AF_INET) { 1496*11963SAfshin.Ardakani@Sun.COM rc = ksocket_bind(ld->ld_so, 1497*11963SAfshin.Ardakani@Sun.COM (struct sockaddr *)&ld->ld_sin, 1498*11963SAfshin.Ardakani@Sun.COM sizeof (ld->ld_sin), CRED()); 14996139Sjb150015 } else { 1500*11963SAfshin.Ardakani@Sun.COM rc = ksocket_bind(ld->ld_so, 1501*11963SAfshin.Ardakani@Sun.COM (struct sockaddr *)&ld->ld_sin6, 1502*11963SAfshin.Ardakani@Sun.COM sizeof (ld->ld_sin6), CRED()); 1503*11963SAfshin.Ardakani@Sun.COM } 1504*11963SAfshin.Ardakani@Sun.COM 1505*11963SAfshin.Ardakani@Sun.COM if (rc != 0) { 1506*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "port %d: bind failed (%d)", port, rc); 1507*11963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(ld); 1508*11963SAfshin.Ardakani@Sun.COM return (rc); 1509*11963SAfshin.Ardakani@Sun.COM } 1510*11963SAfshin.Ardakani@Sun.COM 1511*11963SAfshin.Ardakani@Sun.COM rc = ksocket_listen(ld->ld_so, 20, CRED()); 1512*11963SAfshin.Ardakani@Sun.COM if (rc < 0) { 1513*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "port %d: listen failed", port); 1514*11963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(ld); 1515*11963SAfshin.Ardakani@Sun.COM return (rc); 15166139Sjb150015 } 15176139Sjb150015 } 15186139Sjb150015 15196139Sjb150015 DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so); 15206139Sjb150015 15216139Sjb150015 for (;;) { 1522*11963SAfshin.Ardakani@Sun.COM if (smb_server_is_stopping()) { 1523*11963SAfshin.Ardakani@Sun.COM rc = ECANCELED; 1524*11963SAfshin.Ardakani@Sun.COM break; 1525*11963SAfshin.Ardakani@Sun.COM } 1526*11963SAfshin.Ardakani@Sun.COM 15278348SEric.Yu@Sun.COM rc = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED()); 1528*11963SAfshin.Ardakani@Sun.COM if (rc != 0) 1529*11963SAfshin.Ardakani@Sun.COM break; 1530*11963SAfshin.Ardakani@Sun.COM 1531*11963SAfshin.Ardakani@Sun.COM if (smb_server_is_stopping()) { 1532*11963SAfshin.Ardakani@Sun.COM smb_soshutdown(s_so); 1533*11963SAfshin.Ardakani@Sun.COM smb_sodestroy(s_so); 1534*11963SAfshin.Ardakani@Sun.COM rc = ECANCELED; 1535*11963SAfshin.Ardakani@Sun.COM break; 1536*11963SAfshin.Ardakani@Sun.COM } 15376139Sjb150015 1538*11963SAfshin.Ardakani@Sun.COM DTRACE_PROBE1(so__accept, struct sonode *, s_so); 1539*11963SAfshin.Ardakani@Sun.COM 1540*11963SAfshin.Ardakani@Sun.COM on = 1; 1541*11963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY, 1542*11963SAfshin.Ardakani@Sun.COM &on, sizeof (on), CRED()); 1543*11963SAfshin.Ardakani@Sun.COM 1544*11963SAfshin.Ardakani@Sun.COM on = 1; 1545*11963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE, 1546*11963SAfshin.Ardakani@Sun.COM &on, sizeof (on), CRED()); 15476139Sjb150015 1548*11963SAfshin.Ardakani@Sun.COM txbuf_size = 128*1024; 1549*11963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF, 1550*11963SAfshin.Ardakani@Sun.COM (const void *)&txbuf_size, sizeof (txbuf_size), CRED()); 1551*11963SAfshin.Ardakani@Sun.COM 1552*11963SAfshin.Ardakani@Sun.COM /* 1553*11963SAfshin.Ardakani@Sun.COM * Create a session for this connection. 1554*11963SAfshin.Ardakani@Sun.COM */ 1555*11963SAfshin.Ardakani@Sun.COM session = smb_session_create(s_so, port, sv, family); 1556*11963SAfshin.Ardakani@Sun.COM if (session) { 1557*11963SAfshin.Ardakani@Sun.COM smb_session_list_append(&ld->ld_session_list, session); 1558*11963SAfshin.Ardakani@Sun.COM rc = 0; 1559*11963SAfshin.Ardakani@Sun.COM break; 1560*11963SAfshin.Ardakani@Sun.COM } else { 1561*11963SAfshin.Ardakani@Sun.COM smb_soshutdown(s_so); 1562*11963SAfshin.Ardakani@Sun.COM smb_sodestroy(s_so); 15636139Sjb150015 } 1564*11963SAfshin.Ardakani@Sun.COM } 1565*11963SAfshin.Ardakani@Sun.COM 1566*11963SAfshin.Ardakani@Sun.COM if (rc != 0) 1567*11963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(ld); 1568*11963SAfshin.Ardakani@Sun.COM 1569*11963SAfshin.Ardakani@Sun.COM return (rc); 1570*11963SAfshin.Ardakani@Sun.COM } 1571*11963SAfshin.Ardakani@Sun.COM 1572*11963SAfshin.Ardakani@Sun.COM static void 1573*11963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(smb_listener_daemon_t *ld) 1574*11963SAfshin.Ardakani@Sun.COM { 1575*11963SAfshin.Ardakani@Sun.COM if (ld->ld_so != NULL) { 15766139Sjb150015 smb_session_list_signal(&ld->ld_session_list); 15776139Sjb150015 smb_soshutdown(ld->ld_so); 15786139Sjb150015 smb_sodestroy(ld->ld_so); 15796139Sjb150015 ld->ld_so = NULL; 1580*11963SAfshin.Ardakani@Sun.COM } 1581*11963SAfshin.Ardakani@Sun.COM } 1582*11963SAfshin.Ardakani@Sun.COM 1583*11963SAfshin.Ardakani@Sun.COM static kt_did_t 1584*11963SAfshin.Ardakani@Sun.COM smb_server_listener_tid(smb_listener_daemon_t *ld) 1585*11963SAfshin.Ardakani@Sun.COM { 1586*11963SAfshin.Ardakani@Sun.COM kt_did_t tid; 1587*11963SAfshin.Ardakani@Sun.COM 1588*11963SAfshin.Ardakani@Sun.COM if (ld->ld_ktdid != 0) { 1589*11963SAfshin.Ardakani@Sun.COM tid = ld->ld_ktdid; 1590*11963SAfshin.Ardakani@Sun.COM ld->ld_ktdid = 0; 15916139Sjb150015 } 15926139Sjb150015 1593*11963SAfshin.Ardakani@Sun.COM return (tid); 15946139Sjb150015 } 15956139Sjb150015 15966139Sjb150015 /* 15976139Sjb150015 * smb_server_lookup 15986139Sjb150015 * 15996139Sjb150015 * This function tries to find the server associated with the zone of the 16006139Sjb150015 * caller. 16016139Sjb150015 */ 16026139Sjb150015 static int 16036139Sjb150015 smb_server_lookup(smb_server_t **psv) 16046139Sjb150015 { 16056139Sjb150015 zoneid_t zid; 16066139Sjb150015 smb_server_t *sv; 16076139Sjb150015 16086139Sjb150015 zid = getzoneid(); 16096139Sjb150015 16106139Sjb150015 smb_llist_enter(&smb_servers, RW_READER); 16116139Sjb150015 sv = smb_llist_head(&smb_servers); 16126139Sjb150015 while (sv) { 1613*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 16146139Sjb150015 if (sv->sv_zid == zid) { 16156139Sjb150015 mutex_enter(&sv->sv_mutex); 16166139Sjb150015 if (sv->sv_state != SMB_SERVER_STATE_DELETING) { 16176139Sjb150015 sv->sv_refcnt++; 16186139Sjb150015 mutex_exit(&sv->sv_mutex); 16196139Sjb150015 smb_llist_exit(&smb_servers); 16206139Sjb150015 *psv = sv; 16216139Sjb150015 return (0); 16226139Sjb150015 } 16236139Sjb150015 mutex_exit(&sv->sv_mutex); 16246139Sjb150015 break; 16256139Sjb150015 } 16266139Sjb150015 sv = smb_llist_next(&smb_servers, sv); 16276139Sjb150015 } 16286139Sjb150015 smb_llist_exit(&smb_servers); 16296139Sjb150015 return (EPERM); 16306139Sjb150015 } 16316139Sjb150015 16326139Sjb150015 /* 16336139Sjb150015 * smb_server_release 16346139Sjb150015 * 16356139Sjb150015 * This function decrements the reference count of the server and signals its 16366139Sjb150015 * condition variable if the state of the server is SMB_SERVER_STATE_DELETING. 16376139Sjb150015 */ 16386139Sjb150015 static void 16396139Sjb150015 smb_server_release(smb_server_t *sv) 16406139Sjb150015 { 1641*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 16426139Sjb150015 16436139Sjb150015 mutex_enter(&sv->sv_mutex); 16446139Sjb150015 ASSERT(sv->sv_refcnt); 16456139Sjb150015 sv->sv_refcnt--; 16466139Sjb150015 if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING)) 16476139Sjb150015 cv_signal(&sv->sv_cv); 16486139Sjb150015 mutex_exit(&sv->sv_mutex); 16496139Sjb150015 } 16506139Sjb150015 165110122SJordan.Brown@Sun.COM /* 165210122SJordan.Brown@Sun.COM * Enumerate the users associated with a session list. 165310122SJordan.Brown@Sun.COM */ 165410122SJordan.Brown@Sun.COM static void 165510122SJordan.Brown@Sun.COM smb_server_enum_private(smb_session_list_t *se, smb_svcenum_t *svcenum) 16566139Sjb150015 { 165710122SJordan.Brown@Sun.COM smb_session_t *sn; 165810122SJordan.Brown@Sun.COM smb_llist_t *ulist; 165910122SJordan.Brown@Sun.COM smb_user_t *user; 166010122SJordan.Brown@Sun.COM int rc = 0; 16616139Sjb150015 16626139Sjb150015 rw_enter(&se->se_lock, RW_READER); 16636139Sjb150015 sn = list_head(&se->se_act.lst); 166410122SJordan.Brown@Sun.COM 166510122SJordan.Brown@Sun.COM while (sn != NULL) { 16666139Sjb150015 ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 16676139Sjb150015 ulist = &sn->s_user_list; 16686139Sjb150015 smb_llist_enter(ulist, RW_READER); 16696139Sjb150015 user = smb_llist_head(ulist); 167010122SJordan.Brown@Sun.COM 167110122SJordan.Brown@Sun.COM while (user != NULL) { 167210122SJordan.Brown@Sun.COM if (smb_user_hold(user)) { 167310122SJordan.Brown@Sun.COM rc = smb_user_enum(user, svcenum); 167410122SJordan.Brown@Sun.COM smb_user_release(user); 167510122SJordan.Brown@Sun.COM } 167610122SJordan.Brown@Sun.COM 167710122SJordan.Brown@Sun.COM user = smb_llist_next(ulist, user); 167810122SJordan.Brown@Sun.COM } 167910122SJordan.Brown@Sun.COM 168010122SJordan.Brown@Sun.COM smb_llist_exit(ulist); 168110122SJordan.Brown@Sun.COM 168210122SJordan.Brown@Sun.COM if (rc != 0) 168310122SJordan.Brown@Sun.COM break; 168410122SJordan.Brown@Sun.COM 168510122SJordan.Brown@Sun.COM sn = list_next(&se->se_act.lst, sn); 168610122SJordan.Brown@Sun.COM } 168710122SJordan.Brown@Sun.COM 168810122SJordan.Brown@Sun.COM rw_exit(&se->se_lock); 168910122SJordan.Brown@Sun.COM } 169010122SJordan.Brown@Sun.COM 169110122SJordan.Brown@Sun.COM /* 169210122SJordan.Brown@Sun.COM * Disconnect sessions associated with the specified client and username. 169310122SJordan.Brown@Sun.COM * Empty strings are treated as wildcards. 169410122SJordan.Brown@Sun.COM */ 169510122SJordan.Brown@Sun.COM static int 169610122SJordan.Brown@Sun.COM smb_server_sesion_disconnect(smb_session_list_t *se, 169710122SJordan.Brown@Sun.COM const char *client, const char *name) 169810122SJordan.Brown@Sun.COM { 169910122SJordan.Brown@Sun.COM smb_session_t *sn; 170010122SJordan.Brown@Sun.COM smb_llist_t *ulist; 170110122SJordan.Brown@Sun.COM smb_user_t *user; 170210122SJordan.Brown@Sun.COM boolean_t match; 170310122SJordan.Brown@Sun.COM int count = 0; 170410122SJordan.Brown@Sun.COM 170510122SJordan.Brown@Sun.COM rw_enter(&se->se_lock, RW_READER); 170610122SJordan.Brown@Sun.COM sn = list_head(&se->se_act.lst); 170710122SJordan.Brown@Sun.COM 170810122SJordan.Brown@Sun.COM while (sn != NULL) { 170910122SJordan.Brown@Sun.COM ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 171010122SJordan.Brown@Sun.COM 171110122SJordan.Brown@Sun.COM if ((*client != '\0') && (!smb_session_isclient(sn, client))) { 171210122SJordan.Brown@Sun.COM sn = list_next(&se->se_act.lst, sn); 171310122SJordan.Brown@Sun.COM continue; 171410122SJordan.Brown@Sun.COM } 171510122SJordan.Brown@Sun.COM 171610122SJordan.Brown@Sun.COM ulist = &sn->s_user_list; 171710122SJordan.Brown@Sun.COM smb_llist_enter(ulist, RW_READER); 171810122SJordan.Brown@Sun.COM user = smb_llist_head(ulist); 171910122SJordan.Brown@Sun.COM 172010122SJordan.Brown@Sun.COM while (user != NULL) { 172110122SJordan.Brown@Sun.COM if (smb_user_hold(user)) { 172210122SJordan.Brown@Sun.COM match = (*name == '\0'); 172310122SJordan.Brown@Sun.COM if (!match) 172410122SJordan.Brown@Sun.COM match = smb_user_namecmp(user, name); 172510122SJordan.Brown@Sun.COM 172610122SJordan.Brown@Sun.COM if (match) { 172710122SJordan.Brown@Sun.COM smb_llist_exit(ulist); 172810122SJordan.Brown@Sun.COM smb_user_logoff(user); 172910122SJordan.Brown@Sun.COM ++count; 173010122SJordan.Brown@Sun.COM smb_user_release(user); 173110122SJordan.Brown@Sun.COM smb_llist_enter(ulist, RW_READER); 173210122SJordan.Brown@Sun.COM user = smb_llist_head(ulist); 173310122SJordan.Brown@Sun.COM continue; 17346139Sjb150015 } 173510122SJordan.Brown@Sun.COM 173610122SJordan.Brown@Sun.COM smb_user_release(user); 17376139Sjb150015 } 173810122SJordan.Brown@Sun.COM 17396139Sjb150015 user = smb_llist_next(ulist, user); 17406139Sjb150015 } 174110122SJordan.Brown@Sun.COM 17426139Sjb150015 smb_llist_exit(ulist); 17437961SNatalie.Li@Sun.COM sn = list_next(&se->se_act.lst, sn); 17446139Sjb150015 } 174510122SJordan.Brown@Sun.COM 17466139Sjb150015 rw_exit(&se->se_lock); 174710122SJordan.Brown@Sun.COM return (count); 174810122SJordan.Brown@Sun.COM } 174910122SJordan.Brown@Sun.COM 175010122SJordan.Brown@Sun.COM /* 175110122SJordan.Brown@Sun.COM * Close a file by its unique id. 175210122SJordan.Brown@Sun.COM */ 175310122SJordan.Brown@Sun.COM static int 175410122SJordan.Brown@Sun.COM smb_server_fclose(smb_session_list_t *se, uint32_t uniqid) 175510122SJordan.Brown@Sun.COM { 175610122SJordan.Brown@Sun.COM smb_session_t *sn; 175710122SJordan.Brown@Sun.COM smb_llist_t *ulist; 175810122SJordan.Brown@Sun.COM smb_user_t *user; 175910122SJordan.Brown@Sun.COM int rc = ENOENT; 176010122SJordan.Brown@Sun.COM 176110122SJordan.Brown@Sun.COM rw_enter(&se->se_lock, RW_READER); 176210122SJordan.Brown@Sun.COM sn = list_head(&se->se_act.lst); 176310122SJordan.Brown@Sun.COM 176410122SJordan.Brown@Sun.COM while ((sn != NULL) && (rc == ENOENT)) { 176510122SJordan.Brown@Sun.COM ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 176610122SJordan.Brown@Sun.COM ulist = &sn->s_user_list; 176710122SJordan.Brown@Sun.COM smb_llist_enter(ulist, RW_READER); 176810122SJordan.Brown@Sun.COM user = smb_llist_head(ulist); 176910122SJordan.Brown@Sun.COM 177010122SJordan.Brown@Sun.COM while ((user != NULL) && (rc == ENOENT)) { 177110122SJordan.Brown@Sun.COM if (smb_user_hold(user)) { 177210122SJordan.Brown@Sun.COM rc = smb_user_fclose(user, uniqid); 177310122SJordan.Brown@Sun.COM smb_user_release(user); 177410122SJordan.Brown@Sun.COM } 177510122SJordan.Brown@Sun.COM 177610122SJordan.Brown@Sun.COM user = smb_llist_next(ulist, user); 177710122SJordan.Brown@Sun.COM } 177810122SJordan.Brown@Sun.COM 177910122SJordan.Brown@Sun.COM smb_llist_exit(ulist); 178010122SJordan.Brown@Sun.COM sn = list_next(&se->se_act.lst, sn); 178110122SJordan.Brown@Sun.COM } 178210122SJordan.Brown@Sun.COM 178310122SJordan.Brown@Sun.COM rw_exit(&se->se_lock); 178410122SJordan.Brown@Sun.COM return (rc); 17856139Sjb150015 } 17866139Sjb150015 17876139Sjb150015 static void 17889832Samw@Sun.COM smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc) 17896139Sjb150015 { 17909832Samw@Sun.COM if (ioc->maxconnections == 0) 17919832Samw@Sun.COM ioc->maxconnections = 0xFFFFFFFF; 17926139Sjb150015 17936139Sjb150015 smb_session_correct_keep_alive_values( 17949832Samw@Sun.COM &sv->sv_nbt_daemon.ld_session_list, ioc->keepalive); 17956139Sjb150015 smb_session_correct_keep_alive_values( 17969832Samw@Sun.COM &sv->sv_tcp_daemon.ld_session_list, ioc->keepalive); 17976139Sjb150015 17989832Samw@Sun.COM sv->sv_cfg.skc_maxworkers = ioc->maxworkers; 17999832Samw@Sun.COM sv->sv_cfg.skc_maxconnections = ioc->maxconnections; 18009832Samw@Sun.COM sv->sv_cfg.skc_keepalive = ioc->keepalive; 18019832Samw@Sun.COM sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon; 18029832Samw@Sun.COM sv->sv_cfg.skc_signing_enable = ioc->signing_enable; 18039832Samw@Sun.COM sv->sv_cfg.skc_signing_required = ioc->signing_required; 18049832Samw@Sun.COM sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable; 18059832Samw@Sun.COM sv->sv_cfg.skc_sync_enable = ioc->sync_enable; 18069832Samw@Sun.COM sv->sv_cfg.skc_secmode = ioc->secmode; 18079832Samw@Sun.COM sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable; 18089832Samw@Sun.COM (void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain, 18099832Samw@Sun.COM sizeof (sv->sv_cfg.skc_nbdomain)); 18109832Samw@Sun.COM (void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn, 18119832Samw@Sun.COM sizeof (sv->sv_cfg.skc_fqdn)); 18129832Samw@Sun.COM (void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname, 18139832Samw@Sun.COM sizeof (sv->sv_cfg.skc_hostname)); 18149832Samw@Sun.COM (void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment, 18159832Samw@Sun.COM sizeof (sv->sv_cfg.skc_system_comment)); 18166139Sjb150015 } 18176139Sjb150015 18186139Sjb150015 static int 18196139Sjb150015 smb_server_fsop_start(smb_server_t *sv) 18206139Sjb150015 { 18216139Sjb150015 int error; 18226139Sjb150015 18236139Sjb150015 error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node); 18246139Sjb150015 if (error != 0) 18256139Sjb150015 sv->si_root_smb_node = NULL; 18266139Sjb150015 18276139Sjb150015 return (error); 18286139Sjb150015 } 18296139Sjb150015 18306139Sjb150015 static void 18316139Sjb150015 smb_server_fsop_stop(smb_server_t *sv) 18326139Sjb150015 { 18336139Sjb150015 if (sv->si_root_smb_node != NULL) { 18346139Sjb150015 smb_vfs_rele_all(sv); 18356139Sjb150015 smb_node_release(sv->si_root_smb_node); 18366139Sjb150015 sv->si_root_smb_node = NULL; 18376139Sjb150015 } 18386139Sjb150015 } 1839*11963SAfshin.Ardakani@Sun.COM 1840*11963SAfshin.Ardakani@Sun.COM static void 1841*11963SAfshin.Ardakani@Sun.COM smb_server_signal_listeners(smb_server_t *sv) 1842*11963SAfshin.Ardakani@Sun.COM { 1843*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 1844*11963SAfshin.Ardakani@Sun.COM ASSERT(sv->sv_state == SMB_SERVER_STATE_STOPPING); 1845*11963SAfshin.Ardakani@Sun.COM ASSERT(MUTEX_HELD(&sv->sv_mutex)); 1846*11963SAfshin.Ardakani@Sun.COM 1847*11963SAfshin.Ardakani@Sun.COM smb_event_cancel(sv, 0); 1848*11963SAfshin.Ardakani@Sun.COM 1849*11963SAfshin.Ardakani@Sun.COM if (sv->sv_nbt_daemon.ld_kth != NULL) { 1850*11963SAfshin.Ardakani@Sun.COM tsignal(sv->sv_nbt_daemon.ld_kth, SIGINT); 1851*11963SAfshin.Ardakani@Sun.COM sv->sv_nbt_daemon.ld_kth = NULL; 1852*11963SAfshin.Ardakani@Sun.COM } 1853*11963SAfshin.Ardakani@Sun.COM 1854*11963SAfshin.Ardakani@Sun.COM if (sv->sv_tcp_daemon.ld_kth != NULL) { 1855*11963SAfshin.Ardakani@Sun.COM tsignal(sv->sv_tcp_daemon.ld_kth, SIGINT); 1856*11963SAfshin.Ardakani@Sun.COM sv->sv_tcp_daemon.ld_kth = NULL; 1857*11963SAfshin.Ardakani@Sun.COM } 1858*11963SAfshin.Ardakani@Sun.COM } 1859*11963SAfshin.Ardakani@Sun.COM 1860*11963SAfshin.Ardakani@Sun.COM smb_event_t * 1861*11963SAfshin.Ardakani@Sun.COM smb_event_create(void) 1862*11963SAfshin.Ardakani@Sun.COM { 1863*11963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 1864*11963SAfshin.Ardakani@Sun.COM smb_event_t *event; 1865*11963SAfshin.Ardakani@Sun.COM 1866*11963SAfshin.Ardakani@Sun.COM if (smb_server_is_stopping()) 1867*11963SAfshin.Ardakani@Sun.COM return (NULL); 1868*11963SAfshin.Ardakani@Sun.COM 1869*11963SAfshin.Ardakani@Sun.COM if (smb_server_lookup(&sv) != 0) { 1870*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_NOTE, "smb_event_create failed"); 1871*11963SAfshin.Ardakani@Sun.COM return (NULL); 1872*11963SAfshin.Ardakani@Sun.COM } 1873*11963SAfshin.Ardakani@Sun.COM 1874*11963SAfshin.Ardakani@Sun.COM event = kmem_cache_alloc(sv->si_cache_event, KM_SLEEP); 1875*11963SAfshin.Ardakani@Sun.COM 1876*11963SAfshin.Ardakani@Sun.COM bzero(event, sizeof (smb_event_t)); 1877*11963SAfshin.Ardakani@Sun.COM mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL); 1878*11963SAfshin.Ardakani@Sun.COM cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL); 1879*11963SAfshin.Ardakani@Sun.COM event->se_magic = SMB_EVENT_MAGIC; 1880*11963SAfshin.Ardakani@Sun.COM event->se_txid = smb_event_alloc_txid(); 1881*11963SAfshin.Ardakani@Sun.COM event->se_server = sv; 1882*11963SAfshin.Ardakani@Sun.COM 1883*11963SAfshin.Ardakani@Sun.COM smb_llist_enter(&sv->sv_event_list, RW_WRITER); 1884*11963SAfshin.Ardakani@Sun.COM smb_llist_insert_tail(&sv->sv_event_list, event); 1885*11963SAfshin.Ardakani@Sun.COM smb_llist_exit(&sv->sv_event_list); 1886*11963SAfshin.Ardakani@Sun.COM 1887*11963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 1888*11963SAfshin.Ardakani@Sun.COM return (event); 1889*11963SAfshin.Ardakani@Sun.COM } 1890*11963SAfshin.Ardakani@Sun.COM 1891*11963SAfshin.Ardakani@Sun.COM void 1892*11963SAfshin.Ardakani@Sun.COM smb_event_destroy(smb_event_t *event) 1893*11963SAfshin.Ardakani@Sun.COM { 1894*11963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 1895*11963SAfshin.Ardakani@Sun.COM 1896*11963SAfshin.Ardakani@Sun.COM if (event == NULL) 1897*11963SAfshin.Ardakani@Sun.COM return; 1898*11963SAfshin.Ardakani@Sun.COM 1899*11963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 1900*11963SAfshin.Ardakani@Sun.COM ASSERT(event->se_waittime == 0); 1901*11963SAfshin.Ardakani@Sun.COM 1902*11963SAfshin.Ardakani@Sun.COM if (smb_server_lookup(&sv) != 0) 1903*11963SAfshin.Ardakani@Sun.COM return; 1904*11963SAfshin.Ardakani@Sun.COM 1905*11963SAfshin.Ardakani@Sun.COM smb_llist_enter(&sv->sv_event_list, RW_WRITER); 1906*11963SAfshin.Ardakani@Sun.COM smb_llist_remove(&sv->sv_event_list, event); 1907*11963SAfshin.Ardakani@Sun.COM smb_llist_exit(&sv->sv_event_list); 1908*11963SAfshin.Ardakani@Sun.COM 1909*11963SAfshin.Ardakani@Sun.COM event->se_magic = (uint32_t)~SMB_EVENT_MAGIC; 1910*11963SAfshin.Ardakani@Sun.COM cv_destroy(&event->se_cv); 1911*11963SAfshin.Ardakani@Sun.COM mutex_destroy(&event->se_mutex); 1912*11963SAfshin.Ardakani@Sun.COM 1913*11963SAfshin.Ardakani@Sun.COM kmem_cache_free(sv->si_cache_event, event); 1914*11963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 1915*11963SAfshin.Ardakani@Sun.COM } 1916*11963SAfshin.Ardakani@Sun.COM 1917*11963SAfshin.Ardakani@Sun.COM /* 1918*11963SAfshin.Ardakani@Sun.COM * Get the txid for the specified event. 1919*11963SAfshin.Ardakani@Sun.COM */ 1920*11963SAfshin.Ardakani@Sun.COM uint32_t 1921*11963SAfshin.Ardakani@Sun.COM smb_event_txid(smb_event_t *event) 1922*11963SAfshin.Ardakani@Sun.COM { 1923*11963SAfshin.Ardakani@Sun.COM if (event != NULL) { 1924*11963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 1925*11963SAfshin.Ardakani@Sun.COM return (event->se_txid); 1926*11963SAfshin.Ardakani@Sun.COM } 1927*11963SAfshin.Ardakani@Sun.COM 1928*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_NOTE, "smb_event_txid failed"); 1929*11963SAfshin.Ardakani@Sun.COM return ((uint32_t)-1); 1930*11963SAfshin.Ardakani@Sun.COM } 1931*11963SAfshin.Ardakani@Sun.COM 1932*11963SAfshin.Ardakani@Sun.COM /* 1933*11963SAfshin.Ardakani@Sun.COM * Wait for event notification. 1934*11963SAfshin.Ardakani@Sun.COM */ 1935*11963SAfshin.Ardakani@Sun.COM int 1936*11963SAfshin.Ardakani@Sun.COM smb_event_wait(smb_event_t *event) 1937*11963SAfshin.Ardakani@Sun.COM { 1938*11963SAfshin.Ardakani@Sun.COM int seconds = 1; 1939*11963SAfshin.Ardakani@Sun.COM int ticks; 1940*11963SAfshin.Ardakani@Sun.COM 1941*11963SAfshin.Ardakani@Sun.COM if (event == NULL) 1942*11963SAfshin.Ardakani@Sun.COM return (EINVAL); 1943*11963SAfshin.Ardakani@Sun.COM 1944*11963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 1945*11963SAfshin.Ardakani@Sun.COM 1946*11963SAfshin.Ardakani@Sun.COM mutex_enter(&event->se_mutex); 1947*11963SAfshin.Ardakani@Sun.COM event->se_waittime = 1; 1948*11963SAfshin.Ardakani@Sun.COM event->se_errno = 0; 1949*11963SAfshin.Ardakani@Sun.COM 1950*11963SAfshin.Ardakani@Sun.COM while (!(event->se_notified)) { 1951*11963SAfshin.Ardakani@Sun.COM if (smb_event_debug && ((event->se_waittime % 10) == 0)) 1952*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)", 1953*11963SAfshin.Ardakani@Sun.COM event->se_txid, event->se_waittime); 1954*11963SAfshin.Ardakani@Sun.COM 1955*11963SAfshin.Ardakani@Sun.COM if (event->se_errno != 0) 1956*11963SAfshin.Ardakani@Sun.COM break; 1957*11963SAfshin.Ardakani@Sun.COM 1958*11963SAfshin.Ardakani@Sun.COM if (event->se_waittime > SMB_EVENT_TIMEOUT) { 1959*11963SAfshin.Ardakani@Sun.COM event->se_errno = ETIME; 1960*11963SAfshin.Ardakani@Sun.COM break; 1961*11963SAfshin.Ardakani@Sun.COM } 1962*11963SAfshin.Ardakani@Sun.COM 1963*11963SAfshin.Ardakani@Sun.COM ticks = SEC_TO_TICK(seconds); 1964*11963SAfshin.Ardakani@Sun.COM (void) cv_reltimedwait(&event->se_cv, 1965*11963SAfshin.Ardakani@Sun.COM &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK); 1966*11963SAfshin.Ardakani@Sun.COM ++event->se_waittime; 1967*11963SAfshin.Ardakani@Sun.COM } 1968*11963SAfshin.Ardakani@Sun.COM 1969*11963SAfshin.Ardakani@Sun.COM event->se_waittime = 0; 1970*11963SAfshin.Ardakani@Sun.COM event->se_notified = B_FALSE; 1971*11963SAfshin.Ardakani@Sun.COM cv_signal(&event->se_cv); 1972*11963SAfshin.Ardakani@Sun.COM mutex_exit(&event->se_mutex); 1973*11963SAfshin.Ardakani@Sun.COM return (event->se_errno); 1974*11963SAfshin.Ardakani@Sun.COM } 1975*11963SAfshin.Ardakani@Sun.COM 1976*11963SAfshin.Ardakani@Sun.COM /* 1977*11963SAfshin.Ardakani@Sun.COM * If txid is non-zero, cancel the specified event. 1978*11963SAfshin.Ardakani@Sun.COM * Otherwise, cancel all events. 1979*11963SAfshin.Ardakani@Sun.COM */ 1980*11963SAfshin.Ardakani@Sun.COM static void 1981*11963SAfshin.Ardakani@Sun.COM smb_event_cancel(smb_server_t *sv, uint32_t txid) 1982*11963SAfshin.Ardakani@Sun.COM { 1983*11963SAfshin.Ardakani@Sun.COM smb_event_t *event; 1984*11963SAfshin.Ardakani@Sun.COM smb_llist_t *event_list; 1985*11963SAfshin.Ardakani@Sun.COM 1986*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 1987*11963SAfshin.Ardakani@Sun.COM 1988*11963SAfshin.Ardakani@Sun.COM event_list = &sv->sv_event_list; 1989*11963SAfshin.Ardakani@Sun.COM smb_llist_enter(event_list, RW_WRITER); 1990*11963SAfshin.Ardakani@Sun.COM 1991*11963SAfshin.Ardakani@Sun.COM event = smb_llist_head(event_list); 1992*11963SAfshin.Ardakani@Sun.COM while (event) { 1993*11963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 1994*11963SAfshin.Ardakani@Sun.COM 1995*11963SAfshin.Ardakani@Sun.COM if (txid == 0 || event->se_txid == txid) { 1996*11963SAfshin.Ardakani@Sun.COM mutex_enter(&event->se_mutex); 1997*11963SAfshin.Ardakani@Sun.COM event->se_errno = ECANCELED; 1998*11963SAfshin.Ardakani@Sun.COM event->se_notified = B_TRUE; 1999*11963SAfshin.Ardakani@Sun.COM cv_signal(&event->se_cv); 2000*11963SAfshin.Ardakani@Sun.COM mutex_exit(&event->se_mutex); 2001*11963SAfshin.Ardakani@Sun.COM 2002*11963SAfshin.Ardakani@Sun.COM if (txid != 0) 2003*11963SAfshin.Ardakani@Sun.COM break; 2004*11963SAfshin.Ardakani@Sun.COM } 2005*11963SAfshin.Ardakani@Sun.COM 2006*11963SAfshin.Ardakani@Sun.COM event = smb_llist_next(event_list, event); 2007*11963SAfshin.Ardakani@Sun.COM } 2008*11963SAfshin.Ardakani@Sun.COM 2009*11963SAfshin.Ardakani@Sun.COM smb_llist_exit(event_list); 2010*11963SAfshin.Ardakani@Sun.COM } 2011*11963SAfshin.Ardakani@Sun.COM 2012*11963SAfshin.Ardakani@Sun.COM /* 2013*11963SAfshin.Ardakani@Sun.COM * If txid is non-zero, notify the specified event. 2014*11963SAfshin.Ardakani@Sun.COM * Otherwise, notify all events. 2015*11963SAfshin.Ardakani@Sun.COM */ 2016*11963SAfshin.Ardakani@Sun.COM static void 2017*11963SAfshin.Ardakani@Sun.COM smb_event_notify(smb_server_t *sv, uint32_t txid) 2018*11963SAfshin.Ardakani@Sun.COM { 2019*11963SAfshin.Ardakani@Sun.COM smb_event_t *event; 2020*11963SAfshin.Ardakani@Sun.COM smb_llist_t *event_list; 2021*11963SAfshin.Ardakani@Sun.COM 2022*11963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 2023*11963SAfshin.Ardakani@Sun.COM 2024*11963SAfshin.Ardakani@Sun.COM event_list = &sv->sv_event_list; 2025*11963SAfshin.Ardakani@Sun.COM smb_llist_enter(event_list, RW_READER); 2026*11963SAfshin.Ardakani@Sun.COM 2027*11963SAfshin.Ardakani@Sun.COM event = smb_llist_head(event_list); 2028*11963SAfshin.Ardakani@Sun.COM while (event) { 2029*11963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 2030*11963SAfshin.Ardakani@Sun.COM 2031*11963SAfshin.Ardakani@Sun.COM if (txid == 0 || event->se_txid == txid) { 2032*11963SAfshin.Ardakani@Sun.COM mutex_enter(&event->se_mutex); 2033*11963SAfshin.Ardakani@Sun.COM event->se_notified = B_TRUE; 2034*11963SAfshin.Ardakani@Sun.COM cv_signal(&event->se_cv); 2035*11963SAfshin.Ardakani@Sun.COM mutex_exit(&event->se_mutex); 2036*11963SAfshin.Ardakani@Sun.COM 2037*11963SAfshin.Ardakani@Sun.COM if (txid != 0) 2038*11963SAfshin.Ardakani@Sun.COM break; 2039*11963SAfshin.Ardakani@Sun.COM } 2040*11963SAfshin.Ardakani@Sun.COM 2041*11963SAfshin.Ardakani@Sun.COM event = smb_llist_next(event_list, event); 2042*11963SAfshin.Ardakani@Sun.COM } 2043*11963SAfshin.Ardakani@Sun.COM 2044*11963SAfshin.Ardakani@Sun.COM smb_llist_exit(event_list); 2045*11963SAfshin.Ardakani@Sun.COM } 2046*11963SAfshin.Ardakani@Sun.COM 2047*11963SAfshin.Ardakani@Sun.COM /* 2048*11963SAfshin.Ardakani@Sun.COM * Allocate a new transaction id (txid). 2049*11963SAfshin.Ardakani@Sun.COM * 2050*11963SAfshin.Ardakani@Sun.COM * 0 or -1 are not assigned because they are used to detect invalid 2051*11963SAfshin.Ardakani@Sun.COM * conditions or to indicate all open id's. 2052*11963SAfshin.Ardakani@Sun.COM */ 2053*11963SAfshin.Ardakani@Sun.COM static uint32_t 2054*11963SAfshin.Ardakani@Sun.COM smb_event_alloc_txid(void) 2055*11963SAfshin.Ardakani@Sun.COM { 2056*11963SAfshin.Ardakani@Sun.COM static kmutex_t txmutex; 2057*11963SAfshin.Ardakani@Sun.COM static uint32_t txid; 2058*11963SAfshin.Ardakani@Sun.COM uint32_t txid_ret; 2059*11963SAfshin.Ardakani@Sun.COM 2060*11963SAfshin.Ardakani@Sun.COM mutex_enter(&txmutex); 2061*11963SAfshin.Ardakani@Sun.COM 2062*11963SAfshin.Ardakani@Sun.COM if (txid == 0) 2063*11963SAfshin.Ardakani@Sun.COM txid = ddi_get_lbolt() << 11; 2064*11963SAfshin.Ardakani@Sun.COM 2065*11963SAfshin.Ardakani@Sun.COM do { 2066*11963SAfshin.Ardakani@Sun.COM ++txid; 2067*11963SAfshin.Ardakani@Sun.COM } while (txid == 0 || txid == (uint32_t)-1); 2068*11963SAfshin.Ardakani@Sun.COM 2069*11963SAfshin.Ardakani@Sun.COM txid_ret = txid; 2070*11963SAfshin.Ardakani@Sun.COM mutex_exit(&txmutex); 2071*11963SAfshin.Ardakani@Sun.COM 2072*11963SAfshin.Ardakani@Sun.COM return (txid_ret); 2073*11963SAfshin.Ardakani@Sun.COM } 2074