📄 mib_structs.c
字号:
/** * @file * MIB tree access/construction functions. *//* * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * Author: Christiaan Simons <christiaan.simons@axon.tv> */#include "lwip/opt.h"#if LWIP_SNMP#include "lwip/snmp_structs.h"#include "lwip/mem.h"/** .iso.org.dod.internet address prefix, @see snmp_iso_*() */const s32_t prefix[4] = {1, 3, 6, 1};#define NODE_STACK_SIZE (LWIP_SNMP_OBJ_ID_LEN)/** node stack entry (old news?) */struct nse{ /** right child */ struct mib_node* r_ptr; /** right child identifier */ s32_t r_id; /** right child next level */ u8_t r_nl;};static u8_t node_stack_cnt = 0;static struct nse node_stack[NODE_STACK_SIZE];/** * Pushes nse struct onto stack. */static voidpush_node(struct nse* node){ LWIP_ASSERT("node_stack_cnt < NODE_STACK_SIZE",node_stack_cnt < NODE_STACK_SIZE); LWIP_DEBUGF(SNMP_MIB_DEBUG,("push_node() node=%p id=%"S32_F"\n",(void*)(node->r_ptr),node->r_id)); if (node_stack_cnt < NODE_STACK_SIZE) { node_stack[node_stack_cnt] = *node; node_stack_cnt++; }}/** * Pops nse struct from stack. */static voidpop_node(struct nse* node){ if (node_stack_cnt > 0) { node_stack_cnt--; *node = node_stack[node_stack_cnt]; } LWIP_DEBUGF(SNMP_MIB_DEBUG,("pop_node() node=%p id=%"S32_F"\n",(void *)(node->r_ptr),node->r_id));}/** * Conversion from ifIndex to lwIP netif * @param ifindex is a s32_t object sub-identifier * @param netif points to returned netif struct pointer */voidsnmp_ifindextonetif(s32_t ifindex, struct netif **netif){ struct netif *nif = netif_list; u16_t i, ifidx; ifidx = ifindex - 1; i = 0; while ((nif != NULL) && (i < ifidx)) { nif = nif->next; i++; } *netif = nif;}/** * Conversion from lwIP netif to ifIndex * @param netif points to a netif struct * @param ifindex points to s32_t object sub-identifier */voidsnmp_netiftoifindex(struct netif *netif, s32_t *ifidx){ struct netif *nif = netif_list; u16_t i; i = 0; while (nif != netif) { nif = nif->next; i++; } *ifidx = i+1;}/** * Conversion from oid to lwIP ip_addr * @param ident points to s32_t ident[4] input * @param ip points to output struct */voidsnmp_oidtoip(s32_t *ident, struct ip_addr *ip){ u32_t ipa; ipa = ident[0]; ipa <<= 8; ipa |= ident[1]; ipa <<= 8; ipa |= ident[2]; ipa <<= 8; ipa |= ident[3]; ip->addr = ipa;}/** * Conversion from lwIP ip_addr to oid * @param ip points to input struct * @param ident points to s32_t ident[4] output */voidsnmp_iptooid(struct ip_addr *ip, s32_t *ident){ u32_t ipa; ipa = ip->addr; ident[0] = (ipa >> 24) & 0xff; ident[1] = (ipa >> 16) & 0xff; ident[2] = (ipa >> 8) & 0xff; ident[3] = ipa & 0xff;}struct mib_list_node *snmp_mib_ln_alloc(s32_t id){ struct mib_list_node *ln; ln = (struct mib_list_node *)mem_malloc(sizeof(struct mib_list_node)); if (ln != NULL) { ln->prev = NULL; ln->next = NULL; ln->objid = id; ln->nptr = NULL; } return ln;}voidsnmp_mib_ln_free(struct mib_list_node *ln){ mem_free(ln);}struct mib_list_rootnode *snmp_mib_lrn_alloc(void){ struct mib_list_rootnode *lrn; lrn = (struct mib_list_rootnode*)mem_malloc(sizeof(struct mib_list_rootnode)); if (lrn != NULL) { lrn->get_object_def = noleafs_get_object_def; lrn->get_value = noleafs_get_value; lrn->set_test = noleafs_set_test; lrn->set_value = noleafs_set_value; lrn->node_type = MIB_NODE_LR; lrn->maxlength = 0; lrn->head = NULL; lrn->tail = NULL; lrn->count = 0; } return lrn;}voidsnmp_mib_lrn_free(struct mib_list_rootnode *lrn){ mem_free(lrn);}/** * Inserts node in idx list in a sorted * (ascending order) fashion and * allocates the node if needed. * * @param rn points to the root node * @param objid is the object sub identifier * @param insn points to a pointer to the inserted node * used for constructing the tree. * @return -1 if failed, 1 if inserted, 2 if present. */s8_tsnmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn){ struct mib_list_node *nn; s8_t insert; LWIP_ASSERT("rn != NULL",rn != NULL); /* -1 = malloc failure, 0 = not inserted, 1 = inserted, 2 = was present */ insert = 0; if (rn->head == NULL) { /* empty list, add first node */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc empty list objid==%"S32_F"\n",objid)); nn = snmp_mib_ln_alloc(objid); if (nn != NULL) { rn->head = nn; rn->tail = nn; *insn = nn; insert = 1; } else { insert = -1; } } else { struct mib_list_node *n; /* at least one node is present */ n = rn->head; while ((n != NULL) && (insert == 0)) { if (n->objid == objid) { /* node is already there */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("node already there objid==%"S32_F"\n",objid)); *insn = n; insert = 2; } else if (n->objid < objid) { if (n->next == NULL) { /* alloc and insert at the tail */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins tail objid==%"S32_F"\n",objid)); nn = snmp_mib_ln_alloc(objid); if (nn != NULL) { nn->next = NULL; nn->prev = n; n->next = nn; rn->tail = nn; *insn = nn; insert = 1; } else { /* insertion failure */ insert = -1; } } else { /* there's more to explore: traverse list */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("traverse list\n")); n = n->next; } } else { /* n->objid > objid */ /* alloc and insert between n->prev and n */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins n->prev, objid==%"S32_F", n\n",objid)); nn = snmp_mib_ln_alloc(objid); if (nn != NULL) { if (n->prev == NULL) { /* insert at the head */ nn->next = n; nn->prev = NULL; rn->head = nn; n->prev = nn; } else { /* insert in the middle */ nn->next = n; nn->prev = n->prev; n->prev->next = nn; n->prev = nn; } *insn = nn; insert = 1; } else { /* insertion failure */ insert = -1; } } } } if (insert == 1) { rn->count += 1; } LWIP_ASSERT("insert != 0",insert != 0); return insert;}/** * Finds node in idx list and returns deletion mark. * * @param rn points to the root node * @param objid is the object sub identifier * @param fn returns pointer to found node * @return 0 if not found, 1 if deletable, * 2 can't delete (2 or more children), 3 not a list_node */s8_tsnmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn){ s8_t fc; struct mib_list_node *n; LWIP_ASSERT("rn != NULL",rn != NULL); n = rn->head; while ((n != NULL) && (n->objid != objid)) { n = n->next; } if (n == NULL) { fc = 0; } else if (n->nptr == NULL) { /* leaf, can delete node */ fc = 1; } else { struct mib_list_rootnode *rn; if (n->nptr->node_type == MIB_NODE_LR) { rn = (struct mib_list_rootnode *)n->nptr; if (rn->count > 1) { /* can't delete node */ fc = 2; } else { /* count <= 1, can delete node */ fc = 1; } } else { /* other node type */ fc = 3; } } *fn = n; return fc;}/** * Removes node from idx list * if it has a single child left. * * @param rn points to the root node * @param n points to the node to delete * @return the nptr to be freed by caller */struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n){ struct mib_list_rootnode *next; LWIP_ASSERT("rn != NULL",rn != NULL); LWIP_ASSERT("n != NULL",n != NULL); /* caller must remove this sub-tree */ next = (struct mib_list_rootnode*)(n->nptr); rn->count -= 1; if (n == rn->head) { rn->head = n->next; if (n->next != NULL) { /* not last node, new list begin */ n->next->prev = NULL; } } else if (n == rn->tail) { rn->tail = n->prev; if (n->prev != NULL) { /* not last node, new list end */ n->prev->next = NULL; } } else { /* node must be in the middle */ n->prev->next = n->next; n->next->prev = n->prev; } LWIP_DEBUGF(SNMP_MIB_DEBUG,("free list objid==%"S32_F"\n",n->objid)); snmp_mib_ln_free(n); if (rn->count == 0) { rn->head = NULL; rn->tail = NULL; } return next;}/** * Searches tree for the supplied (scalar?) object identifier. * * @param node points to the root of the tree ('.internet') * @param ident_len the length of the supplied object identifier * @param ident points to the array of sub identifiers * @param np points to the found object instance (rerurn) * @return pointer to the requested parent (!) node if success, NULL otherwise */struct mib_node *snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np){ u8_t node_type, ext_level; ext_level = 0; LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident)); while (node != NULL) { node_type = node->node_type; if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) { struct mib_array_node *an; u16_t i; if (ident_len > 0) { /* array node (internal ROM or RAM, fixed length) */ an = (struct mib_array_node *)node; i = 0; while ((i < an->maxlength) && (an->objid[i] != *ident)) { i++; } if (i < an->maxlength) { /* found it, if available proceed to child, otherwise inspect leaf */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); if (an->nptr[i] == NULL) { /* a scalar leaf OR table, inspect remaining instance number / table index */ np->ident_len = ident_len; np->ident = ident; return (struct mib_node*)an; } else { /* follow next child pointer */ ident++; ident_len--; node = an->nptr[i]; } } else { /* search failed, identifier mismatch (nosuchname) */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident)); return NULL; } } else { /* search failed, short object identifier (nosuchname) */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n")); return NULL; } } else if(node_type == MIB_NODE_LR) { struct mib_list_rootnode *lrn; struct mib_list_node *ln; if (ident_len > 0) { /* list root node (internal 'RAM', variable length) */ lrn = (struct mib_list_rootnode *)node; ln = lrn->head; /* iterate over list, head to tail */ while ((ln != NULL) && (ln->objid != *ident)) { ln = ln->next; } if (ln != NULL) { /* found it, proceed to child */; LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); if (ln->nptr == NULL) { np->ident_len = ident_len; np->ident = ident; return (struct mib_node*)lrn; } else { /* follow next child pointer */ ident_len--; ident++; node = ln->nptr; } } else { /* search failed */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident)); return NULL; } } else { /* search failed, short object identifier (nosuchname) */ LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n")); return NULL; } } else if(node_type == MIB_NODE_EX) { struct mib_external_node *en; u16_t i, len; if (ident_len > 0) { /* external node (addressing and access via functions) */ en = (struct mib_external_node *)node; i = 0; len = en->level_length(en->addr_inf,ext_level); while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0)) { i++; } if (i < len) { s32_t debug_id; en->get_objid(en->addr_inf,ext_level,i,&debug_id); LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident)); if ((ext_level + 1) == en->tree_levels) { np->ident_len = ident_len; np->ident = ident;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -