Blame agent/agent_index.c

Packit fcad23
/*
Packit fcad23
 * agent_index.c
Packit fcad23
 *
Packit fcad23
 * Maintain a registry of index allocations
Packit fcad23
 *      (Primarily required for AgentX support,
Packit fcad23
 *       but it could be more widely useable).
Packit fcad23
 */
Packit fcad23
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
#include <signal.h>
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
#include <sys/types.h>
Packit fcad23
#include <stdio.h>
Packit fcad23
#include <fcntl.h>
Packit fcad23
#if TIME_WITH_SYS_TIME
Packit fcad23
# include <sys/time.h>
Packit fcad23
# include <time.h>
Packit fcad23
#else
Packit fcad23
# if HAVE_SYS_TIME_H
Packit fcad23
#  include <sys/time.h>
Packit fcad23
# else
Packit fcad23
#  include <time.h>
Packit fcad23
# endif
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETINET_IN_H
Packit fcad23
#include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include <net-snmp/agent/net-snmp-agent-includes.h>
Packit fcad23
#include <net-snmp/agent/agent_callbacks.h>
Packit fcad23
#include <net-snmp/agent/agent_index.h>
Packit fcad23
Packit fcad23
#include "snmpd.h"
Packit fcad23
#include "agent_global_vars.h"
Packit fcad23
#include "mibgroup/struct.h"
Packit fcad23
#include <net-snmp/agent/table.h>
Packit fcad23
#include <net-snmp/agent/table_iterator.h>
Packit fcad23
Packit fcad23
#ifdef USING_AGENTX_SUBAGENT_MODULE
Packit fcad23
#include "agentx/subagent.h"
Packit fcad23
#include "agentx/client.h"
Packit fcad23
#endif
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(agent_index_all, libnetsnmpagent)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(remove_index, agent_index_all)
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Initial support for index allocation
Packit fcad23
         */
Packit fcad23
Packit fcad23
struct snmp_index {
Packit fcad23
    netsnmp_variable_list *varbind;     /* or pointer to var_list ? */
Packit fcad23
    int             allocated;
Packit fcad23
    netsnmp_session *session;
Packit fcad23
    struct snmp_index *next_oid;
Packit fcad23
    struct snmp_index *prev_oid;
Packit fcad23
    struct snmp_index *next_idx;
Packit fcad23
}              *snmp_index_head = NULL;
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * The caller is responsible for free()ing the memory returned by
Packit fcad23
 * this function.  
Packit fcad23
 */
Packit fcad23
Packit fcad23
char           *
Packit fcad23
register_string_index(oid * name, size_t name_len, char *cp)
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list varbind, *res;
Packit fcad23
Packit fcad23
    memset(&varbind, 0, sizeof(netsnmp_variable_list));
Packit fcad23
    varbind.type = ASN_OCTET_STR;
Packit fcad23
    snmp_set_var_objid(&varbind, name, name_len);
