Coverage Report

Created: 2025-11-11 06:56

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
45.2k
{
202
45.2k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
203
41.9k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
204
3.61k
        return SNMPERR_GENERR;
205
3.61k
    }
206
207
41.6k
    DEBUGMSGTL(("netsnmp_ds_set_boolean", "Setting %s:%d = %d/%s\n",
208
41.6k
                stores[storeid], which, value, ((value) ? "True" : "False")));
209
210
41.6k
    if (value > 0) {
211
28.3k
        netsnmp_ds_booleans[storeid][which/8] |= (1 << (which % 8));
212
28.3k
    } else {
213
13.2k
        netsnmp_ds_booleans[storeid][which/8] &= (0xff7f >> (7 - (which % 8)));
214
13.2k
    }
215
216
41.6k
    return SNMPERR_SUCCESS;
217
45.2k
}
218
219
int
220
netsnmp_ds_toggle_boolean(int storeid, int which)
221
5.28k
{
222
5.28k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
223
5.28k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
224
0
        return SNMPERR_GENERR;
225
0
    }
226
227
5.28k
    if ((netsnmp_ds_booleans[storeid][which/8] & (1 << (which % 8))) == 0) {
228
2.64k
        netsnmp_ds_booleans[storeid][which/8] |= (1 << (which % 8));
229
2.64k
    } else {
230
2.63k
        netsnmp_ds_booleans[storeid][which/8] &= (0xff7f >> (7 - (which % 8)));
231
2.63k
    }
232
233
5.28k
    DEBUGMSGTL(("netsnmp_ds_toggle_boolean", "Setting %s:%d = %d/%s\n",
234
5.28k
                stores[storeid], which, netsnmp_ds_booleans[storeid][which/8],
235
5.28k
                ((netsnmp_ds_booleans[storeid][which/8]) ? "True" : "False")));
236
237
5.28k
    return SNMPERR_SUCCESS;
238
5.28k
}
239
240
int
241
netsnmp_ds_get_boolean(int storeid, int which)
242
12.0M
{
243
12.0M
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
244
12.0M
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
245
0
        return SNMPERR_GENERR;
246
0
    }
247
248
12.0M
    return (netsnmp_ds_booleans[storeid][which/8] & (1 << (which % 8))) ? 1:0;
249
12.0M
}
250
251
int
252
netsnmp_ds_set_int(int storeid, int which, int value)
253
22.5k
{
254
22.5k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
255
22.5k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
256
0
        return SNMPERR_GENERR;
257
0
    }
258
259
22.5k
    DEBUGMSGTL(("netsnmp_ds_set_int", "Setting %s:%d = %d\n",
260
22.5k
                stores[storeid], which, value));
261
262
22.5k
    netsnmp_ds_integers[storeid][which] = value;
263
22.5k
    return SNMPERR_SUCCESS;
264
22.5k
}
265
266
int
267
netsnmp_ds_get_int(int storeid, int which)
268
162k
{
269
162k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
270
162k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
271
0
        return SNMPERR_GENERR;
272
0
    }
273
274
162k
    return netsnmp_ds_integers[storeid][which];
275
162k
}
276
277
int
278
netsnmp_ds_set_string(int storeid, int which, const char *value)
279
24.2k
{
280
24.2k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
281
24.2k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
282
0
        return SNMPERR_GENERR;
283
0
    }
284
285
24.2k
    DEBUGMSGTL(("netsnmp_ds_set_string", "Setting %s:%d = \"%s\"\n",
286
24.2k
                stores[storeid], which, (value ? value : "(null)")));
287
288
    /*
289
     * is some silly person is calling us with our own pointer?
290
     */
291
24.2k
    if (netsnmp_ds_strings[storeid][which] == value)
292
6.48k
        return SNMPERR_SUCCESS;
293
294
17.7k
    snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
295
17.7k
    if (netsnmp_ds_strings[storeid][which] != NULL) {
296
4.70k
        free(netsnmp_ds_strings[storeid][which]);
297
4.70k
  netsnmp_ds_strings[storeid][which] = NULL;
298
4.70k
    }
299
17.7k
    snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
300
301
17.7k
    if (value) {
302
17.7k
        netsnmp_ds_strings[storeid][which] = strdup(value);
303
17.7k
    } else {
304
0
        netsnmp_ds_strings[storeid][which] = NULL;
305
0
    }
306
307
17.7k
    return SNMPERR_SUCCESS;
308
24.2k
}
309
310
char *
311
netsnmp_ds_get_string(int storeid, int which)
312
596k
{
313
596k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS || 
314
596k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS) {
315
0
        return NULL;
316
0
    }
