uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mib_structs.c
Go to the documentation of this file.
1 
6 /*
7  * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without modification,
11  * are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  * this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  * derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30  * OF SUCH DAMAGE.
31  *
32  * Author: Christiaan Simons <christiaan.simons@axon.tv>
33  */
34 
35 #include "lwip/opt.h"
36 
37 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
38 
39 #include "lwip/snmp_structs.h"
40 #include "lwip/memp.h"
41 #include "lwip/netif.h"
42 
44 const s32_t prefix[4] = {1, 3, 6, 1};
45 
46 #define NODE_STACK_SIZE (LWIP_SNMP_OBJ_ID_LEN)
47 
48 struct nse
49 {
51  struct mib_node* r_ptr;
53  s32_t r_id;
55  u8_t r_nl;
56 };
57 static u8_t node_stack_cnt;
58 static struct nse node_stack[NODE_STACK_SIZE];
59 
63 static void
64 push_node(struct nse* node)
65 {
66  LWIP_ASSERT("node_stack_cnt < NODE_STACK_SIZE",node_stack_cnt < NODE_STACK_SIZE);
67  LWIP_DEBUGF(SNMP_MIB_DEBUG,("push_node() node=%p id=%"S32_F"\n",(void*)(node->r_ptr),node->r_id));
68  if (node_stack_cnt < NODE_STACK_SIZE)
69  {
70  node_stack[node_stack_cnt] = *node;
71  node_stack_cnt++;
72  }
73 }
74 
78 static void
79 pop_node(struct nse* node)
80 {
81  if (node_stack_cnt > 0)
82  {
83  node_stack_cnt--;
84  *node = node_stack[node_stack_cnt];
85  }
86  LWIP_DEBUGF(SNMP_MIB_DEBUG,("pop_node() node=%p id=%"S32_F"\n",(void *)(node->r_ptr),node->r_id));
87 }
88 
94 void
95 snmp_ifindextonetif(s32_t ifindex, struct netif **netif)
96 {
97  struct netif *nif = netif_list;
98  s32_t i, ifidx;
99 
100  ifidx = ifindex - 1;
101  i = 0;
102  while ((nif != NULL) && (i < ifidx))
103  {
104  nif = nif->next;
105  i++;
106  }
107  *netif = nif;
108 }
109 
115 void
116 snmp_netiftoifindex(struct netif *netif, s32_t *ifidx)
117 {
118  struct netif *nif = netif_list;
119  u16_t i;
120 
121  i = 0;
122  while ((nif != NULL) && (nif != netif))
123  {
124  nif = nif->next;
125  i++;
126  }
127  *ifidx = i+1;
128 }
129 
135 void
136 snmp_oidtoip(s32_t *ident, ip_addr_t *ip)
137 {
138  IP4_ADDR(ip, ident[0], ident[1], ident[2], ident[3]);
139 }
140 
146 void
147 snmp_iptooid(ip_addr_t *ip, s32_t *ident)
148 {
149  ident[0] = ip4_addr1(ip);
150  ident[1] = ip4_addr2(ip);
151  ident[2] = ip4_addr3(ip);
152  ident[3] = ip4_addr4(ip);
153 }
154 
155 struct mib_list_node *
156 snmp_mib_ln_alloc(s32_t id)
157 {
158  struct mib_list_node *ln;
159 
160  ln = (struct mib_list_node *)memp_malloc(MEMP_SNMP_NODE);
161  if (ln != NULL)
162  {
163  ln->prev = NULL;
164  ln->next = NULL;
165  ln->objid = id;
166  ln->nptr = NULL;
167  }
168  return ln;
169 }
170 
171 void
172 snmp_mib_ln_free(struct mib_list_node *ln)
173 {
174  memp_free(MEMP_SNMP_NODE, ln);
175 }
176 
177 struct mib_list_rootnode *
178 snmp_mib_lrn_alloc(void)
179 {
180  struct mib_list_rootnode *lrn;
181 
182  lrn = (struct mib_list_rootnode*)memp_malloc(MEMP_SNMP_ROOTNODE);
183  if (lrn != NULL)
184  {
185  lrn->get_object_def = noleafs_get_object_def;
186  lrn->get_value = noleafs_get_value;
187  lrn->set_test = noleafs_set_test;
188  lrn->set_value = noleafs_set_value;
189  lrn->node_type = MIB_NODE_LR;
190  lrn->maxlength = 0;
191  lrn->head = NULL;
192  lrn->tail = NULL;
193  lrn->count = 0;
194  }
195  return lrn;
196 }
197 
198 void
199 snmp_mib_lrn_free(struct mib_list_rootnode *lrn)
200 {
201  memp_free(MEMP_SNMP_ROOTNODE, lrn);
202 }
203 
215 s8_t
216 snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn)
217 {
218  struct mib_list_node *nn;
219  s8_t insert;
220 
221  LWIP_ASSERT("rn != NULL",rn != NULL);
222 
223  /* -1 = malloc failure, 0 = not inserted, 1 = inserted, 2 = was present */
224  insert = 0;
225  if (rn->head == NULL)
226  {
227  /* empty list, add first node */
228  LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc empty list objid==%"S32_F"\n",objid));
229  nn = snmp_mib_ln_alloc(objid);
230  if (nn != NULL)
231  {
232  rn->head = nn;
233  rn->tail = nn;
234  *insn = nn;
235  insert = 1;
236  }
237  else
238  {
239  insert = -1;
240  }
241  }
242  else
243  {
244  struct mib_list_node *n;
245  /* at least one node is present */
246  n = rn->head;
247  while ((n != NULL) && (insert == 0))
248  {
249  if (n->objid == objid)
250  {
251  /* node is already there */
252  LWIP_DEBUGF(SNMP_MIB_DEBUG,("node already there objid==%"S32_F"\n",objid));
253  *insn = n;
254  insert = 2;
255  }
256  else if (n->objid < objid)
257  {
258  if (n->next == NULL)
259  {
260  /* alloc and insert at the tail */
261  LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins tail objid==%"S32_F"\n",objid));
262  nn = snmp_mib_ln_alloc(objid);
263  if (nn != NULL)
264  {
265  nn->next = NULL;
266  nn->prev = n;
267  n->next = nn;
268  rn->tail = nn;
269  *insn = nn;
270  insert = 1;
271  }
272  else
273  {
274  /* insertion failure */
275  insert = -1;
276  }
277  }
278  else
279  {
280  /* there's more to explore: traverse list */
281  LWIP_DEBUGF(SNMP_MIB_DEBUG,("traverse list\n"));
282  n = n->next;
283  }
284  }
285  else
286  {
287  /* n->objid > objid */
288  /* alloc and insert between n->prev and n */
289  LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins n->prev, objid==%"S32_F", n\n",objid));
290  nn = snmp_mib_ln_alloc(objid);
291  if (nn != NULL)
292  {
293  if (n->prev == NULL)
294  {
295  /* insert at the head */
296  nn->next = n;
297  nn->prev = NULL;
298  rn->head = nn;
299  n->prev = nn;
300  }
301  else
302  {
303  /* insert in the middle */
304  nn->next = n;
305  nn->prev = n->prev;
306  n->prev->next = nn;
307  n->prev = nn;
308  }
309  *insn = nn;
310  insert = 1;
311  }
312  else
313  {
314  /* insertion failure */
315  insert = -1;
316  }
317  }
318  }
319  }
320  if (insert == 1)
321  {
322  rn->count += 1;
323  }
324  LWIP_ASSERT("insert != 0",insert != 0);
325  return insert;
326 }
327 
337 s8_t
338 snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn)
339 {
340  s8_t fc;
341  struct mib_list_node *n;
342 
343  LWIP_ASSERT("rn != NULL",rn != NULL);
344  n = rn->head;
345  while ((n != NULL) && (n->objid != objid))
346  {
347  n = n->next;
348  }
349  if (n == NULL)
350  {
351  fc = 0;
352  }
353  else if (n->nptr == NULL)
354  {
355  /* leaf, can delete node */
356  fc = 1;
357  }
358  else
359  {
360  struct mib_list_rootnode *r;
361 
362  if (n->nptr->node_type == MIB_NODE_LR)
363  {
364  r = (struct mib_list_rootnode *)n->nptr;
365  if (r->count > 1)
366  {
367  /* can't delete node */
368  fc = 2;
369  }
370  else
371  {
372  /* count <= 1, can delete node */
373  fc = 1;
374  }
375  }
376  else
377  {
378  /* other node type */
379  fc = 3;
380  }
381  }
382  *fn = n;
383  return fc;
384 }
385 
394 struct mib_list_rootnode *
395 snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n)
396 {
397  struct mib_list_rootnode *next;
398 
399  LWIP_ASSERT("rn != NULL",rn != NULL);
400  LWIP_ASSERT("n != NULL",n != NULL);
401 
402  /* caller must remove this sub-tree */
403  next = (struct mib_list_rootnode*)(n->nptr);
404  rn->count -= 1;
405 
406  if (n == rn->head)
407  {
408  rn->head = n->next;
409  if (n->next != NULL)
410  {
411  /* not last node, new list begin */
412  n->next->prev = NULL;
413  }
414  }
415  else if (n == rn->tail)
416  {
417  rn->tail = n->prev;
418  if (n->prev != NULL)
419  {
420  /* not last node, new list end */
421  n->prev->next = NULL;
422  }
423  }
424  else
425  {
426  /* node must be in the middle */
427  n->prev->next = n->next;
428  n->next->prev = n->prev;
429  }
430  LWIP_DEBUGF(SNMP_MIB_DEBUG,("free list objid==%"S32_F"\n",n->objid));
431  snmp_mib_ln_free(n);
432  if (rn->count == 0)
433  {
434  rn->head = NULL;
435  rn->tail = NULL;
436  }
437  return next;
438 }
439 
440 
441 
451 struct mib_node *
452 snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np)
453 {
454  u8_t node_type, ext_level;
455 
456  ext_level = 0;
457  LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident));
458  while (node != NULL)
459  {
460  node_type = node->node_type;
461  if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA))
462  {
463  struct mib_array_node *an;
464  u16_t i;
465 
466  if (ident_len > 0)
467  {
468  /* array node (internal ROM or RAM, fixed length) */
469  an = (struct mib_array_node *)node;
470  i = 0;
471  while ((i < an->maxlength) && (an->objid[i] != *ident))
472  {
473  i++;
474  }
475  if (i < an->maxlength)
476  {
477  /* found it, if available proceed to child, otherwise inspect leaf */
478  LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident));
479  if (an->nptr[i] == NULL)
480  {
481  /* a scalar leaf OR table,
482  inspect remaining instance number / table index */
483  np->ident_len = ident_len;
484  np->ident = ident;
485  return (struct mib_node*)an;
486  }
487  else
488  {
489  /* follow next child pointer */
490  ident++;
491  ident_len--;
492  node = an->nptr[i];
493  }
494  }
495  else
496  {
497  /* search failed, identifier mismatch (nosuchname) */
498  LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident));
499  return NULL;
500  }
501  }
502  else
503  {
504  /* search failed, short object identifier (nosuchname) */
505  LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n"));
506  return NULL;
507  }
508  }
509  else if(node_type == MIB_NODE_LR)
510  {
511  struct mib_list_rootnode *lrn;
512  struct mib_list_node *ln;
513 
514  if (ident_len > 0)
515  {
516  /* list root node (internal 'RAM', variable length) */
517  lrn = (struct mib_list_rootnode *)node;
518  ln = lrn->head;
519  /* iterate over list, head to tail */
520  while ((ln != NULL) && (ln->objid != *ident))
521  {
522  ln = ln->next;
523  }
524  if (ln != NULL)
525  {
526  /* found it, proceed to child */;
527  LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident));
528  if (ln->nptr == NULL)
529  {
530  np->ident_len = ident_len;
531  np->ident = ident;
532  return (struct mib_node*)lrn;
533  }
534  else
535  {
536  /* follow next child pointer */
537  ident_len--;
538  ident++;
539  node = ln->nptr;
540  }
541  }
542  else
543  {
544  /* search failed */
545  LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident));
546  return NULL;
547  }
548  }
549  else
550  {
551  /* search failed, short object identifier (nosuchname) */
552  LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n"));
553  return NULL;
554  }
555  }
556  else if(node_type == MIB_NODE_EX)
557  {
558  struct mib_external_node *en;
559  u16_t i, len;
560 
561  if (ident_len > 0)
562  {
563  /* external node (addressing and access via functions) */
564  en = (struct mib_external_node *)node;
565 
566  i = 0;
567  len = en->level_length(en->addr_inf,ext_level);
568  while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0))
569  {
570  i++;
571  }
572  if (i < len)
573  {
574  s32_t debug_id;
575 
576  en->get_objid(en->addr_inf,ext_level,i,&debug_id);
577  LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident));
578  if ((ext_level + 1) == en->tree_levels)
579  {
580  np->ident_len = ident_len;
581  np->ident = ident;
582  return (struct mib_node*)en;
583  }
584  else
585  {
586  /* found it, proceed to child */
587  ident_len--;
588  ident++;
589  ext_level++;
590  }
591  }
592  else
593  {
594  /* search failed */
595  LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed *ident==%"S32_F"\n",*ident));
596  return NULL;
597  }
598  }
599  else
600  {
601  /* search failed, short object identifier (nosuchname) */
602  LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed, short object identifier\n"));
603  return NULL;
604  }
605  }
606  else if (node_type == MIB_NODE_SC)
607  {
608  mib_scalar_node *sn;
609 
610  sn = (mib_scalar_node *)node;
611  if ((ident_len == 1) && (*ident == 0))
612  {
613  np->ident_len = ident_len;
614  np->ident = ident;
615  return (struct mib_node*)sn;
616  }
617  else
618  {
619  /* search failed, short object identifier (nosuchname) */
620  LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, invalid object identifier length\n"));
621  return NULL;
622  }
623  }
624  else
625  {
626  /* unknown node_type */
627  LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node_type %"U16_F" unkown\n",(u16_t)node_type));
628  return NULL;
629  }
630  }
631  /* done, found nothing */
632  LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node==%p\n",(void*)node));
633  return NULL;
634 }
635 
639 static u8_t
640 empty_table(struct mib_node *node)
641 {
642  u8_t node_type;
643  u8_t empty = 0;
644 
645  if (node != NULL)
646  {
647  node_type = node->node_type;
648  if (node_type == MIB_NODE_LR)
649  {
650  struct mib_list_rootnode *lrn;
651  lrn = (struct mib_list_rootnode *)node;
652  if ((lrn->count == 0) || (lrn->head == NULL))
653  {
654  empty = 1;
655  }
656  }
657  else if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA))
658  {
659  struct mib_array_node *an;
660  an = (struct mib_array_node *)node;
661  if ((an->maxlength == 0) || (an->nptr == NULL))
662  {
663  empty = 1;
664  }
665  }
666  else if (node_type == MIB_NODE_EX)
667  {
668  struct mib_external_node *en;
669  en = (struct mib_external_node *)node;
670  if (en->tree_levels == 0)
671  {
672  empty = 1;
673  }
674  }
675  }
676  return empty;
677 }
678 
682 struct mib_node *
683 snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret)
684 {
685  u8_t node_type, ext_level, climb_tree;
686 
687  ext_level = 0;
688  /* reset node stack */
689  node_stack_cnt = 0;
690  while (node != NULL)
691  {
692  climb_tree = 0;
693  node_type = node->node_type;
694  if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA))
695  {
696  struct mib_array_node *an;
697  u16_t i;
698 
699  /* array node (internal ROM or RAM, fixed length) */
700  an = (struct mib_array_node *)node;
701  if (ident_len > 0)
702  {
703  i = 0;
704  while ((i < an->maxlength) && (an->objid[i] < *ident))
705  {
706  i++;
707  }
708  if (i < an->maxlength)
709  {
710  LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident));
711  /* add identifier to oidret */
712  oidret->id[oidret->len] = an->objid[i];
713  (oidret->len)++;
714 
715  if (an->nptr[i] == NULL)
716  {
717  LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n"));
718  /* leaf node (e.g. in a fixed size table) */
719  if (an->objid[i] > *ident)
720  {
721  return (struct mib_node*)an;
722  }
723  else if ((i + 1) < an->maxlength)
724  {
725  /* an->objid[i] == *ident */
726  (oidret->len)--;
727  oidret->id[oidret->len] = an->objid[i + 1];
728  (oidret->len)++;
729  return (struct mib_node*)an;
730  }
731  else
732  {
733  /* (i + 1) == an->maxlength */
734  (oidret->len)--;
735  climb_tree = 1;
736  }
737  }
738  else
739  {
740  u8_t j;
741  struct nse cur_node;
742 
743  LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n"));
744  /* non-leaf, store right child ptr and id */
745  LWIP_ASSERT("i < 0xff", i < 0xff);
746  j = (u8_t)i + 1;
747  while ((j < an->maxlength) && (empty_table(an->nptr[j])))
748  {
749  j++;
750  }
751  if (j < an->maxlength)
752  {
753  cur_node.r_ptr = an->nptr[j];
754  cur_node.r_id = an->objid[j];
755  cur_node.r_nl = 0;
756  }
757  else
758  {
759  cur_node.r_ptr = NULL;
760  }
761  push_node(&cur_node);
762  if (an->objid[i] == *ident)
763  {
764  ident_len--;
765  ident++;
766  }
767  else
768  {
769  /* an->objid[i] < *ident */
770  ident_len = 0;
771  }
772  /* follow next child pointer */
773  node = an->nptr[i];
774  }
775  }
776  else
777  {
778  /* i == an->maxlength */
779  climb_tree = 1;
780  }
781  }
782  else
783  {
784  u8_t j;
785  /* ident_len == 0, complete with leftmost '.thing' */
786  j = 0;
787  while ((j < an->maxlength) && empty_table(an->nptr[j]))
788  {
789  j++;
790  }
791  if (j < an->maxlength)
792  {
793  LWIP_DEBUGF(SNMP_MIB_DEBUG,("left an->objid[j]==%"S32_F"\n",an->objid[j]));
794  oidret->id[oidret->len] = an->objid[j];
795  (oidret->len)++;
796  if (an->nptr[j] == NULL)
797  {
798  /* leaf node */
799  return (struct mib_node*)an;
800  }
801  else
802  {
803  /* no leaf, continue */
804  node = an->nptr[j];
805  }
806  }
807  else
808  {
809  /* j == an->maxlength */
810  climb_tree = 1;
811  }
812  }
813  }
814  else if(node_type == MIB_NODE_LR)
815  {
816  struct mib_list_rootnode *lrn;
817  struct mib_list_node *ln;
818 
819  /* list root node (internal 'RAM', variable length) */
820  lrn = (struct mib_list_rootnode *)node;
821  if (ident_len > 0)
822  {
823  ln = lrn->head;
824  /* iterate over list, head to tail */
825  while ((ln != NULL) && (ln->objid < *ident))
826  {
827  ln = ln->next;
828  }
829  if (ln != NULL)
830  {
831  LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident));
832  oidret->id[oidret->len] = ln->objid;
833  (oidret->len)++;
834  if (ln->nptr == NULL)
835  {
836  /* leaf node */
837  if (ln->objid > *ident)
838  {
839  return (struct mib_node*)lrn;
840  }
841  else if (ln->next != NULL)
842  {
843  /* ln->objid == *ident */
844  (oidret->len)--;
845  oidret->id[oidret->len] = ln->next->objid;
846  (oidret->len)++;
847  return (struct mib_node*)lrn;
848  }
849  else
850  {
851  /* ln->next == NULL */
852  (oidret->len)--;
853  climb_tree = 1;
854  }
855  }
856  else
857  {
858  struct mib_list_node *jn;
859  struct nse cur_node;
860 
861  /* non-leaf, store right child ptr and id */
862  jn = ln->next;
863  while ((jn != NULL) && empty_table(jn->nptr))
864  {
865  jn = jn->next;
866  }
867  if (jn != NULL)
868  {
869  cur_node.r_ptr = jn->nptr;
870  cur_node.r_id = jn->objid;
871  cur_node.r_nl = 0;
872  }
873  else
874  {
875  cur_node.r_ptr = NULL;
876  }
877  push_node(&cur_node);
878  if (ln->objid == *ident)
879  {
880  ident_len--;
881  ident++;
882  }
883  else
884  {
885  /* ln->objid < *ident */
886  ident_len = 0;
887  }
888  /* follow next child pointer */
889  node = ln->nptr;
890  }
891 
892  }
893  else
894  {
895  /* ln == NULL */
896  climb_tree = 1;
897  }
898  }
899  else
900  {
901  struct mib_list_node *jn;
902  /* ident_len == 0, complete with leftmost '.thing' */
903  jn = lrn->head;
904  while ((jn != NULL) && empty_table(jn->nptr))
905  {
906  jn = jn->next;
907  }
908  if (jn != NULL)
909  {
910  LWIP_DEBUGF(SNMP_MIB_DEBUG,("left jn->objid==%"S32_F"\n",jn->objid));
911  oidret->id[oidret->len] = jn->objid;
912  (oidret->len)++;
913  if (jn->nptr == NULL)
914  {
915  /* leaf node */
916  LWIP_DEBUGF(SNMP_MIB_DEBUG,("jn->nptr == NULL\n"));
917  return (struct mib_node*)lrn;
918  }
919  else
920  {
921  /* no leaf, continue */
922  node = jn->nptr;
923  }
924  }
925  else
926  {
927  /* jn == NULL */
928  climb_tree = 1;
929  }
930  }
931  }
932  else if(node_type == MIB_NODE_EX)
933  {
934  struct mib_external_node *en;
935  s32_t ex_id;
936 
937  /* external node (addressing and access via functions) */
938  en = (struct mib_external_node *)node;
939  if (ident_len > 0)
940  {
941  u16_t i, len;
942 
943  i = 0;
944  len = en->level_length(en->addr_inf,ext_level);
945  while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) < 0))
946  {
947  i++;
948  }
949  if (i < len)
950  {
951  /* add identifier to oidret */
952  en->get_objid(en->addr_inf,ext_level,i,&ex_id);
953  LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,ex_id,*ident));
954  oidret->id[oidret->len] = ex_id;
955  (oidret->len)++;
956 
957  if ((ext_level + 1) == en->tree_levels)
958  {
959  LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n"));
960  /* leaf node */
961  if (ex_id > *ident)
962  {
963  return (struct mib_node*)en;
964  }
965  else if ((i + 1) < len)
966  {
967  /* ex_id == *ident */
968  en->get_objid(en->addr_inf,ext_level,i + 1,&ex_id);
969  (oidret->len)--;
970  oidret->id[oidret->len] = ex_id;
971  (oidret->len)++;
972  return (struct mib_node*)en;
973  }
974  else
975  {
976  /* (i + 1) == len */
977  (oidret->len)--;
978  climb_tree = 1;
979  }
980  }
981  else
982  {
983  u8_t j;
984  struct nse cur_node;
985 
986  LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n"));
987  /* non-leaf, store right child ptr and id */
988  LWIP_ASSERT("i < 0xff", i < 0xff);
989  j = (u8_t)i + 1;
990  if (j < len)
991  {
992  /* right node is the current external node */
993  cur_node.r_ptr = node;
994  en->get_objid(en->addr_inf,ext_level,j,&cur_node.r_id);
995  cur_node.r_nl = ext_level + 1;
996  }
997  else
998  {
999  cur_node.r_ptr = NULL;
1000  }
1001  push_node(&cur_node);
1002  if (en->ident_cmp(en->addr_inf,ext_level,i,*ident) == 0)
1003  {
1004  ident_len--;
1005  ident++;
1006  }
1007  else
1008  {
1009  /* external id < *ident */
1010  ident_len = 0;
1011  }
1012  /* proceed to child */
1013  ext_level++;
1014  }
1015  }
1016  else
1017  {
1018  /* i == len (en->level_len()) */
1019  climb_tree = 1;
1020  }
1021  }
1022  else
1023  {
1024  /* ident_len == 0, complete with leftmost '.thing' */
1025  en->get_objid(en->addr_inf,ext_level,0,&ex_id);
1026  LWIP_DEBUGF(SNMP_MIB_DEBUG,("left en->objid==%"S32_F"\n",ex_id));
1027  oidret->id[oidret->len] = ex_id;
1028  (oidret->len)++;
1029  if ((ext_level + 1) == en->tree_levels)
1030  {
1031  /* leaf node */
1032  LWIP_DEBUGF(SNMP_MIB_DEBUG,("(ext_level + 1) == en->tree_levels\n"));
1033  return (struct mib_node*)en;
1034  }
1035  else
1036  {
1037  /* no leaf, proceed to child */
1038  ext_level++;
1039  }
1040  }
1041  }
1042  else if(node_type == MIB_NODE_SC)
1043  {
1044  mib_scalar_node *sn;
1045 
1046  /* scalar node */
1047  sn = (mib_scalar_node *)node;
1048  if (ident_len > 0)
1049  {
1050  /* at .0 */
1051  climb_tree = 1;
1052  }
1053  else
1054  {
1055  /* ident_len == 0, complete object identifier */
1056  oidret->id[oidret->len] = 0;
1057  (oidret->len)++;
1058  /* leaf node */
1059  LWIP_DEBUGF(SNMP_MIB_DEBUG,("completed scalar leaf\n"));
1060  return (struct mib_node*)sn;
1061  }
1062  }
1063  else
1064  {
1065  /* unknown/unhandled node_type */
1066  LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node_type %"U16_F" unkown\n",(u16_t)node_type));
1067  return NULL;
1068  }
1069 
1070  if (climb_tree)
1071  {
1072  struct nse child;
1073 
1074  /* find right child ptr */
1075  child.r_ptr = NULL;
1076  child.r_id = 0;
1077  child.r_nl = 0;
1078  while ((node_stack_cnt > 0) && (child.r_ptr == NULL))
1079  {
1080  pop_node(&child);
1081  /* trim returned oid */
1082  (oidret->len)--;
1083  }
1084  if (child.r_ptr != NULL)
1085  {
1086  /* incoming ident is useless beyond this point */
1087  ident_len = 0;
1088  oidret->id[oidret->len] = child.r_id;
1089  oidret->len++;
1090  node = child.r_ptr;
1091  ext_level = child.r_nl;
1092  }
1093  else
1094  {
1095  /* tree ends here ... */
1096  LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed, tree ends here\n"));
1097  return NULL;
1098  }
1099  }
1100  }
1101  /* done, found nothing */
1102  LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node==%p\n",(void*)node));
1103  return NULL;
1104 }
1105 
1113 u8_t
1114 snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident)
1115 {
1116  if ((ident_len > 3) &&
1117  (ident[0] == 1) && (ident[1] == 3) &&
1118  (ident[2] == 6) && (ident[3] == 1))
1119  {
1120  return 1;
1121  }
1122  else
1123  {
1124  return 0;
1125  }
1126 }
1127 
1139 u8_t
1140 snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret)
1141 {
1142  const s32_t *prefix_ptr;
1143  s32_t *ret_ptr;
1144  u8_t i;
1145 
1146  i = 0;
1147  prefix_ptr = &prefix[0];
1148  ret_ptr = &oidret->id[0];
1149  ident_len = ((ident_len < 4)?ident_len:4);
1150  while ((i < ident_len) && ((*ident) <= (*prefix_ptr)))
1151  {
1152  *ret_ptr++ = *prefix_ptr++;
1153  ident++;
1154  i++;
1155  }
1156  if (i == ident_len)
1157  {
1158  /* match, complete missing bits */
1159  while (i < 4)
1160  {
1161  *ret_ptr++ = *prefix_ptr++;
1162  i++;
1163  }
1164  oidret->len = i;
1165  return 1;
1166  }
1167  else
1168  {
1169  /* i != ident_len */
1170  return 0;
1171  }
1172 }
1173 
1174 #endif /* LWIP_SNMP */