]>
git.ipfire.org Git - thirdparty/squid.git/blob - 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 ******************************************************************/
37 #include <sys/types.h>
43 #include <gnumalloc.h>
44 #elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)
60 #include <sys/socket.h>
63 #include <netinet/in.h>
66 #include <arpa/inet.h>
80 #include "snmp_vars.h"
82 #include "snmp_debug.h"
86 #include "cache_snmp.h"
88 * This is one element of an object identifier with either an integer subidentifier,
89 * or a textual string label, or both.
90 * The subid is -1 if not present, and label is NULL if not present.
98 * A linked list of nodes.
102 char label
[64]; /* This node's (unique) textual name */
103 u_int subid
; /* This node's integer subidentifier */
104 char parent
[64]; /* The parent's textual name */
105 int type
; /* The type of object this represents */
106 struct enum_list
*enums
; /* (optional) list of enumerated integers (otherwise NULL) */
111 /* types of tokens */
127 #define SNMP_OPAQUE 12
130 #define OF 15 /* SEQUENCE OF */
140 #define SNMP_OPTIONAL 24
142 #define RECOMMENDED 26
146 #define LEFTBRACKET 30
147 #define RIGHTBRACKET 31
149 #define RIGHTPAREN 33
151 /* For SNMPv2 SMI pseudo-compliance */
152 #define DESCRIPTION 35
157 const char *name
; /* token name */
158 int len
; /* length not counting nul */
159 int token
; /* value */
160 int hash
; /* hash of name */
161 struct tok
*next
; /* pointer to next in hash table */
165 struct tok tokens
[] =
167 {"obsolete", sizeof("obsolete") - 1, OBSOLETE
},
168 {"Opaque", sizeof("Opaque") - 1, SNMP_OPAQUE
},
169 {"recommended", sizeof("recommended") - 1, RECOMMENDED
},
170 {"optional", sizeof("optional") - 1, SNMP_OPTIONAL
},
171 {"mandatory", sizeof("mandatory") - 1, MANDATORY
},
172 {"current", sizeof("current") - 1, MANDATORY
},
173 {"not-accessible", sizeof("not-accessible") - 1, NOACCESS
},
174 {"write-only", sizeof("write-only") - 1, WRITEONLY
},
175 {"read-write", sizeof("read-write") - 1, READWRITE
},
176 {"TimeTicks", sizeof("TimeTicks") - 1, TIMETICKS
},
177 {"OBJECTIDENTIFIER", sizeof("OBJECTIDENTIFIER") - 1, OBJID
},
179 * This CONTINUE appends the next word onto OBJECT,
180 * hopefully matching OBJECTIDENTIFIER above.
182 {"OBJECT", sizeof("OBJECT") - 1, CONTINUE
},
183 {"NetworkAddress", sizeof("NetworkAddress") - 1, NETADDR
},
184 {"Gauge", sizeof("Gauge") - 1, GAUGE
},
185 {"OCTETSTRING", sizeof("OCTETSTRING") - 1, OCTETSTR
},
186 {"OCTET", sizeof("OCTET") - 1, -1},
187 {"OF", sizeof("OF") - 1, OF
},
188 {"SEQUENCE", sizeof("SEQUENCE") - 1, SEQUENCE
},
189 {"NULL", sizeof("NULL") - 1, NUL
},
190 {"IpAddress", sizeof("IpAddress") - 1, IPADDR
},
191 {"INTEGER", sizeof("INTEGER") - 1, INTEGER
},
192 {"Counter", sizeof("Counter") - 1, COUNTER
},
193 {"read-only", sizeof("read-only") - 1, READONLY
},
194 {"ACCESS", sizeof("ACCESS") - 1, ACCESS
},
195 {"MAX-ACCESS", sizeof("MAX-ACCESS") - 1, ACCESS
},
196 {"STATUS", sizeof("STATUS") - 1, STATUS
},
197 {"SYNTAX", sizeof("SYNTAX") - 1, SYNTAX
},
198 {"OBJECT-TYPE", sizeof("OBJECT-TYPE") - 1, OBJTYPE
},
199 {"{", sizeof("{") - 1, LEFTBRACKET
},
200 {"}", sizeof("}") - 1, RIGHTBRACKET
},
201 {"::=", sizeof("::=") - 1, EQUALS
},
202 {"(", sizeof("(") - 1, LEFTPAREN
},
203 {")", sizeof(")") - 1, RIGHTPAREN
},
204 {",", sizeof(",") - 1, COMMA
},
205 {"DESCRIPTION", sizeof("DESCRIPTION") - 1, DESCRIPTION
},
206 {"INDEX", sizeof("INDEX") - 1, INDEX
},
207 {"\"", sizeof("\"") - 1, QUOTE
},
208 {"END", sizeof("END") - 1, ENDOFFILE
},
209 /* Hacks for easier MIBFILE coercing */
210 {"read-create", sizeof("read-create") - 1, READWRITE
},
215 #define BUCKET(x) (x & 0x01F)
217 static struct tok
*buckets
[HASHSIZE
];
222 register struct tok
*tp
;
223 register const char *cp
;
227 memset((char *) buckets
, '\0', sizeof(buckets
));
228 for (tp
= tokens
; tp
->name
; tp
++) {
229 for (h
= 0, cp
= tp
->name
; *cp
; cp
++)
234 tp
->next
= buckets
[b
]; /* BUG ??? */
239 #define NHASHSIZE 128
240 #define NBUCKET(x) (x & 0x7F)
241 struct node
*nbuckets
[NHASHSIZE
];
244 init_node_hash(struct node
*nodes
)
246 register struct node
*np
, *nextp
;
250 memset((char *) nbuckets
, '\0', sizeof(nbuckets
));
251 for (np
= nodes
; np
;) {
254 for (cp
= np
->parent
; *cp
; cp
++)
256 np
->next
= nbuckets
[NBUCKET(hash
)];
257 nbuckets
[NBUCKET(hash
)] = np
;
264 print_error(const char *string
, const char *token
, int type
)
266 assert(string
!= NULL
);
267 if (type
== ENDOFFILE
)
268 snmplib_debug(0, "%s(EOF): On or around line %d\n", string
, Line
);
270 snmplib_debug(0, "%s(%s): On or around line %d\n", string
, token
, Line
);
272 snmplib_debug(0, "%s: On or around line %d\n", string
, Line
);
276 print_subtree(tree
, count
)
277 struct snmp_mib_tree
*tree
;
280 struct snmp_mib_tree
*tp
;
283 for (i
= 0; i
< count
; i
++)
285 printf("Children of %s:\n", tree
->label
);
287 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
288 for (i
= 0; i
< count
; i
++)
290 printf("%s\n", tp
->label
);
292 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
293 print_subtree(tp
, count
);
298 int translation_table
[40];
301 build_translation_table(void)
305 for (count
= 0; count
< 40; count
++) {
308 translation_table
[count
] = TYPE_OBJID
;
311 translation_table
[count
] = TYPE_OCTETSTR
;
314 translation_table
[count
] = TYPE_INTEGER
;
317 translation_table
[count
] = TYPE_IPADDR
;
320 translation_table
[count
] = TYPE_IPADDR
;
323 translation_table
[count
] = TYPE_COUNTER
;
326 translation_table
[count
] = TYPE_GAUGE
;
329 translation_table
[count
] = TYPE_TIMETICKS
;
332 translation_table
[count
] = TYPE_OPAQUE
;
335 translation_table
[count
] = TYPE_NULL
;
338 translation_table
[count
] = TYPE_OTHER
;
345 * Find all the children of root in the list of nodes. Link them into the
346 * tree and out of the nodes list.
349 do_subtree(struct snmp_mib_tree
*root
, struct node
**nodes
)
351 register struct snmp_mib_tree
*tp
;
352 struct snmp_mib_tree
*peer
= NULL
;
353 register struct node
*np
= NULL
, **headp
= NULL
;
354 struct node
*oldnp
= NULL
, *child_list
= NULL
, *childp
= NULL
;
360 for (cp
= tp
->label
; *cp
; cp
++)
362 headp
= &nbuckets
[NBUCKET(hash
)];
364 * Search each of the nodes for one whose parent is root, and
365 * move each into a separate list.
367 for (np
= *headp
; np
; np
= np
->next
) {
368 if ((*tp
->label
!= *np
->parent
) || strcmp(tp
->label
, np
->parent
)) {
369 if ((*tp
->label
== *np
->label
) && !strcmp(tp
->label
, np
->label
)) {
370 /* if there is another node with the same label, assume that
371 * any children after this point in the list belong to the other node.
372 * This adds some scoping to the table and allows vendors to
373 * reuse names such as "ip".
379 if (child_list
== NULL
) {
380 child_list
= childp
= np
; /* first entry in child list */
385 /* take this node out of the node list */
387 *headp
= np
->next
; /* fix root of node list */
389 oldnp
->next
= np
->next
; /* link around this node */
394 childp
->next
= 0; /* re-terminate list */
396 * Take each element in the child list and place it into the tree.
398 for (np
= child_list
; np
; np
= np
->next
) {
399 tp
= (struct snmp_mib_tree
*) xmalloc(sizeof(struct snmp_mib_tree
));
401 tp
->next_peer
= NULL
;
402 tp
->child_list
= NULL
;
403 strcpy(tp
->label
, np
->label
);
404 tp
->subid
= np
->subid
;
405 tp
->type
= translation_table
[np
->type
];
406 tp
->enums
= np
->enums
;
407 np
->enums
= NULL
; /* so we don't free them later */
408 if (root
->child_list
== NULL
) {
409 root
->child_list
= tp
;
411 peer
->next_peer
= tp
;
414 /* if (tp->type == TYPE_OTHER) */
415 do_subtree(tp
, nodes
); /* recurse on this child if it isn't an end node */
417 /* free all nodes that were copied into tree */
419 for (np
= child_list
; np
; np
= np
->next
) {
431 struct snmp_mib_tree
*
432 build_tree(struct node
*nodes
)
435 struct snmp_mib_tree
*tp
;
436 int bucket
, nodes_left
= 0;
438 /* build root node */
439 tp
= (struct snmp_mib_tree
*) xmalloc(sizeof(struct snmp_mib_tree
));
441 tp
->next_peer
= NULL
;
442 tp
->child_list
= NULL
;
444 strcpy(tp
->label
, "iso");
447 build_translation_table();
448 /* grow tree from this root node */
449 init_node_hash(nodes
);
450 /* XXX nodes isn't needed in do_subtree() ??? */
451 do_subtree(tp
, &nodes
);
453 print_subtree(tp
, 0);
455 /* If any nodes are left, the tree is probably inconsistent */
456 for (bucket
= 0; bucket
< NHASHSIZE
; bucket
++) {
457 if (nbuckets
[bucket
]) {
463 snmplib_debug(0, "The mib description doesn't seem to be consistent.\n");
464 snmplib_debug(0, "Some nodes couldn't be linked under the \"iso\" tree.\n");
465 snmplib_debug(0, "these nodes are left:\n");
466 for (bucket
= 0; bucket
< NHASHSIZE
; bucket
++) {
467 for (np
= nbuckets
[bucket
]; np
; np
= np
->next
)
468 snmplib_debug(5, "%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
477 * Parses a token from the file. The type of the token parsed is returned,
478 * and the text is placed in the string pointed to by token.
480 static char last
= ' ';
483 get_token(register FILE *fp
, register char *token
)
486 register char *cp
= token
;
487 register int hash
= 0;
488 register struct tok
*tp
;
491 ch
= (unsigned char)last
;
492 /* skip all white space */
493 while (xisspace(ch
) && ch
!= -1) {
502 * Accumulate characters until end of token is found. Then attempt to match this
503 * token as a reserved word. If a match is found, return the type. Else it is
509 if (xisspace(ch
) || ch
== '(' || ch
== ')' ||
510 ch
== '{' || ch
== '}' || ch
== ',' ||
512 if (!xisspace(ch
) && *token
== 0) {
521 for (tp
= buckets
[BUCKET(hash
)]; tp
; tp
= tp
->next
) {
522 if ((tp
->hash
== hash
) && (strcmp(tp
->name
, token
) == 0))
526 if (tp
->token
== CONTINUE
)
530 if (token
[0] == '-' && token
[1] == '-') {
532 while ((ch
= getc(fp
)) != -1)
540 return get_token(fp
, token
);
542 for (cp
= token
; *cp
; cp
++)
553 } while ((ch
= getc(fp
)) != -1);
558 * Takes a list of the form:
559 * { iso org(3) dod(6) 1 }
560 * and creates several nodes, one for each parent-child pair.
561 * Returns NULL on error.
562 * register struct subid *SubOid; an array of subids
563 * int length; the length of the array
566 getoid(register FILE *fp
, register struct subid
*SubOid
, int length
)
573 if ((type
= get_token(fp
, token
)) != LEFTBRACKET
) {
574 print_error("Expected \"{\"", token
, type
);
577 type
= get_token(fp
, token
);
578 for (count
= 0; count
< length
; count
++, SubOid
++) {
581 if (type
== RIGHTBRACKET
) {
583 } else if (type
!= LABEL
&& type
!= NUMBER
) {
584 print_error("Not valid for object identifier", token
, type
);
588 /* this entry has a label */
589 cp
= (char *) xmalloc((unsigned) strlen(token
) + 1);
592 type
= get_token(fp
, token
);
593 if (type
== LEFTPAREN
) {
594 type
= get_token(fp
, token
);
595 if (type
== NUMBER
) {
596 SubOid
->subid
= atoi(token
);
597 if ((type
= get_token(fp
, token
)) != RIGHTPAREN
) {
598 print_error("Unexpected a closing parenthesis", token
, type
);
602 print_error("Expected a number", token
, type
);
609 /* this entry has just an integer sub-identifier */
610 SubOid
->subid
= atoi(token
);
612 type
= get_token(fp
, token
);
620 free_node(struct node
*np
)
622 struct enum_list
*ep
, *tep
;
634 * Parse an entry of the form:
635 * label OBJECT IDENTIFIER ::= { parent 2 }
636 * The "label OBJECT IDENTIFIER" portion has already been parsed.
637 * Returns 0 on error.
640 parse_objectid(FILE *fp
, char *name
)
645 register struct subid
*op
, *nop
;
647 struct subid SubOid
[32];
648 struct node
*np
, *root
, *oldnp
= NULL
;
650 type
= get_token(fp
, token
);
651 if (type
!= EQUALS
) {
652 print_error("Bad format", token
, type
);
655 if ((length
= getoid(fp
, SubOid
, 32)) != 0) {
656 np
= root
= (struct node
*) xmalloc(sizeof(struct node
));
657 memset((char *) np
, '\0', sizeof(struct node
));
659 * For each parent-child subid pair in the subid array,
660 * create a node and link it into the node list.
662 for (count
= 0, op
= SubOid
, nop
= SubOid
+ 1; count
< (length
- 2); count
++,
664 /* every node must have parent's name and child's name or number */
665 if (op
->label
&& (nop
->label
|| (nop
->subid
!= -1))) {
666 strcpy(np
->parent
, op
->label
);
668 strcpy(np
->label
, nop
->label
);
669 if (nop
->subid
!= -1)
670 np
->subid
= nop
->subid
;
673 /* set up next entry */
674 np
->next
= (struct node
*) xmalloc(sizeof(*np
->next
));
675 memset((char *) np
->next
, '\0', sizeof(struct node
));
680 np
->next
= (struct node
*) NULL
;
682 * The above loop took care of all but the last pair. This pair is taken
683 * care of here. The name for this node is taken from the label for this
685 * np still points to an unused entry.
687 if (count
== (length
- 2)) {
689 strcpy(np
->parent
, op
->label
);
690 strcpy(np
->label
, name
);
691 if (nop
->subid
!= -1)
692 np
->subid
= nop
->subid
;
694 print_error("Warning: This entry is pretty silly", np
->label
, type
);
703 print_error("Missing end of oid", (char *) NULL
, type
);
704 free_node(np
); /* the last node allocated wasn't used */
709 /* free the oid array */
710 for (count
= 0, op
= SubOid
; count
< length
; count
++, op
++) {
717 print_error("Bad object identifier", (char *) NULL
, type
);
723 * Parses an asn type. This structure is ignored by this parser.
724 * Returns NULL on error.
727 parse_asntype(FILE *fp
)
732 type
= get_token(fp
, token
);
733 if (type
!= SEQUENCE
) {
734 print_error("Not a sequence", token
, type
); /* should we handle this */
737 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
738 if (type
== RIGHTBRACKET
)
741 print_error("Expected \"}\"", token
, type
);
746 * Parses an OBJECT TYPE macro.
747 * Returns 0 on error.
750 parse_objecttype(register FILE *fp
, char *name
)
755 struct subid SubOid
[32];
759 register struct node
*np
= NULL
;
760 register struct enum_list
*ep
= NULL
;
762 type
= get_token(fp
, token
);
763 if (type
!= SYNTAX
) {
764 print_error("Bad format for OBJECT TYPE", token
, type
);
767 np
= (struct node
*) xmalloc(sizeof(struct node
));
770 type
= get_token(fp
, token
);
771 nexttype
= get_token(fp
, nexttoken
);
775 strcpy(syntax
, token
);
776 if (nexttype
== OF
) {
778 strcat(syntax
, nexttoken
);
779 nexttype
= get_token(fp
, nexttoken
);
781 strcat(syntax
, nexttoken
);
782 nexttype
= get_token(fp
, nexttoken
);
786 strcpy(syntax
, token
);
787 if (nexttype
== LEFTBRACKET
) {
788 /* if there is an enumeration list, parse it */
789 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
790 if (type
== RIGHTBRACKET
)
793 /* this is an enumerated label */
794 if (np
->enums
== 0) {
795 ep
= np
->enums
= (struct enum_list
*)
796 xmalloc(sizeof(struct enum_list
));
798 ep
->next
= (struct enum_list
*)
799 xmalloc(sizeof(struct enum_list
));
803 /* a reasonable approximation for the length */
804 ep
->label
= (char *) xmalloc((unsigned) strlen(token
) + 1);
805 strcpy(ep
->label
, token
);
806 type
= get_token(fp
, token
);
807 if (type
!= LEFTPAREN
) {
808 print_error("Expected \"(\"", token
, type
);
812 type
= get_token(fp
, token
);
813 if (type
!= NUMBER
) {
814 print_error("Expected integer", token
, type
);
818 ep
->value
= atoi(token
);
819 type
= get_token(fp
, token
);
820 if (type
!= RIGHTPAREN
) {
821 print_error("Expected \")\"", token
, type
);
827 if (type
== ENDOFFILE
) {
828 print_error("Expected \"}\"", token
, type
);
832 nexttype
= get_token(fp
, nexttoken
);
833 } else if (nexttype
== LEFTPAREN
) {
834 /* ignore the "constrained integer" for now */
835 nexttype
= get_token(fp
, nexttoken
);
836 nexttype
= get_token(fp
, nexttoken
);
837 nexttype
= get_token(fp
, nexttoken
);
850 strcpy(syntax
, token
);
853 print_error("Bad syntax", token
, type
);
857 if (nexttype
!= ACCESS
) {
858 print_error("Should be ACCESS", nexttoken
, nexttype
);
862 type
= get_token(fp
, token
);
863 if (type
!= READONLY
&& type
!= READWRITE
&& type
!= WRITEONLY
864 && type
!= NOACCESS
) {
865 print_error("Bad access type", nexttoken
, nexttype
);
869 type
= get_token(fp
, token
);
870 if (type
!= STATUS
) {
871 print_error("Should be STATUS", token
, nexttype
);
875 type
= get_token(fp
, token
);
876 if (type
!= MANDATORY
&& type
!= SNMP_OPTIONAL
&& type
!= OBSOLETE
&& type
!= RECOMMENDED
) {
877 print_error("Bad status", token
, type
);
881 /* Fetch next token. Either:
883 * -> EQUALS (Old MIB format)
884 * -> DESCRIPTION, INDEX (New MIB format)
886 type
= get_token(fp
, token
);
887 if ((type
!= DESCRIPTION
) && (type
!= INDEX
) && (type
!= EQUALS
)) {
888 print_error("Should be DESCRIPTION, INDEX, or EQUALS", token
, nexttype
);
892 if (type
== DESCRIPTION
) {
894 type
= get_token(fp
, token
);
896 print_error("Should be Description open quote", token
, nexttype
);
900 /* Fetch description string */
905 /* skip everything until closing quote */
906 while ((ReadChar
!= '"') && (ReadChar
!= -1)) {
908 if (ReadChar
== '\n')
913 /* ASSERT: Done with description. */
914 type
= get_token(fp
, token
);
916 if ((type
!= INDEX
) && (type
!= EQUALS
)) {
917 print_error("Should be INDEX, or EQUALS", token
, nexttype
);
925 type
= get_token(fp
, token
);
926 if (type
!= LEFTBRACKET
) {
927 print_error("Should be INDEX left brace", token
, type
);
931 /* Fetch description string */
936 /* skip everything until closing quote */
937 while ((ReadChar
!= '}') && (ReadChar
!= -1)) {
939 if (ReadChar
== '\n')
944 /* ASSERT: Done with INDEX. */
945 type
= get_token(fp
, token
);
947 if (type
!= EQUALS
) {
948 print_error("Bad format", token
, type
);
952 length
= getoid(fp
, SubOid
, 32);
953 if (length
> 1 && length
<= 32) {
954 /* just take the last pair in the oid list */
955 if (SubOid
[length
- 2].label
)
956 strncpy(np
->parent
, SubOid
[length
- 2].label
, 64);
957 strcpy(np
->label
, name
);
958 if (SubOid
[length
- 1].subid
!= -1)
959 np
->subid
= SubOid
[length
- 1].subid
;
961 print_error("Warning: This entry is pretty silly", np
->label
, type
);
963 print_error("No end to oid", (char *) NULL
, type
);
968 for (count
= 0; count
< length
; count
++) {
969 if (SubOid
[count
].label
)
970 xfree(SubOid
[count
].label
);
971 SubOid
[count
].label
= 0;
978 * Parses a mib file and returns a linked list of nodes found in the file.
979 * Returns NULL on error.
990 struct node
*np
= NULL
, *root
= NULL
;
994 while (type
!= ENDOFFILE
) {
995 type
= get_token(fp
, token
);
997 if (type
== ENDOFFILE
) {
1000 print_error(token
, "is a reserved word", type
);
1003 strncpy(name
, token
, 64);
1004 type
= get_token(fp
, token
);
1005 if (type
== OBJTYPE
) {
1007 /* first link in chain */
1008 np
= root
= parse_objecttype(fp
, name
);
1010 print_error("Bad parse of object type", (char *) NULL
, type
);
1014 np
->next
= parse_objecttype(fp
, name
);
1015 if (np
->next
== NULL
) {
1016 print_error("Bad parse of objecttype", (char *) NULL
, type
);
1020 /* now find end of chain */
1023 } else if (type
== OBJID
) {
1025 /* first link in chain */
1026 np
= root
= parse_objectid(fp
, name
);
1028 print_error("Bad parse of object id", (char *) NULL
, type
);
1032 np
->next
= parse_objectid(fp
, name
);
1033 if (np
->next
== NULL
) {
1034 print_error("Bad parse of object type", (char *) NULL
, type
);
1038 /* now find end of chain */
1041 } else if (type
== EQUALS
) {
1042 type
= parse_asntype(fp
);
1043 } else if (type
== ENDOFFILE
) {
1046 print_error("Bad operator", (char *) NULL
, type
);
1052 struct enum_list
*ep
;
1054 for (np
= root
; np
; np
= np
->next
) {
1055 printf("%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
1058 printf("Enums: \n");
1059 for (ep
= np
->enums
; ep
; ep
= ep
->next
) {
1060 printf("%s(%d)\n", ep
->label
, ep
->value
);
1069 struct snmp_mib_tree
*
1070 read_mib(char *filename
)
1074 struct snmp_mib_tree
*tree
;
1078 fp
= fopen(filename
, "r");
1080 snmplib_debug(1, "init_mib: %s: %s\n", filename
, xstrerror());
1084 while ((p
= fgets(mbuf
, 256, fp
)) && strncmp(mbuf
, "DUMMY",
1087 snmplib_debug(0, "Bad MIB version or tag missing, install original!\n");
1090 if (!strcmp(mbuf
, "DUMMY")) {
1091 snmplib_debug(0, "You need to update your MIB!\n");
1096 snmplib_debug(0, "Mib table is bad. Exiting\n");
1099 tree
= build_tree(nodes
);