xref: /titanic_44/usr/src/cmd/smbsrv/smbd/smbd_main.c (revision ad09f8b827db90c9a0093f0b6382803fa64a5fd1)
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/string.h>
56 #include <smbsrv/libsmb.h>
57 #include <smbsrv/libsmbns.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 	pset = priv_allocset();
391 	if (pset == NULL)
392 		return;
393 
394 	priv_emptyset(pset);
395 
396 	/* list of privileges for smbd */
397 	(void) priv_addset(pset, PRIV_NET_MAC_AWARE);
398 	(void) priv_addset(pset, PRIV_NET_PRIVADDR);
399 	(void) priv_addset(pset, PRIV_PROC_AUDIT);
400 	(void) priv_addset(pset, PRIV_SYS_DEVICES);
401 	(void) priv_addset(pset, PRIV_SYS_SMB);
402 
403 	priv_inverse(pset);
404 
405 	/* turn off unneeded privileges */
406 	(void) setppriv(PRIV_OFF, PRIV_EFFECTIVE, pset);
407 
408 	priv_freeset(pset);
409 
410 	/* reenable core dumps */
411 	__fini_daemon_priv(NULL);
412 }
413 
414 /*
415  * smbd_service_init
416  */
417 static int
418 smbd_service_init(void)
419 {
420 	int	rc;
421 
422 	smbd.s_pid = getpid();
423 	if ((mkdir(SMB_DBDIR, 0700) < 0) && (errno != EEXIST)) {
424 		smbd_report("mkdir %s: %s", SMB_DBDIR, strerror(errno));
425 		return (1);
426 	}
427 
428 	if ((rc = smb_ccache_init(SMB_VARRUN_DIR, SMB_CCACHE_FILE)) != 0) {
429 		if (rc == -1)
430 			smbd_report("mkdir %s: %s", SMB_VARRUN_DIR,
431 			    strerror(errno));
432 		else
433 			smbd_report("unable to set KRB5CCNAME");
434 		return (1);
435 	}
436 
437 	smb_codepage_init();
438 
439 	if (!smb_wka_init()) {
440 		smbd_report("out of memory");
441 		return (1);
442 	}
443 
444 	if (smb_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0)
445 		smbd_report("NIC monitoring failed to start");
446 
447 	(void) dyndns_start();
448 	smb_ipc_init();
449 
450 	if (smb_netbios_start() != 0)
451 		smbd_report("NetBIOS services failed to start");
452 	else
453 		smbd_report("NetBIOS services started");
454 
455 	/* Get the ID map client handle */
456 	if ((rc = smb_idmap_start()) != 0) {
457 		smbd_report("no idmap handle");
458 		return (rc);
459 	}
460 
461 	smbd.s_secmode = smb_config_get_secmode();
462 	if ((rc = smb_domain_init(smbd.s_secmode)) != 0) {
463 		if (rc == SMB_DOMAIN_NOMACHINE_SID) {
464 			smbd_report(
465 			    "no machine SID: check idmap configuration");
466 			return (rc);
467 		}
468 	}
469 
470 	smb_ads_init();
471 	if ((rc = mlsvc_init()) != 0) {
472 		smbd_report("msrpc initialization failed");
473 		return (rc);
474 	}
475 
476 	if (smbd.s_secmode == SMB_SECMODE_DOMAIN)
477 		if (smbd_locate_dc_start() != 0)
478 			smbd_report("dc discovery failed %s", strerror(errno));
479 
480 	smbd.s_door_srv = smb_door_srv_start();
481 	if (smbd.s_door_srv < 0)
482 		return (rc);
483 
484 	if ((rc = smbd_refresh_init()) != 0)
485 		return (rc);
486 
487 	dyndns_update_zones();
488 
489 	(void) smbd_localtime_init();
490 
491 	smbd.s_door_opipe = smbd_opipe_dsrv_start();
492 	if (smbd.s_door_opipe < 0) {
493 		smbd_report("opipe initialization failed %s",
494 		    strerror(errno));
495 		return (rc);
496 	}
497 
498 	(void) smb_lgrp_start();
499 
500 	smb_pwd_init(B_TRUE);
501 
502 	if ((rc = smb_shr_start()) != 0) {
503 		smbd_report("share initialization failed: %s", strerror(errno));
504 		return (rc);
505 	}
506 
507 	smbd.s_door_lmshr = smb_share_dsrv_start();
508 	if (smbd.s_door_lmshr < 0) {
509 		smbd_report("share initialization failed");
510 	}
511 
512 	if ((rc = smbd_kernel_bind()) != 0) {
513 		smbd_report("kernel bind error: %s", strerror(errno));
514 		return (rc);
515 	}
516 
517 	if ((rc = smb_shr_load()) != 0) {
518 		smbd_report("failed to start loading shares: %s",
519 		    strerror(errno));
520 		return (rc);
521 	}
522 
523 	return (0);
524 }
525 
526 /*
527  * Close the kernel service and shutdown smbd services.
528  * This function is registered with atexit(): ensure that anything
529  * called from here is safe to be called multiple times.
530  */
531 static void
532 smbd_service_fini(void)
533 {
534 	smbd_opipe_dsrv_stop();
535 	smb_wka_fini();
536 	smbd_refresh_fini();
537 	smbd_kernel_unbind();
538 	smb_door_srv_stop();
539 	smb_share_dsrv_stop();
540 	smb_shr_stop();
541 	dyndns_stop();
542 	smb_nicmon_stop();
543 	smb_idmap_stop();
544 	smb_lgrp_stop();
545 	smb_ccache_remove(SMB_CCACHE_PATH);
546 	smb_pwd_fini();
547 	smb_domain_fini();
548 	mlsvc_fini();
549 	smb_ads_fini();
550 	smb_netbios_stop();
551 }
552 
553 
554 /*
555  * smbd_refresh_init()
556  *
557  * SMB service refresh thread initialization.  This thread waits for a
558  * refresh event and updates the daemon's view of the configuration
559  * before going back to sleep.
560  */
561 static int
562 smbd_refresh_init()
563 {
564 	pthread_attr_t		tattr;
565 	pthread_condattr_t	cattr;
566 	int			rc;
567 
568 	(void) pthread_condattr_init(&cattr);
569 	(void) pthread_cond_init(&refresh_cond, &cattr);
570 	(void) pthread_condattr_destroy(&cattr);
571 
572 	(void) pthread_mutex_init(&refresh_mutex, NULL);
573 
574 	(void) pthread_attr_init(&tattr);
575 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
576 	rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0);
577 	(void) pthread_attr_destroy(&tattr);
578 
579 	return (rc);
580 }
581 
582 /*
583  * smbd_refresh_fini()
584  *
585  * Stop the refresh thread.
586  */
587 static void
588 smbd_refresh_fini()
589 {
590 	(void) pthread_cancel(refresh_thr);
591 
592 	(void) pthread_cond_destroy(&refresh_cond);
593 	(void) pthread_mutex_destroy(&refresh_mutex);
594 }
595 
596 /*
597  * smbd_refresh_monitor()
598  *
599  * Wait for a refresh event. When this thread wakes up, update the
600  * smbd configuration from the SMF config information then go back to
601  * wait for the next refresh.
602  */
603 /*ARGSUSED*/
604 static void *
605 smbd_refresh_monitor(void *arg)
606 {
607 	smb_kmod_cfg_t	cfg;
608 	int		error;
609 
610 	while (!smbd.s_shutting_down) {
611 		(void) pthread_mutex_lock(&refresh_mutex);
612 		while ((atomic_swap_uint(&smbd.s_refreshes, 0) == 0) &&
613 		    (!smbd.s_shutting_down))
614 			(void) pthread_cond_wait(&refresh_cond, &refresh_mutex);
615 		(void) pthread_mutex_unlock(&refresh_mutex);
616 
617 		if (smbd.s_shutting_down) {
618 			syslog(LOG_DEBUG, "shutting down");
619 			exit((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL :
620 			    SMF_EXIT_OK);
621 		}
622 
623 		/*
624 		 * We've been woken up by a refresh event so go do
625 		 * what is necessary.
626 		 */
627 		smb_ads_refresh();
628 		smb_ccache_remove(SMB_CCACHE_PATH);
629 
630 		/*
631 		 * Start the dyndns thread, if required.
632 		 * Clear the DNS zones for the existing interfaces
633 		 * before updating the NIC interface list.
634 		 */
635 		(void) dyndns_start();
636 		dyndns_clear_zones();
637 
638 		/* re-initialize NIC table */
639 		if (smb_nic_init() != 0)
640 			smbd_report("failed to get NIC information");
641 		smb_netbios_name_reconfig();
642 		smb_browser_reconfig();
643 		smbd_refresh_dc();
644 		dyndns_update_zones();
645 
646 		if (smbd_set_netlogon_cred()) {
647 			/*
648 			 * Restart required because the domain changed
649 			 * or the credential chain setup failed.
650 			 */
651 			if (smb_smf_restart_service() != 0) {
652 				syslog(LOG_ERR,
653 				    "unable to restart smb service. "
654 				    "Run 'svcs -xv smb/server' for more "
655 				    "information.");
656 				smbd.s_shutting_down = B_TRUE;
657 				exit(SMF_EXIT_OK);
658 			}
659 
660 			break;
661 		}
662 
663 		if (!smbd.s_kbound) {
664 			error = smbd_kernel_bind();
665 			if (error != 0)
666 				smbd_report("kernel bind error: %s",
667 				    strerror(error));
668 			else
669 				(void) smb_shr_load();
670 
671 			continue;
672 		}
673 
674 		(void) smb_shr_load();
675 
676 		smb_load_kconfig(&cfg);
677 		error = smb_kmod_setcfg(&cfg);
678 		if (error < 0)
679 			smbd_report("configuration update failed: %s",
680 			    strerror(error));
681 	}
682 
683 	return (NULL);
684 }
685 
686 /*
687  * Update DC information on a refresh.
688  */
689 static void
690 smbd_refresh_dc(void)
691 {
692 	char fqdomain[MAXHOSTNAMELEN];
693 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
694 		return;
695 
696 	if (smb_getfqdomainname(fqdomain, MAXHOSTNAMELEN))
697 		return;
698 
699 	if (smb_locate_dc(fqdomain, "", NULL))
700 		smbd_report("DC discovery failed");
701 }
702 
703 void
704 smbd_set_secmode(int secmode)
705 {
706 	switch (secmode) {
707 	case SMB_SECMODE_WORKGRP:
708 	case SMB_SECMODE_DOMAIN:
709 		(void) smb_config_set_secmode(secmode);
710 		smbd.s_secmode = secmode;
711 		break;
712 
713 	default:
714 		syslog(LOG_ERR, "invalid security mode: %d", secmode);
715 		syslog(LOG_ERR, "entering maintenance mode");
716 		(void) smb_smf_maintenance_mode();
717 	}
718 }
719 
720 /*
721  * If the door has already been opened by another process (non-zero pid
722  * in target), we assume that another smbd is already running.  If there
723  * is a race here, it will be caught later when smbsrv is opened because
724  * only one process is allowed to open the device at a time.
725  */
726 static int
727 smbd_already_running(void)
728 {
729 	door_info_t info;
730 	int door;
731 
732 	if ((door = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
733 		return (0);
734 
735 	if (door_info(door, &info) < 0)
736 		return (0);
737 
738 	if (info.di_target > 0) {
739 		smbd_report("already running: pid %ld\n", info.di_target);
740 		(void) close(door);
741 		return (1);
742 	}
743 
744 	(void) close(door);
745 	return (0);
746 }
747 
748 /*
749  * smbd_kernel_bind
750  *
751  * This function open the smbsrv device and start the kernel service.
752  */
753 static int
754 smbd_kernel_bind(void)
755 {
756 	int rc;
757 
758 	smbd_kernel_unbind();
759 
760 	rc = smb_kmod_bind();
761 	if (rc == 0) {
762 		rc = smbd_kernel_start();
763 		if (rc != 0)
764 			smb_kmod_unbind();
765 		else
766 			smbd.s_kbound = B_TRUE;
767 	}
768 	return (rc);
769 }
770 
771 static int
772 smbd_kernel_start(void)
773 {
774 	smb_kmod_cfg_t	cfg;
775 	int		rc;
776 
777 	smb_load_kconfig(&cfg);
778 	rc = smb_kmod_setcfg(&cfg);
779 	if (rc != 0)
780 		return (rc);
781 
782 	rc = smb_kmod_setgmtoff(smbd_gmtoff());
783 	if (rc != 0)
784 		return (rc);
785 
786 	rc = smb_kmod_start(smbd.s_door_opipe, smbd.s_door_lmshr,
787 	    smbd.s_door_srv);
788 	if (rc != 0)
789 		return (rc);
790 
791 	rc = smbd_start_listeners();
792 	if (rc != 0)
793 		return (rc);
794 
795 	return (0);
796 }
797 
798 /*
799  * smbd_kernel_unbind
800  */
801 static void
802 smbd_kernel_unbind(void)
803 {
804 	smbd_stop_listeners();
805 	smb_kmod_unbind();
806 	smbd.s_kbound = B_FALSE;
807 }
808 
809 /*
810  * Initialization of the localtime thread.
811  * Returns 0 on success, an error number if thread creation fails.
812  */
813 
814 int
815 smbd_localtime_init(void)
816 {
817 	pthread_attr_t tattr;
818 	int rc;
819 
820 	(void) pthread_attr_init(&tattr);
821 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
822 	rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0);
823 	(void) pthread_attr_destroy(&tattr);
824 	return (rc);
825 }
826 
827 /*
828  * Local time thread to kernel land.
829  * Send local gmtoff to kernel module one time at startup
830  * and each time it changes (up to twice a year).
831  * Local gmtoff is checked once every 15 minutes and
832  * since some timezones are aligned on half and qtr hour boundaries,
833  * once an hour would likely suffice.
834  */
835 
836 /*ARGSUSED*/
837 static void *
838 smbd_localtime_monitor(void *arg)
839 {
840 	struct tm local_tm;
841 	time_t secs;
842 	int32_t gmtoff, last_gmtoff = -1;
843 	int timeout;
844 	int error;
845 
846 	for (;;) {
847 		gmtoff = smbd_gmtoff();
848 
849 		if ((last_gmtoff != gmtoff) && smbd.s_kbound) {
850 			error = smb_kmod_setgmtoff(gmtoff);
851 			if (error != 0)
852 				smbd_report("localtime set failed: %s",
853 				    strerror(error));
854 		}
855 
856 		/*
857 		 * Align the next iteration on a fifteen minute boundary.
858 		 */
859 		secs = time(0);
860 		(void) localtime_r(&secs, &local_tm);
861 		timeout = ((15 - (local_tm.tm_min % 15)) * SECSPERMIN);
862 		(void) sleep(timeout);
863 
864 		last_gmtoff = gmtoff;
865 	}
866 
867 	/*NOTREACHED*/
868 	return (NULL);
869 }
870 
871 /*
872  * smbd_gmtoff
873  *
874  * Determine offset from GMT. If daylight saving time use altzone,
875  * otherwise use timezone.
876  */
877 static int32_t
878 smbd_gmtoff(void)
879 {
880 	time_t clock_val;
881 	struct tm *atm;
882 	int32_t gmtoff;
883 
884 	(void) time(&clock_val);
885 	atm = localtime(&clock_val);
886 
887 	gmtoff = (atm->tm_isdst) ? altzone : timezone;
888 
889 	return (gmtoff);
890 }
891 
892 static void
893 smbd_sig_handler(int sigval)
894 {
895 	if (smbd.s_sigval == 0)
896 		(void) atomic_swap_uint(&smbd.s_sigval, sigval);
897 
898 	if (sigval == SIGHUP) {
899 		atomic_inc_uint(&smbd.s_refreshes);
900 		(void) pthread_cond_signal(&refresh_cond);
901 	}
902 
903 	if (sigval == SIGINT || sigval == SIGTERM) {
904 		smbd.s_shutting_down = B_TRUE;
905 		(void) pthread_cond_signal(&refresh_cond);
906 	}
907 }
908 
909 /*
910  * Set up configuration options and parse the command line.
911  * This function will determine if we will run as a daemon
912  * or in the foreground.
913  *
914  * Failure to find a uid or gid results in using the default (0).
915  */
916 static int
917 smbd_setup_options(int argc, char *argv[])
918 {
919 	struct passwd *pwd;
920 	struct group *grp;
921 	int c;
922 
923 	if ((pwd = getpwnam("root")) != NULL)
924 		smbd.s_uid = pwd->pw_uid;
925 
926 	if ((grp = getgrnam("sys")) != NULL)
927 		smbd.s_gid = grp->gr_gid;
928 
929 	smbd.s_fg = smb_config_get_fg_flag();
930 
931 	while ((c = getopt(argc, argv, ":f")) != -1) {
932 		switch (c) {
933 		case 'f':
934 			smbd.s_fg = 1;
935 			break;
936 
937 		case ':':
938 		case '?':
939 		default:
940 			smbd_usage(stderr);
941 			return (-1);
942 		}
943 	}
944 
945 	return (0);
946 }
947 
948 static void
949 smbd_usage(FILE *fp)
950 {
951 	static char *help[] = {
952 		"-f  run program in foreground"
953 	};
954 
955 	int i;
956 
957 	(void) fprintf(fp, "Usage: %s [-f]\n", smbd.s_pname);
958 
959 	for (i = 0; i < sizeof (help)/sizeof (help[0]); ++i)
960 		(void) fprintf(fp, "    %s\n", help[i]);
961 }
962 
963 static void
964 smbd_report(const char *fmt, ...)
965 {
966 	char buf[128];
967 	va_list ap;
968 
969 	if (fmt == NULL)
970 		return;
971 
972 	va_start(ap, fmt);
973 	(void) vsnprintf(buf, 128, fmt, ap);
974 	va_end(ap);
975 
976 	(void) fprintf(stderr, "smbd: %s\n", buf);
977 }
978 
979 static int
980 smbd_start_listeners(void)
981 {
982 	int		rc1;
983 	int		rc2;
984 	pthread_attr_t	tattr;
985 
986 	(void) pthread_attr_init(&tattr);
987 
988 	if (!smbd.s_nbt_listener_running) {
989 		rc1 = pthread_create(&smbd.s_nbt_listener_id, &tattr,
990 		    smbd_nbt_listener, NULL);
991 		if (rc1 != 0)
992 			smbd_report("unable to start NBT service");
993 		else
994 			smbd.s_nbt_listener_running = B_TRUE;
995 	}
996 
997 	if (!smbd.s_tcp_listener_running) {
998 		rc2 = pthread_create(&smbd.s_tcp_listener_id, &tattr,
999 		    smbd_tcp_listener, NULL);
1000 		if (rc2 != 0)
1001 			smbd_report("unable to start TCP service");
1002 		else
1003 			smbd.s_tcp_listener_running = B_TRUE;
1004 	}
1005 
1006 	(void) pthread_attr_destroy(&tattr);
1007 
1008 	if (rc1 != 0)
1009 		return (rc1);
1010 	return (rc2);
1011 }
1012 
1013 static void
1014 smbd_stop_listeners(void)
1015 {
1016 	void	*status;
1017 
1018 	if (smbd.s_nbt_listener_running) {
1019 		(void) pthread_kill(smbd.s_nbt_listener_id, SIGTERM);
1020 		(void) pthread_join(smbd.s_nbt_listener_id, &status);
1021 		smbd.s_nbt_listener_running = B_FALSE;
1022 	}
1023 
1024 	if (smbd.s_tcp_listener_running) {
1025 		(void) pthread_kill(smbd.s_tcp_listener_id, SIGTERM);
1026 		(void) pthread_join(smbd.s_tcp_listener_id, &status);
1027 		smbd.s_tcp_listener_running = B_FALSE;
1028 	}
1029 }
1030 
1031 /*
1032  * Perform fatal error exit.
1033  */
1034 static void
1035 smbd_fatal_error(const char *msg)
1036 {
1037 	if (msg == NULL)
1038 		msg = "Fatal error";
1039 
1040 	smbd_report("%s", msg);
1041 	smbd.s_fatal_error = B_TRUE;
1042 	(void) kill(smbd.s_pid, SIGTERM);
1043 }
1044 
1045 /*ARGSUSED*/
1046 static void *
1047 smbd_nbt_receiver(void *arg)
1048 {
1049 	(void) smb_kmod_nbtreceive();
1050 	return (NULL);
1051 }
1052 
1053 /*ARGSUSED*/
1054 static void *
1055 smbd_nbt_listener(void *arg)
1056 {
1057 	pthread_attr_t	tattr;
1058 	sigset_t	set;
1059 	sigset_t	oset;
1060 	pthread_t	tid;
1061 	int		error = 0;
1062 
1063 	(void) sigfillset(&set);
1064 	(void) sigdelset(&set, SIGTERM);
1065 	(void) sigdelset(&set, SIGINT);
1066 	(void) pthread_sigmask(SIG_SETMASK, &set, &oset);
1067 	(void) pthread_attr_init(&tattr);
1068 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1069 
1070 	while (smb_kmod_nbtlisten(error) == 0)
1071 		error = pthread_create(&tid, &tattr, smbd_nbt_receiver, NULL);
1072 
1073 	(void) pthread_attr_destroy(&tattr);
1074 
1075 	if (!smbd.s_shutting_down)
1076 		smbd_fatal_error("NBT listener thread terminated unexpectedly");
1077 
1078 	return (NULL);
1079 }
1080 
1081 /*ARGSUSED*/
1082 static void *
1083 smbd_tcp_receiver(void *arg)
1084 {
1085 	(void) smb_kmod_tcpreceive();
1086 	return (NULL);
1087 }
1088 
1089 /*ARGSUSED*/
1090 static void *
1091 smbd_tcp_listener(void *arg)
1092 {
1093 	pthread_attr_t	tattr;
1094 	sigset_t	set;
1095 	sigset_t	oset;
1096 	pthread_t	tid;
1097 	int		error = 0;
1098 
1099 	(void) sigfillset(&set);
1100 	(void) sigdelset(&set, SIGTERM);
1101 	(void) sigdelset(&set, SIGINT);
1102 	(void) pthread_sigmask(SIG_SETMASK, &set, &oset);
1103 	(void) pthread_attr_init(&tattr);
1104 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1105 
1106 	while (smb_kmod_tcplisten(error) == 0)
1107 		error = pthread_create(&tid, &tattr, smbd_tcp_receiver, NULL);
1108 
1109 	(void) pthread_attr_destroy(&tattr);
1110 
1111 	if (!smbd.s_shutting_down)
1112 		smbd_fatal_error("TCP listener thread terminated unexpectedly");
1113 
1114 	return (NULL);
1115 }
1116 
1117 /*
1118  * Enable libumem debugging by default on DEBUG builds.
1119  */
1120 #ifdef DEBUG
1121 const char *
1122 _umem_debug_init(void)
1123 {
1124 	return ("default,verbose"); /* $UMEM_DEBUG setting */
1125 }
1126 
1127 const char *
1128 _umem_logging_init(void)
1129 {
1130 	return ("fail,contents"); /* $UMEM_LOGGING setting */
1131 }
1132 #endif
1133