Coverage Report

Created: 2023-06-07 06:42

/src/net-snmp/snmplib/container.c
Line
Count
Source (jump to first uncovered line)
1
/* Portions of this file are subject to the following copyright(s).  See
2
 * the Net-SNMP's COPYING file for more details and other copyrights
3
 * that may apply:
4
 */
5
/*
6
 * Portions of this file are copyrighted by:
7
 * Copyright (C) 2007 Apple, Inc. All rights reserved.
8
 * Use is subject to license terms specified in the COPYING file
9
 * distributed with the Net-SNMP package.
10
 *
11
 * Portions of this file are copyrighted by:
12
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
13
 * Use is subject to license terms specified in the COPYING file
14
 * distributed with the Net-SNMP package.
15
 */
16
#include <net-snmp/net-snmp-config.h>
17
#include <net-snmp/net-snmp-features.h>
18
#include <net-snmp/net-snmp-includes.h>
19
#include <net-snmp/library/container.h>
20
#include <net-snmp/library/container_binary_array.h>
21
#include <net-snmp/library/container_list_ssll.h>
22
#include <net-snmp/library/container_null.h>
23
#include "factory.h"
24
25
#include <stdint.h>
26
27
netsnmp_feature_child_of(container_all, libnetsnmp);
28
29
netsnmp_feature_child_of(container_factories, container_all);
30
netsnmp_feature_child_of(container_types, container_all);
31
netsnmp_feature_child_of(container_compare, container_all);
32
netsnmp_feature_child_of(container_dup, container_all);
33
netsnmp_feature_child_of(container_free_all, container_all);
34
netsnmp_feature_child_of(subcontainer_find, container_all);
35
36
netsnmp_feature_child_of(container_ncompare_cstring, container_compare);
37
netsnmp_feature_child_of(container_compare_mem, container_compare);
38
netsnmp_feature_child_of(container_compare_long, container_compare);
39
netsnmp_feature_child_of(container_compare_ulong, container_compare);
40
netsnmp_feature_child_of(container_compare_int32, container_compare);
41
netsnmp_feature_child_of(container_compare_uint32, container_compare);
42
43
netsnmp_feature_child_of(container_find_factory, container_factories);
44
45
/** @defgroup container container
46
 */
47
48
/*------------------------------------------------------------------
49
 */
50
static netsnmp_container *containers = NULL;
51
52
typedef struct container_type_s {
53
   const char                 *name;
54
   netsnmp_factory            *factory;
55
   netsnmp_container_compare  *compare;
56
} container_type;
57
58
netsnmp_factory *
59
netsnmp_container_get_factory(const char *type);
60
61
/*------------------------------------------------------------------
62
 */
63
static void 
64
_factory_free(void *dat, void *context)
65
0
{
66
0
    container_type *data = (container_type *)dat;
67
0
    if (data == NULL)
68
0
  return;
69
    
70
0
    if (data->name != NULL) {
71
0
        DEBUGMSGTL(("container", "  _factory_free_list() called for %s\n",
72
0
                    data->name));
73
0
  free(NETSNMP_REMOVE_CONST(void *, data->name)); /* SNMP_FREE wasted on object about to be freed */
74
0
    }
75
0
    free(data); /* SNMP_FREE wasted on param */
76
0
}
77
78
/*------------------------------------------------------------------
79
 */
