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.
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.
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]
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
27 #include <sys/ioccom.h>
28 #include <sys/corectl.h>
41 #include <priv_utils.h>
51 #include <cups/cups.h>
53 #include <smbsrv/smb_door.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>
61 #define SMBD_ONLINE_WAIT_INTERVAL 10
62 #define SMB_CUPS_DOCNAME "generic_doc"
63 #define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv"
64 #define SMB_DBDIR "/var/smb"
65 #define SMB_SPOOL_WAIT 2
67 static void *smbd_nbt_listener(void *);
68 static void *smbd_tcp_listener(void *);
69 static void *smbd_nbt_receiver(void *);
70 static void *smbd_tcp_receiver(void *);
72 static int smbd_daemonize_init(void);
73 static void smbd_daemonize_fini(int, int);
74 static int smb_init_daemon_priv(int, uid_t
, gid_t
);
76 static int smbd_kernel_bind(void);
77 static void smbd_kernel_unbind(void);
78 static int smbd_already_running(void);
80 static int smbd_service_init(void);
81 static void smbd_service_fini(void);
83 static int smbd_setup_options(int argc
, char *argv
[]);
84 static void smbd_usage(FILE *fp
);
85 static void smbd_report(const char *fmt
, ...);
87 static void smbd_sig_handler(int sig
);
89 static int32_t smbd_gmtoff(void);
90 static int smbd_localtime_init(void);
91 static void *smbd_localtime_monitor(void *arg
);
93 static int smbd_spool_init(void);
94 static void *smbd_spool_monitor(void *arg
);
96 static int smbd_spool_init(void);
97 static void *smbd_spool_monitor(void *arg
);
99 static int smbd_refresh_init(void);
100 static void smbd_refresh_fini(void);
101 static void *smbd_refresh_monitor(void *);
103 static void *smbd_nbt_receiver(void *);
104 static void *smbd_nbt_listener(void *);
106 static void *smbd_tcp_receiver(void *);
107 static void *smbd_tcp_listener(void *);
109 static int smbd_start_listeners(void);
110 static void smbd_stop_listeners(void);
111 static int smbd_kernel_start(void);
113 static void smbd_fatal_error(const char *);
115 static pthread_cond_t refresh_cond
;
116 static pthread_mutex_t refresh_mutex
;
118 static cond_t listener_cv
;
119 static mutex_t listener_mutex
;
122 * Mutex to ensure that smbd_service_fini() and smbd_service_init()
123 * are atomic w.r.t. one another. Otherwise, if a shutdown begins
124 * before initialization is complete, resources can get deallocated
125 * while initialization threads are still using them.
127 static mutex_t smbd_service_mutex
;
128 static cond_t smbd_service_cv
;
133 * Use SMF error codes only on return or exit.
136 main(int argc
, char *argv
[])
138 struct sigaction act
;
146 smbd
.s_pname
= basename(argv
[0]);
147 openlog(smbd
.s_pname
, LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
149 if (smbd_setup_options(argc
, argv
) != 0)
150 return (SMF_EXIT_ERR_FATAL
);
152 if ((uid
= getuid()) != smbd
.s_uid
) {
153 smbd_report("user %d: %s", uid
, strerror(EPERM
));
154 return (SMF_EXIT_ERR_FATAL
);
157 if (getzoneid() != GLOBAL_ZONEID
) {
158 smbd_report("non-global zones are not supported");
159 return (SMF_EXIT_ERR_FATAL
);
162 if (is_system_labeled()) {
163 smbd_report("Trusted Extensions not supported");
164 return (SMF_EXIT_ERR_FATAL
);
167 if (smbd_already_running())
168 return (SMF_EXIT_OK
);
171 * Raise the file descriptor limit to accommodate simultaneous user
172 * authentications/file access.
174 if ((getrlimit(RLIMIT_NOFILE
, &rl
) == 0) &&
175 (rl
.rlim_cur
< rl
.rlim_max
)) {
176 orig_limit
= rl
.rlim_cur
;
177 rl
.rlim_cur
= rl
.rlim_max
;
178 if (setrlimit(RLIMIT_NOFILE
, &rl
) != 0)
179 smbd_report("Failed to raise file descriptor limit"
180 " from %d to %d", orig_limit
, rl
.rlim_cur
);
183 (void) sigfillset(&set
);
184 (void) sigdelset(&set
, SIGABRT
);
186 (void) sigfillset(&act
.sa_mask
);
187 act
.sa_handler
= smbd_sig_handler
;
190 (void) sigaction(SIGABRT
, &act
, NULL
);
191 (void) sigaction(SIGTERM
, &act
, NULL
);
192 (void) sigaction(SIGHUP
, &act
, NULL
);
193 (void) sigaction(SIGINT
, &act
, NULL
);
194 (void) sigaction(SIGPIPE
, &act
, NULL
);
195 (void) sigaction(SIGUSR1
, &act
, NULL
);
197 (void) sigdelset(&set
, SIGTERM
);
198 (void) sigdelset(&set
, SIGHUP
);
199 (void) sigdelset(&set
, SIGINT
);
200 (void) sigdelset(&set
, SIGPIPE
);
201 (void) sigdelset(&set
, SIGUSR1
);
204 (void) sigdelset(&set
, SIGTSTP
);
205 (void) sigdelset(&set
, SIGTTIN
);
206 (void) sigdelset(&set
, SIGTTOU
);
208 if (smbd_service_init() != 0) {
209 smbd_report("service initialization failed");
210 exit(SMF_EXIT_ERR_FATAL
);
214 * "pfd" is a pipe descriptor -- any fatal errors
215 * during subsequent initialization of the child
216 * process should be written to this pipe and the
217 * parent will report this error as the exit status.
219 pfd
= smbd_daemonize_init();
221 if (smbd_service_init() != 0) {
222 smbd_report("daemon initialization failed");
223 exit(SMF_EXIT_ERR_FATAL
);
226 smbd_daemonize_fini(pfd
, SMF_EXIT_OK
);
229 (void) atexit(smb_kmod_stop
);
231 while (!smbd
.s_shutting_down
) {
232 if (smbd
.s_sigval
== 0 && smbd
.s_refreshes
== 0)
233 (void) sigsuspend(&set
);
235 sigval
= atomic_swap_uint(&smbd
.s_sigval
, 0);
244 syslog(LOG_DEBUG
, "refresh requested");
245 (void) pthread_cond_signal(&refresh_cond
);
254 * Typically SIGINT or SIGTERM.
256 smbd
.s_shutting_down
= B_TRUE
;
263 return ((smbd
.s_fatal_error
) ? SMF_EXIT_ERR_FATAL
: SMF_EXIT_OK
);
267 * This function will fork off a child process,
268 * from which only the child will return.
270 * Use SMF error codes only on exit.
273 smbd_daemonize_init(void)
281 * Reset privileges to the minimum set required. We continue
282 * to run as root to create and access files in /var.
284 rc
= smb_init_daemon_priv(PU_RESETGROUPS
, smbd
.s_uid
, smbd
.s_gid
);
287 smbd_report("insufficient privileges");
288 exit(SMF_EXIT_ERR_FATAL
);
292 * Block all signals prior to the fork and leave them blocked in the
293 * parent so we don't get in a situation where the parent gets SIGINT
294 * and returns non-zero exit status and the child is actually running.
295 * In the child, restore the signal mask once we've done our setsid().
297 (void) sigfillset(&set
);
298 (void) sigdelset(&set
, SIGABRT
);
299 (void) sigprocmask(SIG_BLOCK
, &set
, &oset
);
301 if (pipe(pfds
) == -1) {
302 smbd_report("unable to create pipe");
303 exit(SMF_EXIT_ERR_FATAL
);
308 if ((pid
= fork()) == -1) {
309 openlog(smbd
.s_pname
, LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
310 smbd_report("unable to fork");
312 exit(SMF_EXIT_ERR_FATAL
);
316 * If we're the parent process, wait for either the child to send us
317 * the appropriate exit status over the pipe or for the read to fail
318 * (presumably with 0 for EOF if our child terminated abnormally).
319 * If the read fails, exit with either the child's exit status if it
320 * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal.
323 (void) close(pfds
[1]);
325 if (read(pfds
[0], &status
, sizeof (status
)) == sizeof (status
))
328 if (waitpid(pid
, &status
, 0) == pid
&& WIFEXITED(status
))
329 _exit(WEXITSTATUS(status
));
331 _exit(SMF_EXIT_ERR_FATAL
);
334 openlog(smbd
.s_pname
, LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
336 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
339 (void) close(pfds
[0]);
345 * This function is based on __init_daemon_priv() and replaces
346 * __init_daemon_priv() since we want smbd to have all privileges so that it
347 * can execute map/unmap commands with all privileges during share
348 * connection/disconnection. Unused privileges are disabled until command
349 * execution. The permitted and the limit set contains all privileges. The
350 * inheritable set contains no privileges.
353 static const char root_cp
[] = "/core.%f.%t";
354 static const char daemon_cp
[] = "/var/tmp/core.%f.%t";
357 smb_init_daemon_priv(int flags
, uid_t uid
, gid_t gid
)
359 priv_set_t
*perm
= NULL
;
364 * This is not a significant failure: it allows us to start programs
365 * with sufficient privileges and with the proper uid. We don't
366 * care enough about the extra groups in that case.
368 if (flags
& PU_RESETGROUPS
)
369 (void) setgroups(0, NULL
);
371 if (gid
!= (gid_t
)-1 && setgid(gid
) != 0)
374 perm
= priv_allocset();
379 (void) getppriv(PRIV_PERMITTED
, perm
);
380 (void) setppriv(PRIV_SET
, PRIV_EFFECTIVE
, perm
);
382 /* Now reset suid and euid */
383 if (uid
!= (uid_t
)-1 && setreuid(uid
, uid
) != 0)
388 ret
= setppriv(PRIV_SET
, PRIV_INHERITABLE
, perm
);
392 if (core_get_process_path(buf
, sizeof (buf
), getpid()) == 0 &&
393 strcmp(buf
, "core") == 0) {
395 if ((uid
== (uid_t
)-1 ? geteuid() : uid
) == 0) {
396 (void) core_set_process_path(root_cp
, sizeof (root_cp
),
399 (void) core_set_process_path(daemon_cp
,
400 sizeof (daemon_cp
), getpid());
403 (void) setpflags(__PROC_PROTECT
, 0);
409 * Most privileges, except the ones that are required for smbd, are turn off
410 * in the effective set. They will be turn on when needed for command
411 * execution during share connection/disconnection.
414 smbd_daemonize_fini(int fd
, int exit_status
)
419 * Now that we're running, if a pipe fd was specified, write an exit
420 * status to it to indicate that our parent process can safely detach.
421 * Then proceed to loading the remaining non-built-in modules.
424 (void) write(fd
, &exit_status
, sizeof (exit_status
));
428 pset
= priv_allocset();
434 /* list of privileges for smbd */
435 (void) priv_addset(pset
, PRIV_NET_MAC_AWARE
);
436 (void) priv_addset(pset
, PRIV_NET_PRIVADDR
);
437 (void) priv_addset(pset
, PRIV_PROC_AUDIT
);
438 (void) priv_addset(pset
, PRIV_SYS_DEVICES
);
439 (void) priv_addset(pset
, PRIV_SYS_SMB
);
440 (void) priv_addset(pset
, PRIV_SYS_MOUNT
);
444 /* turn off unneeded privileges */
445 (void) setppriv(PRIV_OFF
, PRIV_EFFECTIVE
, pset
);
449 /* reenable core dumps */
450 __fini_daemon_priv(NULL
);
457 smbd_service_init(void)
465 { SMB_SYSROOT
, 0755 },
466 { SMB_SYSTEM32
, 0755 },
471 (void) mutex_lock(&smbd_service_mutex
);
473 smbd
.s_pid
= getpid();
474 for (i
= 0; i
< sizeof (dir
)/sizeof (dir
[0]); ++i
) {
475 if ((mkdir(dir
[i
].name
, dir
[i
].perm
) < 0) &&
477 smbd_report("mkdir %s: %s", dir
[i
].name
,
479 (void) mutex_unlock(&smbd_service_mutex
);
484 if ((rc
= smb_ccache_init(SMB_VARRUN_DIR
, SMB_CCACHE_FILE
)) != 0) {
486 smbd_report("mkdir %s: %s", SMB_VARRUN_DIR
,
489 smbd_report("unable to set KRB5CCNAME");
490 (void) mutex_unlock(&smbd_service_mutex
);
494 smbd
.s_loghd
= smb_log_create(SMBD_LOGSIZE
, SMBD_LOGNAME
);
497 if (smbd_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI
) != 0)
498 smbd_report("NIC monitor failed to start");
500 (void) dyndns_start();
503 if (smb_netbios_start() != 0)
504 smbd_report("NetBIOS services failed to start");
506 smbd_report("NetBIOS services started");
508 smbd
.s_secmode
= smb_config_get_secmode();
509 if ((rc
= smb_domain_init(smbd
.s_secmode
)) != 0) {
510 if (rc
== SMB_DOMAIN_NOMACHINE_SID
) {
512 "no machine SID: check idmap configuration");
513 (void) mutex_unlock(&smbd_service_mutex
);
518 if (smbd_dc_monitor_init() != 0)
519 smbd_report("DC monitor initialization failed %s",
522 if (mlsvc_init() != 0) {
523 smbd_report("msrpc initialization failed");
524 (void) mutex_unlock(&smbd_service_mutex
);
528 smbd
.s_door_srv
= smbd_door_start();
529 smbd
.s_door_opipe
= smbd_opipe_start();
530 if (smbd
.s_door_srv
< 0 || smbd
.s_door_opipe
< 0) {
531 smbd_report("door initialization failed %s", strerror(errno
));
532 (void) mutex_unlock(&smbd_service_mutex
);
536 if (smbd_refresh_init() != 0) {
537 (void) mutex_unlock(&smbd_service_mutex
);
541 dyndns_update_zones();
542 (void) smbd_localtime_init();
543 (void) smb_lgrp_start();
544 smb_pwd_init(B_TRUE
);
546 if (smb_shr_start() != 0) {
547 smbd_report("share initialization failed: %s", strerror(errno
));
548 (void) mutex_unlock(&smbd_service_mutex
);
552 smbd
.s_door_lmshr
= smbd_share_start();
553 if (smbd
.s_door_lmshr
< 0)
554 smbd_report("share initialization failed");
556 if (smbd_kernel_bind() != 0) {
557 (void) mutex_unlock(&smbd_service_mutex
);
561 if (smb_shr_load() != 0) {
562 smbd_report("failed to start loading shares: %s",
564 (void) mutex_unlock(&smbd_service_mutex
);
568 if (smbd_spool_init() != 0) {
569 smbd_report("failed to start print monitor: %s",
571 (void) mutex_unlock(&smbd_service_mutex
);
575 smbd
.s_initialized
= B_TRUE
;
576 smbd_report("service initialized");
577 (void) cond_signal(&smbd_service_cv
);
578 (void) mutex_unlock(&smbd_service_mutex
);
583 * Shutdown smbd and smbsrv kernel services.
585 * Shutdown will not begin until initialization has completed.
586 * Only one thread is allowed to perform the shutdown. Other
587 * threads will be blocked on fini_in_progress until the process
591 smbd_service_fini(void)
593 static uint_t fini_in_progress
;
595 (void) mutex_lock(&smbd_service_mutex
);
597 while (!smbd
.s_initialized
)
598 (void) cond_wait(&smbd_service_cv
, &smbd_service_mutex
);
600 if (atomic_swap_uint(&fini_in_progress
, 1) != 0) {
601 while (fini_in_progress
)
602 (void) cond_wait(&smbd_service_cv
, &smbd_service_mutex
);
606 smbd
.s_shutting_down
= B_TRUE
;
607 smbd_report("service shutting down");
615 smbd_kernel_unbind();
620 smb_ccache_remove(SMB_CCACHE_PATH
);
626 smbd
.s_initialized
= B_FALSE
;
627 smbd_report("service terminated");
628 (void) mutex_unlock(&smbd_service_mutex
);
629 exit((smbd
.s_fatal_error
) ? SMF_EXIT_ERR_FATAL
: SMF_EXIT_OK
);
633 * smbd_refresh_init()
635 * SMB service refresh thread initialization. This thread waits for a
636 * refresh event and updates the daemon's view of the configuration
637 * before going back to sleep.
642 pthread_attr_t tattr
;
643 pthread_condattr_t cattr
;
646 (void) pthread_condattr_init(&cattr
);
647 (void) pthread_cond_init(&refresh_cond
, &cattr
);
648 (void) pthread_condattr_destroy(&cattr
);
650 (void) pthread_mutex_init(&refresh_mutex
, NULL
);
652 (void) pthread_attr_init(&tattr
);
653 (void) pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
654 rc
= pthread_create(&smbd
.s_refresh_tid
, &tattr
, smbd_refresh_monitor
,
656 (void) pthread_attr_destroy(&tattr
);
662 * smbd_refresh_fini()
664 * Stop the refresh thread.
669 if (pthread_self() != smbd
.s_refresh_tid
) {
670 (void) pthread_cancel(smbd
.s_refresh_tid
);
671 (void) pthread_cond_destroy(&refresh_cond
);
672 (void) pthread_mutex_destroy(&refresh_mutex
);
677 * smbd_refresh_monitor()
679 * Wait for a refresh event. When this thread wakes up, update the
680 * smbd configuration from the SMF config information then go back to
681 * wait for the next refresh.
685 smbd_refresh_monitor(void *arg
)
690 while (!smbd
.s_shutting_down
) {
691 (void) pthread_mutex_lock(&refresh_mutex
);
692 while ((atomic_swap_uint(&smbd
.s_refreshes
, 0) == 0) &&
693 (!smbd
.s_shutting_down
))
694 (void) pthread_cond_wait(&refresh_cond
, &refresh_mutex
);
695 (void) pthread_mutex_unlock(&refresh_mutex
);
697 if (smbd
.s_shutting_down
) {
702 (void) mutex_lock(&smbd_service_mutex
);
705 * We've been woken up by a refresh event so go do
709 smb_ccache_remove(SMB_CCACHE_PATH
);
712 * Start the dyndns thread, if required.
713 * Clear the DNS zones for the existing interfaces
714 * before updating the NIC interface list.
716 (void) dyndns_start();
717 dyndns_clear_zones();
719 if (smbd_nicmon_refresh() != 0)
720 smbd_report("NIC monitor refresh failed");
721 smb_netbios_name_reconfig();
722 smb_browser_reconfig();
723 dyndns_update_zones();
725 (void) mutex_unlock(&smbd_service_mutex
);
727 if (!smbd
.s_kbound
) {
728 if ((error
= smbd_kernel_bind()) == 0)
729 (void) smb_shr_load();
734 (void) smb_shr_load();
736 smb_load_kconfig(&cfg
);
737 error
= smb_kmod_setcfg(&cfg
);
739 smbd_report("configuration update failed: %s",
747 smbd_set_secmode(int secmode
)
750 case SMB_SECMODE_WORKGRP
:
751 case SMB_SECMODE_DOMAIN
:
752 (void) smb_config_set_secmode(secmode
);
753 smbd
.s_secmode
= secmode
;
757 syslog(LOG_ERR
, "invalid security mode: %d", secmode
);
758 syslog(LOG_ERR
, "entering maintenance mode");
759 (void) smb_smf_maintenance_mode();
764 * The service is online if initialization is complete and shutdown
770 return (smbd
.s_initialized
&& !smbd
.s_shutting_down
);
774 * Wait until the service is online. Provided for threads that
775 * should wait until the service has been fully initialized before
776 * they start performing operations.
779 smbd_online_wait(const char *text
)
781 while (!smbd_online()) {
783 smb_log(smbd
.s_loghd
, LOG_DEBUG
,
784 "%s: waiting for online", text
);
786 (void) sleep(SMBD_ONLINE_WAIT_INTERVAL
);
790 smb_log(smbd
.s_loghd
, LOG_DEBUG
, "%s: online", text
);
794 * If the door has already been opened by another process (non-zero pid
795 * in target), we assume that another smbd is already running. If there
796 * is a race here, it will be caught later when smbsrv is opened because
797 * only one process is allowed to open the device at a time.
800 smbd_already_running(void)
805 if ((door
= open(SMBD_DOOR_NAME
, O_RDONLY
)) < 0)
808 if (door_info(door
, &info
) < 0)
811 if (info
.di_target
> 0) {
812 smbd_report("already running: pid %ld\n", info
.di_target
);
824 * This function open the smbsrv device and start the kernel service.
827 smbd_kernel_bind(void)
831 smbd_kernel_unbind();
833 if ((rc
= smb_kmod_bind()) == 0) {
834 rc
= smbd_kernel_start();
838 smbd
.s_kbound
= B_TRUE
;
842 smbd_report("kernel bind error: %s", strerror(errno
));
847 smbd_kernel_start(void)
852 smb_load_kconfig(&cfg
);
853 rc
= smb_kmod_setcfg(&cfg
);
857 rc
= smb_kmod_setgmtoff(smbd_gmtoff());
861 rc
= smb_kmod_start(smbd
.s_door_opipe
, smbd
.s_door_lmshr
,
866 rc
= smbd_start_listeners();
877 smbd_kernel_unbind(void)
879 smbd_stop_listeners();
881 smbd
.s_kbound
= B_FALSE
;
885 * Initialization of the spool thread.
886 * Returns 0 on success, an error number if thread creation fails.
890 smbd_spool_init(void)
892 pthread_attr_t tattr
;
895 (void) pthread_attr_init(&tattr
);
896 (void) pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
897 rc
= pthread_create(&smbd
.s_spool_tid
, &tattr
, smbd_spool_monitor
,
899 (void) pthread_attr_destroy(&tattr
);
905 * This user thread blocks waiting for close print file
906 * in the kernel. It then uses the data returned from the ioctl
907 * to copy the spool file into the cups spooler.
908 * This function is really only used by Vista and Win7 clients,
909 * other versions of windows create only a zero size file and this
910 * be removed by spoolss_copy_spool_file function.
915 smbd_spool_monitor(void *arg
)
918 char username
[MAXNAMELEN
];
919 char path
[MAXPATHLEN
];
921 int error_retry_cnt
= 5;
923 smbd_online_wait("smbd_spool_monitor");
925 while (!smbd
.s_shutting_down
&& (error_retry_cnt
> 0)) {
928 if (smb_kmod_get_spool_doc(&spool_num
, username
,
929 path
, &ipaddr
) == 0) {
930 spoolss_copy_spool_file(&ipaddr
,
931 username
, path
, SMB_CUPS_DOCNAME
);
934 if (errno
== ECANCELED
)
937 (void) sleep(SMB_SPOOL_WAIT
);
945 * Initialization of the localtime thread.
946 * Returns 0 on success, an error number if thread creation fails.
950 smbd_localtime_init(void)
952 pthread_attr_t tattr
;
955 (void) pthread_attr_init(&tattr
);
956 (void) pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
957 rc
= pthread_create(&smbd
.s_localtime_tid
, &tattr
,
958 smbd_localtime_monitor
, NULL
);
959 (void) pthread_attr_destroy(&tattr
);
964 * Local time thread to kernel land.
965 * Send local gmtoff to kernel module one time at startup
966 * and each time it changes (up to twice a year).
967 * Local gmtoff is checked once every 15 minutes and
968 * since some timezones are aligned on half and qtr hour boundaries,
969 * once an hour would likely suffice.
974 smbd_localtime_monitor(void *arg
)
978 int32_t gmtoff
, last_gmtoff
= -1;
982 smbd_online_wait("smbd_localtime_monitor");
985 gmtoff
= smbd_gmtoff();
987 if ((last_gmtoff
!= gmtoff
) && smbd
.s_kbound
) {
988 error
= smb_kmod_setgmtoff(gmtoff
);
990 smbd_report("localtime set failed: %s",
995 * Align the next iteration on a fifteen minute boundary.
998 (void) localtime_r(&secs
, &local_tm
);
999 timeout
= ((15 - (local_tm
.tm_min
% 15)) * SECSPERMIN
);
1000 (void) sleep(timeout
);
1002 last_gmtoff
= gmtoff
;
1012 * Determine offset from GMT. If daylight saving time use altzone,
1013 * otherwise use timezone.
1022 (void) time(&clock_val
);
1023 atm
= localtime(&clock_val
);
1025 gmtoff
= (atm
->tm_isdst
) ? altzone
: timezone
;
1031 smbd_sig_handler(int sigval
)
1033 if (smbd
.s_sigval
== 0)
1034 (void) atomic_swap_uint(&smbd
.s_sigval
, sigval
);
1036 if (sigval
== SIGHUP
) {
1037 atomic_inc_uint(&smbd
.s_refreshes
);
1038 (void) pthread_cond_signal(&refresh_cond
);
1041 if (sigval
== SIGINT
|| sigval
== SIGTERM
) {
1042 smbd
.s_shutting_down
= B_TRUE
;
1043 (void) pthread_cond_signal(&refresh_cond
);
1048 * Set up configuration options and parse the command line.
1049 * This function will determine if we will run as a daemon
1050 * or in the foreground.
1052 * Failure to find a uid or gid results in using the default (0).
1055 smbd_setup_options(int argc
, char *argv
[])
1061 if ((pwd
= getpwnam("root")) != NULL
)
1062 smbd
.s_uid
= pwd
->pw_uid
;
1064 if ((grp
= getgrnam("sys")) != NULL
)
1065 smbd
.s_gid
= grp
->gr_gid
;
1067 smbd
.s_fg
= smb_config_get_fg_flag();
1069 while ((c
= getopt(argc
, argv
, ":f")) != -1) {
1087 smbd_usage(FILE *fp
)
1089 static char *help
[] = {
1090 "-f run program in foreground"
1095 (void) fprintf(fp
, "Usage: %s [-f]\n", smbd
.s_pname
);
1097 for (i
= 0; i
< sizeof (help
)/sizeof (help
[0]); ++i
)
1098 (void) fprintf(fp
, " %s\n", help
[i
]);
1102 smbd_report(const char *fmt
, ...)
1111 (void) vsnprintf(buf
, 128, fmt
, ap
);
1114 (void) fprintf(stderr
, "smbd: %s\n", buf
);
1118 smbd_start_listeners(void)
1122 pthread_attr_t tattr
;
1124 (void) pthread_attr_init(&tattr
);
1126 if (!smbd
.s_nbt_listener_running
) {
1127 rc1
= pthread_create(&smbd
.s_nbt_listener_id
, &tattr
,
1128 smbd_nbt_listener
, NULL
);
1130 smbd_report("unable to start NBT service");
1132 smbd
.s_nbt_listener_running
= B_TRUE
;
1135 if (!smbd
.s_tcp_listener_running
) {
1136 rc2
= pthread_create(&smbd
.s_tcp_listener_id
, &tattr
,
1137 smbd_tcp_listener
, NULL
);
1139 smbd_report("unable to start TCP service");
1141 smbd
.s_tcp_listener_running
= B_TRUE
;
1144 (void) pthread_attr_destroy(&tattr
);
1152 * Stop the listener threads. In an attempt to ensure that the listener
1153 * threads get the signal, we use the timed wait loop to harass the
1154 * threads into terminating. Then, if they are still running, we make
1155 * one final attempt to deliver the signal before calling thread join
1156 * to wait for them. Note: if these threads don't terminate, smbd will
1157 * hang here and SMF will probably end up killing the contract.
1160 smbd_stop_listeners(void)
1166 (void) mutex_lock(&listener_mutex
);
1168 while ((smbd
.s_nbt_listener_running
|| smbd
.s_tcp_listener_running
) &&
1170 if (smbd
.s_nbt_listener_running
)
1171 (void) pthread_kill(smbd
.s_nbt_listener_id
, SIGTERM
);
1173 if (smbd
.s_tcp_listener_running
)
1174 (void) pthread_kill(smbd
.s_tcp_listener_id
, SIGTERM
);
1178 rc
= cond_reltimedwait(&listener_cv
, &listener_mutex
, &delay
);
1181 (void) mutex_unlock(&listener_mutex
);
1183 if (smbd
.s_nbt_listener_running
) {
1184 syslog(LOG_WARNING
, "NBT listener still running");
1185 (void) pthread_kill(smbd
.s_nbt_listener_id
, SIGTERM
);
1186 (void) pthread_join(smbd
.s_nbt_listener_id
, &status
);
1187 smbd
.s_nbt_listener_running
= B_FALSE
;
1190 if (smbd
.s_tcp_listener_running
) {
1191 syslog(LOG_WARNING
, "TCP listener still running");
1192 (void) pthread_kill(smbd
.s_tcp_listener_id
, SIGTERM
);
1193 (void) pthread_join(smbd
.s_tcp_listener_id
, &status
);
1194 smbd
.s_tcp_listener_running
= B_FALSE
;
1199 * Perform fatal error exit.
1202 smbd_fatal_error(const char *msg
)
1205 msg
= "Fatal error";
1207 smbd_report("%s", msg
);
1208 smbd
.s_fatal_error
= B_TRUE
;
1209 (void) kill(smbd
.s_pid
, SIGTERM
);
1214 smbd_nbt_receiver(void *arg
)
1216 (void) smb_kmod_nbtreceive();
1222 smbd_nbt_listener(void *arg
)
1224 pthread_attr_t tattr
;
1230 (void) sigfillset(&set
);
1231 (void) sigdelset(&set
, SIGTERM
);
1232 (void) sigdelset(&set
, SIGINT
);
1233 (void) pthread_sigmask(SIG_SETMASK
, &set
, &oset
);
1234 (void) pthread_attr_init(&tattr
);
1235 (void) pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
1237 while (smb_kmod_nbtlisten(error
) == 0)
1238 error
= pthread_create(&tid
, &tattr
, smbd_nbt_receiver
, NULL
);
1240 (void) pthread_attr_destroy(&tattr
);
1242 if (!smbd
.s_shutting_down
)
1243 smbd_fatal_error("NBT listener thread terminated unexpectedly");
1245 (void) mutex_lock(&listener_mutex
);
1246 smbd
.s_nbt_listener_running
= B_FALSE
;
1247 (void) cond_broadcast(&listener_cv
);
1248 (void) mutex_unlock(&listener_mutex
);
1254 smbd_tcp_receiver(void *arg
)
1256 (void) smb_kmod_tcpreceive();
1262 smbd_tcp_listener(void *arg
)
1264 pthread_attr_t tattr
;
1270 (void) sigfillset(&set
);
1271 (void) sigdelset(&set
, SIGTERM
);
1272 (void) sigdelset(&set
, SIGINT
);
1273 (void) pthread_sigmask(SIG_SETMASK
, &set
, &oset
);
1274 (void) pthread_attr_init(&tattr
);
1275 (void) pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
1277 while (smb_kmod_tcplisten(error
) == 0)
1278 error
= pthread_create(&tid
, &tattr
, smbd_tcp_receiver
, NULL
);
1280 (void) pthread_attr_destroy(&tattr
);
1282 if (!smbd
.s_shutting_down
)
1283 smbd_fatal_error("TCP listener thread terminated unexpectedly");
1285 (void) mutex_lock(&listener_mutex
);
1286 smbd
.s_tcp_listener_running
= B_FALSE
;
1287 (void) cond_broadcast(&listener_cv
);
1288 (void) mutex_unlock(&listener_mutex
);
1293 * Enable libumem debugging by default on DEBUG builds.
1297 _umem_debug_init(void)
1299 return ("default,verbose"); /* $UMEM_DEBUG setting */
1303 _umem_logging_init(void)
1305 return ("fail,contents"); /* $UMEM_LOGGING setting */