xref: /onnv-gate/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c (revision 10966:37e5dcdf36d3)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
2210717Samw@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw /*
275331Samw  * Main startup code for SMB/NETBIOS and some utility routines
285331Samw  * for the NETBIOS layer.
295331Samw  */
305331Samw 
3110717Samw@Sun.COM #include <sys/tzfile.h>
3210717Samw@Sun.COM #include <assert.h>
335331Samw #include <synch.h>
345331Samw #include <unistd.h>
355331Samw #include <syslog.h>
365331Samw #include <string.h>
375331Samw #include <strings.h>
385331Samw #include <sys/socket.h>
3910717Samw@Sun.COM #include <stdio.h>
4010717Samw@Sun.COM #include <pwd.h>
4110717Samw@Sun.COM #include <grp.h>
425331Samw #include <smbns_netbios.h>
435331Samw 
4410717Samw@Sun.COM #define	SMB_NETBIOS_DUMP_FILE		"netbios"
455331Samw 
4610717Samw@Sun.COM static netbios_service_t nbtd;
475331Samw 
4810717Samw@Sun.COM static void smb_netbios_shutdown(void);
4910717Samw@Sun.COM static void *smb_netbios_service(void *);
5010717Samw@Sun.COM static void smb_netbios_dump(void);
515331Samw 
5210717Samw@Sun.COM /*
5310717Samw@Sun.COM  * Start the NetBIOS services
5410717Samw@Sun.COM  */
555772Sas200622 int
smb_netbios_start(void)565772Sas200622 smb_netbios_start(void)
575331Samw {
5810717Samw@Sun.COM 	pthread_t	tid;
5910717Samw@Sun.COM 	pthread_attr_t	attr;
6010717Samw@Sun.COM 	int		rc;
615331Samw 
6210717Samw@Sun.COM 	if (smb_netbios_cache_init() < 0)
635772Sas200622 		return (-1);
645331Samw 
6510717Samw@Sun.COM 	(void) pthread_attr_init(&attr);
6610717Samw@Sun.COM 	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6710717Samw@Sun.COM 	rc = pthread_create(&tid, &attr, smb_netbios_service, NULL);
6810717Samw@Sun.COM 	(void) pthread_attr_destroy(&attr);
6910717Samw@Sun.COM 	return (rc);
7010717Samw@Sun.COM }
7110717Samw@Sun.COM 
7210717Samw@Sun.COM /*
7310717Samw@Sun.COM  * Stop the NetBIOS services
7410717Samw@Sun.COM  */
7510717Samw@Sun.COM void
smb_netbios_stop(void)7610717Samw@Sun.COM smb_netbios_stop(void)
7710717Samw@Sun.COM {
7810717Samw@Sun.COM 	char	fname[MAXPATHLEN];
7910717Samw@Sun.COM 
8010717Samw@Sun.COM 	smb_netbios_event(NETBIOS_EVENT_STOP);
8110717Samw@Sun.COM 
8210717Samw@Sun.COM 	(void) snprintf(fname, MAXPATHLEN, "%s/%s",
8310717Samw@Sun.COM 	    SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE);
8410717Samw@Sun.COM 	(void) unlink(fname);
855331Samw 
8610717Samw@Sun.COM }
8710717Samw@Sun.COM 
8810717Samw@Sun.COM /*
8910717Samw@Sun.COM  * Launch the NetBIOS Name Service, Datagram and Browser services
9010717Samw@Sun.COM  * and then sit in a loop providing a 1 second resolution timer.
9110717Samw@Sun.COM  * The timer will:
9210717Samw@Sun.COM  *	- update the netbios stats file every 10 minutes
9310717Samw@Sun.COM  *	- clean the cache every 10 minutes
9410717Samw@Sun.COM  */
9510717Samw@Sun.COM /*ARGSUSED*/
9610717Samw@Sun.COM static void *
smb_netbios_service(void * arg)9710717Samw@Sun.COM smb_netbios_service(void *arg)
9810717Samw@Sun.COM {
9910717Samw@Sun.COM 	static uint32_t	ticks = 0;
10010717Samw@Sun.COM 	pthread_t	tid;
10110717Samw@Sun.COM 	int		rc;
10210717Samw@Sun.COM 
10310717Samw@Sun.COM 	smb_netbios_event(NETBIOS_EVENT_START);
10410717Samw@Sun.COM 
10510717Samw@Sun.COM 	rc = pthread_create(&tid, NULL, smb_netbios_name_service, NULL);
10610717Samw@Sun.COM 	if (rc != 0) {
10710717Samw@Sun.COM 		smb_netbios_shutdown();
10810717Samw@Sun.COM 		return (NULL);
1095331Samw 	}
1105331Samw 
11110717Samw@Sun.COM 	smb_netbios_wait(NETBIOS_EVENT_NS_START);
11210717Samw@Sun.COM 	if (smb_netbios_error()) {
1135331Samw 		smb_netbios_shutdown();
11410717Samw@Sun.COM 		return (NULL);
1155331Samw 	}
1165331Samw 
1175331Samw 	smb_netbios_name_config();
1185331Samw 
11910717Samw@Sun.COM 	rc = pthread_create(&tid, NULL, smb_netbios_datagram_service, NULL);
1205772Sas200622 	if (rc != 0) {
1215331Samw 		smb_netbios_shutdown();
12210717Samw@Sun.COM 		return (NULL);
1235331Samw 	}
1245331Samw 
12510717Samw@Sun.COM 	smb_netbios_wait(NETBIOS_EVENT_DGM_START);
12610717Samw@Sun.COM 	if (smb_netbios_error()) {
1275331Samw 		smb_netbios_shutdown();
12810717Samw@Sun.COM 		return (NULL);
1295772Sas200622 	}
1305772Sas200622 
13110717Samw@Sun.COM 	rc = pthread_create(&tid, NULL, smb_browser_service, NULL);
13210717Samw@Sun.COM 	if (rc != 0) {
1335772Sas200622 		smb_netbios_shutdown();
13410717Samw@Sun.COM 		return (NULL);
1355772Sas200622 	}
1365331Samw 
13710717Samw@Sun.COM 	smb_netbios_event(NETBIOS_EVENT_TIMER_START);
1385331Samw 
13910717Samw@Sun.COM 	for (;;) {
1405331Samw 		(void) sleep(1);
1416030Sjb150015 		ticks++;
1425331Samw 
14310717Samw@Sun.COM 		if (!smb_netbios_running())
1446030Sjb150015 			break;
1455331Samw 
1466030Sjb150015 		smb_netbios_datagram_tick();
1476030Sjb150015 		smb_netbios_name_tick();
1486030Sjb150015 
14910717Samw@Sun.COM 		if ((ticks % 600) == 0) {
15010717Samw@Sun.COM 			smb_netbios_event(NETBIOS_EVENT_DUMP);
1516030Sjb150015 			smb_netbios_cache_clean();
15210717Samw@Sun.COM 		}
1535331Samw 	}
1545331Samw 
15510717Samw@Sun.COM 	smb_netbios_event(NETBIOS_EVENT_TIMER_STOP);
15610717Samw@Sun.COM 	smb_netbios_shutdown();
15710717Samw@Sun.COM 	return (NULL);
15810717Samw@Sun.COM }
15910717Samw@Sun.COM 
16010717Samw@Sun.COM static void
smb_netbios_shutdown(void)16110717Samw@Sun.COM smb_netbios_shutdown(void)
16210717Samw@Sun.COM {
16310717Samw@Sun.COM 	(void) pthread_join(nbtd.nbs_browser.s_tid, 0);
16410717Samw@Sun.COM 	(void) pthread_join(nbtd.nbs_dgm.s_tid, 0);
16510717Samw@Sun.COM 	(void) pthread_join(nbtd.nbs_ns.s_tid, 0);
16610717Samw@Sun.COM 
16710717Samw@Sun.COM 	nbtd.nbs_browser.s_tid = 0;
16810717Samw@Sun.COM 	nbtd.nbs_dgm.s_tid = 0;
16910717Samw@Sun.COM 	nbtd.nbs_ns.s_tid = 0;
17010717Samw@Sun.COM 
17110717Samw@Sun.COM 	smb_netbios_cache_fini();
17210717Samw@Sun.COM 
17310717Samw@Sun.COM 	if (smb_netbios_error()) {
17410717Samw@Sun.COM 		smb_netbios_event(NETBIOS_EVENT_RESET);
17510717Samw@Sun.COM 		if (smb_netbios_start() != 0)
17610717Samw@Sun.COM 			syslog(LOG_ERR, "netbios: restart failed");
1775331Samw 	}
1785331Samw }
1795331Samw 
1805331Samw int
smb_first_level_name_encode(struct name_entry * name,unsigned char * out,int max_out)1815331Samw smb_first_level_name_encode(struct name_entry *name,
1825331Samw 				unsigned char *out, int max_out)
1835331Samw {
1845331Samw 	return (netbios_first_level_name_encode(name->name, name->scope,
1855331Samw 	    out, max_out));
1865331Samw }
1875331Samw 
1885331Samw int
smb_first_level_name_decode(unsigned char * in,struct name_entry * name)1895331Samw smb_first_level_name_decode(unsigned char *in, struct name_entry *name)
1905331Samw {
1915331Samw 	return (netbios_first_level_name_decode((char *)in, (char *)name->name,
1925331Samw 	    (char *)name->scope));
1935331Samw }
1945331Samw 
1955331Samw /*
1965331Samw  * smb_encode_netbios_name
1975331Samw  *
1985331Samw  * Set up the name and scope fields in the destination name_entry structure.
1995331Samw  * The name is padded with spaces to 15 bytes. The suffix is copied into the
2005331Samw  * last byte, i.e. "netbiosname    <suffix>". The scope is copied and folded
2015331Samw  * to uppercase.
2025331Samw  */
2035331Samw void
smb_encode_netbios_name(unsigned char * name,char suffix,unsigned char * scope,struct name_entry * dest)2045331Samw smb_encode_netbios_name(unsigned char *name, char suffix, unsigned char *scope,
2055331Samw     struct name_entry *dest)
2065331Samw {
2076030Sjb150015 	smb_tonetbiosname((char *)name, (char *)dest->name, suffix);
2085331Samw 
2096030Sjb150015 	if (scope) {
2106030Sjb150015 		(void) strlcpy((char *)dest->scope, (const char *)scope,
2116030Sjb150015 		    sizeof (dest->scope));
2126030Sjb150015 	} else {
2136030Sjb150015 		(void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)dest->scope,
2146030Sjb150015 		    sizeof (dest->scope));
2155331Samw 	}
2165331Samw 
217*10966SJordan.Brown@Sun.COM 	(void) smb_strupr((char *)dest->scope);
2185331Samw }
2195331Samw 
2205331Samw void
smb_init_name_struct(unsigned char * name,char suffix,unsigned char * scope,uint32_t ipaddr,unsigned short port,uint32_t attr,uint32_t addr_attr,struct name_entry * dest)2215331Samw smb_init_name_struct(unsigned char *name, char suffix, unsigned char *scope,
2225331Samw     uint32_t ipaddr, unsigned short port, uint32_t attr,
2235331Samw     uint32_t addr_attr, struct name_entry *dest)
2245331Samw {
2255331Samw 	bzero(dest, sizeof (struct name_entry));
2265331Samw 	smb_encode_netbios_name(name, suffix, scope, dest);
2275331Samw 
2285331Samw 	switch (smb_node_type) {
2295331Samw 	case 'H':
2305331Samw 		dest->attributes = attr | NAME_ATTR_OWNER_TYPE_HNODE;
2315331Samw 		break;
2325331Samw 	case 'M':
2335331Samw 		dest->attributes = attr | NAME_ATTR_OWNER_TYPE_MNODE;
2345331Samw 		break;
2355331Samw 	case 'P':
2365331Samw 		dest->attributes = attr | NAME_ATTR_OWNER_TYPE_PNODE;
2375331Samw 		break;
2385331Samw 	case 'B':
2395331Samw 	default:
2405331Samw 		dest->attributes = attr | NAME_ATTR_OWNER_TYPE_BNODE;
2415331Samw 		break;
2425331Samw 	}
2435331Samw 
2445331Samw 	dest->addr_list.refresh_ttl = dest->addr_list.ttl =
2455331Samw 	    TO_SECONDS(DEFAULT_TTL);
2465331Samw 
2475331Samw 	dest->addr_list.sin.sin_family = AF_INET;
2485331Samw 	dest->addr_list.sinlen = sizeof (dest->addr_list.sin);
2495331Samw 	dest->addr_list.sin.sin_addr.s_addr = ipaddr;
2505331Samw 	dest->addr_list.sin.sin_port = port;
2515331Samw 	dest->addr_list.attributes = addr_attr;
2525331Samw 	dest->addr_list.forw = dest->addr_list.back = &dest->addr_list;
2535331Samw }
25410717Samw@Sun.COM 
25510717Samw@Sun.COM void
smb_netbios_event(netbios_event_t event)25610717Samw@Sun.COM smb_netbios_event(netbios_event_t event)
25710717Samw@Sun.COM {
25810717Samw@Sun.COM 	static char *event_msg[] = {
25910717Samw@Sun.COM 		"startup",
26010717Samw@Sun.COM 		"shutdown",
26110717Samw@Sun.COM 		"restart",
26210717Samw@Sun.COM 		"name service started",
26310717Samw@Sun.COM 		"name service stopped",
26410717Samw@Sun.COM 		"datagram service started",
26510717Samw@Sun.COM 		"datagram service stopped",
26610717Samw@Sun.COM 		"browser service started",
26710717Samw@Sun.COM 		"browser service stopped",
26810717Samw@Sun.COM 		"timer service started",
26910717Samw@Sun.COM 		"timer service stopped",
27010717Samw@Sun.COM 		"error",
27110717Samw@Sun.COM 		"dump"
27210717Samw@Sun.COM 	};
27310717Samw@Sun.COM 
27410717Samw@Sun.COM 	(void) mutex_lock(&nbtd.nbs_mtx);
27510717Samw@Sun.COM 
27610717Samw@Sun.COM 	if (event == NETBIOS_EVENT_DUMP) {
27710717Samw@Sun.COM 		if (nbtd.nbs_last_event == NULL)
27810717Samw@Sun.COM 			nbtd.nbs_last_event = event_msg[event];
27910717Samw@Sun.COM 		smb_netbios_dump();
28010717Samw@Sun.COM 		(void) mutex_unlock(&nbtd.nbs_mtx);
28110717Samw@Sun.COM 		return;
28210717Samw@Sun.COM 	}
28310717Samw@Sun.COM 
28410717Samw@Sun.COM 	nbtd.nbs_last_event = event_msg[event];
28510717Samw@Sun.COM 	syslog(LOG_DEBUG, "netbios: %s", nbtd.nbs_last_event);
28610717Samw@Sun.COM 
28710717Samw@Sun.COM 	switch (nbtd.nbs_state) {
28810717Samw@Sun.COM 	case NETBIOS_STATE_INIT:
28910717Samw@Sun.COM 		if (event == NETBIOS_EVENT_START)
29010717Samw@Sun.COM 			nbtd.nbs_state = NETBIOS_STATE_RUNNING;
29110717Samw@Sun.COM 		break;
29210717Samw@Sun.COM 
29310717Samw@Sun.COM 	case NETBIOS_STATE_RUNNING:
29410717Samw@Sun.COM 		switch (event) {
29510717Samw@Sun.COM 		case NETBIOS_EVENT_NS_START:
29610717Samw@Sun.COM 			nbtd.nbs_ns.s_tid = pthread_self();
29710717Samw@Sun.COM 			nbtd.nbs_ns.s_up = B_TRUE;
29810717Samw@Sun.COM 			break;
29910717Samw@Sun.COM 		case NETBIOS_EVENT_NS_STOP:
30010717Samw@Sun.COM 			nbtd.nbs_ns.s_up = B_FALSE;
30110717Samw@Sun.COM 			break;
30210717Samw@Sun.COM 		case NETBIOS_EVENT_DGM_START:
30310717Samw@Sun.COM 			nbtd.nbs_dgm.s_tid = pthread_self();
30410717Samw@Sun.COM 			nbtd.nbs_dgm.s_up = B_TRUE;
30510717Samw@Sun.COM 			break;
30610717Samw@Sun.COM 		case NETBIOS_EVENT_DGM_STOP:
30710717Samw@Sun.COM 			nbtd.nbs_dgm.s_up = B_FALSE;
30810717Samw@Sun.COM 			break;
30910717Samw@Sun.COM 		case NETBIOS_EVENT_BROWSER_START:
31010717Samw@Sun.COM 			nbtd.nbs_browser.s_tid = pthread_self();
31110717Samw@Sun.COM 			nbtd.nbs_browser.s_up = B_TRUE;
31210717Samw@Sun.COM 			break;
31310717Samw@Sun.COM 		case NETBIOS_EVENT_BROWSER_STOP:
31410717Samw@Sun.COM 			nbtd.nbs_browser.s_up = B_FALSE;
31510717Samw@Sun.COM 			break;
31610717Samw@Sun.COM 		case NETBIOS_EVENT_TIMER_START:
31710717Samw@Sun.COM 			nbtd.nbs_timer.s_tid = pthread_self();
31810717Samw@Sun.COM 			nbtd.nbs_timer.s_up = B_TRUE;
31910717Samw@Sun.COM 			break;
32010717Samw@Sun.COM 		case NETBIOS_EVENT_TIMER_STOP:
32110717Samw@Sun.COM 			nbtd.nbs_timer.s_up = B_FALSE;
32210717Samw@Sun.COM 			break;
32310717Samw@Sun.COM 		case NETBIOS_EVENT_STOP:
32410717Samw@Sun.COM 			nbtd.nbs_state = NETBIOS_STATE_CLOSING;
32510717Samw@Sun.COM 			break;
32610717Samw@Sun.COM 		case NETBIOS_EVENT_ERROR:
32710717Samw@Sun.COM 			nbtd.nbs_state = NETBIOS_STATE_ERROR;
32810717Samw@Sun.COM 			++nbtd.nbs_errors;
32910717Samw@Sun.COM 			break;
33010717Samw@Sun.COM 		default:
33110717Samw@Sun.COM 			break;
33210717Samw@Sun.COM 		}
33310717Samw@Sun.COM 		break;
33410717Samw@Sun.COM 
33510717Samw@Sun.COM 	case NETBIOS_STATE_CLOSING:
33610717Samw@Sun.COM 	case NETBIOS_STATE_ERROR:
33710717Samw@Sun.COM 	default:
33810717Samw@Sun.COM 		switch (event) {
33910717Samw@Sun.COM 		case NETBIOS_EVENT_NS_STOP:
34010717Samw@Sun.COM 			nbtd.nbs_ns.s_up = B_FALSE;
34110717Samw@Sun.COM 			break;
34210717Samw@Sun.COM 		case NETBIOS_EVENT_DGM_STOP:
34310717Samw@Sun.COM 			nbtd.nbs_dgm.s_up = B_FALSE;
34410717Samw@Sun.COM 			break;
34510717Samw@Sun.COM 		case NETBIOS_EVENT_BROWSER_STOP:
34610717Samw@Sun.COM 			nbtd.nbs_browser.s_up = B_FALSE;
34710717Samw@Sun.COM 			break;
34810717Samw@Sun.COM 		case NETBIOS_EVENT_TIMER_STOP:
34910717Samw@Sun.COM 			nbtd.nbs_timer.s_up = B_FALSE;
35010717Samw@Sun.COM 			break;
35110717Samw@Sun.COM 		case NETBIOS_EVENT_STOP:
35210717Samw@Sun.COM 			nbtd.nbs_state = NETBIOS_STATE_CLOSING;
35310717Samw@Sun.COM 			break;
35410717Samw@Sun.COM 		case NETBIOS_EVENT_RESET:
35510717Samw@Sun.COM 			nbtd.nbs_state = NETBIOS_STATE_INIT;
35610717Samw@Sun.COM 			break;
35710717Samw@Sun.COM 		case NETBIOS_EVENT_ERROR:
35810717Samw@Sun.COM 			++nbtd.nbs_errors;
35910717Samw@Sun.COM 			break;
36010717Samw@Sun.COM 		default:
36110717Samw@Sun.COM 			break;
36210717Samw@Sun.COM 		}
36310717Samw@Sun.COM 		break;
36410717Samw@Sun.COM 	}
36510717Samw@Sun.COM 
36610717Samw@Sun.COM 	smb_netbios_dump();
36710717Samw@Sun.COM 	(void) cond_broadcast(&nbtd.nbs_cv);
36810717Samw@Sun.COM 	(void) mutex_unlock(&nbtd.nbs_mtx);
36910717Samw@Sun.COM }
37010717Samw@Sun.COM 
37110717Samw@Sun.COM void
smb_netbios_wait(netbios_event_t event)37210717Samw@Sun.COM smb_netbios_wait(netbios_event_t event)
37310717Samw@Sun.COM {
37410717Samw@Sun.COM 	boolean_t *svc = NULL;
37510717Samw@Sun.COM 	boolean_t desired_state;
37610717Samw@Sun.COM 
37710717Samw@Sun.COM 	(void) mutex_lock(&nbtd.nbs_mtx);
37810717Samw@Sun.COM 
37910717Samw@Sun.COM 	switch (event) {
38010717Samw@Sun.COM 	case NETBIOS_EVENT_NS_START:
38110717Samw@Sun.COM 	case NETBIOS_EVENT_NS_STOP:
38210717Samw@Sun.COM 		svc = &nbtd.nbs_ns.s_up;
38310717Samw@Sun.COM 		desired_state =
38410717Samw@Sun.COM 		    (event == NETBIOS_EVENT_NS_START) ? B_TRUE : B_FALSE;
38510717Samw@Sun.COM 		break;
38610717Samw@Sun.COM 	case NETBIOS_EVENT_DGM_START:
38710717Samw@Sun.COM 	case NETBIOS_EVENT_DGM_STOP:
38810717Samw@Sun.COM 		svc = &nbtd.nbs_dgm.s_up;
38910717Samw@Sun.COM 		desired_state =
39010717Samw@Sun.COM 		    (event == NETBIOS_EVENT_DGM_START) ? B_TRUE : B_FALSE;
39110717Samw@Sun.COM 		break;
39210717Samw@Sun.COM 	case NETBIOS_EVENT_BROWSER_START:
39310717Samw@Sun.COM 	case NETBIOS_EVENT_BROWSER_STOP:
39410717Samw@Sun.COM 		svc = &nbtd.nbs_browser.s_up;
39510717Samw@Sun.COM 		desired_state =
39610717Samw@Sun.COM 		    (event == NETBIOS_EVENT_BROWSER_START) ? B_TRUE : B_FALSE;
39710717Samw@Sun.COM 		break;
39810717Samw@Sun.COM 	default:
39910717Samw@Sun.COM 		(void) mutex_unlock(&nbtd.nbs_mtx);
40010717Samw@Sun.COM 		return;
40110717Samw@Sun.COM 	}
40210717Samw@Sun.COM 
40310717Samw@Sun.COM 	while (*svc != desired_state) {
40410717Samw@Sun.COM 		if (nbtd.nbs_state != NETBIOS_STATE_RUNNING)
40510717Samw@Sun.COM 			break;
40610717Samw@Sun.COM 
40710717Samw@Sun.COM 		(void) cond_wait(&nbtd.nbs_cv, &nbtd.nbs_mtx);
40810717Samw@Sun.COM 	}
40910717Samw@Sun.COM 
41010717Samw@Sun.COM 	(void) mutex_unlock(&nbtd.nbs_mtx);
41110717Samw@Sun.COM }
41210717Samw@Sun.COM 
41310717Samw@Sun.COM void
smb_netbios_sleep(time_t seconds)41410717Samw@Sun.COM smb_netbios_sleep(time_t seconds)
41510717Samw@Sun.COM {
41610717Samw@Sun.COM 	timestruc_t reltimeout;
41710717Samw@Sun.COM 
41810717Samw@Sun.COM 	(void) mutex_lock(&nbtd.nbs_mtx);
41910717Samw@Sun.COM 
42010717Samw@Sun.COM 	if (nbtd.nbs_state == NETBIOS_STATE_RUNNING) {
42110717Samw@Sun.COM 		if (seconds == 0)
42210717Samw@Sun.COM 			seconds  = 1;
42310717Samw@Sun.COM 		reltimeout.tv_sec = seconds;
42410717Samw@Sun.COM 		reltimeout.tv_nsec = 0;
42510717Samw@Sun.COM 
42610717Samw@Sun.COM 		(void) cond_reltimedwait(&nbtd.nbs_cv,
42710717Samw@Sun.COM 		    &nbtd.nbs_mtx, &reltimeout);
42810717Samw@Sun.COM 	}
42910717Samw@Sun.COM 
43010717Samw@Sun.COM 	(void) mutex_unlock(&nbtd.nbs_mtx);
43110717Samw@Sun.COM }
43210717Samw@Sun.COM 
43310717Samw@Sun.COM boolean_t
smb_netbios_running(void)43410717Samw@Sun.COM smb_netbios_running(void)
43510717Samw@Sun.COM {
43610717Samw@Sun.COM 	boolean_t is_running;
43710717Samw@Sun.COM 
43810717Samw@Sun.COM 	(void) mutex_lock(&nbtd.nbs_mtx);
43910717Samw@Sun.COM 
44010717Samw@Sun.COM 	if (nbtd.nbs_state == NETBIOS_STATE_RUNNING)
44110717Samw@Sun.COM 		is_running = B_TRUE;
44210717Samw@Sun.COM 	else
44310717Samw@Sun.COM 		is_running = B_FALSE;
44410717Samw@Sun.COM 
44510717Samw@Sun.COM 	(void) mutex_unlock(&nbtd.nbs_mtx);
44610717Samw@Sun.COM 	return (is_running);
44710717Samw@Sun.COM }
44810717Samw@Sun.COM 
44910717Samw@Sun.COM boolean_t
smb_netbios_error(void)45010717Samw@Sun.COM smb_netbios_error(void)
45110717Samw@Sun.COM {
45210717Samw@Sun.COM 	boolean_t error;
45310717Samw@Sun.COM 
45410717Samw@Sun.COM 	(void) mutex_lock(&nbtd.nbs_mtx);
45510717Samw@Sun.COM 
45610717Samw@Sun.COM 	if (nbtd.nbs_state == NETBIOS_STATE_ERROR)
45710717Samw@Sun.COM 		error = B_TRUE;
45810717Samw@Sun.COM 	else
45910717Samw@Sun.COM 		error = B_FALSE;
46010717Samw@Sun.COM 
46110717Samw@Sun.COM 	(void) mutex_unlock(&nbtd.nbs_mtx);
46210717Samw@Sun.COM 	return (error);
46310717Samw@Sun.COM }
46410717Samw@Sun.COM 
46510717Samw@Sun.COM /*
46610717Samw@Sun.COM  * Write the service state to /var/run/smb/netbios.
46710717Samw@Sun.COM  *
46810717Samw@Sun.COM  * This is a private interface.  To update the file use:
46910717Samw@Sun.COM  *	smb_netbios_event(NETBIOS_EVENT_DUMP);
47010717Samw@Sun.COM  */
47110717Samw@Sun.COM static void
smb_netbios_dump(void)47210717Samw@Sun.COM smb_netbios_dump(void)
47310717Samw@Sun.COM {
47410717Samw@Sun.COM 	static struct {
47510717Samw@Sun.COM 		netbios_state_t state;
47610717Samw@Sun.COM 		char		*text;
47710717Samw@Sun.COM 	} sm[] = {
47810717Samw@Sun.COM 		{ NETBIOS_STATE_INIT,		"init" },
47910717Samw@Sun.COM 		{ NETBIOS_STATE_RUNNING,	"running" },
48010717Samw@Sun.COM 		{ NETBIOS_STATE_CLOSING,	"closing" },
48110717Samw@Sun.COM 		{ NETBIOS_STATE_ERROR,		"error" }
48210717Samw@Sun.COM 	};
48310717Samw@Sun.COM 
48410717Samw@Sun.COM 	char		fname[MAXPATHLEN];
48510717Samw@Sun.COM 	FILE		*fp;
48610717Samw@Sun.COM 	struct passwd	*pwd;
48710717Samw@Sun.COM 	struct group	*grp;
48810717Samw@Sun.COM 	uid_t		uid;
48910717Samw@Sun.COM 	gid_t		gid;
49010717Samw@Sun.COM 	char		*last_event = "none";
49110717Samw@Sun.COM 	int		i;
49210717Samw@Sun.COM 
49310717Samw@Sun.COM 	(void) snprintf(fname, MAXPATHLEN, "%s/%s",
49410717Samw@Sun.COM 	    SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE);
49510717Samw@Sun.COM 
49610717Samw@Sun.COM 	if ((fp = fopen(fname, "w")) == NULL)
49710717Samw@Sun.COM 		return;
49810717Samw@Sun.COM 
49910717Samw@Sun.COM 	pwd = getpwnam("root");
50010717Samw@Sun.COM 	grp = getgrnam("sys");
50110717Samw@Sun.COM 	uid = (pwd == NULL) ? 0 : pwd->pw_uid;
50210717Samw@Sun.COM 	gid = (grp == NULL) ? 3 : grp->gr_gid;
50310717Samw@Sun.COM 
50410717Samw@Sun.COM 	(void) lockf(fileno(fp), F_LOCK, 0);
50510717Samw@Sun.COM 	(void) fchmod(fileno(fp), 0600);
50610717Samw@Sun.COM 	(void) fchown(fileno(fp), uid, gid);
50710717Samw@Sun.COM 
50810717Samw@Sun.COM 	if (nbtd.nbs_last_event)
50910717Samw@Sun.COM 		last_event = nbtd.nbs_last_event;
51010717Samw@Sun.COM 
51110717Samw@Sun.COM 	for (i = 0; i < sizeof (sm) / sizeof (sm[0]); ++i) {
51210717Samw@Sun.COM 		if (nbtd.nbs_state == sm[i].state) {
51310717Samw@Sun.COM 			(void) fprintf(fp,
51410717Samw@Sun.COM 			    "State             %s  (event: %s, errors: %u)\n",
51510717Samw@Sun.COM 			    sm[i].text, last_event, nbtd.nbs_errors);
51610717Samw@Sun.COM 			break;
51710717Samw@Sun.COM 		}
51810717Samw@Sun.COM 	}
51910717Samw@Sun.COM 
52010717Samw@Sun.COM 	(void) fprintf(fp, "Name Service      %-7s  (%u)\n",
52110717Samw@Sun.COM 	    nbtd.nbs_ns.s_up ? "up" : "down", nbtd.nbs_ns.s_tid);
52210717Samw@Sun.COM 	(void) fprintf(fp, "Datagram Service  %-7s  (%u)\n",
52310717Samw@Sun.COM 	    nbtd.nbs_dgm.s_up ? "up" : "down", nbtd.nbs_dgm.s_tid);
52410717Samw@Sun.COM 	(void) fprintf(fp, "Browser Service   %-7s  (%u)\n",
52510717Samw@Sun.COM 	    nbtd.nbs_browser.s_up ? "up" : "down", nbtd.nbs_browser.s_tid);
52610717Samw@Sun.COM 	(void) fprintf(fp, "Timer Service     %-7s  (%u)\n",
52710717Samw@Sun.COM 	    nbtd.nbs_timer.s_up ? "up" : "down", nbtd.nbs_timer.s_tid);
52810717Samw@Sun.COM 
52910717Samw@Sun.COM 	smb_netbios_cache_dump(fp);
53010717Samw@Sun.COM 
53110717Samw@Sun.COM 	(void) lockf(fileno(fp), F_ULOCK, 0);
53210717Samw@Sun.COM 	(void) fclose(fp);
53310717Samw@Sun.COM }
534