Packit fcad23
    if (cp != ANY_STRING_INDEX) {
Packit fcad23
        snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
Packit fcad23
        res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
Packit fcad23
    } else {
Packit fcad23
        res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (res == NULL) {
Packit fcad23
        return NULL;
Packit fcad23
    } else {
Packit fcad23
        char *rv = (char *)malloc(res->val_len + 1);
Packit fcad23
        if (rv) {
Packit fcad23
            memcpy(rv, res->val.string, res->val_len);
Packit fcad23
            rv[res->val_len] = 0;
Packit fcad23
        }
Packit fcad23
        free(res);
Packit fcad23
        return rv;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
register_int_index(oid * name, size_t name_len, int val)
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list varbind, *res;
Packit fcad23
Packit fcad23
    memset(&varbind, 0, sizeof(netsnmp_variable_list));
Packit fcad23
    varbind.type = ASN_INTEGER;
Packit fcad23
    snmp_set_var_objid(&varbind, name, name_len);
Packit fcad23
    varbind.val.string = varbind.buf;
Packit fcad23
    if (val != ANY_INTEGER_INDEX) {
Packit fcad23
        varbind.val_len = sizeof(long);
Packit fcad23
        *varbind.val.integer = val;
Packit fcad23
        res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
Packit fcad23
    } else {
Packit fcad23
        res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (res == NULL) {
Packit fcad23
        return -1;
Packit fcad23
    } else {
Packit fcad23
        int             rv = *(res->val.integer);
Packit fcad23
        free(res);
Packit fcad23
        return rv;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * The caller is responsible for free()ing the memory returned by
Packit fcad23
 * this function.  
Packit fcad23
 */
Packit fcad23
Packit fcad23
netsnmp_variable_list *
Packit fcad23
register_oid_index(oid * name, size_t name_len,
Packit fcad23
                   oid * value, size_t value_len)
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list varbind;
Packit fcad23
Packit fcad23
    memset(&varbind, 0, sizeof(netsnmp_variable_list));
Packit fcad23
    varbind.type = ASN_OBJECT_ID;
Packit fcad23
    snmp_set_var_objid(&varbind, name, name_len);
Packit fcad23
    if (value != ANY_OID_INDEX) {
Packit fcad23
        snmp_set_var_value(&varbind, (u_char *) value,
Packit fcad23
                           value_len * sizeof(oid));
Packit fcad23
        return register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
Packit fcad23
    } else {
Packit fcad23
        return register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * The caller is responsible for free()ing the memory returned by
Packit fcad23
 * this function.  
Packit fcad23
 */
Packit fcad23
Packit fcad23
netsnmp_variable_list *
Packit fcad23
register_index(netsnmp_variable_list * varbind, int flags,
Packit fcad23
               netsnmp_session * ss)
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list *rv = NULL;
Packit fcad23
    struct snmp_index *new_index, *idxptr, *idxptr2;
Packit fcad23
    struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
Packit fcad23
    int             res, res2, i;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("register_index", "register "));
Packit fcad23
    DEBUGMSGVAR(("register_index", varbind));
Packit fcad23
    DEBUGMSG(("register_index", "for session %8p\n", ss));
Packit fcad23
Packit fcad23
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
Packit fcad23
    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
			       NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
Packit fcad23
        return (agentx_register_index(ss, varbind, flags));
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
    /*
Packit fcad23
     * Look for the requested OID entry 
Packit fcad23
     */
Packit fcad23
    prev_oid_ptr = NULL;
Packit fcad23
    prev_idx_ptr = NULL;
Packit fcad23
    res = 1;
Packit fcad23
    res2 = 1;
Packit fcad23
    for (idxptr = snmp_index_head; idxptr != NULL;
Packit fcad23
         prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
Packit fcad23
        if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
Packit fcad23
                                    idxptr->varbind->name,
Packit fcad23
                                    idxptr->varbind->name_length)) <= 0)
Packit fcad23
            break;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Found the OID - now look at the registered indices 
Packit fcad23
     */
Packit fcad23
    if (res == 0 && idxptr) {
Packit fcad23
        if (varbind->type != idxptr->varbind->type)
Packit fcad23
            return NULL;        /* wrong type */
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * If we've been asked for an arbitrary new value,
Packit fcad23
         *      then find the end of the list.
Packit fcad23
         * If we've been asked for any arbitrary value,
Packit fcad23
         *      then look for an unused entry, and use that.
Packit fcad23
         *      If there aren't any, continue as for new.
Packit fcad23
         * Otherwise, locate the given value in the (sorted)
Packit fcad23
         *      list of already allocated values
Packit fcad23
         */
Packit fcad23
        if (flags & ALLOCATE_ANY_INDEX) {
Packit fcad23
            for (idxptr2 = idxptr; idxptr2 != NULL;
Packit fcad23
                 prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
Packit fcad23
Packit fcad23
                if (flags == ALLOCATE_ANY_INDEX && !(idxptr2->allocated)) {
Packit fcad23
                    if ((rv =
Packit fcad23
                         snmp_clone_varbind(idxptr2->varbind)) != NULL) {
Packit fcad23
                        idxptr2->session = ss;
Packit fcad23
                        idxptr2->allocated = 1;
Packit fcad23
                    }
Packit fcad23
                    return rv;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
        } else {
Packit fcad23
            for (idxptr2 = idxptr; idxptr2 != NULL;
Packit fcad23
                 prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
Packit fcad23
                switch (varbind->type) {
Packit fcad23
                case ASN_INTEGER:
Packit fcad23
                    res2 =
Packit fcad23
                        (*varbind->val.integer -
Packit fcad23
                         *idxptr2->varbind->val.integer);
Packit fcad23
                    break;
Packit fcad23
                case ASN_OCTET_STR:
Packit fcad23
                    i = SNMP_MIN(varbind->val_len,
Packit fcad23
                                 idxptr2->varbind->val_len);
Packit fcad23
                    res2 =
Packit fcad23
                        memcmp(varbind->val.string,
Packit fcad23
                               idxptr2->varbind->val.string, i);
Packit fcad23
                    break;
Packit fcad23
                case ASN_OBJECT_ID:
Packit fcad23
                    res2 =
Packit fcad23
                        snmp_oid_compare(varbind->val.objid,
Packit fcad23
                                         varbind->val_len / sizeof(oid),
Packit fcad23
                                         idxptr2->varbind->val.objid,
Packit fcad23
                                         idxptr2->varbind->val_len /
Packit fcad23
                                         sizeof(oid));
Packit fcad23
                    break;
Packit fcad23
                default:
Packit fcad23
                    return NULL;        /* wrong type */
Packit fcad23
                }
Packit fcad23
                if (res2 <= 0)
Packit fcad23
                    break;
Packit fcad23
            }
Packit fcad23
            if (res2 == 0) {
Packit fcad23
                if (idxptr2->allocated) {
Packit fcad23
                    /*
Packit fcad23
                     * No good: the index is in use.  
Packit fcad23
                     */
Packit fcad23
                    return NULL;
Packit fcad23
                } else {
Packit fcad23
                    /*
Packit fcad23
                     * Okay, it's unallocated, we can just claim ownership
Packit fcad23
                     * here.  
Packit fcad23
                     */
Packit fcad23
                    if ((rv =
Packit fcad23
                         snmp_clone_varbind(idxptr2->varbind)) != NULL) {
Packit fcad23
                        idxptr2->session = ss;
Packit fcad23
                        idxptr2->allocated = 1;
Packit fcad23
                    }
Packit fcad23
                    return rv;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * OK - we've now located where the new entry needs to
Packit fcad23
     *      be fitted into the index registry tree          
Packit fcad23
     * To recap:
Packit fcad23
     *      'prev_oid_ptr' points to the head of the OID index
Packit fcad23
     *          list prior to this one.  If this is null, then
Packit fcad23
     *          it means that this is the first OID in the list.
Packit fcad23
     *      'idxptr' points either to the head of this OID list,
Packit fcad23
     *          or the next OID (if this is a new OID request)
Packit fcad23
     *          These can be distinguished by the value of 'res'.
Packit fcad23
     *
Packit fcad23
     *      'prev_idx_ptr' points to the index entry that sorts
Packit fcad23
     *          immediately prior to the requested value (if any).
Packit fcad23
     *          If an arbitrary value is required, then this will
Packit fcad23
     *          point to the last allocated index.
Packit fcad23
     *          If this pointer is null, then either this is a new
Packit fcad23
     *          OID request, or the requested value is the first
Packit fcad23
     *          in the list.
Packit fcad23
     *      'idxptr2' points to the next sorted index (if any)
Packit fcad23
     *          but is not actually needed any more.
Packit fcad23
     *
Packit fcad23
     *  Clear?  Good!
Packit fcad23
     *      I hope you've been paying attention.
Packit fcad23
     *          There'll be a test later :-)
Packit fcad23
     */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *      We proceed by creating the new entry
Packit fcad23
     *         (by copying the entry provided)
Packit fcad23
     */
Packit fcad23
    new_index = (struct snmp_index *) calloc(1, sizeof(struct snmp_index));
Packit fcad23
    if (new_index == NULL)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    if (NULL == snmp_varlist_add_variable(&new_index->varbind,
Packit fcad23
                                          varbind->name,
Packit fcad23
                                          varbind->name_length,
Packit fcad23
                                          varbind->type,
Packit fcad23
                                          varbind->val.string,
Packit fcad23
                                          varbind->val_len)) {
Packit fcad23
        /*
Packit fcad23
         * if (snmp_clone_var( varbind, new_index->varbind ) != 0 ) 
Packit fcad23
         */
Packit fcad23
        free(new_index);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    new_index->session = ss;
Packit fcad23
    new_index->allocated = 1;
Packit fcad23
Packit fcad23
    if (varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX)
Packit fcad23
        new_index->varbind->val.string[new_index->varbind->val_len] = 0;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * If we've been given a value, then we can use that, but
Packit fcad23
     *    otherwise, we need to create a new value for this entry.
Packit fcad23
     * Note that ANY_INDEX and NEW_INDEX are both covered by this
Packit fcad23
     *   test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?)
Packit fcad23
     */
Packit fcad23
    if (flags & ALLOCATE_ANY_INDEX) {
Packit fcad23
        if (prev_idx_ptr) {
Packit fcad23
            if (snmp_clone_var(prev_idx_ptr->varbind, new_index->varbind)
Packit fcad23
                != 0) {
Packit fcad23
                free(new_index);
Packit fcad23
                return NULL;
Packit fcad23
            }
Packit fcad23
        } else
Packit fcad23
            new_index->varbind->val.string = new_index->varbind->buf;
Packit fcad23
Packit fcad23
        switch (varbind->type) {
Packit fcad23
        case ASN_INTEGER:
Packit fcad23
            if (prev_idx_ptr) {
Packit fcad23
                (*new_index->varbind->val.integer)++;
Packit fcad23
            } else
Packit fcad23
                *(new_index->varbind->val.integer) = 1;
Packit fcad23
            new_index->varbind->val_len = sizeof(long);
Packit fcad23
            break;
Packit fcad23
        case ASN_OCTET_STR:
Packit fcad23
            if (prev_idx_ptr) {
Packit fcad23
                i = new_index->varbind->val_len - 1;
Packit fcad23
                while (new_index->varbind->buf[i] == 'z') {
Packit fcad23
                    new_index->varbind->buf[i] = 'a';
Packit fcad23
                    i--;
Packit fcad23
                    if (i < 0) {
Packit fcad23
                        i = new_index->varbind->val_len;
Packit fcad23
                        new_index->varbind->buf[i] = 'a';
Packit fcad23
                        new_index->varbind->buf[i + 1] = 0;
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                new_index->varbind->buf[i]++;
Packit fcad23
            } else
Packit fcad23
                strcpy((char *) new_index->varbind->buf, "aaaa");
Packit fcad23
            new_index->varbind->val_len =
Packit fcad23
                strlen((char *) new_index->varbind->buf);
Packit fcad23
            break;
Packit fcad23
        case ASN_OBJECT_ID:
Packit fcad23
            if (prev_idx_ptr) {
Packit fcad23
                i = prev_idx_ptr->varbind->val_len / sizeof(oid) - 1;
Packit fcad23
                while (new_index->varbind->val.objid[i] == 255) {
Packit fcad23
                    new_index->varbind->val.objid[i] = 1;
Packit fcad23
                    i--;
Packit fcad23
                    if (i == 0 && new_index->varbind->val.objid[0] == 2) {
Packit fcad23
                        new_index->varbind->val.objid[0] = 1;
Packit fcad23
                        i = new_index->varbind->val_len / sizeof(oid);
Packit fcad23
                        new_index->varbind->val.objid[i] = 0;
Packit fcad23
                        new_index->varbind->val_len += sizeof(oid);
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                new_index->varbind->val.objid[i]++;
Packit fcad23
            } else {
Packit fcad23
                /*
Packit fcad23
                 * If the requested OID name is small enough,
Packit fcad23
                 * *   append another OID (1) and use this as the
Packit fcad23
                 * *   default starting value for new indexes.
Packit fcad23
                 */
Packit fcad23
                if ((varbind->name_length + 1) * sizeof(oid) <= 40) {
Packit fcad23
                    for (i = 0; i < (int) varbind->name_length; i++)
Packit fcad23
                        new_index->varbind->val.objid[i] =
Packit fcad23
                            varbind->name[i];
Packit fcad23
                    new_index->varbind->val.objid[varbind->name_length] =
Packit fcad23
                        1;
Packit fcad23
                    new_index->varbind->val_len =
Packit fcad23
                        (varbind->name_length + 1) * sizeof(oid);
Packit fcad23
                } else {
Packit fcad23
                    /*
Packit fcad23
                     * Otherwise use '.1.1.1.1...' 
Packit fcad23
                     */
Packit fcad23
                    i = 40 / sizeof(oid);
Packit fcad23
                    if (i > 4)
Packit fcad23
                        i = 4;
Packit fcad23
                    new_index->varbind->val_len = i * (sizeof(oid));
Packit fcad23
                    for (i--; i >= 0; i--)
Packit fcad23
                        new_index->varbind->val.objid[i] = 1;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
        default:
Packit fcad23
            snmp_free_var(new_index->varbind);
Packit fcad23
            free(new_index);
Packit fcad23
            return NULL;        /* Index type not supported */
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Try to duplicate the new varbind for return.  
Packit fcad23
     */
Packit fcad23
Packit fcad23
    if ((rv = snmp_clone_varbind(new_index->varbind)) == NULL) {
Packit fcad23
        snmp_free_var(new_index->varbind);
Packit fcad23
        free(new_index);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Right - we've set up the new entry.
Packit fcad23
     * All that remains is to link it into the tree.
Packit fcad23
     * There are a number of possible cases here,
Packit fcad23
     *   so watch carefully.
Packit fcad23
     */
Packit fcad23
    if (prev_idx_ptr) {
Packit fcad23
        new_index->next_idx = prev_idx_ptr->next_idx;
Packit fcad23
        new_index->next_oid = prev_idx_ptr->next_oid;
Packit fcad23
        prev_idx_ptr->next_idx = new_index;
Packit fcad23
    } else {
Packit fcad23
        if (res == 0 && idxptr) {
Packit fcad23
            new_index->next_idx = idxptr;
Packit fcad23
            new_index->next_oid = idxptr->next_oid;
Packit fcad23
        } else {
Packit fcad23
            new_index->next_idx = NULL;
Packit fcad23
            new_index->next_oid = idxptr;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if (prev_oid_ptr) {
Packit fcad23
            while (prev_oid_ptr) {
Packit fcad23
                prev_oid_ptr->next_oid = new_index;
Packit fcad23
                prev_oid_ptr = prev_oid_ptr->next_idx;
Packit fcad23
            }
Packit fcad23
        } else
Packit fcad23
            snmp_index_head = new_index;
Packit fcad23
    }
Packit fcad23
    return rv;
Packit fcad23
}
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Release an allocated index,
Packit fcad23
         *   to allow it to be used elsewhere
Packit fcad23
         */
Packit fcad23
netsnmp_feature_child_of(release_index,netsnmp_unused)
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_RELEASE_INDEX
Packit fcad23
int
Packit fcad23
release_index(netsnmp_variable_list * varbind)
Packit fcad23
{
Packit fcad23
    return (unregister_index(varbind, TRUE, NULL));
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_RELEASE_INDEX */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_REMOVE_INDEX
Packit fcad23
        /*
Packit fcad23
         * Completely remove an allocated index,
Packit fcad23
         *   due to errors in the registration process.
Packit fcad23
         */
Packit fcad23
int
Packit fcad23
remove_index(netsnmp_variable_list * varbind, netsnmp_session * ss)
Packit fcad23
{
Packit fcad23
    return (unregister_index(varbind, FALSE, ss));
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_REMOVE_INDEX */
Packit fcad23
Packit fcad23
void
Packit fcad23
unregister_index_by_session(netsnmp_session * ss)
Packit fcad23
{
Packit fcad23
    struct snmp_index *idxptr, *idxptr2;
Packit fcad23
    for (idxptr = snmp_index_head; idxptr != NULL;
Packit fcad23
         idxptr = idxptr->next_oid)
Packit fcad23
        for (idxptr2 = idxptr; idxptr2 != NULL;
Packit fcad23
             idxptr2 = idxptr2->next_idx)
Packit fcad23
            if (idxptr2->session == ss) {
Packit fcad23
                idxptr2->allocated = 0;
Packit fcad23
                idxptr2->session = NULL;
Packit fcad23
            }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
int
Packit fcad23
unregister_index(netsnmp_variable_list * varbind, int remember,
Packit fcad23
                 netsnmp_session * ss)
Packit fcad23
{
Packit fcad23
    struct snmp_index *idxptr, *idxptr2;
Packit fcad23
    struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
Packit fcad23
    int             res, res2, i;
Packit fcad23
Packit fcad23
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
Packit fcad23
    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
			       NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
Packit fcad23
        return (agentx_unregister_index(ss, varbind));
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
    /*
Packit fcad23
     * Look for the requested OID entry 
Packit fcad23
     */
Packit fcad23
    prev_oid_ptr = NULL;
Packit fcad23
    prev_idx_ptr = NULL;
Packit fcad23
    res = 1;
Packit fcad23
    res2 = 1;
Packit fcad23
    for (idxptr = snmp_index_head; idxptr != NULL;
Packit fcad23
         prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
Packit fcad23
        if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
Packit fcad23
                                    idxptr->varbind->name,
Packit fcad23
                                    idxptr->varbind->name_length)) <= 0)
Packit fcad23
            break;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (res != 0)
Packit fcad23
        return INDEX_ERR_NOT_ALLOCATED;
Packit fcad23
    if (varbind->type != idxptr->varbind->type)
Packit fcad23
        return INDEX_ERR_WRONG_TYPE;
Packit fcad23
Packit fcad23
    for (idxptr2 = idxptr; idxptr2 != NULL;
Packit fcad23
         prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
Packit fcad23
        switch (varbind->type) {
Packit fcad23
        case ASN_INTEGER:
Packit fcad23
            res2 =
Packit fcad23
                (*varbind->val.integer -
Packit fcad23
                 *idxptr2->varbind->val.integer);
Packit fcad23
            break;
Packit fcad23
        case ASN_OCTET_STR:
Packit fcad23
            i = SNMP_MIN(varbind->val_len,
Packit fcad23
                         idxptr2->varbind->val_len);
Packit fcad23
            res2 =
Packit fcad23
                memcmp(varbind->val.string,
Packit fcad23
                       idxptr2->varbind->val.string, i);
Packit fcad23
            break;
Packit fcad23
        case ASN_OBJECT_ID:
Packit fcad23
            res2 =
Packit fcad23
                snmp_oid_compare(varbind->val.objid,
Packit fcad23
                                 varbind->val_len / sizeof(oid),
Packit fcad23
                                 idxptr2->varbind->val.objid,
Packit fcad23
                                 idxptr2->varbind->val_len /
Packit fcad23
                                 sizeof(oid));
Packit fcad23
            break;
Packit fcad23
        default:
Packit fcad23
            return INDEX_ERR_WRONG_TYPE;        /* wrong type */
Packit fcad23
        }
Packit fcad23
        if (res2 <= 0)
Packit fcad23
            break;
Packit fcad23
    }
Packit fcad23
    if (res2 != 0 || (res2 == 0 && !idxptr2->allocated)) {
Packit fcad23
        return INDEX_ERR_NOT_ALLOCATED;
Packit fcad23
    }
Packit fcad23
    if (ss != idxptr2->session)
Packit fcad23
        return INDEX_ERR_WRONG_SESSION;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *  If this is a "normal" index unregistration,
Packit fcad23
     *      mark the index entry as unused, but leave
Packit fcad23
     *      it in situ.  This allows differentiation
Packit fcad23
     *      between ANY_INDEX and NEW_INDEX
Packit fcad23
     */
Packit fcad23
    if (remember) {
Packit fcad23
        idxptr2->allocated = 0; /* Unused index */
Packit fcad23
        idxptr2->session = NULL;
Packit fcad23
        return SNMP_ERR_NOERROR;
Packit fcad23
    }
Packit fcad23
    /*
Packit fcad23
     *  If this is a failed attempt to register a
Packit fcad23
     *      number of indexes, the successful ones
Packit fcad23
     *      must be removed completely.
Packit fcad23
     */
Packit fcad23
    if (prev_idx_ptr) {
Packit fcad23
        prev_idx_ptr->next_idx = idxptr2->next_idx;
Packit fcad23
    } else if (prev_oid_ptr) {
Packit fcad23
        if (idxptr2->next_idx)  /* Use p_idx_ptr as a temp variable */
Packit fcad23
            prev_idx_ptr = idxptr2->next_idx;
Packit fcad23
        else
Packit fcad23
            prev_idx_ptr = idxptr2->next_oid;
Packit fcad23
        while (prev_oid_ptr) {
Packit fcad23
            prev_oid_ptr->next_oid = prev_idx_ptr;
Packit fcad23
            prev_oid_ptr = prev_oid_ptr->next_idx;
Packit fcad23
        }
Packit fcad23
    } else {
Packit fcad23
        if (idxptr2->next_idx)
Packit fcad23
            snmp_index_head = idxptr2->next_idx;
Packit fcad23
        else
Packit fcad23
            snmp_index_head = idxptr2->next_oid;
Packit fcad23
    }
Packit fcad23
    snmp_free_var(idxptr2->varbind);
Packit fcad23
    free(idxptr2);
Packit fcad23
    return SNMP_ERR_NOERROR;
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(unregister_indexes,netsnmp_unused)
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_UNREGISTER_INDEXES
Packit fcad23
int
Packit fcad23
unregister_string_index(oid * name, size_t name_len, char *cp)
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list varbind;
Packit fcad23
Packit fcad23
    memset(&varbind, 0, sizeof(netsnmp_variable_list));
Packit fcad23
    varbind.type = ASN_OCTET_STR;
Packit fcad23
    snmp_set_var_objid(&varbind, name, name_len);
Packit fcad23
    snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
Packit fcad23
    return (unregister_index(&varbind, FALSE, main_session));
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
unregister_int_index(oid * name, size_t name_len, int val)
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list varbind;
Packit fcad23
Packit fcad23
    memset(&varbind, 0, sizeof(netsnmp_variable_list));
Packit fcad23
    varbind.type = ASN_INTEGER;
Packit fcad23
    snmp_set_var_objid(&varbind, name, name_len);
Packit fcad23
    varbind.val.string = varbind.buf;
Packit fcad23
    varbind.val_len = sizeof(long);
Packit fcad23
    *varbind.val.integer = val;
Packit fcad23
    return (unregister_index(&varbind, FALSE, main_session));
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
unregister_oid_index(oid * name, size_t name_len,
Packit fcad23
                     oid * value, size_t value_len)
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list varbind;
Packit fcad23
Packit fcad23
    memset(&varbind, 0, sizeof(netsnmp_variable_list));
Packit fcad23
    varbind.type = ASN_OBJECT_ID;
Packit fcad23
    snmp_set_var_objid(&varbind, name, name_len);
Packit fcad23
    snmp_set_var_value(&varbind, (u_char *) value,
Packit fcad23
                       value_len * sizeof(oid));
Packit fcad23
    return (unregister_index(&varbind, FALSE, main_session));
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_UNREGISTER_INDEXES */
Packit fcad23
Packit fcad23
void
Packit fcad23
dump_idx_registry(void)
Packit fcad23
{
Packit fcad23
    struct snmp_index *idxptr, *idxptr2;
Packit fcad23
    u_char         *sbuf = NULL, *ebuf = NULL;
Packit fcad23
    size_t          sbuf_len = 0, sout_len = 0, ebuf_len = 0, eout_len = 0;
Packit fcad23
Packit fcad23
    if (snmp_index_head != NULL) {
Packit fcad23
        printf("\nIndex Allocations:\n");
Packit fcad23
    }
Packit fcad23
Packit fcad23
    for (idxptr = snmp_index_head; idxptr != NULL;
Packit fcad23
         idxptr = idxptr->next_oid) {
Packit fcad23
        sout_len = 0;
Packit fcad23
        if (sprint_realloc_objid(&sbuf, &sbuf_len, &sout_len, 1,
Packit fcad23
                                 idxptr->varbind->name,
Packit fcad23
                                 idxptr->varbind->name_length)) {
Packit fcad23
            printf("%s indexes:\n", sbuf);
Packit fcad23
        } else {
Packit fcad23
            printf("%s [TRUNCATED] indexes:\n", sbuf);
Packit fcad23
        }
Packit fcad23
Packit fcad23
        for (idxptr2 = idxptr; idxptr2 != NULL;
Packit fcad23
             idxptr2 = idxptr2->next_idx) {
Packit fcad23
            switch (idxptr2->varbind->type) {
Packit fcad23
            case ASN_INTEGER:
Packit fcad23
                printf("    %ld for session %8p, allocated %d\n",
Packit fcad23
                       *idxptr2->varbind->val.integer, idxptr2->session,
Packit fcad23
                       idxptr2->allocated);
Packit fcad23
                break;
Packit fcad23
            case ASN_OCTET_STR:
Packit fcad23
                printf("    \"%s\" for session %8p, allocated %d\n",
Packit fcad23
                       idxptr2->varbind->val.string, idxptr2->session,
Packit fcad23
                       idxptr2->allocated);
Packit fcad23
                break;
Packit fcad23
            case ASN_OBJECT_ID:
Packit fcad23
                eout_len = 0;
Packit fcad23
                if (sprint_realloc_objid(&ebuf, &ebuf_len, &eout_len, 1,
Packit fcad23
                                         idxptr2->varbind->val.objid,
Packit fcad23
                                         idxptr2->varbind->val_len /
Packit fcad23
                                         sizeof(oid))) {
Packit fcad23
                    printf("    %s for session %8p, allocated %d\n", ebuf,
Packit fcad23
                           idxptr2->session, idxptr2->allocated);
Packit fcad23
                } else {
Packit fcad23
                    printf
Packit fcad23
                        ("    %s [TRUNCATED] for sess %8p, allocated %d\n",
Packit fcad23
                         ebuf, idxptr2->session, idxptr2->allocated);
Packit fcad23
                }
Packit fcad23
                break;
Packit fcad23
            default:
Packit fcad23
                printf("unsupported type (%d/0x%02x)\n",
Packit fcad23
                       idxptr2->varbind->type, idxptr2->varbind->type);
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (sbuf != NULL) {
Packit fcad23
        free(sbuf);
Packit fcad23
    }
Packit fcad23
    if (ebuf != NULL) {
Packit fcad23
        free(ebuf);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(count_indexes, netsnmp_unused)
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_UNUSED
Packit fcad23
unsigned long
Packit fcad23
count_indexes(oid * name, size_t namelen, int include_unallocated)
Packit fcad23
{
Packit fcad23
    struct snmp_index *i = NULL, *j = NULL;
Packit fcad23
    unsigned long   n = 0;
Packit fcad23
Packit fcad23
    for (i = snmp_index_head; i != NULL; i = i->next_oid) {
Packit fcad23
        if (netsnmp_oid_equals(name, namelen,
Packit fcad23
                             i->varbind->name,
Packit fcad23
                             i->varbind->name_length) == 0) {
Packit fcad23
            for (j = i; j != NULL; j = j->next_idx) {
Packit fcad23
                if (j->allocated || include_unallocated) {
Packit fcad23
                    n++;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    return n;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_UNUSED */
Packit fcad23
Packit fcad23
#ifdef TESTING
Packit fcad23
netsnmp_variable_list varbind;
Packit fcad23
netsnmp_session main_sess, *main_session = &main_sess;
Packit fcad23
Packit fcad23
void
Packit fcad23
test_string_register(int n, char *cp)
Packit fcad23
{
Packit fcad23
    varbind->name[4] = n;
Packit fcad23
    if (register_string_index(varbind->name, varbind.name_length, cp) ==
Packit fcad23
        NULL)
Packit fcad23
        printf("allocating %s failed\n", cp);
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
test_int_register(int n, int val)
Packit fcad23
{
Packit fcad23
    varbind->name[4] = n;
Packit fcad23
    if (register_int_index(varbind->name, varbind.name_length, val) == -1)
Packit fcad23
        printf("allocating %d/%d failed\n", n, val);
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
test_oid_register(int n, int subid)
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list *res;
Packit fcad23
Packit fcad23
    varbind->name[4] = n;
Packit fcad23
    if (subid != -1) {
Packit fcad23
        varbind->val.objid[5] = subid;
Packit fcad23
        res = register_oid_index(varbind->name, varbind.name_length,
Packit fcad23
                                 varbind->val.objid,
Packit fcad23
                                 varbind->val_len / sizeof(oid));
Packit fcad23
    } else
Packit fcad23
        res =
Packit fcad23
            register_oid_index(varbind->name, varbind.name_length, NULL,
Packit fcad23
                               0);
Packit fcad23
Packit fcad23
    if (res == NULL)
Packit fcad23
        printf("allocating %d/%d failed\n", n, subid);
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
main(int argc, char argv[])
Packit fcad23
{
Packit fcad23
    oid             name[] = { 1, 2, 3, 4, 0 };
Packit fcad23
    int             i;
Packit fcad23
Packit fcad23
    memset(&varbind, 0, sizeof(netsnmp_variable_list));
Packit fcad23
    snmp_set_var_objid(&varbind, name, 5);
Packit fcad23
    varbind->type = ASN_OCTET_STR;
Packit fcad23
    /*
Packit fcad23
     * Test index structure linking:
Packit fcad23
     *      a) sorted by OID
Packit fcad23
     */
Packit fcad23
    test_string_register(20, "empty OID");
Packit fcad23
    test_string_register(10, "first OID");
Packit fcad23
    test_string_register(40, "last OID");
Packit fcad23
    test_string_register(30, "middle OID");
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *      b) sorted by index value
Packit fcad23
     */
Packit fcad23
    test_string_register(25, "eee: empty IDX");
Packit fcad23
    test_string_register(25, "aaa: first IDX");
Packit fcad23
    test_string_register(25, "zzz: last IDX");
Packit fcad23
    test_string_register(25, "mmm: middle IDX");
Packit fcad23
    printf("This next one should fail....\n");
Packit fcad23
    test_string_register(25, "eee: empty IDX"); /* duplicate */
Packit fcad23
    printf("done\n");
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *      c) test initial index linking
Packit fcad23
     */
Packit fcad23
    test_string_register(5, "eee: empty initial IDX");
Packit fcad23
    test_string_register(5, "aaa: replace initial IDX");
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *      Did it all work?
Packit fcad23
     */
Packit fcad23
    dump_idx_registry();
Packit fcad23
    unregister_index_by_session(main_session);
Packit fcad23
    /*
Packit fcad23
     *  Now test index allocation
Packit fcad23
     *      a) integer values
Packit fcad23
     */
Packit fcad23
    test_int_register(110, -1); /* empty */
Packit fcad23
    test_int_register(110, -1); /* append */
Packit fcad23
    test_int_register(110, 10); /* append exact */
Packit fcad23
    printf("This next one should fail....\n");
Packit fcad23
    test_int_register(110, 10); /* exact duplicate */
Packit fcad23
    printf("done\n");
Packit fcad23
    test_int_register(110, -1); /* append */
Packit fcad23
    test_int_register(110, 5);  /* insert exact */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *      b) string values
Packit fcad23
     */
Packit fcad23
    test_string_register(120, NULL);    /* empty */
Packit fcad23
    test_string_register(120, NULL);    /* append */
Packit fcad23
    test_string_register(120, "aaaz");
Packit fcad23
    test_string_register(120, NULL);    /* minor rollover */
Packit fcad23
    test_string_register(120, "zzzz");
Packit fcad23
    test_string_register(120, NULL);    /* major rollover */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *      c) OID values
Packit fcad23
     */
Packit fcad23
Packit fcad23
    test_oid_register(130, -1); /* empty */
Packit fcad23
    test_oid_register(130, -1); /* append */
Packit fcad23
Packit fcad23
    varbind->val_len = varbind.name_length * sizeof(oid);
Packit fcad23
    memcpy(varbind->buf, varbind.name, varbind.val_len);
Packit fcad23
    varbind->val.objid = (oid *) varbind.buf;
Packit fcad23
    varbind->val_len += sizeof(oid);
Packit fcad23
Packit fcad23
    test_oid_register(130, 255);        /* append exact */
Packit fcad23
    test_oid_register(130, -1); /* minor rollover */
Packit fcad23
    test_oid_register(130, 100);        /* insert exact */
Packit fcad23
    printf("This next one should fail....\n");
Packit fcad23
    test_oid_register(130, 100);        /* exact duplicate */
Packit fcad23
    printf("done\n");
Packit fcad23
Packit fcad23
    varbind->val.objid = (oid *) varbind.buf;
Packit fcad23
    for (i = 0; i < 6; i++)
Packit fcad23
        varbind->val.objid[i] = 255;
Packit fcad23
    varbind->val.objid[0] = 1;
Packit fcad23
    test_oid_register(130, 255);        /* set up rollover  */
Packit fcad23
    test_oid_register(130, -1); /* medium rollover */
Packit fcad23
Packit fcad23
    for (i = 0; i < 6; i++)
Packit fcad23
        varbind->val.objid[i] = 255;
Packit fcad23
    varbind->val.objid[0] = 2;
Packit fcad23
    test_oid_register(130, 255);        /* set up rollover  */
Packit fcad23
    test_oid_register(130, -1); /* major rollover */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *      Did it all work?
Packit fcad23
     */
Packit fcad23
    dump_idx_registry();
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *      Test the various "invalid" requests
Packit fcad23
     *      (unsupported types, mis-matched types, etc)
Packit fcad23
     */
Packit fcad23
    printf("The rest of these should fail....\n");
Packit fcad23
    test_oid_register(110, -1);
Packit fcad23
    test_oid_register(110, 100);
Packit fcad23
    test_oid_register(120, -1);
Packit fcad23
    test_oid_register(120, 100);
Packit fcad23
    test_string_register(110, NULL);
Packit fcad23
    test_string_register(110, "aaaa");
Packit fcad23
    test_string_register(130, NULL);
Packit fcad23
    test_string_register(130, "aaaa");
Packit fcad23
    test_int_register(120, -1);
Packit fcad23
    test_int_register(120, 1);
Packit fcad23
    test_int_register(130, -1);
Packit fcad23
    test_int_register(130, 1);
Packit fcad23
    printf("done - this dump should be the same as before\n");
Packit fcad23
    dump_idx_registry();
Packit fcad23
}
Packit fcad23
#endif