80
void
81
netsnmp_container_init_list(void)
82
0
{
83
0
    if (NULL != containers)
84
0
        return;
85
86
    /*
87
     * create a binary arry container to hold container
88
     * factories
89
     */
90
0
    containers = netsnmp_container_get_binary_array();
91
0
    containers->compare = netsnmp_compare_cstring;
92
0
    containers->container_name = strdup("container list");
93
94
    /*
95
     * register containers
96
     */
97
0
    netsnmp_container_binary_array_init();
98
0
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST
99
0
    netsnmp_container_ssll_init();
100
0
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST */
101
0
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_NULL
102
0
    netsnmp_container_null_init();
103
0
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_NULL */
104
105
    /*
106
     * default aliases for some containers
107
     */
108
0
    netsnmp_container_register("table_container",
109
0
                               netsnmp_container_get_factory("binary_array"));
110
111
0
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST
112
0
    netsnmp_container_register("linked_list",
113
0
                               netsnmp_container_get_factory("sorted_singly_linked_list"));
114
0
    netsnmp_container_register("ssll_container",
115
0
                               netsnmp_container_get_factory("sorted_singly_linked_list"));
116
0
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST */
117
118
0
    netsnmp_container_register_with_compare
119
0
        ("cstring", netsnmp_container_get_factory("binary_array"),
120
0
         netsnmp_compare_direct_cstring);
121
122
0
    netsnmp_container_register_with_compare
123
0
        ("string", netsnmp_container_get_factory("binary_array"),
124
0
         netsnmp_compare_cstring);
125
0
    netsnmp_container_register_with_compare
126
0
        ("string_binary_array", netsnmp_container_get_factory("binary_array"),
127
0
         netsnmp_compare_cstring);
128
129
0
}
130
131
void
132
netsnmp_container_free_list(void)
133
0
{
134
0
    DEBUGMSGTL(("container", "netsnmp_container_free_list() called\n"));
135
0
    if (containers == NULL)
136
0
  return;
137
138
    /*
139
     * free memory used by each factory entry
140
     */
141
0
    CONTAINER_FOR_EACH(containers, ((netsnmp_container_obj_func *)_factory_free), NULL);
142
143
    /*
144
     * free factory container
145
     */
146
0
    CONTAINER_FREE(containers);
147
0
    containers = NULL;
148
0
}
149
150
int
151
netsnmp_container_register_with_compare(const char* name, netsnmp_factory *f,
152
                                        netsnmp_container_compare  *c)
153
0
{
154
0
    container_type *ct, tmp;
155
156
0
    if (NULL==containers)
157
0
        return -1;
158
159
0
    tmp.name = NETSNMP_REMOVE_CONST(char *, name);
160
0
    ct = (container_type *)CONTAINER_FIND(containers, &tmp);
161
0
    if (NULL!=ct) {
162
0
        DEBUGMSGT(("container_registry",
163
0
                   "replacing previous container factory\n"));
164
0
        ct->factory = f;
165
0
    }
166
0
    else {
167
0
        ct = SNMP_MALLOC_TYPEDEF(container_type);
168
0
        if (NULL == ct)
169
0
            return -1;
170
0
        ct->name = strdup(name);
171
0
        ct->factory = f;
172
0
        ct->compare = c;
173
0
        CONTAINER_INSERT(containers, ct);
174
0
    }
175
0
    DEBUGMSGT(("container_registry", "registered container factory %s (%s)\n",
176
0
               ct->name, f->product));
177
178
0
    return 0;
179
0
}
180
181
int
182
netsnmp_container_register(const char* name, netsnmp_factory *f)
183
0
{
184
0
    return netsnmp_container_register_with_compare(name, f, NULL);
185
0
}
186
187
/*------------------------------------------------------------------
188
 */
189
netsnmp_factory *
190
netsnmp_container_get_factory(const char *type)
191
0
{
192
0
    container_type ct, *found;
193
    
194
0
    if (NULL==containers)
195
0
        return NULL;
196
197
0
    ct.name = type;
198
0
    found = (container_type *)CONTAINER_FIND(containers, &ct);
199
200
0
    return found ? found->factory : NULL;
201
0
}
202
203
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_FIND_FACTORY
204
netsnmp_factory *
205
netsnmp_container_find_factory(const char *type_list)
206
0
{
207
0
    netsnmp_factory   *f = NULL;
208
0
    char              *list, *entry;
209
0
    char              *st = NULL;
210
211
0
    if (NULL==type_list)
212
0
        return NULL;
213
214
0
    list = strdup(type_list);
215
0
    if (!list)
216
0
        return NULL;
217
0
    entry = strtok_r(list, ":", &st);
218
0
    while (entry) {
219
0
        f = netsnmp_container_get_factory(entry);
220
0
        if (NULL != f)
221
0
            break;
222
0
        entry = strtok_r(NULL, ":", &st);
223
0
    }
224
225
0
    free(list);
226
0
    return f;
227
0
}
228
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_FIND_FACTORY */
229
230
/*------------------------------------------------------------------
231
 */
