12654012fSReza Sabdar /* 28c4f9701SJanice Chang * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 3*faac71c0SJan Kryl * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 42654012fSReza Sabdar */ 52654012fSReza Sabdar 62654012fSReza Sabdar /* 72654012fSReza Sabdar * BSD 3 Clause License 82654012fSReza Sabdar * 92654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 102654012fSReza Sabdar * 112654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 122654012fSReza Sabdar * modification, are permitted provided that the following conditions 132654012fSReza Sabdar * are met: 142654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 152654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 162654012fSReza Sabdar * 172654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 182654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 192654012fSReza Sabdar * the documentation and/or other materials provided with the 202654012fSReza Sabdar * distribution. 212654012fSReza Sabdar * 222654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 232654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 242654012fSReza Sabdar * products derived from this software without specific prior written 252654012fSReza Sabdar * permission. 262654012fSReza Sabdar * 272654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 282654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 292654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 302654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 312654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 322654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 332654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 342654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 352654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 362654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 372654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 382654012fSReza Sabdar */ 392654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 402654012fSReza Sabdar 412654012fSReza Sabdar #include <errno.h> 422654012fSReza Sabdar #include <signal.h> 432654012fSReza Sabdar #include <libgen.h> 442654012fSReza Sabdar #include <libscf.h> 452654012fSReza Sabdar #include <libintl.h> 462654012fSReza Sabdar #include <sys/wait.h> 472654012fSReza Sabdar #include <zone.h> 482654012fSReza Sabdar #include <tsol/label.h> 492654012fSReza Sabdar #include <dlfcn.h> 502654012fSReza Sabdar #include "ndmpd.h" 512654012fSReza Sabdar #include "ndmpd_common.h" 522654012fSReza Sabdar 532654012fSReza Sabdar /* zfs library handle & mutex */ 542654012fSReza Sabdar libzfs_handle_t *zlibh; 552654012fSReza Sabdar mutex_t zlib_mtx; 562654012fSReza Sabdar void *mod_plp; 572654012fSReza Sabdar 582654012fSReza Sabdar static void ndmpd_sig_handler(int sig); 592654012fSReza Sabdar 602654012fSReza Sabdar typedef struct ndmpd { 612654012fSReza Sabdar int s_shutdown_flag; /* Fields for shutdown control */ 622654012fSReza Sabdar int s_sigval; 632654012fSReza Sabdar } ndmpd_t; 642654012fSReza Sabdar 652654012fSReza Sabdar ndmpd_t ndmpd; 662654012fSReza Sabdar 672654012fSReza Sabdar 682654012fSReza Sabdar /* 692654012fSReza Sabdar * Load and initialize the plug-in module 702654012fSReza Sabdar */ 712654012fSReza Sabdar static int 722654012fSReza Sabdar mod_init() 732654012fSReza Sabdar { 742654012fSReza Sabdar char *plname; 752654012fSReza Sabdar ndmp_plugin_t *(*plugin_init)(int); 762654012fSReza Sabdar 772654012fSReza Sabdar ndmp_pl = NULL; 78*faac71c0SJan Kryl 79*faac71c0SJan Kryl plname = ndmpd_get_prop(NDMP_PLUGIN_PATH); 80*faac71c0SJan Kryl if (plname == NULL || *plname == '\0') 812654012fSReza Sabdar return (0); 822654012fSReza Sabdar 832654012fSReza Sabdar if ((mod_plp = dlopen(plname, RTLD_LOCAL | RTLD_NOW)) == NULL) { 84*faac71c0SJan Kryl NDMP_LOG(LOG_ERR, "Error loading the plug-in %s: %s", 85*faac71c0SJan Kryl plname, dlerror()); 862654012fSReza Sabdar return (0); 872654012fSReza Sabdar } 882654012fSReza Sabdar 892654012fSReza Sabdar plugin_init = (ndmp_plugin_t *(*)(int))dlsym(mod_plp, "_ndmp_init"); 902654012fSReza Sabdar if (plugin_init == NULL) { 912654012fSReza Sabdar (void) dlclose(mod_plp); 922654012fSReza Sabdar return (0); 932654012fSReza Sabdar } 942654012fSReza Sabdar if ((ndmp_pl = plugin_init(NDMP_PLUGIN_VERSION)) == NULL) { 95*faac71c0SJan Kryl NDMP_LOG(LOG_ERR, "Error loading the plug-in %s", plname); 962654012fSReza Sabdar return (-1); 972654012fSReza Sabdar } 982654012fSReza Sabdar return (0); 992654012fSReza Sabdar } 1002654012fSReza Sabdar 1012654012fSReza Sabdar /* 1022654012fSReza Sabdar * Unload 1032654012fSReza Sabdar */ 1042654012fSReza Sabdar static void 1052654012fSReza Sabdar mod_fini() 1062654012fSReza Sabdar { 1072654012fSReza Sabdar if (ndmp_pl == NULL) 1082654012fSReza Sabdar return; 1092654012fSReza Sabdar 1102654012fSReza Sabdar void (*plugin_fini)(ndmp_plugin_t *); 1112654012fSReza Sabdar 1122654012fSReza Sabdar plugin_fini = (void (*)(ndmp_plugin_t *))dlsym(mod_plp, "_ndmp_fini"); 1132654012fSReza Sabdar if (plugin_fini == NULL) { 1142654012fSReza Sabdar (void) dlclose(mod_plp); 1152654012fSReza Sabdar return; 1162654012fSReza Sabdar } 1172654012fSReza Sabdar plugin_fini(ndmp_pl); 1182654012fSReza Sabdar (void) dlclose(mod_plp); 1192654012fSReza Sabdar } 1202654012fSReza Sabdar 1212654012fSReza Sabdar static void 122*faac71c0SJan Kryl set_privileges(void) 1232654012fSReza Sabdar { 124634e26ecSCasper H.S. Dik priv_set_t *pset = priv_allocset(); 1252654012fSReza Sabdar 1262654012fSReza Sabdar /* 1272654012fSReza Sabdar * Set effective sets privileges to 'least' required. If fails, send 1282654012fSReza Sabdar * error messages to log file and proceed. 1292654012fSReza Sabdar */ 130634e26ecSCasper H.S. Dik if (pset != NULL) { 131634e26ecSCasper H.S. Dik priv_basicset(pset); 132634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_PROC_AUDIT); 133634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_PROC_SETID); 134634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_PROC_OWNER); 135634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_FILE_CHOWN); 136634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_FILE_CHOWN_SELF); 137634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_FILE_DAC_READ); 138634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_FILE_DAC_SEARCH); 139634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_FILE_DAC_WRITE); 140634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_FILE_OWNER); 141634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_FILE_SETID); 142634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_SYS_LINKDIR); 143634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_SYS_DEVICES); 144634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_SYS_MOUNT); 145634e26ecSCasper H.S. Dik (void) priv_addset(pset, PRIV_SYS_CONFIG); 146634e26ecSCasper H.S. Dik } 147634e26ecSCasper H.S. Dik 148634e26ecSCasper H.S. Dik if (pset == NULL || setppriv(PRIV_SET, PRIV_EFFECTIVE, pset) != 0) { 149*faac71c0SJan Kryl (void) fprintf(stderr, 150*faac71c0SJan Kryl "Failed to set least required privileges to the service\n"); 151634e26ecSCasper H.S. Dik } 152634e26ecSCasper H.S. Dik priv_freeset(pset); 153*faac71c0SJan Kryl } 154*faac71c0SJan Kryl 155*faac71c0SJan Kryl static void 156*faac71c0SJan Kryl daemonize_init(void) 157*faac71c0SJan Kryl { 158*faac71c0SJan Kryl sigset_t set, oset; 159*faac71c0SJan Kryl pid_t pid; 1602654012fSReza Sabdar 1612654012fSReza Sabdar /* 1622654012fSReza Sabdar * Block all signals prior to the fork and leave them blocked in the 1632654012fSReza Sabdar * parent so we don't get in a situation where the parent gets SIGINT 1642654012fSReza Sabdar * and returns non-zero exit status and the child is actually running. 1652654012fSReza Sabdar * In the child, restore the signal mask once we've done our setsid(). 1662654012fSReza Sabdar */ 1672654012fSReza Sabdar (void) sigfillset(&set); 1682654012fSReza Sabdar (void) sigdelset(&set, SIGABRT); 1692654012fSReza Sabdar (void) sigprocmask(SIG_BLOCK, &set, &oset); 1702654012fSReza Sabdar 1712654012fSReza Sabdar if ((pid = fork()) == -1) { 172*faac71c0SJan Kryl (void) fprintf(stderr, 173*faac71c0SJan Kryl "Failed to start process in background.\n"); 1742654012fSReza Sabdar exit(SMF_EXIT_ERR_CONFIG); 1752654012fSReza Sabdar } 1762654012fSReza Sabdar 1772654012fSReza Sabdar /* If we're the parent process, exit. */ 1782654012fSReza Sabdar if (pid != 0) { 1792654012fSReza Sabdar _exit(0); 1802654012fSReza Sabdar } 1812654012fSReza Sabdar (void) setsid(); 1822654012fSReza Sabdar (void) sigprocmask(SIG_SETMASK, &oset, NULL); 1832654012fSReza Sabdar (void) chdir("/"); 1842654012fSReza Sabdar } 1852654012fSReza Sabdar 1862654012fSReza Sabdar /* 1872654012fSReza Sabdar * main 1882654012fSReza Sabdar * 1892654012fSReza Sabdar * The main NDMP daemon function 1902654012fSReza Sabdar * 1912654012fSReza Sabdar * Parameters: 1922654012fSReza Sabdar * argc (input) - the argument count 1932654012fSReza Sabdar * argv (input) - command line options 1942654012fSReza Sabdar * 1952654012fSReza Sabdar * Returns: 1962654012fSReza Sabdar * 0 1972654012fSReza Sabdar */ 1982654012fSReza Sabdar int 1992654012fSReza Sabdar main(int argc, char *argv[]) 2002654012fSReza Sabdar { 2012654012fSReza Sabdar struct sigaction act; 2022654012fSReza Sabdar sigset_t set; 203*faac71c0SJan Kryl char c; 204*faac71c0SJan Kryl void *arg = NULL; 205*faac71c0SJan Kryl boolean_t run_in_foreground = B_FALSE; 206*faac71c0SJan Kryl boolean_t override_debug = B_FALSE; 2072654012fSReza Sabdar 2082654012fSReza Sabdar /* 2092654012fSReza Sabdar * Check for existing ndmpd door server (make sure ndmpd is not already 2102654012fSReza Sabdar * running) 2112654012fSReza Sabdar */ 2122654012fSReza Sabdar if (ndmp_door_check()) { 2132654012fSReza Sabdar /* ndmpd is already running, exit. */ 214*faac71c0SJan Kryl (void) fprintf(stderr, "ndmpd is already running.\n"); 2152654012fSReza Sabdar return (0); 2162654012fSReza Sabdar } 2172654012fSReza Sabdar 2182654012fSReza Sabdar /* Global zone check */ 2192654012fSReza Sabdar if (getzoneid() != GLOBAL_ZONEID) { 220*faac71c0SJan Kryl (void) fprintf(stderr, "Non-global zone not supported.\n"); 2212654012fSReza Sabdar exit(SMF_EXIT_ERR_FATAL); 2222654012fSReza Sabdar } 2232654012fSReza Sabdar 2242654012fSReza Sabdar /* Trusted Solaris check */ 2252654012fSReza Sabdar if (is_system_labeled()) { 226*faac71c0SJan Kryl (void) fprintf(stderr, "Trusted Solaris not supported.\n"); 2272654012fSReza Sabdar exit(SMF_EXIT_ERR_FATAL); 2282654012fSReza Sabdar } 2292654012fSReza Sabdar 230*faac71c0SJan Kryl /* load SMF configuration */ 231*faac71c0SJan Kryl if (ndmpd_load_prop()) { 232*faac71c0SJan Kryl (void) fprintf(stderr, 233*faac71c0SJan Kryl "SMF properties initialization failed.\n"); 2342654012fSReza Sabdar exit(SMF_EXIT_ERR_CONFIG); 2352654012fSReza Sabdar } 2362654012fSReza Sabdar 237*faac71c0SJan Kryl opterr = 0; 238*faac71c0SJan Kryl while ((c = getopt(argc, argv, "df")) != -1) { 239*faac71c0SJan Kryl switch (c) { 240*faac71c0SJan Kryl case 'd': 241*faac71c0SJan Kryl override_debug = B_TRUE; 242*faac71c0SJan Kryl break; 243*faac71c0SJan Kryl case 'f': 244*faac71c0SJan Kryl run_in_foreground = B_TRUE; 245*faac71c0SJan Kryl break; 246*faac71c0SJan Kryl default: 247*faac71c0SJan Kryl (void) fprintf(stderr, "%s: Invalid option -%c.\n", 248*faac71c0SJan Kryl argv[0], optopt); 249*faac71c0SJan Kryl (void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]); 250*faac71c0SJan Kryl exit(SMF_EXIT_ERR_CONFIG); 2512654012fSReza Sabdar } 252*faac71c0SJan Kryl } 2532654012fSReza Sabdar 2542654012fSReza Sabdar /* set up signal handler */ 2552654012fSReza Sabdar (void) sigfillset(&set); 2562654012fSReza Sabdar (void) sigdelset(&set, SIGABRT); /* always unblocked for ASSERT() */ 2572654012fSReza Sabdar (void) sigfillset(&act.sa_mask); 2582654012fSReza Sabdar act.sa_handler = ndmpd_sig_handler; 2592654012fSReza Sabdar act.sa_flags = 0; 2602654012fSReza Sabdar 2612654012fSReza Sabdar (void) sigaction(SIGTERM, &act, NULL); 2622654012fSReza Sabdar (void) sigaction(SIGHUP, &act, NULL); 2632654012fSReza Sabdar (void) sigaction(SIGINT, &act, NULL); 2642654012fSReza Sabdar (void) sigaction(SIGUSR1, &act, NULL); 265c211fc47SReza Sabdar (void) sigaction(SIGPIPE, &act, NULL); 2662654012fSReza Sabdar (void) sigdelset(&set, SIGTERM); 2672654012fSReza Sabdar (void) sigdelset(&set, SIGHUP); 2682654012fSReza Sabdar (void) sigdelset(&set, SIGINT); 2692654012fSReza Sabdar (void) sigdelset(&set, SIGUSR1); 270c211fc47SReza Sabdar (void) sigdelset(&set, SIGPIPE); 2712654012fSReza Sabdar 272*faac71c0SJan Kryl set_privileges(); 273*faac71c0SJan Kryl (void) umask(077); 2742654012fSReza Sabdar openlog(argv[0], LOG_PID | LOG_NDELAY, LOG_DAEMON); 275*faac71c0SJan Kryl 276*faac71c0SJan Kryl /* 277*faac71c0SJan Kryl * Open log file before we detach from terminal in case that open 278*faac71c0SJan Kryl * fails and error message is printed to stderr. 279*faac71c0SJan Kryl */ 280*faac71c0SJan Kryl if (ndmp_log_open_file(run_in_foreground, override_debug) != 0) 281*faac71c0SJan Kryl exit(SMF_EXIT_ERR_FATAL); 282*faac71c0SJan Kryl 283*faac71c0SJan Kryl if (!run_in_foreground) 284*faac71c0SJan Kryl daemonize_init(); 285*faac71c0SJan Kryl 2868c4f9701SJanice Chang (void) mutex_init(&ndmpd_zfs_fd_lock, 0, NULL); 2872654012fSReza Sabdar 2882654012fSReza Sabdar if (mod_init() != 0) { 289*faac71c0SJan Kryl NDMP_LOG(LOG_ERR, "Failed to load the plugin module."); 2902654012fSReza Sabdar exit(SMF_EXIT_ERR_CONFIG); 2912654012fSReza Sabdar } 2922654012fSReza Sabdar 2932654012fSReza Sabdar /* libzfs init */ 2942654012fSReza Sabdar if ((zlibh = libzfs_init()) == NULL) { 295*faac71c0SJan Kryl NDMP_LOG(LOG_ERR, "Failed to initialize ZFS library."); 2962654012fSReza Sabdar exit(SMF_EXIT_ERR_CONFIG); 2972654012fSReza Sabdar } 2982654012fSReza Sabdar 2992654012fSReza Sabdar /* initialize and start the door server */ 3002654012fSReza Sabdar if (ndmp_door_init()) { 301*faac71c0SJan Kryl NDMP_LOG(LOG_ERR, "Can not start ndmpd door server."); 3022654012fSReza Sabdar exit(SMF_EXIT_ERR_CONFIG); 3032654012fSReza Sabdar } 3042654012fSReza Sabdar 3051e05b03fSJanice Chang if (tlm_init() == -1) { 306*faac71c0SJan Kryl NDMP_LOG(LOG_ERR, "Failed to initialize tape manager."); 3071e05b03fSJanice Chang exit(SMF_EXIT_ERR_CONFIG); 3081e05b03fSJanice Chang } 3092654012fSReza Sabdar 3102654012fSReza Sabdar /* 3112654012fSReza Sabdar * Prior to this point, we are single-threaded. We will be 3122654012fSReza Sabdar * multi-threaded from this point on. 3132654012fSReza Sabdar */ 3142654012fSReza Sabdar (void) pthread_create(NULL, NULL, (funct_t)ndmpd_main, 3152654012fSReza Sabdar (void *)&arg); 3162654012fSReza Sabdar 3172654012fSReza Sabdar while (!ndmpd.s_shutdown_flag) { 3182654012fSReza Sabdar (void) sigsuspend(&set); 3192654012fSReza Sabdar 3202654012fSReza Sabdar switch (ndmpd.s_sigval) { 3212654012fSReza Sabdar case 0: 3222654012fSReza Sabdar break; 3232654012fSReza Sabdar 324c211fc47SReza Sabdar case SIGPIPE: 325c211fc47SReza Sabdar break; 326c211fc47SReza Sabdar 3272654012fSReza Sabdar case SIGHUP: 3282654012fSReza Sabdar /* Refresh SMF properties */ 3292654012fSReza Sabdar if (ndmpd_load_prop()) 330*faac71c0SJan Kryl NDMP_LOG(LOG_ERR, 3312654012fSReza Sabdar "Service properties initialization " 3322654012fSReza Sabdar "failed."); 3332654012fSReza Sabdar break; 3342654012fSReza Sabdar 3352654012fSReza Sabdar default: 3362654012fSReza Sabdar /* 3372654012fSReza Sabdar * Typically SIGINT or SIGTERM. 3382654012fSReza Sabdar */ 3392654012fSReza Sabdar ndmpd.s_shutdown_flag = 1; 3402654012fSReza Sabdar break; 3412654012fSReza Sabdar } 3422654012fSReza Sabdar 3432654012fSReza Sabdar ndmpd.s_sigval = 0; 3442654012fSReza Sabdar } 3452654012fSReza Sabdar 3468c4f9701SJanice Chang (void) mutex_destroy(&ndmpd_zfs_fd_lock); 3472654012fSReza Sabdar libzfs_fini(zlibh); 3482654012fSReza Sabdar mod_fini(); 3492654012fSReza Sabdar ndmp_door_fini(); 350*faac71c0SJan Kryl ndmp_log_close_file(); 351*faac71c0SJan Kryl 3522654012fSReza Sabdar return (SMF_EXIT_OK); 3532654012fSReza Sabdar } 3542654012fSReza Sabdar 3552654012fSReza Sabdar static void 3562654012fSReza Sabdar ndmpd_sig_handler(int sig) 3572654012fSReza Sabdar { 3582654012fSReza Sabdar if (ndmpd.s_sigval == 0) 3592654012fSReza Sabdar ndmpd.s_sigval = sig; 3602654012fSReza Sabdar } 3612654012fSReza Sabdar 3622654012fSReza Sabdar /* 3632654012fSReza Sabdar * Enable libumem debugging by default on DEBUG builds. 3642654012fSReza Sabdar */ 3652654012fSReza Sabdar #ifdef DEBUG 3662654012fSReza Sabdar const char * 3672654012fSReza Sabdar _umem_debug_init(void) 3682654012fSReza Sabdar { 3692654012fSReza Sabdar return ("default,verbose"); /* $UMEM_DEBUG setting */ 3702654012fSReza Sabdar } 3712654012fSReza Sabdar 3722654012fSReza Sabdar const char * 3732654012fSReza Sabdar _umem_logging_init(void) 3742654012fSReza Sabdar { 3752654012fSReza Sabdar return ("fail,contents"); /* $UMEM_LOGGING setting */ 3762654012fSReza Sabdar } 3772654012fSReza Sabdar #endif 378