Coverage Report

Created: 2026-09-01 08:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/snmplib/default_store.c
Line
Count
Source
1
/*
2
 * default_store.c: storage space for defaults 
3
 */
4
/* Portions of this file are subject to the following copyright(s).  See
5
 * the Net-SNMP's COPYING file for more details and other copyrights
6
 * that may apply:
7
 */
8
/*
9
 * Portions of this file are copyrighted by:
10
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
11
 * Use is subject to license terms specified in the COPYING file
12
 * distributed with the Net-SNMP package.
13
 */
14
/** @defgroup default_store storage space for defaults 
15
 *  @ingroup library
16
 *
17
       The purpose of the default storage is three-fold:
18
19
       1)     To create a global storage space without creating a
20
              whole  bunch  of globally accessible variables or a
21
              whole bunch of access functions to work  with  more
22
              privately restricted variables.
23
24
       2)     To provide a single location where the thread lock-
25
              ing needs to be implemented. At the  time  of  this
26
              writing,  however,  thread  locking  is  not yet in
27
              place.
28
29
       3)     To reduce the number of cross dependencies  between
30
              code  pieces that may or may not be linked together
31
              in the long run. This provides for a  single  loca-
32
              tion  in which configuration data, for example, can
33
              be stored for a separate section of code  that  may
34
              not be linked in to the application in question.
35
36
       The functions defined here implement these goals.
37
38
       Currently, three data types are supported: booleans, inte-
39
       gers, and strings. Each of these data types have  separate
40
       storage  spaces.  In  addition, the storage space for each
41
       data type is divided further  by  the  application  level.
42
       Currently,  there  are  two  storage  spaces. The first is
43
       reserved for  the  SNMP  library  itself.  The  second  is
44
       intended  for  use  in applications and is not modified or
45
       checked by the library, and, therefore, this is the  space
46
       usable by you.
47
           
48
       These definitions correspond with the "storid" argument to the API
49
       - \#define NETSNMP_DS_LIBRARY_ID     0
50
       - \#define NETSNMP_DS_APPLICATION_ID 1
51
       - \#define NETSNMP_DS_TOKEN_ID       2
52
53
       These definitions correspond with the "which" argument to the API,
54
       when the storeid argument is NETSNMP_DS_LIBRARY_ID
55
56
       library booleans
57
            
58
       - \#define NETSNMP_DS_LIB_MIB_ERRORS          0
59
       - \#define NETSNMP_DS_LIB_SAVE_MIB_DESCRS     1
60
       - \#define NETSNMP_DS_LIB_MIB_COMMENT_TERM    2
61
       - \#define NETSNMP_DS_LIB_MIB_PARSE_LABEL     3
62
       - \#define NETSNMP_DS_LIB_DUMP_PACKET         4
63
       - \#define NETSNMP_DS_LIB_LOG_TIMESTAMP       5
64
       - \#define NETSNMP_DS_LIB_DONT_READ_CONFIGS   6
65
       - \#define NETSNMP_DS_LIB_MIB_REPLACE         7 replace objects from latest module 
66
       - \#define NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM  8 print only numeric enum values
67
       - \#define NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS  9 print only numeric enum values 
68
       - \#define NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS 10 don't print oid indexes specially 
69
       - \#define NETSNMP_DS_LIB_ALARM_DONT_USE_SIG  11 don't use the alarm() signal 
70
       - \#define NETSNMP_DS_LIB_PRINT_FULL_OID      12 print fully qualified oids 
71
       - \#define NETSNMP_DS_LIB_QUICK_PRINT         13 print very brief output for parsing
72
       - \#define NETSNMP_DS_LIB_RANDOM_ACCESS       14 random access to oid labels
73
       - \#define NETSNMP_DS_LIB_REGEX_ACCESS        15 regex matching to oid labels
74
       - \#define NETSNMP_DS_LIB_DONT_CHECK_RANGE    16 don't check values for ranges on send
75
       - \#define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS   17 no warn about unknown config tokens
76
       - \#define NETSNMP_DS_LIB_NUMERIC_TIMETICKS   18 print timeticks as a number 
77
       - \#define NETSNMP_DS_LIB_ESCAPE_QUOTES       19 shell escape quote marks in oids
78
       - \#define NETSNMP_DS_LIB_REVERSE_ENCODE      20 encode packets from back to front
79
       - \#define NETSNMP_DS_LIB_PRINT_BARE_VALUE    21 just print value (not OID = value)
80
       - \#define NETSNMP_DS_LIB_EXTENDED_INDEX      22 print extended index format [x1][x2]
81
       - \#define NETSNMP_DS_LIB_PRINT_HEX_TEXT      23 print ASCII text along with hex strings
82
       - \#define NETSNMP_DS_LIB_PRINT_UCD_STYLE_OID 24 print OID's using the UCD-style prefix suppression
83
       - \#define NETSNMP_DS_LIB_READ_UCD_STYLE_OID  25 require top-level OIDs to be prefixed with a dot
84
       - \#define NETSNMP_DS_LIB_HAVE_READ_PREMIB_CONFIG 26 have the pre-mib parsing config tokens been processed
85
       - \#define NETSNMP_DS_LIB_HAVE_READ_CONFIG    27 have the config tokens been processed
86
       - \#define NETSNMP_DS_LIB_QUICKE_PRINT        28
87
       - \#define NETSNMP_DS_LIB_DONT_PRINT_UNITS    29 don't print UNITS suffix
88
       - \#define NETSNMP_DS_LIB_NO_DISPLAY_HINT     30 don't apply DISPLAY-HINTs
89
       - \#define NETSNMP_DS_LIB_16BIT_IDS           31 restrict requestIDs, etc to 16-bit values
90
       - \#define NETSNMP_DS_LIB_DONT_PERSIST_STATE  32 don't save/load any persistent state
91
       - \#define NETSNMP_DS_LIB_2DIGIT_HEX_OUTPUT   33 print a leading 0 on hex values <= 'f'
92
93
94
       library integers
95
96
       - \#define NETSNMP_DS_LIB_MIB_WARNINGS  0
97
       - \#define NETSNMP_DS_LIB_SECLEVEL      1
98
       - \#define NETSNMP_DS_LIB_SNMPVERSION   2
99
       - \#define NETSNMP_DS_LIB_DEFAULT_PORT  3
100
       - \#define NETSNMP_DS_LIB_OID_OUTPUT_FORMAT  4
101
       - \#define NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT 5
102
103
       library strings
104
105
       - \#define NETSNMP_DS_LIB_SECNAME           0
106
       - \#define NETSNMP_DS_LIB_CONTEXT           1
107
       - \#define NETSNMP_DS_LIB_PASSPHRASE        2
108
       - \#define NETSNMP_DS_LIB_AUTHPASSPHRASE    3
109
       - \#define NETSNMP_DS_LIB_PRIVPASSPHRASE    4
110
       - \#define NETSNMP_DS_LIB_OPTIONALCONFIG    5
111
       - \#define NETSNMP_DS_LIB_APPTYPE           6
112
       - \#define NETSNMP_DS_LIB_COMMUNITY         7
113
       - \#define NETSNMP_DS_LIB_PERSISTENT_DIR    8
114
       - \#define NETSNMP_DS_LIB_CONFIGURATION_DIR 9
115
       - \#define NETSNMP_DS_LIB_SECMODEL          10
116
       - \#define NETSNMP_DS_LIB_MIBDIRS           11
117
       - \#define NETSNMP_DS_LIB_OIDSUFFIX         12
118
       - \#define NETSNMP_DS_LIB_OIDPREFIX         13
119
       - \#define NETSNMP_DS_LIB_CLIENT_ADDR       14
120
       - \#define NETSNMP_DS_LIB_TEMP_FILE_PATTERN 15
121
       - \#define NETSNMP_DS_LIB_AUTHMASTERKEY     16
122
       - \#define NETSNMP_DS_LIB_PRIVMASTERKEY     17
123
       - \#define NETSNMP_DS_LIB_AUTHLOCALIZEDKEY  18
124
       - \#define NETSNMP_DS_LIB_PRIVLOCALIZEDKEY  19
125
126
 *  @{
127
 */
