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.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mib_structs.c Source File

mib_structs.c

Go to the documentation of this file.
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 */