/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 | 1 | { |
83 | 1 | if (NULL != containers) |
84 | 0 | return; |
85 | | |
86 | | /* |
87 | | * create a binary array container to hold container |
88 | | * factories |
89 | | */ |
90 | 1 | containers = netsnmp_container_get_binary_array(); |
91 | 1 | containers->compare = netsnmp_compare_cstring; |
92 | 1 | containers->container_name = strdup("container list"); |
93 | | |
94 | | /* |
95 | | * register containers |
96 | | */ |
97 | 1 | netsnmp_container_binary_array_init(); |
98 | 1 | #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST |
99 | 1 | netsnmp_container_ssll_init(); |
100 | 1 | #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST */ |
101 | 1 | #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_NULL |
102 | 1 | netsnmp_container_null_init(); |
103 | 1 | #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_NULL */ |
104 | | |
105 | | /* |
106 | | * default aliases for some containers |
107 | | */ |
108 | 1 | netsnmp_container_register("table_container", |
109 | 1 | netsnmp_container_get_factory("binary_array")); |
110 | | |
111 | 1 | #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST |
112 | 1 | netsnmp_container_register("linked_list", |
113 | 1 | netsnmp_container_get_factory("sorted_singly_linked_list")); |
114 | 1 | netsnmp_container_register("ssll_container", |
115 | 1 | netsnmp_container_get_factory("sorted_singly_linked_list")); |
116 | 1 | #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST */ |
117 | | |
118 | 1 | netsnmp_container_register_with_compare |
119 | 1 | ("cstring", netsnmp_container_get_factory("binary_array"), |
120 | 1 | netsnmp_compare_direct_cstring); |
121 | | |
122 | 1 | netsnmp_container_register_with_compare |
123 | 1 | ("string", netsnmp_container_get_factory("binary_array"), |
124 | 1 | netsnmp_compare_cstring); |
125 | 1 | netsnmp_container_register_with_compare |
126 | 1 | ("string_binary_array", netsnmp_container_get_factory("binary_array"), |
127 | 1 | netsnmp_compare_cstring); |
128 | | |
129 | 1 | } |
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 | 12 | { |
154 | 12 | container_type *ct, tmp; |
155 | | |
156 | 12 | if (NULL==containers) |
157 | 0 | return -1; |
158 | | |
159 | 12 | tmp.name = NETSNMP_REMOVE_CONST(char *, name); |
160 | 12 | ct = (container_type *)CONTAINER_FIND(containers, &tmp); |
161 | 12 | if (NULL!=ct) { |
162 | 0 | DEBUGMSGT(("container_registry", |
163 | 0 | "replacing previous container factory\n")); |
164 | 0 | ct->factory = f; |
165 | 0 | } |
166 | 12 | else { |
167 | 12 | ct = SNMP_MALLOC_TYPEDEF(container_type); |
168 | 12 | if (NULL == ct) |
169 | 0 | return -1; |
170 | 12 | ct->name = strdup(name); |
171 | 12 | ct->factory = f; |
172 | 12 | ct->compare = c; |
173 | 12 | CONTAINER_INSERT(containers, ct); |
174 | 12 | } |
175 | 12 | DEBUGMSGT(("container_registry", "registered container factory %s (%s)\n", |
176 | 12 | ct->name, f->product)); |
177 | | |
178 | 12 | return 0; |
179 | 12 | } |
180 | | |
181 | | int |
182 | | netsnmp_container_register(const char* name, netsnmp_factory *f) |
183 | 9 | { |
184 | 9 | return netsnmp_container_register_with_compare(name, f, NULL); |
185 | 9 | } |
186 | | |
187 | | /*------------------------------------------------------------------ |
188 | | */ |
189 | | netsnmp_factory * |
190 | | netsnmp_container_get_factory(const char *type) |
191 | 6 | { |
192 | 6 | container_type ct, *found; |
193 | | |
194 | 6 | if (NULL==containers) |
195 | 0 | return NULL; |
196 | | |
197 | 6 | ct.name = type; |
198 | 6 | found = (container_type *)CONTAINER_FIND(containers, &ct); |
199 | | |
200 | 6 | return found ? found->factory : NULL; |
201 | 6 | } |
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 | 12 | { |
235 | 12 | container_type ct; |
236 | | |
237 | 12 | if (NULL == containers) |
238 | 0 | return NULL; |
239 | | |
240 | 12 | ct.name = type; |
241 | 12 | return (container_type *)CONTAINER_FIND(containers, &ct); |
242 | 12 | } |
243 | | |
244 | | static container_type * |
245 | | netsnmp_container_find_ct(const char *type_list) |
246 | 6 | { |
247 | 6 | container_type *ct = NULL; |
248 | 6 | char *list, *entry; |
249 | 6 | char *st = NULL; |
250 | | |
251 | 6 | if (NULL==type_list) |
252 | 0 | return NULL; |
253 | | |
254 | 6 | list = strdup(type_list); |
255 | 6 | if (!list) |
256 | 0 | return NULL; |
257 | 6 | entry = strtok_r(list, ":", &st); |
258 | 12 | while (entry) { |
259 | 12 | ct = netsnmp_container_get_ct(entry); |
260 | 12 | if (NULL != ct) |
261 | 6 | break; |
262 | 6 | entry = strtok_r(NULL, ":", &st); |
263 | 6 | } |
264 | | |
265 | 6 | free(list); |
266 | 6 | return ct; |
267 | 6 | } |
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 | 6 | { |
301 | 6 | container_type *ct = netsnmp_container_find_ct(type); |
302 | 6 | netsnmp_container *c = ct ? (netsnmp_container *)(ct->factory->produce()) : NULL; |
303 | | |
304 | | /* |
305 | | * provide default compare and ncompare |
306 | | */ |
307 | 6 | if (c) { |
308 | 6 | if (ct->compare) |
309 | 0 | c->compare = ct->compare; |
310 | 6 | else if (NULL == c->compare) |
311 | 6 | c->compare = netsnmp_compare_netsnmp_index; |
312 | | |
313 | 6 | if (NULL == c->ncompare) |
314 | 6 | c->ncompare = netsnmp_ncompare_netsnmp_index; |
315 | 6 | } |
316 | | |
317 | 6 | return c; |
318 | 6 | } |
319 | | |
320 | | /*------------------------------------------------------------------ |
321 | | */ |
322 | | void |
323 | | netsnmp_container_add_index(netsnmp_container *primary, |
324 | | netsnmp_container *new_index) |
325 | 3 | { |
326 | 3 | netsnmp_container *curr = primary; |
327 | | |
328 | 3 | 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 | 6 | while(curr->next) |
334 | 3 | curr = curr->next; |
335 | | |
336 | 3 | curr->next = new_index; |
337 | 3 | new_index->prev = curr; |
338 | 3 | } |
339 | | |
340 | | int CONTAINER_INSERT_HELPER(netsnmp_container* x, const void* k) |
341 | 24 | { |
342 | 24 | while(x && x->insert_filter && x->insert_filter(x,k) == 1) |
343 | 0 | x = x->next; |
344 | 24 | if(x) { |
345 | 12 | int rc = x->insert(x,k); |
346 | 12 | 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 | 12 | else { |
350 | 12 | rc = CONTAINER_INSERT_HELPER(x->next, k); |
351 | 12 | if(rc) |
352 | 0 | x->remove(x,k); |
353 | 12 | } |
354 | 12 | return rc; |
355 | 12 | } |
356 | 12 | return 0; |
357 | 24 | } |
358 | | |
359 | | int CONTAINER_INSERT(netsnmp_container* x, const void* k) |
360 | 12 | { |
361 | | /** start at first container */ |
362 | 12 | while(x->prev) |
363 | 0 | x = x->prev; |
364 | 12 | return CONTAINER_INSERT_HELPER(x, k); |
365 | 12 | } |
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 | 1 | { |
470 | 1 | int rc2, rc = 0; |
471 | | |
472 | 1 | if (!x) |
473 | 0 | return rc; |
474 | | |
475 | | /** start at last container */ |
476 | 1 | while(x->next) |
477 | 0 | x = x->next; |
478 | 2 | while(x) { |
479 | 1 | netsnmp_container *tmp; |
480 | 1 | char *name; |
481 | 1 | tmp = x->prev; |
482 | 1 | name = x->container_name; |
483 | 1 | x->container_name = NULL; |
484 | 1 | rc2 = x->cfree(x); |
485 | 1 | 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 | 1 | SNMP_FREE(name); |
491 | 1 | x = tmp; |
492 | 1 | } |
493 | 1 | return rc; |
494 | 1 | } |
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 | 1 | { |
504 | | /** start at last container */ |
505 | 1 | while(x->next) |
506 | 0 | x = x->next; |
507 | 1 | while(x->prev) { |
508 | 0 | x->clear(x, NULL, c); |
509 | 0 | x = x->prev; |
510 | 0 | } |
511 | 1 | x->clear(x, f, c); |
512 | 1 | #ifdef HAVE_MALLOC_TRIM |
513 | 1 | malloc_trim(0); |
514 | 1 | #endif |
515 | 1 | } |
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 | 1 | { |
525 | 1 | CONTAINER_CLEAR(x, x->free_item, c); |
526 | 1 | } |
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 | 7 | { |
564 | 7 | if (c == NULL) |
565 | 0 | return; |
566 | | |
567 | 7 | c->init = init; |
568 | 7 | c->cfree = cfree; |
569 | 7 | c->get_size = size; |
570 | 7 | c->compare = cmp; |
571 | 7 | c->insert = ins; |
572 | 7 | c->remove = rem; |
573 | 7 | c->find = fnd; |
574 | 7 | c->free_item = netsnmp_container_simple_free; |
575 | 7 | } |
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 | 149 | { |
644 | 149 | const container_type *lhs = lhs_arg; |
645 | 149 | const container_type *rhs = rhs_arg; |
646 | | |
647 | 149 | return strcmp(lhs->name, rhs->name); |
648 | 149 | } |
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 | } |