128
#include <net-snmp/net-snmp-config.h>
129
#include <net-snmp/net-snmp-features.h>
130
#include <sys/types.h>
131
#ifdef HAVE_STDLIB_H
132
#include <stdlib.h>
133
#endif
134
#ifdef HAVE_NETINET_IN_H
135
#include <netinet/in.h>
136
#endif
137
#ifdef HAVE_STDLIB_H
138
#include <stdlib.h>
139
#endif
140
#ifdef HAVE_STRING_H
141
#include <string.h>
142
#else
143
#include <strings.h>
144
#endif
145
146
#ifdef HAVE_UNISTD_H
147
#include <unistd.h>
148
#endif
149
150
#include <net-snmp/types.h>
151
#include <net-snmp/output_api.h>
152
#include <net-snmp/config_api.h>
153
#include <net-snmp/library/default_store.h>    /* for "internal" definitions */
154
#include <net-snmp/utilities.h>
155
156
#include <net-snmp/library/snmp_api.h>
157
158
netsnmp_feature_child_of(default_store_all, libnetsnmp);
159
160
netsnmp_feature_child_of(default_store_void, default_store_all);
161
162
#ifndef NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID
163
#endif /* NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID */
164
165
166
static const char * stores [NETSNMP_DS_MAX_IDS] = { "LIB", "APP", "TOK" };
167
168
typedef struct netsnmp_ds_read_config_s {
169
  u_char          type;
170
  char           *token;
171
  char           *ftype;
172
  int             storeid;
173
  int             which;
174
  struct netsnmp_ds_read_config_s *next;
175
} netsnmp_ds_read_config;
176
177
static netsnmp_ds_read_config *netsnmp_ds_configs = NULL;
178
179
static int   netsnmp_ds_integers[NETSNMP_DS_MAX_IDS][NETSNMP_DS_MAX_SUBIDS];
180
static char  netsnmp_ds_booleans[NETSNMP_DS_MAX_IDS][NETSNMP_DS_MAX_SUBIDS/8];
181
static char *netsnmp_ds_strings[NETSNMP_DS_MAX_IDS][NETSNMP_DS_MAX_SUBIDS];
182
#ifndef NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID
183
static void *netsnmp_ds_voids[NETSNMP_DS_MAX_IDS][NETSNMP_DS_MAX_SUBIDS];
184
#endif /* NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID */
185
186
/**
187
 * Stores "true" or "false" given an int value for value into
188
 * netsnmp_ds_booleans[store][which] slot.  
189
 *
190
 * @param storeid an index to the boolean storage container's first index(store)
191
 *
192
 * @param which an index to the boolean storage container's second index(which)
193
 *
194
 * @param value if > 0, "true" is set into the slot otherwise "false"
195
 *
196
 * @return Returns SNMPPERR_GENERR if the storeid and which parameters do not
197
 * correspond to a valid slot, or  SNMPERR_SUCCESS otherwise.
198
 */