232
static container_type *
233
netsnmp_container_get_ct(const char *type)
234
0
{
235
0
    container_type ct;
236
237
0
    if (NULL == containers)
238
0
        return NULL;
239
    
240
0
    ct.name = type;
241
0
    return (container_type *)CONTAINER_FIND(containers, &ct);
242
0
}
243
244
static container_type *
245
netsnmp_container_find_ct(const char *type_list)
246
0
{
247
0
    container_type    *ct = NULL;
248
0
    char              *list, *entry;
249
0
    char              *st = NULL;
250
251
0
    if (NULL==type_list)
252
0
        return NULL;
253
254
0
    list = strdup(type_list);
255
0
    if (!list)
256
0
        return NULL;
257
0
    entry = strtok_r(list, ":", &st);
258
0
    while (entry) {
259
0
        ct = netsnmp_container_get_ct(entry);
260
0
        if (NULL != ct)
261
0
            break;
262
0
        entry = strtok_r(NULL, ":", &st);
263
0
    }
264
265
0
    free(list);
266
0
    return ct;
267
0
}
268
269
270
271
/*------------------------------------------------------------------
272
 */
273
netsnmp_container *
274
netsnmp_container_get(const char *type)
275
0
{
276
0
    netsnmp_container *c;
277
0
    container_type *ct = netsnmp_container_get_ct(type);
278
0
    if (ct) {
279
0
        c = (netsnmp_container *)(ct->factory->produce());
280
0
        if (c && ct->compare)
281
0
            c->compare = ct->compare;
282
0
        return c;
283
0
    }
284
285
0
    return NULL;
286
0
}
287
288
/**
289
 * Allocate a new container of a given type.
290
 *
291
 * @param type A colon-separated string with the container name, followed by
292
 * a colon-separated list of container types.
293
 *
294
 * Creates a new container. The type of the container is the first type
295
 * mentioned in @type for which a factory has been registered with
296
 * netsnmp_container_register_with_compare() or netsnmp_container_register().
297
 */
298
netsnmp_container *
299
netsnmp_container_find(const char *type)
300
0
{
301
0
    container_type *ct = netsnmp_container_find_ct(type);
302
0
    netsnmp_container *c = ct ? (netsnmp_container *)(ct->factory->produce()) : NULL;
303
304
    /*
305
     * provide default compare and ncompare
306
     */
307
0
    if (c) {
308
0
        if (ct->compare)
309
0
            c->compare = ct->compare;
310
0
        else if (NULL == c->compare)
311
0
            c->compare = netsnmp_compare_netsnmp_index;
312
313
0
        if (NULL == c->ncompare)
314
0
            c->ncompare = netsnmp_ncompare_netsnmp_index;
315
0
    }
316
317
0
    return c;
318
0
}
319
320
/*------------------------------------------------------------------
321
 */
322
void
323
netsnmp_container_add_index(netsnmp_container *primary,
324
                            netsnmp_container *new_index)
