Coverage Report

Created: 2024-07-27 06:05

/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
#ifdef HAVE_MALLOC_H
26
#include <malloc.h>
27
#endif
28
#include <stdint.h>
29
30
netsnmp_feature_child_of(container_all, libnetsnmp);
31
32
netsnmp_feature_child_of(container_factories, container_all);
33
netsnmp_feature_child_of(container_types, container_all);
34
netsnmp_feature_child_of(container_compare, container_all);
35
netsnmp_feature_child_of(container_dup, container_all);
36
netsnmp_feature_child_of(container_free_all, container_all);
37
netsnmp_feature_child_of(subcontainer_find, container_all);
38
39
netsnmp_feature_child_of(container_ncompare_cstring, container_compare);
40
netsnmp_feature_child_of(container_compare_mem, container_compare);
41
netsnmp_feature_child_of(container_compare_long, container_compare);
42
netsnmp_feature_child_of(container_compare_ulong, container_compare);
43
netsnmp_feature_child_of(container_compare_int32, container_compare);
44
netsnmp_feature_child_of(container_compare_uint32, container_compare);
45
46
netsnmp_feature_child_of(container_find_factory, container_factories);
47
48
/** @defgroup container container
49
 */
50
51
/*------------------------------------------------------------------
52
 */
53
static netsnmp_container *containers = NULL;
54
55
typedef struct container_type_s {
56
   const char                 *name;
57
   netsnmp_factory            *factory;
58
   netsnmp_container_compare  *compare;
59
} container_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 array 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, _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
#ifdef HAVE_MALLOC_TRIM
513
0
    malloc_trim(0);
514
0
#endif
515
0
}
516
517
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_FREE_ALL
518
/*
519
 * clear all containers. When clearing the *first* container, and
520
 * *only* the first container, call the free_item function for each item.
521
 * After calling this function, all containers should be empty.
522
 */
523
void CONTAINER_FREE_ALL(netsnmp_container *x, void *c)
524
0
{
525
0
    CONTAINER_CLEAR(x, x->free_item, c);
526
0
}
527
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_FREE_ALL */
528
529
#ifndef NETSNMP_FEATURE_REMOVE_SUBCONTAINER_FIND
530
/*
531
 * Find a sub-container with the given name
532
 */
533
netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
534
                                     const char* name)
535
0
{
536
0
    if ((NULL == x) || (NULL == name))
537
0
        return NULL;
538
    
539
    /** start at first container */
540
0
    while(x->prev)
541
0
        x = x->prev;
542
0
    while(x) {
543
0
        if ((NULL != x->container_name) && (0 == strcmp(name,x->container_name)))
544
0
            break;
545
0
        x = x->next;
546
0
    }
547
0
    return x;
548
0
}
549
#endif /* NETSNMP_FEATURE_REMOVE_SUBCONTAINER_FIND */
550
551
552
/*------------------------------------------------------------------
553
 */
554
void
555
netsnmp_init_container(netsnmp_container         *c,
556
                       netsnmp_container_rc      *init,
557
                       netsnmp_container_rc      *cfree,
558
                       netsnmp_container_size    *size,
559
                       netsnmp_container_compare *cmp,
560
                       netsnmp_container_op      *ins,
561
                       netsnmp_container_op      *rem,
562
                       netsnmp_container_rtn     *fnd)
563
0
{
564
0
    if (c == NULL)
565
0
        return;
566
567
0
    c->init = init;
568
0
    c->cfree = cfree;
569
0
    c->get_size = size;
570
0
    c->compare = cmp;
571
0
    c->insert = ins;
572
0
    c->remove = rem;
573
0
    c->find = fnd;
574
0
    c->free_item = netsnmp_container_simple_free;
575
0
}
576
577
int
578
netsnmp_container_data_dup(netsnmp_container *dup, netsnmp_container *c)
579
0
{
580
0
    if (!dup || !c)
581
0
        return -1;
582
583
0
    if (c->container_name)
584
0
        dup->container_name = strdup(c->container_name);
585
0
    dup->compare = c->compare;
586
0
    dup->ncompare = c->ncompare;
587
0
    dup->release = c->release;
588
0
    dup->insert_filter = c->insert_filter;
589
0
    dup->free_item = c->free_item;
590
0
    dup->sync = c->sync;
591
0
    dup->flags = c->flags;
592
593
0
    return 0;
594
0
}
595
596
/*------------------------------------------------------------------
597
 *
598
 * simple comparison routines
599
 *
600
 */
