net-snmp 5.7
container.c
00001 /* Portions of this file are subject to the following copyright(s).  See
00002  * the Net-SNMP's COPYING file for more details and other copyrights
00003  * that may apply:
00004  */
00005 /*
00006  * Portions of this file are copyrighted by:
00007  * Copyright (C) 2007 Apple, Inc. All rights reserved.
00008  * Use is subject to license terms specified in the COPYING file
00009  * distributed with the Net-SNMP package.
00010  */
00011 #include <net-snmp/net-snmp-config.h>
00012 #include <net-snmp/net-snmp-features.h>
00013 #include <net-snmp/net-snmp-includes.h>
00014 #include <net-snmp/library/container.h>
00015 #include <net-snmp/library/container_binary_array.h>
00016 #include <net-snmp/library/container_list_ssll.h>
00017 #include <net-snmp/library/container_null.h>
00018 
00019 netsnmp_feature_child_of(container_all, libnetsnmp)
00020 
00021 netsnmp_feature_child_of(container_factories, container_all)
00022 netsnmp_feature_child_of(container_types, container_all)
00023 netsnmp_feature_child_of(container_compare, container_all)
00024 netsnmp_feature_child_of(container_dup, container_all)
00025 netsnmp_feature_child_of(container_free_all, container_all)
00026 netsnmp_feature_child_of(subcontainer_find, container_all)
00027 
00028 netsnmp_feature_child_of(container_ncompare_cstring, container_compare)
00029 netsnmp_feature_child_of(container_compare_mem, container_compare)
00030 netsnmp_feature_child_of(container_compare_long, container_compare)
00031 netsnmp_feature_child_of(container_compare_ulong, container_compare)
00032 netsnmp_feature_child_of(container_compare_int32, container_compare)
00033 netsnmp_feature_child_of(container_compare_uint32, container_compare)
00034 
00035 netsnmp_feature_child_of(container_find_factory, container_factories)
00036 
00040 /*------------------------------------------------------------------
00041  */
00042 static netsnmp_container *containers = NULL;
00043 
00044 typedef struct container_type_s {
00045    const char                 *name;
00046    netsnmp_factory            *factory;
00047    netsnmp_container_compare  *compare;
00048 } container_type;
00049 
00050 netsnmp_factory *
00051 netsnmp_container_get_factory(const char *type);
00052 
00053 /*------------------------------------------------------------------
00054  */
00055 static void 
00056 _factory_free(void *dat, void *context)
00057 {
00058     container_type *data = (container_type *)dat;
00059     if (data == NULL)
00060         return;
00061     
00062     if (data->name != NULL) {
00063         DEBUGMSGTL(("container", "  _factory_free_list() called for %s\n",
00064                     data->name));
00065         free(NETSNMP_REMOVE_CONST(void *, data->name)); /* SNMP_FREE wasted on object about to be freed */
00066     }
00067     free(data); /* SNMP_FREE wasted on param */
00068 }
00069 
00070 /*------------------------------------------------------------------
00071  */
00072 void
00073 netsnmp_container_init_list(void)
00074 {
00075     if (NULL != containers)
00076         return;
00077 
00078     /*
00079      * create a binary arry container to hold container
00080      * factories
00081      */
00082     containers = netsnmp_container_get_binary_array();
00083     containers->compare = netsnmp_compare_cstring;
00084     containers->container_name = strdup("container list");
00085 
00086     /*
00087      * register containers
00088      */
00089     netsnmp_container_binary_array_init();
00090 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST
00091     netsnmp_container_ssll_init();
00092 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST */
00093 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_NULL
00094     netsnmp_container_null_init();
00095 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_NULL */
00096 
00097     /*
00098      * default aliases for some containers
00099      */
00100     netsnmp_container_register("table_container",
00101                                netsnmp_container_get_factory("binary_array"));
00102 
00103 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST
00104     netsnmp_container_register("linked_list",
00105                                netsnmp_container_get_factory("sorted_singly_linked_list"));
00106     netsnmp_container_register("ssll_container",
00107                                netsnmp_container_get_factory("sorted_singly_linked_list"));
00108 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST */
00109 
00110     netsnmp_container_register_with_compare
00111         ("cstring", netsnmp_container_get_factory("binary_array"),
00112          netsnmp_compare_direct_cstring);
00113 
00114     netsnmp_container_register_with_compare
00115         ("string", netsnmp_container_get_factory("binary_array"),
00116          netsnmp_compare_cstring);
00117     netsnmp_container_register_with_compare
00118         ("string_binary_array", netsnmp_container_get_factory("binary_array"),
00119          netsnmp_compare_cstring);
00120 
00121 }
00122 
00123 void
00124 netsnmp_container_free_list(void)
00125 {
00126     DEBUGMSGTL(("container", "netsnmp_container_free_list() called\n"));
00127     if (containers == NULL)
00128         return;
00129 
00130     /*
00131      * free memory used by each factory entry
00132      */
00133     CONTAINER_FOR_EACH(containers, ((netsnmp_container_obj_func *)_factory_free), NULL);
00134 
00135     /*
00136      * free factory container
00137      */
00138     CONTAINER_FREE(containers);
00139     containers = NULL;
00140 }
00141 
00142 int
00143 netsnmp_container_register_with_compare(const char* name, netsnmp_factory *f,
00144                                         netsnmp_container_compare  *c)
00145 {
00146     container_type *ct, tmp;
00147 
00148     if (NULL==containers)
00149         return -1;
00150 
00151     tmp.name = NETSNMP_REMOVE_CONST(char *, name);
00152     ct = (container_type *)CONTAINER_FIND(containers, &tmp);
00153     if (NULL!=ct) {
00154         DEBUGMSGT(("container_registry",
00155                    "replacing previous container factory\n"));
00156         ct->factory = f;
00157     }
00158     else {
00159         ct = SNMP_MALLOC_TYPEDEF(container_type);
00160         if (NULL == ct)
00161             return -1;
00162         ct->name = strdup(name);
00163         ct->factory = f;
00164         ct->compare = c;
00165         CONTAINER_INSERT(containers, ct);
00166     }
00167     DEBUGMSGT(("container_registry", "registered container factory %s (%s)\n",
00168                ct->name, f->product));
00169 
00170     return 0;
00171 }
00172 
00173 int
00174 netsnmp_container_register(const char* name, netsnmp_factory *f)
00175 {
00176     return netsnmp_container_register_with_compare(name, f, NULL);
00177 }
00178 
00179 /*------------------------------------------------------------------
00180  */
00181 netsnmp_factory *
00182 netsnmp_container_get_factory(const char *type)
00183 {
00184     container_type ct, *found;
00185     
00186     if (NULL==containers)
00187         return NULL;
00188 
00189     ct.name = type;
00190     found = (container_type *)CONTAINER_FIND(containers, &ct);
00191 
00192     return found ? found->factory : NULL;
00193 }
00194 
00195 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_FIND_FACTORY
00196 netsnmp_factory *
00197 netsnmp_container_find_factory(const char *type_list)
00198 {
00199     netsnmp_factory   *f = NULL;
00200     char              *list, *entry;
00201     char              *st = NULL;
00202 
00203     if (NULL==type_list)
00204         return NULL;
00205 
00206     list = strdup(type_list);
00207     entry = strtok_r(list, ":", &st);
00208     while(entry) {
00209         f = netsnmp_container_get_factory(entry);
00210         if (NULL != f)
00211             break;
00212         entry = strtok_r(NULL, ":", &st);
00213     }
00214 
00215     free(list);
00216     return f;
00217 }
00218 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_FIND_FACTORY */
00219 
00220 /*------------------------------------------------------------------
00221  */
00222 static container_type *
00223 netsnmp_container_get_ct(const char *type)
00224 {
00225     container_type ct;
00226 
00227     if (NULL == containers)
00228         return NULL;
00229     
00230     ct.name = type;
00231     return (container_type *)CONTAINER_FIND(containers, &ct);
00232 }
00233 
00234 static container_type *
00235 netsnmp_container_find_ct(const char *type_list)
00236 {
00237     container_type    *ct = NULL;
00238     char              *list, *entry;
00239     char              *st = NULL;
00240 
00241     if (NULL==type_list)
00242         return NULL;
00243 
00244     list = strdup(type_list);
00245     entry = strtok_r(list, ":", &st);
00246     while(entry) {
00247         ct = netsnmp_container_get_ct(entry);
00248         if (NULL != ct)
00249             break;
00250         entry = strtok_r(NULL, ":", &st);
00251     }
00252 
00253     free(list);
00254     return ct;
00255 }
00256 
00257 
00258 
00259 /*------------------------------------------------------------------
00260  */
00261 netsnmp_container *
00262 netsnmp_container_get(const char *type)
00263 {
00264     netsnmp_container *c;
00265     container_type *ct = netsnmp_container_get_ct(type);
00266     if (ct) {
00267         c = (netsnmp_container *)(ct->factory->produce());
00268         if (c && ct->compare)
00269             c->compare = ct->compare;
00270         return c;
00271     }
00272 
00273     return NULL;
00274 }
00275 
00276 /*------------------------------------------------------------------
00277  */
00278 netsnmp_container *
00279 netsnmp_container_find(const char *type)
00280 {
00281     container_type *ct = netsnmp_container_find_ct(type);
00282     netsnmp_container *c = ct ? (netsnmp_container *)(ct->factory->produce()) : NULL;
00283 
00284     /*
00285      * provide default compare
00286      */
00287     if (c) {
00288         if (ct->compare)
00289             c->compare = ct->compare;
00290         else if (NULL == c->compare)
00291             c->compare = netsnmp_compare_netsnmp_index;
00292     }
00293 
00294     return c;
00295 }
00296 
00297 /*------------------------------------------------------------------
00298  */
00299 void
00300 netsnmp_container_add_index(netsnmp_container *primary,
00301                             netsnmp_container *new_index)
00302 {
00303     netsnmp_container *curr = primary;
00304 
00305     if((NULL == new_index) || (NULL == primary)) {
00306         snmp_log(LOG_ERR, "add index called with null pointer\n");
00307         return;
00308     }
00309 
00310     while(curr->next)
00311         curr = curr->next;
00312 
00313     curr->next = new_index;
00314     new_index->prev = curr;
00315 }
00316 
00317 /*------------------------------------------------------------------
00318  * These functions should EXACTLY match the inline version in
00319  * container.h. If you change one, change them both.
00320  */
00321 int CONTAINER_INSERT_HELPER(netsnmp_container* x, const void* k)
00322 {
00323     while(x && x->insert_filter && x->insert_filter(x,k) == 1)
00324         x = x->next;
00325     if(x) {
00326         int rc = x->insert(x,k);
00327         if(rc)
00328             snmp_log(LOG_DEBUG,"error on subcontainer '%s' insert (%d)\n",
00329                      x->container_name ? x->container_name : "", rc);
00330         else {
00331             rc = CONTAINER_INSERT_HELPER(x->next, k);
00332             if(rc)
00333                 x->remove(x,k);
00334         }
00335         return rc;
00336     }
00337     return 0;
00338 }
00339 
00340 /*------------------------------------------------------------------
00341  * These functions should EXACTLY match the inline version in
00342  * container.h. If you change one, change them both.
00343  */
00344 int CONTAINER_INSERT(netsnmp_container* x, const void* k)
00345 {
00347     while(x->prev)
00348         x = x->prev;
00349     return CONTAINER_INSERT_HELPER(x, k);
00350 }
00351 
00352 /*------------------------------------------------------------------
00353  * These functions should EXACTLY match the inline version in
00354  * container.h. If you change one, change them both.
00355  */
00356 int CONTAINER_REMOVE(netsnmp_container *x, const void *k)
00357 {
00358     int rc2, rc = 0;
00359     
00361     while(x->next)
00362         x = x->next;
00363     while(x) {
00364         rc2 = x->remove(x,k);
00366         if ((rc2) && (NULL == x->insert_filter)) {
00367             snmp_log(LOG_ERR,"error on subcontainer '%s' remove (%d)\n",
00368                      x->container_name ? x->container_name : "", rc2);
00369             rc = rc2;
00370         }
00371         x = x->prev;
00372         
00373     }
00374     return rc;
00375 }
00376 
00377 /*------------------------------------------------------------------
00378  * These functions should EXACTLY match the function version in
00379  * container.c. If you change one, change them both.
00380  */
00381 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_DUP
00382 netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx, u_int flags)
00383 {
00384     if (NULL == x->duplicate) {
00385         snmp_log(LOG_ERR, "container '%s' does not support duplicate\n",
00386                  x->container_name ? x->container_name : "");
00387         return NULL;
00388     }
00389     return x->duplicate(x, ctx, flags);
00390 }
00391 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_DUP */
00392 
00393 /*------------------------------------------------------------------
00394  * These functions should EXACTLY match the inline version in
00395  * container.h. If you change one, change them both.
00396  */
00397 int CONTAINER_FREE(netsnmp_container *x)
00398 {
00399     int  rc2, rc = 0;
00400         
00402     while(x->next)
00403         x = x->next;
00404     while(x) {
00405         netsnmp_container *tmp;
00406         char *name;
00407         tmp = x->prev;
00408         name = x->container_name;
00409         x->container_name = NULL;
00410         rc2 = x->cfree(x);
00411         if (rc2) {
00412             snmp_log(LOG_ERR,"error on subcontainer '%s' cfree (%d)\n",
00413                      name ? name : "", rc2);
00414             rc = rc2;
00415         }
00416         SNMP_FREE(name);
00417         x = tmp;
00418     }
00419     return rc;
00420 }
00421 
00422 /*------------------------------------------------------------------
00423  * These functions should EXACTLY match the function version in
00424  * container.c. If you change one, change them both.
00425  */
00426 /*
00427  * clear all containers. When clearing the *first* container, and
00428  * *only* the first container, call the function f for each item.
00429  * After calling this function, all containers should be empty.
00430  */
00431 void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
00432                     void *c)
00433 {
00435     while(x->next)
00436         x = x->next;
00437     while(x->prev) {
00438         x->clear(x, NULL, c);
00439         x = x->prev;
00440     }
00441     x->clear(x, f, c);
00442 }
00443 
00444 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_FREE_ALL
00445 /*
00446  * clear all containers. When clearing the *first* container, and
00447  * *only* the first container, call the free_item function for each item.
00448  * After calling this function, all containers should be empty.
00449  */
00450 void CONTAINER_FREE_ALL(netsnmp_container *x, void *c)
00451 {
00452     CONTAINER_CLEAR(x, x->free_item, c);
00453 }
00454 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_FREE_ALL */
00455 
00456 #ifndef NETSNMP_FEATURE_REMOVE_SUBCONTAINER_FIND
00457 /*------------------------------------------------------------------
00458  * These functions should EXACTLY match the function version in
00459  * container.c. If you change one, change them both.
00460  */
00461 /*
00462  * Find a sub-container with the given name
00463  */
00464 netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
00465                                      const char* name)
00466 {
00467     if ((NULL == x) || (NULL == name))
00468         return NULL;
00469     
00471     while(x->prev)
00472         x = x->prev;
00473     while(x) {
00474         if ((NULL != x->container_name) && (0 == strcmp(name,x->container_name)))
00475             break;
00476         x = x->next;
00477     }
00478     return x;
00479 }
00480 #endif /* NETSNMP_FEATURE_REMOVE_SUBCONTAINER_FIND */
00481 
00482 
00483 /*------------------------------------------------------------------
00484  */
00485 void
00486 netsnmp_init_container(netsnmp_container         *c,
00487                        netsnmp_container_rc      *init,
00488                        netsnmp_container_rc      *cfree,
00489                        netsnmp_container_size    *size,
00490                        netsnmp_container_compare *cmp,
00491                        netsnmp_container_op      *ins,
00492                        netsnmp_container_op      *rem,
00493                        netsnmp_container_rtn     *fnd)
00494 {
00495     if (c == NULL)
00496         return;
00497 
00498     c->init = init;
00499     c->cfree = cfree;
00500     c->get_size = size;
00501     c->compare = cmp;
00502     c->insert = ins;
00503     c->remove = rem;
00504     c->find = fnd;
00505     c->free_item = netsnmp_container_simple_free;
00506 }
00507 
00508 int
00509 netsnmp_container_data_dup(netsnmp_container *dup, netsnmp_container *c)
00510 {
00511     if (!dup || !c)
00512         return -1;
00513 
00514     if (c->container_name)
00515         dup->container_name = strdup(c->container_name);
00516     dup->compare = c->compare;
00517     dup->ncompare = c->ncompare;
00518     dup->release = c->release;
00519     dup->insert_filter = c->insert_filter;
00520     dup->free_item = c->free_item;
00521     dup->sync = c->sync;
00522     dup->flags = c->flags;
00523 
00524     return 0;
00525 }
00526 
00527 /*------------------------------------------------------------------
00528  *
00529  * simple comparison routines
00530  *
00531  */
00532 int
00533 netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs)
00534 {
00535     int rc;
00536     netsnmp_assert((NULL != lhs) && (NULL != rhs));
00537     DEBUGIF("compare:index") {
00538         DEBUGMSGT(("compare:index", "compare "));
00539         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
00540                      ((const netsnmp_index *) lhs)->len));
00541         DEBUGMSG(("compare:index", " to "));
00542         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
00543                      ((const netsnmp_index *) rhs)->len));
00544         DEBUGMSG(("compare:index", "\n"));
00545     }
00546     rc = snmp_oid_compare(((const netsnmp_index *) lhs)->oids,
00547                           ((const netsnmp_index *) lhs)->len,
00548                           ((const netsnmp_index *) rhs)->oids,
00549                           ((const netsnmp_index *) rhs)->len);
00550     DEBUGMSGT(("compare:index", "result was %d\n", rc));
00551     return rc;
00552 }
00553 
00554 int
00555 netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs)
00556 {
00557     int rc;
00558     netsnmp_assert((NULL != lhs) && (NULL != rhs));
00559     DEBUGIF("compare:index") {
00560         DEBUGMSGT(("compare:index", "compare "));
00561         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
00562                      ((const netsnmp_index *) lhs)->len));
00563         DEBUGMSG(("compare:index", " to "));
00564         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
00565                      ((const netsnmp_index *) rhs)->len));
00566         DEBUGMSG(("compare:index", "\n"));
00567     }
00568     rc = snmp_oid_ncompare(((const netsnmp_index *) lhs)->oids,
00569                            ((const netsnmp_index *) lhs)->len,
00570                            ((const netsnmp_index *) rhs)->oids,
00571                            ((const netsnmp_index *) rhs)->len,
00572                            ((const netsnmp_index *) rhs)->len);
00573     DEBUGMSGT(("compare:index", "result was %d\n", rc));
00574     return rc;
00575 }
00576 
00577 int
00578 netsnmp_compare_cstring(const void * lhs, const void * rhs)
00579 {
00580     return strcmp(((const container_type*)lhs)->name,
00581                   ((const container_type*)rhs)->name);
00582 }
00583 
00584 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_NCOMPARE_CSTRING
00585 int
00586 netsnmp_ncompare_cstring(const void * lhs, const void * rhs)
00587 {
00588     return strncmp(((const container_type*)lhs)->name,
00589                    ((const container_type*)rhs)->name,
00590                    strlen(((const container_type*)rhs)->name));
00591 }
00592 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_NCOMPARE_CSTRING */
00593 
00594 int
00595 netsnmp_compare_direct_cstring(const void * lhs, const void * rhs)
00596 {
00597     return strcmp((const char*)lhs, (const char*)rhs);
00598 }
00599 
00600 /*
00601  * compare two memory buffers
00602  *
00603  * since snmp strings aren't NULL terminated, we can't use strcmp. So
00604  * compare up to the length of the smaller, and then use length to
00605  * break any ties.
00606  */
00607 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_MEM
00608 int
00609 netsnmp_compare_mem(const char * lhs, size_t lhs_len,
00610                     const char * rhs, size_t rhs_len)
00611 {
00612     int rc, min = SNMP_MIN(lhs_len, rhs_len);
00613 
00614     rc = memcmp(lhs, rhs, min);
00615     if((rc==0) && (lhs_len != rhs_len)) {
00616         if(lhs_len < rhs_len)
00617             rc = -1;
00618         else
00619             rc = 1;
00620     }
00621 
00622     return rc;
00623 }
00624 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_MEM */
00625 
00626 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_LONG
00627 int
00628 netsnmp_compare_long(const void * lhs, const void * rhs)
00629 {
00630     typedef struct { long index; } dummy;
00631 
00632     const dummy *lhd = (const dummy*)lhs;
00633     const dummy *rhd = (const dummy*)rhs;
00634 
00635     if (lhd->index < rhd->index)
00636         return -1;
00637     else if (lhd->index > rhd->index)
00638         return 1;
00639 
00640     return 0;
00641 }
00642 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_LONG */
00643 
00644 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_ULONG
00645 int
00646 netsnmp_compare_ulong(const void * lhs, const void * rhs)
00647 {
00648     typedef struct { u_long index; } dummy;
00649 
00650     const dummy *lhd = (const dummy*)lhs;
00651     const dummy *rhd = (const dummy*)rhs;
00652 
00653     if (lhd->index < rhd->index)
00654         return -1;
00655     else if (lhd->index > rhd->index)
00656         return 1;
00657 
00658     return 0;
00659 }
00660 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_ULONG */
00661 
00662 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_INT32
00663 int
00664 netsnmp_compare_int32(const void * lhs, const void * rhs)
00665 {
00666     typedef struct { int32_t index; } dummy;
00667 
00668     const dummy *lhd = (const dummy*)lhs;
00669     const dummy *rhd = (const dummy*)rhs;
00670 
00671     if (lhd->index < rhd->index)
00672         return -1;
00673     else if (lhd->index > rhd->index)
00674         return 1;
00675 
00676     return 0;
00677 }
00678 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_INT32 */
00679 
00680 #ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_UINT32
00681 int
00682 netsnmp_compare_uint32(const void * lhs, const void * rhs)
00683 {
00684     typedef struct { uint32_t index; } dummy;
00685 
00686     const dummy *lhd = (const dummy*)lhs;
00687     const dummy *rhd = (const dummy*)rhs;
00688 
00689     if (lhd->index < rhd->index)
00690         return -1;
00691     else if (lhd->index > rhd->index)
00692         return 1;
00693 
00694     return 0;
00695 }
00696 #endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_UINT32 */
00697 
00698 /*------------------------------------------------------------------
00699  * netsnmp_container_simple_free
00700  *
00701  * useful function to pass to CONTAINER_FOR_EACH, when a simple
00702  * free is needed for every item.
00703  */
00704 void 
00705 netsnmp_container_simple_free(void *data, void *context)
00706 {
00707     if (data == NULL)
00708         return;
00709     
00710     DEBUGMSGTL(("verbose:container",
00711                 "netsnmp_container_simple_free) called for %p/%p\n",
00712                 data, context));
00713     free((void*)data); /* SNMP_FREE wasted on param */
00714 }