Coverage Report

Created: 2024-09-11 06:05

/src/net-snmp/snmplib/snmp_enum.c
Line
Count
Source (jump to first uncovered line)
1
#include <net-snmp/net-snmp-config.h>
2
#include <net-snmp/net-snmp-features.h>
3
4
/*
5
 * Portions of this file are copyrighted by:
6
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
7
 * Use is subject to license terms specified in the COPYING file
8
 * distributed with the Net-SNMP package.
9
 */
10
11
#ifdef HAVE_STDLIB_H
12
#include <stdlib.h>
13
#endif
14
#include <stdio.h>
15
#ifdef HAVE_STRING_H
16
#include <string.h>
17
#else
18
#include <strings.h>
19
#endif
20
21
#include <sys/types.h>
22
23
#include <net-snmp/types.h>
24
#include <net-snmp/config_api.h>
25
26
#include <net-snmp/library/snmp_enum.h>
27
#include <net-snmp/library/tools.h>
28
#include <net-snmp/library/system.h>      /* strcasecmp() */
29
#include <net-snmp/library/snmp_assert.h>
30
31
netsnmp_feature_child_of(snmp_enum_all, libnetsnmp);
32
33
netsnmp_feature_child_of(se_find_free_value_in_slist, snmp_enum_all);
34
netsnmp_feature_child_of(snmp_enum_store_list, snmp_enum_all);
35
netsnmp_feature_child_of(snmp_enum_store_slist, snmp_enum_all);
36
netsnmp_feature_child_of(snmp_enum_clear, snmp_enum_all);
37
38
struct snmp_enum_list_str {
39
    char           *name;
40
    struct snmp_enum_list *list;
41
    struct snmp_enum_list_str *next;
42
};
43
44
static struct snmp_enum_list ***snmp_enum_lists;
45
unsigned int    current_maj_num;
46
unsigned int    current_min_num;
47
static struct snmp_enum_list_str *sliststorage;
48
49
static void
50
free_enum_list(struct snmp_enum_list *list);
51
52
int
53
init_snmp_enum(const char *type)
54
2.62k
{
55
2.62k
    int             i;
56
57
2.62k
    if (NULL != snmp_enum_lists)
58
0
        return SE_OK;
59
60
2.62k
    snmp_enum_lists = (struct snmp_enum_list ***)
61
2.62k
        calloc(1, sizeof(struct snmp_enum_list **) * SE_MAX_IDS);
62
2.62k
    if (!snmp_enum_lists)
63
0
        return SE_NOMEM;
64
2.62k
    current_maj_num = SE_MAX_IDS;
65
66
15.7k
    for (i = 0; i < SE_MAX_IDS; i++) {
67
13.1k
        if (!snmp_enum_lists[i])
68
13.1k
            snmp_enum_lists[i] = (struct snmp_enum_list **)
69
13.1k
                calloc(1, sizeof(struct snmp_enum_list *) * SE_MAX_SUBIDS);
70
13.1k
        if (!snmp_enum_lists[i])
71
0
            return SE_NOMEM;
72
13.1k
    }
73
2.62k
    current_min_num = SE_MAX_SUBIDS;
74
75
2.62k
    register_const_config_handler(type, "enum", se_read_conf, NULL, NULL);
76
2.62k
    return SE_OK;
77
2.62k
}
78
79
int
80
se_store_in_list(struct snmp_enum_list *new_list,
81
              unsigned int major, unsigned int minor)
