1 /*
   2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
   4  */
   5 
   6 /*
   7  * BSD 3 Clause License
   8  *
   9  * Copyright (c) 2007, The Storage Networking Industry Association.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  *      - Redistributions of source code must retain the above copyright
  15  *        notice, this list of conditions and the following disclaimer.
  16  *
  17  *      - Redistributions in binary form must reproduce the above copyright
  18  *        notice, this list of conditions and the following disclaimer in
  19  *        the documentation and/or other materials provided with the
  20  *        distribution.
  21  *
  22  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  23  *        nor the names of its contributors may be used to endorse or promote
  24  *        products derived from this software without specific prior written
  25  *        permission.
  26  *
  27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37  * POSSIBILITY OF SUCH DAMAGE.
  38  */
  39 
  40 /*
  41  * NDMP configuration management
  42  */
  43 #include <stdio.h>
  44 #include <stdlib.h>
  45 #include <synch.h>
  46 #include <syslog.h>
  47 #include <strings.h>
  48 #include <ndmpd_prop.h>
  49 #include <libndmp.h>
  50 #include "ndmpd.h"
  51 
  52 typedef struct ndmpd_cfg_param {
  53         char            *sc_name;
  54         char            *sc_defval;
  55         char            *sc_value;
  56         uint32_t        sc_flags;
  57 } ndmpd_cfg_param_t;
  58 
  59 
  60 static int ndmpd_config_update(ndmpd_cfg_param_t *cfg, char *value);
  61 
  62 /*
  63  * IMPORTANT: any changes to the order of this table's entries
  64  * need to be reflected in the enum ndmpd_cfg_id_t.
  65  */
  66 ndmpd_cfg_param_t ndmpd_cfg_table[] =
  67 {
  68         {"dar-support",                 "",     0, NDMP_CF_NOTINIT},
  69         {"mover-nic",                   "",     0, NDMP_CF_NOTINIT},
  70         {"dump-pathnode",               "",     0, NDMP_CF_NOTINIT},
  71         {"tar-pathnode",                "",     0, NDMP_CF_NOTINIT},
  72         {"fh-inode",                    "",     0, NDMP_CF_NOTINIT},
  73         {"ignore-ctime",                "",     0, NDMP_CF_NOTINIT},
  74         {"include-lmtime",              "",     0, NDMP_CF_NOTINIT},
  75         {"token-maxseq",                "",     0, NDMP_CF_NOTINIT},
  76         {"version",                     "",     0, NDMP_CF_NOTINIT},
  77         {"restore-fullpath",            "",     0, NDMP_CF_NOTINIT},
  78         {"debug-path",                  "",     0, NDMP_CF_NOTINIT},
  79         {"plugin-path",                 "",     0, NDMP_CF_NOTINIT},
  80         {"socket-css",                  "",     0, NDMP_CF_NOTINIT},
  81         {"socket-crs",                  "",     0, NDMP_CF_NOTINIT},
  82         {"mover-recordsize",            "",     0, NDMP_CF_NOTINIT},
  83         {"restore-wildcard-enable",     "",     0, NDMP_CF_NOTINIT},
  84         {"cram-md5-username",           "",     0, NDMP_CF_NOTINIT},
  85         {"cram-md5-password",           "",     0, NDMP_CF_NOTINIT},
  86         {"cleartext-username",          "",     0, NDMP_CF_NOTINIT},
  87         {"cleartext-password",          "",     0, NDMP_CF_NOTINIT},
  88         {"tcp-port",                    "",     0, NDMP_CF_NOTINIT},
  89         {"backup-quarantine",           "",     0, NDMP_CF_NOTINIT},
  90         {"restore-quarantine",          "",     0, NDMP_CF_NOTINIT},
  91         {"overwrite-quarantine",        "",     0, NDMP_CF_NOTINIT},
  92         {"zfs-force-override",          "",     0, NDMP_CF_NOTINIT},
  93         {"drive-type",                  "",     0, NDMP_CF_NOTINIT},
  94         {"debug-mode",                  "",     0, NDMP_CF_NOTINIT},
  95         {"vendor-name",                 "",     0, NDMP_CF_NOTINIT},
  96         {"product-name",                "",     0, NDMP_CF_NOTINIT},
  97         {"autosync-support",            "",     0, NDMP_CF_NOTINIT},
  98         {"hpr-support",                 "",     0, NDMP_CF_NOTINIT},
  99 };
 100 
 101 /*
 102  * Loads all the NDMP configuration parameters and sets up the
 103  * config table.
 104  */
 105 int
 106 ndmpd_load_prop(void)
 107 {
 108         ndmpd_cfg_id_t id;
 109         ndmpd_cfg_param_t *cfg;
 110         char *value;
 111 
 112         for (id = 0; id < NDMP_MAXALL; id++) {
 113                 cfg = &ndmpd_cfg_table[id];
 114                 if ((ndmp_get_prop(cfg->sc_name, &value)) == -1) {
 115                         syslog(LOG_ERR, "%s %s",
 116                             cfg->sc_name, ndmp_strerror(ndmp_errno));
 117                         continue;
 118                 }
 119                 /*
 120                  * enval == 0 could mean two things, either the
 121                  * config param is not defined, or it has been
 122                  * removed. If the variable has already been defined
 123                  * and now enval is 0, it should be removed, otherwise
 124                  * we don't need to do anything in this case.
 125                  */
 126                 if ((cfg->sc_flags & NDMP_CF_DEFINED) || value) {
 127                         if (ndmpd_config_update(cfg, value)) {
 128                                 free(value);
 129                                 return (-1);
 130                         }
 131                 }
 132                 free(value);
 133         }
 134         return (0);
 135 }
 136 
 137 /*
 138  * ndmpd_config_update
 139  *
 140  * Updates the specified config param with the given value.
 141  * This function is called both on (re)load and set.
 142  */
 143 static int
 144 ndmpd_config_update(ndmpd_cfg_param_t *cfg, char *value)
 145 {
 146         char *curval;
 147         int rc = 0;
 148         int len;
 149 
 150         if (value) {
 151                 len = strlen(value);
 152                 if (cfg->sc_value) {
 153                         curval = realloc(cfg->sc_value, (len + 1));
 154                 } else {
 155                         curval = ndmp_malloc(len + 1);
 156                 }
 157 
 158                 if (curval) {
 159                         cfg->sc_value = curval;
 160                         (void) strcpy(cfg->sc_value, value);
 161                         cfg->sc_flags |= NDMP_CF_DEFINED;
 162                 } else {
 163                         syslog(LOG_ERR, "Out of memory.");
 164                         rc = -1;
 165                 }
 166         } else if (cfg->sc_value) {
 167                 free(cfg->sc_value);
 168                 cfg->sc_value = 0;
 169                 cfg->sc_flags &= ~NDMP_CF_DEFINED;
 170         }
 171 
 172         return (rc);
 173 }
 174 
 175 /*
 176  * Returns value of the specified config param.
 177  * The return value is a string pointer to the locally
 178  * allocated memory if the config param is defined
 179  * otherwise it would be NULL.
 180  */
 181 char *
 182 ndmpd_get_prop(ndmpd_cfg_id_t id)
 183 {
 184         char *env_val;
 185 
 186         if (id < NDMP_MAXALL) {
 187                 env_val = ndmpd_cfg_table[id].sc_value;
 188                 return (env_val);
 189         }
 190 
 191         return (0);
 192 }
 193 
 194 /*
 195  * Similar to ndmpd_get_prop except it will return dflt value
 196  * if env is not set.
 197  */
 198 char *
 199 ndmpd_get_prop_default(ndmpd_cfg_id_t id, char *dflt)
 200 {
 201         char *env;
 202 
 203         env = ndmpd_get_prop(id);
 204 
 205         if (env && *env != 0) {
 206                 return (env);
 207         } else {
 208                 return (dflt);
 209         }
 210 }
 211 
 212 /*
 213  * Returns the value of a yes/no config param.
 214  * Returns 1 is config is set to "yes", otherwise 0.
 215  */
 216 int
 217 ndmpd_get_prop_yorn(ndmpd_cfg_id_t id)
 218 {
 219         char *val;
 220 
 221         val = ndmpd_get_prop(id);
 222         if (val) {
 223                 if (strcasecmp(val, "yes") == 0)
 224                         return (1);
 225         }
 226 
 227         return (0);
 228 }