199
int
200
netsnmp_ds_set_boolean(int storeid, int which, int value)
201
46.8k
{
202
46.8k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
203
43.5k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
204
3.64k
        return SNMPERR_GENERR;
205
3.64k
    }
206
207
43.1k
    DEBUGMSGTL(("netsnmp_ds_set_boolean", "Setting %s:%d = %d/%s\n",
208
43.1k
                stores[storeid], which, value, ((value) ? "True" : "False")));
209
210
43.1k
    if (value > 0) {
211
29.4k
        netsnmp_ds_booleans[storeid][which/8] |= (1 << (which % 8));
212
29.4k
    } else {
213
13.7k
        netsnmp_ds_booleans[storeid][which/8] &= (0xff7f >> (7 - (which % 8)));
214
13.7k
    }
215
216
43.1k
    return SNMPERR_SUCCESS;
217
46.8k
}
218
219
int
220
netsnmp_ds_toggle_boolean(int storeid, int which)
221
9.91k
{
222
9.91k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
223
9.91k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
224
0
        return SNMPERR_GENERR;
225
0
    }
226
227
9.91k
    if ((netsnmp_ds_booleans[storeid][which/8] & (1 << (which % 8))) == 0) {
228
4.96k
        netsnmp_ds_booleans[storeid][which/8] |= (1 << (which % 8));
229
4.96k
    } else {
230
4.95k
        netsnmp_ds_booleans[storeid][which/8] &= (0xff7f >> (7 - (which % 8)));
231
4.95k
    }
232
233
9.91k
    DEBUGMSGTL(("netsnmp_ds_toggle_boolean", "Setting %s:%d = %d/%s\n",
234
9.91k
                stores[storeid], which, netsnmp_ds_booleans[storeid][which/8],
235
9.91k
                ((netsnmp_ds_booleans[storeid][which/8]) ? "True" : "False")));
