NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
mib_structs.c
00001 /** 00002 * @file 00003 * MIB tree access/construction functions. 00004 */ 00005 00006 /* 00007 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without modification, 00011 * are permitted provided that the following conditions are met: 00012 * 00013 * 1. Redistributions of source code must retain the above copyright notice, 00014 * this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright notice, 00016 * this list of conditions and the following disclaimer in the documentation 00017 * and/or other materials provided with the distribution. 00018 * 3. The name of the author may not be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00024 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00026 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00029 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00030 * OF SUCH DAMAGE. 00031 * 00032 * Author: Christiaan Simons <christiaan.simons@axon.tv> 00033 */ 00034 00035 #include "lwip/opt.h" 00036 00037 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ 00038 00039 #include "lwip/snmp_structs.h" 00040 #include "lwip/memp.h" 00041 #include "lwip/netif.h" 00042 00043 /** .iso.org.dod.internet address prefix, @see snmp_iso_*() */ 00044 const s32_t prefix[4] = {1, 3, 6, 1}; 00045 00046 #define NODE_STACK_SIZE (LWIP_SNMP_OBJ_ID_LEN) 00047 /** node stack entry (old news?) */ 00048 struct nse 00049 { 00050 /** right child */ 00051 struct mib_node* r_ptr; 00052 /** right child identifier */ 00053 s32_t r_id; 00054 /** right child next level */ 00055 u8_t r_nl; 00056 }; 00057 static u8_t node_stack_cnt; 00058 static struct nse node_stack[NODE_STACK_SIZE]; 00059 00060 /** 00061 * Pushes nse struct onto stack. 00062 */ 00063 static void 00064 push_node(struct nse* node) 00065 { 00066 LWIP_ASSERT("node_stack_cnt < NODE_STACK_SIZE",node_stack_cnt < NODE_STACK_SIZE); 00067 LWIP_DEBUGF(SNMP_MIB_DEBUG,("push_node() node=%p id=%"S32_F"\n",(void*)(node->r_ptr),node->r_id)); 00068 if (node_stack_cnt < NODE_STACK_SIZE) 00069 { 00070 node_stack[node_stack_cnt] = *node; 00071 node_stack_cnt++; 00072 } 00073 } 00074 00075 /** 00076 * Pops nse struct from stack. 00077 */ 00078 static void 00079 pop_node(struct nse* node) 00080 { 00081 if (node_stack_cnt > 0) 00082 { 00083 node_stack_cnt--; 00084 *node = node_stack[node_stack_cnt]; 00085 } 00086 LWIP_DEBUGF(SNMP_MIB_DEBUG,("pop_node() node=%p id=%"S32_F"\n",(void *)(node->r_ptr),node->r_id)); 00087 } 00088 00089 /** 00090 * Conversion from ifIndex to lwIP netif 00091 * @param ifindex is a s32_t object sub-identifier 00092 * @param netif points to returned netif struct pointer 00093 */ 00094 void 00095 snmp_ifindextonetif(s32_t ifindex, struct netif **netif) 00096 { 00097 struct netif *nif = netif_list; 00098 s32_t i, ifidx; 00099 00100 ifidx = ifindex - 1; 00101 i = 0; 00102 while ((nif != NULL) && (i < ifidx)) 00103 { 00104 nif = nif->next; 00105 i++; 00106 } 00107 *netif = nif; 00108 } 00109 00110 /** 00111 * Conversion from lwIP netif to ifIndex 00112 * @param netif points to a netif struct 00113 * @param ifidx points to s32_t object sub-identifier 00114 */ 00115 void 00116 snmp_netiftoifindex(struct netif *netif, s32_t *ifidx) 00117 { 00118 struct netif *nif = netif_list; 00119 u16_t i; 00120 00121 i = 0; 00122 while ((nif != NULL) && (nif != netif)) 00123 { 00124 nif = nif->next; 00125 i++; 00126 } 00127 *ifidx = i+1; 00128 } 00129 00130 /** 00131 * Conversion from oid to lwIP ip_addr 00132 * @param ident points to s32_t ident[4] input 00133 * @param ip points to output struct 00134 */ 00135 void 00136 snmp_oidtoip(s32_t *ident, ip_addr_t *ip) 00137 { 00138 IP4_ADDR(ip, ident[0], ident[1], ident[2], ident[3]); 00139 } 00140 00141 /** 00142 * Conversion from lwIP ip_addr to oid 00143 * @param ip points to input struct 00144 * @param ident points to s32_t ident[4] output 00145 */ 00146 void 00147 snmp_iptooid(ip_addr_t *ip, s32_t *ident) 00148 { 00149 ident[0] = ip4_addr1(ip); 00150 ident[1] = ip4_addr2(ip); 00151 ident[2] = ip4_addr3(ip); 00152 ident[3] = ip4_addr4(ip); 00153 } 00154 00155 struct mib_list_node * 00156 snmp_mib_ln_alloc(s32_t id) 00157 { 00158 struct mib_list_node *ln; 00159 00160 ln = (struct mib_list_node *)memp_malloc(MEMP_SNMP_NODE); 00161 if (ln != NULL) 00162 { 00163 ln->prev = NULL; 00164 ln->next = NULL; 00165 ln->objid = id; 00166 ln->nptr = NULL; 00167 } 00168 return ln; 00169 } 00170 00171 void 00172 snmp_mib_ln_free(struct mib_list_node *ln) 00173 { 00174 memp_free(MEMP_SNMP_NODE, ln); 00175 } 00176 00177 struct mib_list_rootnode * 00178 snmp_mib_lrn_alloc(void) 00179 { 00180 struct mib_list_rootnode *lrn; 00181 00182 lrn = (struct mib_list_rootnode*)memp_malloc(MEMP_SNMP_ROOTNODE); 00183 if (lrn != NULL) 00184 { 00185 lrn->get_object_def = noleafs_get_object_def; 00186 lrn->get_value = noleafs_get_value; 00187 lrn->set_test = noleafs_set_test; 00188 lrn->set_value = noleafs_set_value; 00189 lrn->node_type = MIB_NODE_LR; 00190 lrn->maxlength = 0; 00191 lrn->head = NULL; 00192 lrn->tail = NULL; 00193 lrn->count = 0; 00194 } 00195 return lrn; 00196 } 00197 00198 void 00199 snmp_mib_lrn_free(struct mib_list_rootnode *lrn) 00200 { 00201 memp_free(MEMP_SNMP_ROOTNODE, lrn); 00202 } 00203 00204 /** 00205 * Inserts node in idx list in a sorted 00206 * (ascending order) fashion and 00207 * allocates the node if needed. 00208 * 00209 * @param rn points to the root node 00210 * @param objid is the object sub identifier 00211 * @param insn points to a pointer to the inserted node 00212 * used for constructing the tree. 00213 * @return -1 if failed, 1 if inserted, 2 if present. 00214 */ 00215 s8_t 00216 snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn) 00217 { 00218 struct mib_list_node *nn; 00219 s8_t insert; 00220 00221 LWIP_ASSERT("rn != NULL",rn != NULL); 00222 00223 /* -1 = malloc failure, 0 = not inserted, 1 = inserted, 2 = was present */ 00224 insert = 0; 00225 if (rn->head == NULL) 00226 { 00227 /* empty list, add first node */ 00228 LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc empty list objid==%"S32_F"\n",objid)); 00229 nn = snmp_mib_ln_alloc(objid); 00230 if (nn != NULL) 00231 { 00232 rn->head = nn; 00233 rn->tail = nn; 00234 *insn = nn; 00235 insert = 1; 00236 } 00237 else 00238 { 00239 insert = -1; 00240 } 00241 } 00242 else 00243 { 00244 struct mib_list_node *n; 00245 /* at least one node is present */ 00246 n = rn->head; 00247 while ((n != NULL) && (insert == 0)) 00248 { 00249 if (n->objid == objid) 00250 { 00251 /* node is already there */ 00252 LWIP_DEBUGF(SNMP_MIB_DEBUG,("node already there objid==%"S32_F"\n",objid)); 00253 *insn = n; 00254 insert = 2; 00255 } 00256 else if (n->objid < objid) 00257 { 00258 if (n->next == NULL) 00259 { 00260 /* alloc and insert at the tail */ 00261 LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins tail objid==%"S32_F"\n",objid)); 00262 nn = snmp_mib_ln_alloc(objid); 00263 if (nn != NULL) 00264 { 00265 nn->next = NULL; 00266 nn->prev = n; 00267 n->next = nn; 00268 rn->tail = nn; 00269 *insn = nn; 00270 insert = 1; 00271 } 00272 else 00273 { 00274 /* insertion failure */ 00275 insert = -1; 00276 } 00277 } 00278 else 00279 { 00280 /* there's more to explore: traverse list */ 00281 LWIP_DEBUGF(SNMP_MIB_DEBUG,("traverse list\n")); 00282 n = n->next; 00283 } 00284 } 00285 else 00286 { 00287 /* n->objid > objid */ 00288 /* alloc and insert between n->prev and n */ 00289 LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins n->prev, objid==%"S32_F", n\n",objid)); 00290 nn = snmp_mib_ln_alloc(objid); 00291 if (nn != NULL) 00292 { 00293 if (n->prev == NULL) 00294 { 00295 /* insert at the head */ 00296 nn->next = n; 00297 nn->prev = NULL; 00298 rn->head = nn; 00299 n->prev = nn; 00300 } 00301 else 00302 { 00303 /* insert in the middle */ 00304 nn->next = n; 00305 nn->prev = n->prev; 00306 n->prev->next = nn; 00307 n->prev = nn; 00308 } 00309 *insn = nn; 00310 insert = 1; 00311 } 00312 else 00313 { 00314 /* insertion failure */ 00315 insert = -1; 00316 } 00317 } 00318 } 00319 } 00320 if (insert == 1) 00321 { 00322 rn->count += 1; 00323 } 00324 LWIP_ASSERT("insert != 0",insert != 0); 00325 return insert; 00326 } 00327 00328 /** 00329 * Finds node in idx list and returns deletion mark. 00330 * 00331 * @param rn points to the root node 00332 * @param objid is the object sub identifier 00333 * @param fn returns pointer to found node 00334 * @return 0 if not found, 1 if deletable, 00335 * 2 can't delete (2 or more children), 3 not a list_node 00336 */ 00337 s8_t 00338 snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn) 00339 { 00340 s8_t fc; 00341 struct mib_list_node *n; 00342 00343 LWIP_ASSERT("rn != NULL",rn != NULL); 00344 n = rn->head; 00345 while ((n != NULL) && (n->objid != objid)) 00346 { 00347 n = n->next; 00348 } 00349 if (n == NULL) 00350 { 00351 fc = 0; 00352 } 00353 else if (n->nptr == NULL) 00354 { 00355 /* leaf, can delete node */ 00356 fc = 1; 00357 } 00358 else 00359 { 00360 struct mib_list_rootnode *r; 00361 00362 if (n->nptr->node_type == MIB_NODE_LR) 00363 { 00364 r = (struct mib_list_rootnode *)n->nptr; 00365 if (r->count > 1) 00366 { 00367 /* can't delete node */ 00368 fc = 2; 00369 } 00370 else 00371 { 00372 /* count <= 1, can delete node */ 00373 fc = 1; 00374 } 00375 } 00376 else 00377 { 00378 /* other node type */ 00379 fc = 3; 00380 } 00381 } 00382 *fn = n; 00383 return fc; 00384 } 00385 00386 /** 00387 * Removes node from idx list 00388 * if it has a single child left. 00389 * 00390 * @param rn points to the root node 00391 * @param n points to the node to delete 00392 * @return the nptr to be freed by caller 00393 */ 00394 struct mib_list_rootnode * 00395 snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n) 00396 { 00397 struct mib_list_rootnode *next; 00398 00399 LWIP_ASSERT("rn != NULL",rn != NULL); 00400 LWIP_ASSERT("n != NULL",n != NULL); 00401 00402 /* caller must remove this sub-tree */ 00403 next = (struct mib_list_rootnode*)(n->nptr); 00404 rn->count -= 1; 00405 00406 if (n == rn->head) 00407 { 00408 rn->head = n->next; 00409 if (n->next != NULL) 00410 { 00411 /* not last node, new list begin */ 00412 n->next->prev = NULL; 00413 } 00414 } 00415 else if (n == rn->tail) 00416 { 00417 rn->tail = n->prev; 00418 if (n->prev != NULL) 00419 { 00420 /* not last node, new list end */ 00421 n->prev->next = NULL; 00422 } 00423 } 00424 else 00425 { 00426 /* node must be in the middle */ 00427 n->prev->next = n->next; 00428 n->next->prev = n->prev; 00429 } 00430 LWIP_DEBUGF(SNMP_MIB_DEBUG,("free list objid==%"S32_F"\n",n->objid)); 00431 snmp_mib_ln_free(n); 00432 if (rn->count == 0) 00433 { 00434 rn->head = NULL; 00435 rn->tail = NULL; 00436 } 00437 return next; 00438 } 00439 00440 00441 00442 /** 00443 * Searches tree for the supplied (scalar?) object identifier. 00444 * 00445 * @param node points to the root of the tree ('.internet') 00446 * @param ident_len the length of the supplied object identifier 00447 * @param ident points to the array of sub identifiers 00448 * @param np points to the found object instance (return) 00449 * @return pointer to the requested parent (!) node if success, NULL otherwise 00450 */ 00451 struct mib_node * 00452 snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np) 00453 { 00454 u8_t node_type, ext_level; 00455 00456 ext_level = 0; 00457 LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident)); 00458 while (node != NULL) 00459 { 00460 node_type = node->node_type; 00461 if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) 00462 { 00463 struct mib_array_node *an; 00464 u16_t i; 00465 00466 if (ident_len > 0) 00467 { 00468 /* array node (internal ROM or RAM, fixed length) */ 00469 an = (struct mib_array_node *)node; 00470 i = 0; 00471 while ((i < an->maxlength) && (an->objid[i] != *ident)) 00472 { 00473 i++; 00474 } 00475 if (i < an->maxlength) 00476 { 00477 /* found it, if available proceed to child, otherwise inspect leaf */ 00478 LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); 00479 if (an->nptr[i] == NULL) 00480 { 00481 /* a scalar leaf OR table, 00482 inspect remaining instance number / table index */ 00483 np->ident_len = ident_len; 00484 np->ident = ident; 00485 return (struct mib_node*)an; 00486 } 00487 else 00488 { 00489 /* follow next child pointer */ 00490 ident++; 00491 ident_len--; 00492 node = an->nptr[i]; 00493 } 00494 } 00495 else 00496 { 00497 /* search failed, identifier mismatch (nosuchname) */ 00498 LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident)); 00499 return NULL; 00500 } 00501 } 00502 else 00503 { 00504 /* search failed, short object identifier (nosuchname) */ 00505 LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n")); 00506 return NULL; 00507 } 00508 } 00509 else if(node_type == MIB_NODE_LR) 00510 { 00511 struct mib_list_rootnode *lrn; 00512 struct mib_list_node *ln; 00513 00514 if (ident_len > 0) 00515 { 00516 /* list root node (internal 'RAM', variable length) */ 00517 lrn = (struct mib_list_rootnode *)node; 00518 ln = lrn->head; 00519 /* iterate over list, head to tail */ 00520 while ((ln != NULL) && (ln->objid != *ident)) 00521 { 00522 ln = ln->next; 00523 } 00524 if (ln != NULL) 00525 { 00526 /* found it, proceed to child */; 00527 LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); 00528 if (ln->nptr == NULL) 00529 { 00530 np->ident_len = ident_len; 00531 np->ident = ident; 00532 return (struct mib_node*)lrn; 00533 } 00534 else 00535 { 00536 /* follow next child pointer */ 00537 ident_len--; 00538 ident++; 00539 node = ln->nptr; 00540 } 00541 } 00542 else 00543 { 00544 /* search failed */ 00545 LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident)); 00546 return NULL; 00547 } 00548 } 00549 else 00550 { 00551 /* search failed, short object identifier (nosuchname) */ 00552 LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n")); 00553 return NULL; 00554 } 00555 } 00556 else if(node_type == MIB_NODE_EX) 00557 { 00558 struct mib_external_node *en; 00559 u16_t i, len; 00560 00561 if (ident_len > 0) 00562 { 00563 /* external node (addressing and access via functions) */ 00564 en = (struct mib_external_node *)node; 00565 00566 i = 0; 00567 len = en->level_length(en->addr_inf,ext_level); 00568 while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0)) 00569 { 00570 i++; 00571 } 00572 if (i < len) 00573 { 00574 s32_t debug_id; 00575 00576 en->get_objid(en->addr_inf,ext_level,i,&debug_id); 00577 LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident)); 00578 if ((ext_level + 1) == en->tree_levels) 00579 { 00580 np->ident_len = ident_len; 00581 np->ident = ident; 00582 return (struct mib_node*)en; 00583 } 00584 else 00585 { 00586 /* found it, proceed to child */ 00587 ident_len--; 00588 ident++; 00589 ext_level++; 00590 } 00591 } 00592 else 00593 { 00594 /* search failed */ 00595 LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed *ident==%"S32_F"\n",*ident)); 00596 return NULL; 00597 } 00598 } 00599 else 00600 { 00601 /* search failed, short object identifier (nosuchname) */ 00602 LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed, short object identifier\n")); 00603 return NULL; 00604 } 00605 } 00606 else if (node_type == MIB_NODE_SC) 00607 { 00608 mib_scalar_node *sn; 00609 00610 sn = (mib_scalar_node *)node; 00611 if ((ident_len == 1) && (*ident == 0)) 00612 { 00613 np->ident_len = ident_len; 00614 np->ident = ident; 00615 return (struct mib_node*)sn; 00616 } 00617 else 00618 { 00619 /* search failed, short object identifier (nosuchname) */ 00620 LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, invalid object identifier length\n")); 00621 return NULL; 00622 } 00623 } 00624 else 00625 { 00626 /* unknown node_type */ 00627 LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node_type %"U16_F" unkown\n",(u16_t)node_type)); 00628 return NULL; 00629 } 00630 } 00631 /* done, found nothing */ 00632 LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node==%p\n",(void*)node)); 00633 return NULL; 00634 } 00635 00636 /** 00637 * Test table for presence of at least one table entry. 00638 */ 00639 static u8_t 00640 empty_table(struct mib_node *node) 00641 { 00642 u8_t node_type; 00643 u8_t empty = 0; 00644 00645 if (node != NULL) 00646 { 00647 node_type = node->node_type; 00648 if (node_type == MIB_NODE_LR) 00649 { 00650 struct mib_list_rootnode *lrn; 00651 lrn = (struct mib_list_rootnode *)node; 00652 if ((lrn->count == 0) || (lrn->head == NULL)) 00653 { 00654 empty = 1; 00655 } 00656 } 00657 else if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) 00658 { 00659 struct mib_array_node *an; 00660 an = (struct mib_array_node *)node; 00661 if ((an->maxlength == 0) || (an->nptr == NULL)) 00662 { 00663 empty = 1; 00664 } 00665 } 00666 else if (node_type == MIB_NODE_EX) 00667 { 00668 struct mib_external_node *en; 00669 en = (struct mib_external_node *)node; 00670 if (en->tree_levels == 0) 00671 { 00672 empty = 1; 00673 } 00674 } 00675 } 00676 return empty; 00677 } 00678 00679 /** 00680 * Tree expansion. 00681 */ 00682 struct mib_node * 00683 snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) 00684 { 00685 u8_t node_type, ext_level, climb_tree; 00686 00687 ext_level = 0; 00688 /* reset node stack */ 00689 node_stack_cnt = 0; 00690 while (node != NULL) 00691 { 00692 climb_tree = 0; 00693 node_type = node->node_type; 00694 if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) 00695 { 00696 struct mib_array_node *an; 00697 u16_t i; 00698 00699 /* array node (internal ROM or RAM, fixed length) */ 00700 an = (struct mib_array_node *)node; 00701 if (ident_len > 0) 00702 { 00703 i = 0; 00704 while ((i < an->maxlength) && (an->objid[i] < *ident)) 00705 { 00706 i++; 00707 } 00708 if (i < an->maxlength) 00709 { 00710 LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); 00711 /* add identifier to oidret */ 00712 oidret->id[oidret->len] = an->objid[i]; 00713 (oidret->len)++; 00714 00715 if (an->nptr[i] == NULL) 00716 { 00717 LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); 00718 /* leaf node (e.g. in a fixed size table) */ 00719 if (an->objid[i] > *ident) 00720 { 00721 return (struct mib_node*)an; 00722 } 00723 else if ((i + 1) < an->maxlength) 00724 { 00725 /* an->objid[i] == *ident */ 00726 (oidret->len)--; 00727 oidret->id[oidret->len] = an->objid[i + 1]; 00728 (oidret->len)++; 00729 return (struct mib_node*)an; 00730 } 00731 else 00732 { 00733 /* (i + 1) == an->maxlength */ 00734 (oidret->len)--; 00735 climb_tree = 1; 00736 } 00737 } 00738 else 00739 { 00740 u8_t j; 00741 struct nse cur_node; 00742 00743 LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); 00744 /* non-leaf, store right child ptr and id */ 00745 LWIP_ASSERT("i < 0xff", i < 0xff); 00746 j = (u8_t)i + 1; 00747 while ((j < an->maxlength) && (empty_table(an->nptr[j]))) 00748 { 00749 j++; 00750 } 00751 if (j < an->maxlength) 00752 { 00753 cur_node.r_ptr = an->nptr[j]; 00754 cur_node.r_id = an->objid[j]; 00755 cur_node.r_nl = 0; 00756 } 00757 else 00758 { 00759 cur_node.r_ptr = NULL; 00760 } 00761 push_node(&cur_node); 00762 if (an->objid[i] == *ident) 00763 { 00764 ident_len--; 00765 ident++; 00766 } 00767 else 00768 { 00769 /* an->objid[i] < *ident */ 00770 ident_len = 0; 00771 } 00772 /* follow next child pointer */ 00773 node = an->nptr[i]; 00774 } 00775 } 00776 else 00777 { 00778 /* i == an->maxlength */ 00779 climb_tree = 1; 00780 } 00781 } 00782 else 00783 { 00784 u8_t j; 00785 /* ident_len == 0, complete with leftmost '.thing' */ 00786 j = 0; 00787 while ((j < an->maxlength) && empty_table(an->nptr[j])) 00788 { 00789 j++; 00790 } 00791 if (j < an->maxlength) 00792 { 00793 LWIP_DEBUGF(SNMP_MIB_DEBUG,("left an->objid[j]==%"S32_F"\n",an->objid[j])); 00794 oidret->id[oidret->len] = an->objid[j]; 00795 (oidret->len)++; 00796 if (an->nptr[j] == NULL) 00797 { 00798 /* leaf node */ 00799 return (struct mib_node*)an; 00800 } 00801 else 00802 { 00803 /* no leaf, continue */ 00804 node = an->nptr[j]; 00805 } 00806 } 00807 else 00808 { 00809 /* j == an->maxlength */ 00810 climb_tree = 1; 00811 } 00812 } 00813 } 00814 else if(node_type == MIB_NODE_LR) 00815 { 00816 struct mib_list_rootnode *lrn; 00817 struct mib_list_node *ln; 00818 00819 /* list root node (internal 'RAM', variable length) */ 00820 lrn = (struct mib_list_rootnode *)node; 00821 if (ident_len > 0) 00822 { 00823 ln = lrn->head; 00824 /* iterate over list, head to tail */ 00825 while ((ln != NULL) && (ln->objid < *ident)) 00826 { 00827 ln = ln->next; 00828 } 00829 if (ln != NULL) 00830 { 00831 LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); 00832 oidret->id[oidret->len] = ln->objid; 00833 (oidret->len)++; 00834 if (ln->nptr == NULL) 00835 { 00836 /* leaf node */ 00837 if (ln->objid > *ident) 00838 { 00839 return (struct mib_node*)lrn; 00840 } 00841 else if (ln->next != NULL) 00842 { 00843 /* ln->objid == *ident */ 00844 (oidret->len)--; 00845 oidret->id[oidret->len] = ln->next->objid; 00846 (oidret->len)++; 00847 return (struct mib_node*)lrn; 00848 } 00849 else 00850 { 00851 /* ln->next == NULL */ 00852 (oidret->len)--; 00853 climb_tree = 1; 00854 } 00855 } 00856 else 00857 { 00858 struct mib_list_node *jn; 00859 struct nse cur_node; 00860 00861 /* non-leaf, store right child ptr and id */ 00862 jn = ln->next; 00863 while ((jn != NULL) && empty_table(jn->nptr)) 00864 { 00865 jn = jn->next; 00866 } 00867 if (jn != NULL) 00868 { 00869 cur_node.r_ptr = jn->nptr; 00870 cur_node.r_id = jn->objid; 00871 cur_node.r_nl = 0; 00872 } 00873 else 00874 { 00875 cur_node.r_ptr = NULL; 00876 } 00877 push_node(&cur_node); 00878 if (ln->objid == *ident) 00879 { 00880 ident_len--; 00881 ident++; 00882 } 00883 else 00884 { 00885 /* ln->objid < *ident */ 00886 ident_len = 0; 00887 } 00888 /* follow next child pointer */ 00889 node = ln->nptr; 00890 } 00891 00892 } 00893 else 00894 { 00895 /* ln == NULL */ 00896 climb_tree = 1; 00897 } 00898 } 00899 else 00900 { 00901 struct mib_list_node *jn; 00902 /* ident_len == 0, complete with leftmost '.thing' */ 00903 jn = lrn->head; 00904 while ((jn != NULL) && empty_table(jn->nptr)) 00905 { 00906 jn = jn->next; 00907 } 00908 if (jn != NULL) 00909 { 00910 LWIP_DEBUGF(SNMP_MIB_DEBUG,("left jn->objid==%"S32_F"\n",jn->objid)); 00911 oidret->id[oidret->len] = jn->objid; 00912 (oidret->len)++; 00913 if (jn->nptr == NULL) 00914 { 00915 /* leaf node */ 00916 LWIP_DEBUGF(SNMP_MIB_DEBUG,("jn->nptr == NULL\n")); 00917 return (struct mib_node*)lrn; 00918 } 00919 else 00920 { 00921 /* no leaf, continue */ 00922 node = jn->nptr; 00923 } 00924 } 00925 else 00926 { 00927 /* jn == NULL */ 00928 climb_tree = 1; 00929 } 00930 } 00931 } 00932 else if(node_type == MIB_NODE_EX) 00933 { 00934 struct mib_external_node *en; 00935 s32_t ex_id; 00936 00937 /* external node (addressing and access via functions) */ 00938 en = (struct mib_external_node *)node; 00939 if (ident_len > 0) 00940 { 00941 u16_t i, len; 00942 00943 i = 0; 00944 len = en->level_length(en->addr_inf,ext_level); 00945 while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) < 0)) 00946 { 00947 i++; 00948 } 00949 if (i < len) 00950 { 00951 /* add identifier to oidret */ 00952 en->get_objid(en->addr_inf,ext_level,i,&ex_id); 00953 LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,ex_id,*ident)); 00954 oidret->id[oidret->len] = ex_id; 00955 (oidret->len)++; 00956 00957 if ((ext_level + 1) == en->tree_levels) 00958 { 00959 LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); 00960 /* leaf node */ 00961 if (ex_id > *ident) 00962 { 00963 return (struct mib_node*)en; 00964 } 00965 else if ((i + 1) < len) 00966 { 00967 /* ex_id == *ident */ 00968 en->get_objid(en->addr_inf,ext_level,i + 1,&ex_id); 00969 (oidret->len)--; 00970 oidret->id[oidret->len] = ex_id; 00971 (oidret->len)++; 00972 return (struct mib_node*)en; 00973 } 00974 else 00975 { 00976 /* (i + 1) == len */ 00977 (oidret->len)--; 00978 climb_tree = 1; 00979 } 00980 } 00981 else 00982 { 00983 u8_t j; 00984 struct nse cur_node; 00985 00986 LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); 00987 /* non-leaf, store right child ptr and id */ 00988 LWIP_ASSERT("i < 0xff", i < 0xff); 00989 j = (u8_t)i + 1; 00990 if (j < len) 00991 { 00992 /* right node is the current external node */ 00993 cur_node.r_ptr = node; 00994 en->get_objid(en->addr_inf,ext_level,j,&cur_node.r_id); 00995 cur_node.r_nl = ext_level + 1; 00996 } 00997 else 00998 { 00999 cur_node.r_ptr = NULL; 01000 } 01001 push_node(&cur_node); 01002 if (en->ident_cmp(en->addr_inf,ext_level,i,*ident) == 0) 01003 { 01004 ident_len--; 01005 ident++; 01006 } 01007 else 01008 { 01009 /* external id < *ident */ 01010 ident_len = 0; 01011 } 01012 /* proceed to child */ 01013 ext_level++; 01014 } 01015 } 01016 else 01017 { 01018 /* i == len (en->level_len()) */ 01019 climb_tree = 1; 01020 } 01021 } 01022 else 01023 { 01024 /* ident_len == 0, complete with leftmost '.thing' */ 01025 en->get_objid(en->addr_inf,ext_level,0,&ex_id); 01026 LWIP_DEBUGF(SNMP_MIB_DEBUG,("left en->objid==%"S32_F"\n",ex_id)); 01027 oidret->id[oidret->len] = ex_id; 01028 (oidret->len)++; 01029 if ((ext_level + 1) == en->tree_levels) 01030 { 01031 /* leaf node */ 01032 LWIP_DEBUGF(SNMP_MIB_DEBUG,("(ext_level + 1) == en->tree_levels\n")); 01033 return (struct mib_node*)en; 01034 } 01035 else 01036 { 01037 /* no leaf, proceed to child */ 01038 ext_level++; 01039 } 01040 } 01041 } 01042 else if(node_type == MIB_NODE_SC) 01043 { 01044 mib_scalar_node *sn; 01045 01046 /* scalar node */ 01047 sn = (mib_scalar_node *)node; 01048 if (ident_len > 0) 01049 { 01050 /* at .0 */ 01051 climb_tree = 1; 01052 } 01053 else 01054 { 01055 /* ident_len == 0, complete object identifier */ 01056 oidret->id[oidret->len] = 0; 01057 (oidret->len)++; 01058 /* leaf node */ 01059 LWIP_DEBUGF(SNMP_MIB_DEBUG,("completed scalar leaf\n")); 01060 return (struct mib_node*)sn; 01061 } 01062 } 01063 else 01064 { 01065 /* unknown/unhandled node_type */ 01066 LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node_type %"U16_F" unkown\n",(u16_t)node_type)); 01067 return NULL; 01068 } 01069 01070 if (climb_tree) 01071 { 01072 struct nse child; 01073 01074 /* find right child ptr */ 01075 child.r_ptr = NULL; 01076 child.r_id = 0; 01077 child.r_nl = 0; 01078 while ((node_stack_cnt > 0) && (child.r_ptr == NULL)) 01079 { 01080 pop_node(&child); 01081 /* trim returned oid */ 01082 (oidret->len)--; 01083 } 01084 if (child.r_ptr != NULL) 01085 { 01086 /* incoming ident is useless beyond this point */ 01087 ident_len = 0; 01088 oidret->id[oidret->len] = child.r_id; 01089 oidret->len++; 01090 node = child.r_ptr; 01091 ext_level = child.r_nl; 01092 } 01093 else 01094 { 01095 /* tree ends here ... */ 01096 LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed, tree ends here\n")); 01097 return NULL; 01098 } 01099 } 01100 } 01101 /* done, found nothing */ 01102 LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node==%p\n",(void*)node)); 01103 return NULL; 01104 } 01105 01106 /** 01107 * Test object identifier for the iso.org.dod.internet prefix. 01108 * 01109 * @param ident_len the length of the supplied object identifier 01110 * @param ident points to the array of sub identifiers 01111 * @return 1 if it matches, 0 otherwise 01112 */ 01113 u8_t 01114 snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident) 01115 { 01116 if ((ident_len > 3) && 01117 (ident[0] == 1) && (ident[1] == 3) && 01118 (ident[2] == 6) && (ident[3] == 1)) 01119 { 01120 return 1; 01121 } 01122 else 01123 { 01124 return 0; 01125 } 01126 } 01127 01128 /** 01129 * Expands object identifier to the iso.org.dod.internet 01130 * prefix for use in getnext operation. 01131 * 01132 * @param ident_len the length of the supplied object identifier 01133 * @param ident points to the array of sub identifiers 01134 * @param oidret points to returned expanded object identifier 01135 * @return 1 if it matches, 0 otherwise 01136 * 01137 * @note ident_len 0 is allowed, expanding to the first known object id!! 01138 */ 01139 u8_t 01140 snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) 01141 { 01142 const s32_t *prefix_ptr; 01143 s32_t *ret_ptr; 01144 u8_t i; 01145 01146 i = 0; 01147 prefix_ptr = &prefix[0]; 01148 ret_ptr = &oidret->id[0]; 01149 ident_len = ((ident_len < 4)?ident_len:4); 01150 while ((i < ident_len) && ((*ident) <= (*prefix_ptr))) 01151 { 01152 *ret_ptr++ = *prefix_ptr++; 01153 ident++; 01154 i++; 01155 } 01156 if (i == ident_len) 01157 { 01158 /* match, complete missing bits */ 01159 while (i < 4) 01160 { 01161 *ret_ptr++ = *prefix_ptr++; 01162 i++; 01163 } 01164 oidret->len = i; 01165 return 1; 01166 } 01167 else 01168 { 01169 /* i != ident_len */ 01170 return 0; 01171 } 01172 } 01173 01174 #endif /* LWIP_SNMP */
Generated on Tue Jul 12 2022 11:52:57 by 1.7.2