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 /* 2212065SKeyur.Desai@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 236139Sjb150015 */ 246139Sjb150015 256139Sjb150015 /* 266139Sjb150015 * General Structures Layout 276139Sjb150015 * ------------------------- 286139Sjb150015 * 296139Sjb150015 * This is a simplified diagram showing the relationship between most of the 306139Sjb150015 * main structures. 316139Sjb150015 * 326139Sjb150015 * +-------------------+ 336139Sjb150015 * | SMB_SERVER | 346139Sjb150015 * +-------------------+ 356139Sjb150015 * | 366139Sjb150015 * | 376139Sjb150015 * v 386139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 396139Sjb150015 * | SESSION |<----->| SESSION |......| SESSION | 406139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 416139Sjb150015 * | 426139Sjb150015 * | 436139Sjb150015 * v 446139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 456139Sjb150015 * | USER |<----->| USER |......| USER | 466139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 476139Sjb150015 * | 486139Sjb150015 * | 496139Sjb150015 * v 506139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 516139Sjb150015 * | TREE |<----->| TREE |......| TREE | 526139Sjb150015 * +-------------------+ +-------------------+ +-------------------+ 536139Sjb150015 * | | 546139Sjb150015 * | | 556139Sjb150015 * | v 566139Sjb150015 * | +-------+ +-------+ +-------+ 576139Sjb150015 * | | OFILE |<----->| OFILE |......| OFILE | 586139Sjb150015 * | +-------+ +-------+ +-------+ 596139Sjb150015 * | 606139Sjb150015 * | 616139Sjb150015 * v 626139Sjb150015 * +-------+ +------+ +------+ 636139Sjb150015 * | ODIR |<----->| ODIR |......| ODIR | 646139Sjb150015 * +-------+ +------+ +------+ 656139Sjb150015 * 666139Sjb150015 * 676139Sjb150015 * Module Interface Overview 686139Sjb150015 * ------------------------- 696139Sjb150015 * 706139Sjb150015 * 716139Sjb150015 * +===================================+ 726139Sjb150015 * | smbd daemon | 736139Sjb150015 * +===================================+ 746139Sjb150015 * | | ^ 756139Sjb150015 * | | | 766139Sjb150015 * User | | | 776139Sjb150015 * -----------|--------------|----------------|-------------------------------- 786139Sjb150015 * Kernel | | | 796139Sjb150015 * | | | 806139Sjb150015 * | | | 816139Sjb150015 * +=========|==============|================|=================+ 826139Sjb150015 * | v v | | 836139Sjb150015 * | +-----------+ +--------------------+ +------------------+ | 846139Sjb150015 * | | IO | | Kernel Door Server | | User Door Servers| | 856139Sjb150015 * | | Interface | | Interface | | Interface | | 866139Sjb150015 * | +-----------+ +--------------------+ +------------------+ | 876139Sjb150015 * | | | ^ ^ | 886139Sjb150015 * | v v | | | +=========+ 896139Sjb150015 * | +-----------------------------------+ | | | | 906139Sjb150015 * | + SMB Server Management (this file) |<------------------| ZFS | 916139Sjb150015 * | +-----------------------------------+ | | | | 926139Sjb150015 * | | | | Module | 936139Sjb150015 * | +-----------------------------------+ | | | | 946139Sjb150015 * | + SMB Server Internal Layers |------+ | +=========+ 956139Sjb150015 * | +-----------------------------------+ | 966139Sjb150015 * | | 976139Sjb150015 * | | 986139Sjb150015 * +===========================================================+ 996139Sjb150015 * 1006139Sjb150015 * 1016139Sjb150015 * Server State Machine 1026139Sjb150015 * -------------------- 1036139Sjb150015 * | 1046139Sjb150015 * | T0 1056139Sjb150015 * | 1066139Sjb150015 * v 1076139Sjb150015 * +-----------------------------+ 1086139Sjb150015 * | SMB_SERVER_STATE_CREATED | 1096139Sjb150015 * +-----------------------------+ 1106139Sjb150015 * | 1116139Sjb150015 * | T1 1126139Sjb150015 * | 1136139Sjb150015 * v 1146139Sjb150015 * +-----------------------------+ 1156139Sjb150015 * | SMB_SERVER_STATE_CONFIGURED | 1166139Sjb150015 * +-----------------------------+ 1176139Sjb150015 * | 1186139Sjb150015 * | T2 1196139Sjb150015 * | 1206139Sjb150015 * v 1216139Sjb150015 * +-----------------------------+ 12211963SAfshin.Ardakani@Sun.COM * | SMB_SERVER_STATE_RUNNING / | 12311963SAfshin.Ardakani@Sun.COM * | SMB_SERVER_STATE_STOPPING | 1246139Sjb150015 * +-----------------------------+ 1256139Sjb150015 * | 1266139Sjb150015 * | T3 1276139Sjb150015 * | 1286139Sjb150015 * v 1296139Sjb150015 * +-----------------------------+ 1306139Sjb150015 * | SMB_SERVER_STATE_DELETING | 1316139Sjb150015 * +-----------------------------+ 1326139Sjb150015 * | 1336139Sjb150015 * | 1346139Sjb150015 * | 1356139Sjb150015 * v 1366139Sjb150015 * 1376139Sjb150015 * States 1386139Sjb150015 * ------ 1396139Sjb150015 * 1406139Sjb150015 * SMB_SERVER_STATE_CREATED 1416139Sjb150015 * 1426139Sjb150015 * This is the state of the server just after creation. 1436139Sjb150015 * 1446139Sjb150015 * SMB_SERVER_STATE_CONFIGURED 1456139Sjb150015 * 1466139Sjb150015 * The server has been configured. 1476139Sjb150015 * 1486139Sjb150015 * SMB_SERVER_STATE_RUNNING 1496139Sjb150015 * 1506139Sjb150015 * The server has been started. While in this state the threads listening on 1516139Sjb150015 * the sockets car be started. The smbd daemon does so through an Ioctl: 1526139Sjb150015 * 1536139Sjb150015 * smb_drv_ioctl(SMB_IOC_NBT_LISTEN) --> smb_server_nbt_listen() 1546139Sjb150015 * smb_drv_ioctl(SMB_IOC_TCP_LISTEN) --> smb_server_nbt_listen() 1556139Sjb150015 * 1566139Sjb150015 * When a client establishes a connection the thread listening leaves 1576139Sjb150015 * temporarily the kernel. While in user space it creates a thread for the 1586139Sjb150015 * new session. It then returns to kernel with the result of the thread 1596139Sjb150015 * creation. If the creation failed the new session context is destroyed 1606139Sjb150015 * before returning listening. 1616139Sjb150015 * 1626139Sjb150015 * The new created thread enters the kernel though an Ioctl: 1636139Sjb150015 * 1646139Sjb150015 * smb_drv_ioctl(SMB_IOC_NBT_RECEIVE) --> smb_server_nbt_receive() 1656139Sjb150015 * smb_drv_ioctl(SMB_IOC_TCP_RECEIVE) --> smb_server_tcp_receive() 1666139Sjb150015 * 1676139Sjb150015 * SMB_SERVER_STATE_STOPPING 1686139Sjb150015 * 1696139Sjb150015 * The threads listening on the NBT and TCP sockets are being terminated. 1706139Sjb150015 * 1716139Sjb150015 * 1726139Sjb150015 * Transitions 1736139Sjb150015 * ----------- 1746139Sjb150015 * 1756139Sjb150015 * Transition T0 1766139Sjb150015 * 1776139Sjb150015 * The daemon smbd triggers its creation by opening the smbsrv device. If 1786139Sjb150015 * the zone where the daemon lives doesn't have an smb server yet it is 1796139Sjb150015 * created. 1806139Sjb150015 * 1816139Sjb150015 * smb_drv_open() --> smb_server_create() 1826139Sjb150015 * 1836139Sjb150015 * Transition T1 1846139Sjb150015 * 1856139Sjb150015 * This transition occurs in smb_server_configure(). It is triggered by the 1866139Sjb150015 * daemon through an Ioctl. 1876139Sjb150015 * 1886139Sjb150015 * smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure() 1896139Sjb150015 * 1906139Sjb150015 * Transition T2 1916139Sjb150015 * 1926139Sjb150015 * This transition occurs in smb_server_start(). It is triggered by the 1936139Sjb150015 * daemon through an Ioctl. 1946139Sjb150015 * 1956139Sjb150015 * smb_drv_ioctl(SMB_IOC_START) --> smb_server_start() 1966139Sjb150015 * 1976139Sjb150015 * Transition T3 1986139Sjb150015 * 1996139Sjb150015 * This transition occurs in smb_server_delete(). It is triggered by the 2006139Sjb150015 * daemon when closing the smbsrv device 2016139Sjb150015 * 2026139Sjb150015 * smb_drv_close() --> smb_server_delete() 2036139Sjb150015 * 2046139Sjb150015 * Comments 2056139Sjb150015 * -------- 2066139Sjb150015 * 2076139Sjb150015 * This files assumes that there will one SMB server per zone. For now the 2086139Sjb150015 * smb server works only in global zone. There's nothing in this file preventing 2096139Sjb150015 * an smb server from being created in a non global zone. That limitation is 2106139Sjb150015 * enforced in user space. 2116139Sjb150015 */ 2126139Sjb150015 2136139Sjb150015 #include <sys/strsubr.h> 2146139Sjb150015 #include <sys/cmn_err.h> 2156139Sjb150015 #include <sys/priv.h> 2166139Sjb150015 #include <sys/socketvar.h> 2176139Sjb150015 #include <sys/zone.h> 21810966SJordan.Brown@Sun.COM #include <netinet/in.h> 21910966SJordan.Brown@Sun.COM #include <netinet/in_systm.h> 22010966SJordan.Brown@Sun.COM #include <netinet/ip.h> 22110966SJordan.Brown@Sun.COM #include <netinet/ip_icmp.h> 22210966SJordan.Brown@Sun.COM #include <netinet/ip_var.h> 22310966SJordan.Brown@Sun.COM #include <netinet/tcp.h> 2246139Sjb150015 #include <smbsrv/smb_kproto.h> 22510966SJordan.Brown@Sun.COM #include <smbsrv/string.h> 2266139Sjb150015 #include <smbsrv/netbios.h> 2276139Sjb150015 #include <smbsrv/smb_fsops.h> 2287052Samw #include <smbsrv/smb_share.h> 22911963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_door.h> 2306432Sas200622 #include <smbsrv/smb_kstat.h> 2316139Sjb150015 23211963SAfshin.Ardakani@Sun.COM #define SMB_EVENT_TIMEOUT 45 /* seconds */ 23311963SAfshin.Ardakani@Sun.COM 2346139Sjb150015 extern void smb_reply_notify_change_request(smb_request_t *); 2356139Sjb150015 236*12508Samw@Sun.COM static void smb_server_kstat_init(smb_server_t *); 2376139Sjb150015 static void smb_server_kstat_fini(smb_server_t *); 2386139Sjb150015 static void smb_server_timers(smb_thread_t *, void *); 2396139Sjb150015 static int smb_server_listen(smb_server_t *, smb_listener_daemon_t *, 2408670SJose.Borrego@Sun.COM in_port_t, int, int); 24111963SAfshin.Ardakani@Sun.COM static void smb_server_listen_fini(smb_listener_daemon_t *); 24211963SAfshin.Ardakani@Sun.COM static kt_did_t smb_server_listener_tid(smb_listener_daemon_t *); 2436139Sjb150015 static int smb_server_lookup(smb_server_t **); 2446139Sjb150015 static void smb_server_release(smb_server_t *); 2459832Samw@Sun.COM static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *); 24611963SAfshin.Ardakani@Sun.COM static void smb_server_shutdown(smb_server_t *); 2476139Sjb150015 static int smb_server_fsop_start(smb_server_t *); 2486139Sjb150015 static void smb_server_fsop_stop(smb_server_t *); 24911963SAfshin.Ardakani@Sun.COM static void smb_server_signal_listeners(smb_server_t *); 25011963SAfshin.Ardakani@Sun.COM static void smb_event_cancel(smb_server_t *, uint32_t); 25111963SAfshin.Ardakani@Sun.COM static void smb_event_notify(smb_server_t *, uint32_t); 25211963SAfshin.Ardakani@Sun.COM static uint32_t smb_event_alloc_txid(void); 2536139Sjb150015 25411963SAfshin.Ardakani@Sun.COM static void smb_server_disconnect_share(smb_session_list_t *, const char *); 25510122SJordan.Brown@Sun.COM static void smb_server_enum_private(smb_session_list_t *, smb_svcenum_t *); 25610122SJordan.Brown@Sun.COM static int smb_server_sesion_disconnect(smb_session_list_t *, const char *, 25710122SJordan.Brown@Sun.COM const char *); 25810122SJordan.Brown@Sun.COM static int smb_server_fclose(smb_session_list_t *, uint32_t); 259*12508Samw@Sun.COM static int smb_server_kstat_update(kstat_t *, int); 26010122SJordan.Brown@Sun.COM 26111963SAfshin.Ardakani@Sun.COM int smb_event_debug = 0; 26211963SAfshin.Ardakani@Sun.COM 2636139Sjb150015 static smb_llist_t smb_servers; 2646139Sjb150015 2656139Sjb150015 /* 2666139Sjb150015 * ***************************************************************************** 2676139Sjb150015 * **************** Functions called from the device interface ***************** 2686139Sjb150015 * ***************************************************************************** 2696139Sjb150015 * 27010122SJordan.Brown@Sun.COM * These functions typically have to determine the relevant smb server 27110122SJordan.Brown@Sun.COM * to which the call applies. 2726139Sjb150015 */ 2736139Sjb150015 2746139Sjb150015 /* 2756139Sjb150015 * smb_server_svc_init 2766139Sjb150015 * 2777348SJose.Borrego@Sun.COM * This function must be called from smb_drv_attach(). 2786139Sjb150015 */ 2796139Sjb150015 int 2806139Sjb150015 smb_server_svc_init(void) 2816139Sjb150015 { 2826139Sjb150015 int rc = 0; 2836139Sjb150015 2846139Sjb150015 while (rc == 0) { 2858934SJose.Borrego@Sun.COM if (rc = smb_mbc_init()) 2868934SJose.Borrego@Sun.COM continue; 2876139Sjb150015 if (rc = smb_vop_init()) 2886139Sjb150015 continue; 2896139Sjb150015 if (rc = smb_node_init()) 2906496Sjb150015 continue; 2916139Sjb150015 if (rc = smb_fem_init()) 2926496Sjb150015 continue; 2936139Sjb150015 if (rc = smb_notify_init()) 2946496Sjb150015 continue; 2956496Sjb150015 if (rc = smb_net_init()) 2966496Sjb150015 continue; 29711963SAfshin.Ardakani@Sun.COM smb_llist_init(); 2986139Sjb150015 smb_llist_constructor(&smb_servers, sizeof (smb_server_t), 2996139Sjb150015 offsetof(smb_server_t, sv_lnd)); 3006139Sjb150015 return (0); 3016139Sjb150015 } 30211963SAfshin.Ardakani@Sun.COM 30311963SAfshin.Ardakani@Sun.COM smb_llist_fini(); 3046496Sjb150015 smb_net_fini(); 3056139Sjb150015 smb_notify_fini(); 3066139Sjb150015 smb_fem_fini(); 3076139Sjb150015 smb_node_fini(); 3086139Sjb150015 smb_vop_fini(); 3098934SJose.Borrego@Sun.COM smb_mbc_fini(); 3106139Sjb150015 return (rc); 3116139Sjb150015 } 3126139Sjb150015 3136139Sjb150015 /* 3146139Sjb150015 * smb_server_svc_fini 3156139Sjb150015 * 3166139Sjb150015 * This function must called from smb_drv_detach(). It will fail if servers 3176139Sjb150015 * still exist. 3186139Sjb150015 */ 3196139Sjb150015 int 3206139Sjb150015 smb_server_svc_fini(void) 3216139Sjb150015 { 3226139Sjb150015 int rc = EBUSY; 3236139Sjb150015 3246139Sjb150015 if (smb_llist_get_count(&smb_servers) == 0) { 32511963SAfshin.Ardakani@Sun.COM smb_llist_fini(); 3266496Sjb150015 smb_net_fini(); 3276139Sjb150015 smb_notify_fini(); 3286139Sjb150015 smb_fem_fini(); 3296139Sjb150015 smb_node_fini(); 3306139Sjb150015 smb_vop_fini(); 3318934SJose.Borrego@Sun.COM smb_mbc_fini(); 3326139Sjb150015 smb_llist_destructor(&smb_servers); 3336139Sjb150015 rc = 0; 3346139Sjb150015 } 3356139Sjb150015 return (rc); 3366139Sjb150015 } 3376139Sjb150015 3386139Sjb150015 /* 3396139Sjb150015 * smb_server_create 3406139Sjb150015 * 3416139Sjb150015 * This function will fail if there's already a server associated with the 3426139Sjb150015 * caller's zone. 3436139Sjb150015 */ 3446139Sjb150015 int 3456139Sjb150015 smb_server_create(void) 3466139Sjb150015 { 3476139Sjb150015 zoneid_t zid; 3486139Sjb150015 smb_server_t *sv; 3496139Sjb150015 3506139Sjb150015 zid = getzoneid(); 3516139Sjb150015 3526139Sjb150015 smb_llist_enter(&smb_servers, RW_WRITER); 3536139Sjb150015 sv = smb_llist_head(&smb_servers); 3546139Sjb150015 while (sv) { 35511963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 3566139Sjb150015 if (sv->sv_zid == zid) { 3576139Sjb150015 smb_llist_exit(&smb_servers); 3588167Samw@Sun.COM return (EPERM); 3596139Sjb150015 } 3606139Sjb150015 sv = smb_llist_next(&smb_servers, sv); 3616139Sjb150015 } 3626139Sjb150015 3636139Sjb150015 sv = kmem_zalloc(sizeof (smb_server_t), KM_NOSLEEP); 3646139Sjb150015 if (sv == NULL) { 3656139Sjb150015 smb_llist_exit(&smb_servers); 3666139Sjb150015 return (ENOMEM); 3676139Sjb150015 } 3686139Sjb150015 36911963SAfshin.Ardakani@Sun.COM smb_llist_constructor(&sv->sv_opipe_list, sizeof (smb_opipe_t), 37011963SAfshin.Ardakani@Sun.COM offsetof(smb_opipe_t, p_lnd)); 37111963SAfshin.Ardakani@Sun.COM 37211963SAfshin.Ardakani@Sun.COM smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t), 37311963SAfshin.Ardakani@Sun.COM offsetof(smb_event_t, se_lnd)); 37411963SAfshin.Ardakani@Sun.COM 3756139Sjb150015 smb_session_list_constructor(&sv->sv_nbt_daemon.ld_session_list); 3766139Sjb150015 smb_session_list_constructor(&sv->sv_tcp_daemon.ld_session_list); 3776139Sjb150015 3786139Sjb150015 sv->si_cache_request = kmem_cache_create("smb_request_cache", 3796139Sjb150015 sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3806139Sjb150015 sv->si_cache_session = kmem_cache_create("smb_session_cache", 3816139Sjb150015 sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3826139Sjb150015 sv->si_cache_user = kmem_cache_create("smb_user_cache", 3836139Sjb150015 sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3846139Sjb150015 sv->si_cache_tree = kmem_cache_create("smb_tree_cache", 3856139Sjb150015 sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3866139Sjb150015 sv->si_cache_ofile = kmem_cache_create("smb_ofile_cache", 3876139Sjb150015 sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3886139Sjb150015 sv->si_cache_odir = kmem_cache_create("smb_odir_cache", 3896139Sjb150015 sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 39011963SAfshin.Ardakani@Sun.COM sv->si_cache_opipe = kmem_cache_create("smb_opipe_cache", 39111963SAfshin.Ardakani@Sun.COM sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 39211963SAfshin.Ardakani@Sun.COM sv->si_cache_event = kmem_cache_create("smb_event_cache", 39311963SAfshin.Ardakani@Sun.COM sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 3946139Sjb150015 3956139Sjb150015 smb_thread_init(&sv->si_thread_timers, 3966139Sjb150015 "smb_timers", smb_server_timers, sv, 3976139Sjb150015 NULL, NULL); 3986139Sjb150015 3996432Sas200622 sv->sv_pid = curproc->p_pid; 400*12508Samw@Sun.COM smb_srqueue_init(&sv->sv_srqueue); 4016139Sjb150015 40211963SAfshin.Ardakani@Sun.COM smb_kdoor_init(); 4037052Samw smb_opipe_door_init(); 404*12508Samw@Sun.COM smb_server_kstat_init(sv); 4056139Sjb150015 4066139Sjb150015 mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL); 4076139Sjb150015 cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL); 4086139Sjb150015 sv->sv_state = SMB_SERVER_STATE_CREATED; 4096139Sjb150015 sv->sv_magic = SMB_SERVER_MAGIC; 4106139Sjb150015 sv->sv_zid = zid; 4116139Sjb150015 4126139Sjb150015 smb_llist_insert_tail(&smb_servers, sv); 4136139Sjb150015 smb_llist_exit(&smb_servers); 4146139Sjb150015 return (0); 4156139Sjb150015 } 4166139Sjb150015 4176139Sjb150015 /* 4186139Sjb150015 * smb_server_delete 4196139Sjb150015 * 4206139Sjb150015 * This function will delete the server passed in. It will make sure that all 4216139Sjb150015 * activity associated that server has ceased before destroying it. 4226139Sjb150015 */ 4236139Sjb150015 int 4246139Sjb150015 smb_server_delete(void) 4256139Sjb150015 { 4266139Sjb150015 smb_server_t *sv; 42711963SAfshin.Ardakani@Sun.COM kt_did_t nbt_tid; 42811963SAfshin.Ardakani@Sun.COM kt_did_t tcp_tid; 4296139Sjb150015 int rc; 4306139Sjb150015 4316139Sjb150015 rc = smb_server_lookup(&sv); 4326139Sjb150015 if (rc != 0) 4336139Sjb150015 return (rc); 4346139Sjb150015 4356139Sjb150015 mutex_enter(&sv->sv_mutex); 4366139Sjb150015 switch (sv->sv_state) { 4376139Sjb150015 case SMB_SERVER_STATE_RUNNING: 43811963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 43911963SAfshin.Ardakani@Sun.COM sv->sv_state = SMB_SERVER_STATE_STOPPING; 44011963SAfshin.Ardakani@Sun.COM smb_server_signal_listeners(sv); 44111963SAfshin.Ardakani@Sun.COM nbt_tid = smb_server_listener_tid(&sv->sv_nbt_daemon); 44211963SAfshin.Ardakani@Sun.COM tcp_tid = smb_server_listener_tid(&sv->sv_tcp_daemon); 4436139Sjb150015 4446139Sjb150015 sv->sv_state = SMB_SERVER_STATE_DELETING; 4456139Sjb150015 mutex_exit(&sv->sv_mutex); 44611963SAfshin.Ardakani@Sun.COM 44711963SAfshin.Ardakani@Sun.COM if (nbt_tid != 0) 44811963SAfshin.Ardakani@Sun.COM thread_join(nbt_tid); 44911963SAfshin.Ardakani@Sun.COM if (tcp_tid != 0) 45011963SAfshin.Ardakani@Sun.COM thread_join(tcp_tid); 45111963SAfshin.Ardakani@Sun.COM 45211963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(&sv->sv_nbt_daemon); 45311963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(&sv->sv_tcp_daemon); 4546139Sjb150015 mutex_enter(&sv->sv_mutex); 4556139Sjb150015 break; 4566139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 4576139Sjb150015 case SMB_SERVER_STATE_CREATED: 4586139Sjb150015 sv->sv_state = SMB_SERVER_STATE_DELETING; 4596139Sjb150015 break; 4606139Sjb150015 default: 46111963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 4626139Sjb150015 mutex_exit(&sv->sv_mutex); 4636139Sjb150015 smb_server_release(sv); 4646139Sjb150015 return (ENOTTY); 4656139Sjb150015 } 4666139Sjb150015 4676139Sjb150015 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 4686139Sjb150015 4696139Sjb150015 sv->sv_refcnt--; 4706139Sjb150015 while (sv->sv_refcnt) 4716139Sjb150015 cv_wait(&sv->sv_cv, &sv->sv_mutex); 4726139Sjb150015 4736139Sjb150015 mutex_exit(&sv->sv_mutex); 4746139Sjb150015 4756139Sjb150015 smb_llist_enter(&smb_servers, RW_WRITER); 4766139Sjb150015 smb_llist_remove(&smb_servers, sv); 4776139Sjb150015 smb_llist_exit(&smb_servers); 4786139Sjb150015 47911963SAfshin.Ardakani@Sun.COM smb_server_shutdown(sv); 4806139Sjb150015 rw_destroy(&sv->sv_cfg_lock); 4817052Samw smb_opipe_door_fini(); 48211963SAfshin.Ardakani@Sun.COM smb_kdoor_fini(); 4836139Sjb150015 smb_server_kstat_fini(sv); 48411963SAfshin.Ardakani@Sun.COM smb_llist_destructor(&sv->sv_opipe_list); 48511963SAfshin.Ardakani@Sun.COM smb_llist_destructor(&sv->sv_event_list); 4867619SJose.Borrego@Sun.COM 4876139Sjb150015 kmem_cache_destroy(sv->si_cache_request); 4886139Sjb150015 kmem_cache_destroy(sv->si_cache_session); 4896139Sjb150015 kmem_cache_destroy(sv->si_cache_user); 4906139Sjb150015 kmem_cache_destroy(sv->si_cache_tree); 4916139Sjb150015 kmem_cache_destroy(sv->si_cache_ofile); 4926139Sjb150015 kmem_cache_destroy(sv->si_cache_odir); 49311963SAfshin.Ardakani@Sun.COM kmem_cache_destroy(sv->si_cache_opipe); 49411963SAfshin.Ardakani@Sun.COM kmem_cache_destroy(sv->si_cache_event); 4956139Sjb150015 496*12508Samw@Sun.COM smb_srqueue_destroy(&sv->sv_srqueue); 497*12508Samw@Sun.COM 4986139Sjb150015 smb_thread_destroy(&sv->si_thread_timers); 4996139Sjb150015 mutex_destroy(&sv->sv_mutex); 5006139Sjb150015 cv_destroy(&sv->sv_cv); 5016139Sjb150015 sv->sv_magic = 0; 5026139Sjb150015 kmem_free(sv, sizeof (smb_server_t)); 5036139Sjb150015 5046139Sjb150015 return (0); 5056139Sjb150015 } 5066139Sjb150015 5076139Sjb150015 /* 5086139Sjb150015 * smb_server_configure 5096139Sjb150015 */ 5106139Sjb150015 int 5119832Samw@Sun.COM smb_server_configure(smb_ioc_cfg_t *ioc) 5126139Sjb150015 { 5136139Sjb150015 int rc = 0; 5146139Sjb150015 smb_server_t *sv; 5156139Sjb150015 5166139Sjb150015 rc = smb_server_lookup(&sv); 5176139Sjb150015 if (rc) 5186139Sjb150015 return (rc); 5196139Sjb150015 5206139Sjb150015 mutex_enter(&sv->sv_mutex); 5216139Sjb150015 switch (sv->sv_state) { 5226139Sjb150015 case SMB_SERVER_STATE_CREATED: 5239832Samw@Sun.COM smb_server_store_cfg(sv, ioc); 5246139Sjb150015 sv->sv_state = SMB_SERVER_STATE_CONFIGURED; 5256139Sjb150015 break; 5266139Sjb150015 5276139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 5289832Samw@Sun.COM smb_server_store_cfg(sv, ioc); 5296139Sjb150015 break; 5306139Sjb150015 5316139Sjb150015 case SMB_SERVER_STATE_RUNNING: 53211963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 5336139Sjb150015 rw_enter(&sv->sv_cfg_lock, RW_WRITER); 5349832Samw@Sun.COM smb_server_store_cfg(sv, ioc); 5356139Sjb150015 rw_exit(&sv->sv_cfg_lock); 5366139Sjb150015 break; 5376139Sjb150015 5386139Sjb150015 default: 53911963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 5406139Sjb150015 rc = EFAULT; 5416139Sjb150015 break; 5426139Sjb150015 } 5436139Sjb150015 mutex_exit(&sv->sv_mutex); 5446139Sjb150015 5456139Sjb150015 smb_server_release(sv); 5466139Sjb150015 5476139Sjb150015 return (rc); 5486139Sjb150015 } 5496139Sjb150015 5506139Sjb150015 /* 5516139Sjb150015 * smb_server_start 5526139Sjb150015 */ 5536139Sjb150015 int 5549832Samw@Sun.COM smb_server_start(smb_ioc_start_t *ioc) 5556139Sjb150015 { 5566139Sjb150015 int rc = 0; 5576139Sjb150015 smb_server_t *sv; 5586139Sjb150015 5596139Sjb150015 rc = smb_server_lookup(&sv); 5606139Sjb150015 if (rc) 5616139Sjb150015 return (rc); 5626139Sjb150015 5636139Sjb150015 mutex_enter(&sv->sv_mutex); 5646139Sjb150015 switch (sv->sv_state) { 5656139Sjb150015 case SMB_SERVER_STATE_CONFIGURED: 56610966SJordan.Brown@Sun.COM smb_codepage_init(); 5676139Sjb150015 5686139Sjb150015 sv->sv_thread_pool = taskq_create("smb_workers", 5696139Sjb150015 sv->sv_cfg.skc_maxworkers, SMB_WORKER_PRIORITY, 5706139Sjb150015 sv->sv_cfg.skc_maxworkers, INT_MAX, 5716139Sjb150015 TASKQ_DYNAMIC|TASKQ_PREPOPULATE); 5726139Sjb150015 5738670SJose.Borrego@Sun.COM sv->sv_session = smb_session_create(NULL, 0, sv, 0); 5747588Samw@Sun.COM 5757588Samw@Sun.COM if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) { 5766139Sjb150015 rc = ENOMEM; 5776139Sjb150015 break; 5786139Sjb150015 } 5796139Sjb150015 5806139Sjb150015 if (rc = smb_server_fsop_start(sv)) 5816139Sjb150015 break; 5826139Sjb150015 ASSERT(sv->sv_lmshrd == NULL); 583*12508Samw@Sun.COM sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd); 5846139Sjb150015 if (sv->sv_lmshrd == NULL) 5856139Sjb150015 break; 58611963SAfshin.Ardakani@Sun.COM if (rc = smb_kdoor_open(ioc->udoor)) { 58711963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "Cannot open smbd door"); 5886139Sjb150015 break; 58911963SAfshin.Ardakani@Sun.COM } 59011963SAfshin.Ardakani@Sun.COM if (rc = smb_opipe_door_open(ioc->opipe)) { 59111963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "Cannot open opipe door"); 59211963SAfshin.Ardakani@Sun.COM break; 59311963SAfshin.Ardakani@Sun.COM } 5946139Sjb150015 if (rc = smb_thread_start(&sv->si_thread_timers)) 5956139Sjb150015 break; 5966139Sjb150015 sv->sv_state = SMB_SERVER_STATE_RUNNING; 597*12508Samw@Sun.COM sv->sv_start_time = gethrtime(); 5986139Sjb150015 mutex_exit(&sv->sv_mutex); 5996139Sjb150015 smb_server_release(sv); 600*12508Samw@Sun.COM 601*12508Samw@Sun.COM smb_export_start(); 6026139Sjb150015 return (0); 6036139Sjb150015 default: 60411963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 6056139Sjb150015 mutex_exit(&sv->sv_mutex); 6066139Sjb150015 smb_server_release(sv); 6076139Sjb150015 return (ENOTTY); 6086139Sjb150015 } 6096139Sjb150015 61011963SAfshin.Ardakani@Sun.COM smb_server_shutdown(sv); 6116139Sjb150015 mutex_exit(&sv->sv_mutex); 6126139Sjb150015 smb_server_release(sv); 6136139Sjb150015 return (rc); 6146139Sjb150015 } 6156139Sjb150015 6166139Sjb150015 /* 61711963SAfshin.Ardakani@Sun.COM * An smbd is shutting down. 61811963SAfshin.Ardakani@Sun.COM */ 61911963SAfshin.Ardakani@Sun.COM int 62011963SAfshin.Ardakani@Sun.COM smb_server_stop(void) 62111963SAfshin.Ardakani@Sun.COM { 62211963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 62311963SAfshin.Ardakani@Sun.COM int rc; 62411963SAfshin.Ardakani@Sun.COM 62511963SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) != 0) 62611963SAfshin.Ardakani@Sun.COM return (rc); 62711963SAfshin.Ardakani@Sun.COM 62811963SAfshin.Ardakani@Sun.COM mutex_enter(&sv->sv_mutex); 62911963SAfshin.Ardakani@Sun.COM switch (sv->sv_state) { 63011963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_RUNNING: 63111963SAfshin.Ardakani@Sun.COM sv->sv_state = SMB_SERVER_STATE_STOPPING; 63211963SAfshin.Ardakani@Sun.COM smb_server_signal_listeners(sv); 63311963SAfshin.Ardakani@Sun.COM break; 63411963SAfshin.Ardakani@Sun.COM default: 63511963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 63611963SAfshin.Ardakani@Sun.COM break; 63711963SAfshin.Ardakani@Sun.COM } 63811963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 63911963SAfshin.Ardakani@Sun.COM 64011963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 64111963SAfshin.Ardakani@Sun.COM return (0); 64211963SAfshin.Ardakani@Sun.COM } 64311963SAfshin.Ardakani@Sun.COM 64411963SAfshin.Ardakani@Sun.COM boolean_t 64511963SAfshin.Ardakani@Sun.COM smb_server_is_stopping(void) 64611963SAfshin.Ardakani@Sun.COM { 647*12508Samw@Sun.COM smb_server_t *sv; 64811963SAfshin.Ardakani@Sun.COM boolean_t status; 64911963SAfshin.Ardakani@Sun.COM 65011963SAfshin.Ardakani@Sun.COM if (smb_server_lookup(&sv) != 0) 65111963SAfshin.Ardakani@Sun.COM return (B_TRUE); 65211963SAfshin.Ardakani@Sun.COM 65311963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 65411963SAfshin.Ardakani@Sun.COM 65511963SAfshin.Ardakani@Sun.COM mutex_enter(&sv->sv_mutex); 65611963SAfshin.Ardakani@Sun.COM 65711963SAfshin.Ardakani@Sun.COM switch (sv->sv_state) { 65811963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 65911963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_DELETING: 66011963SAfshin.Ardakani@Sun.COM status = B_TRUE; 66111963SAfshin.Ardakani@Sun.COM break; 66211963SAfshin.Ardakani@Sun.COM default: 66311963SAfshin.Ardakani@Sun.COM status = B_FALSE; 66411963SAfshin.Ardakani@Sun.COM break; 66511963SAfshin.Ardakani@Sun.COM } 66611963SAfshin.Ardakani@Sun.COM 66711963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 66811963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 66911963SAfshin.Ardakani@Sun.COM return (status); 67011963SAfshin.Ardakani@Sun.COM } 67111963SAfshin.Ardakani@Sun.COM 67211963SAfshin.Ardakani@Sun.COM int 67311963SAfshin.Ardakani@Sun.COM smb_server_cancel_event(uint32_t txid) 67411963SAfshin.Ardakani@Sun.COM { 67511963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 67611963SAfshin.Ardakani@Sun.COM int rc; 67711963SAfshin.Ardakani@Sun.COM 67811963SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 67911963SAfshin.Ardakani@Sun.COM smb_event_cancel(sv, txid); 68011963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 68111963SAfshin.Ardakani@Sun.COM } 68211963SAfshin.Ardakani@Sun.COM 68311963SAfshin.Ardakani@Sun.COM return (rc); 68411963SAfshin.Ardakani@Sun.COM } 68511963SAfshin.Ardakani@Sun.COM 68611963SAfshin.Ardakani@Sun.COM int 68711963SAfshin.Ardakani@Sun.COM smb_server_notify_event(smb_ioc_event_t *ioc) 68811963SAfshin.Ardakani@Sun.COM { 68911963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 69011963SAfshin.Ardakani@Sun.COM int rc; 69111963SAfshin.Ardakani@Sun.COM 69211963SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 69311963SAfshin.Ardakani@Sun.COM smb_event_notify(sv, ioc->txid); 69411963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 69511963SAfshin.Ardakani@Sun.COM } 69611963SAfshin.Ardakani@Sun.COM 69711963SAfshin.Ardakani@Sun.COM return (rc); 69811963SAfshin.Ardakani@Sun.COM } 69911963SAfshin.Ardakani@Sun.COM 70011963SAfshin.Ardakani@Sun.COM /* 70111963SAfshin.Ardakani@Sun.COM * SMB-over-NetBIOS (port 139) 7026139Sjb150015 * 70311963SAfshin.Ardakani@Sun.COM * Traditional SMB service over NetBIOS, which requires that a NetBIOS 70411963SAfshin.Ardakani@Sun.COM * session be established. 7056139Sjb150015 */ 7066139Sjb150015 int 7079832Samw@Sun.COM smb_server_nbt_listen(smb_ioc_listen_t *ioc) 7086139Sjb150015 { 7096139Sjb150015 smb_server_t *sv; 7106139Sjb150015 int rc; 7116139Sjb150015 7126139Sjb150015 rc = smb_server_lookup(&sv); 7136139Sjb150015 if (rc) 7146139Sjb150015 return (rc); 7156139Sjb150015 7166139Sjb150015 mutex_enter(&sv->sv_mutex); 7176139Sjb150015 switch (sv->sv_state) { 7186139Sjb150015 case SMB_SERVER_STATE_RUNNING: 7196139Sjb150015 if ((sv->sv_nbt_daemon.ld_kth != NULL) && 7206139Sjb150015 (sv->sv_nbt_daemon.ld_kth != curthread)) { 7216139Sjb150015 mutex_exit(&sv->sv_mutex); 7229422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 7236139Sjb150015 return (EACCES); 7246139Sjb150015 } else { 7256139Sjb150015 sv->sv_nbt_daemon.ld_kth = curthread; 7266139Sjb150015 sv->sv_nbt_daemon.ld_ktdid = curthread->t_did; 7276139Sjb150015 } 7286139Sjb150015 break; 72911963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 73011963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 73111963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 73211963SAfshin.Ardakani@Sun.COM return (ECANCELED); 7336139Sjb150015 default: 73411963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 7356139Sjb150015 mutex_exit(&sv->sv_mutex); 7366139Sjb150015 smb_server_release(sv); 7376139Sjb150015 return (EFAULT); 7386139Sjb150015 } 7396139Sjb150015 mutex_exit(&sv->sv_mutex); 7406139Sjb150015 7418670SJose.Borrego@Sun.COM /* 7428670SJose.Borrego@Sun.COM * netbios must be ipv4 7438670SJose.Borrego@Sun.COM */ 74410717Samw@Sun.COM rc = smb_server_listen(sv, &sv->sv_nbt_daemon, IPPORT_NETBIOS_SSN, 7459832Samw@Sun.COM AF_INET, ioc->error); 7466139Sjb150015 74711963SAfshin.Ardakani@Sun.COM mutex_enter(&sv->sv_mutex); 74811963SAfshin.Ardakani@Sun.COM sv->sv_nbt_daemon.ld_kth = NULL; 74911963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 7506139Sjb150015 7516139Sjb150015 smb_server_release(sv); 7526139Sjb150015 return (rc); 7536139Sjb150015 } 7546139Sjb150015 75511963SAfshin.Ardakani@Sun.COM /* 75611963SAfshin.Ardakani@Sun.COM * SMB-over-TCP (port 445) 75711963SAfshin.Ardakani@Sun.COM */ 7586139Sjb150015 int 7599832Samw@Sun.COM smb_server_tcp_listen(smb_ioc_listen_t *ioc) 7606139Sjb150015 { 7616139Sjb150015 smb_server_t *sv; 7626139Sjb150015 int rc; 7636139Sjb150015 7646139Sjb150015 rc = smb_server_lookup(&sv); 7656139Sjb150015 if (rc) 7666139Sjb150015 return (rc); 7676139Sjb150015 7686139Sjb150015 mutex_enter(&sv->sv_mutex); 7696139Sjb150015 switch (sv->sv_state) { 7706139Sjb150015 case SMB_SERVER_STATE_RUNNING: 77111963SAfshin.Ardakani@Sun.COM if ((sv->sv_tcp_daemon.ld_kth != NULL) && 7726139Sjb150015 (sv->sv_tcp_daemon.ld_kth != curthread)) { 7736139Sjb150015 mutex_exit(&sv->sv_mutex); 7749422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 7756139Sjb150015 return (EACCES); 7766139Sjb150015 } else { 7776139Sjb150015 sv->sv_tcp_daemon.ld_kth = curthread; 7786139Sjb150015 sv->sv_tcp_daemon.ld_ktdid = curthread->t_did; 7796139Sjb150015 } 7806139Sjb150015 break; 78111963SAfshin.Ardakani@Sun.COM case SMB_SERVER_STATE_STOPPING: 78211963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 78311963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 78411963SAfshin.Ardakani@Sun.COM return (ECANCELED); 7856139Sjb150015 default: 78611963SAfshin.Ardakani@Sun.COM SMB_SERVER_STATE_VALID(sv->sv_state); 7876139Sjb150015 mutex_exit(&sv->sv_mutex); 7889422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 7896139Sjb150015 return (EFAULT); 7906139Sjb150015 } 7916139Sjb150015 mutex_exit(&sv->sv_mutex); 7926139Sjb150015 7938670SJose.Borrego@Sun.COM if (sv->sv_cfg.skc_ipv6_enable) 7948670SJose.Borrego@Sun.COM rc = smb_server_listen(sv, &sv->sv_tcp_daemon, 79510717Samw@Sun.COM IPPORT_SMB, AF_INET6, ioc->error); 7968670SJose.Borrego@Sun.COM else 7978670SJose.Borrego@Sun.COM rc = smb_server_listen(sv, &sv->sv_tcp_daemon, 79810717Samw@Sun.COM IPPORT_SMB, AF_INET, ioc->error); 79911963SAfshin.Ardakani@Sun.COM 80011963SAfshin.Ardakani@Sun.COM mutex_enter(&sv->sv_mutex); 80111963SAfshin.Ardakani@Sun.COM sv->sv_tcp_daemon.ld_kth = NULL; 80211963SAfshin.Ardakani@Sun.COM mutex_exit(&sv->sv_mutex); 8036139Sjb150015 8046139Sjb150015 smb_server_release(sv); 8056139Sjb150015 return (rc); 8066139Sjb150015 } 8076139Sjb150015 8086139Sjb150015 /* 8096139Sjb150015 * smb_server_nbt_receive 8106139Sjb150015 */ 8116139Sjb150015 int 8126139Sjb150015 smb_server_nbt_receive(void) 8136139Sjb150015 { 8146139Sjb150015 int rc; 8156139Sjb150015 smb_server_t *sv; 8166139Sjb150015 8179422SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 8189422SAfshin.Ardakani@Sun.COM rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list); 8199422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 8209422SAfshin.Ardakani@Sun.COM } 8216139Sjb150015 8226139Sjb150015 return (rc); 8236139Sjb150015 } 8246139Sjb150015 8256139Sjb150015 /* 8266139Sjb150015 * smb_server_tcp_receive 8276139Sjb150015 */ 8286139Sjb150015 int 8296139Sjb150015 smb_server_tcp_receive(void) 8306139Sjb150015 { 8316139Sjb150015 int rc; 8326139Sjb150015 smb_server_t *sv; 8336139Sjb150015 8349422SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 8359422SAfshin.Ardakani@Sun.COM rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list); 8369422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 8379422SAfshin.Ardakani@Sun.COM } 8386139Sjb150015 8396139Sjb150015 return (rc); 8406139Sjb150015 } 8416139Sjb150015 8426139Sjb150015 int 8439832Samw@Sun.COM smb_server_set_gmtoff(smb_ioc_gmt_t *ioc) 8446139Sjb150015 { 8456139Sjb150015 int rc; 8466139Sjb150015 smb_server_t *sv; 8476139Sjb150015 8489422SAfshin.Ardakani@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 8499832Samw@Sun.COM sv->si_gmtoff = ioc->offset; 8509422SAfshin.Ardakani@Sun.COM smb_server_release(sv); 8519422SAfshin.Ardakani@Sun.COM } 8526139Sjb150015 8536139Sjb150015 return (rc); 8546139Sjb150015 } 8556139Sjb150015 8569832Samw@Sun.COM int 85710122SJordan.Brown@Sun.COM smb_server_numopen(smb_ioc_opennum_t *ioc) 8589832Samw@Sun.COM { 8599832Samw@Sun.COM smb_server_t *sv; 8609832Samw@Sun.COM int rc; 8619832Samw@Sun.COM 8629832Samw@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 863*12508Samw@Sun.COM ioc->open_users = sv->sv_users; 864*12508Samw@Sun.COM ioc->open_trees = sv->sv_trees; 865*12508Samw@Sun.COM ioc->open_files = sv->sv_files + sv->sv_pipes; 8669832Samw@Sun.COM smb_server_release(sv); 8679832Samw@Sun.COM } 8689832Samw@Sun.COM return (rc); 8699832Samw@Sun.COM } 8709832Samw@Sun.COM 8716139Sjb150015 /* 87210122SJordan.Brown@Sun.COM * Enumerate objects within the server. The svcenum provides the 87310122SJordan.Brown@Sun.COM * enumeration context, i.e. what the caller want to get back. 87410122SJordan.Brown@Sun.COM */ 87510122SJordan.Brown@Sun.COM int 87610122SJordan.Brown@Sun.COM smb_server_enum(smb_ioc_svcenum_t *ioc) 87710122SJordan.Brown@Sun.COM { 87810122SJordan.Brown@Sun.COM smb_svcenum_t *svcenum = &ioc->svcenum; 87910122SJordan.Brown@Sun.COM smb_server_t *sv; 88010122SJordan.Brown@Sun.COM smb_session_list_t *se; 88110122SJordan.Brown@Sun.COM int rc; 88210122SJordan.Brown@Sun.COM 88310122SJordan.Brown@Sun.COM switch (svcenum->se_type) { 88410122SJordan.Brown@Sun.COM case SMB_SVCENUM_TYPE_USER: 88510122SJordan.Brown@Sun.COM case SMB_SVCENUM_TYPE_TREE: 88610122SJordan.Brown@Sun.COM case SMB_SVCENUM_TYPE_FILE: 88710122SJordan.Brown@Sun.COM break; 88810122SJordan.Brown@Sun.COM default: 88910122SJordan.Brown@Sun.COM return (EINVAL); 89010122SJordan.Brown@Sun.COM } 89110122SJordan.Brown@Sun.COM 89210122SJordan.Brown@Sun.COM if ((rc = smb_server_lookup(&sv)) != 0) 89310122SJordan.Brown@Sun.COM return (rc); 89410122SJordan.Brown@Sun.COM 89510122SJordan.Brown@Sun.COM svcenum->se_bavail = svcenum->se_buflen; 89610122SJordan.Brown@Sun.COM svcenum->se_bused = 0; 89710122SJordan.Brown@Sun.COM svcenum->se_nitems = 0; 89810122SJordan.Brown@Sun.COM 89910122SJordan.Brown@Sun.COM se = &sv->sv_nbt_daemon.ld_session_list; 90010122SJordan.Brown@Sun.COM smb_server_enum_private(se, svcenum); 90110122SJordan.Brown@Sun.COM 90210122SJordan.Brown@Sun.COM se = &sv->sv_tcp_daemon.ld_session_list; 90310122SJordan.Brown@Sun.COM smb_server_enum_private(se, svcenum); 90410122SJordan.Brown@Sun.COM 90510122SJordan.Brown@Sun.COM smb_server_release(sv); 90610122SJordan.Brown@Sun.COM return (0); 90710122SJordan.Brown@Sun.COM } 90810122SJordan.Brown@Sun.COM 90910122SJordan.Brown@Sun.COM /* 91010122SJordan.Brown@Sun.COM * Look for sessions to disconnect by client and user name. 91110122SJordan.Brown@Sun.COM */ 91210122SJordan.Brown@Sun.COM int 91310122SJordan.Brown@Sun.COM smb_server_session_close(smb_ioc_session_t *ioc) 91410122SJordan.Brown@Sun.COM { 91510122SJordan.Brown@Sun.COM smb_session_list_t *se; 91610122SJordan.Brown@Sun.COM smb_server_t *sv; 91710122SJordan.Brown@Sun.COM int nbt_cnt; 91810122SJordan.Brown@Sun.COM int tcp_cnt; 91910122SJordan.Brown@Sun.COM int rc; 92010122SJordan.Brown@Sun.COM 92110122SJordan.Brown@Sun.COM if ((rc = smb_server_lookup(&sv)) != 0) 92210122SJordan.Brown@Sun.COM return (rc); 92310122SJordan.Brown@Sun.COM 92410122SJordan.Brown@Sun.COM se = &sv->sv_nbt_daemon.ld_session_list; 92510122SJordan.Brown@Sun.COM nbt_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username); 92610122SJordan.Brown@Sun.COM 92710122SJordan.Brown@Sun.COM se = &sv->sv_tcp_daemon.ld_session_list; 92810122SJordan.Brown@Sun.COM tcp_cnt = smb_server_sesion_disconnect(se, ioc->client, ioc->username); 92910122SJordan.Brown@Sun.COM 93010122SJordan.Brown@Sun.COM smb_server_release(sv); 93110122SJordan.Brown@Sun.COM 93210122SJordan.Brown@Sun.COM if ((nbt_cnt == 0) && (tcp_cnt == 0)) 93310122SJordan.Brown@Sun.COM return (ENOENT); 93410122SJordan.Brown@Sun.COM return (0); 93510122SJordan.Brown@Sun.COM } 93610122SJordan.Brown@Sun.COM 93710122SJordan.Brown@Sun.COM /* 93810122SJordan.Brown@Sun.COM * Close a file by uniqid. 93910122SJordan.Brown@Sun.COM */ 94010122SJordan.Brown@Sun.COM int 94110122SJordan.Brown@Sun.COM smb_server_file_close(smb_ioc_fileid_t *ioc) 94210122SJordan.Brown@Sun.COM { 94310122SJordan.Brown@Sun.COM uint32_t uniqid = ioc->uniqid; 94410122SJordan.Brown@Sun.COM smb_session_list_t *se; 94510122SJordan.Brown@Sun.COM smb_server_t *sv; 94610122SJordan.Brown@Sun.COM int rc; 94710122SJordan.Brown@Sun.COM 94810122SJordan.Brown@Sun.COM if ((rc = smb_server_lookup(&sv)) != 0) 94910122SJordan.Brown@Sun.COM return (rc); 95010122SJordan.Brown@Sun.COM 95110122SJordan.Brown@Sun.COM se = &sv->sv_nbt_daemon.ld_session_list; 95210122SJordan.Brown@Sun.COM rc = smb_server_fclose(se, uniqid); 95310122SJordan.Brown@Sun.COM 95410122SJordan.Brown@Sun.COM if (rc == ENOENT) { 95510122SJordan.Brown@Sun.COM se = &sv->sv_tcp_daemon.ld_session_list; 95610122SJordan.Brown@Sun.COM rc = smb_server_fclose(se, uniqid); 95710122SJordan.Brown@Sun.COM } 95810122SJordan.Brown@Sun.COM 95910122SJordan.Brown@Sun.COM smb_server_release(sv); 96010122SJordan.Brown@Sun.COM return (rc); 96110122SJordan.Brown@Sun.COM } 96210122SJordan.Brown@Sun.COM 96310122SJordan.Brown@Sun.COM /* 9646139Sjb150015 * These functions determine the relevant smb server to which the call apply. 9656139Sjb150015 */ 9666139Sjb150015 9676139Sjb150015 uint32_t 9686139Sjb150015 smb_server_get_session_count(void) 9696139Sjb150015 { 9706139Sjb150015 smb_server_t *sv; 9716139Sjb150015 uint32_t counter = 0; 9726139Sjb150015 9736139Sjb150015 if (smb_server_lookup(&sv)) 9746139Sjb150015 return (0); 9756139Sjb150015 9766139Sjb150015 rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER); 9776139Sjb150015 counter = sv->sv_nbt_daemon.ld_session_list.se_act.count; 9786139Sjb150015 rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock); 9796139Sjb150015 rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER); 9806139Sjb150015 counter += sv->sv_tcp_daemon.ld_session_list.se_act.count; 9816139Sjb150015 rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock); 9826139Sjb150015 9836139Sjb150015 smb_server_release(sv); 9846139Sjb150015 9856139Sjb150015 return (counter); 9866139Sjb150015 } 9876139Sjb150015 9886139Sjb150015 /* 989*12508Samw@Sun.COM * Gets the vnode of the specified share path. 990*12508Samw@Sun.COM * 991*12508Samw@Sun.COM * A hold on the returned vnode pointer is taken so the caller 992*12508Samw@Sun.COM * must call VN_RELE. 993*12508Samw@Sun.COM */ 994*12508Samw@Sun.COM int 995*12508Samw@Sun.COM smb_server_sharevp(const char *shr_path, vnode_t **vp) 996*12508Samw@Sun.COM { 997*12508Samw@Sun.COM smb_server_t *sv; 998*12508Samw@Sun.COM smb_request_t *sr; 999*12508Samw@Sun.COM smb_node_t *fnode = NULL; 1000*12508Samw@Sun.COM smb_node_t *dnode; 1001*12508Samw@Sun.COM char last_comp[MAXNAMELEN]; 1002*12508Samw@Sun.COM int rc = 0; 1003*12508Samw@Sun.COM 1004*12508Samw@Sun.COM ASSERT(shr_path); 1005*12508Samw@Sun.COM 1006*12508Samw@Sun.COM if ((rc = smb_server_lookup(&sv))) 1007*12508Samw@Sun.COM return (rc); 1008*12508Samw@Sun.COM 1009*12508Samw@Sun.COM mutex_enter(&sv->sv_mutex); 1010*12508Samw@Sun.COM switch (sv->sv_state) { 1011*12508Samw@Sun.COM case SMB_SERVER_STATE_RUNNING: 1012*12508Samw@Sun.COM break; 1013*12508Samw@Sun.COM default: 1014*12508Samw@Sun.COM mutex_exit(&sv->sv_mutex); 1015*12508Samw@Sun.COM smb_server_release(sv); 1016*12508Samw@Sun.COM return (ENOTACTIVE); 1017*12508Samw@Sun.COM } 1018*12508Samw@Sun.COM mutex_exit(&sv->sv_mutex); 1019*12508Samw@Sun.COM 1020*12508Samw@Sun.COM if ((sr = smb_request_alloc(sv->sv_session, 0)) == NULL) { 1021*12508Samw@Sun.COM smb_server_release(sv); 1022*12508Samw@Sun.COM return (ENOMEM); 1023*12508Samw@Sun.COM } 1024*12508Samw@Sun.COM sr->user_cr = kcred; 1025*12508Samw@Sun.COM 1026*12508Samw@Sun.COM rc = smb_pathname_reduce(sr, sr->user_cr, shr_path, 1027*12508Samw@Sun.COM NULL, NULL, &dnode, last_comp); 1028*12508Samw@Sun.COM 1029*12508Samw@Sun.COM if (rc == 0) { 1030*12508Samw@Sun.COM rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, 1031*12508Samw@Sun.COM sv->si_root_smb_node, dnode, last_comp, &fnode); 1032*12508Samw@Sun.COM smb_node_release(dnode); 1033*12508Samw@Sun.COM } 1034*12508Samw@Sun.COM 1035*12508Samw@Sun.COM smb_request_free(sr); 1036*12508Samw@Sun.COM smb_server_release(sv); 1037*12508Samw@Sun.COM 1038*12508Samw@Sun.COM if (rc != 0) 1039*12508Samw@Sun.COM return (rc); 1040*12508Samw@Sun.COM 1041*12508Samw@Sun.COM ASSERT(fnode->vp && fnode->vp->v_vfsp); 1042*12508Samw@Sun.COM 1043*12508Samw@Sun.COM VN_HOLD(fnode->vp); 1044*12508Samw@Sun.COM *vp = fnode->vp; 1045*12508Samw@Sun.COM 1046*12508Samw@Sun.COM smb_node_release(fnode); 1047*12508Samw@Sun.COM 1048*12508Samw@Sun.COM return (0); 1049*12508Samw@Sun.COM } 1050*12508Samw@Sun.COM 1051*12508Samw@Sun.COM 1052*12508Samw@Sun.COM /* 1053*12508Samw@Sun.COM * This is a special interface that will be utilized by ZFS to cause a share to 1054*12508Samw@Sun.COM * be added/removed. 1055*12508Samw@Sun.COM * 1056*12508Samw@Sun.COM * arg is either a lmshare_info_t or share_name from userspace. 1057*12508Samw@Sun.COM * It will need to be copied into the kernel. It is lmshare_info_t 1058*12508Samw@Sun.COM * for add operations and share_name for delete operations. 1059*12508Samw@Sun.COM */ 1060*12508Samw@Sun.COM int 1061*12508Samw@Sun.COM smb_server_share(void *arg, boolean_t add_share) 1062*12508Samw@Sun.COM { 1063*12508Samw@Sun.COM smb_server_t *sv; 1064*12508Samw@Sun.COM int rc; 1065*12508Samw@Sun.COM 1066*12508Samw@Sun.COM if ((rc = smb_server_lookup(&sv)) == 0) { 1067*12508Samw@Sun.COM mutex_enter(&sv->sv_mutex); 1068*12508Samw@Sun.COM switch (sv->sv_state) { 1069*12508Samw@Sun.COM case SMB_SERVER_STATE_RUNNING: 1070*12508Samw@Sun.COM mutex_exit(&sv->sv_mutex); 1071*12508Samw@Sun.COM (void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share); 1072*12508Samw@Sun.COM break; 1073*12508Samw@Sun.COM default: 1074*12508Samw@Sun.COM mutex_exit(&sv->sv_mutex); 1075*12508Samw@Sun.COM break; 1076*12508Samw@Sun.COM } 1077*12508Samw@Sun.COM smb_server_release(sv); 1078*12508Samw@Sun.COM } 1079*12508Samw@Sun.COM 1080*12508Samw@Sun.COM return (rc); 1081*12508Samw@Sun.COM } 1082*12508Samw@Sun.COM 1083*12508Samw@Sun.COM int 1084*12508Samw@Sun.COM smb_server_unshare(const char *sharename) 1085*12508Samw@Sun.COM { 1086*12508Samw@Sun.COM smb_server_t *sv; 1087*12508Samw@Sun.COM smb_session_list_t *slist; 1088*12508Samw@Sun.COM int rc; 1089*12508Samw@Sun.COM 1090*12508Samw@Sun.COM if ((rc = smb_server_lookup(&sv))) 1091*12508Samw@Sun.COM return (rc); 1092*12508Samw@Sun.COM 1093*12508Samw@Sun.COM mutex_enter(&sv->sv_mutex); 1094*12508Samw@Sun.COM switch (sv->sv_state) { 1095*12508Samw@Sun.COM case SMB_SERVER_STATE_RUNNING: 1096*12508Samw@Sun.COM case SMB_SERVER_STATE_STOPPING: 1097*12508Samw@Sun.COM break; 1098*12508Samw@Sun.COM default: 1099*12508Samw@Sun.COM mutex_exit(&sv->sv_mutex); 1100*12508Samw@Sun.COM smb_server_release(sv); 1101*12508Samw@Sun.COM return (ENOTACTIVE); 1102*12508Samw@Sun.COM } 1103*12508Samw@Sun.COM mutex_exit(&sv->sv_mutex); 1104*12508Samw@Sun.COM 1105*12508Samw@Sun.COM slist = &sv->sv_nbt_daemon.ld_session_list; 1106*12508Samw@Sun.COM smb_server_disconnect_share(slist, sharename); 1107*12508Samw@Sun.COM 1108*12508Samw@Sun.COM slist = &sv->sv_tcp_daemon.ld_session_list; 1109*12508Samw@Sun.COM smb_server_disconnect_share(slist, sharename); 1110*12508Samw@Sun.COM 1111*12508Samw@Sun.COM smb_server_release(sv); 1112*12508Samw@Sun.COM return (0); 1113*12508Samw@Sun.COM } 1114*12508Samw@Sun.COM 1115*12508Samw@Sun.COM /* 111611963SAfshin.Ardakani@Sun.COM * Disconnect the specified share. 111711963SAfshin.Ardakani@Sun.COM * Typically called when a share has been removed. 11186139Sjb150015 */ 11197619SJose.Borrego@Sun.COM static void 112011963SAfshin.Ardakani@Sun.COM smb_server_disconnect_share(smb_session_list_t *slist, const char *sharename) 11216139Sjb150015 { 112211963SAfshin.Ardakani@Sun.COM smb_session_t *session; 112311963SAfshin.Ardakani@Sun.COM 112411963SAfshin.Ardakani@Sun.COM rw_enter(&slist->se_lock, RW_READER); 112511963SAfshin.Ardakani@Sun.COM 112611963SAfshin.Ardakani@Sun.COM session = list_head(&slist->se_act.lst); 112711963SAfshin.Ardakani@Sun.COM while (session) { 112811963SAfshin.Ardakani@Sun.COM ASSERT(session->s_magic == SMB_SESSION_MAGIC); 112911963SAfshin.Ardakani@Sun.COM smb_rwx_rwenter(&session->s_lock, RW_READER); 113011963SAfshin.Ardakani@Sun.COM switch (session->s_state) { 113111963SAfshin.Ardakani@Sun.COM case SMB_SESSION_STATE_NEGOTIATED: 113211963SAfshin.Ardakani@Sun.COM case SMB_SESSION_STATE_OPLOCK_BREAKING: 113311963SAfshin.Ardakani@Sun.COM case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: 113411963SAfshin.Ardakani@Sun.COM smb_session_disconnect_share(session, sharename); 113511963SAfshin.Ardakani@Sun.COM break; 113611963SAfshin.Ardakani@Sun.COM default: 113711963SAfshin.Ardakani@Sun.COM break; 113811963SAfshin.Ardakani@Sun.COM } 113911963SAfshin.Ardakani@Sun.COM smb_rwx_rwexit(&session->s_lock); 114011963SAfshin.Ardakani@Sun.COM session = list_next(&slist->se_act.lst, session); 114111963SAfshin.Ardakani@Sun.COM } 114211963SAfshin.Ardakani@Sun.COM 114311963SAfshin.Ardakani@Sun.COM rw_exit(&slist->se_lock); 11446139Sjb150015 } 11456139Sjb150015 11466139Sjb150015 /* 11476139Sjb150015 * ***************************************************************************** 11486139Sjb150015 * **************** Functions called from the internal layers ****************** 11496139Sjb150015 * ***************************************************************************** 11506139Sjb150015 * 11516139Sjb150015 * These functions are provided the relevant smb server by the caller. 11526139Sjb150015 */ 11536139Sjb150015 11546139Sjb150015 void 11556139Sjb150015 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session) 11566139Sjb150015 { 11576139Sjb150015 ASSERT(sv == session->s_server); 11586139Sjb150015 11596139Sjb150015 smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list, 11606139Sjb150015 session); 11616139Sjb150015 smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list, 11626139Sjb150015 session); 11636139Sjb150015 } 11646139Sjb150015 11656139Sjb150015 void 11666139Sjb150015 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 11676139Sjb150015 { 11686139Sjb150015 rw_enter(&sv->sv_cfg_lock, RW_READER); 11696139Sjb150015 bcopy(&sv->sv_cfg, cfg, sizeof (*cfg)); 11706139Sjb150015 rw_exit(&sv->sv_cfg_lock); 11716139Sjb150015 } 11726139Sjb150015 11736139Sjb150015 /* 1174*12508Samw@Sun.COM * 1175*12508Samw@Sun.COM */ 1176*12508Samw@Sun.COM void 1177*12508Samw@Sun.COM smb_server_inc_nbt_sess(smb_server_t *sv) 1178*12508Samw@Sun.COM { 1179*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1180*12508Samw@Sun.COM atomic_inc_32(&sv->sv_nbt_sess); 1181*12508Samw@Sun.COM } 1182*12508Samw@Sun.COM 1183*12508Samw@Sun.COM void 1184*12508Samw@Sun.COM smb_server_dec_nbt_sess(smb_server_t *sv) 1185*12508Samw@Sun.COM { 1186*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1187*12508Samw@Sun.COM atomic_dec_32(&sv->sv_nbt_sess); 1188*12508Samw@Sun.COM } 1189*12508Samw@Sun.COM 1190*12508Samw@Sun.COM void 1191*12508Samw@Sun.COM smb_server_inc_tcp_sess(smb_server_t *sv) 1192*12508Samw@Sun.COM { 1193*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1194*12508Samw@Sun.COM atomic_inc_32(&sv->sv_tcp_sess); 1195*12508Samw@Sun.COM } 1196*12508Samw@Sun.COM 1197*12508Samw@Sun.COM void 1198*12508Samw@Sun.COM smb_server_dec_tcp_sess(smb_server_t *sv) 1199*12508Samw@Sun.COM { 1200*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1201*12508Samw@Sun.COM atomic_dec_32(&sv->sv_tcp_sess); 1202*12508Samw@Sun.COM } 1203*12508Samw@Sun.COM 1204*12508Samw@Sun.COM void 1205*12508Samw@Sun.COM smb_server_inc_users(smb_server_t *sv) 1206*12508Samw@Sun.COM { 1207*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1208*12508Samw@Sun.COM atomic_inc_32(&sv->sv_users); 1209*12508Samw@Sun.COM } 1210*12508Samw@Sun.COM 1211*12508Samw@Sun.COM void 1212*12508Samw@Sun.COM smb_server_dec_users(smb_server_t *sv) 1213*12508Samw@Sun.COM { 1214*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1215*12508Samw@Sun.COM atomic_dec_32(&sv->sv_users); 1216*12508Samw@Sun.COM } 1217*12508Samw@Sun.COM 1218*12508Samw@Sun.COM void 1219*12508Samw@Sun.COM smb_server_inc_trees(smb_server_t *sv) 1220*12508Samw@Sun.COM { 1221*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1222*12508Samw@Sun.COM atomic_inc_32(&sv->sv_trees); 1223*12508Samw@Sun.COM } 1224*12508Samw@Sun.COM 1225*12508Samw@Sun.COM void 1226*12508Samw@Sun.COM smb_server_dec_trees(smb_server_t *sv) 1227*12508Samw@Sun.COM { 1228*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1229*12508Samw@Sun.COM atomic_dec_32(&sv->sv_trees); 1230*12508Samw@Sun.COM } 1231*12508Samw@Sun.COM 1232*12508Samw@Sun.COM void 1233*12508Samw@Sun.COM smb_server_inc_files(smb_server_t *sv) 1234*12508Samw@Sun.COM { 1235*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1236*12508Samw@Sun.COM atomic_inc_32(&sv->sv_files); 1237*12508Samw@Sun.COM } 1238*12508Samw@Sun.COM 1239*12508Samw@Sun.COM void 1240*12508Samw@Sun.COM smb_server_dec_files(smb_server_t *sv) 1241*12508Samw@Sun.COM { 1242*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1243*12508Samw@Sun.COM atomic_dec_32(&sv->sv_files); 1244*12508Samw@Sun.COM } 1245*12508Samw@Sun.COM 1246*12508Samw@Sun.COM void 1247*12508Samw@Sun.COM smb_server_inc_pipes(smb_server_t *sv) 1248*12508Samw@Sun.COM { 1249*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1250*12508Samw@Sun.COM atomic_inc_32(&sv->sv_pipes); 1251*12508Samw@Sun.COM } 1252*12508Samw@Sun.COM 1253*12508Samw@Sun.COM void 1254*12508Samw@Sun.COM smb_server_dec_pipes(smb_server_t *sv) 1255*12508Samw@Sun.COM { 1256*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1257*12508Samw@Sun.COM atomic_dec_32(&sv->sv_pipes); 1258*12508Samw@Sun.COM } 1259*12508Samw@Sun.COM 1260*12508Samw@Sun.COM void 1261*12508Samw@Sun.COM smb_server_add_rxb(smb_server_t *sv, int64_t value) 1262*12508Samw@Sun.COM { 1263*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1264*12508Samw@Sun.COM atomic_add_64(&sv->sv_rxb, value); 1265*12508Samw@Sun.COM } 1266*12508Samw@Sun.COM 1267*12508Samw@Sun.COM void 1268*12508Samw@Sun.COM smb_server_add_txb(smb_server_t *sv, int64_t value) 1269*12508Samw@Sun.COM { 1270*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1271*12508Samw@Sun.COM atomic_add_64(&sv->sv_txb, value); 1272*12508Samw@Sun.COM } 1273*12508Samw@Sun.COM 1274*12508Samw@Sun.COM void 1275*12508Samw@Sun.COM smb_server_inc_req(smb_server_t *sv) 1276*12508Samw@Sun.COM { 1277*12508Samw@Sun.COM SMB_SERVER_VALID(sv); 1278*12508Samw@Sun.COM atomic_inc_64(&sv->sv_nreq); 1279*12508Samw@Sun.COM } 1280*12508Samw@Sun.COM 1281*12508Samw@Sun.COM /* 12826139Sjb150015 * ***************************************************************************** 12836139Sjb150015 * *************************** Static Functions ******************************** 12846139Sjb150015 * ***************************************************************************** 12856139Sjb150015 */ 12866139Sjb150015 12876139Sjb150015 static void 12886139Sjb150015 smb_server_timers(smb_thread_t *thread, void *arg) 12896139Sjb150015 { 12906139Sjb150015 smb_server_t *sv = (smb_server_t *)arg; 12916139Sjb150015 12926139Sjb150015 ASSERT(sv != NULL); 12936139Sjb150015 12946139Sjb150015 while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) { 12956139Sjb150015 smb_session_timers(&sv->sv_nbt_daemon.ld_session_list); 12966139Sjb150015 smb_session_timers(&sv->sv_tcp_daemon.ld_session_list); 12976139Sjb150015 } 12986139Sjb150015 } 12996139Sjb150015 13006139Sjb150015 /* 13016139Sjb150015 * smb_server_kstat_init 13026139Sjb150015 */ 1303*12508Samw@Sun.COM static void 13046139Sjb150015 smb_server_kstat_init(smb_server_t *sv) 13056139Sjb150015 { 1306*12508Samw@Sun.COM sv->sv_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, sv->sv_zid, 1307*12508Samw@Sun.COM SMBSRV_KSTAT_STATISTICS, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW, 1308*12508Samw@Sun.COM sizeof (smbsrv_kstats_t), 0, sv->sv_zid); 13096139Sjb150015 1310*12508Samw@Sun.COM if (sv->sv_ksp != NULL) { 1311*12508Samw@Sun.COM sv->sv_ksp->ks_update = smb_server_kstat_update; 1312*12508Samw@Sun.COM sv->sv_ksp->ks_private = sv; 1313*12508Samw@Sun.COM ((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_start_time = 1314*12508Samw@Sun.COM sv->sv_start_time; 1315*12508Samw@Sun.COM smb_dispatch_stats_init( 1316*12508Samw@Sun.COM ((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_reqs); 13176139Sjb150015 kstat_install(sv->sv_ksp); 1318*12508Samw@Sun.COM } else { 1319*12508Samw@Sun.COM cmn_err(CE_WARN, "SMB Server: Statistics unavailable"); 13206139Sjb150015 } 13216139Sjb150015 } 13226139Sjb150015 13236139Sjb150015 /* 13246139Sjb150015 * smb_server_kstat_fini 13256139Sjb150015 */ 13266139Sjb150015 static void 13276139Sjb150015 smb_server_kstat_fini(smb_server_t *sv) 13286139Sjb150015 { 1329*12508Samw@Sun.COM if (sv->sv_ksp != NULL) { 13306139Sjb150015 kstat_delete(sv->sv_ksp); 13316139Sjb150015 sv->sv_ksp = NULL; 1332*12508Samw@Sun.COM smb_dispatch_stats_fini(); 13336139Sjb150015 } 13346139Sjb150015 } 13356139Sjb150015 1336*12508Samw@Sun.COM /* 1337*12508Samw@Sun.COM * smb_server_kstat_update 1338*12508Samw@Sun.COM */ 13396139Sjb150015 static int 1340*12508Samw@Sun.COM smb_server_kstat_update(kstat_t *ksp, int rw) 13416139Sjb150015 { 13426139Sjb150015 smb_server_t *sv; 1343*12508Samw@Sun.COM smbsrv_kstats_t *ksd; 13446139Sjb150015 1345*12508Samw@Sun.COM if (rw == KSTAT_READ) { 1346*12508Samw@Sun.COM sv = ksp->ks_private; 134711963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 1348*12508Samw@Sun.COM ksd = (smbsrv_kstats_t *)ksp->ks_data; 1349*12508Samw@Sun.COM /* 1350*12508Samw@Sun.COM * Counters 1351*12508Samw@Sun.COM */ 1352*12508Samw@Sun.COM ksd->ks_nbt_sess = sv->sv_nbt_sess; 1353*12508Samw@Sun.COM ksd->ks_tcp_sess = sv->sv_tcp_sess; 1354*12508Samw@Sun.COM ksd->ks_users = sv->sv_users; 1355*12508Samw@Sun.COM ksd->ks_trees = sv->sv_trees; 1356*12508Samw@Sun.COM ksd->ks_files = sv->sv_files; 1357*12508Samw@Sun.COM ksd->ks_pipes = sv->sv_pipes; 1358*12508Samw@Sun.COM /* 1359*12508Samw@Sun.COM * Throughput 1360*12508Samw@Sun.COM */ 1361*12508Samw@Sun.COM ksd->ks_txb = sv->sv_txb; 1362*12508Samw@Sun.COM ksd->ks_rxb = sv->sv_rxb; 1363*12508Samw@Sun.COM ksd->ks_nreq = sv->sv_nreq; 1364*12508Samw@Sun.COM /* 1365*12508Samw@Sun.COM * Busyness 1366*12508Samw@Sun.COM */ 1367*12508Samw@Sun.COM ksd->ks_maxreqs = sv->sv_cfg.skc_maxworkers; 1368*12508Samw@Sun.COM smb_srqueue_update(&sv->sv_srqueue, 1369*12508Samw@Sun.COM &ksd->ks_utilization); 1370*12508Samw@Sun.COM /* 1371*12508Samw@Sun.COM * Latency & Throughput of the requests 1372*12508Samw@Sun.COM */ 1373*12508Samw@Sun.COM smb_dispatch_stats_update(ksd->ks_reqs, 0, SMB_COM_NUM); 1374*12508Samw@Sun.COM return (0); 1375*12508Samw@Sun.COM } 1376*12508Samw@Sun.COM if (rw == KSTAT_WRITE) 1377*12508Samw@Sun.COM return (EACCES); 13786139Sjb150015 1379*12508Samw@Sun.COM return (EIO); 13806139Sjb150015 } 13816139Sjb150015 13826139Sjb150015 /* 13836139Sjb150015 * The mutex of the server must have been entered before calling this function. 13846139Sjb150015 */ 13856139Sjb150015 static void 138611963SAfshin.Ardakani@Sun.COM smb_server_shutdown(smb_server_t *sv) 13876139Sjb150015 { 138811963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 13896139Sjb150015 13907052Samw smb_opipe_door_close(); 13916139Sjb150015 smb_thread_stop(&sv->si_thread_timers); 139211963SAfshin.Ardakani@Sun.COM smb_kdoor_close(); 1393*12508Samw@Sun.COM smb_kshare_door_fini(sv->sv_lmshrd); 13946849Sjb150015 sv->sv_lmshrd = NULL; 1395*12508Samw@Sun.COM smb_export_stop(); 13966139Sjb150015 smb_server_fsop_stop(sv); 13977588Samw@Sun.COM 13986139Sjb150015 if (sv->sv_session) { 13996139Sjb150015 smb_session_delete(sv->sv_session); 14006139Sjb150015 sv->sv_session = NULL; 14016139Sjb150015 } 14027588Samw@Sun.COM 14037588Samw@Sun.COM if (sv->sv_thread_pool) { 14047588Samw@Sun.COM taskq_destroy(sv->sv_thread_pool); 14057588Samw@Sun.COM sv->sv_thread_pool = NULL; 14067588Samw@Sun.COM } 14076139Sjb150015 } 14086139Sjb150015 14096139Sjb150015 static int 14106139Sjb150015 smb_server_listen( 14116139Sjb150015 smb_server_t *sv, 14126139Sjb150015 smb_listener_daemon_t *ld, 14136139Sjb150015 in_port_t port, 14148670SJose.Borrego@Sun.COM int family, 14156139Sjb150015 int pthread_create_error) 14166139Sjb150015 { 141711963SAfshin.Ardakani@Sun.COM int rc = 0; 14188348SEric.Yu@Sun.COM ksocket_t s_so; 141911963SAfshin.Ardakani@Sun.COM uint32_t on; 142011963SAfshin.Ardakani@Sun.COM uint32_t off; 142111963SAfshin.Ardakani@Sun.COM uint32_t txbuf_size; 14226139Sjb150015 smb_session_t *session; 14236139Sjb150015 14246139Sjb150015 if (pthread_create_error) { 14256139Sjb150015 /* 14266139Sjb150015 * Delete the last session created. The user space thread 14276139Sjb150015 * creation failed. 14286139Sjb150015 */ 14296139Sjb150015 smb_session_list_delete_tail(&ld->ld_session_list); 14306139Sjb150015 } 14316139Sjb150015 14326139Sjb150015 if (ld->ld_so == NULL) { 14336139Sjb150015 /* First time listener */ 14348670SJose.Borrego@Sun.COM if (family == AF_INET) { 14358670SJose.Borrego@Sun.COM ld->ld_sin.sin_family = (uint32_t)family; 14368670SJose.Borrego@Sun.COM ld->ld_sin.sin_port = htons(port); 14378670SJose.Borrego@Sun.COM ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY); 14388670SJose.Borrego@Sun.COM } else { 14398670SJose.Borrego@Sun.COM ld->ld_sin6.sin6_family = (uint32_t)family; 14408670SJose.Borrego@Sun.COM ld->ld_sin6.sin6_port = htons(port); 14418670SJose.Borrego@Sun.COM (void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0, 14428670SJose.Borrego@Sun.COM sizeof (ld->ld_sin6.sin6_addr.s6_addr)); 14438670SJose.Borrego@Sun.COM } 144411963SAfshin.Ardakani@Sun.COM 14458670SJose.Borrego@Sun.COM ld->ld_so = smb_socreate(family, SOCK_STREAM, 0); 144611963SAfshin.Ardakani@Sun.COM if (ld->ld_so == NULL) { 144711963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "port %d: socket create failed", port); 144811963SAfshin.Ardakani@Sun.COM return (ENOMEM); 144911963SAfshin.Ardakani@Sun.COM } 14506139Sjb150015 145111963SAfshin.Ardakani@Sun.COM off = 0; 145211963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 145311963SAfshin.Ardakani@Sun.COM SO_MAC_EXEMPT, &off, sizeof (off), CRED()); 145411963SAfshin.Ardakani@Sun.COM 145511963SAfshin.Ardakani@Sun.COM on = 1; 145611963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 145711963SAfshin.Ardakani@Sun.COM SO_REUSEADDR, &on, sizeof (on), CRED()); 14589021Samw@Sun.COM 145911963SAfshin.Ardakani@Sun.COM if (family == AF_INET) { 146011963SAfshin.Ardakani@Sun.COM rc = ksocket_bind(ld->ld_so, 146111963SAfshin.Ardakani@Sun.COM (struct sockaddr *)&ld->ld_sin, 146211963SAfshin.Ardakani@Sun.COM sizeof (ld->ld_sin), CRED()); 14636139Sjb150015 } else { 146411963SAfshin.Ardakani@Sun.COM rc = ksocket_bind(ld->ld_so, 146511963SAfshin.Ardakani@Sun.COM (struct sockaddr *)&ld->ld_sin6, 146611963SAfshin.Ardakani@Sun.COM sizeof (ld->ld_sin6), CRED()); 146711963SAfshin.Ardakani@Sun.COM } 146811963SAfshin.Ardakani@Sun.COM 146911963SAfshin.Ardakani@Sun.COM if (rc != 0) { 147011963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "port %d: bind failed (%d)", port, rc); 147111963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(ld); 147211963SAfshin.Ardakani@Sun.COM return (rc); 147311963SAfshin.Ardakani@Sun.COM } 147411963SAfshin.Ardakani@Sun.COM 147511963SAfshin.Ardakani@Sun.COM rc = ksocket_listen(ld->ld_so, 20, CRED()); 147611963SAfshin.Ardakani@Sun.COM if (rc < 0) { 147711963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "port %d: listen failed", port); 147811963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(ld); 147911963SAfshin.Ardakani@Sun.COM return (rc); 14806139Sjb150015 } 14816139Sjb150015 } 14826139Sjb150015 14836139Sjb150015 DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so); 14846139Sjb150015 14856139Sjb150015 for (;;) { 148611963SAfshin.Ardakani@Sun.COM if (smb_server_is_stopping()) { 148711963SAfshin.Ardakani@Sun.COM rc = ECANCELED; 148811963SAfshin.Ardakani@Sun.COM break; 148911963SAfshin.Ardakani@Sun.COM } 149011963SAfshin.Ardakani@Sun.COM 14918348SEric.Yu@Sun.COM rc = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED()); 149211963SAfshin.Ardakani@Sun.COM if (rc != 0) 149311963SAfshin.Ardakani@Sun.COM break; 149411963SAfshin.Ardakani@Sun.COM 149511963SAfshin.Ardakani@Sun.COM if (smb_server_is_stopping()) { 149611963SAfshin.Ardakani@Sun.COM smb_soshutdown(s_so); 149711963SAfshin.Ardakani@Sun.COM smb_sodestroy(s_so); 149811963SAfshin.Ardakani@Sun.COM rc = ECANCELED; 149911963SAfshin.Ardakani@Sun.COM break; 150011963SAfshin.Ardakani@Sun.COM } 15016139Sjb150015 150211963SAfshin.Ardakani@Sun.COM DTRACE_PROBE1(so__accept, struct sonode *, s_so); 150311963SAfshin.Ardakani@Sun.COM 150411963SAfshin.Ardakani@Sun.COM on = 1; 150511963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY, 150611963SAfshin.Ardakani@Sun.COM &on, sizeof (on), CRED()); 150711963SAfshin.Ardakani@Sun.COM 150811963SAfshin.Ardakani@Sun.COM on = 1; 150911963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE, 151011963SAfshin.Ardakani@Sun.COM &on, sizeof (on), CRED()); 15116139Sjb150015 151211963SAfshin.Ardakani@Sun.COM txbuf_size = 128*1024; 151311963SAfshin.Ardakani@Sun.COM (void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF, 151411963SAfshin.Ardakani@Sun.COM (const void *)&txbuf_size, sizeof (txbuf_size), CRED()); 151511963SAfshin.Ardakani@Sun.COM 151611963SAfshin.Ardakani@Sun.COM /* 151711963SAfshin.Ardakani@Sun.COM * Create a session for this connection. 151811963SAfshin.Ardakani@Sun.COM */ 151911963SAfshin.Ardakani@Sun.COM session = smb_session_create(s_so, port, sv, family); 152011963SAfshin.Ardakani@Sun.COM if (session) { 152111963SAfshin.Ardakani@Sun.COM smb_session_list_append(&ld->ld_session_list, session); 152211963SAfshin.Ardakani@Sun.COM rc = 0; 152311963SAfshin.Ardakani@Sun.COM break; 152411963SAfshin.Ardakani@Sun.COM } else { 152511963SAfshin.Ardakani@Sun.COM smb_soshutdown(s_so); 152611963SAfshin.Ardakani@Sun.COM smb_sodestroy(s_so); 15276139Sjb150015 } 152811963SAfshin.Ardakani@Sun.COM } 152911963SAfshin.Ardakani@Sun.COM 153011963SAfshin.Ardakani@Sun.COM if (rc != 0) 153111963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(ld); 153211963SAfshin.Ardakani@Sun.COM 153311963SAfshin.Ardakani@Sun.COM return (rc); 153411963SAfshin.Ardakani@Sun.COM } 153511963SAfshin.Ardakani@Sun.COM 153611963SAfshin.Ardakani@Sun.COM static void 153711963SAfshin.Ardakani@Sun.COM smb_server_listen_fini(smb_listener_daemon_t *ld) 153811963SAfshin.Ardakani@Sun.COM { 153911963SAfshin.Ardakani@Sun.COM if (ld->ld_so != NULL) { 15406139Sjb150015 smb_session_list_signal(&ld->ld_session_list); 15416139Sjb150015 smb_soshutdown(ld->ld_so); 15426139Sjb150015 smb_sodestroy(ld->ld_so); 15436139Sjb150015 ld->ld_so = NULL; 154411963SAfshin.Ardakani@Sun.COM } 154511963SAfshin.Ardakani@Sun.COM } 154611963SAfshin.Ardakani@Sun.COM 154711963SAfshin.Ardakani@Sun.COM static kt_did_t 154811963SAfshin.Ardakani@Sun.COM smb_server_listener_tid(smb_listener_daemon_t *ld) 154911963SAfshin.Ardakani@Sun.COM { 155011963SAfshin.Ardakani@Sun.COM kt_did_t tid; 155111963SAfshin.Ardakani@Sun.COM 155211963SAfshin.Ardakani@Sun.COM if (ld->ld_ktdid != 0) { 155311963SAfshin.Ardakani@Sun.COM tid = ld->ld_ktdid; 155411963SAfshin.Ardakani@Sun.COM ld->ld_ktdid = 0; 15556139Sjb150015 } 15566139Sjb150015 155711963SAfshin.Ardakani@Sun.COM return (tid); 15586139Sjb150015 } 15596139Sjb150015 15606139Sjb150015 /* 15616139Sjb150015 * smb_server_lookup 15626139Sjb150015 * 15636139Sjb150015 * This function tries to find the server associated with the zone of the 15646139Sjb150015 * caller. 15656139Sjb150015 */ 15666139Sjb150015 static int 15676139Sjb150015 smb_server_lookup(smb_server_t **psv) 15686139Sjb150015 { 15696139Sjb150015 zoneid_t zid; 15706139Sjb150015 smb_server_t *sv; 15716139Sjb150015 15726139Sjb150015 zid = getzoneid(); 15736139Sjb150015 15746139Sjb150015 smb_llist_enter(&smb_servers, RW_READER); 15756139Sjb150015 sv = smb_llist_head(&smb_servers); 15766139Sjb150015 while (sv) { 157711963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 15786139Sjb150015 if (sv->sv_zid == zid) { 15796139Sjb150015 mutex_enter(&sv->sv_mutex); 15806139Sjb150015 if (sv->sv_state != SMB_SERVER_STATE_DELETING) { 15816139Sjb150015 sv->sv_refcnt++; 15826139Sjb150015 mutex_exit(&sv->sv_mutex); 15836139Sjb150015 smb_llist_exit(&smb_servers); 15846139Sjb150015 *psv = sv; 15856139Sjb150015 return (0); 15866139Sjb150015 } 15876139Sjb150015 mutex_exit(&sv->sv_mutex); 15886139Sjb150015 break; 15896139Sjb150015 } 15906139Sjb150015 sv = smb_llist_next(&smb_servers, sv); 15916139Sjb150015 } 15926139Sjb150015 smb_llist_exit(&smb_servers); 15936139Sjb150015 return (EPERM); 15946139Sjb150015 } 15956139Sjb150015 15966139Sjb150015 /* 15976139Sjb150015 * smb_server_release 15986139Sjb150015 * 15996139Sjb150015 * This function decrements the reference count of the server and signals its 16006139Sjb150015 * condition variable if the state of the server is SMB_SERVER_STATE_DELETING. 16016139Sjb150015 */ 16026139Sjb150015 static void 16036139Sjb150015 smb_server_release(smb_server_t *sv) 16046139Sjb150015 { 160511963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 16066139Sjb150015 16076139Sjb150015 mutex_enter(&sv->sv_mutex); 16086139Sjb150015 ASSERT(sv->sv_refcnt); 16096139Sjb150015 sv->sv_refcnt--; 16106139Sjb150015 if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING)) 16116139Sjb150015 cv_signal(&sv->sv_cv); 16126139Sjb150015 mutex_exit(&sv->sv_mutex); 16136139Sjb150015 } 16146139Sjb150015 161510122SJordan.Brown@Sun.COM /* 161610122SJordan.Brown@Sun.COM * Enumerate the users associated with a session list. 161710122SJordan.Brown@Sun.COM */ 161810122SJordan.Brown@Sun.COM static void 161910122SJordan.Brown@Sun.COM smb_server_enum_private(smb_session_list_t *se, smb_svcenum_t *svcenum) 16206139Sjb150015 { 162110122SJordan.Brown@Sun.COM smb_session_t *sn; 162210122SJordan.Brown@Sun.COM smb_llist_t *ulist; 162310122SJordan.Brown@Sun.COM smb_user_t *user; 162410122SJordan.Brown@Sun.COM int rc = 0; 16256139Sjb150015 16266139Sjb150015 rw_enter(&se->se_lock, RW_READER); 16276139Sjb150015 sn = list_head(&se->se_act.lst); 162810122SJordan.Brown@Sun.COM 162910122SJordan.Brown@Sun.COM while (sn != NULL) { 16306139Sjb150015 ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 16316139Sjb150015 ulist = &sn->s_user_list; 16326139Sjb150015 smb_llist_enter(ulist, RW_READER); 16336139Sjb150015 user = smb_llist_head(ulist); 163410122SJordan.Brown@Sun.COM 163510122SJordan.Brown@Sun.COM while (user != NULL) { 163610122SJordan.Brown@Sun.COM if (smb_user_hold(user)) { 163710122SJordan.Brown@Sun.COM rc = smb_user_enum(user, svcenum); 163810122SJordan.Brown@Sun.COM smb_user_release(user); 163910122SJordan.Brown@Sun.COM } 164010122SJordan.Brown@Sun.COM 164110122SJordan.Brown@Sun.COM user = smb_llist_next(ulist, user); 164210122SJordan.Brown@Sun.COM } 164310122SJordan.Brown@Sun.COM 164410122SJordan.Brown@Sun.COM smb_llist_exit(ulist); 164510122SJordan.Brown@Sun.COM 164610122SJordan.Brown@Sun.COM if (rc != 0) 164710122SJordan.Brown@Sun.COM break; 164810122SJordan.Brown@Sun.COM 164910122SJordan.Brown@Sun.COM sn = list_next(&se->se_act.lst, sn); 165010122SJordan.Brown@Sun.COM } 165110122SJordan.Brown@Sun.COM 165210122SJordan.Brown@Sun.COM rw_exit(&se->se_lock); 165310122SJordan.Brown@Sun.COM } 165410122SJordan.Brown@Sun.COM 165510122SJordan.Brown@Sun.COM /* 165610122SJordan.Brown@Sun.COM * Disconnect sessions associated with the specified client and username. 165710122SJordan.Brown@Sun.COM * Empty strings are treated as wildcards. 165810122SJordan.Brown@Sun.COM */ 165910122SJordan.Brown@Sun.COM static int 166010122SJordan.Brown@Sun.COM smb_server_sesion_disconnect(smb_session_list_t *se, 166110122SJordan.Brown@Sun.COM const char *client, const char *name) 166210122SJordan.Brown@Sun.COM { 166310122SJordan.Brown@Sun.COM smb_session_t *sn; 166410122SJordan.Brown@Sun.COM smb_llist_t *ulist; 166510122SJordan.Brown@Sun.COM smb_user_t *user; 166610122SJordan.Brown@Sun.COM boolean_t match; 166710122SJordan.Brown@Sun.COM int count = 0; 166810122SJordan.Brown@Sun.COM 166910122SJordan.Brown@Sun.COM rw_enter(&se->se_lock, RW_READER); 167010122SJordan.Brown@Sun.COM sn = list_head(&se->se_act.lst); 167110122SJordan.Brown@Sun.COM 167210122SJordan.Brown@Sun.COM while (sn != NULL) { 167310122SJordan.Brown@Sun.COM ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 167410122SJordan.Brown@Sun.COM 167510122SJordan.Brown@Sun.COM if ((*client != '\0') && (!smb_session_isclient(sn, client))) { 167610122SJordan.Brown@Sun.COM sn = list_next(&se->se_act.lst, sn); 167710122SJordan.Brown@Sun.COM continue; 167810122SJordan.Brown@Sun.COM } 167910122SJordan.Brown@Sun.COM 168010122SJordan.Brown@Sun.COM ulist = &sn->s_user_list; 168110122SJordan.Brown@Sun.COM smb_llist_enter(ulist, RW_READER); 168210122SJordan.Brown@Sun.COM user = smb_llist_head(ulist); 168310122SJordan.Brown@Sun.COM 168410122SJordan.Brown@Sun.COM while (user != NULL) { 168510122SJordan.Brown@Sun.COM if (smb_user_hold(user)) { 168610122SJordan.Brown@Sun.COM match = (*name == '\0'); 168710122SJordan.Brown@Sun.COM if (!match) 168810122SJordan.Brown@Sun.COM match = smb_user_namecmp(user, name); 168910122SJordan.Brown@Sun.COM 169010122SJordan.Brown@Sun.COM if (match) { 169110122SJordan.Brown@Sun.COM smb_llist_exit(ulist); 169210122SJordan.Brown@Sun.COM smb_user_logoff(user); 169310122SJordan.Brown@Sun.COM ++count; 169410122SJordan.Brown@Sun.COM smb_user_release(user); 169510122SJordan.Brown@Sun.COM smb_llist_enter(ulist, RW_READER); 169610122SJordan.Brown@Sun.COM user = smb_llist_head(ulist); 169710122SJordan.Brown@Sun.COM continue; 16986139Sjb150015 } 169910122SJordan.Brown@Sun.COM 170010122SJordan.Brown@Sun.COM smb_user_release(user); 17016139Sjb150015 } 170210122SJordan.Brown@Sun.COM 17036139Sjb150015 user = smb_llist_next(ulist, user); 17046139Sjb150015 } 170510122SJordan.Brown@Sun.COM 17066139Sjb150015 smb_llist_exit(ulist); 17077961SNatalie.Li@Sun.COM sn = list_next(&se->se_act.lst, sn); 17086139Sjb150015 } 170910122SJordan.Brown@Sun.COM 17106139Sjb150015 rw_exit(&se->se_lock); 171110122SJordan.Brown@Sun.COM return (count); 171210122SJordan.Brown@Sun.COM } 171310122SJordan.Brown@Sun.COM 171410122SJordan.Brown@Sun.COM /* 171510122SJordan.Brown@Sun.COM * Close a file by its unique id. 171610122SJordan.Brown@Sun.COM */ 171710122SJordan.Brown@Sun.COM static int 171810122SJordan.Brown@Sun.COM smb_server_fclose(smb_session_list_t *se, uint32_t uniqid) 171910122SJordan.Brown@Sun.COM { 172010122SJordan.Brown@Sun.COM smb_session_t *sn; 172110122SJordan.Brown@Sun.COM smb_llist_t *ulist; 172210122SJordan.Brown@Sun.COM smb_user_t *user; 172310122SJordan.Brown@Sun.COM int rc = ENOENT; 172410122SJordan.Brown@Sun.COM 172510122SJordan.Brown@Sun.COM rw_enter(&se->se_lock, RW_READER); 172610122SJordan.Brown@Sun.COM sn = list_head(&se->se_act.lst); 172710122SJordan.Brown@Sun.COM 172810122SJordan.Brown@Sun.COM while ((sn != NULL) && (rc == ENOENT)) { 172910122SJordan.Brown@Sun.COM ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 173010122SJordan.Brown@Sun.COM ulist = &sn->s_user_list; 173110122SJordan.Brown@Sun.COM smb_llist_enter(ulist, RW_READER); 173210122SJordan.Brown@Sun.COM user = smb_llist_head(ulist); 173310122SJordan.Brown@Sun.COM 173410122SJordan.Brown@Sun.COM while ((user != NULL) && (rc == ENOENT)) { 173510122SJordan.Brown@Sun.COM if (smb_user_hold(user)) { 173610122SJordan.Brown@Sun.COM rc = smb_user_fclose(user, uniqid); 173710122SJordan.Brown@Sun.COM smb_user_release(user); 173810122SJordan.Brown@Sun.COM } 173910122SJordan.Brown@Sun.COM 174010122SJordan.Brown@Sun.COM user = smb_llist_next(ulist, user); 174110122SJordan.Brown@Sun.COM } 174210122SJordan.Brown@Sun.COM 174310122SJordan.Brown@Sun.COM smb_llist_exit(ulist); 174410122SJordan.Brown@Sun.COM sn = list_next(&se->se_act.lst, sn); 174510122SJordan.Brown@Sun.COM } 174610122SJordan.Brown@Sun.COM 174710122SJordan.Brown@Sun.COM rw_exit(&se->se_lock); 174810122SJordan.Brown@Sun.COM return (rc); 17496139Sjb150015 } 17506139Sjb150015 17516139Sjb150015 static void 17529832Samw@Sun.COM smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc) 17536139Sjb150015 { 17549832Samw@Sun.COM if (ioc->maxconnections == 0) 17559832Samw@Sun.COM ioc->maxconnections = 0xFFFFFFFF; 17566139Sjb150015 17576139Sjb150015 smb_session_correct_keep_alive_values( 17589832Samw@Sun.COM &sv->sv_nbt_daemon.ld_session_list, ioc->keepalive); 17596139Sjb150015 smb_session_correct_keep_alive_values( 17609832Samw@Sun.COM &sv->sv_tcp_daemon.ld_session_list, ioc->keepalive); 17616139Sjb150015 17629832Samw@Sun.COM sv->sv_cfg.skc_maxworkers = ioc->maxworkers; 17639832Samw@Sun.COM sv->sv_cfg.skc_maxconnections = ioc->maxconnections; 17649832Samw@Sun.COM sv->sv_cfg.skc_keepalive = ioc->keepalive; 17659832Samw@Sun.COM sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon; 17669832Samw@Sun.COM sv->sv_cfg.skc_signing_enable = ioc->signing_enable; 17679832Samw@Sun.COM sv->sv_cfg.skc_signing_required = ioc->signing_required; 17689832Samw@Sun.COM sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable; 17699832Samw@Sun.COM sv->sv_cfg.skc_sync_enable = ioc->sync_enable; 17709832Samw@Sun.COM sv->sv_cfg.skc_secmode = ioc->secmode; 17719832Samw@Sun.COM sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable; 1772*12508Samw@Sun.COM sv->sv_cfg.skc_execflags = ioc->exec_flags; 1773*12508Samw@Sun.COM sv->sv_cfg.skc_version = ioc->version; 17749832Samw@Sun.COM (void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain, 17759832Samw@Sun.COM sizeof (sv->sv_cfg.skc_nbdomain)); 17769832Samw@Sun.COM (void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn, 17779832Samw@Sun.COM sizeof (sv->sv_cfg.skc_fqdn)); 17789832Samw@Sun.COM (void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname, 17799832Samw@Sun.COM sizeof (sv->sv_cfg.skc_hostname)); 17809832Samw@Sun.COM (void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment, 17819832Samw@Sun.COM sizeof (sv->sv_cfg.skc_system_comment)); 17826139Sjb150015 } 17836139Sjb150015 17846139Sjb150015 static int 17856139Sjb150015 smb_server_fsop_start(smb_server_t *sv) 17866139Sjb150015 { 17876139Sjb150015 int error; 17886139Sjb150015 17896139Sjb150015 error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node); 17906139Sjb150015 if (error != 0) 17916139Sjb150015 sv->si_root_smb_node = NULL; 17926139Sjb150015 17936139Sjb150015 return (error); 17946139Sjb150015 } 17956139Sjb150015 17966139Sjb150015 static void 17976139Sjb150015 smb_server_fsop_stop(smb_server_t *sv) 17986139Sjb150015 { 17996139Sjb150015 if (sv->si_root_smb_node != NULL) { 18006139Sjb150015 smb_node_release(sv->si_root_smb_node); 18016139Sjb150015 sv->si_root_smb_node = NULL; 18026139Sjb150015 } 18036139Sjb150015 } 180411963SAfshin.Ardakani@Sun.COM 180511963SAfshin.Ardakani@Sun.COM static void 180611963SAfshin.Ardakani@Sun.COM smb_server_signal_listeners(smb_server_t *sv) 180711963SAfshin.Ardakani@Sun.COM { 180811963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 180911963SAfshin.Ardakani@Sun.COM ASSERT(sv->sv_state == SMB_SERVER_STATE_STOPPING); 181011963SAfshin.Ardakani@Sun.COM ASSERT(MUTEX_HELD(&sv->sv_mutex)); 181111963SAfshin.Ardakani@Sun.COM 181211963SAfshin.Ardakani@Sun.COM smb_event_cancel(sv, 0); 181311963SAfshin.Ardakani@Sun.COM 181411963SAfshin.Ardakani@Sun.COM if (sv->sv_nbt_daemon.ld_kth != NULL) { 181511963SAfshin.Ardakani@Sun.COM tsignal(sv->sv_nbt_daemon.ld_kth, SIGINT); 181611963SAfshin.Ardakani@Sun.COM sv->sv_nbt_daemon.ld_kth = NULL; 181711963SAfshin.Ardakani@Sun.COM } 181811963SAfshin.Ardakani@Sun.COM 181911963SAfshin.Ardakani@Sun.COM if (sv->sv_tcp_daemon.ld_kth != NULL) { 182011963SAfshin.Ardakani@Sun.COM tsignal(sv->sv_tcp_daemon.ld_kth, SIGINT); 182111963SAfshin.Ardakani@Sun.COM sv->sv_tcp_daemon.ld_kth = NULL; 182211963SAfshin.Ardakani@Sun.COM } 182311963SAfshin.Ardakani@Sun.COM } 182411963SAfshin.Ardakani@Sun.COM 182511963SAfshin.Ardakani@Sun.COM smb_event_t * 182611963SAfshin.Ardakani@Sun.COM smb_event_create(void) 182711963SAfshin.Ardakani@Sun.COM { 182811963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 182911963SAfshin.Ardakani@Sun.COM smb_event_t *event; 183011963SAfshin.Ardakani@Sun.COM 183111963SAfshin.Ardakani@Sun.COM if (smb_server_is_stopping()) 183211963SAfshin.Ardakani@Sun.COM return (NULL); 183311963SAfshin.Ardakani@Sun.COM 183411963SAfshin.Ardakani@Sun.COM if (smb_server_lookup(&sv) != 0) { 183511963SAfshin.Ardakani@Sun.COM cmn_err(CE_NOTE, "smb_event_create failed"); 183611963SAfshin.Ardakani@Sun.COM return (NULL); 183711963SAfshin.Ardakani@Sun.COM } 183811963SAfshin.Ardakani@Sun.COM 183911963SAfshin.Ardakani@Sun.COM event = kmem_cache_alloc(sv->si_cache_event, KM_SLEEP); 184011963SAfshin.Ardakani@Sun.COM 184111963SAfshin.Ardakani@Sun.COM bzero(event, sizeof (smb_event_t)); 184211963SAfshin.Ardakani@Sun.COM mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL); 184311963SAfshin.Ardakani@Sun.COM cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL); 184411963SAfshin.Ardakani@Sun.COM event->se_magic = SMB_EVENT_MAGIC; 184511963SAfshin.Ardakani@Sun.COM event->se_txid = smb_event_alloc_txid(); 184611963SAfshin.Ardakani@Sun.COM event->se_server = sv; 184711963SAfshin.Ardakani@Sun.COM 184811963SAfshin.Ardakani@Sun.COM smb_llist_enter(&sv->sv_event_list, RW_WRITER); 184911963SAfshin.Ardakani@Sun.COM smb_llist_insert_tail(&sv->sv_event_list, event); 185011963SAfshin.Ardakani@Sun.COM smb_llist_exit(&sv->sv_event_list); 185111963SAfshin.Ardakani@Sun.COM 185211963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 185311963SAfshin.Ardakani@Sun.COM return (event); 185411963SAfshin.Ardakani@Sun.COM } 185511963SAfshin.Ardakani@Sun.COM 185611963SAfshin.Ardakani@Sun.COM void 185711963SAfshin.Ardakani@Sun.COM smb_event_destroy(smb_event_t *event) 185811963SAfshin.Ardakani@Sun.COM { 185911963SAfshin.Ardakani@Sun.COM smb_server_t *sv; 186011963SAfshin.Ardakani@Sun.COM 186111963SAfshin.Ardakani@Sun.COM if (event == NULL) 186211963SAfshin.Ardakani@Sun.COM return; 186311963SAfshin.Ardakani@Sun.COM 186411963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 186511963SAfshin.Ardakani@Sun.COM ASSERT(event->se_waittime == 0); 186611963SAfshin.Ardakani@Sun.COM 186711963SAfshin.Ardakani@Sun.COM if (smb_server_lookup(&sv) != 0) 186811963SAfshin.Ardakani@Sun.COM return; 186911963SAfshin.Ardakani@Sun.COM 187011963SAfshin.Ardakani@Sun.COM smb_llist_enter(&sv->sv_event_list, RW_WRITER); 187111963SAfshin.Ardakani@Sun.COM smb_llist_remove(&sv->sv_event_list, event); 187211963SAfshin.Ardakani@Sun.COM smb_llist_exit(&sv->sv_event_list); 187311963SAfshin.Ardakani@Sun.COM 187411963SAfshin.Ardakani@Sun.COM event->se_magic = (uint32_t)~SMB_EVENT_MAGIC; 187511963SAfshin.Ardakani@Sun.COM cv_destroy(&event->se_cv); 187611963SAfshin.Ardakani@Sun.COM mutex_destroy(&event->se_mutex); 187711963SAfshin.Ardakani@Sun.COM 187811963SAfshin.Ardakani@Sun.COM kmem_cache_free(sv->si_cache_event, event); 187911963SAfshin.Ardakani@Sun.COM smb_server_release(sv); 188011963SAfshin.Ardakani@Sun.COM } 188111963SAfshin.Ardakani@Sun.COM 188211963SAfshin.Ardakani@Sun.COM /* 188311963SAfshin.Ardakani@Sun.COM * Get the txid for the specified event. 188411963SAfshin.Ardakani@Sun.COM */ 188511963SAfshin.Ardakani@Sun.COM uint32_t 188611963SAfshin.Ardakani@Sun.COM smb_event_txid(smb_event_t *event) 188711963SAfshin.Ardakani@Sun.COM { 188811963SAfshin.Ardakani@Sun.COM if (event != NULL) { 188911963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 189011963SAfshin.Ardakani@Sun.COM return (event->se_txid); 189111963SAfshin.Ardakani@Sun.COM } 189211963SAfshin.Ardakani@Sun.COM 189311963SAfshin.Ardakani@Sun.COM cmn_err(CE_NOTE, "smb_event_txid failed"); 189411963SAfshin.Ardakani@Sun.COM return ((uint32_t)-1); 189511963SAfshin.Ardakani@Sun.COM } 189611963SAfshin.Ardakani@Sun.COM 189711963SAfshin.Ardakani@Sun.COM /* 189811963SAfshin.Ardakani@Sun.COM * Wait for event notification. 189911963SAfshin.Ardakani@Sun.COM */ 190011963SAfshin.Ardakani@Sun.COM int 190111963SAfshin.Ardakani@Sun.COM smb_event_wait(smb_event_t *event) 190211963SAfshin.Ardakani@Sun.COM { 190311963SAfshin.Ardakani@Sun.COM int seconds = 1; 190411963SAfshin.Ardakani@Sun.COM int ticks; 190511963SAfshin.Ardakani@Sun.COM 190611963SAfshin.Ardakani@Sun.COM if (event == NULL) 190711963SAfshin.Ardakani@Sun.COM return (EINVAL); 190811963SAfshin.Ardakani@Sun.COM 190911963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 191011963SAfshin.Ardakani@Sun.COM 191111963SAfshin.Ardakani@Sun.COM mutex_enter(&event->se_mutex); 191211963SAfshin.Ardakani@Sun.COM event->se_waittime = 1; 191311963SAfshin.Ardakani@Sun.COM event->se_errno = 0; 191411963SAfshin.Ardakani@Sun.COM 191511963SAfshin.Ardakani@Sun.COM while (!(event->se_notified)) { 191612065SKeyur.Desai@Sun.COM if (smb_event_debug && ((event->se_waittime % 30) == 0)) 191711963SAfshin.Ardakani@Sun.COM cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)", 191811963SAfshin.Ardakani@Sun.COM event->se_txid, event->se_waittime); 191911963SAfshin.Ardakani@Sun.COM 192011963SAfshin.Ardakani@Sun.COM if (event->se_errno != 0) 192111963SAfshin.Ardakani@Sun.COM break; 192211963SAfshin.Ardakani@Sun.COM 192311963SAfshin.Ardakani@Sun.COM if (event->se_waittime > SMB_EVENT_TIMEOUT) { 192411963SAfshin.Ardakani@Sun.COM event->se_errno = ETIME; 192511963SAfshin.Ardakani@Sun.COM break; 192611963SAfshin.Ardakani@Sun.COM } 192711963SAfshin.Ardakani@Sun.COM 192811963SAfshin.Ardakani@Sun.COM ticks = SEC_TO_TICK(seconds); 192911963SAfshin.Ardakani@Sun.COM (void) cv_reltimedwait(&event->se_cv, 193011963SAfshin.Ardakani@Sun.COM &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK); 193111963SAfshin.Ardakani@Sun.COM ++event->se_waittime; 193211963SAfshin.Ardakani@Sun.COM } 193311963SAfshin.Ardakani@Sun.COM 193411963SAfshin.Ardakani@Sun.COM event->se_waittime = 0; 193511963SAfshin.Ardakani@Sun.COM event->se_notified = B_FALSE; 193611963SAfshin.Ardakani@Sun.COM cv_signal(&event->se_cv); 193711963SAfshin.Ardakani@Sun.COM mutex_exit(&event->se_mutex); 193811963SAfshin.Ardakani@Sun.COM return (event->se_errno); 193911963SAfshin.Ardakani@Sun.COM } 194011963SAfshin.Ardakani@Sun.COM 194111963SAfshin.Ardakani@Sun.COM /* 194211963SAfshin.Ardakani@Sun.COM * If txid is non-zero, cancel the specified event. 194311963SAfshin.Ardakani@Sun.COM * Otherwise, cancel all events. 194411963SAfshin.Ardakani@Sun.COM */ 194511963SAfshin.Ardakani@Sun.COM static void 194611963SAfshin.Ardakani@Sun.COM smb_event_cancel(smb_server_t *sv, uint32_t txid) 194711963SAfshin.Ardakani@Sun.COM { 194811963SAfshin.Ardakani@Sun.COM smb_event_t *event; 194911963SAfshin.Ardakani@Sun.COM smb_llist_t *event_list; 195011963SAfshin.Ardakani@Sun.COM 195111963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 195211963SAfshin.Ardakani@Sun.COM 195311963SAfshin.Ardakani@Sun.COM event_list = &sv->sv_event_list; 195411963SAfshin.Ardakani@Sun.COM smb_llist_enter(event_list, RW_WRITER); 195511963SAfshin.Ardakani@Sun.COM 195611963SAfshin.Ardakani@Sun.COM event = smb_llist_head(event_list); 195711963SAfshin.Ardakani@Sun.COM while (event) { 195811963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 195911963SAfshin.Ardakani@Sun.COM 196011963SAfshin.Ardakani@Sun.COM if (txid == 0 || event->se_txid == txid) { 196111963SAfshin.Ardakani@Sun.COM mutex_enter(&event->se_mutex); 196211963SAfshin.Ardakani@Sun.COM event->se_errno = ECANCELED; 196311963SAfshin.Ardakani@Sun.COM event->se_notified = B_TRUE; 196411963SAfshin.Ardakani@Sun.COM cv_signal(&event->se_cv); 196511963SAfshin.Ardakani@Sun.COM mutex_exit(&event->se_mutex); 196611963SAfshin.Ardakani@Sun.COM 196711963SAfshin.Ardakani@Sun.COM if (txid != 0) 196811963SAfshin.Ardakani@Sun.COM break; 196911963SAfshin.Ardakani@Sun.COM } 197011963SAfshin.Ardakani@Sun.COM 197111963SAfshin.Ardakani@Sun.COM event = smb_llist_next(event_list, event); 197211963SAfshin.Ardakani@Sun.COM } 197311963SAfshin.Ardakani@Sun.COM 197411963SAfshin.Ardakani@Sun.COM smb_llist_exit(event_list); 197511963SAfshin.Ardakani@Sun.COM } 197611963SAfshin.Ardakani@Sun.COM 197711963SAfshin.Ardakani@Sun.COM /* 197811963SAfshin.Ardakani@Sun.COM * If txid is non-zero, notify the specified event. 197911963SAfshin.Ardakani@Sun.COM * Otherwise, notify all events. 198011963SAfshin.Ardakani@Sun.COM */ 198111963SAfshin.Ardakani@Sun.COM static void 198211963SAfshin.Ardakani@Sun.COM smb_event_notify(smb_server_t *sv, uint32_t txid) 198311963SAfshin.Ardakani@Sun.COM { 198411963SAfshin.Ardakani@Sun.COM smb_event_t *event; 198511963SAfshin.Ardakani@Sun.COM smb_llist_t *event_list; 198611963SAfshin.Ardakani@Sun.COM 198711963SAfshin.Ardakani@Sun.COM SMB_SERVER_VALID(sv); 198811963SAfshin.Ardakani@Sun.COM 198911963SAfshin.Ardakani@Sun.COM event_list = &sv->sv_event_list; 199011963SAfshin.Ardakani@Sun.COM smb_llist_enter(event_list, RW_READER); 199111963SAfshin.Ardakani@Sun.COM 199211963SAfshin.Ardakani@Sun.COM event = smb_llist_head(event_list); 199311963SAfshin.Ardakani@Sun.COM while (event) { 199411963SAfshin.Ardakani@Sun.COM SMB_EVENT_VALID(event); 199511963SAfshin.Ardakani@Sun.COM 199611963SAfshin.Ardakani@Sun.COM if (txid == 0 || event->se_txid == txid) { 199711963SAfshin.Ardakani@Sun.COM mutex_enter(&event->se_mutex); 199811963SAfshin.Ardakani@Sun.COM event->se_notified = B_TRUE; 199911963SAfshin.Ardakani@Sun.COM cv_signal(&event->se_cv); 200011963SAfshin.Ardakani@Sun.COM mutex_exit(&event->se_mutex); 200111963SAfshin.Ardakani@Sun.COM 200211963SAfshin.Ardakani@Sun.COM if (txid != 0) 200311963SAfshin.Ardakani@Sun.COM break; 200411963SAfshin.Ardakani@Sun.COM } 200511963SAfshin.Ardakani@Sun.COM 200611963SAfshin.Ardakani@Sun.COM event = smb_llist_next(event_list, event); 200711963SAfshin.Ardakani@Sun.COM } 200811963SAfshin.Ardakani@Sun.COM 200911963SAfshin.Ardakani@Sun.COM smb_llist_exit(event_list); 201011963SAfshin.Ardakani@Sun.COM } 201111963SAfshin.Ardakani@Sun.COM 201211963SAfshin.Ardakani@Sun.COM /* 201311963SAfshin.Ardakani@Sun.COM * Allocate a new transaction id (txid). 201411963SAfshin.Ardakani@Sun.COM * 201511963SAfshin.Ardakani@Sun.COM * 0 or -1 are not assigned because they are used to detect invalid 201611963SAfshin.Ardakani@Sun.COM * conditions or to indicate all open id's. 201711963SAfshin.Ardakani@Sun.COM */ 201811963SAfshin.Ardakani@Sun.COM static uint32_t 201911963SAfshin.Ardakani@Sun.COM smb_event_alloc_txid(void) 202011963SAfshin.Ardakani@Sun.COM { 202111963SAfshin.Ardakani@Sun.COM static kmutex_t txmutex; 202211963SAfshin.Ardakani@Sun.COM static uint32_t txid; 202311963SAfshin.Ardakani@Sun.COM uint32_t txid_ret; 202411963SAfshin.Ardakani@Sun.COM 202511963SAfshin.Ardakani@Sun.COM mutex_enter(&txmutex); 202611963SAfshin.Ardakani@Sun.COM 202711963SAfshin.Ardakani@Sun.COM if (txid == 0) 202811963SAfshin.Ardakani@Sun.COM txid = ddi_get_lbolt() << 11; 202911963SAfshin.Ardakani@Sun.COM 203011963SAfshin.Ardakani@Sun.COM do { 203111963SAfshin.Ardakani@Sun.COM ++txid; 203211963SAfshin.Ardakani@Sun.COM } while (txid == 0 || txid == (uint32_t)-1); 203311963SAfshin.Ardakani@Sun.COM 203411963SAfshin.Ardakani@Sun.COM txid_ret = txid; 203511963SAfshin.Ardakani@Sun.COM mutex_exit(&txmutex); 203611963SAfshin.Ardakani@Sun.COM 203711963SAfshin.Ardakani@Sun.COM return (txid_ret); 203811963SAfshin.Ardakani@Sun.COM } 2039