net-snmp 5.7
default_store.c
00001 /*
00002  * default_store.c: storage space for defaults 
00003  */
00004 /* Portions of this file are subject to the following copyright(s).  See
00005  * the Net-SNMP's COPYING file for more details and other copyrights
00006  * that may apply:
00007  */
00008 /*
00009  * Portions of this file are copyrighted by:
00010  * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
00011  * Use is subject to license terms specified in the COPYING file
00012  * distributed with the Net-SNMP package.
00013  */
00128 #include <net-snmp/net-snmp-config.h>
00129 #include <net-snmp/net-snmp-features.h>
00130 #include <sys/types.h>
00131 #if HAVE_STDLIB_H
00132 #include <stdlib.h>
00133 #endif
00134 #if HAVE_NETINET_IN_H
00135 #include <netinet/in.h>
00136 #endif
00137 #if HAVE_STDLIB_H
00138 #include <stdlib.h>
00139 #endif
00140 #if HAVE_STRING_H
00141 #include <string.h>
00142 #else
00143 #include <strings.h>
00144 #endif
00145 
00146 #if HAVE_UNISTD_H
00147 #include <unistd.h>
00148 #endif
00149 #if HAVE_DMALLOC_H
00150 #include <dmalloc.h>
00151 #endif
00152 
00153 #include <net-snmp/types.h>
00154 #include <net-snmp/output_api.h>
00155 #include <net-snmp/config_api.h>
00156 #include <net-snmp/library/default_store.h>    /* for "internal" definitions */
00157 #include <net-snmp/utilities.h>
00158 
00159 #include <net-snmp/library/snmp_api.h>
00160 
00161 netsnmp_feature_child_of(default_store_all, libnetsnmp)
00162 
00163 netsnmp_feature_child_of(default_store_void, default_store_all)
00164 
00165 #ifndef NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID
00166 #endif /* NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID */
00167 
00168 
00169 static const char * stores [NETSNMP_DS_MAX_IDS] = { "LIB", "APP", "TOK" };
00170 
00171 typedef struct netsnmp_ds_read_config_s {
00172   u_char          type;
00173   char           *token;
00174   char           *ftype;
00175   int             storeid;
00176   int             which;
00177   struct netsnmp_ds_read_config_s *next;
00178 } netsnmp_ds_read_config;
00179 
00180 static netsnmp_ds_read_config *netsnmp_ds_configs = NULL;
00181 
00182 static int   netsnmp_ds_integers[NETSNMP_DS_MAX_IDS][NETSNMP_DS_MAX_SUBIDS];
00183 static char  netsnmp_ds_booleans[NETSNMP_DS_MAX_IDS][NETSNMP_DS_MAX_SUBIDS/8];
00184 static char *netsnmp_ds_strings[NETSNMP_DS_MAX_IDS][NETSNMP_DS_MAX_SUBIDS];
00185 #ifndef NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID
00186 static void *netsnmp_ds_voids[NETSNMP_DS_MAX_IDS][NETSNMP_DS_MAX_SUBIDS];
00187 #endif /* NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID */
00188 
00189 /*
00190  * Prototype definitions 
00191  */
00192 void            netsnmp_ds_handle_config(const char *token, char *line);
00193 
00207 int
00208 netsnmp_ds_set_boolean(int storeid, int which, int value)
00209 {
00210     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00211         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00212         return SNMPERR_GENERR;
00213     }
00214 
00215     DEBUGMSGTL(("netsnmp_ds_set_boolean", "Setting %s:%d = %d/%s\n",
00216                 stores[storeid], which, value, ((value) ? "True" : "False")));
00217 
00218     if (value > 0) {
00219         netsnmp_ds_booleans[storeid][which/8] |= (1 << (which % 8));
00220     } else {
00221         netsnmp_ds_booleans[storeid][which/8] &= (0xff7f >> (7 - (which % 8)));
00222     }
00223 
00224     return SNMPERR_SUCCESS;
00225 }
00226 
00227 int
00228 netsnmp_ds_toggle_boolean(int storeid, int which)
00229 {
00230     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00231         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00232         return SNMPERR_GENERR;
00233     }
00234 
00235     if ((netsnmp_ds_booleans[storeid][which/8] & (1 << (which % 8))) == 0) {
00236         netsnmp_ds_booleans[storeid][which/8] |= (1 << (which % 8));
00237     } else {
00238         netsnmp_ds_booleans[storeid][which/8] &= (0xff7f >> (7 - (which % 8)));
00239     }
00240 
00241     DEBUGMSGTL(("netsnmp_ds_toggle_boolean", "Setting %s:%d = %d/%s\n",
00242                 stores[storeid], which, netsnmp_ds_booleans[storeid][which/8],
00243                 ((netsnmp_ds_booleans[storeid][which/8]) ? "True" : "False")));
00244 
00245     return SNMPERR_SUCCESS;
00246 }
00247 
00248 int
00249 netsnmp_ds_get_boolean(int storeid, int which)
00250 {
00251     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00252         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00253         return SNMPERR_GENERR;
00254     }
00255 
00256     return (netsnmp_ds_booleans[storeid][which/8] & (1 << (which % 8))) ? 1:0;
00257 }
00258 
00259 int
00260 netsnmp_ds_set_int(int storeid, int which, int value)
00261 {
00262     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00263         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00264         return SNMPERR_GENERR;
00265     }
00266 
00267     DEBUGMSGTL(("netsnmp_ds_set_int", "Setting %s:%d = %d\n",
00268                 stores[storeid], which, value));
00269 
00270     netsnmp_ds_integers[storeid][which] = value;
00271     return SNMPERR_SUCCESS;
00272 }
00273 
00274 int
00275 netsnmp_ds_get_int(int storeid, int which)
00276 {
00277     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00278         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00279         return SNMPERR_GENERR;
00280     }
00281 
00282     return netsnmp_ds_integers[storeid][which];
00283 }
00284 
00285 int
00286 netsnmp_ds_set_string(int storeid, int which, const char *value)
00287 {
00288     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00289         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00290         return SNMPERR_GENERR;
00291     }
00292 
00293     DEBUGMSGTL(("netsnmp_ds_set_string", "Setting %s:%d = \"%s\"\n",
00294                 stores[storeid], which, (value ? value : "(null)")));
00295 
00296     /*
00297      * is some silly person is calling us with our own pointer?
00298      */
00299     if (netsnmp_ds_strings[storeid][which] == value)
00300         return SNMPERR_SUCCESS;
00301     
00302     if (netsnmp_ds_strings[storeid][which] != NULL) {
00303         free(netsnmp_ds_strings[storeid][which]);
00304         netsnmp_ds_strings[storeid][which] = NULL;
00305     }
00306 
00307     if (value) {
00308         netsnmp_ds_strings[storeid][which] = strdup(value);
00309     } else {
00310         netsnmp_ds_strings[storeid][which] = NULL;
00311     }
00312 
00313     return SNMPERR_SUCCESS;
00314 }
00315 
00316 char *
00317 netsnmp_ds_get_string(int storeid, int which)
00318 {
00319     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00320         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00321         return NULL;
00322     }
00323 
00324     return netsnmp_ds_strings[storeid][which];
00325 }
00326 
00327 #ifndef NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID
00328 int
00329 netsnmp_ds_set_void(int storeid, int which, void *value)
00330 {
00331     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00332         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00333         return SNMPERR_GENERR;
00334     }
00335 
00336     DEBUGMSGTL(("netsnmp_ds_set_void", "Setting %s:%d = %p\n",
00337                 stores[storeid], which, value));
00338 
00339     netsnmp_ds_voids[storeid][which] = value;
00340 
00341     return SNMPERR_SUCCESS;
00342 }
00343 
00344 void *
00345 netsnmp_ds_get_void(int storeid, int which)
00346 {
00347     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
00348         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
00349         return NULL;
00350     }
00351 
00352     return netsnmp_ds_voids[storeid][which];
00353 }
00354 #endif /* NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID */
00355 
00356 int
00357 netsnmp_ds_parse_boolean(char *line)
00358 {
00359     char           *value, *endptr;
00360     int             itmp;
00361     char           *st;
00362 
00363     value = strtok_r(line, " \t\n", &st);
00364     if (strcasecmp(value, "yes") == 0 || 
00365         strcasecmp(value, "true") == 0) {
00366         return 1;
00367     } else if (strcasecmp(value, "no") == 0 ||
00368                strcasecmp(value, "false") == 0) {
00369         return 0;
00370     } else {
00371         itmp = strtol(value, &endptr, 10);
00372         if (*endptr != 0 || itmp < 0 || itmp > 1) {
00373             config_perror("Should be yes|no|true|false|0|1");
00374             return -1;
00375         }
00376         return itmp;
00377     }
00378 }
00379 
00380 void
00381 netsnmp_ds_handle_config(const char *token, char *line)
00382 {
00383     netsnmp_ds_read_config *drsp;
00384     char            buf[SNMP_MAXBUF];
00385     char           *value, *endptr;
00386     int             itmp;
00387     char           *st;
00388 
00389     DEBUGMSGTL(("netsnmp_ds_handle_config", "handling %s\n", token));
00390 
00391     for (drsp = netsnmp_ds_configs;
00392          drsp != NULL && strcasecmp(token, drsp->token) != 0;
00393          drsp = drsp->next);
00394 
00395     if (drsp != NULL) {
00396         DEBUGMSGTL(("netsnmp_ds_handle_config",
00397                     "setting: token=%s, type=%d, id=%s, which=%d\n",
00398                     drsp->token, drsp->type, stores[drsp->storeid],
00399                     drsp->which));
00400 
00401         switch (drsp->type) {
00402         case ASN_BOOLEAN:
00403             itmp = netsnmp_ds_parse_boolean(line);
00404             if ( itmp != -1 )
00405                 netsnmp_ds_set_boolean(drsp->storeid, drsp->which, itmp);
00406             DEBUGMSGTL(("netsnmp_ds_handle_config", "bool: %d\n", itmp));
00407             break;
00408 
00409         case ASN_INTEGER:
00410             value = strtok_r(line, " \t\n", &st);
00411             itmp = strtol(value, &endptr, 10);
00412             if (*endptr != 0) {
00413                 config_perror("Bad integer value");
00414             } else {
00415                 netsnmp_ds_set_int(drsp->storeid, drsp->which, itmp);
00416             }
00417             DEBUGMSGTL(("netsnmp_ds_handle_config", "int: %d\n", itmp));
00418             break;
00419 
00420         case ASN_OCTET_STR:
00421             if (*line == '"') {
00422                 copy_nword(line, buf, sizeof(buf));
00423                 netsnmp_ds_set_string(drsp->storeid, drsp->which, buf);
00424             } else {
00425                 netsnmp_ds_set_string(drsp->storeid, drsp->which, line);
00426             }
00427             DEBUGMSGTL(("netsnmp_ds_handle_config", "string: %s\n", line));
00428             break;
00429 
00430         default:
00431             snmp_log(LOG_ERR, "netsnmp_ds_handle_config: type %d (0x%02x)\n",
00432                      drsp->type, drsp->type);
00433             break;
00434         }
00435     } else {
00436         snmp_log(LOG_ERR, "netsnmp_ds_handle_config: no registration for %s\n",
00437                  token);
00438     }
00439 }
00440 
00441 
00442 int
00443 netsnmp_ds_register_config(u_char type, const char *ftype, const char *token,
00444                            int storeid, int which)
00445 {
00446     netsnmp_ds_read_config *drsp;
00447 
00448     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS    || 
00449         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS || token == NULL) {
00450         return SNMPERR_GENERR;
00451     }
00452 
00453     if (netsnmp_ds_configs == NULL) {
00454         netsnmp_ds_configs = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
00455         if (netsnmp_ds_configs == NULL)
00456             return SNMPERR_GENERR;
00457         drsp = netsnmp_ds_configs;
00458     } else {
00459         for (drsp = netsnmp_ds_configs; drsp->next != NULL; drsp = drsp->next);
00460         drsp->next = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
00461         if (drsp->next == NULL)
00462             return SNMPERR_GENERR;
00463         drsp = drsp->next;
00464     }
00465 
00466     drsp->type    = type;
00467     drsp->ftype   = strdup(ftype);
00468     drsp->token   = strdup(token);
00469     drsp->storeid = storeid;
00470     drsp->which   = which;
00471 
00472     switch (type) {
00473     case ASN_BOOLEAN:
00474         register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
00475                                 "(1|yes|true|0|no|false)");
00476         break;
00477 
00478     case ASN_INTEGER:
00479         register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
00480                                 "integerValue");
00481         break;
00482 
00483     case ASN_OCTET_STR:
00484         register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
00485                                 "string");
00486         break;
00487 
00488     }
00489     return SNMPERR_SUCCESS;
00490 }
00491 
00492 int
00493 netsnmp_ds_register_premib(u_char type, const char *ftype, const char *token,
00494                            int storeid, int which)
00495 {
00496     netsnmp_ds_read_config *drsp;
00497 
00498     if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS    || 
00499         which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS || token == NULL) {
00500         return SNMPERR_GENERR;
00501     }
00502 
00503     if (netsnmp_ds_configs == NULL) {
00504         netsnmp_ds_configs = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
00505         if (netsnmp_ds_configs == NULL)
00506             return SNMPERR_GENERR;
00507         drsp = netsnmp_ds_configs;
00508     } else {
00509         for (drsp = netsnmp_ds_configs; drsp->next != NULL; drsp = drsp->next);
00510         drsp->next = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
00511         if (drsp->next == NULL)
00512             return SNMPERR_GENERR;
00513         drsp = drsp->next;
00514     }
00515 
00516     drsp->type    = type;
00517     drsp->ftype   = strdup(ftype);
00518     drsp->token   = strdup(token);
00519     drsp->storeid = storeid;
00520     drsp->which   = which;
00521 
00522     switch (type) {
00523     case ASN_BOOLEAN:
00524         register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
00525                                         NULL, "(1|yes|true|0|no|false)");
00526         break;
00527 
00528     case ASN_INTEGER:
00529         register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
00530                                         NULL, "integerValue");
00531         break;
00532 
00533     case ASN_OCTET_STR:
00534         register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
00535                                         NULL, "string");
00536         break;
00537 
00538     }
00539     return SNMPERR_SUCCESS;
00540 }
00541 
00542 void
00543 netsnmp_ds_shutdown(void)
00544 {
00545     netsnmp_ds_read_config *drsp;
00546     int             i, j;
00547 
00548     for (drsp = netsnmp_ds_configs; drsp; drsp = netsnmp_ds_configs) {
00549         netsnmp_ds_configs = drsp->next;
00550 
00551         if (drsp->ftype && drsp->token) {
00552             unregister_config_handler(drsp->ftype, drsp->token);
00553         }
00554         if (drsp->ftype != NULL) {
00555             free(drsp->ftype);
00556         }
00557         if (drsp->token != NULL) {
00558             free(drsp->token);
00559         }
00560         free(drsp);
00561     }
00562 
00563     for (i = 0; i < NETSNMP_DS_MAX_IDS; i++) {
00564         for (j = 0; j < NETSNMP_DS_MAX_SUBIDS; j++) {
00565             if (netsnmp_ds_strings[i][j] != NULL) {
00566                 free(netsnmp_ds_strings[i][j]);
00567                 netsnmp_ds_strings[i][j] = NULL;
00568             }
00569         }
00570     }
00571 }