1 /*
   2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright 2014 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 };
  96 
  97 /*
  98  * Loads all the NDMP configuration parameters and sets up the
  99  * config table.
 100  */
 101 int
 102 ndmpd_load_prop(void)
 103 {
 104         ndmpd_cfg_id_t id;
 105         ndmpd_cfg_param_t *cfg;
 106         char *value;
 107 
 108         for (id = 0; id < NDMP_MAXALL; id++) {
 109                 cfg = &ndmpd_cfg_table[id];
 110                 if ((ndmp_get_prop(cfg->sc_name, &value)) == -1) {
 111                         syslog(LOG_DEBUG, "%s %s",
 112                             cfg->sc_name, ndmp_strerror(ndmp_errno));
 113                         continue;
 114                 }
 115                 /*
 116                  * enval == 0 could mean two things, either the
 117                  * config param is not defined, or it has been
 118                  * removed. If the variable has already been defined
 119                  * and now enval is 0, it should be removed, otherwise
 120                  * we don't need to do anything in this case.
 121                  */
 122                 if ((cfg->sc_flags & NDMP_CF_DEFINED) || value) {
 123                         if (ndmpd_config_update(cfg, value)) {
 124                                 free(value);
 125                                 return (-1);
 126                         }
 127                 }
 128                 free(value);
 129         }
 130         return (0);
 131 }
 132 
 133 /*
 134  * ndmpd_config_update
 135  *
 136  * Updates the specified config param with the given value.
 137  * This function is called both on (re)load and set.
 138  */
 139 static int
 140 ndmpd_config_update(ndmpd_cfg_param_t *cfg, char *value)
 141 {
 142         char *curval;
 143         int rc = 0;
 144         int len;
 145 
 146         if (value) {
 147                 len = strlen(value);
 148                 if (cfg->sc_value) {
 149                         curval = realloc(cfg->sc_value, (len + 1));
 150                 } else {
 151                         curval = ndmp_malloc(len + 1);
 152                 }
 153 
 154                 if (curval) {
 155                         cfg->sc_value = curval;
 156                         (void) strcpy(cfg->sc_value, value);
 157                         cfg->sc_flags |= NDMP_CF_DEFINED;
 158                 } else {
 159                         syslog(LOG_ERR, "Out of memory.");
 160                         rc = -1;
 161                 }
 162         } else if (cfg->sc_value) {
 163                 free(cfg->sc_value);
 164                 cfg->sc_value = 0;
 165                 cfg->sc_flags &= ~NDMP_CF_DEFINED;
 166         }
 167 
 168         return (rc);
 169 }
 170 
 171 /*
 172  * Returns value of the specified config param.
 173  * The return value is a string pointer to the locally
 174  * allocated memory if the config param is defined
 175  * otherwise it would be NULL.
 176  */
 177 char *
 178 ndmpd_get_prop(ndmpd_cfg_id_t id)
 179 {
 180         char *env_val;
 181 
 182         if (id < NDMP_MAXALL) {
 183                 env_val = ndmpd_cfg_table[id].sc_value;
 184                 return (env_val);
 185         }
 186 
 187         return (0);
 188 }
 189 
 190 /*
 191  * Similar to ndmpd_get_prop except it will return dflt value
 192  * if env is not set.
 193  */
 194 char *
 195 ndmpd_get_prop_default(ndmpd_cfg_id_t id, char *dflt)
 196 {
 197         char *env;
 198 
 199         env = ndmpd_get_prop(id);
 200 
 201         if (env && *env != 0) {
 202                 return (env);
 203         } else {
 204                 return (dflt);
 205         }
 206 }
 207 
 208 /*
 209  * Returns the value of a yes/no config param.
 210  * Returns 1 is config is set to "yes", otherwise 0.
 211  */
 212 int
 213 ndmpd_get_prop_yorn(ndmpd_cfg_id_t id)
 214 {
 215         char *val;
 216 
 217         val = ndmpd_get_prop(id);
 218         if (val) {
 219                 if (strcasecmp(val, "yes") == 0)
 220                         return (1);
 221         }
 222 
 223         return (0);
 224 }