325
0
{
326
0
    netsnmp_container *curr = primary;
327
328
0
    if((NULL == new_index) || (NULL == primary)) {
329
0
        snmp_log(LOG_ERR, "add index called with null pointer\n");
330
0
        return;
331
0
    }
332
333
0
    while(curr->next)
334
0
        curr = curr->next;
335
336
0
    curr->next = new_index;
337
0
    new_index->prev = curr;
338
0
}
339
340
int CONTAINER_INSERT_HELPER(netsnmp_container* x, const void* k)
341
0
{
342
0
    while(x && x->insert_filter && x->insert_filter(x,k) == 1)
343
0
        x = x->next;
344
0
    if(x) {
345
0
        int rc = x->insert(x,k);
346
0
        if(rc)
347
0
            snmp_log(LOG_DEBUG,"error on subcontainer '%s' insert (%d)\n",
348
0
                     x->container_name ? x->container_name : "", rc);
349
0
        else {
350
0
            rc = CONTAINER_INSERT_HELPER(x->next, k);
351
0
            if(rc)
352
0
                x->remove(x,k);
353
0
        }
354
0
        return rc;
355
0
    }
356
0
    return 0;
357
0
}
358
359
int CONTAINER_INSERT(netsnmp_container* x, const void* k)
360
0
{
361
    /** start at first container */
362
0
    while(x->prev)
363
0
        x = x->prev;
364
0
    return CONTAINER_INSERT_HELPER(x, k);
365
0
}
366
367
int CONTAINER_INSERT_BEFORE(netsnmp_container *x, size_t pos, void *k)
368
0
{
369
0
    int rc = 0;
370
371
0
    if (NULL == x || NULL == x->insert_before) {
372
0
        snmp_log(LOG_ERR, "container '%s' does not support insert_before\n",
373
0
                 x && x->container_name ? x->container_name : "");
374
0
        return -1;
375
0
    }
376
377
0
    rc = x->insert_before(x, pos, k);
378
0
    if (rc < 0)
379
0
        snmp_log(LOG_ERR, "error on container '%s' insert_before %" NETSNMP_PRIz "d (%d)\n",
380
0
                 x->container_name ? x->container_name : "", pos, rc);
381
382
0
    return rc;
383
0
}
384
385
int CONTAINER_REMOVE(netsnmp_container *x, const void *k)
386
0
{
387
0
    int rc2, rc = 0;
388
    
389
    /** start at last container */
390
0
    while(x->next)
391
0
        x = x->next;
392
0
    while(x) {
393
0
        rc2 = x->remove(x,k);
394
        /** ignore remove errors if there is a filter in place */
395
0
        if ((rc2) && (NULL == x->insert_filter)) {
396
0
            snmp_log(LOG_ERR,"error on subcontainer '%s' remove (%d)\n",
397
0
                     x->container_name ? x->container_name : "", rc2);
398
0
            rc = rc2;
399
0
        }
400
0
        x = x->prev;
401
        
402
0
    }
403
0
    return rc;
404
0
}
405
406
int CONTAINER_REMOVE_AT(netsnmp_container *x, size_t pos, void **k)
407
0
{
408
0
    int rc = 0;
409
0
    netsnmp_container *orig = x;
410
411
0
    if (NULL == x || NULL == x->remove_at) {
412
0
        snmp_log(LOG_ERR, "container '%s' does not support REMOVE_AT\n",
413
0
                 x && x->container_name ? x->container_name : "");
414
0
        return -1;
415
0
    }
416
417
    /** start at given container */
418
0
    rc = x->remove_at(x, pos, k);
419
0
    if (rc < 0) {
420
0
        snmp_log(LOG_ERR, "error on container '%s' remove_at %" NETSNMP_PRIz "d (%d)\n",
421
0
                 x->container_name ? x->container_name : "", pos, rc);
422
0
        return rc;
423
0
    } else if (NULL == k || NULL == *k)
424
0
        return rc;
425
426
    /** remove k from any other containers */
427
0
    while(x->prev)
428
0
        x = x->prev;
429
0
    for(; x; x = x->next) {
430
0
        if (x == orig)
431
0
            continue;
432
0
        x->remove(x,*k); /** ignore remove errors in other containers */
433
0
    }
434
0
    return rc;
435
0
}
436
437
int CONTAINER_GET_AT(netsnmp_container *x, size_t pos, void **k)
438
0
{
439
0
    int rc = 0;
440
441
0
    if (NULL == x || NULL == x->get_at) {
442
0
        snmp_log(LOG_ERR, "container '%s' does not support GET_AT\n",
443
0
                 x && x->container_name ? x->container_name : "");
444
0
        return -1;
445
0
    }
446
447
    /** start at given container */
448
0
    rc = x->get_at(x, pos, k);
449
0
    if (rc < 0)
450
0
        snmp_log(LOG_ERR, "error on container '%s' get_at %" NETSNMP_PRIz "d (%d)\n",
451
0
                 x->container_name ? x->container_name : "", pos, rc);
452
453
0
    return rc;
454
0
}
455
456
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_DUP
457
netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx, u_int flags)
458
0
{
459
0
    if (NULL == x->duplicate) {
460
0
        snmp_log(LOG_ERR, "container '%s' does not support duplicate\n",
461
0
                 x->container_name ? x->container_name : "");
462
0
        return NULL;
463
0
    }
464
0
    return x->duplicate(x, ctx, flags);
465
0
}
466
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_DUP */
467
468
int CONTAINER_FREE(netsnmp_container *x)
469
0
{
470
0
    int  rc2, rc = 0;
471
472
0
    if (!x)
473
0
        return rc;
474
475
    /** start at last container */
476
0
    while(x->next)
477
0
        x = x->next;
478
0
    while(x) {
479
0
        netsnmp_container *tmp;
480
0
        char *name;
481
0
        tmp = x->prev;
482
0
        name = x->container_name;
483
0
        x->container_name = NULL;
484
0
        rc2 = x->cfree(x);
485
0
        if (rc2) {
486
0
            snmp_log(LOG_ERR,"error on subcontainer '%s' cfree (%d)\n",
487
0
                     name ? name : "", rc2);
488
0
            rc = rc2;
489
0
        }
490
0
        SNMP_FREE(name);
491
0
        x = tmp;
492
0
    }
493
0
    return rc;
494
0
}
495
496
/*
497
 * clear all containers. When clearing the *first* container, and
498
 * *only* the first container, call the function f for each item.
499
 * After calling this function, all containers should be empty.
500
 */
