Blame snmplib/container.c

Packit fcad23
/* Portions of this file are subject to the following copyright(s).  See
Packit fcad23
 * the Net-SNMP's COPYING file for more details and other copyrights
Packit fcad23
 * that may apply:
Packit fcad23
 */
Packit fcad23
/*
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright (C) 2007 Apple, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
Packit fcad23
 *
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
Packit fcad23
 */
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include <net-snmp/library/container.h>
Packit fcad23
#include <net-snmp/library/container_binary_array.h>
Packit fcad23
#include <net-snmp/library/container_list_ssll.h>
Packit fcad23
#include <net-snmp/library/container_null.h>
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(container_all, libnetsnmp)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(container_factories, container_all)
Packit fcad23
netsnmp_feature_child_of(container_types, container_all)
Packit fcad23
netsnmp_feature_child_of(container_compare, container_all)
Packit fcad23
netsnmp_feature_child_of(container_dup, container_all)
Packit fcad23
netsnmp_feature_child_of(container_free_all, container_all)
Packit fcad23
netsnmp_feature_child_of(subcontainer_find, container_all)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(container_ncompare_cstring, container_compare)
Packit fcad23
netsnmp_feature_child_of(container_compare_mem, container_compare)
Packit fcad23
netsnmp_feature_child_of(container_compare_long, container_compare)
Packit fcad23
netsnmp_feature_child_of(container_compare_ulong, container_compare)
Packit fcad23
netsnmp_feature_child_of(container_compare_int32, container_compare)
Packit fcad23
netsnmp_feature_child_of(container_compare_uint32, container_compare)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(container_find_factory, container_factories)
Packit fcad23
Packit fcad23
/** @defgroup container container
Packit fcad23
 */
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
static netsnmp_container *containers = NULL;
Packit fcad23
Packit fcad23
typedef struct container_type_s {
Packit fcad23
   const char                 *name;
Packit fcad23
   netsnmp_factory            *factory;
Packit fcad23
   netsnmp_container_compare  *compare;
Packit fcad23
} container_type;
Packit fcad23
Packit fcad23
netsnmp_factory *
Packit fcad23
netsnmp_container_get_factory(const char *type);
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
static void 
Packit fcad23
_factory_free(void *dat, void *context)
Packit fcad23
{
Packit fcad23
    container_type *data = (container_type *)dat;
Packit fcad23
    if (data == NULL)
Packit fcad23
	return;
Packit fcad23
    
Packit fcad23
    if (data->name != NULL) {
Packit fcad23
        DEBUGMSGTL(("container", "  _factory_free_list() called for %s\n",
Packit fcad23
                    data->name));
Packit fcad23
	free(NETSNMP_REMOVE_CONST(void *, data->name)); /* SNMP_FREE wasted on object about to be freed */
Packit fcad23
    }
Packit fcad23
    free(data); /* SNMP_FREE wasted on param */
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
netsnmp_container_init_list(void)
Packit fcad23
{
Packit fcad23
    if (NULL != containers)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * create a binary arry container to hold container
Packit fcad23
     * factories
Packit fcad23
     */
Packit fcad23
    containers = netsnmp_container_get_binary_array();
Packit fcad23
    containers->compare = netsnmp_compare_cstring;
Packit fcad23
    containers->container_name = strdup("container list");
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * register containers
Packit fcad23
     */
Packit fcad23
    netsnmp_container_binary_array_init();
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST
Packit fcad23
    netsnmp_container_ssll_init();
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST */
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_NULL
Packit fcad23
    netsnmp_container_null_init();
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_NULL */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * default aliases for some containers
Packit fcad23
     */
Packit fcad23
    netsnmp_container_register("table_container",
Packit fcad23
                               netsnmp_container_get_factory("binary_array"));
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST
Packit fcad23
    netsnmp_container_register("linked_list",
Packit fcad23
                               netsnmp_container_get_factory("sorted_singly_linked_list"));
Packit fcad23
    netsnmp_container_register("ssll_container",
Packit fcad23
                               netsnmp_container_get_factory("sorted_singly_linked_list"));
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_LINKED_LIST */
Packit fcad23
Packit fcad23
    netsnmp_container_register_with_compare
Packit fcad23
        ("cstring", netsnmp_container_get_factory("binary_array"),
Packit fcad23
         netsnmp_compare_direct_cstring);
Packit fcad23
Packit fcad23
    netsnmp_container_register_with_compare
Packit fcad23
        ("string", netsnmp_container_get_factory("binary_array"),
Packit fcad23
         netsnmp_compare_cstring);
Packit fcad23
    netsnmp_container_register_with_compare
Packit fcad23
        ("string_binary_array", netsnmp_container_get_factory("binary_array"),
Packit fcad23
         netsnmp_compare_cstring);
Packit fcad23
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_container_free_list(void)
Packit fcad23
{
Packit fcad23
    DEBUGMSGTL(("container", "netsnmp_container_free_list() called\n"));
Packit fcad23
    if (containers == NULL)
Packit fcad23
	return;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * free memory used by each factory entry
Packit fcad23
     */
Packit fcad23
    CONTAINER_FOR_EACH(containers, ((netsnmp_container_obj_func *)_factory_free), NULL);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * free factory container
Packit fcad23
     */
Packit fcad23
    CONTAINER_FREE(containers);
Packit fcad23
    containers = NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_container_register_with_compare(const char* name, netsnmp_factory *f,
Packit fcad23
                                        netsnmp_container_compare  *c)
Packit fcad23
{
Packit fcad23
    container_type *ct, tmp;
Packit fcad23
Packit fcad23
    if (NULL==containers)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    tmp.name = NETSNMP_REMOVE_CONST(char *, name);
Packit fcad23
    ct = (container_type *)CONTAINER_FIND(containers, &tmp);
Packit fcad23
    if (NULL!=ct) {
Packit fcad23
        DEBUGMSGT(("container_registry",
Packit fcad23
                   "replacing previous container factory\n"));
Packit fcad23
        ct->factory = f;
Packit fcad23
    }
Packit fcad23
    else {
Packit fcad23
        ct = SNMP_MALLOC_TYPEDEF(container_type);
Packit fcad23
        if (NULL == ct)
Packit fcad23
            return -1;
Packit fcad23
        ct->name = strdup(name);
Packit fcad23
        ct->factory = f;
Packit fcad23
        ct->compare = c;
Packit fcad23
        CONTAINER_INSERT(containers, ct);
Packit fcad23
    }
Packit fcad23
    DEBUGMSGT(("container_registry", "registered container factory %s (%s)\n",
Packit fcad23
               ct->name, f->product));
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_container_register(const char* name, netsnmp_factory *f)
Packit fcad23
{
Packit fcad23
    return netsnmp_container_register_with_compare(name, f, NULL);
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
netsnmp_factory *
Packit fcad23
netsnmp_container_get_factory(const char *type)
Packit fcad23
{
Packit fcad23
    container_type ct, *found;
Packit fcad23
    
Packit fcad23
    if (NULL==containers)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    ct.name = type;
Packit fcad23
    found = (container_type *)CONTAINER_FIND(containers, &ct);
Packit fcad23
Packit fcad23
    return found ? found->factory : NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_FIND_FACTORY
Packit fcad23
netsnmp_factory *
Packit fcad23
netsnmp_container_find_factory(const char *type_list)
Packit fcad23
{
Packit fcad23
    netsnmp_factory   *f = NULL;
Packit fcad23
    char              *list, *entry;
Packit fcad23
    char              *st = NULL;
Packit fcad23
Packit fcad23
    if (NULL==type_list)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    list = strdup(type_list);
Packit fcad23
    if (!list)
Packit fcad23
        return NULL;
Packit fcad23
    entry = strtok_r(list, ":", &st);
Packit fcad23
    while (entry) {
Packit fcad23
        f = netsnmp_container_get_factory(entry);
Packit fcad23
        if (NULL != f)
Packit fcad23
            break;
Packit fcad23
        entry = strtok_r(NULL, ":", &st);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    free(list);
Packit fcad23
    return f;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_FIND_FACTORY */
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
static container_type *
Packit fcad23
netsnmp_container_get_ct(const char *type)
Packit fcad23
{
Packit fcad23
    container_type ct;
Packit fcad23
Packit fcad23
    if (NULL == containers)
Packit fcad23
        return NULL;
Packit fcad23
    
Packit fcad23
    ct.name = type;
Packit fcad23
    return (container_type *)CONTAINER_FIND(containers, &ct);
Packit fcad23
}
Packit fcad23
Packit fcad23
static container_type *
Packit fcad23
netsnmp_container_find_ct(const char *type_list)
Packit fcad23
{
Packit fcad23
    container_type    *ct = NULL;
Packit fcad23
    char              *list, *entry;
Packit fcad23
    char              *st = NULL;
Packit fcad23
Packit fcad23
    if (NULL==type_list)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    list = strdup(type_list);
Packit fcad23
    if (!list)
Packit fcad23
        return NULL;
Packit fcad23
    entry = strtok_r(list, ":", &st);
Packit fcad23
    while (entry) {
Packit fcad23
        ct = netsnmp_container_get_ct(entry);
Packit fcad23
        if (NULL != ct)
Packit fcad23
            break;
Packit fcad23
        entry = strtok_r(NULL, ":", &st);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    free(list);
Packit fcad23
    return ct;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
netsnmp_container *
Packit fcad23
netsnmp_container_get(const char *type)
Packit fcad23
{
Packit fcad23
    netsnmp_container *c;
Packit fcad23
    container_type *ct = netsnmp_container_get_ct(type);
Packit fcad23
    if (ct) {
Packit fcad23
        c = (netsnmp_container *)(ct->factory->produce());
Packit fcad23
        if (c && ct->compare)
Packit fcad23
            c->compare = ct->compare;
Packit fcad23
        return c;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
netsnmp_container *
Packit fcad23
netsnmp_container_find(const char *type)
Packit fcad23
{
Packit fcad23
    container_type *ct = netsnmp_container_find_ct(type);
Packit fcad23
    netsnmp_container *c = ct ? (netsnmp_container *)(ct->factory->produce()) : NULL;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * provide default compare
Packit fcad23
     */
Packit fcad23
    if (c) {
Packit fcad23
        if (ct->compare)
Packit fcad23
            c->compare = ct->compare;
Packit fcad23
        else if (NULL == c->compare)
Packit fcad23
            c->compare = netsnmp_compare_netsnmp_index;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return c;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
netsnmp_container_add_index(netsnmp_container *primary,
Packit fcad23
                            netsnmp_container *new_index)
Packit fcad23
{
Packit fcad23
    netsnmp_container *curr = primary;
Packit fcad23
Packit fcad23
    if((NULL == new_index) || (NULL == primary)) {
Packit fcad23
        snmp_log(LOG_ERR, "add index called with null pointer\n");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    while(curr->next)
Packit fcad23
        curr = curr->next;
Packit fcad23
Packit fcad23
    curr->next = new_index;
Packit fcad23
    new_index->prev = curr;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the inline version in
Packit fcad23
 * container.h. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
int CONTAINER_INSERT_HELPER(netsnmp_container* x, const void* k)
Packit fcad23
{
Packit fcad23
    while(x && x->insert_filter && x->insert_filter(x,k) == 1)
Packit fcad23
        x = x->next;
Packit fcad23
    if(x) {
Packit fcad23
        int rc = x->insert(x,k);
Packit fcad23
        if(rc)
Packit fcad23
            snmp_log(LOG_DEBUG,"error on subcontainer '%s' insert (%d)\n",
Packit fcad23
                     x->container_name ? x->container_name : "", rc);
Packit fcad23
        else {
Packit fcad23
            rc = CONTAINER_INSERT_HELPER(x->next, k);
Packit fcad23
            if(rc)
Packit fcad23
                x->remove(x,k);
Packit fcad23
        }
Packit fcad23
        return rc;
Packit fcad23
    }
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the inline version in
Packit fcad23
 * container.h. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
int CONTAINER_INSERT(netsnmp_container* x, const void* k)
Packit fcad23
{
Packit fcad23
    /** start at first container */
Packit fcad23
    while(x->prev)
Packit fcad23
        x = x->prev;
Packit fcad23
    return CONTAINER_INSERT_HELPER(x, k);
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the inline version in
Packit fcad23
 * container.h. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
int CONTAINER_INSERT_BEFORE(netsnmp_container *x, size_t pos, void *k)
Packit fcad23
{
Packit fcad23
    int rc = 0;
Packit fcad23
Packit fcad23
    if (NULL == x || NULL == x->insert_before) {
Packit fcad23
        snmp_log(LOG_ERR, "container '%s' does not support insert_before\n",
Packit fcad23
                 x && x->container_name ? x->container_name : "");
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    rc = x->insert_before(x, pos, k);
Packit fcad23
    if (rc < 0)
Packit fcad23
        snmp_log(LOG_ERR, "error on container '%s' insert_before %" NETSNMP_PRIz "d (%d)\n",
Packit fcad23
                 x->container_name ? x->container_name : "", pos, rc);
Packit fcad23
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the inline version in
Packit fcad23
 * container.h. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
int CONTAINER_REMOVE(netsnmp_container *x, const void *k)
Packit fcad23
{
Packit fcad23
    int rc2, rc = 0;
Packit fcad23
    
Packit fcad23
    /** start at last container */
Packit fcad23
    while(x->next)
Packit fcad23
        x = x->next;
Packit fcad23
    while(x) {
Packit fcad23
        rc2 = x->remove(x,k);
Packit fcad23
        /** ignore remove errors if there is a filter in place */
Packit fcad23
        if ((rc2) && (NULL == x->insert_filter)) {
Packit fcad23
            snmp_log(LOG_ERR,"error on subcontainer '%s' remove (%d)\n",
Packit fcad23
                     x->container_name ? x->container_name : "", rc2);
Packit fcad23
            rc = rc2;
Packit fcad23
        }
Packit fcad23
        x = x->prev;
Packit fcad23
        
Packit fcad23
    }
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the inline version in
Packit fcad23
 * container.h. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
int CONTAINER_REMOVE_AT(netsnmp_container *x, size_t pos, void **k)
Packit fcad23
{
Packit fcad23
    int rc = 0;
Packit fcad23
    netsnmp_container *orig = x;
Packit fcad23
Packit fcad23
    if (NULL == x || NULL == x->remove_at) {
Packit fcad23
        snmp_log(LOG_ERR, "container '%s' does not support REMOVE_AT\n",
Packit fcad23
                 x && x->container_name ? x->container_name : "");
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** start at given container */
Packit fcad23
    rc = x->remove_at(x, pos, k);
Packit fcad23
    if (rc < 0) {
Packit fcad23
        snmp_log(LOG_ERR, "error on container '%s' remove_at %" NETSNMP_PRIz "d (%d)\n",
Packit fcad23
                 x->container_name ? x->container_name : "", pos, rc);
Packit fcad23
        return rc;
Packit fcad23
    } else if (NULL == k || NULL == *k)
Packit fcad23
        return rc;
Packit fcad23
Packit fcad23
    /** remove k from any other containers */
Packit fcad23
    while(x->prev)
Packit fcad23
        x = x->prev;
Packit fcad23
    for(; x; x = x->next) {
Packit fcad23
        if (x == orig)
Packit fcad23
            continue;
Packit fcad23
        x->remove(x,*k); /** ignore remove errors in other containers */
Packit fcad23
    }
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the inline version in
Packit fcad23
 * container.h. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
int CONTAINER_GET_AT(netsnmp_container *x, size_t pos, void **k)
Packit fcad23
{
Packit fcad23
    int rc = 0;
Packit fcad23
Packit fcad23
    if (NULL == x || NULL == x->get_at) {
Packit fcad23
        snmp_log(LOG_ERR, "container '%s' does not support GET_AT\n",
Packit fcad23
                 x && x->container_name ? x->container_name : "");
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** start at given container */
Packit fcad23
    rc = x->get_at(x, pos, k);
Packit fcad23
    if (rc < 0)
Packit fcad23
        snmp_log(LOG_ERR, "error on container '%s' get_at %" NETSNMP_PRIz "d (%d)\n",
Packit fcad23
                 x->container_name ? x->container_name : "", pos, rc);
Packit fcad23
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the function version in
Packit fcad23
 * container.c. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_DUP
Packit fcad23
netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx, u_int flags)
Packit fcad23
{
Packit fcad23
    if (NULL == x->duplicate) {
Packit fcad23
        snmp_log(LOG_ERR, "container '%s' does not support duplicate\n",
Packit fcad23
                 x->container_name ? x->container_name : "");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    return x->duplicate(x, ctx, flags);
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_DUP */
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the inline version in
Packit fcad23
 * container.h. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
int CONTAINER_FREE(netsnmp_container *x)
Packit fcad23
{
Packit fcad23
    int  rc2, rc = 0;
Packit fcad23
Packit fcad23
    if (!x)
Packit fcad23
        return rc;
Packit fcad23
Packit fcad23
    /** start at last container */
Packit fcad23
    while(x->next)
Packit fcad23
        x = x->next;
Packit fcad23
    while(x) {
Packit fcad23
        netsnmp_container *tmp;
Packit fcad23
        char *name;
Packit fcad23
        tmp = x->prev;
Packit fcad23
        name = x->container_name;
Packit fcad23
        x->container_name = NULL;
Packit fcad23
        rc2 = x->cfree(x);
Packit fcad23
        if (rc2) {
Packit fcad23
            snmp_log(LOG_ERR,"error on subcontainer '%s' cfree (%d)\n",
Packit fcad23
                     name ? name : "", rc2);
Packit fcad23
            rc = rc2;
Packit fcad23
        }
Packit fcad23
        SNMP_FREE(name);
Packit fcad23
        x = tmp;
Packit fcad23
    }
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the function version in
Packit fcad23
 * container.c. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
/*
Packit fcad23
 * clear all containers. When clearing the *first* container, and
Packit fcad23
 * *only* the first container, call the function f for each item.
Packit fcad23
 * After calling this function, all containers should be empty.
Packit fcad23
 */
Packit fcad23
void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
Packit fcad23
                    void *c)
Packit fcad23
{
Packit fcad23
    /** start at last container */
Packit fcad23
    while(x->next)
Packit fcad23
        x = x->next;
Packit fcad23
    while(x->prev) {
Packit fcad23
        x->clear(x, NULL, c);
Packit fcad23
        x = x->prev;
Packit fcad23
    }
Packit fcad23
    x->clear(x, f, c);
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_FREE_ALL
Packit fcad23
/*
Packit fcad23
 * clear all containers. When clearing the *first* container, and
Packit fcad23
 * *only* the first container, call the free_item function for each item.
Packit fcad23
 * After calling this function, all containers should be empty.
Packit fcad23
 */
Packit fcad23
void CONTAINER_FREE_ALL(netsnmp_container *x, void *c)
Packit fcad23
{
Packit fcad23
    CONTAINER_CLEAR(x, x->free_item, c);
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_FREE_ALL */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_SUBCONTAINER_FIND
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * These functions should EXACTLY match the function version in
Packit fcad23
 * container.c. If you change one, change them both.
Packit fcad23
 */
Packit fcad23
/*
Packit fcad23
 * Find a sub-container with the given name
Packit fcad23
 */
Packit fcad23
netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
Packit fcad23
                                     const char* name)
Packit fcad23
{
Packit fcad23
    if ((NULL == x) || (NULL == name))
Packit fcad23
        return NULL;
Packit fcad23
    
Packit fcad23
    /** start at first container */
Packit fcad23
    while(x->prev)
Packit fcad23
        x = x->prev;
Packit fcad23
    while(x) {
Packit fcad23
        if ((NULL != x->container_name) && (0 == strcmp(name,x->container_name)))
Packit fcad23
            break;
Packit fcad23
        x = x->next;
Packit fcad23
    }
Packit fcad23
    return x;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_SUBCONTAINER_FIND */
Packit fcad23
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
netsnmp_init_container(netsnmp_container         *c,
Packit fcad23
                       netsnmp_container_rc      *init,
Packit fcad23
                       netsnmp_container_rc      *cfree,
Packit fcad23
                       netsnmp_container_size    *size,
Packit fcad23
                       netsnmp_container_compare *cmp,
Packit fcad23
                       netsnmp_container_op      *ins,
Packit fcad23
                       netsnmp_container_op      *rem,
Packit fcad23
                       netsnmp_container_rtn     *fnd)
Packit fcad23
{
Packit fcad23
    if (c == NULL)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    c->init = init;
Packit fcad23
    c->cfree = cfree;
Packit fcad23
    c->get_size = size;
Packit fcad23
    c->compare = cmp;
Packit fcad23
    c->insert = ins;
Packit fcad23
    c->remove = rem;
Packit fcad23
    c->find = fnd;
Packit fcad23
    c->free_item = netsnmp_container_simple_free;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_container_data_dup(netsnmp_container *dup, netsnmp_container *c)
Packit fcad23
{
Packit fcad23
    if (!dup || !c)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    if (c->container_name)
Packit fcad23
        dup->container_name = strdup(c->container_name);
Packit fcad23
    dup->compare = c->compare;
Packit fcad23
    dup->ncompare = c->ncompare;
Packit fcad23
    dup->release = c->release;
Packit fcad23
    dup->insert_filter = c->insert_filter;
Packit fcad23
    dup->free_item = c->free_item;
Packit fcad23
    dup->sync = c->sync;
Packit fcad23
    dup->flags = c->flags;
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 *
Packit fcad23
 * simple comparison routines
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs)
Packit fcad23
{
Packit fcad23
    int rc;
Packit fcad23
    netsnmp_assert((NULL != lhs) && (NULL != rhs));
Packit fcad23
    DEBUGIF("compare:index") {
Packit fcad23
        DEBUGMSGT(("compare:index", "compare "));
Packit fcad23
        DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
Packit fcad23
                     ((const netsnmp_index *) lhs)->len));
Packit fcad23
        DEBUGMSG(("compare:index", " to "));
Packit fcad23
        DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
Packit fcad23
                     ((const netsnmp_index *) rhs)->len));
Packit fcad23
        DEBUGMSG(("compare:index", "\n"));
Packit fcad23
    }
Packit fcad23
    rc = snmp_oid_compare(((const netsnmp_index *) lhs)->oids,
Packit fcad23
                          ((const netsnmp_index *) lhs)->len,
Packit fcad23
                          ((const netsnmp_index *) rhs)->oids,
Packit fcad23
                          ((const netsnmp_index *) rhs)->len);
Packit fcad23
    DEBUGMSGT(("compare:index", "result was %d\n", rc));
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs)
Packit fcad23
{
Packit fcad23
    int rc;
Packit fcad23
    netsnmp_assert((NULL != lhs) && (NULL != rhs));
Packit fcad23
    DEBUGIF("compare:index") {
Packit fcad23
        DEBUGMSGT(("compare:index", "compare "));
Packit fcad23
        DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
Packit fcad23
                     ((const netsnmp_index *) lhs)->len));
Packit fcad23
        DEBUGMSG(("compare:index", " to "));
Packit fcad23
        DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
Packit fcad23
                     ((const netsnmp_index *) rhs)->len));
Packit fcad23
        DEBUGMSG(("compare:index", "\n"));
Packit fcad23
    }
Packit fcad23
    rc = snmp_oid_ncompare(((const netsnmp_index *) lhs)->oids,
Packit fcad23
                           ((const netsnmp_index *) lhs)->len,
Packit fcad23
                           ((const netsnmp_index *) rhs)->oids,
Packit fcad23
                           ((const netsnmp_index *) rhs)->len,
Packit fcad23
                           ((const netsnmp_index *) rhs)->len);
Packit fcad23
    DEBUGMSGT(("compare:index", "result was %d\n", rc));
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_compare_cstring(const void * lhs, const void * rhs)
Packit fcad23
{
Packit fcad23
    return strcmp(((const container_type*)lhs)->name,
Packit fcad23
                  ((const container_type*)rhs)->name);
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_NCOMPARE_CSTRING
Packit fcad23
int
Packit fcad23
netsnmp_ncompare_cstring(const void * lhs, const void * rhs)
Packit fcad23
{
Packit fcad23
    return strncmp(((const container_type*)lhs)->name,
Packit fcad23
                   ((const container_type*)rhs)->name,
Packit fcad23
                   strlen(((const container_type*)rhs)->name));
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_NCOMPARE_CSTRING */
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_compare_direct_cstring(const void * lhs, const void * rhs)
Packit fcad23
{
Packit fcad23
    return strcmp((const char*)lhs, (const char*)rhs);
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * compare two memory buffers
Packit fcad23
 *
Packit fcad23
 * since snmp strings aren't NULL terminated, we can't use strcmp. So
Packit fcad23
 * compare up to the length of the smaller, and then use length to
Packit fcad23
 * break any ties.
Packit fcad23
 */
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_MEM
Packit fcad23
int
Packit fcad23
netsnmp_compare_mem(const char * lhs, size_t lhs_len,
Packit fcad23
                    const char * rhs, size_t rhs_len)
Packit fcad23
{
Packit fcad23
    int rc, min = SNMP_MIN(lhs_len, rhs_len);
Packit fcad23
Packit fcad23
    rc = memcmp(lhs, rhs, min);
Packit fcad23
    if((rc==0) && (lhs_len != rhs_len)) {
Packit fcad23
        if(lhs_len < rhs_len)
Packit fcad23
            rc = -1;
Packit fcad23
        else
Packit fcad23
            rc = 1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_MEM */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_LONG
Packit fcad23
int
Packit fcad23
netsnmp_compare_long(const void * lhs, const void * rhs)
Packit fcad23
{
Packit fcad23
    typedef struct { long index; } dummy;
Packit fcad23
Packit fcad23
    const dummy *lhd = (const dummy*)lhs;
Packit fcad23
    const dummy *rhd = (const dummy*)rhs;
Packit fcad23
Packit fcad23
    if (lhd->index < rhd->index)
Packit fcad23
        return -1;
Packit fcad23
    else if (lhd->index > rhd->index)
Packit fcad23
        return 1;
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_LONG */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_ULONG
Packit fcad23
int
Packit fcad23
netsnmp_compare_ulong(const void * lhs, const void * rhs)
Packit fcad23
{
Packit fcad23
    typedef struct { u_long index; } dummy;
Packit fcad23
Packit fcad23
    const dummy *lhd = (const dummy*)lhs;
Packit fcad23
    const dummy *rhd = (const dummy*)rhs;
Packit fcad23
Packit fcad23
    if (lhd->index < rhd->index)
Packit fcad23
        return -1;
Packit fcad23
    else if (lhd->index > rhd->index)
Packit fcad23
        return 1;
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_ULONG */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_INT32
Packit fcad23
int
Packit fcad23
netsnmp_compare_int32(const void * lhs, const void * rhs)
Packit fcad23
{
Packit fcad23
    typedef struct { int32_t index; } dummy;
Packit fcad23
Packit fcad23
    const dummy *lhd = (const dummy*)lhs;
Packit fcad23
    const dummy *rhd = (const dummy*)rhs;
Packit fcad23
Packit fcad23
    if (lhd->index < rhd->index)
Packit fcad23
        return -1;
Packit fcad23
    else if (lhd->index > rhd->index)
Packit fcad23
        return 1;
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_INT32 */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_UINT32
Packit fcad23
int
Packit fcad23
netsnmp_compare_uint32(const void * lhs, const void * rhs)
Packit fcad23
{
Packit fcad23
    typedef struct { uint32_t index; } dummy;
Packit fcad23
Packit fcad23
    const dummy *lhd = (const dummy*)lhs;
Packit fcad23
    const dummy *rhd = (const dummy*)rhs;
Packit fcad23
Packit fcad23
    if (lhd->index < rhd->index)
Packit fcad23
        return -1;
Packit fcad23
    else if (lhd->index > rhd->index)
Packit fcad23
        return 1;
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CONTAINER_COMPARE_UINT32 */
Packit fcad23
Packit fcad23
/*------------------------------------------------------------------
Packit fcad23
 * netsnmp_container_simple_free
Packit fcad23
 *
Packit fcad23
 * useful function to pass to CONTAINER_FOR_EACH, when a simple
Packit fcad23
 * free is needed for every item.
Packit fcad23
 */
Packit fcad23
void 
Packit fcad23
netsnmp_container_simple_free(void *data, void *context)
Packit fcad23
{
Packit fcad23
    if (data == NULL)
Packit fcad23
	return;
Packit fcad23
    
Packit fcad23
    DEBUGMSGTL(("verbose:container",
Packit fcad23
                "netsnmp_container_simple_free) called for %p/%p\n",
Packit fcad23
                data, context));
Packit fcad23
    free((void*)data); /* SNMP_FREE wasted on param */
Packit fcad23
}