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 /*
22a0aa776eSAlan 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
31a0aa776eSAlan Wright #include <sys/tzfile.h>
32a0aa776eSAlan 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>
39a0aa776eSAlan Wright #include <stdio.h>
40a0aa776eSAlan Wright #include <pwd.h>
41a0aa776eSAlan Wright #include <grp.h>
42da6c28aaSamw #include <smbns_netbios.h>
43da6c28aaSamw
44a0aa776eSAlan Wright #define SMB_NETBIOS_DUMP_FILE "netbios"
45da6c28aaSamw
46a0aa776eSAlan Wright static netbios_service_t nbtd;
47da6c28aaSamw
48a0aa776eSAlan Wright static void smb_netbios_shutdown(void);
49a0aa776eSAlan Wright static void *smb_netbios_service(void *);
50a0aa776eSAlan Wright static void smb_netbios_dump(void);
51da6c28aaSamw
52a0aa776eSAlan Wright /*
53a0aa776eSAlan Wright * Start the NetBIOS services
54a0aa776eSAlan Wright */
55dc20a302Sas200622 int
smb_netbios_start(void)56dc20a302Sas200622 smb_netbios_start(void)
57da6c28aaSamw {
58a0aa776eSAlan Wright pthread_t tid;
59a0aa776eSAlan Wright pthread_attr_t attr;
60da6c28aaSamw int rc;
61da6c28aaSamw
62a0aa776eSAlan Wright if (smb_netbios_cache_init() < 0)
63dc20a302Sas200622 return (-1);
64da6c28aaSamw
65a0aa776eSAlan Wright (void) pthread_attr_init(&attr);
66a0aa776eSAlan Wright (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
67a0aa776eSAlan Wright rc = pthread_create(&tid, &attr, smb_netbios_service, NULL);
68a0aa776eSAlan Wright (void) pthread_attr_destroy(&attr);
69a0aa776eSAlan Wright return (rc);
70da6c28aaSamw }
71da6c28aaSamw
72a0aa776eSAlan Wright /*
73a0aa776eSAlan Wright * Stop the NetBIOS services
74a0aa776eSAlan Wright */
75a0aa776eSAlan Wright void
smb_netbios_stop(void)76a0aa776eSAlan Wright smb_netbios_stop(void)
77a0aa776eSAlan Wright {
78a0aa776eSAlan Wright char fname[MAXPATHLEN];
79a0aa776eSAlan Wright
80a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_STOP);
81a0aa776eSAlan Wright
82a0aa776eSAlan Wright (void) snprintf(fname, MAXPATHLEN, "%s/%s",
83a0aa776eSAlan Wright SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE);
84a0aa776eSAlan Wright (void) unlink(fname);
85a0aa776eSAlan Wright
86a0aa776eSAlan Wright }
87a0aa776eSAlan Wright
88a0aa776eSAlan Wright /*
89a0aa776eSAlan Wright * Launch the NetBIOS Name Service, Datagram and Browser services
90a0aa776eSAlan Wright * and then sit in a loop providing a 1 second resolution timer.
91a0aa776eSAlan Wright * The timer will:
92a0aa776eSAlan Wright * - update the netbios stats file every 10 minutes
93a0aa776eSAlan Wright * - clean the cache every 10 minutes
94a0aa776eSAlan Wright */
95a0aa776eSAlan Wright /*ARGSUSED*/
96a0aa776eSAlan Wright static void *
smb_netbios_service(void * arg)97a0aa776eSAlan Wright smb_netbios_service(void *arg)
98a0aa776eSAlan Wright {
99a0aa776eSAlan Wright static uint32_t ticks = 0;
100a0aa776eSAlan Wright pthread_t tid;
101a0aa776eSAlan Wright int rc;
102a0aa776eSAlan Wright
103a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_START);
104a0aa776eSAlan Wright
105a0aa776eSAlan Wright rc = pthread_create(&tid, NULL, smb_netbios_name_service, NULL);
106a0aa776eSAlan Wright if (rc != 0) {
107da6c28aaSamw smb_netbios_shutdown();
108a0aa776eSAlan Wright return (NULL);
109da6c28aaSamw }
110a0aa776eSAlan Wright
111a0aa776eSAlan Wright smb_netbios_wait(NETBIOS_EVENT_NS_START);
112a0aa776eSAlan Wright if (smb_netbios_error()) {
113a0aa776eSAlan Wright smb_netbios_shutdown();
114a0aa776eSAlan Wright return (NULL);
115a0aa776eSAlan Wright }
116da6c28aaSamw
117da6c28aaSamw smb_netbios_name_config();
118da6c28aaSamw
119a0aa776eSAlan Wright rc = pthread_create(&tid, NULL, smb_netbios_datagram_service, NULL);
120dc20a302Sas200622 if (rc != 0) {
121dc20a302Sas200622 smb_netbios_shutdown();
122a0aa776eSAlan Wright return (NULL);
123dc20a302Sas200622 }
124dc20a302Sas200622
125a0aa776eSAlan Wright smb_netbios_wait(NETBIOS_EVENT_DGM_START);
126a0aa776eSAlan Wright if (smb_netbios_error()) {
127da6c28aaSamw smb_netbios_shutdown();
128a0aa776eSAlan Wright return (NULL);
129da6c28aaSamw }
130da6c28aaSamw
131a0aa776eSAlan Wright rc = pthread_create(&tid, NULL, smb_browser_service, NULL);
132dc20a302Sas200622 if (rc != 0) {
133dc20a302Sas200622 smb_netbios_shutdown();
134a0aa776eSAlan Wright return (NULL);
135dc20a302Sas200622 }
136dc20a302Sas200622
137a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_TIMER_START);
138da6c28aaSamw
139a0aa776eSAlan Wright for (;;) {
140da6c28aaSamw (void) sleep(1);
1417b59d02dSjb150015 ticks++;
142da6c28aaSamw
143a0aa776eSAlan Wright if (!smb_netbios_running())
1447b59d02dSjb150015 break;
1457b59d02dSjb150015
1467b59d02dSjb150015 smb_netbios_datagram_tick();
147da6c28aaSamw smb_netbios_name_tick();
148da6c28aaSamw
149a0aa776eSAlan Wright if ((ticks % 600) == 0) {
150a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_DUMP);
151da6c28aaSamw smb_netbios_cache_clean();
152da6c28aaSamw }
153da6c28aaSamw }
154da6c28aaSamw
155a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_TIMER_STOP);
156a0aa776eSAlan Wright smb_netbios_shutdown();
157a0aa776eSAlan Wright return (NULL);
158a0aa776eSAlan Wright }
159a0aa776eSAlan Wright
160a0aa776eSAlan Wright static void
smb_netbios_shutdown(void)161a0aa776eSAlan Wright smb_netbios_shutdown(void)
162a0aa776eSAlan Wright {
163a0aa776eSAlan Wright (void) pthread_join(nbtd.nbs_browser.s_tid, 0);
164a0aa776eSAlan Wright (void) pthread_join(nbtd.nbs_dgm.s_tid, 0);
165a0aa776eSAlan Wright (void) pthread_join(nbtd.nbs_ns.s_tid, 0);
166a0aa776eSAlan Wright
167a0aa776eSAlan Wright nbtd.nbs_browser.s_tid = 0;
168a0aa776eSAlan Wright nbtd.nbs_dgm.s_tid = 0;
169a0aa776eSAlan Wright nbtd.nbs_ns.s_tid = 0;
170a0aa776eSAlan Wright
171a0aa776eSAlan Wright smb_netbios_cache_fini();
172a0aa776eSAlan Wright
173a0aa776eSAlan Wright if (smb_netbios_error()) {
174a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_RESET);
175a0aa776eSAlan Wright if (smb_netbios_start() != 0)
176a0aa776eSAlan Wright syslog(LOG_ERR, "netbios: restart failed");
177a0aa776eSAlan Wright }
178da6c28aaSamw }
179da6c28aaSamw
180da6c28aaSamw int
smb_first_level_name_encode(struct name_entry * name,unsigned char * out,int max_out)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
smb_first_level_name_decode(unsigned char * in,struct name_entry * name)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
smb_encode_netbios_name(unsigned char * name,char suffix,unsigned char * scope,struct name_entry * dest)204da6c28aaSamw smb_encode_netbios_name(unsigned char *name, char suffix, unsigned char *scope,
205da6c28aaSamw struct name_entry *dest)
206da6c28aaSamw {
2077b59d02dSjb150015 smb_tonetbiosname((char *)name, (char *)dest->name, suffix);
208da6c28aaSamw
2097b59d02dSjb150015 if (scope) {
210da6c28aaSamw (void) strlcpy((char *)dest->scope, (const char *)scope,
2117b59d02dSjb150015 sizeof (dest->scope));
2127b59d02dSjb150015 } else {
2137b59d02dSjb150015 (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)dest->scope,
2147b59d02dSjb150015 sizeof (dest->scope));
215da6c28aaSamw }
2167b59d02dSjb150015
217*bbf6f00cSJordan Brown (void) smb_strupr((char *)dest->scope);
218da6c28aaSamw }
219da6c28aaSamw
220da6c28aaSamw 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)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 }
254a0aa776eSAlan Wright
255a0aa776eSAlan Wright void
smb_netbios_event(netbios_event_t event)256a0aa776eSAlan Wright smb_netbios_event(netbios_event_t event)
257a0aa776eSAlan Wright {
258a0aa776eSAlan Wright static char *event_msg[] = {
259a0aa776eSAlan Wright "startup",
260a0aa776eSAlan Wright "shutdown",
261a0aa776eSAlan Wright "restart",
262a0aa776eSAlan Wright "name service started",
263a0aa776eSAlan Wright "name service stopped",
264a0aa776eSAlan Wright "datagram service started",
265a0aa776eSAlan Wright "datagram service stopped",
266a0aa776eSAlan Wright "browser service started",
267a0aa776eSAlan Wright "browser service stopped",
268a0aa776eSAlan Wright "timer service started",
269a0aa776eSAlan Wright "timer service stopped",
270a0aa776eSAlan Wright "error",
271a0aa776eSAlan Wright "dump"
272a0aa776eSAlan Wright };
273a0aa776eSAlan Wright
274a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx);
275a0aa776eSAlan Wright
276a0aa776eSAlan Wright if (event == NETBIOS_EVENT_DUMP) {
277a0aa776eSAlan Wright if (nbtd.nbs_last_event == NULL)
278a0aa776eSAlan Wright nbtd.nbs_last_event = event_msg[event];
279a0aa776eSAlan Wright smb_netbios_dump();
280a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx);
281a0aa776eSAlan Wright return;
282a0aa776eSAlan Wright }
283a0aa776eSAlan Wright
284a0aa776eSAlan Wright nbtd.nbs_last_event = event_msg[event];
285a0aa776eSAlan Wright syslog(LOG_DEBUG, "netbios: %s", nbtd.nbs_last_event);
286a0aa776eSAlan Wright
287a0aa776eSAlan Wright switch (nbtd.nbs_state) {
288a0aa776eSAlan Wright case NETBIOS_STATE_INIT:
289a0aa776eSAlan Wright if (event == NETBIOS_EVENT_START)
290a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_RUNNING;
291a0aa776eSAlan Wright break;
292a0aa776eSAlan Wright
293a0aa776eSAlan Wright case NETBIOS_STATE_RUNNING:
294a0aa776eSAlan Wright switch (event) {
295a0aa776eSAlan Wright case NETBIOS_EVENT_NS_START:
296a0aa776eSAlan Wright nbtd.nbs_ns.s_tid = pthread_self();
297a0aa776eSAlan Wright nbtd.nbs_ns.s_up = B_TRUE;
298a0aa776eSAlan Wright break;
299a0aa776eSAlan Wright case NETBIOS_EVENT_NS_STOP:
300a0aa776eSAlan Wright nbtd.nbs_ns.s_up = B_FALSE;
301a0aa776eSAlan Wright break;
302a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_START:
303a0aa776eSAlan Wright nbtd.nbs_dgm.s_tid = pthread_self();
304a0aa776eSAlan Wright nbtd.nbs_dgm.s_up = B_TRUE;
305a0aa776eSAlan Wright break;
306a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_STOP:
307a0aa776eSAlan Wright nbtd.nbs_dgm.s_up = B_FALSE;
308a0aa776eSAlan Wright break;
309a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_START:
310a0aa776eSAlan Wright nbtd.nbs_browser.s_tid = pthread_self();
311a0aa776eSAlan Wright nbtd.nbs_browser.s_up = B_TRUE;
312a0aa776eSAlan Wright break;
313a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_STOP:
314a0aa776eSAlan Wright nbtd.nbs_browser.s_up = B_FALSE;
315a0aa776eSAlan Wright break;
316a0aa776eSAlan Wright case NETBIOS_EVENT_TIMER_START:
317a0aa776eSAlan Wright nbtd.nbs_timer.s_tid = pthread_self();
318a0aa776eSAlan Wright nbtd.nbs_timer.s_up = B_TRUE;
319a0aa776eSAlan Wright break;
320a0aa776eSAlan Wright case NETBIOS_EVENT_TIMER_STOP:
321a0aa776eSAlan Wright nbtd.nbs_timer.s_up = B_FALSE;
322a0aa776eSAlan Wright break;
323a0aa776eSAlan Wright case NETBIOS_EVENT_STOP:
324a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_CLOSING;
325a0aa776eSAlan Wright break;
326a0aa776eSAlan Wright case NETBIOS_EVENT_ERROR:
327a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_ERROR;
328a0aa776eSAlan Wright ++nbtd.nbs_errors;
329a0aa776eSAlan Wright break;
330a0aa776eSAlan Wright default:
331a0aa776eSAlan Wright break;
332a0aa776eSAlan Wright }
333a0aa776eSAlan Wright break;
334a0aa776eSAlan Wright
335a0aa776eSAlan Wright case NETBIOS_STATE_CLOSING:
336a0aa776eSAlan Wright case NETBIOS_STATE_ERROR:
337a0aa776eSAlan Wright default:
338a0aa776eSAlan Wright switch (event) {
339a0aa776eSAlan Wright case NETBIOS_EVENT_NS_STOP:
340a0aa776eSAlan Wright nbtd.nbs_ns.s_up = B_FALSE;
341a0aa776eSAlan Wright break;
342a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_STOP:
343a0aa776eSAlan Wright nbtd.nbs_dgm.s_up = B_FALSE;
344a0aa776eSAlan Wright break;
345a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_STOP:
346a0aa776eSAlan Wright nbtd.nbs_browser.s_up = B_FALSE;
347a0aa776eSAlan Wright break;
348a0aa776eSAlan Wright case NETBIOS_EVENT_TIMER_STOP:
349a0aa776eSAlan Wright nbtd.nbs_timer.s_up = B_FALSE;
350a0aa776eSAlan Wright break;
351a0aa776eSAlan Wright case NETBIOS_EVENT_STOP:
352a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_CLOSING;
353a0aa776eSAlan Wright break;
354a0aa776eSAlan Wright case NETBIOS_EVENT_RESET:
355a0aa776eSAlan Wright nbtd.nbs_state = NETBIOS_STATE_INIT;
356a0aa776eSAlan Wright break;
357a0aa776eSAlan Wright case NETBIOS_EVENT_ERROR:
358a0aa776eSAlan Wright ++nbtd.nbs_errors;
359a0aa776eSAlan Wright break;
360a0aa776eSAlan Wright default:
361a0aa776eSAlan Wright break;
362a0aa776eSAlan Wright }
363a0aa776eSAlan Wright break;
364a0aa776eSAlan Wright }
365a0aa776eSAlan Wright
366a0aa776eSAlan Wright smb_netbios_dump();
367a0aa776eSAlan Wright (void) cond_broadcast(&nbtd.nbs_cv);
368a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx);
369a0aa776eSAlan Wright }
370a0aa776eSAlan Wright
371a0aa776eSAlan Wright void
smb_netbios_wait(netbios_event_t event)372a0aa776eSAlan Wright smb_netbios_wait(netbios_event_t event)
373a0aa776eSAlan Wright {
374a0aa776eSAlan Wright boolean_t *svc = NULL;
375a0aa776eSAlan Wright boolean_t desired_state;
376a0aa776eSAlan Wright
377a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx);
378a0aa776eSAlan Wright
379a0aa776eSAlan Wright switch (event) {
380a0aa776eSAlan Wright case NETBIOS_EVENT_NS_START:
381a0aa776eSAlan Wright case NETBIOS_EVENT_NS_STOP:
382a0aa776eSAlan Wright svc = &nbtd.nbs_ns.s_up;
383a0aa776eSAlan Wright desired_state =
384a0aa776eSAlan Wright (event == NETBIOS_EVENT_NS_START) ? B_TRUE : B_FALSE;
385a0aa776eSAlan Wright break;
386a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_START:
387a0aa776eSAlan Wright case NETBIOS_EVENT_DGM_STOP:
388a0aa776eSAlan Wright svc = &nbtd.nbs_dgm.s_up;
389a0aa776eSAlan Wright desired_state =
390a0aa776eSAlan Wright (event == NETBIOS_EVENT_DGM_START) ? B_TRUE : B_FALSE;
391a0aa776eSAlan Wright break;
392a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_START:
393a0aa776eSAlan Wright case NETBIOS_EVENT_BROWSER_STOP:
394a0aa776eSAlan Wright svc = &nbtd.nbs_browser.s_up;
395a0aa776eSAlan Wright desired_state =
396a0aa776eSAlan Wright (event == NETBIOS_EVENT_BROWSER_START) ? B_TRUE : B_FALSE;
397a0aa776eSAlan Wright break;
398a0aa776eSAlan Wright default:
399a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx);
400a0aa776eSAlan Wright return;
401a0aa776eSAlan Wright }
402a0aa776eSAlan Wright
403a0aa776eSAlan Wright while (*svc != desired_state) {
404a0aa776eSAlan Wright if (nbtd.nbs_state != NETBIOS_STATE_RUNNING)
405a0aa776eSAlan Wright break;
406a0aa776eSAlan Wright
407a0aa776eSAlan Wright (void) cond_wait(&nbtd.nbs_cv, &nbtd.nbs_mtx);
408a0aa776eSAlan Wright }
409a0aa776eSAlan Wright
410a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx);
411a0aa776eSAlan Wright }
412a0aa776eSAlan Wright
413a0aa776eSAlan Wright void
smb_netbios_sleep(time_t seconds)414a0aa776eSAlan Wright smb_netbios_sleep(time_t seconds)
415a0aa776eSAlan Wright {
416a0aa776eSAlan Wright timestruc_t reltimeout;
417a0aa776eSAlan Wright
418a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx);
419a0aa776eSAlan Wright
420a0aa776eSAlan Wright if (nbtd.nbs_state == NETBIOS_STATE_RUNNING) {
421a0aa776eSAlan Wright if (seconds == 0)
422a0aa776eSAlan Wright seconds = 1;
423a0aa776eSAlan Wright reltimeout.tv_sec = seconds;
424a0aa776eSAlan Wright reltimeout.tv_nsec = 0;
425a0aa776eSAlan Wright
426a0aa776eSAlan Wright (void) cond_reltimedwait(&nbtd.nbs_cv,
427a0aa776eSAlan Wright &nbtd.nbs_mtx, &reltimeout);
428a0aa776eSAlan Wright }
429a0aa776eSAlan Wright
430a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx);
431a0aa776eSAlan Wright }
432a0aa776eSAlan Wright
433a0aa776eSAlan Wright boolean_t
smb_netbios_running(void)434a0aa776eSAlan Wright smb_netbios_running(void)
435a0aa776eSAlan Wright {
436a0aa776eSAlan Wright boolean_t is_running;
437a0aa776eSAlan Wright
438a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx);
439a0aa776eSAlan Wright
440a0aa776eSAlan Wright if (nbtd.nbs_state == NETBIOS_STATE_RUNNING)
441a0aa776eSAlan Wright is_running = B_TRUE;
442a0aa776eSAlan Wright else
443a0aa776eSAlan Wright is_running = B_FALSE;
444a0aa776eSAlan Wright
445a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx);
446a0aa776eSAlan Wright return (is_running);
447a0aa776eSAlan Wright }
448a0aa776eSAlan Wright
449a0aa776eSAlan Wright boolean_t
smb_netbios_error(void)450a0aa776eSAlan Wright smb_netbios_error(void)
451a0aa776eSAlan Wright {
452a0aa776eSAlan Wright boolean_t error;
453a0aa776eSAlan Wright
454a0aa776eSAlan Wright (void) mutex_lock(&nbtd.nbs_mtx);
455a0aa776eSAlan Wright
456a0aa776eSAlan Wright if (nbtd.nbs_state == NETBIOS_STATE_ERROR)
457a0aa776eSAlan Wright error = B_TRUE;
458a0aa776eSAlan Wright else
459a0aa776eSAlan Wright error = B_FALSE;
460a0aa776eSAlan Wright
461a0aa776eSAlan Wright (void) mutex_unlock(&nbtd.nbs_mtx);
462a0aa776eSAlan Wright return (error);
463a0aa776eSAlan Wright }
464a0aa776eSAlan Wright
465a0aa776eSAlan Wright /*
466a0aa776eSAlan Wright * Write the service state to /var/run/smb/netbios.
467a0aa776eSAlan Wright *
468a0aa776eSAlan Wright * This is a private interface. To update the file use:
469a0aa776eSAlan Wright * smb_netbios_event(NETBIOS_EVENT_DUMP);
470a0aa776eSAlan Wright */
471a0aa776eSAlan Wright static void
smb_netbios_dump(void)472a0aa776eSAlan Wright smb_netbios_dump(void)
473a0aa776eSAlan Wright {
474a0aa776eSAlan Wright static struct {
475a0aa776eSAlan Wright netbios_state_t state;
476a0aa776eSAlan Wright char *text;
477a0aa776eSAlan Wright } sm[] = {
478a0aa776eSAlan Wright { NETBIOS_STATE_INIT, "init" },
479a0aa776eSAlan Wright { NETBIOS_STATE_RUNNING, "running" },
480a0aa776eSAlan Wright { NETBIOS_STATE_CLOSING, "closing" },
481a0aa776eSAlan Wright { NETBIOS_STATE_ERROR, "error" }
482a0aa776eSAlan Wright };
483a0aa776eSAlan Wright
484a0aa776eSAlan Wright char fname[MAXPATHLEN];
485a0aa776eSAlan Wright FILE *fp;
486a0aa776eSAlan Wright struct passwd *pwd;
487a0aa776eSAlan Wright struct group *grp;
488a0aa776eSAlan Wright uid_t uid;
489a0aa776eSAlan Wright gid_t gid;
490a0aa776eSAlan Wright char *last_event = "none";
491a0aa776eSAlan Wright int i;
492a0aa776eSAlan Wright
493a0aa776eSAlan Wright (void) snprintf(fname, MAXPATHLEN, "%s/%s",
494a0aa776eSAlan Wright SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE);
495a0aa776eSAlan Wright
496a0aa776eSAlan Wright if ((fp = fopen(fname, "w")) == NULL)
497a0aa776eSAlan Wright return;
498a0aa776eSAlan Wright
499a0aa776eSAlan Wright pwd = getpwnam("root");
500a0aa776eSAlan Wright grp = getgrnam("sys");
501a0aa776eSAlan Wright uid = (pwd == NULL) ? 0 : pwd->pw_uid;
502a0aa776eSAlan Wright gid = (grp == NULL) ? 3 : grp->gr_gid;
503a0aa776eSAlan Wright
504a0aa776eSAlan Wright (void) lockf(fileno(fp), F_LOCK, 0);
505a0aa776eSAlan Wright (void) fchmod(fileno(fp), 0600);
506a0aa776eSAlan Wright (void) fchown(fileno(fp), uid, gid);
507a0aa776eSAlan Wright
508a0aa776eSAlan Wright if (nbtd.nbs_last_event)
509a0aa776eSAlan Wright last_event = nbtd.nbs_last_event;
510a0aa776eSAlan Wright
511a0aa776eSAlan Wright for (i = 0; i < sizeof (sm) / sizeof (sm[0]); ++i) {
512a0aa776eSAlan Wright if (nbtd.nbs_state == sm[i].state) {
513a0aa776eSAlan Wright (void) fprintf(fp,
514a0aa776eSAlan Wright "State %s (event: %s, errors: %u)\n",
515a0aa776eSAlan Wright sm[i].text, last_event, nbtd.nbs_errors);
516a0aa776eSAlan Wright break;
517a0aa776eSAlan Wright }
518a0aa776eSAlan Wright }
519a0aa776eSAlan Wright
520a0aa776eSAlan Wright (void) fprintf(fp, "Name Service %-7s (%u)\n",
521a0aa776eSAlan Wright nbtd.nbs_ns.s_up ? "up" : "down", nbtd.nbs_ns.s_tid);
522a0aa776eSAlan Wright (void) fprintf(fp, "Datagram Service %-7s (%u)\n",
523a0aa776eSAlan Wright nbtd.nbs_dgm.s_up ? "up" : "down", nbtd.nbs_dgm.s_tid);
524a0aa776eSAlan Wright (void) fprintf(fp, "Browser Service %-7s (%u)\n",
525a0aa776eSAlan Wright nbtd.nbs_browser.s_up ? "up" : "down", nbtd.nbs_browser.s_tid);
526a0aa776eSAlan Wright (void) fprintf(fp, "Timer Service %-7s (%u)\n",
527a0aa776eSAlan Wright nbtd.nbs_timer.s_up ? "up" : "down", nbtd.nbs_timer.s_tid);
528a0aa776eSAlan Wright
529a0aa776eSAlan Wright smb_netbios_cache_dump(fp);
530a0aa776eSAlan Wright
531a0aa776eSAlan Wright (void) lockf(fileno(fp), F_ULOCK, 0);
532a0aa776eSAlan Wright (void) fclose(fp);
533a0aa776eSAlan Wright }
534