601
int
602
netsnmp_compare_netsnmp_index(const void *lhs_arg, const void *rhs_arg)
603
0
{
604
0
    const netsnmp_index *lhs = lhs_arg;
605
0
    const netsnmp_index *rhs = rhs_arg;
606
0
    int rc;
607
608
0
    netsnmp_assert(lhs && rhs);
609
0
    DEBUGIF("compare:index") {
610
0
        DEBUGMSGT(("compare:index", "compare "));
611
0
        DEBUGMSGSUBOID(("compare:index", lhs->oids, lhs->len));
612
0
        DEBUGMSG(("compare:index", " to "));
613
0
        DEBUGMSGSUBOID(("compare:index", rhs->oids, rhs->len));
614
0
        DEBUGMSG(("compare:index", "\n"));
615
0
    }
616
0
    rc = snmp_oid_compare(lhs->oids, lhs->len, rhs->oids, rhs->len);
617
0
    DEBUGMSGT(("compare:index", "result was %d\n", rc));
618
0
    return rc;
619
0
}
620
621
int
622
netsnmp_ncompare_netsnmp_index(const void *lhs_arg, const void *rhs_arg)
623
0
{
624
0
    const netsnmp_index *lhs = lhs_arg;
625
0
    const netsnmp_index *rhs = rhs_arg;
626
0
    int rc;
627
628
0
    netsnmp_assert(lhs && rhs);
629
0
    DEBUGIF("compare:index") {
630
0
        DEBUGMSGT(("compare:index", "compare "));
631
0
        DEBUGMSGSUBOID(("compare:index", lhs->oids, lhs->len));
632
0
        DEBUGMSG(("compare:index", " to "));
633
0
        DEBUGMSGSUBOID(("compare:index", rhs->oids, rhs->len));
634
0
        DEBUGMSG(("compare:index", "\n"));
635
0
    }
636
0
    rc = snmp_oid_ncompare(lhs->oids, lhs->len, rhs->oids, rhs->len, rhs->len);
637
0
    DEBUGMSGT(("compare:index", "result was %d\n", rc));
638
0
    return rc;
639
0
}
640
641
int
642
netsnmp_compare_cstring(const void *lhs_arg, const void *rhs_arg)
643
0
{
644
0
    const container_type *lhs = lhs_arg;
645
0
    const container_type *rhs = rhs_arg;
646
647
0
    return strcmp(lhs->name, rhs->name);
648
0
}
649
650
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_NCOMPARE_CSTRING
651
int
652
netsnmp_ncompare_cstring(const void *lhs_arg, const void *rhs_arg)
653
0
{
654
0
    const container_type *lhs = lhs_arg;
655
0
    const container_type *rhs = rhs_arg;
656
657
0
    return strncmp(lhs->name, rhs->name, strlen(rhs->name));
658
0
}
659
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_NCOMPARE_CSTRING */
660
661
int
662
netsnmp_compare_direct_cstring(const void * lhs, const void * rhs)
663
0
{
664
0
    return strcmp(lhs, rhs);
665
0
}
666
667
/*
668
 * compare two memory buffers
669
 *
670
 * since snmp strings aren't NULL terminated, we can't use strcmp. So
671
 * compare up to the length of the smaller, and then use length to
672
 * break any ties.
673
 */
674
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_MEM
675
int
676
netsnmp_compare_mem(const char * lhs, size_t lhs_len,
677
                    const char * rhs, size_t rhs_len)
678
0
{
679
0
    int rc, min = SNMP_MIN(lhs_len, rhs_len);
680
681
0
    rc = memcmp(lhs, rhs, min);
682
0
    return rc ? rc : lhs_len - rhs_len;
683
0
}
684
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_MEM */
685
686
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_LONG
687
int
688
netsnmp_compare_long(const void * lhs, const void * rhs)
689
0
{
690
0
    typedef struct { long index; } dummy;
691
692
0
    const dummy *lhd = (const dummy*)lhs;
693
0
    const dummy *rhd = (const dummy*)rhs;
694
695
0
    if (lhd->index < rhd->index)
696
0
        return -1;
697
0
    else if (lhd->index > rhd->index)
698
0
        return 1;
699
700
0
    return 0;
701
0
}
702
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_LONG */
703
704
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_ULONG
705
int
706
netsnmp_compare_ulong(const void * lhs, const void * rhs)
707
0
{
708
0
    typedef struct { u_long index; } dummy;
709
710
0
    const dummy *lhd = (const dummy*)lhs;
711
0
    const dummy *rhd = (const dummy*)rhs;
712
713
0
    if (lhd->index < rhd->index)
714
0
        return -1;
715
0
    else if (lhd->index > rhd->index)
716
0
        return 1;
717
718
0
    return 0;
719
0
}
720
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_ULONG */
721
722
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_INT32
723
int
724
netsnmp_compare_int32(const void * lhs, const void * rhs)
725
0
{
726
0
    typedef struct { int32_t index; } dummy;
727
728
0
    const dummy *lhd = (const dummy*)lhs;
729
0
    const dummy *rhd = (const dummy*)rhs;
730
731
0
    if (lhd->index < rhd->index)
732
0
        return -1;
733
0
    else if (lhd->index > rhd->index)
734
0
        return 1;
735
736
0
    return 0;
737
0
}
738
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_INT32 */
739
740
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_UINT32
741
int
742
netsnmp_compare_uint32(const void * lhs, const void * rhs)
743
0
{
744
0
    typedef struct { uint32_t index; } dummy;
745
746
0
    const dummy *lhd = (const dummy*)lhs;
747
0
    const dummy *rhd = (const dummy*)rhs;
748
749
0
    if (lhd->index < rhd->index)
750
0
        return -1;
751
0
    else if (lhd->index > rhd->index)
752
0
        return 1;
753
754
0
    return 0;
755
0
}
756
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_UINT32 */
757
758
/*------------------------------------------------------------------
759
 * netsnmp_container_simple_free
760
 *
761
 * useful function to pass to CONTAINER_FOR_EACH, when a simple
762
 * free is needed for every item.
763
 */
764
void 
765
netsnmp_container_simple_free(void *data, void *context)
766
0
{
767
0
    if (data == NULL)
768
0
  return;
769
    
770
0
    DEBUGMSGTL(("verbose:container",
771
0
                "netsnmp_container_simple_free) called for %p/%p\n",
772
0
                data, context));
773
0
    free(data); /* SNMP_FREE wasted on param */
774
0
}
775
776
int netsnmp_str_compare(const void *left, const void *right)
777
0
{
778
0
    return strcmp(left, right);
779
0
}