xref: /illumos-gate/usr/src/cmd/smbsrv/smbd/smbd_main.c (revision e44e85a7f9935f0428e188393e3da61b17e83884)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/ioccom.h>
29 #include <sys/corectl.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <stdarg.h>
36 #include <fcntl.h>
37 #include <wait.h>
38 #include <signal.h>
39 #include <atomic.h>
40 #include <libscf.h>
41 #include <limits.h>
42 #include <priv_utils.h>
43 #include <door.h>
44 #include <errno.h>
45 #include <pthread.h>
46 #include <time.h>
47 #include <libscf.h>
48 #include <zone.h>
49 #include <libgen.h>
50 #include <pwd.h>
51 #include <grp.h>
52 
53 #include <smbsrv/smb_door_svc.h>
54 #include <smbsrv/smb_ioctl.h>
55 #include <smbsrv/libsmb.h>
56 #include <smbsrv/libsmbns.h>
57 #include <smbsrv/libsmbrdr.h>
58 #include <smbsrv/libmlsvc.h>
59 #include "smbd.h"
60 
61 #define	DRV_DEVICE_PATH	"/devices/pseudo/smbsrv@0:smbsrv"
62 #define	SMB_DBDIR "/var/smb"
63 
64 static void *smbd_nbt_listener(void *);
65 static void *smbd_tcp_listener(void *);
66 static void *smbd_nbt_receiver(void *);
67 static void *smbd_tcp_receiver(void *);
68 
69 static int smbd_daemonize_init(void);
70 static void smbd_daemonize_fini(int, int);
71 static int smb_init_daemon_priv(int, uid_t, gid_t);
72 
73 static int smbd_kernel_bind(void);
74 static void smbd_kernel_unbind(void);
75 static int smbd_already_running(void);
76 
77 static int smbd_service_init(void);
78 static void smbd_service_fini(void);
79 
80 static int smbd_setup_options(int argc, char *argv[]);
81 static void smbd_usage(FILE *fp);
82 static void smbd_report(const char *fmt, ...);
83 
84 static void smbd_sig_handler(int sig);
85 
86 static int32_t smbd_gmtoff(void);
87 static int smbd_localtime_init(void);
88 static void *smbd_localtime_monitor(void *arg);
89 
90 static pthread_t localtime_thr;
91 
92 static int smbd_refresh_init(void);
93 static void smbd_refresh_fini(void);
94 static void *smbd_refresh_monitor(void *);
95 static void smbd_refresh_dc(void);
96 
97 static void *smbd_nbt_receiver(void *);
98 static void *smbd_nbt_listener(void *);
99 
100 static void *smbd_tcp_receiver(void *);
101 static void *smbd_tcp_listener(void *);
102 
103 static int smbd_start_listeners(void);
104 static void smbd_stop_listeners(void);
105 static int smbd_kernel_start(void);
106 
107 static void smbd_fatal_error(const char *);
108 
109 static pthread_t refresh_thr;
110 static pthread_cond_t refresh_cond;
111 static pthread_mutex_t refresh_mutex;
112 
113 smbd_t smbd;
114 
115 /*
116  * smbd user land daemon
117  *
118  * Use SMF error codes only on return or exit.
119  */
120 int
121 main(int argc, char *argv[])
122 {
123 	struct sigaction	act;
124 	sigset_t		set;
125 	uid_t			uid;
126 	int			pfd = -1;
127 	uint_t			sigval;
128 
129 	smbd.s_pname = basename(argv[0]);
130 	openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
131 
132 	if (smbd_setup_options(argc, argv) != 0)
133 		return (SMF_EXIT_ERR_FATAL);
134 
135 	if ((uid = getuid()) != smbd.s_uid) {
136 		smbd_report("user %d: %s", uid, strerror(EPERM));
137 		return (SMF_EXIT_ERR_FATAL);
138 	}
139 
140 	if (getzoneid() != GLOBAL_ZONEID) {
141 		smbd_report("non-global zones are not supported");
142 		return (SMF_EXIT_ERR_FATAL);
143 	}
144 
145 	if (is_system_labeled()) {
146 		smbd_report("Trusted Extensions not supported");
147 		return (SMF_EXIT_ERR_FATAL);
148 	}
149 
150 	if (smbd_already_running())
151 		return (SMF_EXIT_OK);
152 
153 	(void) sigfillset(&set);
154 	(void) sigdelset(&set, SIGABRT);
155 
156 	(void) sigfillset(&act.sa_mask);
157 	act.sa_handler = smbd_sig_handler;
158 	act.sa_flags = 0;
159 
160 	(void) sigaction(SIGTERM, &act, NULL);
161 	(void) sigaction(SIGHUP, &act, NULL);
162 	(void) sigaction(SIGINT, &act, NULL);
163 	(void) sigaction(SIGPIPE, &act, NULL);
164 
165 	(void) sigdelset(&set, SIGTERM);
166 	(void) sigdelset(&set, SIGHUP);
167 	(void) sigdelset(&set, SIGINT);
168 	(void) sigdelset(&set, SIGPIPE);
169 
170 	if (smbd.s_fg) {
171 		(void) sigdelset(&set, SIGTSTP);
172 		(void) sigdelset(&set, SIGTTIN);
173 		(void) sigdelset(&set, SIGTTOU);
174 
175 		if (smbd_service_init() != 0) {
176 			smbd_report("service initialization failed");
177 			exit(SMF_EXIT_ERR_FATAL);
178 		}
179 	} else {
180 		/*
181 		 * "pfd" is a pipe descriptor -- any fatal errors
182 		 * during subsequent initialization of the child
183 		 * process should be written to this pipe and the
184 		 * parent will report this error as the exit status.
185 		 */
186 		pfd = smbd_daemonize_init();
187 
188 		if (smbd_service_init() != 0) {
189 			smbd_report("daemon initialization failed");
190 			exit(SMF_EXIT_ERR_FATAL);
191 		}
192 
193 		smbd_daemonize_fini(pfd, SMF_EXIT_OK);
194 	}
195 
196 	(void) atexit(smbd_service_fini);
197 
198 	while (!smbd.s_shutting_down) {
199 		if (smbd.s_sigval == 0 && smbd.s_refreshes == 0)
200 			(void) sigsuspend(&set);
201 
202 		sigval = atomic_swap_uint(&smbd.s_sigval, 0);
203 
204 		switch (sigval) {
205 		case 0:
206 		case SIGPIPE:
207 			break;
208 
209 		case SIGHUP:
210 			syslog(LOG_DEBUG, "refresh requested");
211 			(void) pthread_cond_signal(&refresh_cond);
212 			break;
213 
214 		default:
215 			/*
216 			 * Typically SIGINT or SIGTERM.
217 			 */
218 			smbd.s_shutting_down = B_TRUE;
219 			break;
220 		}
221 	}
222 
223 	smbd_service_fini();
224 	closelog();
225 	return ((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL : SMF_EXIT_OK);
226 }
227 
228 /*
229  * This function will fork off a child process,
230  * from which only the child will return.
231  *
232  * Use SMF error codes only on exit.
233  */
234 static int
235 smbd_daemonize_init(void)
236 {
237 	int status, pfds[2];
238 	sigset_t set, oset;
239 	pid_t pid;
240 	int rc;
241 
242 	/*
243 	 * Reset privileges to the minimum set required. We continue
244 	 * to run as root to create and access files in /var.
245 	 */
246 	rc = smb_init_daemon_priv(PU_RESETGROUPS, smbd.s_uid, smbd.s_gid);
247 
248 	if (rc != 0) {
249 		smbd_report("insufficient privileges");
250 		exit(SMF_EXIT_ERR_FATAL);
251 	}
252 
253 	/*
254 	 * Block all signals prior to the fork and leave them blocked in the
255 	 * parent so we don't get in a situation where the parent gets SIGINT
256 	 * and returns non-zero exit status and the child is actually running.
257 	 * In the child, restore the signal mask once we've done our setsid().
258 	 */
259 	(void) sigfillset(&set);
260 	(void) sigdelset(&set, SIGABRT);
261 	(void) sigprocmask(SIG_BLOCK, &set, &oset);
262 
263 	if (pipe(pfds) == -1) {
264 		smbd_report("unable to create pipe");
265 		exit(SMF_EXIT_ERR_FATAL);
266 	}
267 
268 	closelog();
269 
270 	if ((pid = fork()) == -1) {
271 		openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
272 		smbd_report("unable to fork");
273 		closelog();
274 		exit(SMF_EXIT_ERR_FATAL);
275 	}
276 
277 	/*
278 	 * If we're the parent process, wait for either the child to send us
279 	 * the appropriate exit status over the pipe or for the read to fail
280 	 * (presumably with 0 for EOF if our child terminated abnormally).
281 	 * If the read fails, exit with either the child's exit status if it
282 	 * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal.
283 	 */
284 	if (pid != 0) {
285 		(void) close(pfds[1]);
286 
287 		if (read(pfds[0], &status, sizeof (status)) == sizeof (status))
288 			_exit(status);
289 
290 		if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
291 			_exit(WEXITSTATUS(status));
292 
293 		_exit(SMF_EXIT_ERR_FATAL);
294 	}
295 
296 	openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
297 	(void) setsid();
298 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
299 	(void) chdir("/");
300 	(void) umask(022);
301 	(void) close(pfds[0]);
302 
303 	return (pfds[1]);
304 }
305 
306 /*
307  * This function is based on __init_daemon_priv() and replaces
308  * __init_daemon_priv() since we want smbd to have all privileges so that it
309  * can execute map/unmap commands with all privileges during share
310  * connection/disconnection.  Unused privileges are disabled until command
311  * execution.  The permitted and the limit set contains all privileges.  The
312  * inheritable set contains no privileges.
313  */
314 
315 static const char root_cp[] = "/core.%f.%t";
316 static const char daemon_cp[] = "/var/tmp/core.%f.%t";
317 
318 static int
319 smb_init_daemon_priv(int flags, uid_t uid, gid_t gid)
320 {
321 	priv_set_t *perm = NULL;
322 	int ret = -1;
323 	char buf[1024];
324 
325 	/*
326 	 * This is not a significant failure: it allows us to start programs
327 	 * with sufficient privileges and with the proper uid.   We don't
328 	 * care enough about the extra groups in that case.
329 	 */
330 	if (flags & PU_RESETGROUPS)
331 		(void) setgroups(0, NULL);
332 
333 	if (gid != (gid_t)-1 && setgid(gid) != 0)
334 		goto end;
335 
336 	perm = priv_allocset();
337 	if (perm == NULL)
338 		goto end;
339 
340 	/* E = P */
341 	(void) getppriv(PRIV_PERMITTED, perm);
342 	(void) setppriv(PRIV_SET, PRIV_EFFECTIVE, perm);
343 
344 	/* Now reset suid and euid */
345 	if (uid != (uid_t)-1 && setreuid(uid, uid) != 0)
346 		goto end;
347 
348 	/* I = 0 */
349 	priv_emptyset(perm);
350 	ret = setppriv(PRIV_SET, PRIV_INHERITABLE, perm);
351 end:
352 	priv_freeset(perm);
353 
354 	if (core_get_process_path(buf, sizeof (buf), getpid()) == 0 &&
355 	    strcmp(buf, "core") == 0) {
356 
357 		if ((uid == (uid_t)-1 ? geteuid() : uid) == 0) {
358 			(void) core_set_process_path(root_cp, sizeof (root_cp),
359 			    getpid());
360 		} else {
361 			(void) core_set_process_path(daemon_cp,
362 			    sizeof (daemon_cp), getpid());
363 		}
364 	}
365 	(void) setpflags(__PROC_PROTECT, 0);
366 
367 	return (ret);
368 }
369 
370 /*
371  * Most privileges, except the ones that are required for smbd, are turn off
372  * in the effective set.  They will be turn on when needed for command
373  * execution during share connection/disconnection.
374  */
375 static void
376 smbd_daemonize_fini(int fd, int exit_status)
377 {
378 	priv_set_t *pset;
379 
380 	/*
381 	 * Now that we're running, if a pipe fd was specified, write an exit
382 	 * status to it to indicate that our parent process can safely detach.
383 	 * Then proceed to loading the remaining non-built-in modules.
384 	 */
385 	if (fd >= 0)
386 		(void) write(fd, &exit_status, sizeof (exit_status));
387 
388 	(void) close(fd);
389 
390 	if ((fd = open("/dev/null", O_RDWR)) >= 0) {
391 		(void) fcntl(fd, F_DUP2FD, STDIN_FILENO);
392 		(void) fcntl(fd, F_DUP2FD, STDOUT_FILENO);
393 		(void) fcntl(fd, F_DUP2FD, STDERR_FILENO);
394 		(void) close(fd);
395 	}
396 
397 	pset = priv_allocset();
398 	if (pset == NULL)
399 		return;
400 
401 	priv_emptyset(pset);
402 
403 	/* list of privileges for smbd */
404 	(void) priv_addset(pset, PRIV_NET_MAC_AWARE);
405 	(void) priv_addset(pset, PRIV_NET_PRIVADDR);
406 	(void) priv_addset(pset, PRIV_PROC_AUDIT);
407 	(void) priv_addset(pset, PRIV_SYS_DEVICES);
408 	(void) priv_addset(pset, PRIV_SYS_SMB);
409 
410 	priv_inverse(pset);
411 
412 	/* turn off unneeded privileges */
413 	(void) setppriv(PRIV_OFF, PRIV_EFFECTIVE, pset);
414 
415 	priv_freeset(pset);
416 
417 	/* reenable core dumps */
418 	__fini_daemon_priv(NULL);
419 }
420 
421 /*
422  * smbd_service_init
423  */
424 static int
425 smbd_service_init(void)
426 {
427 	int	rc;
428 
429 	smbd.s_pid = getpid();
430 	if ((mkdir(SMB_DBDIR, 0700) < 0) && (errno != EEXIST)) {
431 		smbd_report("mkdir %s: %s", SMB_DBDIR, strerror(errno));
432 		return (1);
433 	}
434 
435 	if ((rc = smb_ccache_init(SMB_VARRUN_DIR, SMB_CCACHE_FILE)) != 0) {
436 		if (rc == -1)
437 			smbd_report("mkdir %s: %s", SMB_VARRUN_DIR,
438 			    strerror(errno));
439 		else
440 			smbd_report("unable to set KRB5CCNAME");
441 		return (1);
442 	}
443 
444 
445 	(void) oem_language_set("english");
446 
447 	if (!smb_wka_init()) {
448 		smbd_report("out of memory");
449 		return (1);
450 	}
451 
452 	if (smb_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0)
453 		smbd_report("NIC monitoring failed to start");
454 
455 	(void) dyndns_start();
456 	smbrdr_init();
457 
458 	if (smb_netbios_start() != 0)
459 		smbd_report("NetBIOS services failed to start");
460 	else
461 		smbd_report("NetBIOS services started");
462 
463 	/* Get the ID map client handle */
464 	if ((rc = smb_idmap_start()) != 0) {
465 		smbd_report("no idmap handle");
466 		return (rc);
467 	}
468 
469 	smbd.s_secmode = smb_config_get_secmode();
470 	if ((rc = nt_domain_init(smbd.s_secmode)) != 0) {
471 		if (rc == SMB_DOMAIN_NOMACHINE_SID) {
472 			smbd_report(
473 			    "no machine SID: check idmap configuration");
474 			return (rc);
475 		}
476 	}
477 
478 	smb_ads_init();
479 	if ((rc = mlsvc_init()) != 0) {
480 		smbd_report("msrpc initialization failed");
481 		return (rc);
482 	}
483 
484 	if (smbd.s_secmode == SMB_SECMODE_DOMAIN)
485 		if (smbd_locate_dc_start() != 0)
486 			smbd_report("dc discovery failed %s", strerror(errno));
487 
488 	smbd.s_door_srv = smb_door_srv_start();
489 	if (smbd.s_door_srv < 0)
490 		return (rc);
491 
492 	if ((rc = smbd_refresh_init()) != 0)
493 		return (rc);
494 
495 	dyndns_update_zones();
496 
497 	(void) smbd_localtime_init();
498 
499 	smbd.s_door_opipe = smbd_opipe_dsrv_start();
500 	if (smbd.s_door_opipe < 0) {
501 		smbd_report("opipe initialization failed %s",
502 		    strerror(errno));
503 		return (rc);
504 	}
505 
506 	(void) smb_lgrp_start();
507 
508 	smb_pwd_init(B_TRUE);
509 
510 	if ((rc = smb_shr_start()) != 0) {
511 		smbd_report("share initialization failed: %s", strerror(errno));
512 		return (rc);
513 	}
514 
515 	smbd.s_door_lmshr = smb_share_dsrv_start();
516 	if (smbd.s_door_lmshr < 0) {
517 		smbd_report("share initialization failed");
518 	}
519 
520 	if ((rc = smbd_kernel_bind()) != 0) {
521 		smbd_report("kernel bind error: %s", strerror(errno));
522 		return (rc);
523 	}
524 
525 	if ((rc = smb_shr_load()) != 0) {
526 		smbd_report("failed to start loading shares: %s",
527 		    strerror(errno));
528 		return (rc);
529 	}
530 
531 	return (0);
532 }
533 
534 /*
535  * Close the kernel service and shutdown smbd services.
536  * This function is registered with atexit(): ensure that anything
537  * called from here is safe to be called multiple times.
538  */
539 static void
540 smbd_service_fini(void)
541 {
542 	smbd_opipe_dsrv_stop();
543 	smb_wka_fini();
544 	smbd_refresh_fini();
545 	smbd_kernel_unbind();
546 	smb_door_srv_stop();
547 	smb_share_dsrv_stop();
548 	smb_shr_stop();
549 	dyndns_stop();
550 	smb_nicmon_stop();
551 	smb_idmap_stop();
552 	smb_lgrp_stop();
553 	smb_ccache_remove(SMB_CCACHE_PATH);
554 	smb_pwd_fini();
555 	nt_domain_fini();
556 	mlsvc_fini();
557 	smb_ads_fini();
558 }
559 
560 
561 /*
562  * smbd_refresh_init()
563  *
564  * SMB service refresh thread initialization.  This thread waits for a
565  * refresh event and updates the daemon's view of the configuration
566  * before going back to sleep.
567  */
568 static int
569 smbd_refresh_init()
570 {
571 	pthread_attr_t		tattr;
572 	pthread_condattr_t	cattr;
573 	int			rc;
574 
575 	(void) pthread_condattr_init(&cattr);
576 	(void) pthread_cond_init(&refresh_cond, &cattr);
577 	(void) pthread_condattr_destroy(&cattr);
578 
579 	(void) pthread_mutex_init(&refresh_mutex, NULL);
580 
581 	(void) pthread_attr_init(&tattr);
582 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
583 	rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0);
584 	(void) pthread_attr_destroy(&tattr);
585 
586 	return (rc);
587 }
588 
589 /*
590  * smbd_refresh_fini()
591  *
592  * Stop the refresh thread.
593  */
594 static void
595 smbd_refresh_fini()
596 {
597 	(void) pthread_cancel(refresh_thr);
598 
599 	(void) pthread_cond_destroy(&refresh_cond);
600 	(void) pthread_mutex_destroy(&refresh_mutex);
601 }
602 
603 /*
604  * smbd_refresh_monitor()
605  *
606  * Wait for a refresh event. When this thread wakes up, update the
607  * smbd configuration from the SMF config information then go back to
608  * wait for the next refresh.
609  */
610 /*ARGSUSED*/
611 static void *
612 smbd_refresh_monitor(void *arg)
613 {
614 	smb_kmod_cfg_t	cfg;
615 	int		error;
616 
617 	while (!smbd.s_shutting_down) {
618 		(void) pthread_mutex_lock(&refresh_mutex);
619 		while ((atomic_swap_uint(&smbd.s_refreshes, 0) == 0) &&
620 		    (!smbd.s_shutting_down))
621 			(void) pthread_cond_wait(&refresh_cond, &refresh_mutex);
622 		(void) pthread_mutex_unlock(&refresh_mutex);
623 
624 		if (smbd.s_shutting_down) {
625 			syslog(LOG_DEBUG, "shutting down");
626 			exit((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL :
627 			    SMF_EXIT_OK);
628 		}
629 
630 		/*
631 		 * We've been woken up by a refresh event so go do
632 		 * what is necessary.
633 		 */
634 		smb_ads_refresh();
635 		smb_ccache_remove(SMB_CCACHE_PATH);
636 
637 		/*
638 		 * Start the dyndns thread, if required.
639 		 * Clear the DNS zones for the existing interfaces
640 		 * before updating the NIC interface list.
641 		 */
642 		(void) dyndns_start();
643 		dyndns_clear_zones();
644 
645 		/* re-initialize NIC table */
646 		if (smb_nic_init() != 0)
647 			smbd_report("failed to get NIC information");
648 		smb_netbios_name_reconfig();
649 		smb_browser_reconfig();
650 		smbd_refresh_dc();
651 		dyndns_update_zones();
652 
653 		if (smbd_set_netlogon_cred()) {
654 			/*
655 			 * Restart required because the domain changed
656 			 * or the credential chain setup failed.
657 			 */
658 			if (smb_smf_restart_service() != 0) {
659 				syslog(LOG_ERR,
660 				    "unable to restart smb service. "
661 				    "Run 'svcs -xv smb/server' for more "
662 				    "information.");
663 				smbd.s_shutting_down = B_TRUE;
664 				exit(SMF_EXIT_OK);
665 			}
666 
667 			break;
668 		}
669 
670 		if (!smbd.s_kbound) {
671 			error = smbd_kernel_bind();
672 			if (error != 0)
673 				smbd_report("kernel bind error: %s",
674 				    strerror(error));
675 			else
676 				(void) smb_shr_load();
677 
678 			continue;
679 		}
680 
681 		(void) smb_shr_load();
682 
683 		smb_load_kconfig(&cfg);
684 		error = smb_kmod_setcfg(&cfg);
685 		if (error < 0)
686 			smbd_report("configuration update failed: %s",
687 			    strerror(error));
688 	}
689 
690 	return (NULL);
691 }
692 
693 /*
694  * Update DC information on a refresh.
695  */
696 static void
697 smbd_refresh_dc(void)
698 {
699 	char fqdomain[MAXHOSTNAMELEN];
700 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
701 		return;
702 
703 	if (smb_getfqdomainname(fqdomain, MAXHOSTNAMELEN))
704 		return;
705 
706 	if (smb_locate_dc(fqdomain, "", NULL))
707 		smbd_report("DC discovery failed");
708 }
709 
710 void
711 smbd_set_secmode(int secmode)
712 {
713 	switch (secmode) {
714 	case SMB_SECMODE_WORKGRP:
715 	case SMB_SECMODE_DOMAIN:
716 		(void) smb_config_set_secmode(secmode);
717 		smbd.s_secmode = secmode;
718 		break;
719 
720 	default:
721 		syslog(LOG_ERR, "invalid security mode: %d", secmode);
722 		syslog(LOG_ERR, "entering maintenance mode");
723 		(void) smb_smf_maintenance_mode();
724 	}
725 }
726 
727 /*
728  * If the door has already been opened by another process (non-zero pid
729  * in target), we assume that another smbd is already running.  If there
730  * is a race here, it will be caught later when smbsrv is opened because
731  * only one process is allowed to open the device at a time.
732  */
733 static int
734 smbd_already_running(void)
735 {
736 	door_info_t info;
737 	int door;
738 
739 	if ((door = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
740 		return (0);
741 
742 	if (door_info(door, &info) < 0)
743 		return (0);
744 
745 	if (info.di_target > 0) {
746 		smbd_report("already running: pid %ld\n", info.di_target);
747 		(void) close(door);
748 		return (1);
749 	}
750 
751 	(void) close(door);
752 	return (0);
753 }
754 
755 /*
756  * smbd_kernel_bind
757  *
758  * This function open the smbsrv device and start the kernel service.
759  */
760 static int
761 smbd_kernel_bind(void)
762 {
763 	int rc;
764 
765 	smbd_kernel_unbind();
766 
767 	rc = smb_kmod_bind();
768 	if (rc == 0) {
769 		rc = smbd_kernel_start();
770 		if (rc != 0)
771 			smb_kmod_unbind();
772 		else
773 			smbd.s_kbound = B_TRUE;
774 	}
775 	return (rc);
776 }
777 
778 static int
779 smbd_kernel_start(void)
780 {
781 	smb_kmod_cfg_t	cfg;
782 	int		rc;
783 
784 	smb_load_kconfig(&cfg);
785 	rc = smb_kmod_setcfg(&cfg);
786 	if (rc != 0)
787 		return (rc);
788 
789 	rc = smb_kmod_setgmtoff(smbd_gmtoff());
790 	if (rc != 0)
791 		return (rc);
792 
793 	rc = smb_kmod_start(smbd.s_door_opipe, smbd.s_door_lmshr,
794 	    smbd.s_door_srv);
795 	if (rc != 0)
796 		return (rc);
797 
798 	rc = smbd_start_listeners();
799 	if (rc != 0)
800 		return (rc);
801 
802 	return (0);
803 }
804 
805 /*
806  * smbd_kernel_unbind
807  */
808 static void
809 smbd_kernel_unbind(void)
810 {
811 	smbd_stop_listeners();
812 	smb_kmod_unbind();
813 	smbd.s_kbound = B_FALSE;
814 }
815 
816 /*
817  * Initialization of the localtime thread.
818  * Returns 0 on success, an error number if thread creation fails.
819  */
820 
821 int
822 smbd_localtime_init(void)
823 {
824 	pthread_attr_t tattr;
825 	int rc;
826 
827 	(void) pthread_attr_init(&tattr);
828 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
829 	rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0);
830 	(void) pthread_attr_destroy(&tattr);
831 	return (rc);
832 }
833 
834 /*
835  * Local time thread to kernel land.
836  * Send local gmtoff to kernel module one time at startup
837  * and each time it changes (up to twice a year).
838  * Local gmtoff is checked once every 15 minutes and
839  * since some timezones are aligned on half and qtr hour boundaries,
840  * once an hour would likely suffice.
841  */
842 
843 /*ARGSUSED*/
844 static void *
845 smbd_localtime_monitor(void *arg)
846 {
847 	struct tm local_tm;
848 	time_t secs;
849 	int32_t gmtoff, last_gmtoff = -1;
850 	int timeout;
851 	int error;
852 
853 	for (;;) {
854 		gmtoff = smbd_gmtoff();
855 
856 		if ((last_gmtoff != gmtoff) && smbd.s_kbound) {
857 			error = smb_kmod_setgmtoff(gmtoff);
858 			if (error != 0)
859 				smbd_report("localtime set failed: %s",
860 				    strerror(error));
861 		}
862 
863 		/*
864 		 * Align the next iteration on a fifteen minute boundary.
865 		 */
866 		secs = time(0);
867 		(void) localtime_r(&secs, &local_tm);
868 		timeout = ((15 - (local_tm.tm_min % 15)) * SECSPERMIN);
869 		(void) sleep(timeout);
870 
871 		last_gmtoff = gmtoff;
872 	}
873 
874 	/*NOTREACHED*/
875 	return (NULL);
876 }
877 
878 /*
879  * smbd_gmtoff
880  *
881  * Determine offset from GMT. If daylight saving time use altzone,
882  * otherwise use timezone.
883  */
884 static int32_t
885 smbd_gmtoff(void)
886 {
887 	time_t clock_val;
888 	struct tm *atm;
889 	int32_t gmtoff;
890 
891 	(void) time(&clock_val);
892 	atm = localtime(&clock_val);
893 
894 	gmtoff = (atm->tm_isdst) ? altzone : timezone;
895 
896 	return (gmtoff);
897 }
898 
899 static void
900 smbd_sig_handler(int sigval)
901 {
902 	if (smbd.s_sigval == 0)
903 		(void) atomic_swap_uint(&smbd.s_sigval, sigval);
904 
905 	if (sigval == SIGHUP) {
906 		atomic_inc_uint(&smbd.s_refreshes);
907 		(void) pthread_cond_signal(&refresh_cond);
908 	}
909 
910 	if (sigval == SIGINT || sigval == SIGTERM) {
911 		smbd.s_shutting_down = B_TRUE;
912 		(void) pthread_cond_signal(&refresh_cond);
913 	}
914 }
915 
916 /*
917  * Set up configuration options and parse the command line.
918  * This function will determine if we will run as a daemon
919  * or in the foreground.
920  *
921  * Failure to find a uid or gid results in using the default (0).
922  */
923 static int
924 smbd_setup_options(int argc, char *argv[])
925 {
926 	struct passwd *pwd;
927 	struct group *grp;
928 	int c;
929 
930 	if ((pwd = getpwnam("root")) != NULL)
931 		smbd.s_uid = pwd->pw_uid;
932 
933 	if ((grp = getgrnam("sys")) != NULL)
934 		smbd.s_gid = grp->gr_gid;
935 
936 	smbd.s_fg = smb_config_get_fg_flag();
937 
938 	while ((c = getopt(argc, argv, ":f")) != -1) {
939 		switch (c) {
940 		case 'f':
941 			smbd.s_fg = 1;
942 			break;
943 
944 		case ':':
945 		case '?':
946 		default:
947 			smbd_usage(stderr);
948 			return (-1);
949 		}
950 	}
951 
952 	return (0);
953 }
954 
955 static void
956 smbd_usage(FILE *fp)
957 {
958 	static char *help[] = {
959 		"-f  run program in foreground"
960 	};
961 
962 	int i;
963 
964 	(void) fprintf(fp, "Usage: %s [-f]\n", smbd.s_pname);
965 
966 	for (i = 0; i < sizeof (help)/sizeof (help[0]); ++i)
967 		(void) fprintf(fp, "    %s\n", help[i]);
968 }
969 
970 static void
971 smbd_report(const char *fmt, ...)
972 {
973 	char buf[128];
974 	va_list ap;
975 
976 	if (fmt == NULL)
977 		return;
978 
979 	va_start(ap, fmt);
980 	(void) vsnprintf(buf, 128, fmt, ap);
981 	va_end(ap);
982 
983 	(void) fprintf(stderr, "smbd: %s\n", buf);
984 }
985 
986 static int
987 smbd_start_listeners(void)
988 {
989 	int		rc1;
990 	int		rc2;
991 	pthread_attr_t	tattr;
992 
993 	(void) pthread_attr_init(&tattr);
994 
995 	if (!smbd.s_nbt_listener_running) {
996 		rc1 = pthread_create(&smbd.s_nbt_listener_id, &tattr,
997 		    smbd_nbt_listener, NULL);
998 		if (rc1 != 0)
999 			smbd_report("unable to start NBT service");
1000 		else
1001 			smbd.s_nbt_listener_running = B_TRUE;
1002 	}
1003 
1004 	if (!smbd.s_tcp_listener_running) {
1005 		rc2 = pthread_create(&smbd.s_tcp_listener_id, &tattr,
1006 		    smbd_tcp_listener, NULL);
1007 		if (rc2 != 0)
1008 			smbd_report("unable to start TCP service");
1009 		else
1010 			smbd.s_tcp_listener_running = B_TRUE;
1011 	}
1012 
1013 	(void) pthread_attr_destroy(&tattr);
1014 
1015 	if (rc1 != 0)
1016 		return (rc1);
1017 	return (rc2);
1018 }
1019 
1020 static void
1021 smbd_stop_listeners(void)
1022 {
1023 	void	*status;
1024 
1025 	if (smbd.s_nbt_listener_running) {
1026 		(void) pthread_kill(smbd.s_nbt_listener_id, SIGTERM);
1027 		(void) pthread_join(smbd.s_nbt_listener_id, &status);
1028 		smbd.s_nbt_listener_running = B_FALSE;
1029 	}
1030 
1031 	if (smbd.s_tcp_listener_running) {
1032 		(void) pthread_kill(smbd.s_tcp_listener_id, SIGTERM);
1033 		(void) pthread_join(smbd.s_tcp_listener_id, &status);
1034 		smbd.s_tcp_listener_running = B_FALSE;
1035 	}
1036 }
1037 
1038 /*
1039  * Perform fatal error exit.
1040  */
1041 static void
1042 smbd_fatal_error(const char *msg)
1043 {
1044 	if (msg == NULL)
1045 		msg = "Fatal error";
1046 
1047 	smbd_report("%s", msg);
1048 	smbd.s_fatal_error = B_TRUE;
1049 	(void) kill(smbd.s_pid, SIGTERM);
1050 }
1051 
1052 /*ARGSUSED*/
1053 static void *
1054 smbd_nbt_receiver(void *arg)
1055 {
1056 	(void) smb_kmod_nbtreceive();
1057 	return (NULL);
1058 }
1059 
1060 /*ARGSUSED*/
1061 static void *
1062 smbd_nbt_listener(void *arg)
1063 {
1064 	pthread_attr_t	tattr;
1065 	sigset_t	set;
1066 	sigset_t	oset;
1067 	pthread_t	tid;
1068 	int		error = 0;
1069 
1070 	(void) sigfillset(&set);
1071 	(void) sigdelset(&set, SIGTERM);
1072 	(void) sigdelset(&set, SIGINT);
1073 	(void) pthread_sigmask(SIG_SETMASK, &set, &oset);
1074 	(void) pthread_attr_init(&tattr);
1075 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1076 
1077 	while (smb_kmod_nbtlisten(error) == 0)
1078 		error = pthread_create(&tid, &tattr, smbd_nbt_receiver, NULL);
1079 
1080 	(void) pthread_attr_destroy(&tattr);
1081 
1082 	if (!smbd.s_shutting_down)
1083 		smbd_fatal_error("NBT listener thread terminated unexpectedly");
1084 
1085 	return (NULL);
1086 }
1087 
1088 /*ARGSUSED*/
1089 static void *
1090 smbd_tcp_receiver(void *arg)
1091 {
1092 	(void) smb_kmod_tcpreceive();
1093 	return (NULL);
1094 }
1095 
1096 /*ARGSUSED*/
1097 static void *
1098 smbd_tcp_listener(void *arg)
1099 {
1100 	pthread_attr_t	tattr;
1101 	sigset_t	set;
1102 	sigset_t	oset;
1103 	pthread_t	tid;
1104 	int		error = 0;
1105 
1106 	(void) sigfillset(&set);
1107 	(void) sigdelset(&set, SIGTERM);
1108 	(void) sigdelset(&set, SIGINT);
1109 	(void) pthread_sigmask(SIG_SETMASK, &set, &oset);
1110 	(void) pthread_attr_init(&tattr);
1111 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1112 
1113 	while (smb_kmod_tcplisten(error) == 0)
1114 		error = pthread_create(&tid, &tattr, smbd_tcp_receiver, NULL);
1115 
1116 	(void) pthread_attr_destroy(&tattr);
1117 
1118 	if (!smbd.s_shutting_down)
1119 		smbd_fatal_error("TCP listener thread terminated unexpectedly");
1120 
1121 	return (NULL);
1122 }
1123 
1124 /*
1125  * Enable libumem debugging by default on DEBUG builds.
1126  */
1127 #ifdef DEBUG
1128 const char *
1129 _umem_debug_init(void)
1130 {
1131 	return ("default,verbose"); /* $UMEM_DEBUG setting */
1132 }
1133 
1134 const char *
1135 _umem_logging_init(void)
1136 {
1137 	return ("fail,contents"); /* $UMEM_LOGGING setting */
1138 }
1139 #endif
1140