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