Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.
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 (rerurn) 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 21:10:25 by 1.7.2