1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22*a0aa776eSAlan Wright * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * Main startup code for SMB/NETBIOS and some utility routines 28da6c28aaSamw * for the NETBIOS layer. 29da6c28aaSamw */ 30da6c28aaSamw 31*a0aa776eSAlan Wright #include <sys/tzfile.h> 32*a0aa776eSAlan Wright #include <assert.h> 33da6c28aaSamw #include <synch.h> 34da6c28aaSamw #include <unistd.h> 35da6c28aaSamw #include <syslog.h> 36da6c28aaSamw #include <string.h> 37da6c28aaSamw #include <strings.h> 38da6c28aaSamw #include <sys/socket.h> 39*a0aa776eSAlan Wright #include <stdio.h> 40*a0aa776eSAlan Wright #include <pwd.h> 41*a0aa776eSAlan Wright #include <grp.h> 42da6c28aaSamw #include <smbns_netbios.h> 43da6c28aaSamw 44*a0aa776eSAlan Wright #define SMB_NETBIOS_DUMP_FILE "netbios" 45da6c28aaSamw 46*a0aa776eSAlan Wright static netbios_service_t nbtd; 47da6c28aaSamw 48*a0aa776eSAlan Wright static void smb_netbios_shutdown(void); 49*a0aa776eSAlan Wright static void *smb_netbios_service(void *); 50*a0aa776eSAlan Wright static void smb_netbios_dump(void); 51da6c28aaSamw 52*a0aa776eSAlan Wright /* 53*a0aa776eSAlan Wright * Start the NetBIOS services 54*a0aa776eSAlan Wright */ 55*a0aa776eSAlan Wright int 56*a0aa776eSAlan Wright smb_netbios_start(void) 57da6c28aaSamw { 58*a0aa776eSAlan Wright pthread_t tid; 59*a0aa776eSAlan Wright pthread_attr_t attr; 60*a0aa776eSAlan Wright int rc; 61*a0aa776eSAlan Wright 62*a0aa776eSAlan Wright if (smb_netbios_cache_init() < 0) 63*a0aa776eSAlan Wright return (-1); 64*a0aa776eSAlan Wright 65*a0aa776eSAlan Wright (void) pthread_attr_init(&attr); 66*a0aa776eSAlan Wright (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 67*a0aa776eSAlan Wright rc = pthread_create(&tid, &attr, smb_netbios_service, NULL); 68*a0aa776eSAlan Wright (void) pthread_attr_destroy(&attr); 69*a0aa776eSAlan Wright return (rc); 70da6c28aaSamw } 71da6c28aaSamw 72*a0aa776eSAlan Wright /* 73*a0aa776eSAlan Wright * Stop the NetBIOS services 74*a0aa776eSAlan Wright */ 75da6c28aaSamw void 76*a0aa776eSAlan Wright smb_netbios_stop(void) 77da6c28aaSamw { 78*a0aa776eSAlan Wright char fname[MAXPATHLEN]; 79da6c28aaSamw 80*a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_STOP); 81*a0aa776eSAlan Wright 82*a0aa776eSAlan Wright (void) snprintf(fname, MAXPATHLEN, "%s/%s", 83*a0aa776eSAlan Wright SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE); 84*a0aa776eSAlan Wright (void) unlink(fname); 85da6c28aaSamw 86da6c28aaSamw } 87da6c28aaSamw 88*a0aa776eSAlan Wright /* 89*a0aa776eSAlan Wright * Launch the NetBIOS Name Service, Datagram and Browser services 90*a0aa776eSAlan Wright * and then sit in a loop providing a 1 second resolution timer. 91*a0aa776eSAlan Wright * The timer will: 92*a0aa776eSAlan Wright * - update the netbios stats file every 10 minutes 93*a0aa776eSAlan Wright * - clean the cache every 10 minutes 94*a0aa776eSAlan Wright */ 95*a0aa776eSAlan Wright /*ARGSUSED*/ 96*a0aa776eSAlan Wright static void * 97*a0aa776eSAlan Wright smb_netbios_service(void *arg) 98da6c28aaSamw { 99*a0aa776eSAlan Wright static uint32_t ticks = 0; 100*a0aa776eSAlan Wright pthread_t tid; 101*a0aa776eSAlan Wright int rc; 102da6c28aaSamw 103*a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_START); 104da6c28aaSamw 105*a0aa776eSAlan Wright rc = pthread_create(&tid, NULL, smb_netbios_name_service, NULL); 106*a0aa776eSAlan Wright if (rc != 0) { 107*a0aa776eSAlan Wright smb_netbios_shutdown(); 108*a0aa776eSAlan Wright return (NULL); 109da6c28aaSamw } 110da6c28aaSamw 111*a0aa776eSAlan Wright smb_netbios_wait(NETBIOS_EVENT_NS_START); 112*a0aa776eSAlan Wright if (smb_netbios_error()) { 113da6c28aaSamw smb_netbios_shutdown(); 114*a0aa776eSAlan Wright return (NULL); 115da6c28aaSamw } 116da6c28aaSamw 117da6c28aaSamw smb_netbios_name_config(); 118da6c28aaSamw 119*a0aa776eSAlan Wright rc = pthread_create(&tid, NULL, smb_netbios_datagram_service, NULL); 120dc20a302Sas if (rc != 0) { 121dc20a302Sas smb_netbios_shutdown(); 122*a0aa776eSAlan Wright return (NULL); 123da6c28aaSamw } 124da6c28aaSamw 125*a0aa776eSAlan Wright smb_netbios_wait(NETBIOS_EVENT_DGM_START); 126*a0aa776eSAlan Wright if (smb_netbios_error()) { 127da6c28aaSamw smb_netbios_shutdown(); 128*a0aa776eSAlan Wright return (NULL); 129da6c28aaSamw } 130da6c28aaSamw 131*a0aa776eSAlan Wright rc = pthread_create(&tid, NULL, smb_browser_service, NULL); 132dc20a302Sas if (rc != 0) { 133dc20a302Sas smb_netbios_shutdown(); 134*a0aa776eSAlan Wright return (NULL); 135dc20a302Sas } 136da6c28aaSamw 137*a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_TIMER_START); 138dc20a302Sas 139*a0aa776eSAlan Wright for (;;) { 140da6c28aaSamw (void) sleep(1); 1417b59d02dSjb ticks++; 142da6c28aaSamw 143*a0aa776eSAlan Wright if (!smb_netbios_running()) 144da6c28aaSamw break; 1457b59d02dSjb 1467b59d02dSjb smb_netbios_datagram_tick(); 1477b59d02dSjb smb_netbios_name_tick(); 1487b59d02dSjb 149*a0aa776eSAlan Wright if ((ticks % 600) == 0) { 150*a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_DUMP); 1517b59d02dSjb smb_netbios_cache_clean(); 152*a0aa776eSAlan Wright } 153da6c28aaSamw } 154da6c28aaSamw 155*a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_TIMER_STOP); 156*a0aa776eSAlan Wright smb_netbios_shutdown(); 157*a0aa776eSAlan Wright return (NULL); 158*a0aa776eSAlan Wright } 159*a0aa776eSAlan Wright 160*a0aa776eSAlan Wright static void 161*a0aa776eSAlan Wright smb_netbios_shutdown(void) 162*a0aa776eSAlan Wright { 163*a0aa776eSAlan Wright (void) pthread_join(nbtd.nbs_browser.s_tid, 0); 164*a0aa776eSAlan Wright (void) pthread_join(nbtd.nbs_dgm.s_tid, 0); 165*a0aa776eSAlan Wright (void) pthread_join(nbtd.nbs_ns.s_tid, 0); 166da6c28aaSamw 167*a0aa776eSAlan Wright nbtd.nbs_browser.s_tid = 0; 168*a0aa776eSAlan Wright nbtd.nbs_dgm.s_tid = 0; 169*a0aa776eSAlan Wright nbtd.nbs_ns.s_tid = 0; 170*a0aa776eSAlan Wright 171*a0aa776eSAlan Wright smb_netbios_cache_fini(); 172*a0aa776eSAlan Wright 173*a0aa776eSAlan Wright if (smb_netbios_error()) { 174*a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_RESET); 175*a0aa776eSAlan Wright if (smb_netbios_start() != 0) 176*a0aa776eSAlan Wright syslog(LOG_ERR, "netbios: restart failed"); 177*a0aa776eSAlan Wright } 178da6c28aaSamw } 179da6c28aaSamw 180da6c28aaSamw int 181da6c28aaSamw smb_first_level_name_encode(struct name_entry *name, 182da6c28aaSamw unsigned char *out, int max_out) 183da6c28aaSamw { 184da6c28aaSamw return (netbios_first_level_name_encode(name->name, name->scope, 185da6c28aaSamw out, max_out)); 186da6c28aaSamw } 187da6c28aaSamw 188da6c28aaSamw int 189da6c28aaSamw smb_first_level_name_decode(unsigned char *in, struct name_entry *name) 190da6c28aaSamw { 191da6c28aaSamw return (netbios_first_level_name_decode((char *)in, (char *)name->name, 192da6c28aaSamw (char *)name->scope)); 193da6c28aaSamw } 194da6c28aaSamw 195da6c28aaSamw /* 196da6c28aaSamw * smb_encode_netbios_name 197da6c28aaSamw * 198da6c28aaSamw * Set up the name and scope fields in the destination name_entry structure. 199da6c28aaSamw * The name is padded with spaces to 15 bytes. The suffix is copied into the 200da6c28aaSamw * last byte, i.e. "netbiosname <suffix>". The scope is copied and folded 201da6c28aaSamw * to uppercase. 202da6c28aaSamw */ 203da6c28aaSamw void 204da6c28aaSamw smb_encode_netbios_name(unsigned char *name, char suffix, unsigned char *scope, 205da6c28aaSamw struct name_entry *dest) 206da6c28aaSamw { 2077b59d02dSjb smb_tonetbiosname((char *)name, (char *)dest->name, suffix); 208da6c28aaSamw 2097b59d02dSjb if (scope) { 210da6c28aaSamw (void) strlcpy((char *)dest->scope, (const char *)scope, 2117b59d02dSjb sizeof (dest->scope)); 2127b59d02dSjb } else { 2137b59d02dSjb (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)dest->scope, 2147b59d02dSjb sizeof (dest->scope)); 215da6c28aaSamw } 2167b59d02dSjb 217da6c28aaSamw (void) utf8_strupr((char *)dest->scope); 218da6c28aaSamw } 219da6c28aaSamw 220da6c28aaSamw void 221da6c28aaSamw smb_init_name_struct(unsigned char *name, char suffix, unsigned char *scope, 222da6c28aaSamw uint32_t ipaddr, unsigned short port, uint32_t attr, 223da6c28aaSamw uint32_t addr_attr, struct name_entry *dest) 224da6c28aaSamw { 225da6c28aaSamw bzero(dest, sizeof (struct name_entry)); 226da6c28aaSamw smb_encode_netbios_name(name, suffix, scope, dest); 227da6c28aaSamw 228da6c28aaSamw switch (smb_node_type) { 229da6c28aaSamw case 'H': 230da6c28aaSamw dest->attributes = attr | NAME_ATTR_OWNER_TYPE_HNODE; 231da6c28aaSamw break; 232da6c28aaSamw case 'M': 233da6c28aaSamw dest->attributes = attr | NAME_ATTR_OWNER_TYPE_MNODE; 234da6c28aaSamw break; 235da6c28aaSamw case 'P': 236da6c28aaSamw dest->attributes = attr | NAME_ATTR_OWNER_TYPE_PNODE; 237da6c28aaSamw break; 238da6c28aaSamw case 'B': 239da6c28aaSamw default: 240da6c28aaSamw dest->attributes = attr | NAME_ATTR_OWNER_TYPE_BNODE; 241da6c28aaSamw break; 242da6c28aaSamw } 243da6c28aaSamw 244da6c28aaSamw dest->addr_list.refresh_ttl = dest->addr_list.ttl = 245da6c28aaSamw TO_SECONDS(DEFAULT_TTL); 246da6c28aaSamw 247da6c28aaSamw dest->addr_list.sin.sin_family = AF_INET; 248da6c28aaSamw dest->addr_list.sinlen = sizeof (dest->addr_list.sin); 249da6c28aaSamw dest->addr_list.sin.sin_addr.s_addr = ipaddr; 250da6c28aaSamw dest->addr_list.sin.sin_port = port; 251da6c28aaSamw dest->addr_list.attributes = addr_attr; 252da6c28aaSamw dest->addr_list.forw = dest->addr_list.back = &dest->addr_list; 253da6c28aaSamw } 254*a0aa776eSAlan Wright 255*a0aa776eSAlan Wright void 256*a0aa776eSAlan Wright smb_netbios_event(netbios_event_t event) 257*a0aa776eSAlan Wright { 258*a0aa776eSAlan Wright static char *event_msg[] = { 259*a0aa776eSAlan Wright "startup", 260*a0aa776eSAlan Wright "shutdown", 261*a0aa776eSAlan Wright "restart", 262*a0aa776eSAlan Wright "name service started", 263*a0aa776eSAlan Wright "name service stopped", 264*a0aa776eSAlan Wright "datagram service started", 265*a0aa776eSAlan Wright "datagram service stopped", 266*a0aa776eSAlan Wright "browser service started", 267*a0aa776eSAlan Wright "browser service stopped", 268*a0aa776eSAlan Wright "timer service started", 269*a0aa776eSAlan Wright "timer service stopped", 270*a0aa776eSAlan Wright "error", 271*a0aa776eSAlan Wright "dump" 272*a0aa776eSAlan Wright }; 273*a0aa776eSAlan Wright 274*a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx); 275*a0aa776eSAlan Wright 276*a0aa776eSAlan Wright if (event == NETBIOS_EVENT_DUMP) { 277*a0aa776eSAlan Wright if (nbtd.nbs_last_event == NULL) 278*a0aa776eSAlan Wright nbtd.nbs_last_event = event_msg[event]; 279*a0aa776eSAlan Wright smb_netbios_dump(); 280*a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx); 281*a0aa776eSAlan Wright return; 282*a0aa776eSAlan Wright } 283*a0aa776eSAlan Wright 284*a0aa776eSAlan Wright nbtd.nbs_last_event = event_msg[event]; 285*a0aa776eSAlan Wright syslog(LOG_DEBUG, "netbios: %s", nbtd.nbs_last_event); 286*a0aa776eSAlan Wright 287*a0aa776eSAlan Wright switch (nbtd.nbs_state) { 288*a0aa776eSAlan Wright case NETBIOS_STATE_INIT: 289*a0aa776eSAlan Wright if (event == NETBIOS_EVENT_START) 290*a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_RUNNING; 291*a0aa776eSAlan Wright break; 292*a0aa776eSAlan Wright 293*a0aa776eSAlan Wright case NETBIOS_STATE_RUNNING: 294*a0aa776eSAlan Wright switch (event) { 295*a0aa776eSAlan Wright case NETBIOS_EVENT_NS_START: 296*a0aa776eSAlan Wright nbtd.nbs_ns.s_tid = pthread_self(); 297*a0aa776eSAlan Wright nbtd.nbs_ns.s_up = B_TRUE; 298*a0aa776eSAlan Wright break; 299*a0aa776eSAlan Wright case NETBIOS_EVENT_NS_STOP: 300*a0aa776eSAlan Wright nbtd.nbs_ns.s_up = B_FALSE; 301*a0aa776eSAlan Wright break; 302*a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_START: 303*a0aa776eSAlan Wright nbtd.nbs_dgm.s_tid = pthread_self(); 304*a0aa776eSAlan Wright nbtd.nbs_dgm.s_up = B_TRUE; 305*a0aa776eSAlan Wright break; 306*a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_STOP: 307*a0aa776eSAlan Wright nbtd.nbs_dgm.s_up = B_FALSE; 308*a0aa776eSAlan Wright break; 309*a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_START: 310*a0aa776eSAlan Wright nbtd.nbs_browser.s_tid = pthread_self(); 311*a0aa776eSAlan Wright nbtd.nbs_browser.s_up = B_TRUE; 312*a0aa776eSAlan Wright break; 313*a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_STOP: 314*a0aa776eSAlan Wright nbtd.nbs_browser.s_up = B_FALSE; 315*a0aa776eSAlan Wright break; 316*a0aa776eSAlan Wright case NETBIOS_EVENT_TIMER_START: 317*a0aa776eSAlan Wright nbtd.nbs_timer.s_tid = pthread_self(); 318*a0aa776eSAlan Wright nbtd.nbs_timer.s_up = B_TRUE; 319*a0aa776eSAlan Wright break; 320*a0aa776eSAlan Wright case NETBIOS_EVENT_TIMER_STOP: 321*a0aa776eSAlan Wright nbtd.nbs_timer.s_up = B_FALSE; 322*a0aa776eSAlan Wright break; 323*a0aa776eSAlan Wright case NETBIOS_EVENT_STOP: 324*a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_CLOSING; 325*a0aa776eSAlan Wright break; 326*a0aa776eSAlan Wright case NETBIOS_EVENT_ERROR: 327*a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_ERROR; 328*a0aa776eSAlan Wright ++nbtd.nbs_errors; 329*a0aa776eSAlan Wright break; 330*a0aa776eSAlan Wright default: 331*a0aa776eSAlan Wright break; 332*a0aa776eSAlan Wright } 333*a0aa776eSAlan Wright break; 334*a0aa776eSAlan Wright 335*a0aa776eSAlan Wright case NETBIOS_STATE_CLOSING: 336*a0aa776eSAlan Wright case NETBIOS_STATE_ERROR: 337*a0aa776eSAlan Wright default: 338*a0aa776eSAlan Wright switch (event) { 339*a0aa776eSAlan Wright case NETBIOS_EVENT_NS_STOP: 340*a0aa776eSAlan Wright nbtd.nbs_ns.s_up = B_FALSE; 341*a0aa776eSAlan Wright break; 342*a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_STOP: 343*a0aa776eSAlan Wright nbtd.nbs_dgm.s_up = B_FALSE; 344*a0aa776eSAlan Wright break; 345*a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_STOP: 346*a0aa776eSAlan Wright nbtd.nbs_browser.s_up = B_FALSE; 347*a0aa776eSAlan Wright break; 348*a0aa776eSAlan Wright case NETBIOS_EVENT_TIMER_STOP: 349*a0aa776eSAlan Wright nbtd.nbs_timer.s_up = B_FALSE; 350*a0aa776eSAlan Wright break; 351*a0aa776eSAlan Wright case NETBIOS_EVENT_STOP: 352*a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_CLOSING; 353*a0aa776eSAlan Wright break; 354*a0aa776eSAlan Wright case NETBIOS_EVENT_RESET: 355*a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_INIT; 356*a0aa776eSAlan Wright break; 357*a0aa776eSAlan Wright case NETBIOS_EVENT_ERROR: 358*a0aa776eSAlan Wright ++nbtd.nbs_errors; 359*a0aa776eSAlan Wright break; 360*a0aa776eSAlan Wright default: 361*a0aa776eSAlan Wright break; 362*a0aa776eSAlan Wright } 363*a0aa776eSAlan Wright break; 364*a0aa776eSAlan Wright } 365*a0aa776eSAlan Wright 366*a0aa776eSAlan Wright smb_netbios_dump(); 367*a0aa776eSAlan Wright (void) cond_broadcast(&nbtd.nbs_cv); 368*a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx); 369*a0aa776eSAlan Wright } 370*a0aa776eSAlan Wright 371*a0aa776eSAlan Wright void 372*a0aa776eSAlan Wright smb_netbios_wait(netbios_event_t event) 373*a0aa776eSAlan Wright { 374*a0aa776eSAlan Wright boolean_t *svc = NULL; 375*a0aa776eSAlan Wright boolean_t desired_state; 376*a0aa776eSAlan Wright 377*a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx); 378*a0aa776eSAlan Wright 379*a0aa776eSAlan Wright switch (event) { 380*a0aa776eSAlan Wright case NETBIOS_EVENT_NS_START: 381*a0aa776eSAlan Wright case NETBIOS_EVENT_NS_STOP: 382*a0aa776eSAlan Wright svc = &nbtd.nbs_ns.s_up; 383*a0aa776eSAlan Wright desired_state = 384*a0aa776eSAlan Wright (event == NETBIOS_EVENT_NS_START) ? B_TRUE : B_FALSE; 385*a0aa776eSAlan Wright break; 386*a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_START: 387*a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_STOP: 388*a0aa776eSAlan Wright svc = &nbtd.nbs_dgm.s_up; 389*a0aa776eSAlan Wright desired_state = 390*a0aa776eSAlan Wright (event == NETBIOS_EVENT_DGM_START) ? B_TRUE : B_FALSE; 391*a0aa776eSAlan Wright break; 392*a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_START: 393*a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_STOP: 394*a0aa776eSAlan Wright svc = &nbtd.nbs_browser.s_up; 395*a0aa776eSAlan Wright desired_state = 396*a0aa776eSAlan Wright (event == NETBIOS_EVENT_BROWSER_START) ? B_TRUE : B_FALSE; 397*a0aa776eSAlan Wright break; 398*a0aa776eSAlan Wright default: 399*a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx); 400*a0aa776eSAlan Wright return; 401*a0aa776eSAlan Wright } 402*a0aa776eSAlan Wright 403*a0aa776eSAlan Wright while (*svc != desired_state) { 404*a0aa776eSAlan Wright if (nbtd.nbs_state != NETBIOS_STATE_RUNNING) 405*a0aa776eSAlan Wright break; 406*a0aa776eSAlan Wright 407*a0aa776eSAlan Wright (void) cond_wait(&nbtd.nbs_cv, &nbtd.nbs_mtx); 408*a0aa776eSAlan Wright } 409*a0aa776eSAlan Wright 410*a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx); 411*a0aa776eSAlan Wright } 412*a0aa776eSAlan Wright 413*a0aa776eSAlan Wright void 414*a0aa776eSAlan Wright smb_netbios_sleep(time_t seconds) 415*a0aa776eSAlan Wright { 416*a0aa776eSAlan Wright timestruc_t reltimeout; 417*a0aa776eSAlan Wright 418*a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx); 419*a0aa776eSAlan Wright 420*a0aa776eSAlan Wright if (nbtd.nbs_state == NETBIOS_STATE_RUNNING) { 421*a0aa776eSAlan Wright if (seconds == 0) 422*a0aa776eSAlan Wright seconds = 1; 423*a0aa776eSAlan Wright reltimeout.tv_sec = seconds; 424*a0aa776eSAlan Wright reltimeout.tv_nsec = 0; 425*a0aa776eSAlan Wright 426*a0aa776eSAlan Wright (void) cond_reltimedwait(&nbtd.nbs_cv, 427*a0aa776eSAlan Wright &nbtd.nbs_mtx, &reltimeout); 428*a0aa776eSAlan Wright } 429*a0aa776eSAlan Wright 430*a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx); 431*a0aa776eSAlan Wright } 432*a0aa776eSAlan Wright 433*a0aa776eSAlan Wright boolean_t 434*a0aa776eSAlan Wright smb_netbios_running(void) 435*a0aa776eSAlan Wright { 436*a0aa776eSAlan Wright boolean_t is_running; 437*a0aa776eSAlan Wright 438*a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx); 439*a0aa776eSAlan Wright 440*a0aa776eSAlan Wright if (nbtd.nbs_state == NETBIOS_STATE_RUNNING) 441*a0aa776eSAlan Wright is_running = B_TRUE; 442*a0aa776eSAlan Wright else 443*a0aa776eSAlan Wright is_running = B_FALSE; 444*a0aa776eSAlan Wright 445*a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx); 446*a0aa776eSAlan Wright return (is_running); 447*a0aa776eSAlan Wright } 448*a0aa776eSAlan Wright 449*a0aa776eSAlan Wright boolean_t 450*a0aa776eSAlan Wright smb_netbios_error(void) 451*a0aa776eSAlan Wright { 452*a0aa776eSAlan Wright boolean_t error; 453*a0aa776eSAlan Wright 454*a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx); 455*a0aa776eSAlan Wright 456*a0aa776eSAlan Wright if (nbtd.nbs_state == NETBIOS_STATE_ERROR) 457*a0aa776eSAlan Wright error = B_TRUE; 458*a0aa776eSAlan Wright else 459*a0aa776eSAlan Wright error = B_FALSE; 460*a0aa776eSAlan Wright 461*a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx); 462*a0aa776eSAlan Wright return (error); 463*a0aa776eSAlan Wright } 464*a0aa776eSAlan Wright 465*a0aa776eSAlan Wright /* 466*a0aa776eSAlan Wright * Write the service state to /var/run/smb/netbios. 467*a0aa776eSAlan Wright * 468*a0aa776eSAlan Wright * This is a private interface. To update the file use: 469*a0aa776eSAlan Wright * smb_netbios_event(NETBIOS_EVENT_DUMP); 470*a0aa776eSAlan Wright */ 471*a0aa776eSAlan Wright static void 472*a0aa776eSAlan Wright smb_netbios_dump(void) 473*a0aa776eSAlan Wright { 474*a0aa776eSAlan Wright static struct { 475*a0aa776eSAlan Wright netbios_state_t state; 476*a0aa776eSAlan Wright char *text; 477*a0aa776eSAlan Wright } sm[] = { 478*a0aa776eSAlan Wright { NETBIOS_STATE_INIT, "init" }, 479*a0aa776eSAlan Wright { NETBIOS_STATE_RUNNING, "running" }, 480*a0aa776eSAlan Wright { NETBIOS_STATE_CLOSING, "closing" }, 481*a0aa776eSAlan Wright { NETBIOS_STATE_ERROR, "error" } 482*a0aa776eSAlan Wright }; 483*a0aa776eSAlan Wright 484*a0aa776eSAlan Wright char fname[MAXPATHLEN]; 485*a0aa776eSAlan Wright FILE *fp; 486*a0aa776eSAlan Wright struct passwd *pwd; 487*a0aa776eSAlan Wright struct group *grp; 488*a0aa776eSAlan Wright uid_t uid; 489*a0aa776eSAlan Wright gid_t gid; 490*a0aa776eSAlan Wright char *last_event = "none"; 491*a0aa776eSAlan Wright int i; 492*a0aa776eSAlan Wright 493*a0aa776eSAlan Wright (void) snprintf(fname, MAXPATHLEN, "%s/%s", 494*a0aa776eSAlan Wright SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE); 495*a0aa776eSAlan Wright 496*a0aa776eSAlan Wright if ((fp = fopen(fname, "w")) == NULL) 497*a0aa776eSAlan Wright return; 498*a0aa776eSAlan Wright 499*a0aa776eSAlan Wright pwd = getpwnam("root"); 500*a0aa776eSAlan Wright grp = getgrnam("sys"); 501*a0aa776eSAlan Wright uid = (pwd == NULL) ? 0 : pwd->pw_uid; 502*a0aa776eSAlan Wright gid = (grp == NULL) ? 3 : grp->gr_gid; 503*a0aa776eSAlan Wright 504*a0aa776eSAlan Wright (void) lockf(fileno(fp), F_LOCK, 0); 505*a0aa776eSAlan Wright (void) fchmod(fileno(fp), 0600); 506*a0aa776eSAlan Wright (void) fchown(fileno(fp), uid, gid); 507*a0aa776eSAlan Wright 508*a0aa776eSAlan Wright if (nbtd.nbs_last_event) 509*a0aa776eSAlan Wright last_event = nbtd.nbs_last_event; 510*a0aa776eSAlan Wright 511*a0aa776eSAlan Wright for (i = 0; i < sizeof (sm) / sizeof (sm[0]); ++i) { 512*a0aa776eSAlan Wright if (nbtd.nbs_state == sm[i].state) { 513*a0aa776eSAlan Wright (void) fprintf(fp, 514*a0aa776eSAlan Wright "State %s (event: %s, errors: %u)\n", 515*a0aa776eSAlan Wright sm[i].text, last_event, nbtd.nbs_errors); 516*a0aa776eSAlan Wright break; 517*a0aa776eSAlan Wright } 518*a0aa776eSAlan Wright } 519*a0aa776eSAlan Wright 520*a0aa776eSAlan Wright (void) fprintf(fp, "Name Service %-7s (%u)\n", 521*a0aa776eSAlan Wright nbtd.nbs_ns.s_up ? "up" : "down", nbtd.nbs_ns.s_tid); 522*a0aa776eSAlan Wright (void) fprintf(fp, "Datagram Service %-7s (%u)\n", 523*a0aa776eSAlan Wright nbtd.nbs_dgm.s_up ? "up" : "down", nbtd.nbs_dgm.s_tid); 524*a0aa776eSAlan Wright (void) fprintf(fp, "Browser Service %-7s (%u)\n", 525*a0aa776eSAlan Wright nbtd.nbs_browser.s_up ? "up" : "down", nbtd.nbs_browser.s_tid); 526*a0aa776eSAlan Wright (void) fprintf(fp, "Timer Service %-7s (%u)\n", 527*a0aa776eSAlan Wright nbtd.nbs_timer.s_up ? "up" : "down", nbtd.nbs_timer.s_tid); 528*a0aa776eSAlan Wright 529*a0aa776eSAlan Wright smb_netbios_cache_dump(fp); 530*a0aa776eSAlan Wright 531*a0aa776eSAlan Wright (void) lockf(fileno(fp), F_ULOCK, 0); 532*a0aa776eSAlan Wright (void) fclose(fp); 533*a0aa776eSAlan Wright } 534