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 267348SJose.Borrego@Sun.COM #pragma ident "@(#)smbd_main.c 1.13 08/08/05 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> 507348SJose.Borrego@Sun.COM #include <time.h> 515331Samw #include <tzfile.h> 525331Samw #include <libgen.h> 535331Samw #include <pwd.h> 545331Samw #include <grp.h> 555331Samw 565331Samw #include <smbsrv/smb_door_svc.h> 575331Samw #include <smbsrv/smb_ioctl.h> 585331Samw #include <smbsrv/libsmb.h> 595331Samw #include <smbsrv/libsmbns.h> 605331Samw #include <smbsrv/libsmbrdr.h> 615331Samw #include <smbsrv/libmlsvc.h> 625331Samw 635331Samw #include "smbd.h" 645331Samw 655331Samw #define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv" 665331Samw #define SMB_DBDIR "/var/smb" 675331Samw 686139Sjb150015 extern void *smbd_nbt_listener(void *); 696139Sjb150015 extern void *smbd_tcp_listener(void *); 706139Sjb150015 715331Samw static int smbd_daemonize_init(void); 725331Samw static void smbd_daemonize_fini(int, int); 735331Samw 746432Sas200622 static int smbd_kernel_bind(void); 755331Samw static void smbd_kernel_unbind(void); 765331Samw static int smbd_already_running(void); 775331Samw 785331Samw static int smbd_service_init(void); 795331Samw static void smbd_service_fini(void); 805331Samw 815331Samw static int smbd_setup_options(int argc, char *argv[]); 825331Samw static void smbd_usage(FILE *fp); 835331Samw static void smbd_report(const char *fmt, ...); 845331Samw 855331Samw static void smbd_sig_handler(int sig); 865331Samw 877348SJose.Borrego@Sun.COM static int32_t smbd_gmtoff(void); 885331Samw static int smbd_localtime_init(void); 895331Samw static void *smbd_localtime_monitor(void *arg); 905331Samw 915331Samw static pthread_t localtime_thr; 925331Samw 935331Samw static int smbd_refresh_init(void); 945331Samw static void smbd_refresh_fini(void); 955331Samw static void *smbd_refresh_monitor(void *); 966139Sjb150015 static pthread_t nbt_listener; 976139Sjb150015 static pthread_t tcp_listener; 985331Samw static pthread_t refresh_thr; 995331Samw static pthread_cond_t refresh_cond; 1005331Samw static pthread_mutex_t refresh_mutex; 1015331Samw 1026139Sjb150015 smbd_t smbd; 1035331Samw 1045331Samw /* 1055331Samw * smbd user land daemon 1065331Samw * 1075331Samw * Use SMF error codes only on return or exit. 1085331Samw */ 1095331Samw int 1105331Samw main(int argc, char *argv[]) 1115331Samw { 1126432Sas200622 struct sigaction act; 1136432Sas200622 sigset_t set; 1146432Sas200622 uid_t uid; 1156432Sas200622 int pfd = -1; 1167052Samw int sigval; 1175331Samw 1185331Samw smbd.s_pname = basename(argv[0]); 1195331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 1205331Samw 1215331Samw if (smbd_setup_options(argc, argv) != 0) 1225331Samw return (SMF_EXIT_ERR_FATAL); 1235331Samw 1245331Samw if ((uid = getuid()) != smbd.s_uid) { 1255331Samw smbd_report("user %d: %s", uid, strerror(EPERM)); 1265331Samw return (SMF_EXIT_ERR_FATAL); 1275331Samw } 1285331Samw 1295331Samw if (getzoneid() != GLOBAL_ZONEID) { 1305331Samw smbd_report("non-global zones are not supported"); 1315331Samw return (SMF_EXIT_ERR_FATAL); 1325331Samw } 1335331Samw 1345331Samw if (is_system_labeled()) { 1355331Samw smbd_report("Trusted Extensions not supported"); 1365331Samw return (SMF_EXIT_ERR_FATAL); 1375331Samw } 1385331Samw 1395331Samw if (smbd_already_running()) 1405331Samw return (SMF_EXIT_OK); 1415331Samw 1425331Samw (void) sigfillset(&set); 1435331Samw (void) sigdelset(&set, SIGABRT); 1445331Samw 1455331Samw (void) sigfillset(&act.sa_mask); 1465331Samw act.sa_handler = smbd_sig_handler; 1475331Samw act.sa_flags = 0; 1485331Samw 1495331Samw (void) sigaction(SIGTERM, &act, NULL); 1505331Samw (void) sigaction(SIGHUP, &act, NULL); 1515331Samw (void) sigaction(SIGINT, &act, NULL); 1525331Samw (void) sigaction(SIGPIPE, &act, NULL); 1535331Samw 1545331Samw (void) sigdelset(&set, SIGTERM); 1555331Samw (void) sigdelset(&set, SIGHUP); 1565331Samw (void) sigdelset(&set, SIGINT); 1575331Samw (void) sigdelset(&set, SIGPIPE); 1585331Samw 1595331Samw if (smbd.s_fg) { 1605331Samw (void) sigdelset(&set, SIGTSTP); 1615331Samw (void) sigdelset(&set, SIGTTIN); 1625331Samw (void) sigdelset(&set, SIGTTOU); 1635331Samw 1645331Samw if (smbd_service_init() != 0) { 1655331Samw smbd_report("service initialization failed"); 1665331Samw exit(SMF_EXIT_ERR_FATAL); 1675331Samw } 1685331Samw } else { 1695331Samw /* 1705331Samw * "pfd" is a pipe descriptor -- any fatal errors 1715331Samw * during subsequent initialization of the child 1725331Samw * process should be written to this pipe and the 1735331Samw * parent will report this error as the exit status. 1745331Samw */ 1755331Samw pfd = smbd_daemonize_init(); 1765331Samw 1775331Samw if (smbd_service_init() != 0) { 1785331Samw smbd_report("daemon initialization failed"); 1795331Samw exit(SMF_EXIT_ERR_FATAL); 1805331Samw } 1815331Samw 1825331Samw smbd_daemonize_fini(pfd, SMF_EXIT_OK); 1835331Samw } 1845331Samw 1855331Samw (void) atexit(smbd_service_fini); 1865331Samw 1875331Samw while (!smbd.s_shutdown_flag) { 1887052Samw if (smbd.s_sigval == 0) 1897052Samw (void) sigsuspend(&set); 1905331Samw 1917052Samw sigval = smbd.s_sigval; 1927052Samw smbd.s_sigval = 0; 1937052Samw 1947052Samw switch (sigval) { 1955331Samw case 0: 1965331Samw case SIGPIPE: 1975331Samw break; 1985331Samw 1995331Samw case SIGHUP: 2005331Samw /* Refresh config was triggered */ 2015331Samw if (smbd.s_fg) 2025331Samw smbd_report("reconfiguration requested"); 2035331Samw (void) pthread_cond_signal(&refresh_cond); 2045331Samw break; 2055331Samw 2065331Samw default: 2075331Samw /* 2085331Samw * Typically SIGINT or SIGTERM. 2095331Samw */ 2105331Samw smbd.s_shutdown_flag = 1; 2115331Samw break; 2125331Samw } 2135331Samw } 2145331Samw 2155331Samw smbd_service_fini(); 2165331Samw closelog(); 2175331Samw return (SMF_EXIT_OK); 2185331Samw } 2195331Samw 2205331Samw /* 2215331Samw * This function will fork off a child process, 2225331Samw * from which only the child will return. 2235331Samw * 2245331Samw * Use SMF error codes only on exit. 2255331Samw */ 2265331Samw static int 2275331Samw smbd_daemonize_init(void) 2285331Samw { 2295331Samw int status, pfds[2]; 2305331Samw sigset_t set, oset; 2315331Samw pid_t pid; 2325331Samw int rc; 2335331Samw 2345331Samw /* 2355331Samw * Reset privileges to the minimum set required. We continue 2365331Samw * to run as root to create and access files in /var. 2375331Samw */ 2385331Samw rc = __init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS, 2395331Samw smbd.s_uid, smbd.s_gid, 2405331Samw PRIV_NET_MAC_AWARE, PRIV_NET_PRIVADDR, PRIV_PROC_AUDIT, 2415331Samw PRIV_SYS_DEVICES, PRIV_SYS_SMB, NULL); 2425331Samw 2435331Samw if (rc != 0) { 2445331Samw smbd_report("insufficient privileges"); 2455331Samw exit(SMF_EXIT_ERR_FATAL); 2465331Samw } 2475331Samw 2485331Samw /* 2495331Samw * Block all signals prior to the fork and leave them blocked in the 2505331Samw * parent so we don't get in a situation where the parent gets SIGINT 2515331Samw * and returns non-zero exit status and the child is actually running. 2525331Samw * In the child, restore the signal mask once we've done our setsid(). 2535331Samw */ 2545331Samw (void) sigfillset(&set); 2555331Samw (void) sigdelset(&set, SIGABRT); 2565331Samw (void) sigprocmask(SIG_BLOCK, &set, &oset); 2575331Samw 2585331Samw if (pipe(pfds) == -1) { 2595331Samw smbd_report("unable to create pipe"); 2605331Samw exit(SMF_EXIT_ERR_FATAL); 2615331Samw } 2625331Samw 2635331Samw closelog(); 2645331Samw 2655331Samw if ((pid = fork()) == -1) { 2665331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 2675331Samw smbd_report("unable to fork"); 2685331Samw closelog(); 2695331Samw exit(SMF_EXIT_ERR_FATAL); 2705331Samw } 2715331Samw 2725331Samw /* 2735331Samw * If we're the parent process, wait for either the child to send us 2745331Samw * the appropriate exit status over the pipe or for the read to fail 2755331Samw * (presumably with 0 for EOF if our child terminated abnormally). 2765331Samw * If the read fails, exit with either the child's exit status if it 2775331Samw * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal. 2785331Samw */ 2795331Samw if (pid != 0) { 2805331Samw (void) close(pfds[1]); 2815331Samw 2825331Samw if (read(pfds[0], &status, sizeof (status)) == sizeof (status)) 2835331Samw _exit(status); 2845331Samw 2855331Samw if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) 2865331Samw _exit(WEXITSTATUS(status)); 2875331Samw 2885331Samw _exit(SMF_EXIT_ERR_FATAL); 2895331Samw } 2905331Samw 2915331Samw openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 2925331Samw smbd.s_pid = getpid(); 2935331Samw (void) setsid(); 2945331Samw (void) sigprocmask(SIG_SETMASK, &oset, NULL); 2955331Samw (void) chdir("/"); 2965331Samw (void) umask(022); 2975331Samw (void) close(pfds[0]); 2985331Samw 2995331Samw return (pfds[1]); 3005331Samw } 3015331Samw 3025331Samw static void 3035331Samw smbd_daemonize_fini(int fd, int exit_status) 3045331Samw { 3055331Samw /* 3065331Samw * Now that we're running, if a pipe fd was specified, write an exit 3075331Samw * status to it to indicate that our parent process can safely detach. 3085331Samw * Then proceed to loading the remaining non-built-in modules. 3095331Samw */ 3105331Samw if (fd >= 0) 3115331Samw (void) write(fd, &exit_status, sizeof (exit_status)); 3125331Samw 3135331Samw (void) close(fd); 3145331Samw 3155331Samw if ((fd = open("/dev/null", O_RDWR)) >= 0) { 3165331Samw (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); 3175331Samw (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); 3185331Samw (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); 3195331Samw (void) close(fd); 3205331Samw } 3215331Samw 3225331Samw __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 3235331Samw PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, NULL); 3245331Samw } 3255331Samw 3266139Sjb150015 /* 3276139Sjb150015 * smbd_service_init 3286139Sjb150015 */ 3295331Samw static int 3305331Samw smbd_service_init(void) 3315331Samw { 3326432Sas200622 int rc; 3336432Sas200622 char resource_domain[SMB_PI_MAX_DOMAIN]; 3346432Sas200622 char fqdn[MAXHOSTNAMELEN]; 3356432Sas200622 3365331Samw smbd.s_drv_fd = -1; 3375331Samw 3386139Sjb150015 if ((mkdir(SMB_DBDIR, 0700) < 0) && (errno != EEXIST)) { 3396139Sjb150015 smbd_report("mkdir %s: %s", SMB_DBDIR, strerror(errno)); 3406139Sjb150015 return (1); 3415331Samw } 3425331Samw 3436139Sjb150015 if ((rc = smb_ccache_init(SMB_VARRUN_DIR, SMB_CCACHE_FILE)) != 0) { 3446139Sjb150015 if (rc == -1) 3456139Sjb150015 smbd_report("mkdir %s: %s", SMB_VARRUN_DIR, 3466139Sjb150015 strerror(errno)); 3476139Sjb150015 else 3486139Sjb150015 smbd_report("unable to set KRB5CCNAME"); 3495331Samw return (1); 3505331Samw } 3515331Samw 3526139Sjb150015 3535331Samw (void) oem_language_set("english"); 3545331Samw 3556432Sas200622 if (!smb_wka_init()) { 3565331Samw smbd_report("out of memory"); 3575331Samw return (1); 3585331Samw } 3595331Samw 3606432Sas200622 if (smb_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0) 3616432Sas200622 smbd_report("NIC monitoring failed to start"); 3626432Sas200622 3637348SJose.Borrego@Sun.COM dns_msgid_init(); 3645331Samw smbrdr_init(); 3655331Samw 3665772Sas200622 if (smb_netbios_start() != 0) 3675772Sas200622 smbd_report("NetBIOS services failed to start"); 3685772Sas200622 else 3695772Sas200622 smbd_report("NetBIOS services started"); 3705772Sas200622 3715331Samw if (smb_netlogon_init() != 0) { 3725331Samw smbd_report("netlogon initialization failed"); 3735331Samw return (1); 3745331Samw } 3755331Samw 3765772Sas200622 (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); 3775331Samw (void) utf8_strupr(resource_domain); 3785331Samw 3795331Samw /* Get the ID map client handle */ 3805331Samw if ((rc = smb_idmap_start()) != 0) { 3815331Samw smbd_report("no idmap handle"); 3825331Samw return (rc); 3835331Samw } 3845331Samw 3856432Sas200622 smbd.s_secmode = smb_config_get_secmode(); 3866432Sas200622 if ((rc = nt_domain_init(resource_domain, smbd.s_secmode)) != 0) { 3875772Sas200622 if (rc == SMB_DOMAIN_NOMACHINE_SID) { 3885772Sas200622 smbd_report( 3895772Sas200622 "no machine SID: check idmap configuration"); 3905772Sas200622 return (rc); 3915772Sas200622 } 3925331Samw } 3935331Samw 3947052Samw smb_ads_init(); 3955331Samw if ((rc = mlsvc_init()) != 0) { 3965331Samw smbd_report("msrpc initialization failed"); 3975331Samw return (rc); 3985331Samw } 3995331Samw 4007348SJose.Borrego@Sun.COM if (smbd.s_secmode == SMB_SECMODE_DOMAIN) 4017348SJose.Borrego@Sun.COM if (smbd_locate_dc_start(resource_domain) != 0) 4027348SJose.Borrego@Sun.COM smbd_report("dc discovery failed %s", strerror(errno)); 4036139Sjb150015 4046771Sjb150015 smbd.s_door_lmshr = smb_share_dsrv_start(); 4056432Sas200622 if (smbd.s_door_lmshr < 0) { 4065331Samw smbd_report("share initialization failed"); 4075331Samw } 4085331Samw 4096432Sas200622 smbd.s_door_srv = smb_door_srv_start(); 4106432Sas200622 if (smbd.s_door_srv < 0) 4115331Samw return (rc); 4125331Samw 4135331Samw if ((rc = smbd_refresh_init()) != 0) 4145331Samw return (rc); 4155331Samw 4166139Sjb150015 if (smb_getfqdomainname(fqdn, MAXHOSTNAMELEN) == 0) 4176600Sas200622 (void) dyndns_update_core(fqdn); 4185331Samw 4195331Samw (void) smbd_localtime_init(); 4205331Samw 4217052Samw smbd.s_door_opipe = smbd_opipe_dsrv_start(); 4227052Samw if (smbd.s_door_opipe < 0) { 4237052Samw smbd_report("opipe initialization failed %s", 4245521Sas200622 strerror(errno)); 4255521Sas200622 return (rc); 4265521Sas200622 } 4275521Sas200622 4285772Sas200622 (void) smb_lgrp_start(); 4296030Sjb150015 4307052Samw smb_pwd_init(B_TRUE); 4316030Sjb150015 4326432Sas200622 rc = smbd_kernel_bind(); 4336432Sas200622 if (rc != 0) { 4346139Sjb150015 smbd_report("kernel bind error: %s", strerror(errno)); 4356432Sas200622 return (rc); 4366432Sas200622 } 4375331Samw 4387348SJose.Borrego@Sun.COM if ((rc = smb_shr_start()) != 0) { 4397348SJose.Borrego@Sun.COM smbd_report("share initialization failed: %s", strerror(errno)); 4407348SJose.Borrego@Sun.COM return (rc); 4417348SJose.Borrego@Sun.COM } 4427348SJose.Borrego@Sun.COM 4437348SJose.Borrego@Sun.COM return (0); 4445521Sas200622 } 4455521Sas200622 4465331Samw /* 4475331Samw * Close the kernel service and shutdown smbd services. 4485331Samw * This function is registered with atexit(): ensure that anything 4495331Samw * called from here is safe to be called multiple times. 4505331Samw */ 4515331Samw static void 4525331Samw smbd_service_fini(void) 4535331Samw { 4547052Samw smbd_opipe_dsrv_stop(); 4556432Sas200622 smb_wka_fini(); 4565331Samw smbd_refresh_fini(); 4575331Samw smbd_kernel_unbind(); 4585331Samw smb_door_srv_stop(); 4596771Sjb150015 smb_share_dsrv_stop(); 4607052Samw smb_shr_stop(); 4615331Samw smb_nicmon_stop(); 4625331Samw smb_idmap_stop(); 4635772Sas200622 smb_lgrp_stop(); 4646139Sjb150015 smb_ccache_remove(SMB_CCACHE_PATH); 4656030Sjb150015 smb_pwd_fini(); 4665521Sas200622 4675331Samw } 4685331Samw 4696139Sjb150015 4705331Samw /* 4715331Samw * smbd_refresh_init() 4725331Samw * 4735331Samw * SMB service refresh thread initialization. This thread waits for a 4745331Samw * refresh event and updates the daemon's view of the configuration 4755331Samw * before going back to sleep. 4765331Samw */ 4775331Samw static int 4785331Samw smbd_refresh_init() 4795331Samw { 4806432Sas200622 pthread_attr_t tattr; 4816432Sas200622 pthread_condattr_t cattr; 4826432Sas200622 int rc; 4835331Samw 4845331Samw (void) pthread_condattr_init(&cattr); 4855331Samw (void) pthread_cond_init(&refresh_cond, &cattr); 4865331Samw (void) pthread_condattr_destroy(&cattr); 4875331Samw 4885331Samw (void) pthread_mutex_init(&refresh_mutex, NULL); 4895331Samw 4905331Samw (void) pthread_attr_init(&tattr); 4915331Samw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 4925331Samw rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0); 4935331Samw (void) pthread_attr_destroy(&tattr); 4946432Sas200622 4955331Samw return (rc); 4965331Samw } 4975331Samw 4985331Samw /* 4995331Samw * smbd_refresh_fini() 5005331Samw * 5015331Samw * Stop the refresh thread. 5025331Samw */ 5035331Samw static void 5045331Samw smbd_refresh_fini() 5055331Samw { 5065331Samw (void) pthread_cancel(refresh_thr); 5075331Samw 5085331Samw (void) pthread_cond_destroy(&refresh_cond); 5095331Samw (void) pthread_mutex_destroy(&refresh_mutex); 5105331Samw } 5115331Samw 5125331Samw /* 5135331Samw * smbd_refresh_monitor() 5145331Samw * 5155331Samw * Wait for a refresh event. When this thread wakes up, update the 5165331Samw * smbd configuration from the SMF config information then go back to 5175331Samw * wait for the next refresh. 5185331Samw */ 5195331Samw /*ARGSUSED*/ 5205331Samw static void * 5215331Samw smbd_refresh_monitor(void *arg) 5225331Samw { 5236432Sas200622 smb_io_t smb_io; 5246432Sas200622 size_t len; 5256432Sas200622 char *new_dom; 5266432Sas200622 int new_secmod; 5276432Sas200622 char *old_dom; 5286432Sas200622 char fqdn[MAXHOSTNAMELEN]; 5296432Sas200622 int rc = 0; 5305331Samw 5316771Sjb150015 bzero(&smb_io, sizeof (smb_io)); 5326771Sjb150015 smb_io.sio_version = SMB_IOC_VERSION; 5336771Sjb150015 5345331Samw (void) pthread_mutex_lock(&refresh_mutex); 5355331Samw while (pthread_cond_wait(&refresh_cond, &refresh_mutex) == 0) { 5365331Samw /* 5375331Samw * We've been woken up by a refresh event so go do 5385331Samw * what is necessary. 5395331Samw */ 5407052Samw smb_ads_refresh(); 5416139Sjb150015 smb_ccache_remove(SMB_CCACHE_PATH); 5426432Sas200622 5436432Sas200622 if ((rc = smb_getfqdomainname(fqdn, MAXHOSTNAMELEN)) != 0) 5446432Sas200622 smbd_report("failed to get fully qualified domainname"); 5456432Sas200622 5466432Sas200622 if (rc == 0) 5476432Sas200622 /* Clear rev zone before creating if list */ 5486432Sas200622 if (dyndns_clear_rev_zone(fqdn) != 0) 5496432Sas200622 smbd_report("failed to clear DNS reverse " 5506432Sas200622 "lookup zone"); 5516432Sas200622 5526432Sas200622 /* re-initialize NIC table */ 5536432Sas200622 if (smb_nic_init() != 0) 5546432Sas200622 smbd_report("failed to get NIC information"); 5556432Sas200622 5566432Sas200622 smb_netbios_name_reconfig(); 5576432Sas200622 smb_browser_reconfig(); 5586432Sas200622 5596432Sas200622 if (rc == 0) 5606600Sas200622 if (dyndns_update_core(fqdn) != 0) 5616432Sas200622 smbd_report("failed to update dynamic DNS"); 5626432Sas200622 5636139Sjb150015 smb_set_netlogon_cred(); 5646432Sas200622 5656432Sas200622 smb_load_kconfig(&smb_io.sio_data.cfg); 5666432Sas200622 new_dom = smb_io.sio_data.cfg.skc_resource_domain; 5676432Sas200622 old_dom = smbd.s_kcfg.skc_resource_domain; 5686432Sas200622 len = strlen(old_dom); 5696432Sas200622 new_secmod = smb_config_get_secmode(); 5706432Sas200622 if ((len != strlen(new_dom)) || 5716432Sas200622 (strncasecmp(new_dom, old_dom, len)) || 5726432Sas200622 (new_secmod != smbd.s_secmode) || 5736432Sas200622 (smbd.s_drv_fd == -1)) { 5746432Sas200622 /* 5756432Sas200622 * The active sessions have to be disconnected. 5766432Sas200622 */ 5776432Sas200622 smbd_kernel_unbind(); 5786432Sas200622 if (smbd_kernel_bind()) { 5796432Sas200622 smbd_report("kernel bind error: %s", 5806432Sas200622 strerror(errno)); 5816432Sas200622 } 5826432Sas200622 continue; 5836432Sas200622 } 5846432Sas200622 5856432Sas200622 bcopy(&smb_io.sio_data.cfg, &smbd.s_kcfg, sizeof (smbd.s_kcfg)); 5866432Sas200622 if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG, &smb_io) < 0) { 5875331Samw smbd_report("configuration update ioctl: %s", 5885331Samw strerror(errno)); 5895331Samw } 5905331Samw } 5915331Samw return (NULL); 5925331Samw } 5935331Samw 5945331Samw 5955331Samw /* 5965331Samw * If the door has already been opened by another process (non-zero pid 5975331Samw * in target), we assume that another smbd is already running. If there 5985331Samw * is a race here, it will be caught later when smbsrv is opened because 5995331Samw * only one process is allowed to open the device at a time. 6005331Samw */ 6015331Samw static int 6025331Samw smbd_already_running(void) 6035331Samw { 6045331Samw door_info_t info; 6055331Samw int door; 6065331Samw 6076139Sjb150015 if ((door = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) 6085331Samw return (0); 6095331Samw 6105331Samw if (door_info(door, &info) < 0) 6115331Samw return (0); 6125331Samw 6135331Samw if (info.di_target > 0) { 6145331Samw smbd_report("already running: pid %ld\n", info.di_target); 6155331Samw (void) close(door); 6165331Samw return (1); 6175331Samw } 6185331Samw 6195331Samw (void) close(door); 6205331Samw return (0); 6215331Samw } 6225331Samw 6236139Sjb150015 /* 6246139Sjb150015 * smbd_kernel_bind 6256432Sas200622 * 6266432Sas200622 * This function open the smbsrv device and start the kernel service. 6276139Sjb150015 */ 6285331Samw static int 6296432Sas200622 smbd_kernel_bind(void) 6305331Samw { 631*7826SJose.Borrego@Sun.COM pthread_attr_t tattr; 6326139Sjb150015 smb_io_t smb_io; 633*7826SJose.Borrego@Sun.COM int rc1; 634*7826SJose.Borrego@Sun.COM int rc2; 6356139Sjb150015 int rc; 6366139Sjb150015 6376139Sjb150015 bzero(&smb_io, sizeof (smb_io)); 6386139Sjb150015 smb_io.sio_version = SMB_IOC_VERSION; 6396139Sjb150015 6405331Samw if (smbd.s_drv_fd != -1) 6415331Samw (void) close(smbd.s_drv_fd); 6425331Samw 6435331Samw if ((smbd.s_drv_fd = open(DRV_DEVICE_PATH, 0)) < 0) { 6445331Samw smbd.s_drv_fd = -1; 6456139Sjb150015 return (errno); 6466139Sjb150015 } 6476432Sas200622 smb_load_kconfig(&smbd.s_kcfg); 6486432Sas200622 bcopy(&smbd.s_kcfg, &smb_io.sio_data.cfg, sizeof (smb_io.sio_data.cfg)); 6496139Sjb150015 if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG, &smb_io) < 0) { 6506139Sjb150015 (void) close(smbd.s_drv_fd); 6516139Sjb150015 smbd.s_drv_fd = -1; 6526139Sjb150015 return (errno); 6536139Sjb150015 } 6547348SJose.Borrego@Sun.COM smb_io.sio_data.gmtoff = smbd_gmtoff(); 6556139Sjb150015 if (ioctl(smbd.s_drv_fd, SMB_IOC_GMTOFF, &smb_io) < 0) { 6566139Sjb150015 (void) close(smbd.s_drv_fd); 6576139Sjb150015 smbd.s_drv_fd = -1; 6586139Sjb150015 return (errno); 6595331Samw } 6607052Samw smb_io.sio_data.start.opipe = smbd.s_door_opipe; 6616432Sas200622 smb_io.sio_data.start.lmshrd = smbd.s_door_lmshr; 6626432Sas200622 smb_io.sio_data.start.udoor = smbd.s_door_srv; 6636139Sjb150015 if (ioctl(smbd.s_drv_fd, SMB_IOC_START, &smb_io) < 0) { 6646139Sjb150015 (void) close(smbd.s_drv_fd); 6656139Sjb150015 smbd.s_drv_fd = -1; 6666139Sjb150015 return (errno); 6676139Sjb150015 } 6686139Sjb150015 669*7826SJose.Borrego@Sun.COM (void) pthread_attr_init(&tattr); 670*7826SJose.Borrego@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 671*7826SJose.Borrego@Sun.COM 672*7826SJose.Borrego@Sun.COM rc1 = pthread_create(&nbt_listener, &tattr, smbd_nbt_listener, NULL); 673*7826SJose.Borrego@Sun.COM if (rc1 != 0) 674*7826SJose.Borrego@Sun.COM smbd_report("unable to start NBT service"); 675*7826SJose.Borrego@Sun.COM 676*7826SJose.Borrego@Sun.COM rc2 = pthread_create(&tcp_listener, &tattr, smbd_tcp_listener, NULL); 677*7826SJose.Borrego@Sun.COM if (rc2 != 0) 678*7826SJose.Borrego@Sun.COM smbd_report("unable to start TCP service"); 679*7826SJose.Borrego@Sun.COM 680*7826SJose.Borrego@Sun.COM (void) pthread_attr_destroy(&tattr); 681*7826SJose.Borrego@Sun.COM 682*7826SJose.Borrego@Sun.COM rc = rc1; 683*7826SJose.Borrego@Sun.COM if (rc == 0) 684*7826SJose.Borrego@Sun.COM rc = rc2; 685*7826SJose.Borrego@Sun.COM 6866139Sjb150015 if (rc == 0) { 687*7826SJose.Borrego@Sun.COM smbd.s_kbound = B_TRUE; 688*7826SJose.Borrego@Sun.COM return (0); 6896432Sas200622 } 6906432Sas200622 6916139Sjb150015 (void) close(smbd.s_drv_fd); 6926139Sjb150015 smbd.s_drv_fd = -1; 6936139Sjb150015 return (rc); 6945331Samw } 6955331Samw 6966139Sjb150015 /* 6976139Sjb150015 * smbd_kernel_unbind 6986139Sjb150015 */ 6996139Sjb150015 static void 7006139Sjb150015 smbd_kernel_unbind(void) 7016139Sjb150015 { 7026139Sjb150015 if (smbd.s_drv_fd != -1) { 7036139Sjb150015 (void) close(smbd.s_drv_fd); 7046139Sjb150015 smbd.s_drv_fd = -1; 7056432Sas200622 smbd.s_kbound = B_FALSE; 7066139Sjb150015 } 7076139Sjb150015 } 7085331Samw 7095331Samw /* 7105331Samw * Initialization of the localtime thread. 7115331Samw * Returns 0 on success, an error number if thread creation fails. 7125331Samw */ 7135331Samw 7145331Samw int 7155331Samw smbd_localtime_init(void) 7165331Samw { 7175331Samw pthread_attr_t tattr; 7185331Samw int rc; 7195331Samw 7205331Samw (void) pthread_attr_init(&tattr); 7215331Samw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 7225331Samw rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0); 7235331Samw (void) pthread_attr_destroy(&tattr); 7245331Samw return (rc); 7255331Samw } 7265331Samw 7275331Samw /* 7285331Samw * Local time thread to kernel land. 7295331Samw * Send local gmtoff to kernel module one time at startup 7305331Samw * and each time it changes (up to twice a year). 7315331Samw * Local gmtoff is checked once every 15 minutes and 7325331Samw * since some timezones are aligned on half and qtr hour boundaries, 7335331Samw * once an hour would likely suffice. 7345331Samw */ 7355331Samw 7365331Samw /*ARGSUSED*/ 7375331Samw static void * 7385331Samw smbd_localtime_monitor(void *arg) 7395331Samw { 7405331Samw struct tm local_tm; 7417348SJose.Borrego@Sun.COM time_t secs; 7427348SJose.Borrego@Sun.COM int32_t gmtoff, last_gmtoff = -1; 7435331Samw int timeout; 7445331Samw 7455331Samw for (;;) { 7467348SJose.Borrego@Sun.COM gmtoff = smbd_gmtoff(); 7475331Samw 7485331Samw if ((last_gmtoff != gmtoff) && (smbd.s_drv_fd != -1)) { 7495331Samw if (ioctl(smbd.s_drv_fd, SMB_IOC_GMTOFF, &gmtoff) < 0) { 7505331Samw smbd_report("localtime ioctl: %s", 7515331Samw strerror(errno)); 7525331Samw } 7535331Samw } 7545331Samw 7555331Samw /* 7565331Samw * Align the next iteration on a fifteen minute boundary. 7575331Samw */ 7585331Samw secs = time(0); 7595331Samw (void) localtime_r(&secs, &local_tm); 7605331Samw timeout = ((15 - (local_tm.tm_min % 15)) * SECSPERMIN); 7615331Samw (void) sleep(timeout); 7625331Samw 7635331Samw last_gmtoff = gmtoff; 7645331Samw } 7655331Samw 7665331Samw /*NOTREACHED*/ 7675331Samw return (NULL); 7685331Samw } 7695331Samw 7707348SJose.Borrego@Sun.COM /* 7717348SJose.Borrego@Sun.COM * smbd_gmtoff 7727348SJose.Borrego@Sun.COM * 7737348SJose.Borrego@Sun.COM * Determine offset from GMT. If daylight saving time use altzone, 7747348SJose.Borrego@Sun.COM * otherwise use timezone. 7757348SJose.Borrego@Sun.COM */ 7767348SJose.Borrego@Sun.COM static int32_t 7777348SJose.Borrego@Sun.COM smbd_gmtoff(void) 7787348SJose.Borrego@Sun.COM { 7797348SJose.Borrego@Sun.COM time_t clock_val; 7807348SJose.Borrego@Sun.COM struct tm *atm; 7817348SJose.Borrego@Sun.COM int32_t gmtoff; 7827348SJose.Borrego@Sun.COM 7837348SJose.Borrego@Sun.COM (void) time(&clock_val); 7847348SJose.Borrego@Sun.COM atm = localtime(&clock_val); 7857348SJose.Borrego@Sun.COM 7867348SJose.Borrego@Sun.COM gmtoff = (atm->tm_isdst) ? altzone : timezone; 7877348SJose.Borrego@Sun.COM 7887348SJose.Borrego@Sun.COM return (gmtoff); 7897348SJose.Borrego@Sun.COM } 7907348SJose.Borrego@Sun.COM 7915331Samw static void 7925331Samw smbd_sig_handler(int sigval) 7935331Samw { 7945331Samw if (smbd.s_sigval == 0) 7955331Samw smbd.s_sigval = sigval; 7965331Samw } 7975331Samw 7985331Samw /* 7995331Samw * Set up configuration options and parse the command line. 8005331Samw * This function will determine if we will run as a daemon 8015331Samw * or in the foreground. 8025331Samw * 8035331Samw * Failure to find a uid or gid results in using the default (0). 8045331Samw */ 8055331Samw static int 8065331Samw smbd_setup_options(int argc, char *argv[]) 8075331Samw { 8085331Samw struct passwd *pwd; 8095331Samw struct group *grp; 8105331Samw int c; 8115331Samw 8125331Samw if ((pwd = getpwnam("root")) != NULL) 8135331Samw smbd.s_uid = pwd->pw_uid; 8145331Samw 8155331Samw if ((grp = getgrnam("sys")) != NULL) 8165331Samw smbd.s_gid = grp->gr_gid; 8175331Samw 8185772Sas200622 smbd.s_fg = smb_config_get_fg_flag(); 8195331Samw 8205331Samw while ((c = getopt(argc, argv, ":f")) != -1) { 8215331Samw switch (c) { 8225331Samw case 'f': 8235331Samw smbd.s_fg = 1; 8245331Samw break; 8255331Samw 8265331Samw case ':': 8275331Samw case '?': 8285331Samw default: 8295331Samw smbd_usage(stderr); 8305331Samw return (-1); 8315331Samw } 8325331Samw } 8335331Samw 8345331Samw return (0); 8355331Samw } 8365331Samw 8375331Samw static void 8385331Samw smbd_usage(FILE *fp) 8395331Samw { 8405331Samw static char *help[] = { 8415331Samw "-f run program in foreground" 8425331Samw }; 8435331Samw 8445331Samw int i; 8455331Samw 8465331Samw (void) fprintf(fp, "Usage: %s [-f]\n", smbd.s_pname); 8475331Samw 8485331Samw for (i = 0; i < sizeof (help)/sizeof (help[0]); ++i) 8495331Samw (void) fprintf(fp, " %s\n", help[i]); 8505331Samw } 8515331Samw 8525331Samw static void 8535331Samw smbd_report(const char *fmt, ...) 8545331Samw { 8555331Samw char buf[128]; 8565331Samw va_list ap; 8575331Samw 8585331Samw if (fmt == NULL) 8595331Samw return; 8605331Samw 8615331Samw va_start(ap, fmt); 8625331Samw (void) vsnprintf(buf, 128, fmt, ap); 8635331Samw va_end(ap); 8645331Samw 8655331Samw (void) fprintf(stderr, "smbd: %s\n", buf); 8665331Samw } 8675331Samw 8685331Samw /* 8695331Samw * Enable libumem debugging by default on DEBUG builds. 8705331Samw */ 8715331Samw #ifdef DEBUG 8725331Samw const char * 8735331Samw _umem_debug_init(void) 8745331Samw { 8755331Samw return ("default,verbose"); /* $UMEM_DEBUG setting */ 8765331Samw } 8775331Samw 8785331Samw const char * 8795331Samw _umem_logging_init(void) 8805331Samw { 8815331Samw return ("fail,contents"); /* $UMEM_LOGGING setting */ 8825331Samw } 8835331Samw #endif 884