1*5331Samw /* 2*5331Samw * CDDL HEADER START 3*5331Samw * 4*5331Samw * The contents of this file are subject to the terms of the 5*5331Samw * Common Development and Distribution License (the "License"). 6*5331Samw * You may not use this file except in compliance with the License. 7*5331Samw * 8*5331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5331Samw * or http://www.opensolaris.org/os/licensing. 10*5331Samw * See the License for the specific language governing permissions 11*5331Samw * and limitations under the License. 12*5331Samw * 13*5331Samw * When distributing Covered Code, include this CDDL HEADER in each 14*5331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5331Samw * If applicable, add the following below this CDDL HEADER, with the 16*5331Samw * fields enclosed by brackets "[]" replaced with your own identifying 17*5331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 18*5331Samw * 19*5331Samw * CDDL HEADER END 20*5331Samw */ 21*5331Samw /* 22*5331Samw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*5331Samw * Use is subject to license terms. 24*5331Samw */ 25*5331Samw 26*5331Samw #pragma ident "%Z%%M% %I% %E% SMI" 27*5331Samw 28*5331Samw #include <sys/types.h> 29*5331Samw #include <sys/stat.h> 30*5331Samw #include <sys/ioccom.h> 31*5331Samw #include <stdio.h> 32*5331Samw #include <string.h> 33*5331Samw #include <strings.h> 34*5331Samw #include <stdlib.h> 35*5331Samw #include <unistd.h> 36*5331Samw #include <stdarg.h> 37*5331Samw #include <fcntl.h> 38*5331Samw #include <wait.h> 39*5331Samw #include <signal.h> 40*5331Samw #include <libscf.h> 41*5331Samw #include <limits.h> 42*5331Samw #include <priv_utils.h> 43*5331Samw #include <door.h> 44*5331Samw #include <errno.h> 45*5331Samw #include <syslog.h> 46*5331Samw #include <pthread.h> 47*5331Samw #include <time.h> 48*5331Samw #include <libscf.h> 49*5331Samw #include <zone.h> 50*5331Samw #include <tzfile.h> 51*5331Samw #include <libgen.h> 52*5331Samw #include <pwd.h> 53*5331Samw #include <grp.h> 54*5331Samw 55*5331Samw #include <smbsrv/smb_door_svc.h> 56*5331Samw #include <smbsrv/smb_ioctl.h> 57*5331Samw #include <smbsrv/libsmb.h> 58*5331Samw #include <smbsrv/libsmbns.h> 59*5331Samw #include <smbsrv/libsmbrdr.h> 60*5331Samw #include <smbsrv/libmlsvc.h> 61*5331Samw 62*5331Samw #include "smbd.h" 63*5331Samw 64*5331Samw #define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv" 65*5331Samw #define SMB_CACHEDIR "/var/run/smb" 66*5331Samw #define SMB_DBDIR "/var/smb" 67*5331Samw 68*5331Samw extern void smb_netbios_name_reconfig(); 69*5331Samw extern void smb_browser_config(); 70*5331Samw 71*5331Samw static int smbd_daemonize_init(void); 72*5331Samw static void smbd_daemonize_fini(int, int); 73*5331Samw 74*5331Samw static int smbd_kernel_bind(void); 75*5331Samw static void smbd_kernel_unbind(void); 76*5331Samw static int smbd_already_running(void); 77*5331Samw 78*5331Samw static int smbd_service_init(void); 79*5331Samw static void smbd_service_fini(void); 80*5331Samw 81*5331Samw static int smbd_setup_options(int argc, char *argv[]); 82*5331Samw static void smbd_usage(FILE *fp); 83*5331Samw static void smbd_report(const char *fmt, ...); 84*5331Samw 85*5331Samw static void smbd_sig_handler(int sig); 86*5331Samw 87*5331Samw static int smbd_localtime_init(void); 88*5331Samw static void *smbd_localtime_monitor(void *arg); 89*5331Samw 90*5331Samw extern time_t altzone; 91*5331Samw 92*5331Samw static pthread_t localtime_thr; 93*5331Samw 94*5331Samw static int smbd_refresh_init(void); 95*5331Samw static void smbd_refresh_fini(void); 96*5331Samw static void *smbd_refresh_monitor(void *); 97*5331Samw static pthread_t refresh_thr; 98*5331Samw static pthread_cond_t refresh_cond; 99*5331Samw static pthread_mutex_t refresh_mutex; 100*5331Samw 101*5331Samw static smbd_t smbd; 102*5331Samw 103*5331Samw /* 104*5331Samw * smbd user land daemon 105*5331Samw * 106*5331Samw * Use SMF error codes only on return or exit. 107*5331Samw */ 108*5331Samw int 109*5331Samw main(int argc, char *argv[]) 110*5331Samw { 111*5331Samw struct sigaction act; 112*5331Samw sigset_t set; 113*5331Samw uid_t uid; 114*5331Samw int pfd = -1; 115*5331Samw 116*5331Samw smbd.s_pname = basename(argv[0]); 117*5331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 118*5331Samw 119*5331Samw if (smbd_setup_options(argc, argv) != 0) 120*5331Samw return (SMF_EXIT_ERR_FATAL); 121*5331Samw 122*5331Samw if ((uid = getuid()) != smbd.s_uid) { 123*5331Samw smbd_report("user %d: %s", uid, strerror(EPERM)); 124*5331Samw return (SMF_EXIT_ERR_FATAL); 125*5331Samw } 126*5331Samw 127*5331Samw if (getzoneid() != GLOBAL_ZONEID) { 128*5331Samw smbd_report("non-global zones are not supported"); 129*5331Samw return (SMF_EXIT_ERR_FATAL); 130*5331Samw } 131*5331Samw 132*5331Samw if (is_system_labeled()) { 133*5331Samw smbd_report("Trusted Extensions not supported"); 134*5331Samw return (SMF_EXIT_ERR_FATAL); 135*5331Samw } 136*5331Samw 137*5331Samw if (smbd_already_running()) 138*5331Samw return (SMF_EXIT_OK); 139*5331Samw 140*5331Samw (void) sigfillset(&set); 141*5331Samw (void) sigdelset(&set, SIGABRT); 142*5331Samw 143*5331Samw (void) sigfillset(&act.sa_mask); 144*5331Samw act.sa_handler = smbd_sig_handler; 145*5331Samw act.sa_flags = 0; 146*5331Samw 147*5331Samw (void) sigaction(SIGTERM, &act, NULL); 148*5331Samw (void) sigaction(SIGHUP, &act, NULL); 149*5331Samw (void) sigaction(SIGINT, &act, NULL); 150*5331Samw (void) sigaction(SIGPIPE, &act, NULL); 151*5331Samw 152*5331Samw (void) sigdelset(&set, SIGTERM); 153*5331Samw (void) sigdelset(&set, SIGHUP); 154*5331Samw (void) sigdelset(&set, SIGINT); 155*5331Samw (void) sigdelset(&set, SIGPIPE); 156*5331Samw 157*5331Samw if (smbd.s_fg) { 158*5331Samw (void) sigdelset(&set, SIGTSTP); 159*5331Samw (void) sigdelset(&set, SIGTTIN); 160*5331Samw (void) sigdelset(&set, SIGTTOU); 161*5331Samw 162*5331Samw if (smbd_service_init() != 0) { 163*5331Samw smbd_report("service initialization failed"); 164*5331Samw exit(SMF_EXIT_ERR_FATAL); 165*5331Samw } 166*5331Samw } else { 167*5331Samw /* 168*5331Samw * "pfd" is a pipe descriptor -- any fatal errors 169*5331Samw * during subsequent initialization of the child 170*5331Samw * process should be written to this pipe and the 171*5331Samw * parent will report this error as the exit status. 172*5331Samw */ 173*5331Samw pfd = smbd_daemonize_init(); 174*5331Samw 175*5331Samw if (smbd_service_init() != 0) { 176*5331Samw smbd_report("daemon initialization failed"); 177*5331Samw exit(SMF_EXIT_ERR_FATAL); 178*5331Samw } 179*5331Samw 180*5331Samw smbd_daemonize_fini(pfd, SMF_EXIT_OK); 181*5331Samw } 182*5331Samw 183*5331Samw (void) atexit(smbd_service_fini); 184*5331Samw 185*5331Samw while (!smbd.s_shutdown_flag) { 186*5331Samw (void) sigsuspend(&set); 187*5331Samw 188*5331Samw switch (smbd.s_sigval) { 189*5331Samw case 0: 190*5331Samw break; 191*5331Samw 192*5331Samw case SIGPIPE: 193*5331Samw break; 194*5331Samw 195*5331Samw case SIGHUP: 196*5331Samw /* Refresh config was triggered */ 197*5331Samw if (smbd.s_fg) 198*5331Samw smbd_report("reconfiguration requested"); 199*5331Samw (void) pthread_cond_signal(&refresh_cond); 200*5331Samw break; 201*5331Samw 202*5331Samw default: 203*5331Samw /* 204*5331Samw * Typically SIGINT or SIGTERM. 205*5331Samw */ 206*5331Samw smbd.s_shutdown_flag = 1; 207*5331Samw break; 208*5331Samw } 209*5331Samw 210*5331Samw smbd.s_sigval = 0; 211*5331Samw } 212*5331Samw 213*5331Samw smbd_service_fini(); 214*5331Samw closelog(); 215*5331Samw return (SMF_EXIT_OK); 216*5331Samw } 217*5331Samw 218*5331Samw /* 219*5331Samw * This function will fork off a child process, 220*5331Samw * from which only the child will return. 221*5331Samw * 222*5331Samw * Use SMF error codes only on exit. 223*5331Samw */ 224*5331Samw static int 225*5331Samw smbd_daemonize_init(void) 226*5331Samw { 227*5331Samw int status, pfds[2]; 228*5331Samw sigset_t set, oset; 229*5331Samw pid_t pid; 230*5331Samw int rc; 231*5331Samw 232*5331Samw /* 233*5331Samw * Reset privileges to the minimum set required. We continue 234*5331Samw * to run as root to create and access files in /var. 235*5331Samw */ 236*5331Samw rc = __init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS, 237*5331Samw smbd.s_uid, smbd.s_gid, 238*5331Samw PRIV_NET_MAC_AWARE, PRIV_NET_PRIVADDR, PRIV_PROC_AUDIT, 239*5331Samw PRIV_SYS_DEVICES, PRIV_SYS_SMB, NULL); 240*5331Samw 241*5331Samw if (rc != 0) { 242*5331Samw smbd_report("insufficient privileges"); 243*5331Samw exit(SMF_EXIT_ERR_FATAL); 244*5331Samw } 245*5331Samw 246*5331Samw /* 247*5331Samw * Block all signals prior to the fork and leave them blocked in the 248*5331Samw * parent so we don't get in a situation where the parent gets SIGINT 249*5331Samw * and returns non-zero exit status and the child is actually running. 250*5331Samw * In the child, restore the signal mask once we've done our setsid(). 251*5331Samw */ 252*5331Samw (void) sigfillset(&set); 253*5331Samw (void) sigdelset(&set, SIGABRT); 254*5331Samw (void) sigprocmask(SIG_BLOCK, &set, &oset); 255*5331Samw 256*5331Samw if (pipe(pfds) == -1) { 257*5331Samw smbd_report("unable to create pipe"); 258*5331Samw exit(SMF_EXIT_ERR_FATAL); 259*5331Samw } 260*5331Samw 261*5331Samw closelog(); 262*5331Samw 263*5331Samw if ((pid = fork()) == -1) { 264*5331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 265*5331Samw smbd_report("unable to fork"); 266*5331Samw closelog(); 267*5331Samw exit(SMF_EXIT_ERR_FATAL); 268*5331Samw } 269*5331Samw 270*5331Samw /* 271*5331Samw * If we're the parent process, wait for either the child to send us 272*5331Samw * the appropriate exit status over the pipe or for the read to fail 273*5331Samw * (presumably with 0 for EOF if our child terminated abnormally). 274*5331Samw * If the read fails, exit with either the child's exit status if it 275*5331Samw * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal. 276*5331Samw */ 277*5331Samw if (pid != 0) { 278*5331Samw (void) close(pfds[1]); 279*5331Samw 280*5331Samw if (read(pfds[0], &status, sizeof (status)) == sizeof (status)) 281*5331Samw _exit(status); 282*5331Samw 283*5331Samw if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) 284*5331Samw _exit(WEXITSTATUS(status)); 285*5331Samw 286*5331Samw _exit(SMF_EXIT_ERR_FATAL); 287*5331Samw } 288*5331Samw 289*5331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 290*5331Samw smbd.s_pid = getpid(); 291*5331Samw (void) setsid(); 292*5331Samw (void) sigprocmask(SIG_SETMASK, &oset, NULL); 293*5331Samw (void) chdir("/"); 294*5331Samw (void) umask(022); 295*5331Samw (void) close(pfds[0]); 296*5331Samw 297*5331Samw return (pfds[1]); 298*5331Samw } 299*5331Samw 300*5331Samw static void 301*5331Samw smbd_daemonize_fini(int fd, int exit_status) 302*5331Samw { 303*5331Samw /* 304*5331Samw * Now that we're running, if a pipe fd was specified, write an exit 305*5331Samw * status to it to indicate that our parent process can safely detach. 306*5331Samw * Then proceed to loading the remaining non-built-in modules. 307*5331Samw */ 308*5331Samw if (fd >= 0) 309*5331Samw (void) write(fd, &exit_status, sizeof (exit_status)); 310*5331Samw 311*5331Samw (void) close(fd); 312*5331Samw 313*5331Samw if ((fd = open("/dev/null", O_RDWR)) >= 0) { 314*5331Samw (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); 315*5331Samw (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); 316*5331Samw (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); 317*5331Samw (void) close(fd); 318*5331Samw } 319*5331Samw 320*5331Samw __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 321*5331Samw PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, NULL); 322*5331Samw } 323*5331Samw 324*5331Samw static int 325*5331Samw smbd_service_init(void) 326*5331Samw { 327*5331Samw static char *dir[] = { 328*5331Samw SMB_DBDIR, /* smbpasswd */ 329*5331Samw SMB_CACHEDIR /* KRB credential cache */ 330*5331Samw }; 331*5331Samw 332*5331Samw int rc; 333*5331Samw int ddns_enabled; 334*5331Samw uint32_t mode; 335*5331Samw char resource_domain[SMB_PI_MAX_DOMAIN]; 336*5331Samw int i; 337*5331Samw 338*5331Samw smbd.s_drv_fd = -1; 339*5331Samw 340*5331Samw for (i = 0; i < (sizeof (dir)/sizeof (dir[0])); ++i) { 341*5331Samw errno = 0; 342*5331Samw 343*5331Samw if ((mkdir(dir[i], 0700) < 0) && (errno != EEXIST)) { 344*5331Samw smbd_report("mkdir %s: %s", dir[i], strerror(errno)); 345*5331Samw return (1); 346*5331Samw } 347*5331Samw } 348*5331Samw 349*5331Samw /* 350*5331Samw * Set KRB5CCNAME (for the SMB credential cache) in the environment. 351*5331Samw */ 352*5331Samw if (putenv("KRB5CCNAME=" SMB_CACHEDIR "/ccache") != 0) { 353*5331Samw smbd_report("unable to set KRB5CCNAME"); 354*5331Samw return (1); 355*5331Samw } 356*5331Samw 357*5331Samw (void) oem_language_set("english"); 358*5331Samw 359*5331Samw if (!nt_builtin_init()) { 360*5331Samw smbd_report("out of memory"); 361*5331Samw return (1); 362*5331Samw } 363*5331Samw 364*5331Samw /* 365*5331Samw * Need to load the configuration data prior to getting the 366*5331Samw * interface information. 367*5331Samw */ 368*5331Samw if (smb_config_load() != 0) { 369*5331Samw smbd_report("failed to load configuration data"); 370*5331Samw return (1); 371*5331Samw } 372*5331Samw 373*5331Samw smb_resolver_init(); 374*5331Samw (void) smb_nicmon_start(); 375*5331Samw 376*5331Samw smbrdr_init(); 377*5331Samw 378*5331Samw smb_netbios_start(); 379*5331Samw if (smb_netlogon_init() != 0) { 380*5331Samw smbd_report("netlogon initialization failed"); 381*5331Samw return (1); 382*5331Samw } 383*5331Samw 384*5331Samw smb_config_rdlock(); 385*5331Samw resource_domain[0] = '\0'; 386*5331Samw (void) strlcpy(resource_domain, 387*5331Samw smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); 388*5331Samw (void) utf8_strupr(resource_domain); 389*5331Samw smb_config_unlock(); 390*5331Samw 391*5331Samw mode = smb_get_security_mode(); 392*5331Samw 393*5331Samw if (mode == SMB_SECMODE_DOMAIN) 394*5331Samw (void) locate_resource_pdc(resource_domain); 395*5331Samw 396*5331Samw /* Get the ID map client handle */ 397*5331Samw if ((rc = smb_idmap_start()) != 0) { 398*5331Samw smbd_report("no idmap handle"); 399*5331Samw return (rc); 400*5331Samw } 401*5331Samw 402*5331Samw if ((rc = nt_domain_init(resource_domain, mode)) != 0) { 403*5331Samw if (rc == SMB_DOMAIN_NOMACHINE_SID) 404*5331Samw smbd_report("No Security Identifier (SID) has been " 405*5331Samw "generated for this system.\n" 406*5331Samw "Check idmap service configuration."); 407*5331Samw 408*5331Samw if (rc == SMB_DOMAIN_NODOMAIN_SID) { 409*5331Samw /* Get the domain sid from domain controller */ 410*5331Samw if ((rc = lsa_query_primary_domain_info()) != 0) 411*5331Samw smbd_report("Failed to get the Security " 412*5331Samw "Identifier (SID) of domain %s", 413*5331Samw resource_domain); 414*5331Samw } 415*5331Samw return (rc); 416*5331Samw } 417*5331Samw 418*5331Samw if ((rc = mlsvc_init()) != 0) { 419*5331Samw smbd_report("msrpc initialization failed"); 420*5331Samw return (rc); 421*5331Samw } 422*5331Samw 423*5331Samw if (rc = smb_mlsvc_srv_start()) { 424*5331Samw smbd_report("msrpc door initialization failed: %d", rc); 425*5331Samw return (rc); 426*5331Samw } 427*5331Samw 428*5331Samw if (smb_lmshrd_srv_start() != 0) { 429*5331Samw smbd_report("share initialization failed"); 430*5331Samw } 431*5331Samw 432*5331Samw /* XXX following will get removed */ 433*5331Samw (void) smb_doorsrv_start(); 434*5331Samw if ((rc = smb_door_srv_start()) != 0) 435*5331Samw return (rc); 436*5331Samw 437*5331Samw if ((rc = smbd_refresh_init()) != 0) 438*5331Samw return (rc); 439*5331Samw 440*5331Samw /* Call dyndns update - Just in case its configured to refresh DNS */ 441*5331Samw smb_config_rdlock(); 442*5331Samw ddns_enabled = smb_config_getyorn(SMB_CI_DYNDNS_ENABLE); 443*5331Samw smb_config_unlock(); 444*5331Samw if (ddns_enabled) { 445*5331Samw (void) dyndns_update(); 446*5331Samw } 447*5331Samw 448*5331Samw if ((rc = smbd_kernel_bind()) != 0) 449*5331Samw smbd_report("kernel bind error: %s", strerror(errno)); 450*5331Samw 451*5331Samw (void) smbd_localtime_init(); 452*5331Samw 453*5331Samw return (lmshare_start()); 454*5331Samw } 455*5331Samw 456*5331Samw /* 457*5331Samw * Close the kernel service and shutdown smbd services. 458*5331Samw * This function is registered with atexit(): ensure that anything 459*5331Samw * called from here is safe to be called multiple times. 460*5331Samw */ 461*5331Samw static void 462*5331Samw smbd_service_fini(void) 463*5331Samw { 464*5331Samw nt_builtin_fini(); 465*5331Samw smbd_refresh_fini(); 466*5331Samw smbd_kernel_unbind(); 467*5331Samw smb_door_srv_stop(); 468*5331Samw smb_doorsrv_stop(); 469*5331Samw smb_lmshrd_srv_stop(); 470*5331Samw lmshare_stop(); 471*5331Samw smb_mlsvc_srv_stop(); 472*5331Samw smb_nicmon_stop(); 473*5331Samw smb_resolver_close(); 474*5331Samw smb_idmap_stop(); 475*5331Samw } 476*5331Samw 477*5331Samw /* 478*5331Samw * smbd_refresh_init() 479*5331Samw * 480*5331Samw * SMB service refresh thread initialization. This thread waits for a 481*5331Samw * refresh event and updates the daemon's view of the configuration 482*5331Samw * before going back to sleep. 483*5331Samw */ 484*5331Samw static int 485*5331Samw smbd_refresh_init() 486*5331Samw { 487*5331Samw pthread_attr_t tattr; 488*5331Samw pthread_condattr_t cattr; 489*5331Samw int rc; 490*5331Samw 491*5331Samw (void) pthread_condattr_init(&cattr); 492*5331Samw (void) pthread_cond_init(&refresh_cond, &cattr); 493*5331Samw (void) pthread_condattr_destroy(&cattr); 494*5331Samw 495*5331Samw (void) pthread_mutex_init(&refresh_mutex, NULL); 496*5331Samw 497*5331Samw (void) pthread_attr_init(&tattr); 498*5331Samw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 499*5331Samw rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0); 500*5331Samw (void) pthread_attr_destroy(&tattr); 501*5331Samw return (rc); 502*5331Samw 503*5331Samw } 504*5331Samw 505*5331Samw /* 506*5331Samw * smbd_refresh_fini() 507*5331Samw * 508*5331Samw * Stop the refresh thread. 509*5331Samw */ 510*5331Samw static void 511*5331Samw smbd_refresh_fini() 512*5331Samw { 513*5331Samw (void) pthread_cancel(refresh_thr); 514*5331Samw 515*5331Samw (void) pthread_cond_destroy(&refresh_cond); 516*5331Samw (void) pthread_mutex_destroy(&refresh_mutex); 517*5331Samw } 518*5331Samw 519*5331Samw /* 520*5331Samw * smbd_refresh_monitor() 521*5331Samw * 522*5331Samw * Wait for a refresh event. When this thread wakes up, update the 523*5331Samw * smbd configuration from the SMF config information then go back to 524*5331Samw * wait for the next refresh. 525*5331Samw */ 526*5331Samw /*ARGSUSED*/ 527*5331Samw static void * 528*5331Samw smbd_refresh_monitor(void *arg) 529*5331Samw { 530*5331Samw int dummy = 0; 531*5331Samw 532*5331Samw (void) pthread_mutex_lock(&refresh_mutex); 533*5331Samw while (pthread_cond_wait(&refresh_cond, &refresh_mutex) == 0) { 534*5331Samw /* 535*5331Samw * We've been woken up by a refresh event so go do 536*5331Samw * what is necessary. 537*5331Samw */ 538*5331Samw (void) smb_config_load(); 539*5331Samw smb_nic_build_info(); 540*5331Samw (void) smb_netbios_name_reconfig(); 541*5331Samw (void) smb_browser_config(); 542*5331Samw if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG_REFRESH, &dummy) < 0) { 543*5331Samw smbd_report("configuration update ioctl: %s", 544*5331Samw strerror(errno)); 545*5331Samw } 546*5331Samw } 547*5331Samw return (NULL); 548*5331Samw } 549*5331Samw 550*5331Samw 551*5331Samw /* 552*5331Samw * If the door has already been opened by another process (non-zero pid 553*5331Samw * in target), we assume that another smbd is already running. If there 554*5331Samw * is a race here, it will be caught later when smbsrv is opened because 555*5331Samw * only one process is allowed to open the device at a time. 556*5331Samw */ 557*5331Samw static int 558*5331Samw smbd_already_running(void) 559*5331Samw { 560*5331Samw door_info_t info; 561*5331Samw int door; 562*5331Samw 563*5331Samw if ((door = open(SMBD_DOOR_NAME, O_RDONLY)) < 0) 564*5331Samw return (0); 565*5331Samw 566*5331Samw if (door_info(door, &info) < 0) 567*5331Samw return (0); 568*5331Samw 569*5331Samw if (info.di_target > 0) { 570*5331Samw smbd_report("already running: pid %ld\n", info.di_target); 571*5331Samw (void) close(door); 572*5331Samw return (1); 573*5331Samw } 574*5331Samw 575*5331Samw (void) close(door); 576*5331Samw return (0); 577*5331Samw } 578*5331Samw 579*5331Samw static int 580*5331Samw smbd_kernel_bind(void) 581*5331Samw { 582*5331Samw if (smbd.s_drv_fd != -1) 583*5331Samw (void) close(smbd.s_drv_fd); 584*5331Samw 585*5331Samw if ((smbd.s_drv_fd = open(DRV_DEVICE_PATH, 0)) < 0) { 586*5331Samw smbd.s_drv_fd = -1; 587*5331Samw return (1); 588*5331Samw } 589*5331Samw return (0); 590*5331Samw } 591*5331Samw 592*5331Samw 593*5331Samw /* 594*5331Samw * Initialization of the localtime thread. 595*5331Samw * Returns 0 on success, an error number if thread creation fails. 596*5331Samw */ 597*5331Samw 598*5331Samw int 599*5331Samw smbd_localtime_init(void) 600*5331Samw { 601*5331Samw pthread_attr_t tattr; 602*5331Samw int rc; 603*5331Samw 604*5331Samw (void) pthread_attr_init(&tattr); 605*5331Samw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 606*5331Samw rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0); 607*5331Samw (void) pthread_attr_destroy(&tattr); 608*5331Samw return (rc); 609*5331Samw } 610*5331Samw 611*5331Samw /* 612*5331Samw * Local time thread to kernel land. 613*5331Samw * Send local gmtoff to kernel module one time at startup 614*5331Samw * and each time it changes (up to twice a year). 615*5331Samw * Local gmtoff is checked once every 15 minutes and 616*5331Samw * since some timezones are aligned on half and qtr hour boundaries, 617*5331Samw * once an hour would likely suffice. 618*5331Samw */ 619*5331Samw 620*5331Samw /*ARGSUSED*/ 621*5331Samw static void * 622*5331Samw smbd_localtime_monitor(void *arg) 623*5331Samw { 624*5331Samw struct tm local_tm; 625*5331Samw time_t secs, gmtoff; 626*5331Samw time_t last_gmtoff = -1; 627*5331Samw int timeout; 628*5331Samw 629*5331Samw for (;;) { 630*5331Samw gmtoff = -altzone; 631*5331Samw 632*5331Samw if ((last_gmtoff != gmtoff) && (smbd.s_drv_fd != -1)) { 633*5331Samw if (ioctl(smbd.s_drv_fd, SMB_IOC_GMTOFF, &gmtoff) < 0) { 634*5331Samw smbd_report("localtime ioctl: %s", 635*5331Samw strerror(errno)); 636*5331Samw } 637*5331Samw } 638*5331Samw 639*5331Samw /* 640*5331Samw * Align the next iteration on a fifteen minute boundary. 641*5331Samw */ 642*5331Samw secs = time(0); 643*5331Samw (void) localtime_r(&secs, &local_tm); 644*5331Samw timeout = ((15 - (local_tm.tm_min % 15)) * SECSPERMIN); 645*5331Samw (void) sleep(timeout); 646*5331Samw 647*5331Samw last_gmtoff = gmtoff; 648*5331Samw } 649*5331Samw 650*5331Samw /*NOTREACHED*/ 651*5331Samw return (NULL); 652*5331Samw } 653*5331Samw 654*5331Samw 655*5331Samw static void 656*5331Samw smbd_kernel_unbind(void) 657*5331Samw { 658*5331Samw if (smbd.s_drv_fd != -1) { 659*5331Samw (void) close(smbd.s_drv_fd); 660*5331Samw smbd.s_drv_fd = -1; 661*5331Samw } 662*5331Samw } 663*5331Samw 664*5331Samw static void 665*5331Samw smbd_sig_handler(int sigval) 666*5331Samw { 667*5331Samw if (smbd.s_sigval == 0) 668*5331Samw smbd.s_sigval = sigval; 669*5331Samw } 670*5331Samw 671*5331Samw /* 672*5331Samw * Set up configuration options and parse the command line. 673*5331Samw * This function will determine if we will run as a daemon 674*5331Samw * or in the foreground. 675*5331Samw * 676*5331Samw * Failure to find a uid or gid results in using the default (0). 677*5331Samw */ 678*5331Samw static int 679*5331Samw smbd_setup_options(int argc, char *argv[]) 680*5331Samw { 681*5331Samw struct passwd *pwd; 682*5331Samw struct group *grp; 683*5331Samw int c; 684*5331Samw 685*5331Samw if ((pwd = getpwnam("root")) != NULL) 686*5331Samw smbd.s_uid = pwd->pw_uid; 687*5331Samw 688*5331Samw if ((grp = getgrnam("sys")) != NULL) 689*5331Samw smbd.s_gid = grp->gr_gid; 690*5331Samw 691*5331Samw smbd.s_fg = smb_get_fg_flag(); 692*5331Samw 693*5331Samw while ((c = getopt(argc, argv, ":f")) != -1) { 694*5331Samw switch (c) { 695*5331Samw case 'f': 696*5331Samw smbd.s_fg = 1; 697*5331Samw break; 698*5331Samw 699*5331Samw case ':': 700*5331Samw case '?': 701*5331Samw default: 702*5331Samw smbd_usage(stderr); 703*5331Samw return (-1); 704*5331Samw } 705*5331Samw } 706*5331Samw 707*5331Samw return (0); 708*5331Samw } 709*5331Samw 710*5331Samw static void 711*5331Samw smbd_usage(FILE *fp) 712*5331Samw { 713*5331Samw static char *help[] = { 714*5331Samw "-f run program in foreground" 715*5331Samw }; 716*5331Samw 717*5331Samw int i; 718*5331Samw 719*5331Samw (void) fprintf(fp, "Usage: %s [-f]\n", smbd.s_pname); 720*5331Samw 721*5331Samw for (i = 0; i < sizeof (help)/sizeof (help[0]); ++i) 722*5331Samw (void) fprintf(fp, " %s\n", help[i]); 723*5331Samw } 724*5331Samw 725*5331Samw static void 726*5331Samw smbd_report(const char *fmt, ...) 727*5331Samw { 728*5331Samw char buf[128]; 729*5331Samw va_list ap; 730*5331Samw 731*5331Samw if (fmt == NULL) 732*5331Samw return; 733*5331Samw 734*5331Samw va_start(ap, fmt); 735*5331Samw (void) vsnprintf(buf, 128, fmt, ap); 736*5331Samw va_end(ap); 737*5331Samw 738*5331Samw (void) fprintf(stderr, "smbd: %s\n", buf); 739*5331Samw } 740*5331Samw 741*5331Samw /* 742*5331Samw * Enable libumem debugging by default on DEBUG builds. 743*5331Samw */ 744*5331Samw #ifdef DEBUG 745*5331Samw /* LINTED - external libumem symbol */ 746*5331Samw const char * 747*5331Samw _umem_debug_init(void) 748*5331Samw { 749*5331Samw return ("default,verbose"); /* $UMEM_DEBUG setting */ 750*5331Samw } 751*5331Samw 752*5331Samw /* LINTED - external libumem symbol */ 753*5331Samw const char * 754*5331Samw _umem_logging_init(void) 755*5331Samw { 756*5331Samw return ("fail,contents"); /* $UMEM_LOGGING setting */ 757*5331Samw } 758*5331Samw #endif 759