317
318
596k
    return netsnmp_ds_strings[storeid][which];
319
596k
}
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
247
{
353
247
    char           *value, *endptr;
354
247
    int             itmp;
355
247
    char           *st;
356
357
247
    value = strtok_r(line, " \t\n", &st);
358
247
    if (!value)
359
11
        goto invalid;
360
236
    if (strcasecmp(value, "yes") == 0 || 
361
226
  strcasecmp(value, "true") == 0) {
362
11
        return 1;
363
225
    } else if (strcasecmp(value, "no") == 0 ||
364
215
         strcasecmp(value, "false") == 0) {
365
28
        return 0;
366
197
    } else {
367
197
        itmp = strtol(value, &endptr, 10);
368
197
        if (*endptr != 0 || itmp < 0 || itmp > 1)
369
185
            goto invalid;
370
12
        return itmp;
371
197
    }
372
373
196
invalid:
374
196
    config_perror("Should be yes|no|true|false|0|1");
375
196
    return -1;
376
236
}
377
378
void
379
netsnmp_ds_handle_config(const char *token, char *line)
380
397
{
381
397
    netsnmp_ds_read_config *drsp;
382
397
    char            buf[SNMP_MAXBUF];
383
397
    char           *value, *endptr;
384
397
    int             itmp;
385
397
    char           *st;
386
387
397
    DEBUGMSGTL(("netsnmp_ds_handle_config", "handling %s\n", token));
388
389
397
    for (drsp = netsnmp_ds_configs;
390
17.6k
         drsp != NULL && strcasecmp(token, drsp->token) != 0;
391
17.3k
         drsp = drsp->next);
392
393
397
    if (drsp != NULL) {
394
397
        DEBUGMSGTL(("netsnmp_ds_handle_config",
395
397
                    "setting: token=%s, type=%d, id=%s, which=%d\n",
396
397
                    drsp->token, drsp->type, stores[drsp->storeid],
397
397
                    drsp->which));
398
399
397
        switch (drsp->type) {
400
247
        case ASN_BOOLEAN:
401
247
            itmp = netsnmp_ds_parse_boolean(line);
402
247
            if ( itmp != -1 )
403
51
                netsnmp_ds_set_boolean(drsp->storeid, drsp->which, itmp);
404
247
            DEBUGMSGTL(("netsnmp_ds_handle_config", "bool: %d\n", itmp));
405
247
            break;
406
407
103
        case ASN_INTEGER:
408
103
            value = strtok_r(line, " \t\n", &st);
409
103
            if (!value) {
410
29
                config_perror("Missing value");
411
74
            } else {
412
74
                itmp = strtol(value, &endptr, 10);
413
74
                if (*endptr != 0) {
414
47
                    config_perror("Bad integer value");
415
47
                } else {
416
27
                    netsnmp_ds_set_int(drsp->storeid, drsp->which, itmp);
417
27
                }
418
74
                DEBUGMSGTL(("netsnmp_ds_handle_config", "int: %d\n", itmp));
419
74
            }
420
103
            break;
421
422
47
        case ASN_OCTET_STR:
423
47
            if (*line == '"') {
424
11
                copy_nword(line, buf, sizeof(buf));
425
11
                netsnmp_ds_set_string(drsp->storeid, drsp->which, buf);
426
36
            } else {
427
36
                netsnmp_ds_set_string(drsp->storeid, drsp->which, line);
428
36
            }
429
47
            DEBUGMSGTL(("netsnmp_ds_handle_config", "string: %s\n", line));
430
47
            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
397
        }
437
397
    } else {
438
0
        snmp_log(LOG_ERR, "netsnmp_ds_handle_config: no registration for %s\n",
439
0
                 token);
440
0
    }
441
397
}
442
443
444
int
445
netsnmp_ds_register_config(u_char type, const char *ftype, const char *token,
446
         int storeid, int which)
447
174k
{
448
174k
    netsnmp_ds_read_config *drsp;
449
450
174k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS    || 
451
174k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS || token == NULL) {
452
0
        return SNMPERR_GENERR;
453
0
    }
454
455
174k
    if (netsnmp_ds_configs == NULL) {
456
3.24k
        netsnmp_ds_configs = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
457
3.24k
        if (netsnmp_ds_configs == NULL)
458
0
            return SNMPERR_GENERR;
459
3.24k
        drsp = netsnmp_ds_configs;
460
171k
    } else {
461
24.6M
        for (drsp = netsnmp_ds_configs; drsp->next != NULL; drsp = drsp->next);
462
171k
        drsp->next = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
463
171k
        if (drsp->next == NULL)
464
0
            return SNMPERR_GENERR;
465
171k
        drsp = drsp->next;
466
171k
    }
