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