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 2015 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_DEVICES);
 406         (void) priv_addset(pset, PRIV_SYS_SMB);
 407         (void) priv_addset(pset, PRIV_SYS_MOUNT);
 408 
 409         priv_inverse(pset);
 410 
 411         /* turn off unneeded privileges */
 412         (void) setppriv(PRIV_OFF, PRIV_EFFECTIVE, pset);
 413 
 414         priv_freeset(pset);
 415 
 416         /* reenable core dumps */
 417         __fini_daemon_priv(NULL);
 418 }
 419 
 420 /*
 421  * smbd_service_init
 422  */
 423 static int
 424 smbd_service_init(void)
 425 {
 426         static struct dir {
 427                 char    *name;
 428                 int     perm;
 429         } dir[] = {
 430                 { SMB_DBDIR,    0700 },
 431                 { SMB_CVOL,     0755 },
 432                 { SMB_SYSROOT,  0755 },
 433                 { SMB_SYSTEM32, 0755 },
 434                 { SMB_VSS,      0755 },
 435                 { SMB_PIPE_DIR, 0755 },
 436                 { "/var/smb/lipc", 0755 },
 437         };
 438         int     rc, i;
 439 
 440         smbd.s_pid = getpid();
 441 
 442         /*
 443          * Stop for a debugger attach here, which is after the
 444          * fork() etc. in smb_daemonize_init()
 445          */
 446         if (smbd.s_dbg_stop) {
 447                 smbd_report("pid %d stop for debugger attach", smbd.s_pid);
 448                 (void) kill(smbd.s_pid, SIGSTOP);
 449         }
 450         smbd_report("smbd starting, pid %d", smbd.s_pid);
 451 
 452         for (i = 0; i < sizeof (dir)/sizeof (dir[0]); ++i) {
 453                 if ((mkdir(dir[i].name, dir[i].perm) < 0) &&
 454                     (errno != EEXIST)) {
 455                         smbd_report("mkdir %s: %s", dir[i].name,
 456                             strerror(errno));
 457                         return (-1);
 458                 }
 459         }
 460 
 461         /*
 462          * This environment variable tells mech_krb5 to give us
 463          * MS-compatible behavior.
 464          */
 465         (void) putenv("MS_INTEROP=1");
 466 
 467         if ((rc = smb_ccache_init(SMB_VARRUN_DIR, SMB_CCACHE_FILE)) != 0) {
 468                 if (rc == -1)
 469                         smbd_report("mkdir %s: %s", SMB_VARRUN_DIR,
 470                             strerror(errno));
 471                 else
 472                         smbd_report("unable to set KRB5CCNAME");
 473                 return (-1);
 474         }
 475 
 476 #ifndef FKSMBD
 477         /* Upgrade SMF settings, if necessary. */
 478         smb_config_upgrade();
 479 #endif
 480 
 481         smb_codepage_init();
 482 
 483         rc = smbd_cups_init();
 484         if (smb_config_getbool(SMB_CI_PRINT_ENABLE))
 485                 smbd_report("print service %savailable", (rc == 0) ? "" : "un");
 486 
 487         if (smbd_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0)
 488                 smbd_report("NIC monitor failed to start");
 489 
 490         smbd_dyndns_init();
 491         smb_ipc_init();
 492 
 493         if (smb_config_getbool(SMB_CI_NETBIOS_ENABLE) == 0)
 494                 smbd_report("NetBIOS services disabled");
 495         else if (smb_netbios_start() != 0)
 496                 smbd_report("NetBIOS services failed to start");
 497         else
 498                 smbd_report("NetBIOS services started");
 499 
 500         smbd.s_secmode = smb_config_get_secmode();
 501         if ((rc = smb_domain_init(smbd.s_secmode)) != 0) {
 502                 if (rc == SMB_DOMAIN_NOMACHINE_SID) {
 503                         smbd_report(
 504                             "no machine SID: check idmap configuration");
 505                         return (-1);
 506                 }
 507         }
 508 
 509         if (smbd_dc_monitor_init() != 0)
 510                 smbd_report("DC monitor initialization failed %s",
 511                     strerror(errno));
 512 
 513         if (smbd_pipesvc_start() != 0) {
 514                 smbd_report("pipesvc initialization failed");
 515                 return (-1);
 516         }
 517 
 518         if (smbd_authsvc_start() != 0) {
 519                 smbd_report("authsvc initialization failed");
 520                 return (-1);
 521         }
 522 
 523         smbd.s_door_srv = smbd_door_start();
 524         if (smbd.s_door_srv < 0) {
 525                 smbd_report("door initialization failed %s", strerror(errno));
 526                 return (-1);
 527         }
 528 
 529         dyndns_update_zones();
 530         smbd_localtime_init();
 531         (void) smb_lgrp_start();
 532         smb_pwd_init(B_TRUE);
 533 
 534         if (smb_shr_start() != 0) {
 535                 smbd_report("share initialization failed: %s", strerror(errno));
 536                 return (-1);
 537         }
 538 
 539         smbd.s_door_lmshr = smbd_share_start();
 540         if (smbd.s_door_lmshr < 0)
 541                 smbd_report("share initialization failed");
 542 
 543         /* Open the driver, load the kernel config. */
 544         if (smbd_kernel_bind() != 0) {
 545                 return (-1);
 546         }
 547 
 548         smbd_load_shares();
 549         smbd_load_printers();
 550         smbd_spool_start();
 551 
 552         smbd.s_initialized = B_TRUE;
 553         smbd_report("service initialized");
 554 
 555         return (0);
 556 }
 557 
 558 /*
 559  * Shutdown smbd and smbsrv kernel services.
 560  *
 561  * Called only by the main thread.
 562  */
 563 static void
 564 smbd_service_fini(void)
 565 {
 566 
 567         smbd.s_shutting_down = B_TRUE;
 568         smbd_report("service shutting down");
 569 
 570         smb_kmod_stop();
 571         smb_logon_abort();
 572         smb_lgrp_stop();
 573         smbd_pipesvc_stop();
 574         smbd_door_stop();
 575         smbd_authsvc_stop();
 576         smbd_spool_stop();
 577         smbd_kernel_unbind();
 578         smbd_share_stop();
 579         smb_shr_stop();
 580         dyndns_stop();
 581         smbd_nicmon_stop();
 582         smb_ccache_remove(SMB_CCACHE_PATH);
 583         smb_pwd_fini();
 584         smb_domain_fini();
 585         mlsvc_fini();
 586         smb_netbios_stop();
 587         smbd_cups_fini();
 588 
 589         smbd.s_initialized = B_FALSE;
 590         smbd_report("service terminated");
 591         closelog();
 592 }
 593 
 594 /*
 595  * Called when SMF sends us a SIGHUP.  Update the smbd configuration
 596  * from SMF and check for changes that require service reconfiguration.
 597  */
 598 static void
 599 smbd_refresh_handler()
 600 {
 601         int new_debug;
 602 
 603         if (smbd.s_shutting_down)
 604                 return;
 605 
 606         smbd.s_refreshes++;
 607 
 608         new_debug = smb_config_get_debug();
 609         if (smbd.s_debug || new_debug)
 610                 smbd_report("debug=%d", new_debug);
 611         smbd.s_debug = new_debug;
 612 
 613         smbd_spool_stop();
 614         smbd_dc_monitor_refresh();
 615         smb_ccache_remove(SMB_CCACHE_PATH);
 616 
 617         /*
 618          * Clear the DNS zones for the existing interfaces
 619          * before updating the NIC interface list.
 620          */
 621         dyndns_clear_zones();
 622 
 623         if (smbd_nicmon_refresh() != 0)
 624                 smbd_report("NIC monitor refresh failed");
 625 
 626         smb_netbios_name_reconfig();
 627         smb_browser_reconfig();
 628         dyndns_update_zones();
 629 
 630         /* This reloads the in-kernel config. */
 631         (void) smbd_kernel_bind();
 632 
 633         smbd_load_shares();
 634         smbd_load_printers();
 635         smbd_spool_start();
 636 }
 637 
 638 void
 639 smbd_set_secmode(int secmode)
 640 {
 641         switch (secmode) {
 642         case SMB_SECMODE_WORKGRP:
 643         case SMB_SECMODE_DOMAIN:
 644                 (void) smb_config_set_secmode(secmode);
 645                 smbd.s_secmode = secmode;
 646                 break;
 647 
 648         default:
 649                 syslog(LOG_ERR, "invalid security mode: %d", secmode);
 650                 syslog(LOG_ERR, "entering maintenance mode");
 651                 (void) smb_smf_maintenance_mode();
 652         }
 653 }
 654 
 655 /*
 656  * The service is online if initialization is complete and shutdown
 657  * has not begun.
 658  */
 659 boolean_t
 660 smbd_online(void)
 661 {
 662         return (smbd.s_initialized && !smbd.s_shutting_down);
 663 }
 664 
 665 /*
 666  * Wait until the service is online.  Provided for threads that
 667  * should wait until the service has been fully initialized before
 668  * they start performing operations.
 669  */
 670 void
 671 smbd_online_wait(const char *text)
 672 {
 673         while (!smbd_online())
 674                 (void) sleep(SMBD_ONLINE_WAIT_INTERVAL);
 675 
 676         if (text != NULL) {
 677                 syslog(LOG_DEBUG, "%s: online", text);
 678                 (void) fprintf(stderr, "%s: online\n", text);
 679         }
 680 }
 681 
 682 /*
 683  * If the door has already been opened by another process (non-zero pid
 684  * in target), we assume that another smbd is already running.  If there
 685  * is a race here, it will be caught later when smbsrv is opened because
 686  * only one process is allowed to open the device at a time.
 687  */
 688 static int
 689 smbd_already_running(void)
 690 {
 691         door_info_t     info;
 692         char            *door_name;
 693         int             door;
 694 
 695         door_name = getenv("SMBD_DOOR_NAME");
 696         if (door_name == NULL)
 697                 door_name = SMBD_DOOR_NAME;
 698 
 699         if ((door = open(door_name, O_RDONLY)) < 0)
 700                 return (0);
 701 
 702         if (door_info(door, &info) < 0)
 703                 return (0);
 704 
 705         if (info.di_target > 0) {
 706                 smbd_report("already running: pid %ld\n", info.di_target);
 707                 (void) close(door);
 708                 return (1);
 709         }
 710 
 711         (void) close(door);
 712         return (0);
 713 }
 714 
 715 /*
 716  * smbd_kernel_bind
 717  *
 718  * If smbsrv is already bound, reload the configuration and update smbsrv.
 719  * Otherwise, open the smbsrv device and start the kernel service.
 720  */
 721 static int
 722 smbd_kernel_bind(void)
 723 {
 724         smb_kmod_cfg_t  cfg;
 725         int             rc;
 726 
 727         if (smbd.s_kbound) {
 728                 smb_load_kconfig(&cfg);
 729                 smbd_get_authconf(&cfg);
 730                 rc = smb_kmod_setcfg(&cfg);
 731                 if (rc < 0)
 732                         smbd_report("kernel configuration update failed: %s",
 733                             strerror(rc));
 734                 return (rc);
 735         }
 736 
 737         if (smb_kmod_isbound())
 738                 smbd_kernel_unbind();
 739 
 740         if ((rc = smb_kmod_bind()) == 0) {
 741                 rc = smbd_kernel_start();
 742                 if (rc != 0)
 743                         smb_kmod_unbind();
 744                 else
 745                         smbd.s_kbound = B_TRUE;
 746         } else {
 747                 smbd_report("kernel bind error: %s", strerror(rc));
 748         }
 749 
 750         return (rc);
 751 }
 752 
 753 static int
 754 smbd_kernel_start(void)
 755 {
 756         smb_kmod_cfg_t  cfg;
 757         int             rc;
 758 
 759         smb_load_kconfig(&cfg);
 760         smbd_get_authconf(&cfg);
 761         rc = smb_kmod_setcfg(&cfg);
 762         if (rc != 0) {
 763                 smbd_report("kernel config ioctl error: %s", strerror(rc));
 764                 return (rc);
 765         }
 766 
 767         rc = smb_kmod_setgmtoff(smbd_gmtoff());
 768         if (rc != 0) {
 769                 smbd_report("kernel gmtoff ioctl error: %s", strerror(rc));
 770                 return (rc);
 771         }
 772 
 773         rc = smb_kmod_start(smbd.s_door_opipe, smbd.s_door_lmshr,
 774             smbd.s_door_srv);
 775 
 776         if (rc != 0) {
 777                 smbd_report("kernel start ioctl error: %s", strerror(rc));
 778                 return (rc);
 779         }
 780 
 781         return (0);
 782 }
 783 
 784 /*
 785  * smbd_kernel_unbind
 786  */
 787 static void
 788 smbd_kernel_unbind(void)
 789 {
 790         smb_kmod_unbind();
 791         smbd.s_kbound = B_FALSE;
 792 }
 793 
 794 /*
 795  * Create the Dynamic DNS publisher thread.
 796  */
 797 static void
 798 smbd_dyndns_init(void)
 799 {
 800         pthread_t       tid;
 801         pthread_attr_t  attr;
 802         int             rc;
 803 
 804         dyndns_start();
 805 
 806         (void) pthread_attr_init(&attr);
 807         (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 808         rc = pthread_create(&tid, &attr, dyndns_publisher, NULL);
 809         (void) pthread_attr_destroy(&attr);
 810 
 811         if (rc != 0)
 812                 smbd_report("unable to start dyndns publisher: %s",
 813                     strerror(errno));
 814 }
 815 
 816 /*
 817  * Launches a thread to populate the share cache by share information
 818  * stored in sharemgr
 819  */
 820 static void
 821 smbd_load_shares(void)
 822 {
 823         pthread_t       tid;
 824         pthread_attr_t  attr;
 825         int             rc;
 826 
 827         (void) pthread_attr_init(&attr);
 828         (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 829         rc = pthread_create(&tid, &attr, smbd_share_loader, NULL);
 830         (void) pthread_attr_destroy(&attr);
 831 
 832         if (rc != 0)
 833                 smbd_report("unable to load disk shares: %s", strerror(errno));
 834 }
 835 
 836 static void *
 837 smbd_share_loader(void *args)
 838 {
 839         (void) smb_shr_load(args);
 840         return (NULL);
 841 }
 842 
 843 /*
 844  * Initialization of the localtime thread.
 845  * Returns 0 on success, an error number if thread creation fails.
 846  */
 847 
 848 static void
 849 smbd_localtime_init(void)
 850 {
 851         pthread_attr_t  attr;
 852         int             rc;
 853 
 854         (void) pthread_attr_init(&attr);
 855         (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 856         rc = pthread_create(&smbd.s_localtime_tid, &attr,
 857             smbd_localtime_monitor, NULL);
 858         (void) pthread_attr_destroy(&attr);
 859 
 860         if (rc != 0)
 861                 smbd_report("unable to monitor localtime: %s", strerror(errno));
 862 }
 863 
 864 /*
 865  * Send local gmtoff to the kernel module one time at startup and each
 866  * time it changes (up to twice a year).
 867  * Local gmtoff is checked once every 15 minutes since some timezones
 868  * are aligned on half and quarter hour boundaries.
 869  */
 870 /*ARGSUSED*/
 871 static void *
 872 smbd_localtime_monitor(void *arg)
 873 {
 874         struct tm local_tm;
 875         time_t secs;
 876         int32_t gmtoff, last_gmtoff = -1;
 877         int timeout;
 878         int error;
 879 
 880         smbd_online_wait("smbd_localtime_monitor");
 881 
 882         for (;;) {
 883                 gmtoff = smbd_gmtoff();
 884 
 885                 if ((last_gmtoff != gmtoff) && smbd.s_kbound) {
 886                         error = smb_kmod_setgmtoff(gmtoff);
 887                         if (error != 0)
 888                                 smbd_report("localtime set failed: %s",
 889                                     strerror(error));
 890                 }
 891 
 892                 /*
 893                  * Align the next iteration on a fifteen minute boundary.
 894                  */
 895                 secs = time(0);
 896                 (void) localtime_r(&secs, &local_tm);
 897                 timeout = ((15 - (local_tm.tm_min % 15)) * SECSPERMIN);
 898                 (void) sleep(timeout);
 899 
 900                 last_gmtoff = gmtoff;
 901         }
 902 
 903         /*NOTREACHED*/
 904         return (NULL);
 905 }
 906 
 907 /*
 908  * smbd_gmtoff
 909  *
 910  * Determine offset from GMT. If daylight saving time use altzone,
 911  * otherwise use timezone.
 912  */
 913 static int32_t
 914 smbd_gmtoff(void)
 915 {
 916         time_t clock_val;
 917         struct tm *atm;
 918         int32_t gmtoff;
 919 
 920         (void) time(&clock_val);
 921         atm = localtime(&clock_val);
 922 
 923         gmtoff = (atm->tm_isdst) ? altzone : timezone;
 924 
 925         return (gmtoff);
 926 }
 927 
 928 /*
 929  * Set up configuration options and parse the command line.
 930  * This function will determine if we will run as a daemon
 931  * or in the foreground.
 932  *
 933  * Failure to find a uid or gid results in using the default (0).
 934  */
 935 static int
 936 smbd_setup_options(int argc, char *argv[])
 937 {
 938         struct passwd *pwd;
 939         struct group *grp;
 940         int c;
 941 
 942         if ((pwd = getpwnam("root")) != NULL)
 943                 smbd.s_uid = pwd->pw_uid;
 944 
 945         if ((grp = getgrnam("sys")) != NULL)
 946                 smbd.s_gid = grp->gr_gid;
 947 
 948         smbd.s_debug = smb_config_get_debug();
 949         smbd.s_fg = smb_config_get_fg_flag();
 950 
 951         while ((c = getopt(argc, argv, ":dfs")) != -1) {
 952                 switch (c) {
 953                 case 'd':
 954                         smbd.s_debug++;
 955                         break;
 956                 case 'f':
 957                         smbd.s_fg = 1;
 958                         break;
 959                 case 's':
 960                         smbd.s_dbg_stop = 1;
 961                         break;
 962                 case ':':
 963                 case '?':
 964                 default:
 965                         smbd_usage(stderr);
 966                         return (-1);
 967                 }
 968         }
 969 
 970         return (0);
 971 }
 972 
 973 static void
 974 smbd_usage(FILE *fp)
 975 {
 976         static char *help[] = {
 977                 "-d  enable debug messages"
 978                 "-f  run program in foreground"
 979         };
 980 
 981         int i;
 982 
 983         (void) fprintf(fp, "Usage: %s [-f]\n", smbd.s_pname);
 984 
 985         for (i = 0; i < sizeof (help)/sizeof (help[0]); ++i)
 986                 (void) fprintf(fp, "    %s\n", help[i]);
 987 }
 988 
 989 void
 990 smbd_report(const char *fmt, ...)
 991 {
 992         char buf[128];
 993         va_list ap;
 994 
 995         if (fmt == NULL)
 996                 return;
 997 
 998         va_start(ap, fmt);
 999         (void) vsnprintf(buf, 128, fmt, ap);
1000         va_end(ap);
1001 
1002         (void) fprintf(stderr, "smbd: %s\n", buf);
1003 }
1004 
1005 /*
1006  * Enable libumem debugging by default on DEBUG builds.
1007  */
1008 #ifdef DEBUG
1009 const char *
1010 _umem_debug_init(void)
1011 {
1012         return ("default,verbose"); /* $UMEM_DEBUG setting */
1013 }
1014 
1015 const char *
1016 _umem_logging_init(void)
1017 {
1018         return ("fail,contents"); /* $UMEM_LOGGING setting */
1019 }
1020 #endif