15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 225772Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #pragma ident "%Z%%M% %I% %E% SMI" 275331Samw 285331Samw #include <sys/types.h> 295331Samw #include <sys/stat.h> 305331Samw #include <sys/ioccom.h> 315331Samw #include <stdio.h> 325331Samw #include <string.h> 335331Samw #include <strings.h> 345331Samw #include <stdlib.h> 355331Samw #include <unistd.h> 365331Samw #include <stdarg.h> 375331Samw #include <fcntl.h> 385331Samw #include <wait.h> 395331Samw #include <signal.h> 405331Samw #include <libscf.h> 415331Samw #include <limits.h> 425331Samw #include <priv_utils.h> 435331Samw #include <door.h> 445331Samw #include <errno.h> 455331Samw #include <syslog.h> 465331Samw #include <pthread.h> 475331Samw #include <time.h> 485331Samw #include <libscf.h> 495331Samw #include <zone.h> 505331Samw #include <tzfile.h> 515331Samw #include <libgen.h> 525331Samw #include <pwd.h> 535331Samw #include <grp.h> 545331Samw 555331Samw #include <smbsrv/smb_door_svc.h> 565331Samw #include <smbsrv/smb_ioctl.h> 575331Samw #include <smbsrv/libsmb.h> 585331Samw #include <smbsrv/libsmbns.h> 595331Samw #include <smbsrv/libsmbrdr.h> 605331Samw #include <smbsrv/libmlsvc.h> 615331Samw 625331Samw #include "smbd.h" 635331Samw 645331Samw #define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv" 655331Samw #define SMB_DBDIR "/var/smb" 665331Samw 67*6139Sjb150015 extern void *smbd_nbt_listener(void *); 68*6139Sjb150015 extern void *smbd_tcp_listener(void *); 69*6139Sjb150015 705331Samw static int smbd_daemonize_init(void); 715331Samw static void smbd_daemonize_fini(int, int); 725331Samw 73*6139Sjb150015 static int smbd_kernel_bind(int, int, int); 745331Samw static void smbd_kernel_unbind(void); 755331Samw static int smbd_already_running(void); 765331Samw 775331Samw static int smbd_service_init(void); 785331Samw static void smbd_service_fini(void); 795331Samw 805331Samw static int smbd_setup_options(int argc, char *argv[]); 815331Samw static void smbd_usage(FILE *fp); 825331Samw static void smbd_report(const char *fmt, ...); 835331Samw 845331Samw static void smbd_sig_handler(int sig); 855331Samw 865331Samw static int smbd_localtime_init(void); 875331Samw static void *smbd_localtime_monitor(void *arg); 885331Samw 895331Samw 905331Samw static pthread_t localtime_thr; 915331Samw 925331Samw static int smbd_refresh_init(void); 935331Samw static void smbd_refresh_fini(void); 945331Samw static void *smbd_refresh_monitor(void *); 95*6139Sjb150015 static pthread_t nbt_listener; 96*6139Sjb150015 static pthread_t tcp_listener; 975331Samw static pthread_t refresh_thr; 985331Samw static pthread_cond_t refresh_cond; 995331Samw static pthread_mutex_t refresh_mutex; 1005331Samw 101*6139Sjb150015 smbd_t smbd; 1025331Samw 1035331Samw /* 1045331Samw * smbd user land daemon 1055331Samw * 1065331Samw * Use SMF error codes only on return or exit. 1075331Samw */ 1085331Samw int 1095331Samw main(int argc, char *argv[]) 1105331Samw { 1115331Samw struct sigaction act; 1125331Samw sigset_t set; 1135331Samw uid_t uid; 1145331Samw int pfd = -1; 1155331Samw 1165331Samw smbd.s_pname = basename(argv[0]); 1175331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 1185331Samw 1195331Samw if (smbd_setup_options(argc, argv) != 0) 1205331Samw return (SMF_EXIT_ERR_FATAL); 1215331Samw 1225331Samw if ((uid = getuid()) != smbd.s_uid) { 1235331Samw smbd_report("user %d: %s", uid, strerror(EPERM)); 1245331Samw return (SMF_EXIT_ERR_FATAL); 1255331Samw } 1265331Samw 1275331Samw if (getzoneid() != GLOBAL_ZONEID) { 1285331Samw smbd_report("non-global zones are not supported"); 1295331Samw return (SMF_EXIT_ERR_FATAL); 1305331Samw } 1315331Samw 1325331Samw if (is_system_labeled()) { 1335331Samw smbd_report("Trusted Extensions not supported"); 1345331Samw return (SMF_EXIT_ERR_FATAL); 1355331Samw } 1365331Samw 1375331Samw if (smbd_already_running()) 1385331Samw return (SMF_EXIT_OK); 1395331Samw 1405331Samw (void) sigfillset(&set); 1415331Samw (void) sigdelset(&set, SIGABRT); 1425331Samw 1435331Samw (void) sigfillset(&act.sa_mask); 1445331Samw act.sa_handler = smbd_sig_handler; 1455331Samw act.sa_flags = 0; 1465331Samw 1475331Samw (void) sigaction(SIGTERM, &act, NULL); 1485331Samw (void) sigaction(SIGHUP, &act, NULL); 1495331Samw (void) sigaction(SIGINT, &act, NULL); 1505331Samw (void) sigaction(SIGPIPE, &act, NULL); 1515331Samw 1525331Samw (void) sigdelset(&set, SIGTERM); 1535331Samw (void) sigdelset(&set, SIGHUP); 1545331Samw (void) sigdelset(&set, SIGINT); 1555331Samw (void) sigdelset(&set, SIGPIPE); 1565331Samw 1575331Samw if (smbd.s_fg) { 1585331Samw (void) sigdelset(&set, SIGTSTP); 1595331Samw (void) sigdelset(&set, SIGTTIN); 1605331Samw (void) sigdelset(&set, SIGTTOU); 1615331Samw 1625331Samw if (smbd_service_init() != 0) { 1635331Samw smbd_report("service initialization failed"); 1645331Samw exit(SMF_EXIT_ERR_FATAL); 1655331Samw } 1665331Samw } else { 1675331Samw /* 1685331Samw * "pfd" is a pipe descriptor -- any fatal errors 1695331Samw * during subsequent initialization of the child 1705331Samw * process should be written to this pipe and the 1715331Samw * parent will report this error as the exit status. 1725331Samw */ 1735331Samw pfd = smbd_daemonize_init(); 1745331Samw 1755331Samw if (smbd_service_init() != 0) { 1765331Samw smbd_report("daemon initialization failed"); 1775331Samw exit(SMF_EXIT_ERR_FATAL); 1785331Samw } 1795331Samw 1805331Samw smbd_daemonize_fini(pfd, SMF_EXIT_OK); 1815331Samw } 1825331Samw 1835331Samw (void) atexit(smbd_service_fini); 1845331Samw 1855331Samw while (!smbd.s_shutdown_flag) { 1865331Samw (void) sigsuspend(&set); 1875331Samw 1885331Samw switch (smbd.s_sigval) { 1895331Samw case 0: 1905331Samw break; 1915331Samw 1925331Samw case SIGPIPE: 1935331Samw break; 1945331Samw 1955331Samw case SIGHUP: 1965331Samw /* Refresh config was triggered */ 1975331Samw if (smbd.s_fg) 1985331Samw smbd_report("reconfiguration requested"); 1995331Samw (void) pthread_cond_signal(&refresh_cond); 2005331Samw break; 2015331Samw 2025331Samw default: 2035331Samw /* 2045331Samw * Typically SIGINT or SIGTERM. 2055331Samw */ 2065331Samw smbd.s_shutdown_flag = 1; 2075331Samw break; 2085331Samw } 2095331Samw 2105331Samw smbd.s_sigval = 0; 2115331Samw } 2125331Samw 2135331Samw smbd_service_fini(); 2145331Samw closelog(); 2155331Samw return (SMF_EXIT_OK); 2165331Samw } 2175331Samw 2185331Samw /* 2195331Samw * This function will fork off a child process, 2205331Samw * from which only the child will return. 2215331Samw * 2225331Samw * Use SMF error codes only on exit. 2235331Samw */ 2245331Samw static int 2255331Samw smbd_daemonize_init(void) 2265331Samw { 2275331Samw int status, pfds[2]; 2285331Samw sigset_t set, oset; 2295331Samw pid_t pid; 2305331Samw int rc; 2315331Samw 2325331Samw /* 2335331Samw * Reset privileges to the minimum set required. We continue 2345331Samw * to run as root to create and access files in /var. 2355331Samw */ 2365331Samw rc = __init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS, 2375331Samw smbd.s_uid, smbd.s_gid, 2385331Samw PRIV_NET_MAC_AWARE, PRIV_NET_PRIVADDR, PRIV_PROC_AUDIT, 2395331Samw PRIV_SYS_DEVICES, PRIV_SYS_SMB, NULL); 2405331Samw 2415331Samw if (rc != 0) { 2425331Samw smbd_report("insufficient privileges"); 2435331Samw exit(SMF_EXIT_ERR_FATAL); 2445331Samw } 2455331Samw 2465331Samw /* 2475331Samw * Block all signals prior to the fork and leave them blocked in the 2485331Samw * parent so we don't get in a situation where the parent gets SIGINT 2495331Samw * and returns non-zero exit status and the child is actually running. 2505331Samw * In the child, restore the signal mask once we've done our setsid(). 2515331Samw */ 2525331Samw (void) sigfillset(&set); 2535331Samw (void) sigdelset(&set, SIGABRT); 2545331Samw (void) sigprocmask(SIG_BLOCK, &set, &oset); 2555331Samw 2565331Samw if (pipe(pfds) == -1) { 2575331Samw smbd_report("unable to create pipe"); 2585331Samw exit(SMF_EXIT_ERR_FATAL); 2595331Samw } 2605331Samw 2615331Samw closelog(); 2625331Samw 2635331Samw if ((pid = fork()) == -1) { 2645331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 2655331Samw smbd_report("unable to fork"); 2665331Samw closelog(); 2675331Samw exit(SMF_EXIT_ERR_FATAL); 2685331Samw } 2695331Samw 2705331Samw /* 2715331Samw * If we're the parent process, wait for either the child to send us 2725331Samw * the appropriate exit status over the pipe or for the read to fail 2735331Samw * (presumably with 0 for EOF if our child terminated abnormally). 2745331Samw * If the read fails, exit with either the child's exit status if it 2755331Samw * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal. 2765331Samw */ 2775331Samw if (pid != 0) { 2785331Samw (void) close(pfds[1]); 2795331Samw 2805331Samw if (read(pfds[0], &status, sizeof (status)) == sizeof (status)) 2815331Samw _exit(status); 2825331Samw 2835331Samw if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) 2845331Samw _exit(WEXITSTATUS(status)); 2855331Samw 2865331Samw _exit(SMF_EXIT_ERR_FATAL); 2875331Samw } 2885331Samw 2895331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 2905331Samw smbd.s_pid = getpid(); 2915331Samw (void) setsid(); 2925331Samw (void) sigprocmask(SIG_SETMASK, &oset, NULL); 2935331Samw (void) chdir("/"); 2945331Samw (void) umask(022); 2955331Samw (void) close(pfds[0]); 2965331Samw 2975331Samw return (pfds[1]); 2985331Samw } 2995331Samw 3005331Samw static void 3015331Samw smbd_daemonize_fini(int fd, int exit_status) 3025331Samw { 3035331Samw /* 3045331Samw * Now that we're running, if a pipe fd was specified, write an exit 3055331Samw * status to it to indicate that our parent process can safely detach. 3065331Samw * Then proceed to loading the remaining non-built-in modules. 3075331Samw */ 3085331Samw if (fd >= 0) 3095331Samw (void) write(fd, &exit_status, sizeof (exit_status)); 3105331Samw 3115331Samw (void) close(fd); 3125331Samw 3135331Samw if ((fd = open("/dev/null", O_RDWR)) >= 0) { 3145331Samw (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); 3155331Samw (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); 3165331Samw (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); 3175331Samw (void) close(fd); 3185331Samw } 3195331Samw 3205331Samw __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 3215331Samw PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, NULL); 3225331Samw } 3235331Samw 324*6139Sjb150015 /* 325*6139Sjb150015 * smbd_service_init 326*6139Sjb150015 */ 3275331Samw static int 3285331Samw smbd_service_init(void) 3295331Samw { 330*6139Sjb150015 int id_winpipe_door; 331*6139Sjb150015 int id_lmshr_door; 332*6139Sjb150015 int id_srv_door; 333*6139Sjb150015 int rc; 334*6139Sjb150015 uint32_t mode; 335*6139Sjb150015 char resource_domain[SMB_PI_MAX_DOMAIN]; 336*6139Sjb150015 char fqdn[MAXHOSTNAMELEN]; 3375331Samw smbd.s_drv_fd = -1; 3385331Samw 3395331Samw 340*6139Sjb150015 if ((mkdir(SMB_DBDIR, 0700) < 0) && (errno != EEXIST)) { 341*6139Sjb150015 smbd_report("mkdir %s: %s", SMB_DBDIR, strerror(errno)); 342*6139Sjb150015 return (1); 3435331Samw } 3445331Samw 345*6139Sjb150015 if ((rc = smb_ccache_init(SMB_VARRUN_DIR, SMB_CCACHE_FILE)) != 0) { 346*6139Sjb150015 if (rc == -1) 347*6139Sjb150015 smbd_report("mkdir %s: %s", SMB_VARRUN_DIR, 348*6139Sjb150015 strerror(errno)); 349*6139Sjb150015 else 350*6139Sjb150015 smbd_report("unable to set KRB5CCNAME"); 3515331Samw return (1); 3525331Samw } 3535331Samw 354*6139Sjb150015 3555331Samw (void) oem_language_set("english"); 3565331Samw 3575331Samw if (!nt_builtin_init()) { 3585331Samw smbd_report("out of memory"); 3595331Samw return (1); 3605331Samw } 3615331Samw 3625772Sas200622 (void) smb_nicmon_start(); 3635772Sas200622 if (dns_msgid_init() != 0) { 3645772Sas200622 smbd_report("DNS message id initialization failed"); 3655331Samw return (1); 3665331Samw } 3675331Samw 3685331Samw smbrdr_init(); 3695331Samw 3705772Sas200622 if (smb_netbios_start() != 0) 3715772Sas200622 smbd_report("NetBIOS services failed to start"); 3725772Sas200622 else 3735772Sas200622 smbd_report("NetBIOS services started"); 3745772Sas200622 3755331Samw if (smb_netlogon_init() != 0) { 3765331Samw smbd_report("netlogon initialization failed"); 3775331Samw return (1); 3785331Samw } 3795331Samw 3805772Sas200622 (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); 3815331Samw (void) utf8_strupr(resource_domain); 3825331Samw 3835331Samw /* Get the ID map client handle */ 3845331Samw if ((rc = smb_idmap_start()) != 0) { 3855331Samw smbd_report("no idmap handle"); 3865331Samw return (rc); 3875331Samw } 3885331Samw 389*6139Sjb150015 mode = smb_config_get_secmode(); 3905331Samw if ((rc = nt_domain_init(resource_domain, mode)) != 0) { 3915772Sas200622 if (rc == SMB_DOMAIN_NOMACHINE_SID) { 3925772Sas200622 smbd_report( 3935772Sas200622 "no machine SID: check idmap configuration"); 3945772Sas200622 return (rc); 3955772Sas200622 } 3965331Samw } 3975331Samw 3985772Sas200622 ads_init(); 3995331Samw if ((rc = mlsvc_init()) != 0) { 4005331Samw smbd_report("msrpc initialization failed"); 4015331Samw return (rc); 4025331Samw } 4035331Samw 404*6139Sjb150015 if (mode == SMB_SECMODE_DOMAIN) { 405*6139Sjb150015 if (!smb_match_netlogon_seqnum()) 406*6139Sjb150015 smb_set_netlogon_cred(); 407*6139Sjb150015 else 408*6139Sjb150015 (void) smbd_locate_dc(resource_domain, ""); 409*6139Sjb150015 410*6139Sjb150015 (void) lsa_query_primary_domain_info(); 411*6139Sjb150015 } 412*6139Sjb150015 413*6139Sjb150015 id_lmshr_door = smb_lmshrd_srv_start(); 414*6139Sjb150015 if (id_lmshr_door < 0) { 4155331Samw smbd_report("share initialization failed"); 4165331Samw } 4175331Samw 418*6139Sjb150015 id_srv_door = smb_door_srv_start(); 419*6139Sjb150015 if (id_srv_door < 0) 4205331Samw return (rc); 4215331Samw 4225331Samw if ((rc = smbd_refresh_init()) != 0) 4235331Samw return (rc); 4245331Samw 425*6139Sjb150015 if (smb_getfqdomainname(fqdn, MAXHOSTNAMELEN) == 0) 426*6139Sjb150015 (void) dyndns_update(fqdn, B_FALSE); 4275331Samw 4285331Samw (void) smbd_localtime_init(); 4295331Samw 430*6139Sjb150015 id_winpipe_door = smb_winpipe_doorsvc_start(); 431*6139Sjb150015 if (id_winpipe_door < 0) { 4325521Sas200622 smbd_report("winpipe initialization failed %s", 4335521Sas200622 strerror(errno)); 4345521Sas200622 return (rc); 4355521Sas200622 } 4365521Sas200622 4375772Sas200622 (void) smb_lgrp_start(); 4386030Sjb150015 4396030Sjb150015 (void) smb_pwd_init(); 4406030Sjb150015 441*6139Sjb150015 rc = smbd_kernel_bind(id_lmshr_door, id_srv_door, id_winpipe_door); 442*6139Sjb150015 if (rc != 0) 443*6139Sjb150015 smbd_report("kernel bind error: %s", strerror(errno)); 4445331Samw 445*6139Sjb150015 return (lmshare_start()); 4465521Sas200622 } 4475521Sas200622 4485331Samw /* 4495331Samw * Close the kernel service and shutdown smbd services. 4505331Samw * This function is registered with atexit(): ensure that anything 4515331Samw * called from here is safe to be called multiple times. 4525331Samw */ 4535331Samw static void 4545331Samw smbd_service_fini(void) 4555331Samw { 4565521Sas200622 smb_winpipe_doorsvc_stop(); 4575331Samw nt_builtin_fini(); 4585331Samw smbd_refresh_fini(); 4595331Samw smbd_kernel_unbind(); 4605331Samw smb_door_srv_stop(); 4615331Samw smb_lmshrd_srv_stop(); 4625331Samw lmshare_stop(); 4635331Samw smb_nicmon_stop(); 4645331Samw smb_idmap_stop(); 4655772Sas200622 smb_lgrp_stop(); 466*6139Sjb150015 smb_ccache_remove(SMB_CCACHE_PATH); 4676030Sjb150015 smb_pwd_fini(); 4685521Sas200622 4695331Samw } 4705331Samw 471*6139Sjb150015 4725331Samw /* 4735331Samw * smbd_refresh_init() 4745331Samw * 4755331Samw * SMB service refresh thread initialization. This thread waits for a 4765331Samw * refresh event and updates the daemon's view of the configuration 4775331Samw * before going back to sleep. 4785331Samw */ 4795331Samw static int 4805331Samw smbd_refresh_init() 4815331Samw { 4825331Samw pthread_attr_t tattr; 4835331Samw pthread_condattr_t cattr; 4845331Samw int rc; 4855331Samw 4865331Samw (void) pthread_condattr_init(&cattr); 4875331Samw (void) pthread_cond_init(&refresh_cond, &cattr); 4885331Samw (void) pthread_condattr_destroy(&cattr); 4895331Samw 4905331Samw (void) pthread_mutex_init(&refresh_mutex, NULL); 4915331Samw 4925331Samw (void) pthread_attr_init(&tattr); 4935331Samw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 4945331Samw rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0); 4955331Samw (void) pthread_attr_destroy(&tattr); 4965331Samw return (rc); 4975331Samw 4985331Samw } 4995331Samw 5005331Samw /* 5015331Samw * smbd_refresh_fini() 5025331Samw * 5035331Samw * Stop the refresh thread. 5045331Samw */ 5055331Samw static void 5065331Samw smbd_refresh_fini() 5075331Samw { 5085331Samw (void) pthread_cancel(refresh_thr); 5095331Samw 5105331Samw (void) pthread_cond_destroy(&refresh_cond); 5115331Samw (void) pthread_mutex_destroy(&refresh_mutex); 5125331Samw } 5135331Samw 5145331Samw /* 5155331Samw * smbd_refresh_monitor() 5165331Samw * 5175331Samw * Wait for a refresh event. When this thread wakes up, update the 5185331Samw * smbd configuration from the SMF config information then go back to 5195331Samw * wait for the next refresh. 5205331Samw */ 5215331Samw /*ARGSUSED*/ 5225331Samw static void * 5235331Samw smbd_refresh_monitor(void *arg) 5245331Samw { 5255331Samw int dummy = 0; 5265331Samw 5275331Samw (void) pthread_mutex_lock(&refresh_mutex); 5285331Samw while (pthread_cond_wait(&refresh_cond, &refresh_mutex) == 0) { 5295331Samw /* 5305331Samw * We've been woken up by a refresh event so go do 5315331Samw * what is necessary. 5325331Samw */ 5335772Sas200622 ads_refresh(); 534*6139Sjb150015 smb_ccache_remove(SMB_CCACHE_PATH); 5356030Sjb150015 smb_nicmon_reconfig(); 536*6139Sjb150015 smb_set_netlogon_cred(); 5375521Sas200622 if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG, &dummy) < 0) { 5385331Samw smbd_report("configuration update ioctl: %s", 5395331Samw strerror(errno)); 5405331Samw } 5415331Samw } 5425331Samw return (NULL); 5435331Samw } 5445331Samw 5455331Samw 5465331Samw /* 5475331Samw * If the door has already been opened by another process (non-zero pid 5485331Samw * in target), we assume that another smbd is already running. If there 5495331Samw * is a race here, it will be caught later when smbsrv is opened because 5505331Samw * only one process is allowed to open the device at a time. 5515331Samw */ 5525331Samw static int 5535331Samw smbd_already_running(void) 5545331Samw { 5555331Samw door_info_t info; 5565331Samw int door; 5575331Samw 558*6139Sjb150015 if ((door = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) 5595331Samw return (0); 5605331Samw 5615331Samw if (door_info(door, &info) < 0) 5625331Samw return (0); 5635331Samw 5645331Samw if (info.di_target > 0) { 5655331Samw smbd_report("already running: pid %ld\n", info.di_target); 5665331Samw (void) close(door); 5675331Samw return (1); 5685331Samw } 5695331Samw 5705331Samw (void) close(door); 5715331Samw return (0); 5725331Samw } 5735331Samw 574*6139Sjb150015 /* 575*6139Sjb150015 * smbd_kernel_bind 576*6139Sjb150015 */ 5775331Samw static int 578*6139Sjb150015 smbd_kernel_bind(int id_lmshr_door, int id_srv_door, int id_winpipe_door) 5795331Samw { 580*6139Sjb150015 smb_io_t smb_io; 581*6139Sjb150015 int rc; 582*6139Sjb150015 583*6139Sjb150015 bzero(&smb_io, sizeof (smb_io)); 584*6139Sjb150015 smb_io.sio_version = SMB_IOC_VERSION; 585*6139Sjb150015 5865331Samw if (smbd.s_drv_fd != -1) 5875331Samw (void) close(smbd.s_drv_fd); 5885331Samw 5895331Samw if ((smbd.s_drv_fd = open(DRV_DEVICE_PATH, 0)) < 0) { 5905331Samw smbd.s_drv_fd = -1; 591*6139Sjb150015 return (errno); 592*6139Sjb150015 } 593*6139Sjb150015 smb_load_kconfig(&smb_io.sio_data.cfg); 594*6139Sjb150015 if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG, &smb_io) < 0) { 595*6139Sjb150015 (void) close(smbd.s_drv_fd); 596*6139Sjb150015 smbd.s_drv_fd = -1; 597*6139Sjb150015 return (errno); 598*6139Sjb150015 } 599*6139Sjb150015 smb_io.sio_data.gmtoff = (uint32_t)(-altzone); 600*6139Sjb150015 if (ioctl(smbd.s_drv_fd, SMB_IOC_GMTOFF, &smb_io) < 0) { 601*6139Sjb150015 (void) close(smbd.s_drv_fd); 602*6139Sjb150015 smbd.s_drv_fd = -1; 603*6139Sjb150015 return (errno); 6045331Samw } 605*6139Sjb150015 smb_io.sio_data.start.winpipe = id_winpipe_door; 606*6139Sjb150015 smb_io.sio_data.start.lmshrd = id_lmshr_door; 607*6139Sjb150015 smb_io.sio_data.start.udoor = id_srv_door; 608*6139Sjb150015 if (ioctl(smbd.s_drv_fd, SMB_IOC_START, &smb_io) < 0) { 609*6139Sjb150015 (void) close(smbd.s_drv_fd); 610*6139Sjb150015 smbd.s_drv_fd = -1; 611*6139Sjb150015 return (errno); 612*6139Sjb150015 } 613*6139Sjb150015 614*6139Sjb150015 rc = pthread_create(&nbt_listener, NULL, smbd_nbt_listener, NULL); 615*6139Sjb150015 if (rc == 0) { 616*6139Sjb150015 rc = pthread_create(&tcp_listener, NULL, smbd_tcp_listener, 617*6139Sjb150015 NULL); 618*6139Sjb150015 if (rc == 0) 619*6139Sjb150015 return (0); 620*6139Sjb150015 } 621*6139Sjb150015 (void) close(smbd.s_drv_fd); 622*6139Sjb150015 smbd.s_drv_fd = -1; 623*6139Sjb150015 return (rc); 6245331Samw } 6255331Samw 626*6139Sjb150015 /* 627*6139Sjb150015 * smbd_kernel_unbind 628*6139Sjb150015 */ 629*6139Sjb150015 static void 630*6139Sjb150015 smbd_kernel_unbind(void) 631*6139Sjb150015 { 632*6139Sjb150015 if (smbd.s_drv_fd != -1) { 633*6139Sjb150015 (void) close(smbd.s_drv_fd); 634*6139Sjb150015 smbd.s_drv_fd = -1; 635*6139Sjb150015 } 636*6139Sjb150015 } 6375331Samw 6385331Samw /* 6395331Samw * Initialization of the localtime thread. 6405331Samw * Returns 0 on success, an error number if thread creation fails. 6415331Samw */ 6425331Samw 6435331Samw int 6445331Samw smbd_localtime_init(void) 6455331Samw { 6465331Samw pthread_attr_t tattr; 6475331Samw int rc; 6485331Samw 6495331Samw (void) pthread_attr_init(&tattr); 6505331Samw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 6515331Samw rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0); 6525331Samw (void) pthread_attr_destroy(&tattr); 6535331Samw return (rc); 6545331Samw } 6555331Samw 6565331Samw /* 6575331Samw * Local time thread to kernel land. 6585331Samw * Send local gmtoff to kernel module one time at startup 6595331Samw * and each time it changes (up to twice a year). 6605331Samw * Local gmtoff is checked once every 15 minutes and 6615331Samw * since some timezones are aligned on half and qtr hour boundaries, 6625331Samw * once an hour would likely suffice. 6635331Samw */ 6645331Samw 6655331Samw /*ARGSUSED*/ 6665331Samw static void * 6675331Samw smbd_localtime_monitor(void *arg) 6685331Samw { 6695331Samw struct tm local_tm; 6705331Samw time_t secs, gmtoff; 6715331Samw time_t last_gmtoff = -1; 6725331Samw int timeout; 6735331Samw 6745331Samw for (;;) { 6755331Samw gmtoff = -altzone; 6765331Samw 6775331Samw if ((last_gmtoff != gmtoff) && (smbd.s_drv_fd != -1)) { 6785331Samw if (ioctl(smbd.s_drv_fd, SMB_IOC_GMTOFF, &gmtoff) < 0) { 6795331Samw smbd_report("localtime ioctl: %s", 6805331Samw strerror(errno)); 6815331Samw } 6825331Samw } 6835331Samw 6845331Samw /* 6855331Samw * Align the next iteration on a fifteen minute boundary. 6865331Samw */ 6875331Samw secs = time(0); 6885331Samw (void) localtime_r(&secs, &local_tm); 6895331Samw timeout = ((15 - (local_tm.tm_min % 15)) * SECSPERMIN); 6905331Samw (void) sleep(timeout); 6915331Samw 6925331Samw last_gmtoff = gmtoff; 6935331Samw } 6945331Samw 6955331Samw /*NOTREACHED*/ 6965331Samw return (NULL); 6975331Samw } 6985331Samw 6995331Samw static void 7005331Samw smbd_sig_handler(int sigval) 7015331Samw { 7025331Samw if (smbd.s_sigval == 0) 7035331Samw smbd.s_sigval = sigval; 7045331Samw } 7055331Samw 7065331Samw /* 7075331Samw * Set up configuration options and parse the command line. 7085331Samw * This function will determine if we will run as a daemon 7095331Samw * or in the foreground. 7105331Samw * 7115331Samw * Failure to find a uid or gid results in using the default (0). 7125331Samw */ 7135331Samw static int 7145331Samw smbd_setup_options(int argc, char *argv[]) 7155331Samw { 7165331Samw struct passwd *pwd; 7175331Samw struct group *grp; 7185331Samw int c; 7195331Samw 7205331Samw if ((pwd = getpwnam("root")) != NULL) 7215331Samw smbd.s_uid = pwd->pw_uid; 7225331Samw 7235331Samw if ((grp = getgrnam("sys")) != NULL) 7245331Samw smbd.s_gid = grp->gr_gid; 7255331Samw 7265772Sas200622 smbd.s_fg = smb_config_get_fg_flag(); 7275331Samw 7285331Samw while ((c = getopt(argc, argv, ":f")) != -1) { 7295331Samw switch (c) { 7305331Samw case 'f': 7315331Samw smbd.s_fg = 1; 7325331Samw break; 7335331Samw 7345331Samw case ':': 7355331Samw case '?': 7365331Samw default: 7375331Samw smbd_usage(stderr); 7385331Samw return (-1); 7395331Samw } 7405331Samw } 7415331Samw 7425331Samw return (0); 7435331Samw } 7445331Samw 7455331Samw static void 7465331Samw smbd_usage(FILE *fp) 7475331Samw { 7485331Samw static char *help[] = { 7495331Samw "-f run program in foreground" 7505331Samw }; 7515331Samw 7525331Samw int i; 7535331Samw 7545331Samw (void) fprintf(fp, "Usage: %s [-f]\n", smbd.s_pname); 7555331Samw 7565331Samw for (i = 0; i < sizeof (help)/sizeof (help[0]); ++i) 7575331Samw (void) fprintf(fp, " %s\n", help[i]); 7585331Samw } 7595331Samw 7605331Samw static void 7615331Samw smbd_report(const char *fmt, ...) 7625331Samw { 7635331Samw char buf[128]; 7645331Samw va_list ap; 7655331Samw 7665331Samw if (fmt == NULL) 7675331Samw return; 7685331Samw 7695331Samw va_start(ap, fmt); 7705331Samw (void) vsnprintf(buf, 128, fmt, ap); 7715331Samw va_end(ap); 7725331Samw 7735331Samw (void) fprintf(stderr, "smbd: %s\n", buf); 7745331Samw } 7755331Samw 7765331Samw /* 7775331Samw * Enable libumem debugging by default on DEBUG builds. 7785331Samw */ 7795331Samw #ifdef DEBUG 7805331Samw const char * 7815331Samw _umem_debug_init(void) 7825331Samw { 7835331Samw return ("default,verbose"); /* $UMEM_DEBUG setting */ 7845331Samw } 7855331Samw 7865331Samw const char * 7875331Samw _umem_logging_init(void) 7885331Samw { 7895331Samw return ("fail,contents"); /* $UMEM_LOGGING setting */ 7905331Samw } 7915331Samw #endif 792