smbd_main.c revision c8ec8eea9849cac239663c46be8a7f5d2ba7ca00
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego#pragma ident "@(#)smbd_main.c 1.13 08/08/05 SMI"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv"
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbextern void *smbd_nbt_listener(void *);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbextern void *smbd_tcp_listener(void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int smbd_daemonize_init(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void smbd_daemonize_fini(int, int);
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2easstatic int smbd_kernel_bind(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void smbd_kernel_unbind(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int smbd_already_running(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int smbd_service_init(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void smbd_service_fini(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int smbd_localtime_init(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int smbd_refresh_init(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void smbd_refresh_fini(void);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void *smbd_refresh_monitor(void *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smbd user land daemon
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use SMF error codes only on return or exit.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smbd_service_init() != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * "pfd" is a pipe descriptor -- any fatal errors
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * during subsequent initialization of the child
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * process should be written to this pipe and the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * parent will report this error as the exit status.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smbd_service_init() != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Refresh config was triggered */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Typically SIGINT or SIGTERM.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function will fork off a child process,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * from which only the child will return.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use SMF error codes only on exit.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Reset privileges to the minimum set required. We continue
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to run as root to create and access files in /var.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Block all signals prior to the fork and leave them blocked in the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * parent so we don't get in a situation where the parent gets SIGINT
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and returns non-zero exit status and the child is actually running.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * In the child, restore the signal mask once we've done our setsid().
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If we're the parent process, wait for either the child to send us
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the appropriate exit status over the pipe or for the read to fail
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * (presumably with 0 for EOF if our child terminated abnormally).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the read fails, exit with either the child's exit status if it
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pid != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (read(pfds[0], &status, sizeof (status)) == sizeof (status))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Now that we're running, if a pipe fd was specified, write an exit
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * status to it to indicate that our parent process can safely detach.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Then proceed to loading the remaining non-built-in modules.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * smbd_service_init
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return (1);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if ((rc = smb_ccache_init(SMB_VARRUN_DIR, SMB_CCACHE_FILE)) != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_netlogon_init() != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Get the ID map client handle */
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas if ((rc = nt_domain_init(resource_domain, smbd.s_secmode)) != 0) {
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as "no machine SID: check idmap configuration");
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as return (rc);
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego if (smbd_locate_dc_start(resource_domain) != 0)
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego smbd_report("dc discovery failed %s", strerror(errno));
55bf511df53aad0fdb7eb3fa349f0308cc05234cas return (rc);
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas if (rc != 0) {
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas return (rc);
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego smbd_report("share initialization failed: %s", strerror(errno));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Close the kernel service and shutdown smbd services.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function is registered with atexit(): ensure that anything
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * called from here is safe to be called multiple times.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smbd_refresh_init()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SMB service refresh thread initialization. This thread waits for a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * refresh event and updates the daemon's view of the configuration
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * before going back to sleep.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0);
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smbd_refresh_fini()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Stop the refresh thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smbd_refresh_monitor()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Wait for a refresh event. When this thread wakes up, update the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smbd configuration from the SMF config information then go back to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wait for the next refresh.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (pthread_cond_wait(&refresh_cond, &refresh_mutex) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * We've been woken up by a refresh event so go do
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * what is necessary.
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas if ((rc = smb_getfqdomainname(fqdn, MAXHOSTNAMELEN)) != 0)
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas if (rc == 0)
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas /* Clear rev zone before creating if list */
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas "lookup zone");
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas /* re-initialize NIC table */
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas if (rc == 0)
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * The active sessions have to be disconnected.
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas bcopy(&smb_io.sio_data.cfg, &smbd.s_kcfg, sizeof (smbd.s_kcfg));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the door has already been opened by another process (non-zero pid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in target), we assume that another smbd is already running. If there
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is a race here, it will be caught later when smbsrv is opened because
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * only one process is allowed to open the device at a time.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smbd_report("already running: pid %ld\n", info.di_target);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * smbd_kernel_bind
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * This function open the smbsrv device and start the kernel service.
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas bcopy(&smbd.s_kcfg, &smb_io.sio_data.cfg, sizeof (smb_io.sio_data.cfg));
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb rc = pthread_create(&nbt_listener, NULL, smbd_nbt_listener, NULL);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (rc == 0) {
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb rc = pthread_create(&tcp_listener, NULL, smbd_tcp_listener,
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas if (rc == 0) {
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return (0);
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas rc = pthread_create(&nbt_listener, NULL, smbd_nbt_listener, NULL);
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas if (rc == 0) {
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas rc = pthread_create(&tcp_listener, NULL, smbd_tcp_listener,
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas if (rc == 0) {
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas return (0);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return (rc);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * smbd_kernel_unbind
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Initialization of the localtime thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns 0 on success, an error number if thread creation fails.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Local time thread to kernel land.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send local gmtoff to kernel module one time at startup
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and each time it changes (up to twice a year).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Local gmtoff is checked once every 15 minutes and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * since some timezones are aligned on half and qtr hour boundaries,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * once an hour would likely suffice.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (;;) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ioctl(smbd.s_drv_fd, SMB_IOC_GMTOFF, &gmtoff) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Align the next iteration on a fifteen minute boundary.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*NOTREACHED*/
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * smbd_gmtoff
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * Determine offset from GMT. If daylight saving time use altzone,
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * otherwise use timezone.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Set up configuration options and parse the command line.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function will determine if we will run as a daemon
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or in the foreground.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Failure to find a uid or gid results in using the default (0).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (c) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw static char *help[] = {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "-f run program in foreground"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Enable libumem debugging by default on DEBUG builds.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwconst char *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwconst char *