501
void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
502
                    void *c)
503
0
{
504
    /** start at last container */
505
0
    while(x->next)
506
0
        x = x->next;
507
0
    while(x->prev) {
508
0
        x->clear(x, NULL, c);
509
0
        x = x->prev;
510
0
    }
511
0
    x->clear(x, f, c);
512
0
}
513
514
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_FREE_ALL
515
/*
516
 * clear all containers. When clearing the *first* container, and
517
 * *only* the first container, call the free_item function for each item.
518
 * After calling this function, all containers should be empty.
519
 */
520
void CONTAINER_FREE_ALL(netsnmp_container *x, void *c)
521
0
{
522
0
    CONTAINER_CLEAR(x, x->free_item, c);
523
0
}
524
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_FREE_ALL */
525
526
#ifndef NETSNMP_FEATURE_REMOVE_SUBCONTAINER_FIND
527
/*
528
 * Find a sub-container with the given name
529
 */
530
netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
531
                                     const char* name)
532
0
{
533
0
    if ((NULL == x) || (NULL == name))
534
0
        return NULL;
535
    
536
    /** start at first container */
537
0
    while(x->prev)
538
0
        x = x->prev;
539
0
    while(x) {
540
0
        if ((NULL != x->container_name) && (0 == strcmp(name,x->container_name)))
541
0
            break;
542
0
        x = x->next;
543
0
    }
544
0
    return x;
545
0
}
546
#endif /* NETSNMP_FEATURE_REMOVE_SUBCONTAINER_FIND */
547
548
549
/*------------------------------------------------------------------
550
 */
551
void
552
netsnmp_init_container(netsnmp_container         *c,
553
                       netsnmp_container_rc      *init,
554
                       netsnmp_container_rc      *cfree,
555
                       netsnmp_container_size    *size,
556
                       netsnmp_container_compare *cmp,
557
                       netsnmp_container_op      *ins,
558
                       netsnmp_container_op      *rem,
559
                       netsnmp_container_rtn     *fnd)
