]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/snmplib/parse.c
1 /***********************************************************
2 Copyright 1989 by Carnegie Mellon University
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of CMU not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
14 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 ******************************************************************/
28 #include "cache_snmp.h"
30 #include "snmp_debug.h"
32 #include "snmp_vars.h"
42 #include <sys/types.h>
48 #include <gnumalloc.h>
65 #include <sys/socket.h>
68 #include <netinet/in.h>
71 #include <arpa/inet.h>
87 * This is one element of an object identifier with either an integer subidentifier,
88 * or a textual string label, or both.
89 * The subid is -1 if not present, and label is NULL if not present.
97 * A linked list of nodes.
101 char label
[64]; /* This node's (unique) textual name */
102 u_int subid
; /* This node's integer subidentifier */
103 char parent
[64]; /* The parent's textual name */
104 int type
; /* The type of object this represents */
105 struct enum_list
*enums
; /* (optional) list of enumerated integers (otherwise NULL) */
110 /* types of tokens */
126 #define SNMP_OPAQUE 12
129 #define OF 15 /* SEQUENCE OF */
137 #define SNMP_STATUS 22
139 #define SNMP_OPTIONAL 24
141 #define RECOMMENDED 26
145 #define LEFTBRACKET 30
146 #define RIGHTBRACKET 31
148 #define RIGHTPAREN 33
150 /* For SNMPv2 SMI pseudo-compliance */
151 #define DESCRIPTION 35
156 const char *name
; /* token name */
157 int len
; /* length not counting nul */
158 int token
; /* value */
159 int hash
; /* hash of name */
160 struct tok
*next
; /* pointer to next in hash table */
163 struct tok tokens
[] = {
164 {"obsolete", sizeof("obsolete") - 1, OBSOLETE
},
165 {"Opaque", sizeof("Opaque") - 1, SNMP_OPAQUE
},
166 {"recommended", sizeof("recommended") - 1, RECOMMENDED
},
167 {"optional", sizeof("optional") - 1, SNMP_OPTIONAL
},
168 {"mandatory", sizeof("mandatory") - 1, MANDATORY
},
169 {"current", sizeof("current") - 1, MANDATORY
},
170 {"not-accessible", sizeof("not-accessible") - 1, NOACCESS
},
171 {"write-only", sizeof("write-only") - 1, WRITEONLY
},
172 {"read-write", sizeof("read-write") - 1, READWRITE
},
173 {"TimeTicks", sizeof("TimeTicks") - 1, TIMETICKS
},
174 {"OBJECTIDENTIFIER", sizeof("OBJECTIDENTIFIER") - 1, OBJID
},
176 * This CONTINUE appends the next word onto OBJECT,
177 * hopefully matching OBJECTIDENTIFIER above.
179 {"OBJECT", sizeof("OBJECT") - 1, CONTINUE
},
180 {"NetworkAddress", sizeof("NetworkAddress") - 1, NETADDR
},
181 {"Gauge", sizeof("Gauge") - 1, GAUGE
},
182 {"OCTETSTRING", sizeof("OCTETSTRING") - 1, OCTETSTR
},
183 {"OCTET", sizeof("OCTET") - 1, -1},
184 {"OF", sizeof("OF") - 1, OF
},
185 {"SEQUENCE", sizeof("SEQUENCE") - 1, SEQUENCE
},
186 {"NULL", sizeof("NULL") - 1, NUL
},
187 {"IpAddress", sizeof("IpAddress") - 1, IPADDR
},
188 {"INTEGER", sizeof("INTEGER") - 1, INTEGER
},
189 {"Counter", sizeof("Counter") - 1, COUNTER
},
190 {"read-only", sizeof("read-only") - 1, READONLY
},
191 {"ACCESS", sizeof("ACCESS") - 1, ACCESS
},
192 {"MAX-ACCESS", sizeof("MAX-ACCESS") - 1, ACCESS
},
193 {"STATUS", sizeof("STATUS") - 1, SNMP_STATUS
},
194 {"SYNTAX", sizeof("SYNTAX") - 1, SYNTAX
},
195 {"OBJECT-TYPE", sizeof("OBJECT-TYPE") - 1, OBJTYPE
},
196 {"{", sizeof("{") - 1, LEFTBRACKET
},
197 {"}", sizeof("}") - 1, RIGHTBRACKET
},
198 {"::=", sizeof("::=") - 1, EQUALS
},
199 {"(", sizeof("(") - 1, LEFTPAREN
},
200 {")", sizeof(")") - 1, RIGHTPAREN
},
201 {",", sizeof(",") - 1, COMMA
},
202 {"DESCRIPTION", sizeof("DESCRIPTION") - 1, DESCRIPTION
},
203 {"INDEX", sizeof("INDEX") - 1, INDEX
},
204 {"\"", sizeof("\"") - 1, QUOTE
},
205 {"END", sizeof("END") - 1, ENDOFFILE
},
206 /* Hacks for easier MIBFILE coercing */
207 {"read-create", sizeof("read-create") - 1, READWRITE
},
212 #define BUCKET(x) (x & 0x01F)
214 static struct tok
*buckets
[HASHSIZE
];
219 register struct tok
*tp
;
220 register const char *cp
;
224 memset((char *) buckets
, '\0', sizeof(buckets
));
225 for (tp
= tokens
; tp
->name
; tp
++) {
226 for (h
= 0, cp
= tp
->name
; *cp
; cp
++)
231 tp
->next
= buckets
[b
]; /* BUG ??? */
236 #define NHASHSIZE 128
237 #define NBUCKET(x) (x & 0x7F)
238 struct node
*nbuckets
[NHASHSIZE
];
241 init_node_hash(struct node
*nodes
)
243 register struct node
*np
, *nextp
;
247 memset((char *) nbuckets
, '\0', sizeof(nbuckets
));
248 for (np
= nodes
; np
;) {
251 for (cp
= np
->parent
; *cp
; cp
++)
253 np
->next
= nbuckets
[NBUCKET(hash
)];
254 nbuckets
[NBUCKET(hash
)] = np
;
260 print_error(const char *string
, const char *token
, int type
)
262 assert(string
!= NULL
);
263 if (type
== ENDOFFILE
)
264 snmplib_debug(0, "%s(EOF): On or around line %d\n", string
, Line
);
266 snmplib_debug(0, "%s(%s): On or around line %d\n", string
, token
, Line
);
268 snmplib_debug(0, "%s: On or around line %d\n", string
, Line
);
272 print_subtree(tree
, count
)
273 struct snmp_mib_tree
*tree
;
276 struct snmp_mib_tree
*tp
;
279 for (i
= 0; i
< count
; i
++)
281 printf("Children of %s:\n", tree
->label
);
283 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
284 for (i
= 0; i
< count
; i
++)
286 printf("%s\n", tp
->label
);
288 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
289 print_subtree(tp
, count
);
294 int translation_table
[40];
297 build_translation_table(void)
301 for (count
= 0; count
< 40; count
++) {
304 translation_table
[count
] = TYPE_OBJID
;
307 translation_table
[count
] = TYPE_OCTETSTR
;
310 translation_table
[count
] = TYPE_INTEGER
;
313 translation_table
[count
] = TYPE_IPADDR
;
316 translation_table
[count
] = TYPE_IPADDR
;
319 translation_table
[count
] = TYPE_COUNTER
;
322 translation_table
[count
] = TYPE_GAUGE
;
325 translation_table
[count
] = TYPE_TIMETICKS
;
328 translation_table
[count
] = TYPE_OPAQUE
;
331 translation_table
[count
] = TYPE_NULL
;
334 translation_table
[count
] = TYPE_OTHER
;
341 * Find all the children of root in the list of nodes. Link them into the
342 * tree and out of the nodes list.
345 do_subtree(struct snmp_mib_tree
*root
, struct node
**nodes
)
347 register struct snmp_mib_tree
*tp
;
348 struct snmp_mib_tree
*peer
= NULL
;
349 register struct node
*np
= NULL
, **headp
= NULL
;
350 struct node
*oldnp
= NULL
, *child_list
= NULL
, *childp
= NULL
;
356 for (cp
= tp
->label
; *cp
; cp
++)
358 headp
= &nbuckets
[NBUCKET(hash
)];
360 * Search each of the nodes for one whose parent is root, and
361 * move each into a separate list.
363 for (np
= *headp
; np
; np
= np
->next
) {
364 if ((*tp
->label
!= *np
->parent
) || strcmp(tp
->label
, np
->parent
)) {
365 if ((*tp
->label
== *np
->label
) && !strcmp(tp
->label
, np
->label
)) {
366 /* if there is another node with the same label, assume that
367 * any children after this point in the list belong to the other node.
368 * This adds some scoping to the table and allows vendors to
369 * reuse names such as "ip".
375 if (child_list
== NULL
) {
376 child_list
= childp
= np
; /* first entry in child list */
381 /* take this node out of the node list */
383 *headp
= np
->next
; /* fix root of node list */
385 oldnp
->next
= np
->next
; /* link around this node */
390 childp
->next
= 0; /* re-terminate list */
392 * Take each element in the child list and place it into the tree.
394 for (np
= child_list
; np
; np
= np
->next
) {
395 tp
= (struct snmp_mib_tree
*) xmalloc(sizeof(struct snmp_mib_tree
));
397 tp
->next_peer
= NULL
;
398 tp
->child_list
= NULL
;
399 strcpy(tp
->label
, np
->label
);
400 tp
->subid
= np
->subid
;
401 tp
->type
= translation_table
[np
->type
];
402 tp
->enums
= np
->enums
;
403 np
->enums
= NULL
; /* so we don't free them later */
404 if (root
->child_list
== NULL
) {
405 root
->child_list
= tp
;
407 peer
->next_peer
= tp
;
410 /* if (tp->type == TYPE_OTHER) */
411 do_subtree(tp
, nodes
); /* recurse on this child if it isn't an end node */
413 /* free all nodes that were copied into tree */
415 for (np
= child_list
; np
; np
= np
->next
) {
427 struct snmp_mib_tree
*
428 build_tree(struct node
*nodes
) {
430 struct snmp_mib_tree
*tp
;
431 int bucket
, nodes_left
= 0;
433 /* build root node */
434 tp
= (struct snmp_mib_tree
*) xmalloc(sizeof(struct snmp_mib_tree
));
436 tp
->next_peer
= NULL
;
437 tp
->child_list
= NULL
;
439 strcpy(tp
->label
, "iso");
442 build_translation_table();
443 /* grow tree from this root node */
444 init_node_hash(nodes
);
445 /* XXX nodes isn't needed in do_subtree() ??? */
446 do_subtree(tp
, &nodes
);
448 print_subtree(tp
, 0);
450 /* If any nodes are left, the tree is probably inconsistent */
451 for (bucket
= 0; bucket
< NHASHSIZE
; bucket
++) {
452 if (nbuckets
[bucket
]) {
458 snmplib_debug(0, "The mib description doesn't seem to be consistent.\n");
459 snmplib_debug(0, "Some nodes couldn't be linked under the \"iso\" tree.\n");
460 snmplib_debug(0, "these nodes are left:\n");
461 for (bucket
= 0; bucket
< NHASHSIZE
; bucket
++) {
462 for (np
= nbuckets
[bucket
]; np
; np
= np
->next
)
463 snmplib_debug(5, "%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
471 * Parses a token from the file. The type of the token parsed is returned,
472 * and the text is placed in the string pointed to by token.
474 static char last
= ' ';
477 get_token(register FILE *fp
, register char *token
)
480 register char *cp
= token
;
481 register int hash
= 0;
482 register struct tok
*tp
;
485 ch
= (unsigned char)last
;
486 /* skip all white space */
487 while (xisspace(ch
) && ch
!= -1) {
496 * Accumulate characters until end of token is found. Then attempt to match this
497 * token as a reserved word. If a match is found, return the type. Else it is
503 if (xisspace(ch
) || ch
== '(' || ch
== ')' ||
504 ch
== '{' || ch
== '}' || ch
== ',' ||
506 if (!xisspace(ch
) && *token
== 0) {
515 for (tp
= buckets
[BUCKET(hash
)]; tp
; tp
= tp
->next
) {
516 if ((tp
->hash
== hash
) && (strcmp(tp
->name
, token
) == 0))
520 if (tp
->token
== CONTINUE
)
524 if (token
[0] == '-' && token
[1] == '-') {
526 while ((ch
= getc(fp
)) != -1)
534 return get_token(fp
, token
);
536 for (cp
= token
; *cp
; cp
++)
547 } while ((ch
= getc(fp
)) != -1);
552 * Takes a list of the form:
553 * { iso org(3) dod(6) 1 }
554 * and creates several nodes, one for each parent-child pair.
555 * Returns NULL on error.
556 * register struct subid *SubOid; an array of subids
557 * int length; the length of the array
560 getoid(register FILE *fp
, register struct subid
*SubOid
, int length
)
567 if ((type
= get_token(fp
, token
)) != LEFTBRACKET
) {
568 print_error("Expected \"{\"", token
, type
);
571 type
= get_token(fp
, token
);
572 for (count
= 0; count
< length
; count
++, SubOid
++) {
575 if (type
== RIGHTBRACKET
) {
577 } else if (type
!= LABEL
&& type
!= NUMBER
) {
578 print_error("Not valid for object identifier", token
, type
);
582 /* this entry has a label */
583 cp
= (char *) xmalloc((unsigned) strlen(token
) + 1);
586 type
= get_token(fp
, token
);
587 if (type
== LEFTPAREN
) {
588 type
= get_token(fp
, token
);
589 if (type
== NUMBER
) {
590 SubOid
->subid
= atoi(token
);
591 if ((type
= get_token(fp
, token
)) != RIGHTPAREN
) {
592 print_error("Unexpected a closing parenthesis", token
, type
);
596 print_error("Expected a number", token
, type
);
603 /* this entry has just an integer sub-identifier */
604 SubOid
->subid
= atoi(token
);
606 type
= get_token(fp
, token
);
613 free_node(struct node
*np
)
615 struct enum_list
*ep
, *tep
;
627 free_node_list(struct node
*nl
)
630 struct node
*t
= nl
->next
;
637 * Parse an entry of the form:
638 * label OBJECT IDENTIFIER ::= { parent 2 }
639 * The "label OBJECT IDENTIFIER" portion has already been parsed.
640 * Returns 0 on error.
643 parse_objectid(FILE *fp
, char *name
) {
647 register struct subid
*op
, *nop
;
649 struct subid SubOid
[32];
650 struct node
*np
, *root
, *oldnp
= NULL
;
652 type
= get_token(fp
, token
);
653 if (type
!= EQUALS
) {
654 print_error("Bad format", token
, type
);
657 if ((length
= getoid(fp
, SubOid
, 32)) != 0) {
658 np
= root
= (struct node
*) xmalloc(sizeof(struct node
));
659 memset((char *) np
, '\0', sizeof(struct node
));
661 * For each parent-child subid pair in the subid array,
662 * create a node and link it into the node list.
664 for (count
= 0, op
= SubOid
, nop
= SubOid
+ 1; count
< (length
- 2); count
++,
666 /* every node must have parent's name and child's name or number */
667 if (op
->label
&& (nop
->label
|| (nop
->subid
!= -1))) {
668 strncpy(np
->parent
, op
->label
, sizeof(np
->parent
) - 1);
670 strncpy(np
->label
, nop
->label
, sizeof(np
->label
) - 1);
671 if (nop
->subid
!= -1)
672 np
->subid
= nop
->subid
;
675 /* set up next entry */
676 np
->next
= (struct node
*) xmalloc(sizeof(*np
->next
));
677 memset((char *) np
->next
, '\0', sizeof(struct node
));
682 np
->next
= (struct node
*) NULL
;
684 * The above loop took care of all but the last pair. This pair is taken
685 * care of here. The name for this node is taken from the label for this
687 * np still points to an unused entry.
689 if (count
== (length
- 2)) {
691 strncpy(np
->parent
, op
->label
, sizeof(np
->parent
)-1);
692 strncpy(np
->label
, name
, sizeof(np
->label
)-1);
693 if (nop
->subid
!= -1)
694 np
->subid
= nop
->subid
;
696 print_error("Warning: This entry is pretty silly", np
->label
, type
);
702 free_node_list(root
); // we need to clear the newly allocated list
707 print_error("Missing end of oid", (char *) NULL
, type
);
708 free_node_list(root
); // we need to clear the newly allocated list
713 /* free the oid array */
714 for (count
= 0, op
= SubOid
; count
< length
; count
++, op
++) {
721 print_error("Bad object identifier", (char *) NULL
, type
);
727 * Parses an asn type. This structure is ignored by this parser.
728 * Returns NULL on error.
731 parse_asntype(FILE *fp
)
736 type
= get_token(fp
, token
);
737 if (type
!= SEQUENCE
) {
738 print_error("Not a sequence", token
, type
); /* should we handle this */
741 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
742 if (type
== RIGHTBRACKET
)
745 print_error("Expected \"}\"", token
, type
);
750 * Parses an OBJECT TYPE macro.
751 * Returns 0 on error.
754 parse_objecttype(register FILE *fp
, char *name
) {
758 struct subid SubOid
[32];
762 register struct node
*np
= NULL
;
763 register struct enum_list
*ep
= NULL
;
765 type
= get_token(fp
, token
);
766 if (type
!= SYNTAX
) {
767 print_error("Bad format for OBJECT TYPE", token
, type
);
770 np
= (struct node
*) xmalloc(sizeof(struct node
));
773 type
= get_token(fp
, token
);
774 nexttype
= get_token(fp
, nexttoken
);
778 strcpy(syntax
, token
);
779 if (nexttype
== OF
) {
781 strcat(syntax
, nexttoken
);
782 nexttype
= get_token(fp
, nexttoken
);
784 strcat(syntax
, nexttoken
);
785 nexttype
= get_token(fp
, nexttoken
);
789 strcpy(syntax
, token
);
790 if (nexttype
== LEFTBRACKET
) {
791 /* if there is an enumeration list, parse it */
792 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
793 if (type
== RIGHTBRACKET
)
796 /* this is an enumerated label */
797 if (np
->enums
== 0) {
798 ep
= np
->enums
= (struct enum_list
*)
799 xmalloc(sizeof(struct enum_list
));
801 ep
->next
= (struct enum_list
*)
802 xmalloc(sizeof(struct enum_list
));
806 /* a reasonable approximation for the length */
807 ep
->label
= (char *) xmalloc((unsigned) strlen(token
) + 1);
808 strcpy(ep
->label
, token
);
809 type
= get_token(fp
, token
);
810 if (type
!= LEFTPAREN
) {
811 print_error("Expected \"(\"", token
, type
);
815 type
= get_token(fp
, token
);
816 if (type
!= NUMBER
) {
817 print_error("Expected integer", token
, type
);
821 ep
->value
= atoi(token
);
822 type
= get_token(fp
, token
);
823 if (type
!= RIGHTPAREN
) {
824 print_error("Expected \")\"", token
, type
);
830 if (type
== ENDOFFILE
) {
831 print_error("Expected \"}\"", token
, type
);
835 nexttype
= get_token(fp
, nexttoken
);
836 } else if (nexttype
== LEFTPAREN
) {
837 /* ignore the "constrained integer" for now */
838 nexttype
= get_token(fp
, nexttoken
);
839 nexttype
= get_token(fp
, nexttoken
);
840 nexttype
= get_token(fp
, nexttoken
);
853 strcpy(syntax
, token
);
856 print_error("Bad syntax", token
, type
);
860 if (nexttype
!= ACCESS
) {
861 print_error("Should be ACCESS", nexttoken
, nexttype
);
865 type
= get_token(fp
, token
);
866 if (type
!= READONLY
&& type
!= READWRITE
&& type
!= WRITEONLY
867 && type
!= NOACCESS
) {
868 print_error("Bad access type", nexttoken
, nexttype
);
872 type
= get_token(fp
, token
);
873 if (type
!= SNMP_STATUS
) {
874 print_error("Should be STATUS", token
, nexttype
);
878 type
= get_token(fp
, token
);
879 if (type
!= MANDATORY
&& type
!= SNMP_OPTIONAL
&& type
!= OBSOLETE
&& type
!= RECOMMENDED
) {
880 print_error("Bad status", token
, type
);
884 /* Fetch next token. Either:
886 * -> EQUALS (Old MIB format)
887 * -> DESCRIPTION, INDEX (New MIB format)
889 type
= get_token(fp
, token
);
890 if ((type
!= DESCRIPTION
) && (type
!= INDEX
) && (type
!= EQUALS
)) {
891 print_error("Should be DESCRIPTION, INDEX, or EQUALS", token
, nexttype
);
895 if (type
== DESCRIPTION
) {
897 type
= get_token(fp
, token
);
899 print_error("Should be Description open quote", token
, nexttype
);
903 /* Fetch description string */
908 /* skip everything until closing quote */
909 while ((ReadChar
!= '"') && (ReadChar
!= -1)) {
911 if (ReadChar
== '\n')
916 /* ASSERT: Done with description. */
917 type
= get_token(fp
, token
);
919 if ((type
!= INDEX
) && (type
!= EQUALS
)) {
920 print_error("Should be INDEX, or EQUALS", token
, nexttype
);
928 type
= get_token(fp
, token
);
929 if (type
!= LEFTBRACKET
) {
930 print_error("Should be INDEX left brace", token
, type
);
934 /* Fetch description string */
939 /* skip everything until closing quote */
940 while ((ReadChar
!= '}') && (ReadChar
!= -1)) {
942 if (ReadChar
== '\n')
947 /* ASSERT: Done with INDEX. */
948 type
= get_token(fp
, token
);
950 if (type
!= EQUALS
) {
951 print_error("Bad format", token
, type
);
955 length
= getoid(fp
, SubOid
, 32);
956 if (length
> 1 && length
<= 32) {
957 /* just take the last pair in the oid list */
958 if (SubOid
[length
- 2].label
) {
959 strncpy(np
->parent
, SubOid
[length
- 2].label
, 64);
960 np
->parent
[63] = '\0';
962 strncpy(np
->label
, name
, sizeof(np
->label
));
963 np
->label
[sizeof(np
->label
) - 1] = '\0';
964 if (SubOid
[length
- 1].subid
!= -1)
965 np
->subid
= SubOid
[length
- 1].subid
;
967 print_error("Warning: This entry is pretty silly", np
->label
, type
);
969 print_error("No end to oid", (char *) NULL
, type
);
974 for (count
= 0; count
< length
; count
++) {
975 if (SubOid
[count
].label
)
976 xfree(SubOid
[count
].label
);
977 SubOid
[count
].label
= 0;
983 * Parses a mib file and returns a linked list of nodes found in the file.
984 * Returns NULL on error.
994 struct node
*np
= NULL
, *root
= NULL
;
998 while (type
!= ENDOFFILE
) {
999 type
= get_token(fp
, token
);
1000 if (type
!= LABEL
) {
1001 if (type
== ENDOFFILE
) {
1004 print_error(token
, "is a reserved word", type
);
1005 free_node_list(root
);
1008 strncpy(name
, token
, 64);
1010 type
= get_token(fp
, token
);
1011 if (type
== OBJTYPE
) {
1013 /* first link in chain */
1014 np
= root
= parse_objecttype(fp
, name
);
1016 print_error("Bad parse of object type", (char *) NULL
, type
);
1020 np
->next
= parse_objecttype(fp
, name
);
1021 if (np
->next
== NULL
) {
1022 print_error("Bad parse of objecttype", (char *) NULL
, type
);
1023 free_node_list(root
);
1027 /* now find end of chain */
1030 } else if (type
== OBJID
) {
1032 /* first link in chain */
1033 np
= root
= parse_objectid(fp
, name
);
1035 print_error("Bad parse of object id", (char *) NULL
, type
);
1039 np
->next
= parse_objectid(fp
, name
);
1040 if (np
->next
== NULL
) {
1041 print_error("Bad parse of object type", (char *) NULL
, type
);
1042 free_node_list(root
);
1046 /* now find end of chain */
1049 } else if (type
== EQUALS
) {
1050 type
= parse_asntype(fp
);
1051 } else if (type
== ENDOFFILE
) {
1054 print_error("Bad operator", (char *) NULL
, type
);
1055 free_node_list(root
);
1061 struct enum_list
*ep
;
1063 for (np
= root
; np
; np
= np
->next
) {
1064 printf("%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
1067 printf("Enums: \n");
1068 for (ep
= np
->enums
; ep
; ep
= ep
->next
) {
1069 printf("%s(%d)\n", ep
->label
, ep
->value
);
1078 struct snmp_mib_tree
*
1079 read_mib(char *filename
) {
1082 struct snmp_mib_tree
*tree
;
1086 fp
= fopen(filename
, "r");
1088 snmplib_debug(1, "init_mib: %s: %s\n", filename
, xstrerror());
1092 while ((p
= fgets(mbuf
, 256, fp
)) && strncmp(mbuf
, "DUMMY",
1095 snmplib_debug(0, "Bad MIB version or tag missing, install original!\n");
1099 if (!strcmp(mbuf
, "DUMMY")) {
1100 snmplib_debug(0, "You need to update your MIB!\n");
1107 snmplib_debug(0, "Mib table is bad. Exiting\n");
1110 tree
= build_tree(nodes
);