236
237
9.91k
    return SNMPERR_SUCCESS;
238
9.91k
}
239
240
int
241
netsnmp_ds_get_boolean(int storeid, int which)
242
5.58M
{
243
5.58M
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
244
5.58M
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
245
0
        return SNMPERR_GENERR;
246
0
    }
247
248
5.58M
    return (netsnmp_ds_booleans[storeid][which/8] & (1 << (which % 8))) ? 1:0;
249
5.58M
}
250
251
int
252
netsnmp_ds_set_int(int storeid, int which, int value)
253
23.5k
{
254
23.5k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
255
23.5k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
256
0
        return SNMPERR_GENERR;
257
0
    }
258
259
23.5k
    DEBUGMSGTL(("netsnmp_ds_set_int", "Setting %s:%d = %d\n",
260
23.5k
                stores[storeid], which, value));
261
262
23.5k
    netsnmp_ds_integers[storeid][which] = value;
263
23.5k
    return SNMPERR_SUCCESS;
264
23.5k
}
265
266
int
267
netsnmp_ds_get_int(int storeid, int which)
268
141k
{
269
141k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
270
141k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
271
0
        return SNMPERR_GENERR;
272
0
    }
273
274
141k
    return netsnmp_ds_integers[storeid][which];
275
141k
}
276
277
int
278
netsnmp_ds_set_string(int storeid, int which, const char *value)
279
25.7k
{
280
25.7k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
281
25.7k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
282
0
        return SNMPERR_GENERR;
283
0
    }
284
285
25.7k
    DEBUGMSGTL(("netsnmp_ds_set_string", "Setting %s:%d = \"%s\"\n",
286
25.7k
                stores[storeid], which, (value ? value : "(null)")));
287
288
    /*
289
     * is some silly person is calling us with our own pointer?
290
     */
291
25.7k
    if (netsnmp_ds_strings[storeid][which] == value)
292
6.75k
        return SNMPERR_SUCCESS;
293
294
19.0k
    snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
295
19.0k
    if (netsnmp_ds_strings[storeid][which] != NULL) {
296
5.40k
        free(netsnmp_ds_strings[storeid][which]);
297
5.40k
  netsnmp_ds_strings[storeid][which] = NULL;
298
5.40k
    }
299
19.0k
    snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
300
301
19.0k
    if (value) {
302
19.0k
        netsnmp_ds_strings[storeid][which] = strdup(value);
303
19.0k
    } else {
304
0
        netsnmp_ds_strings[storeid][which] = NULL;
305
0
    }
306
307
19.0k
    return SNMPERR_SUCCESS;
308
25.7k
}
309
310
char *
311
netsnmp_ds_get_string(int storeid, int which)
312
601k
{
313
601k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
314
601k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
315
0
        return NULL;
316
0
    }
317
318
601k
    return netsnmp_ds_strings[storeid][which];
319
601k
}
320
321
#ifndef NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID
322
int
323
netsnmp_ds_set_void(int storeid, int which, void *value)
324
0
{
325
0
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
326
0
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
327
0
        return SNMPERR_GENERR;
328
0
    }
329
330
0
    DEBUGMSGTL(("netsnmp_ds_set_void", "Setting %s:%d = %p\n",
331
0
                stores[storeid], which, value));
332
333
0
    netsnmp_ds_voids[storeid][which] = value;
334
335
0
    return SNMPERR_SUCCESS;
336
0
}
337
338
void *
339
netsnmp_ds_get_void(int storeid, int which)
340
0
{
341
0
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
342
0
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
343
0
        return NULL;
344
0
    }
345
346
0
    return netsnmp_ds_voids[storeid][which];