560
0
{
561
0
    if (c == NULL)
562
0
        return;
563
564
0
    c->init = init;
565
0
    c->cfree = cfree;
566
0
    c->get_size = size;
567
0
    c->compare = cmp;
568
0
    c->insert = ins;
569
0
    c->remove = rem;
570
0
    c->find = fnd;
571
0
    c->free_item = netsnmp_container_simple_free;
572
0
}
573
574
int
575
netsnmp_container_data_dup(netsnmp_container *dup, netsnmp_container *c)
576
0
{
577
0
    if (!dup || !c)
578
0
        return -1;
579
580
0
    if (c->container_name)
581
0
        dup->container_name = strdup(c->container_name);
582
0
    dup->compare = c->compare;
583
0
    dup->ncompare = c->ncompare;
584
0
    dup->release = c->release;
585
0
    dup->insert_filter = c->insert_filter;
586
0
    dup->free_item = c->free_item;
587
0
    dup->sync = c->sync;
588
0
    dup->flags = c->flags;
589
590
0
    return 0;
591
0
}
592
593
/*------------------------------------------------------------------
594
 *
595
 * simple comparison routines
596
 *
597
 */
598
int
599
netsnmp_compare_netsnmp_index(const void *lhs_arg, const void *rhs_arg)
600
0
{
601
0
    const netsnmp_index *lhs = lhs_arg;
602
0
    const netsnmp_index *rhs = rhs_arg;
603
0
    int rc;
604
605
0
    netsnmp_assert(lhs && rhs);
606
0
    DEBUGIF("compare:index") {
607
0
        DEBUGMSGT(("compare:index", "compare "));
608
0
        DEBUGMSGSUBOID(("compare:index", lhs->oids, lhs->len));
609
0
        DEBUGMSG(("compare:index", " to "));
610
0
        DEBUGMSGSUBOID(("compare:index", rhs->oids, rhs->len));
611
0
        DEBUGMSG(("compare:index", "\n"));
612
0
    }
613
0
    rc = snmp_oid_compare(lhs->oids, lhs->len, rhs->oids, rhs->len);
614
0
    DEBUGMSGT(("compare:index", "result was %d\n", rc));
615
0
    return rc;
616
0
}
617
618
int
619
netsnmp_ncompare_netsnmp_index(const void *lhs_arg, const void *rhs_arg)
620
0
{
621
0
    const netsnmp_index *lhs = lhs_arg;
622
0
    const netsnmp_index *rhs = rhs_arg;
623
0
    int rc;
624
625
0
    netsnmp_assert(lhs && rhs);
626
0
    DEBUGIF("compare:index") {
627
0
        DEBUGMSGT(("compare:index", "compare "));
628
0
        DEBUGMSGSUBOID(("compare:index", lhs->oids, lhs->len));
629
0
        DEBUGMSG(("compare:index", " to "));
630
0
        DEBUGMSGSUBOID(("compare:index", rhs->oids, rhs->len));
631
0
        DEBUGMSG(("compare:index", "\n"));
632
0
    }
633
0
    rc = snmp_oid_ncompare(lhs->oids, lhs->len, rhs->oids, rhs->len, rhs->len);
634
0
    DEBUGMSGT(("compare:index", "result was %d\n", rc));
635
0
    return rc;
636
0
}
637
638
int
639
netsnmp_compare_cstring(const void *lhs_arg, const void *rhs_arg)
640
0
{
641
0
    const container_type *lhs = lhs_arg;
642
0
    const container_type *rhs = rhs_arg;
643
644
0
    return strcmp(lhs->name, rhs->name);
645
0
}
646
647
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_NCOMPARE_CSTRING
648
int
649
netsnmp_ncompare_cstring(const void *lhs_arg, const void *rhs_arg)
650
0
{
651
0
    const container_type *lhs = lhs_arg;
652
0
    const container_type *rhs = rhs_arg;
653
654
0
    return strncmp(lhs->name, rhs->name, strlen(rhs->name));
655
0
}
656
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_NCOMPARE_CSTRING */
657
658
int
659
netsnmp_compare_direct_cstring(const void * lhs, const void * rhs)
660
0
{
661
0
    return strcmp(lhs, rhs);
662
0
}
663
664
/*
665
 * compare two memory buffers
666
 *
667
 * since snmp strings aren't NULL terminated, we can't use strcmp. So
668
 * compare up to the length of the smaller, and then use length to
669
 * break any ties.
670
 */