467
468
174k
    drsp->type    = type;
469
174k
    drsp->ftype   = strdup(ftype);
470
174k
    drsp->token   = strdup(token);
471
174k
    drsp->storeid = storeid;
472
174k
    drsp->which   = which;
473
474
174k
    switch (type) {
475
52.6k
    case ASN_BOOLEAN:
476
52.6k
        register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
477
52.6k
                                "(1|yes|true|0|no|false)");
478
52.6k
        break;
479
480
42.1k
    case ASN_INTEGER:
481
42.1k
        register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
482
42.1k
                                "integerValue");
483
42.1k
        break;
484
485
79.8k
    case ASN_OCTET_STR:
486
79.8k
        register_config_handler(ftype, token, netsnmp_ds_handle_config, NULL,
487
79.8k
                                "string");
488
79.8k
        break;
489
490
174k
    }
491
174k
    return SNMPERR_SUCCESS;
492
174k
}
493
494
int
495
netsnmp_ds_register_premib(u_char type, const char *ftype, const char *token,
496
         int storeid, int which)
497
102k
{
498
102k
    netsnmp_ds_read_config *drsp;
499
500
102k
    if (storeid < 0 || storeid >= NETSNMP_DS_MAX_IDS    || 
501
102k
  which   < 0 || which   >= NETSNMP_DS_MAX_SUBIDS || token == NULL) {
502
0
        return SNMPERR_GENERR;
503
0
    }
504
505
102k
    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
102k
    } else {
511
224M
        for (drsp = netsnmp_ds_configs; drsp->next != NULL; drsp = drsp->next);
512
102k
        drsp->next = SNMP_MALLOC_TYPEDEF(netsnmp_ds_read_config);
513
102k
        if (drsp->next == NULL)
514
0
            return SNMPERR_GENERR;
515
102k
        drsp = drsp->next;
516
102k
    }
517
518
102k
    drsp->type    = type;
519
102k
    drsp->ftype   = strdup(ftype);
520
102k
    drsp->token   = strdup(token);
521
102k
    drsp->storeid = storeid;
522
102k
    drsp->which   = which;
523
524
102k
    switch (type) {
525
71.5k
    case ASN_BOOLEAN:
526
71.5k
        register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
527
71.5k
                                        NULL, "(1|yes|true|0|no|false)");
528
71.5k
        break;
529
530
17.6k
    case ASN_INTEGER:
531
17.6k
        register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
532
17.6k
                                        NULL, "integerValue");
533
17.6k
        break;
534
535
12.9k
    case ASN_OCTET_STR:
536
12.9k
        register_prenetsnmp_mib_handler(ftype, token, netsnmp_ds_handle_config,
537
12.9k
                                        NULL, "string");
538
12.9k
        break;
539
540
102k
    }
541
102k
    return SNMPERR_SUCCESS;
542
102k
}
543
544
void
545
netsnmp_ds_shutdown(void)
546
3.24k
{
547
3.24k
    netsnmp_ds_read_config *drsp;
548
3.24k
    int             i, j;
549
550
3.24k
    snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
551
253k
    for (drsp = netsnmp_ds_configs; drsp; drsp = netsnmp_ds_configs) {
552
249k
        netsnmp_ds_configs = drsp->next;
553
554
249k
        if (drsp->ftype && drsp->token) {
555
249k
            unregister_config_handler(drsp->ftype, drsp->token);
556
249k
        }
557
249k
  if (drsp->ftype != NULL) {
558
249k
      free(drsp->ftype);
559
249k
  }
560
249k
  if (drsp->token != NULL) {
561
249k
      free(drsp->token);
562
249k
  }
563
249k
        free(drsp);
564
249k
    }
565
566
12.9k
    for (i = 0; i < NETSNMP_DS_MAX_IDS; i++) {
567
632k
        for (j = 0; j < NETSNMP_DS_MAX_SUBIDS; j++) {
568
622k
            if (netsnmp_ds_strings[i][j] != NULL) {
569
12.9k
                free(netsnmp_ds_strings[i][j]);
570
12.9k
                netsnmp_ds_strings[i][j] = NULL;
571
12.9k
            }
572
622k
        }
573
9.73k
    }
574
3.24k
    snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
575
3.24k
}
576
/**  @} */