82
0
{
83
0
    int             ret = SE_OK;
84
85
0
    if (major > current_maj_num || minor > current_min_num) {
86
        /*
87
         * XXX: realloc 
88
         */
89
0
        return SE_NOMEM;
90
0
    }
91
0
    netsnmp_assert(NULL != snmp_enum_lists);
92
93
0
    if (snmp_enum_lists[major][minor] != NULL)
94
0
        ret = SE_ALREADY_THERE;
95
96
0
    snmp_enum_lists[major][minor] = new_list;
97
98
0
    return ret;
99
0
}
100
101
void
102
se_read_conf(const char *word, const char *cptr)
103
0
{
104
0
    int major, minor;
105
0
    int value;
106
0
    const char *cp, *cp2;
107
0
    char e_name[BUFSIZ];
108
0
    char e_enum[  BUFSIZ];
109
110
0
    if (!cptr || *cptr=='\0')
111
0
        return;
112
113
    /*
114
     * Extract the first token
115
     *   (which should be the name of the list)
116
     */
117
0
    cp = copy_nword_const(cptr, e_name, sizeof(e_name));
118
0
    cp = skip_white_const(cp);
119
0
    if (!cp || *cp=='\0')
120
0
        return;
121
122
123
    /*
124
     * Add each remaining enumeration to the list,
125
     *   using the appropriate style interface
126
     */
127
0
    if (sscanf(e_name, "%d:%d", &major, &minor) == 2) {
128
        /*
129
         *  Numeric major/minor style
130
         */
131
0
        while (1) {
132
0
            cp = copy_nword_const(cp, e_enum, sizeof(e_enum));
133
0
            if (sscanf(e_enum, "%d:", &value) != 1) {
134
0
                break;
135
0
            }
136
0
            cp2 = e_enum;
137
0
            while (*(cp2++) != ':')
138
0
                ;
139
0
            se_add_pair(major, minor, strdup(cp2), value);
140
0
            if (!cp)
141
0
                break;
142
0
        }
143
0
    } else {
144
        /*
145
         *  Named enumeration
146
         */
147
0
        while (1) {
148
0
            cp = copy_nword_const(cp, e_enum, sizeof(e_enum));
149
0
            if (sscanf(e_enum, "%d:", &value) != 1) {
150
0
                break;
151
0
            }
152
0
            cp2 = e_enum;
153
0
            while (*(cp2++) != ':')
154
0
                ;
155
0
            se_add_pair_to_slist(e_name, strdup(cp2), value);
156
0
            if (!cp)
157
0
                break;
158
0
        }
159
0
    }
160
0
}
161
162
void
163
se_store_enum_list(struct snmp_enum_list *new_list,
164
                   const char *token, const char *type)
165
0
{
166
0
    struct snmp_enum_list *listp = new_list;
167
0
    char line[2048];
168
0
    char buf[512];
169
0
    int  len;
170
171
0
    snprintf(line, sizeof(line), "enum %s", token);
172
0
    while (listp) {
173
0
        snprintf(buf, sizeof(buf), " %d:%s", listp->value, listp->label);
174
        /*
175
         * Calculate the space left in the buffer.
176
         * If this is not sufficient to include the next enum,
177
         *   then save the line so far, and start again.
178
         */
179
0
  len = sizeof(line) - strlen(line);
180
0
  if ((int)strlen(buf) > len) {
181
0
      read_config_store(type, line);
182
0
            snprintf(line, sizeof(line), "enum %s", token);
183
0
      len = sizeof(line) - strlen(line);
184
0
  }
185
186
0
  strncat(line, buf, len);
187
0
        listp = listp->next;
188
0
    }
189
190
0
    read_config_store(type, line);
191
0
}
192
193
#ifndef NETSNMP_FEATURE_REMOVE_SNMP_ENUM_STORE_LIST
194
void
195
se_store_list(unsigned int major, unsigned int minor, const char *type)
196
0
{
197
0
    char token[32];
198
199
0
    snprintf(token, sizeof(token), "%d:%d", major, minor);
200
0
    se_store_enum_list(se_find_list(major, minor), token, type);
201
0
}
202
#endif /* NETSNMP_FEATURE_REMOVE_SNMP_ENUM_STORE_LIST */
203
204
struct snmp_enum_list *
205
se_find_list(unsigned int major, unsigned int minor)
206
0
{
207
0
    if (major > current_maj_num || minor > current_min_num)
208
0
        return NULL;
209
0
    netsnmp_assert(NULL != snmp_enum_lists);
210
211
0
    return snmp_enum_lists[major][minor];
212
0
}
213
214
int
215
se_find_value_in_list(struct snmp_enum_list *list, const char *label)
216
0
{
217
0
    if (!list)
218
0
        return SE_DNE;          /* XXX: um, no good solution here */
219
0
    while (list) {
220
0
        if (strcmp(list->label, label) == 0)
221
0
            return (list->value);
222
0
        list = list->next;
223
0
    }
224
225
0
    return SE_DNE;              /* XXX: um, no good solution here */
226
0
}
227
228
int
229
se_find_casevalue_in_list(struct snmp_enum_list *list, const char *label)
230
0
{
231
0
    if (!list)
232
0
        return SE_DNE;          /* XXX: um, no good solution here */
233
0
    while (list) {
234
0
        if (strcasecmp(list->label, label) == 0)
235
0
            return (list->value);
236
0
        list = list->next;
237
0
    }
238
239
0
    return SE_DNE;              /* XXX: um, no good solution here */
240
0
}
241
242
int
243
se_find_free_value_in_list(struct snmp_enum_list *list)
244
0
{
245
0
    int max_value = 0;
246
0
    if (!list)
247
0
        return SE_DNE;
248
249
0
    for (;list; list=list->next) {
250
0
        if (max_value < list->value)
251
0
            max_value = list->value;
252
0
    }
253
0
    return max_value+1;
254
0
}
255
256
int
257
se_find_value(unsigned int major, unsigned int minor, const char *label)
258
0
{
259
0
    return se_find_value_in_list(se_find_list(major, minor), label);
260
0
}
261
262
int
263
se_find_free_value(unsigned int major, unsigned int minor)
264
0
{
265
0
    return se_find_free_value_in_list(se_find_list(major, minor));
266
0
}
267
268
char           *
269
se_find_label_in_list(struct snmp_enum_list *list, int value)
270
0
{
271
0
    if (!list)
272
0
        return NULL;
273
0
    while (list) {
274
0
        if (list->value == value)
275
0
            return (list->label);
276
0
        list = list->next;
277
0
    }
278
0
    return NULL;
279
0
}
280
281
char           *
282
se_find_label(unsigned int major, unsigned int minor, int value)
283
0
{
284
0
    return se_find_label_in_list(se_find_list(major, minor), value);
285
0
}
286
287
int
288
se_add_pair_to_list(struct snmp_enum_list **list, char *label, int value)
289
147k
{
290
147k
    struct snmp_enum_list *lastnode = NULL, *tmp;
291
292
147k
    if (!list)
293
0
        return SE_DNE;
294
295
147k
    tmp = *list;
296
667k
    while (tmp) {
297
530k
        if (tmp->value == value) {
298
10.5k
            free(label);
299
10.5k
            return (SE_ALREADY_THERE);
300
10.5k
        }
301
520k
        lastnode = tmp;
302
520k
        tmp = tmp->next;
303
520k
    }
304
305
136k
    if (lastnode) {
306
115k
        lastnode->next = SNMP_MALLOC_STRUCT(snmp_enum_list);
307
115k
        lastnode = lastnode->next;
308
115k
    } else {
309
21.0k
        (*list) = SNMP_MALLOC_STRUCT(snmp_enum_list);
310
21.0k
        lastnode = (*list);
311
21.0k
    }
312
136k
    if (!lastnode) {
313
0
        free(label);
314
0
        return (SE_NOMEM);
315
0
    }
316
136k
    lastnode->label = label;
317
136k
    lastnode->value = value;
318
136k
    lastnode->next = NULL;
319
136k
    return (SE_OK);
320
136k
}
321
322
int
323
se_add_pair(unsigned int major, unsigned int minor, char *label, int value)
324
0
{
325
0
    struct snmp_enum_list *list = se_find_list(major, minor);
326
0
    int             created = (list) ? 1 : 0;
327
0
    int             ret = se_add_pair_to_list(&list, label, value);
328
0
    if (!created)
329
0
        se_store_in_list(list, major, minor);
330
0
    return ret;
331
0
}
332
333
/*
334
 * remember a list of enums based on a lookup name.
335
 */
