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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  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.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 SECSPERMIN                      60
  62 #define SMBD_ONLINE_WAIT_INTERVAL       10
  63 #define SMBD_REFRESH_INTERVAL           10
  64 #define SMB_DBDIR "/var/smb"
  65 
  66 static int smbd_daemonize_init(void);
  67 static void smbd_daemonize_fini(int, int);
  68 static int smb_init_daemon_priv(int, uid_t, gid_t);
  69 
  70 static int smbd_kernel_bind(void);
  71 static void smbd_kernel_unbind(void);
  72 static int smbd_already_running(void);
  73 
  74 static int smbd_service_init(void);
  75 static void smbd_service_fini(void);
  76 
  77 static int smbd_setup_options(int argc, char *argv[]);
  78 static void smbd_usage(FILE *fp);
  79 
  80 static int32_t smbd_gmtoff(void);
  81 static void smbd_localtime_init(void);
  82 static void *smbd_localtime_monitor(void *arg);
  83 
  84 static void smbd_dyndns_init(void);
  85 static void smbd_load_shares(void);
  86 static void *smbd_share_loader(void *);
  87 
  88 static void smbd_refresh_handler(void);
  89 
  90 static int smbd_kernel_start(void);
  91 
  92 smbd_t smbd;
  93 
  94 /*
  95  * Use SMF error codes only on return or exit.
  96  */
  97 int
  98 main(int argc, char *argv[])
  99 {
 100         sigset_t                set;
 101         uid_t                   uid;
 102         int                     pfd = -1;
 103         int                     sigval;
 104         struct rlimit           rl;
 105         int                     orig_limit;
 106 
 107 #ifdef  FKSMBD
 108         fksmbd_init();
 109 #endif
 110         smbd.s_pname = basename(argv[0]);
 111         openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
 112 
 113         if (smbd_setup_options(argc, argv) != 0)
 114                 return (SMF_EXIT_ERR_FATAL);
 115 
 116         if ((uid = getuid()) != smbd.s_uid) {
 117 #ifdef  FKSMBD
 118                 /* Can't manipulate privileges in daemonize. */
 119                 if (smbd.s_fg == 0) {
 120                         smbd.s_fg = 1;
 121                         smbd_report("user %d (forced -f)", uid);
 122                 }
 123 #else   /* FKSMBD */
 124                 smbd_report("user %d: %s", uid, strerror(EPERM));
 125                 return (SMF_EXIT_ERR_FATAL);
 126 #endif  /* FKSMBD */
 127         }
 128 
 129         if (is_system_labeled()) {
 130                 smbd_report("Trusted Extensions not supported");
 131                 return (SMF_EXIT_ERR_FATAL);
 132         }
 133 
 134         if (smbd_already_running())
 135                 return (SMF_EXIT_OK);
 136 
 137         /*
 138          * Raise the file descriptor limit to accommodate simultaneous user
 139          * authentications/file access.
 140          */
 141         if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) &&
 142             (rl.rlim_cur < rl.rlim_max)) {
 143                 orig_limit = rl.rlim_cur;
 144                 rl.rlim_cur = rl.rlim_max;
 145                 if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
 146                         smbd_report("Failed to raise file descriptor limit"
 147                             " from %d to %d", orig_limit, rl.rlim_cur);
 148         }
 149 
 150         /*
 151          * Block async signals in all threads.
 152          */
 153         (void) sigemptyset(&set);
 154 
 155         (void) sigaddset(&set, SIGHUP);
 156         (void) sigaddset(&set, SIGINT);
 157         (void) sigaddset(&set, SIGQUIT);
 158         (void) sigaddset(&set, SIGPIPE);
 159         (void) sigaddset(&set, SIGTERM);
 160         (void) sigaddset(&set, SIGUSR1);
 161         (void) sigaddset(&set, SIGUSR2);
 162 
 163         (void) sigprocmask(SIG_SETMASK, &set, NULL);
 164 
 165         if (smbd.s_fg) {
 166                 if (smbd_service_init() != 0) {
 167                         smbd_report("service initialization failed");
 168                         exit(SMF_EXIT_ERR_FATAL);
 169                 }
 170         } else {
 171                 /*
 172                  * "pfd" is a pipe descriptor -- any fatal errors
 173                  * during subsequent initialization of the child
 174                  * process should be written to this pipe and the
 175                  * parent will report this error as the exit status.
 176                  */
 177                 pfd = smbd_daemonize_init();
 178 
 179                 if (smbd_service_init() != 0) {
 180                         smbd_report("daemon initialization failed");
 181                         exit(SMF_EXIT_ERR_FATAL);
 182                 }
 183 
 184                 smbd_daemonize_fini(pfd, SMF_EXIT_OK);
 185         }
 186 
 187         while (!smbd.s_shutting_down) {
 188                 sigval = sigwait(&set);
 189 
 190                 switch (sigval) {
 191                 case -1:
 192                         syslog(LOG_DEBUG, "sigwait failed: %s",
 193                             strerror(errno));
 194                         break;
 195                 case SIGPIPE:
 196                         break;
 197 
 198                 case SIGHUP:
 199                         syslog(LOG_DEBUG, "refresh requested");
 200                         smbd_refresh_handler();
 201                         break;
 202 
 203                 case SIGUSR1:
 204                         syslog(LOG_DEBUG, "SIGUSR1 ignored");
 205                         break;
 206 
 207                 default:
 208                         /*
 209                          * Typically SIGINT or SIGTERM.
 210                          */
 211                         smbd.s_shutting_down = B_TRUE;
 212                         break;
 213                 }
 214         }
 215 
 216         /*
 217          * Allow termination signals while shutting down.
 218          */
 219         (void) sigemptyset(&set);
 220 
 221         if (smbd.s_fg) {
 222                 (void) sigaddset(&set, SIGHUP);
 223                 (void) sigaddset(&set, SIGINT);
 224         }
 225         (void) sigaddset(&set, SIGTERM);
 226 
 227         (void) sigprocmask(SIG_UNBLOCK, &set, NULL);
 228 
 229         smbd_service_fini();
 230         return ((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL : SMF_EXIT_OK);
 231 }
 232 
 233 /*
 234  * This function will fork off a child process,
 235  * from which only the child will return.
 236  *
 237  * Use SMF error codes only on exit.
 238  */
 239 static int
 240 smbd_daemonize_init(void)
 241 {
 242         int status, pfds[2];
 243         sigset_t set, oset;
 244         pid_t pid;
 245         int rc;
 246 
 247         /*
 248          * Reset privileges to the minimum set required. We continue
 249          * to run as root to create and access files in /var.
 250          */
 251         rc = smb_init_daemon_priv(PU_RESETGROUPS, smbd.s_uid, smbd.s_gid);
 252 
 253         if (rc != 0) {
 254                 smbd_report("insufficient privileges");
 255                 exit(SMF_EXIT_ERR_FATAL);
 256         }
 257 
 258         /*
 259          * Block all signals prior to the fork and leave them blocked in the
 260          * parent so we don't get in a situation where the parent gets SIGINT
 261          * and returns non-zero exit status and the child is actually running.
 262          * In the child, restore the signal mask once we've done our setsid().
 263          */
 264         (void) sigfillset(&set);
 265         (void) sigdelset(&set, SIGABRT);
 266         (void) sigprocmask(SIG_BLOCK, &set, &oset);
 267 
 268         if (pipe(pfds) == -1) {
 269                 smbd_report("unable to create pipe");
 270                 exit(SMF_EXIT_ERR_FATAL);
 271         }
 272 
 273         closelog();
 274 
 275         if ((pid = fork()) == -1) {
 276                 openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
 277                 smbd_report("unable to fork");
 278                 closelog();
 279                 exit(SMF_EXIT_ERR_FATAL);
 280         }
 281 
 282         /*
 283          * If we're the parent process, wait for either the child to send us
 284          * the appropriate exit status over the pipe or for the read to fail
 285          * (presumably with 0 for EOF if our child terminated abnormally).
 286          * If the read fails, exit with either the child's exit status if it
 287          * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal.
 288          */
 289         if (pid != 0) {
 290                 (void) close(pfds[1]);
 291 
 292                 if (read(pfds[0], &status, sizeof (status)) == sizeof (status))
 293                         _exit(status);
 294 
 295                 if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
 296                         _exit(WEXITSTATUS(status));
 297 
 298                 _exit(SMF_EXIT_ERR_FATAL);
 299         }
 300 
 301         openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
 302         (void) setsid();
 303         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
 304         (void) chdir("/");
 305         (void) umask(022);
 306         (void) close(pfds[0]);
 307 
 308         return (pfds[1]);
 309 }
 310 
 311 /*
 312  * This function is based on __init_daemon_priv() and replaces
 313  * __init_daemon_priv() since we want smbd to have all privileges so that it
 314  * can execute map/unmap commands with all privileges during share
 315  * connection/disconnection.  Unused privileges are disabled until command
 316  * execution.  The permitted and the limit set contains all privileges.  The
 317  * inheritable set contains no privileges.
 318  */
 319 
 320 static const char root_cp[] = "/core.%f.%t";
 321 static const char daemon_cp[] = "/var/tmp/core.%f.%t";
 322 
 323 static int
 324 smb_init_daemon_priv(int flags, uid_t uid, gid_t gid)
 325 {
 326         priv_set_t *perm = NULL;
 327         int ret = -1;
 328         char buf[1024];
 329 
 330         /*
 331          * This is not a significant failure: it allows us to start programs
 332          * with sufficient privileges and with the proper uid.   We don't
 333          * care enough about the extra groups in that case.
 334          */
 335         if (flags & PU_RESETGROUPS)
 336                 (void) setgroups(0, NULL);
 337 
 338         if (gid != (gid_t)-1 && setgid(gid) != 0)
 339                 goto end;
 340 
 341         perm = priv_allocset();
 342         if (perm == NULL)
 343                 goto end;
 344 
 345         /* E = P */
 346         (void) getppriv(PRIV_PERMITTED, perm);
 347         (void) setppriv(PRIV_SET, PRIV_EFFECTIVE, perm);
 348 
 349         /* Now reset suid and euid */
 350         if (uid != (uid_t)-1 && setreuid(uid, uid) != 0)
 351                 goto end;
 352 
 353         /* I = 0 */
 354         priv_emptyset(perm);
 355         ret = setppriv(PRIV_SET, PRIV_INHERITABLE, perm);
 356 end:
 357         priv_freeset(perm);
 358 
 359         if (core_get_process_path(buf, sizeof (buf), getpid()) == 0 &&
 360             strcmp(buf, "core") == 0) {
 361 
 362                 if ((uid == (uid_t)-1 ? geteuid() : uid) == 0) {
 363                         (void) core_set_process_path(root_cp, sizeof (root_cp),
 364                             getpid());
 365                 } else {
 366                         (void) core_set_process_path(daemon_cp,
 367                             sizeof (daemon_cp), getpid());
 368                 }
 369         }
 370         (void) setpflags(__PROC_PROTECT, 0);
 371 
 372         return (ret);
 373 }
 374 
 375 /*
 376  * Most privileges, except the ones that are required for smbd, are turn off
 377  * in the effective set.  They will be turn on when needed for command
 378  * execution during share connection/disconnection.
 379  */
 380 static void
 381 smbd_daemonize_fini(int fd, int exit_status)
 382 {
 383         priv_set_t *pset;
 384 
 385         /*
 386          * Now that we're running, if a pipe fd was specified, write an exit
 387          * status to it to indicate that our parent process can safely detach.
 388          * Then proceed to loading the remaining non-built-in modules.
 389          */
 390         if (fd >= 0)
 391                 (void) write(fd, &exit_status, sizeof (exit_status));
 392 
 393         (void) close(fd);
 394 
 395         pset = priv_allocset();
 396         if (pset == NULL)
 397                 return;
 398 
 399         priv_basicset(pset);
 400 
 401         /* list of privileges for smbd */
 402         (void) priv_addset(pset, PRIV_NET_MAC_AWARE);
 403         (void) priv_addset(pset, PRIV_NET_PRIVADDR);
 404         (void) priv_addset(pset, PRIV_PROC_AUDIT);
 405         (void) priv_addset(pset, PRIV_SYS_CONFIG);
 406         (void) priv_addset(pset, PRIV_SYS_DEVICES);
 407         (void) priv_addset(pset, PRIV_SYS_SMB);
 408         (void) priv_addset(pset, PRIV_SYS_MOUNT);
 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         static struct dir {
 428                 char    *name;
 429                 int     perm;
 430         } dir[] = {
 431                 { SMB_DBDIR,    0700 },
 432                 { SMB_CVOL,     0755 },
 433                 { SMB_SYSROOT,  0755 },
 434                 { SMB_SYSTEM32, 0755 },
 435                 { SMB_VSS,      0755 },
 436                 { SMB_PIPE_DIR, 0755 },
 437                 { "/var/smb/lipc", 0755 },
 438         };
 439         int     rc, i;
 440 
 441         smbd.s_pid = getpid();
 442 
 443         /*
 444          * Stop for a debugger attach here, which is after the
 445          * fork() etc. in smb_daemonize_init()
 446          */
 447         if (smbd.s_dbg_stop) {
 448                 smbd_report("pid %d stop for debugger attach", smbd.s_pid);
 449                 (void) kill(smbd.s_pid, SIGSTOP);
 450         }
 451         smbd_report("smbd starting, pid %d", smbd.s_pid);
 452 
 453         for (i = 0; i < sizeof (dir)/sizeof (dir[0]); ++i) {
 454                 if ((mkdir(dir[i].name, dir[i].perm) < 0) &&
 455                     (errno != EEXIST)) {
 456                         smbd_report("mkdir %s: %s", dir[i].name,
 457                             strerror(errno));
 458                         return (-1);
 459                 }
 460         }
 461 
 462         /*
 463          * This environment variable tells mech_krb5 to give us
 464          * MS-compatible behavior.
 465          */
 466         (void) putenv("MS_INTEROP=1");
 467 
 468         if ((rc = smb_ccache_init(SMB_VARRUN_DIR, SMB_CCACHE_FILE)) != 0) {
 469                 if (rc == -1)
 470                         smbd_report("mkdir %s: %s", SMB_VARRUN_DIR,
 471                             strerror(errno));
 472                 else
 473                         smbd_report("unable to set KRB5CCNAME");
 474                 return (-1);
 475         }
 476 
 477 #ifndef FKSMBD
 478         /* Upgrade SMF settings, if necessary. */
 479         smb_config_upgrade();
 480 #endif
 481 
 482         smb_codepage_init();
 483 
 484         rc = smbd_cups_init();
 485         if (smb_config_getbool(SMB_CI_PRINT_ENABLE))
 486                 smbd_report("print service %savailable", (rc == 0) ? "" : "un");
 487 
 488         if (smbd_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0)
 489                 smbd_report("NIC monitor failed to start");
 490 
 491         smbd_dyndns_init();
 492         smb_ipc_init();
 493 
 494         if (smb_config_getbool(SMB_CI_NETBIOS_ENABLE) == 0)
 495                 smbd_report("NetBIOS services disabled");
 496         else if (smb_netbios_start() != 0)
 497                 smbd_report("NetBIOS services failed to start");
 498         else
 499                 smbd_report("NetBIOS services started");
 500 
 501         smbd.s_secmode = smb_config_get_secmode();
 502         if ((rc = smb_domain_init(smbd.s_secmode)) != 0) {
 503                 if (rc == SMB_DOMAIN_NOMACHINE_SID) {
 504                         smbd_report(
 505                             "no machine SID: check idmap configuration");
 506                         return (-1);
 507                 }
 508         }
 509 
 510         if (smbd_dc_monitor_init() != 0)
 511                 smbd_report("DC monitor initialization failed %s",
 512                     strerror(errno));
 513 
 514         if (smbd_pipesvc_start() != 0) {
 515                 smbd_report("pipesvc initialization failed");
 516                 return (-1);
 517         }
 518 
 519         if (smbd_authsvc_start() != 0) {
 520                 smbd_report("authsvc initialization failed");
 521                 return (-1);
 522         }
 523 
 524         smbd.s_door_srv = smbd_door_start();
 525         if (smbd.s_door_srv < 0) {
 526                 smbd_report("door initialization failed %s", strerror(errno));
 527                 return (-1);
 528         }
 529 
 530         dyndns_update_zones();
 531         smbd_localtime_init();
 532         (void) smb_lgrp_start();
 533         smb_pwd_init(B_TRUE);
 534 
 535         if (smb_shr_start() != 0) {
 536                 smbd_report("share initialization failed: %s", strerror(errno));
 537                 return (-1);
 538         }
 539 
 540         smbd.s_door_lmshr = smbd_share_start();
 541         if (smbd.s_door_lmshr < 0)
 542                 smbd_report("share initialization failed");
 543 
 544         /* Open the driver, load the kernel config. */
 545         if (smbd_kernel_bind() != 0) {
 546                 return (-1);
 547         }
 548 
 549         smbd_load_shares();
 550         smbd_load_printers();
 551         smbd_spool_start();
 552 
 553         smbd.s_initialized = B_TRUE;
 554         smbd_report("service initialized");
 555 
 556         return (0);
 557 }
 558 
 559 /*
 560  * Shutdown smbd and smbsrv kernel services.
 561  *
 562  * Called only by the main thread.
 563  */
 564 static void
 565 smbd_service_fini(void)
 566 {
 567 
 568         smbd.s_shutting_down = B_TRUE;
 569         smbd_report("service shutting down");
 570 
 571         smb_kmod_stop();
 572         smb_logon_abort();
 573         smb_lgrp_stop();
 574         smbd_pipesvc_stop();
 575         smbd_door_stop();
 576         smbd_authsvc_stop();
 577         smbd_spool_stop();
 578         smbd_kernel_unbind();
 579         smbd_share_stop();
 580         smb_shr_unload();
 581         smb_shr_stop();
 582         dyndns_stop();
 583         smbd_nicmon_stop();
 584         smb_ccache_remove(SMB_CCACHE_PATH);
 585         smb_pwd_fini();
 586         smb_domain_fini();
 587         mlsvc_fini();
 588         smb_netbios_stop();
 589         smbd_cups_fini();
 590 
 591         smbd.s_initialized = B_FALSE;
 592         smbd_report("service terminated");
 593         closelog();
 594 }
 595 
 596 /*
 597  * Called when SMF sends us a SIGHUP.  Update the smbd configuration
 598  * from SMF and check for changes that require service reconfiguration.
 599  */
 600 static void
 601 smbd_refresh_handler()
 602 {
 603         int new_debug;
 604 
 605         if (smbd.s_shutting_down)
 606                 return;
 607 
 608         smbd.s_refreshes++;
 609 
 610         new_debug = smb_config_get_debug();
 611         if (smbd.s_debug || new_debug)
 612                 smbd_report("debug=%d", new_debug);
 613         smbd.s_debug = new_debug;
 614 
 615         smbd_spool_stop();
 616         smbd_dc_monitor_refresh();
 617         smb_ccache_remove(SMB_CCACHE_PATH);
 618 
 619         /*
 620          * Clear the DNS zones for the existing interfaces
 621          * before updating the NIC interface list.
 622          */
 623         dyndns_clear_zones();
 624 
 625         if (smbd_nicmon_refresh() != 0)
 626                 smbd_report("NIC monitor refresh failed");
 627 
 628         smb_netbios_name_reconfig();
 629         smb_browser_reconfig();
 630         dyndns_update_zones();
 631 
 632         /* This reloads the in-kernel config. */
 633         (void) smbd_kernel_bind();
 634 
 635         /* On refresh load share properties only, not the shares themselves */
 636         smb_shr_load_execinfo();
 637 
 638         smbd_load_printers();
 639         smbd_spool_start();
 640 }
 641 
 642 void
 643 smbd_set_secmode(int secmode)
 644 {
 645         switch (secmode) {
 646         case SMB_SECMODE_WORKGRP:
 647         case SMB_SECMODE_DOMAIN:
 648                 (void) smb_config_set_secmode(secmode);
 649                 smbd.s_secmode = secmode;
 650                 break;
 651 
 652         default:
 653                 syslog(LOG_ERR, "invalid security mode: %d", secmode);
 654                 syslog(LOG_ERR, "entering maintenance mode");
 655                 (void) smb_smf_maintenance_mode();
 656         }
 657 }
 658 
 659 /*
 660  * The service is online if initialization is complete and shutdown
 661  * has not begun.
 662  */
 663 boolean_t
 664 smbd_online(void)
 665 {
 666         return (smbd.s_initialized && !smbd.s_shutting_down);
 667 }
 668 
 669 /*
 670  * Wait until the service is online.  Provided for threads that
 671  * should wait until the service has been fully initialized before
 672  * they start performing operations.
 673  */
 674 void
 675 smbd_online_wait(const char *text)
 676 {
 677         while (!smbd_online())
 678                 (void) sleep(SMBD_ONLINE_WAIT_INTERVAL);
 679 
 680         if (text != NULL) {
 681                 syslog(LOG_DEBUG, "%s: online", text);
 682                 (void) fprintf(stderr, "%s: online\n", text);
 683         }
 684 }
 685 
 686 /*
 687  * If the door has already been opened by another process (non-zero pid
 688  * in target), we assume that another smbd is already running.  If there
 689  * is a race here, it will be caught later when smbsrv is opened because
 690  * only one process is allowed to open the device at a time.
 691  */
 692 static int
 693 smbd_already_running(void)
 694 {
 695         door_info_t     info;
 696         char            *door_name;
 697         int             door;
 698 
 699         door_name = getenv("SMBD_DOOR_NAME");
 700         if (door_name == NULL)
 701                 door_name = SMBD_DOOR_NAME;
 702 
 703         if ((door = open(door_name, O_RDONLY)) < 0)
 704                 return (0);
 705 
 706         if (door_info(door, &info) < 0)
 707                 return (0);
 708 
 709         if (info.di_target > 0) {
 710                 smbd_report("already running: pid %ld\n", info.di_target);
 711                 (void) close(door);
 712                 return (1);
 713         }
 714 
 715         (void) close(door);
 716         return (0);
 717 }
 718 
 719 /*
 720  * smbd_kernel_bind
 721  *
 722  * If smbsrv is already bound, reload the configuration and update smbsrv.
 723  * Otherwise, open the smbsrv device and start the kernel service.
 724  */
 725 static int
 726 smbd_kernel_bind(void)
 727 {
 728         smb_kmod_cfg_t  cfg;
 729         int             rc;
 730 
 731         if (smbd.s_kbound) {
 732                 smb_load_kconfig(&cfg);
 733                 smbd_get_authconf(&cfg);
 734                 rc = smb_kmod_setcfg(&cfg);
 735                 if (rc < 0)
 736                         smbd_report("kernel configuration update failed: %s",
 737                             strerror(rc));
 738                 return (rc);
 739         }
 740 
 741         if (smb_kmod_isbound())
 742                 smbd_kernel_unbind();
 743 
 744         if ((rc = smb_kmod_bind()) == 0) {
 745                 rc = smbd_kernel_start();
 746                 if (rc != 0)
 747                         smb_kmod_unbind();
 748                 else
 749                         smbd.s_kbound = B_TRUE;
 750         } else {
 751                 smbd_report("kernel bind error: %s", strerror(rc));
 752         }
 753 
 754         return (rc);
 755 }
 756 
 757 static int
 758 smbd_kernel_start(void)
 759 {
 760         smb_kmod_cfg_t  cfg;
 761         int             rc;
 762 
 763         smb_load_kconfig(&cfg);
 764         smbd_get_authconf(&cfg);
 765         rc = smb_kmod_setcfg(&cfg);
 766         if (rc != 0) {
 767                 smbd_report("kernel config ioctl error: %s", strerror(rc));
 768                 return (rc);
 769         }
 770 
 771         rc = smb_kmod_setgmtoff(smbd_gmtoff());
 772         if (rc != 0) {
 773                 smbd_report("kernel gmtoff ioctl error: %s", strerror(rc));
 774                 return (rc);
 775         }
 776 
 777         rc = smb_kmod_start(smbd.s_door_opipe, smbd.s_door_lmshr,
 778             smbd.s_door_srv);
 779 
 780         if (rc != 0) {
 781                 smbd_report("kernel start ioctl error: %s", strerror(rc));
 782                 return (rc);
 783         }
 784 
 785         return (0);
 786 }
 787 
 788 /*
 789  * smbd_kernel_unbind
 790  */
 791 static void
 792 smbd_kernel_unbind(void)
 793 {
 794         smb_kmod_unbind();
 795         smbd.s_kbound = B_FALSE;
 796 }
 797 
 798 /*
 799  * Create the Dynamic DNS publisher thread.
 800  */
 801 static void
 802 smbd_dyndns_init(void)
 803 {
 804         pthread_t       tid;
 805         pthread_attr_t  attr;
 806         int             rc;
 807 
 808         dyndns_start();
 809 
 810         (void) pthread_attr_init(&attr);
 811         (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 812         rc = pthread_create(&tid, &attr, dyndns_publisher, NULL);
 813         (void) pthread_attr_destroy(&attr);
 814 
 815         if (rc != 0)
 816                 smbd_report("unable to start dyndns publisher: %s",
 817                     strerror(errno));
 818 }
 819 
 820 /*
 821  * Launches a thread to populate the share cache by share information
 822  * stored in sharemgr
 823  */
 824 static void
 825 smbd_load_shares(void)
 826 {
 827         pthread_t       tid;
 828         pthread_attr_t  attr;
 829         int             rc;
 830 
 831         (void) pthread_attr_init(&attr);
 832         (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 833         rc = pthread_create(&tid, &attr, smbd_share_loader, NULL);
 834         (void) pthread_attr_destroy(&attr);
 835 
 836         if (rc != 0)
 837                 smbd_report("unable to load disk shares: %s", strerror(errno));
 838 }
 839 
 840 /*
 841  * This wrapper function is used to avoid casting smb_shr_load() in
 842  * pthread_create() above. It is called very infrequently.
 843  */
 844 static void *
 845 smbd_share_loader(void *args)
 846 {
 847         (void) smb_shr_load(args);
 848         return (NULL);
 849 }
 850 
 851 /*
 852  * Initialization of the localtime thread.
 853  * Returns 0 on success, an error number if thread creation fails.
 854  */
 855 
 856 static void
 857 smbd_localtime_init(void)
 858 {
 859         pthread_attr_t  attr;
 860         int             rc;
 861 
 862         (void) pthread_attr_init(&attr);
 863         (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 864         rc = pthread_create(&smbd.s_localtime_tid, &attr,
 865             smbd_localtime_monitor, NULL);
 866         (void) pthread_attr_destroy(&attr);
 867 
 868         if (rc != 0)
 869                 smbd_report("unable to monitor localtime: %s", strerror(errno));
 870 }
 871 
 872 /*
 873  * Send local gmtoff to the kernel module one time at startup and each
 874  * time it changes (up to twice a year).
 875  * Local gmtoff is checked once every 15 minutes since some timezones
 876  * are aligned on half and quarter hour boundaries.
 877  */
 878 /*ARGSUSED*/
 879 static void *
 880 smbd_localtime_monitor(void *arg)
 881 {
 882         struct tm local_tm;
 883         time_t secs;
 884         int32_t gmtoff, last_gmtoff = -1;
 885         int timeout;
 886         int error;
 887 
 888         smbd_online_wait("smbd_localtime_monitor");
 889 
 890         for (;;) {
 891                 gmtoff = smbd_gmtoff();
 892 
 893                 if ((last_gmtoff != gmtoff) && smbd.s_kbound) {
 894                         error = smb_kmod_setgmtoff(gmtoff);
 895                         if (error != 0)
 896                                 smbd_report("localtime set failed: %s",
 897                                     strerror(error));
 898                 }
 899 
 900                 /*
 901                  * Align the next iteration on a fifteen minute boundary.
 902                  */
 903                 secs = time(0);
 904                 (void) localtime_r(&secs, &local_tm);
 905                 timeout = ((15 - (local_tm.tm_min % 15)) * SECSPERMIN);
 906                 (void) sleep(timeout);
 907 
 908                 last_gmtoff = gmtoff;
 909         }
 910 
 911         /*NOTREACHED*/
 912         return (NULL);
 913 }
 914 
 915 /*
 916  * smbd_gmtoff
 917  *
 918  * Determine offset from GMT. If daylight saving time use altzone,
 919  * otherwise use timezone.
 920  */
 921 static int32_t
 922 smbd_gmtoff(void)
 923 {
 924         time_t clock_val;
 925         struct tm *atm;
 926         int32_t gmtoff;
 927 
 928         (void) time(&clock_val);
 929         atm = localtime(&clock_val);
 930 
 931         gmtoff = (atm->tm_isdst) ? altzone : timezone;
 932 
 933         return (gmtoff);
 934 }
 935 
 936 /*
 937  * Set up configuration options and parse the command line.
 938  * This function will determine if we will run as a daemon
 939  * or in the foreground.
 940  *
 941  * Failure to find a uid or gid results in using the default (0).
 942  */
 943 static int
 944 smbd_setup_options(int argc, char *argv[])
 945 {
 946         struct passwd *pwd;
 947         struct group *grp;
 948         int c;
 949 
 950         if ((pwd = getpwnam("root")) != NULL)
 951                 smbd.s_uid = pwd->pw_uid;
 952 
 953         if ((grp = getgrnam("sys")) != NULL)
 954                 smbd.s_gid = grp->gr_gid;
 955 
 956         smbd.s_debug = smb_config_get_debug();
 957         smbd.s_fg = smb_config_get_fg_flag();
 958 
 959         while ((c = getopt(argc, argv, ":dfs")) != -1) {
 960                 switch (c) {
 961                 case 'd':
 962                         smbd.s_debug++;
 963                         break;
 964                 case 'f':
 965                         smbd.s_fg = 1;
 966                         break;
 967                 case 's':
 968                         smbd.s_dbg_stop = 1;
 969                         break;
 970                 case ':':
 971                 case '?':
 972                 default:
 973                         smbd_usage(stderr);
 974                         return (-1);
 975                 }
 976         }
 977 
 978         return (0);
 979 }
 980 
 981 static void
 982 smbd_usage(FILE *fp)
 983 {
 984         static char *help[] = {
 985                 "-d  enable debug messages"
 986                 "-f  run program in foreground"
 987         };
 988 
 989         int i;
 990 
 991         (void) fprintf(fp, "Usage: %s [-f]\n", smbd.s_pname);
 992 
 993         for (i = 0; i < sizeof (help)/sizeof (help[0]); ++i)
 994                 (void) fprintf(fp, "    %s\n", help[i]);
 995 }
 996 
 997 void
 998 smbd_report(const char *fmt, ...)
 999 {
1000         char buf[128];
1001         va_list ap;
1002 
1003         if (fmt == NULL)
1004                 return;
1005 
1006         va_start(ap, fmt);
1007         (void) vsnprintf(buf, 128, fmt, ap);
1008         va_end(ap);
1009 
1010         (void) fprintf(stderr, "smbd: %s\n", buf);
1011 }
1012 
1013 /*
1014  * Enable libumem debugging by default on DEBUG builds.
1015  */
1016 #ifdef DEBUG
1017 const char *
1018 _umem_debug_init(void)
1019 {
1020         return ("default,verbose"); /* $UMEM_DEBUG setting */
1021 }
1022 
1023 const char *
1024 _umem_logging_init(void)
1025 {
1026         return ("fail,contents"); /* $UMEM_LOGGING setting */
1027 }
1028 #endif