347
0
}
348
#endif /* NETSNMP_FEATURE_REMOVE_DEFAULT_STORE_VOID */
349
350
int
351
netsnmp_ds_parse_boolean(char *line)
352
339
{
353
339
    char           *value, *endptr;
354
339
    int             itmp;
355
339
    char           *st;
356
357
339
    value = strtok_r(line, " \t\n", &st);
358
339
    if (!value)
359
37
        goto invalid;
360
302
    if (strcasecmp(value, "yes") == 0 || 
361
280
  strcasecmp(value, "true") == 0) {
362
23
        return 1;
363
279
    } else if (strcasecmp(value, "no") == 0 ||
364
265
         strcasecmp(value, "false") == 0) {
365
35
        return 0;
366
244
    } else {
367
244
        itmp = strtol(value, &endptr, 10);
368
244
        if (*endptr != 0 || itmp < 0 || itmp > 1)
369
231
            goto invalid;
370
13
        return itmp;
371
244
    }
372
373
268
invalid:
374
268
    config_perror("Should be yes|no|true|false|0|1");
375
268
    return -1;
376
302
}
377
378
void
379
netsnmp_ds_handle_config(const char *token, char *line)
380
540
{
381
540
    netsnmp_ds_read_config *drsp;
382
540
    char            buf[SNMP_MAXBUF];
383
540
    char           *value, *endptr;
384
540
    int             itmp;
385
540
    char           *st;
386
387
540
    DEBUGMSGTL(("netsnmp_ds_handle_config", "handling %s\n", token));
388
389
540
    for (drsp = netsnmp_ds_configs;
390
24.3k
         drsp != NULL && strcasecmp(token, drsp->token) != 0;
391
23.8k
         drsp = drsp->next);
392
393
540
    if (drsp != NULL) {
394
540
        DEBUGMSGTL(("netsnmp_ds_handle_config",
395
540
                    "setting: token=%s, type=%d, id=%s, which=%d\n",
396
540
                    drsp->token, drsp->type, stores[drsp->storeid],
397
540
                    drsp->which));
398
399
540
        switch (drsp->type) {
400
339
        case ASN_BOOLEAN:
401
339
            itmp = netsnmp_ds_parse_boolean(line);
402
339
            if ( itmp != -1 )
403
71
                netsnmp_ds_set_boolean(drsp->storeid, drsp->which, itmp);
404
339
            DEBUGMSGTL(("netsnmp_ds_handle_config", "bool: %d\n", itmp));
405
339
            break;
406
407
105
        case ASN_INTEGER:
408
105
            value = strtok_r(line, " \t\n", &st);
409
105
            if (!value) {
410
19
                config_perror("Missing value");
411
86
            } else {
412
86
                itmp = strtol(value, &endptr, 10);
413
86
                if (*endptr != 0) {
414
60
                    config_perror("Bad integer value");
415
60
                } else {
416
26
                    netsnmp_ds_set_int(drsp->storeid, drsp->which, itmp);
417
26
                }
418
86
                DEBUGMSGTL(("netsnmp_ds_handle_config", "int: %d\n", itmp));
419
86
            }
420
105
            break;
421
422
96
        case ASN_OCTET_STR:
423
96
            if (*line == '"') {
424
37
                copy_nword(line, buf, sizeof(buf));
425
37
                netsnmp_ds_set_string(drsp->storeid, drsp->which, buf);
426
59
            } else {
427
59
                netsnmp_ds_set_string(drsp->storeid, drsp->which, line);
428
59
            }
429
96
            DEBUGMSGTL(("netsnmp_ds_handle_config", "string: %s\n", line));
430
96
            break;
431
432
0
        default:
433
0
            snmp_log(LOG_ERR, "netsnmp_ds_handle_config: type %d (0x%02x)\n",
434
0
                     drsp->type, drsp->type);
435
0
            break;
436
540
        }
437
540
    } else {
438
0
        snmp_log(LOG_ERR, "netsnmp_ds_handle_config: no registration for %s\n",
439
0
                 token);
440
0
    }
441
540
}
442
443
444
int
445
netsnmp_ds_register_config(u_char type, const char *ftype, const char *token,
446
         int storeid, int which)
447
182k
{
448
182k
    netsnmp_ds_read_config *drsp;
449
450
182k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS    || 
451
182k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS || token == NULL) {
452
0
        return SNMPERR_GENERR;
453
0
    }
454
455
182k
    if (netsnmp_ds_configs == NULL) {
456
3.40k
        netsnmp_ds_configs = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
457
3.40k
        if (netsnmp_ds_configs == NULL)
458
0
            return SNMPERR_GENERR;
459
3.40k
        drsp = netsnmp_ds_configs;
460
179k
    } else {
461
26.0M
        for (drsp = netsnmp_ds_configs; drsp->next != NULL; drsp = drsp->next);
462
179k
        drsp->next = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
463
179k
        if (drsp->next == NULL)
464
0
            return SNMPERR_GENERR;
465
179k
        drsp = drsp->next;
466
179k
    }