671
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_MEM
672
int
673
netsnmp_compare_mem(const char * lhs, size_t lhs_len,
674
                    const char * rhs, size_t rhs_len)
675
0
{
676
0
    int rc, min = SNMP_MIN(lhs_len, rhs_len);
677
678
0
    rc = memcmp(lhs, rhs, min);
679
0
    return rc ? rc : lhs_len - rhs_len;
680
0
}
681
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_MEM */
682
683
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_LONG
684
int
685
netsnmp_compare_long(const void * lhs, const void * rhs)
686
0
{
687
0
    typedef struct { long index; } dummy;
688
689
0
    const dummy *lhd = (const dummy*)lhs;
690
0
    const dummy *rhd = (const dummy*)rhs;
691
692
0
    if (lhd->index < rhd->index)
693
0
        return -1;
694
0
    else if (lhd->index > rhd->index)
695
0
        return 1;
696
697
0
    return 0;
698
0
}
699
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_LONG */
700
701
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_ULONG
702
int
703
netsnmp_compare_ulong(const void * lhs, const void * rhs)
704
0
{
705
0
    typedef struct { u_long index; } dummy;
706
707
0
    const dummy *lhd = (const dummy*)lhs;
708
0
    const dummy *rhd = (const dummy*)rhs;
709
710
0
    if (lhd->index < rhd->index)
711
0
        return -1;
712
0
    else if (lhd->index > rhd->index)
713
0
        return 1;
714
715
0
    return 0;
716
0
}
717
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_ULONG */
718
719
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_INT32
720
int
721
netsnmp_compare_int32(const void * lhs, const void * rhs)
722
0
{
723
0
    typedef struct { int32_t index; } dummy;
724
725
0
    const dummy *lhd = (const dummy*)lhs;
726
0
    const dummy *rhd = (const dummy*)rhs;
727
728
0
    if (lhd->index < rhd->index)
729
0
        return -1;
730
0
    else if (lhd->index > rhd->index)
731
0
        return 1;
732
733
0
    return 0;
734
0
}
735
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_INT32 */
736
737
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_UINT32
738
int
739
netsnmp_compare_uint32(const void * lhs, const void * rhs)
740
0
{
741
0
    typedef struct { uint32_t index; } dummy;
742
743
0
    const dummy *lhd = (const dummy*)lhs;
744
0
    const dummy *rhd = (const dummy*)rhs;
745
746
0
    if (lhd->index < rhd->index)
747
0
        return -1;
748
0
    else if (lhd->index > rhd->index)
749
0
        return 1;
750
751
0
    return 0;
752
0
}
753
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_UINT32 */
754
755
/*------------------------------------------------------------------
756
 * netsnmp_container_simple_free
757
 *
758
 * useful function to pass to CONTAINER_FOR_EACH, when a simple
759
 * free is needed for every item.
760
 */
761
void 
762
netsnmp_container_simple_free(void *data, void *context)
763
0
{
764
0
    if (data == NULL)
765
0
  return;
766
    
767
0
    DEBUGMSGTL(("verbose:container",
768
0
                "netsnmp_container_simple_free) called for %p/%p\n",
769
0
                data, context));
770
0
    free(data); /* SNMP_FREE wasted on param */
771
0
}