336
static struct snmp_enum_list **
337
se_find_slist_ptr(const char *listname)
338
147k
{
339
147k
    struct snmp_enum_list_str *sptr;
340
147k
    if (!listname)
341
0
        return NULL;
342
343
220k
    for (sptr = sliststorage; sptr != NULL; sptr = sptr->next)
344
199k
        if (sptr->name && strcmp(sptr->name, listname) == 0)
345
126k
            return &sptr->list;
346
347
21.0k
    return NULL;
348
147k
}
349
350
struct snmp_enum_list *
351
se_find_slist(const char *listname)
352
147k
{
353
147k
    struct snmp_enum_list **ptr = se_find_slist_ptr(listname);
354
147k
    return ptr ? *ptr : NULL;
355
147k
}
356
357
char           *
358
se_find_label_in_slist(const char *listname, int value)
359
0
{
360
0
    return (se_find_label_in_list(se_find_slist(listname), value));
361
0
}
362
363
int
364
se_find_value_in_slist(const char *listname, const char *label)
365
0
{
366
0
    return (se_find_value_in_list(se_find_slist(listname), label));
367
0
}
368
369
int
370
se_find_casevalue_in_slist(const char *listname, const char *label)
371
0
{
372
0
    return (se_find_casevalue_in_list(se_find_slist(listname), label));
373
0
}
374
375
#ifndef NETSNMP_FEATURE_REMOVE_SE_FIND_FREE_VALUE_IN_SLIST
376
int
377
se_find_free_value_in_slist(const char *listname)
378
0
{
379
0
    return (se_find_free_value_in_list(se_find_slist(listname)));
380
0
}
381
#endif /* NETSNMP_FEATURE_REMOVE_SE_FIND_FREE_VALUE_IN_SLIST */
382
383
int
384
se_add_pair_to_slist(const char *listname, char *label, int value)
385
147k
{
386
147k
    struct snmp_enum_list *list = se_find_slist(listname);
387
147k
    int             created = (list) ? 1 : 0;
388
147k
    int             ret = se_add_pair_to_list(&list, label, value);
389
390
147k
    if (!created) {
391
21.0k
        struct snmp_enum_list_str *sptr =
392
21.0k
            SNMP_MALLOC_STRUCT(snmp_enum_list_str);
393
21.0k
        if (!sptr) {
394
0
            free_enum_list(list);
395
0
            return SE_NOMEM;
396
0
        }
397
21.0k
        sptr->next = sliststorage;
398
21.0k
        sptr->name = strdup(listname);
399
21.0k
        if (!sptr->name) {
400
0
            free(sptr);
401
0
            free_enum_list(list);
402
0
            return SE_NOMEM;
403
0
        }
404
21.0k
        sptr->list = list;
405
21.0k
        sliststorage = sptr;
406
21.0k
    }
407
147k
    return ret;
408
147k
}
409
410
static void
411
free_enum_list(struct snmp_enum_list *list)
412
21.0k
{
413
21.0k
    struct snmp_enum_list *next;
414
415
157k
    while (list) {
416
136k
        next = list->next;
417
136k
        SNMP_FREE(list->label);
418
136k
        SNMP_FREE(list);
419
136k
        list = next;
420
136k
    }
421
21.0k
}
422
423
void
424
clear_snmp_enum(void)
425
5.25k
{
426
5.25k
    struct snmp_enum_list_str *sptr = sliststorage, *next = NULL;
427
5.25k
    int i, j;
428
429
26.2k
    while (sptr != NULL) {
430
21.0k
  next = sptr->next;
431
21.0k
  free_enum_list(sptr->list);
432
21.0k
  SNMP_FREE(sptr->name);
433
21.0k
  SNMP_FREE(sptr);
434
21.0k
  sptr = next;
435
21.0k
    }
436
5.25k
    sliststorage = NULL;
437
438
5.25k
    if (snmp_enum_lists) {
439
15.7k
        for (i = 0; i < SE_MAX_IDS; i++) {
440
13.1k
            if (snmp_enum_lists[i]) {
441
433k
                for (j = 0; j < SE_MAX_SUBIDS; j++) {
442
420k
                    if (snmp_enum_lists[i][j])
443
0
                        free_enum_list(snmp_enum_lists[i][j]);
444
420k
                }
445
13.1k
                SNMP_FREE(snmp_enum_lists[i]);
446
13.1k
            }
447
13.1k
        }
448
2.62k
        SNMP_FREE(snmp_enum_lists);
449
2.62k
    }
450
5.25k
}
451
452
void
453
se_clear_list(struct snmp_enum_list **list)
454
0
{
455
0
    struct snmp_enum_list *this_entry, *next_entry;
456
457
0
    if (!list)
458
0
        return;
459
460
0
    this_entry = *list;
461
0
    while (this_entry) {
462
0
        next_entry = this_entry->next;
463
0
        SNMP_FREE(this_entry->label);
464
0
        SNMP_FREE(this_entry);
465
0
        this_entry = next_entry;
466
0
    }
467
0
    *list = NULL;
468
0
    return;
469
0
}
470
471
#ifndef NETSNMP_FEATURE_REMOVE_SNMP_ENUM_STORE_SLIST
472
void
473
se_store_slist(const char *listname, const char *type)
474
0
{
475
0
    struct snmp_enum_list *list = se_find_slist(listname);
476
0
    se_store_enum_list(list, listname, type);
477
0
}
478
479
int
480
se_store_slist_callback(int majorID, int minorID,
481
                        void *serverargs, void *clientargs)
482
0
{
483
0
    char *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
484
0
                                          NETSNMP_DS_LIB_APPTYPE);
485
0
    se_store_slist((char *)clientargs, appname);
486
0
    return SNMPERR_SUCCESS;
487
0
}
488
#endif /* NETSNMP_FEATURE_REMOVE_SNMP_ENUM_STORE_SLIST */
489
490
#ifndef NETSNMP_FEATURE_REMOVE_SNMP_ENUM_CLEAR
491
void
492
se_clear_slist(const char *listname)
493
0
{
494
0
    se_clear_list(se_find_slist_ptr(listname));
495
0
}
496
497
void
498
se_clear_all_lists(void)
499
0
{
500
0
    struct snmp_enum_list_str *sptr = NULL;
501
502
0
    for (sptr = sliststorage; sptr != NULL; sptr = sptr->next)
503
0
        se_clear_list(&(sptr->list));
504
0
}
505
#endif /* NETSNMP_FEATURE_REMOVE_SNMP_ENUM_CLEAR */