467
468
182k
    drsp->type    = type;
469
182k
    drsp->ftype   = strdup(ftype);
470
182k
    drsp->token   = strdup(token);
471
182k
    drsp->storeid = storeid;
472
182k
    drsp->which   = which;
473
474
182k
    switch (type) {
475
55.0k
    case ASN_BOOLEAN:
476
55.0k
        register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
477
55.0k
                                "(1|yes|true|0|no|false)");
478
55.0k
        break;
479
480
43.9k
    case ASN_INTEGER:
481
43.9k
        register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
482
43.9k
                                "integerValue");
483
43.9k
        break;
484
485
83.6k
    case ASN_OCTET_STR:
486
83.6k
        register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
487
83.6k
                                "string");
488
83.6k
        break;
489
490
182k
    }
491
182k
    return SNMPERR_SUCCESS;
492
182k
}
493
494
int
495
netsnmp_ds_register_premib(u_char type, const char *ftype, const char *token,
496
         int storeid, int which)
497
109k
{
498
109k
    netsnmp_ds_read_config *drsp;
499
500
109k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS    || 
501
109k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS || token == NULL) {
502
0
        return SNMPERR_GENERR;
503
0
    }
504
505
109k
    if (netsnmp_ds_configs == NULL) {
506
1
        netsnmp_ds_configs = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
507
1
        if (netsnmp_ds_configs == NULL)
508
0
            return SNMPERR_GENERR;
509
1
        drsp = netsnmp_ds_configs;
510
109k
    } else {
511
291M
        for (drsp = netsnmp_ds_configs; drsp->next != NULL; drsp = drsp->next);
512
109k
        drsp->next = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
513
109k
        if (drsp->next == NULL)
514
0
            return SNMPERR_GENERR;
515
109k
        drsp = drsp->next;
516
109k
    }
517
518
109k
    drsp->type    = type;
519
109k
    drsp->ftype   = strdup(ftype);
520
109k
    drsp->token   = strdup(token);
521
109k
    drsp->storeid = storeid;
522
109k
    drsp->which   = which;
523
524
109k
    switch (type) {
525
76.6k
    case ASN_BOOLEAN:
526
76.6k
        register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
527
76.6k
                                        NULL, "(1|yes|true|0|no|false)");
528
76.6k
        break;
529
530
18.9k
    case ASN_INTEGER:
531
18.9k
        register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
532
18.9k
                                        NULL, "integerValue");
533
18.9k
        break;
534
535
13.5k
    case ASN_OCTET_STR:
536
13.5k
        register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
537
13.5k
                                        NULL, "string");
538
13.5k
        break;
539
540
109k
    }
541
109k
    return SNMPERR_SUCCESS;
542
109k
}
543
544
void
545
netsnmp_ds_shutdown(void)
546
3.40k
{
547
3.40k
    netsnmp_ds_read_config *drsp;
548
3.40k
    int             i, j;
549
550
3.40k
    snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
551
264k
    for (drsp = netsnmp_ds_configs; drsp; drsp = netsnmp_ds_configs) {
552
261k
        netsnmp_ds_configs = drsp->next;
553
554
261k
        if (drsp->ftype && drsp->token) {
555
261k
            unregister_config_handler(drsp->ftype, drsp->token);
556
261k
        }
557
261k
  if (drsp->ftype != NULL) {
558
261k
      free(drsp->ftype);
559
261k
  }
560
261k
  if (drsp->token != NULL) {
561
261k
      free(drsp->token);
562
261k
  }
563
261k
        free(drsp);
564
261k
    }
565
566
13.6k
    for (i = 0; i < NETSNMP_DS_MAX_IDS; i++) {
567
663k
        for (j = 0; j < NETSNMP_DS_MAX_SUBIDS; j++) {
568
653k
            if (netsnmp_ds_strings[i][j] != NULL) {
569
13.5k
                free(netsnmp_ds_strings[i][j]);
570
13.5k
                netsnmp_ds_strings[i][j] = NULL;
571
13.5k
            }
572
653k
        }
573
10.2k
    }
574
3.40k
    snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
575
3.40k
}
576
/**  @} */