]>
git.ipfire.org Git - thirdparty/squid.git/blob - snmplib/parse.c
02fe588e7641a0a253deb0847ce83ce82decf260
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"
44 #include <sys/types.h>
50 #include <gnumalloc.h>
67 #include <sys/socket.h>
70 #include <netinet/in.h>
73 #include <arpa/inet.h>
89 * This is one element of an object identifier with either an integer subidentifier,
90 * or a textual string label, or both.
91 * The subid is -1 if not present, and label is NULL if not present.
99 * A linked list of nodes.
103 char label
[64]; /* This node's (unique) textual name */
104 u_int subid
; /* This node's integer subidentifier */
105 char parent
[64]; /* The parent's textual name */
106 int type
; /* The type of object this represents */
107 struct enum_list
*enums
; /* (optional) list of enumerated integers (otherwise NULL) */
112 /* types of tokens */
128 #define SNMP_OPAQUE 12
131 #define OF 15 /* SEQUENCE OF */
139 #define SNMP_STATUS 22
141 #define SNMP_OPTIONAL 24
143 #define RECOMMENDED 26
147 #define LEFTBRACKET 30
148 #define RIGHTBRACKET 31
150 #define RIGHTPAREN 33
152 /* For SNMPv2 SMI pseudo-compliance */
153 #define DESCRIPTION 35
158 const char *name
; /* token name */
159 int len
; /* length not counting nul */
160 int token
; /* value */
161 int hash
; /* hash of name */
162 struct tok
*next
; /* pointer to next in hash table */
165 struct tok tokens
[] = {
166 {"obsolete", sizeof("obsolete") - 1, OBSOLETE
},
167 {"Opaque", sizeof("Opaque") - 1, SNMP_OPAQUE
},
168 {"recommended", sizeof("recommended") - 1, RECOMMENDED
},
169 {"optional", sizeof("optional") - 1, SNMP_OPTIONAL
},
170 {"mandatory", sizeof("mandatory") - 1, MANDATORY
},
171 {"current", sizeof("current") - 1, MANDATORY
},
172 {"not-accessible", sizeof("not-accessible") - 1, NOACCESS
},
173 {"write-only", sizeof("write-only") - 1, WRITEONLY
},
174 {"read-write", sizeof("read-write") - 1, READWRITE
},
175 {"TimeTicks", sizeof("TimeTicks") - 1, TIMETICKS
},
176 {"OBJECTIDENTIFIER", sizeof("OBJECTIDENTIFIER") - 1, OBJID
},
178 * This CONTINUE appends the next word onto OBJECT,
179 * hopefully matching OBJECTIDENTIFIER above.
181 {"OBJECT", sizeof("OBJECT") - 1, CONTINUE
},
182 {"NetworkAddress", sizeof("NetworkAddress") - 1, NETADDR
},
183 {"Gauge", sizeof("Gauge") - 1, GAUGE
},
184 {"OCTETSTRING", sizeof("OCTETSTRING") - 1, OCTETSTR
},
185 {"OCTET", sizeof("OCTET") - 1, -1},
186 {"OF", sizeof("OF") - 1, OF
},
187 {"SEQUENCE", sizeof("SEQUENCE") - 1, SEQUENCE
},
188 {"NULL", sizeof("NULL") - 1, NUL
},
189 {"IpAddress", sizeof("IpAddress") - 1, IPADDR
},
190 {"INTEGER", sizeof("INTEGER") - 1, INTEGER
},
191 {"Counter", sizeof("Counter") - 1, COUNTER
},
192 {"read-only", sizeof("read-only") - 1, READONLY
},
193 {"ACCESS", sizeof("ACCESS") - 1, ACCESS
},
194 {"MAX-ACCESS", sizeof("MAX-ACCESS") - 1, ACCESS
},
195 {"STATUS", sizeof("STATUS") - 1, SNMP_STATUS
},
196 {"SYNTAX", sizeof("SYNTAX") - 1, SYNTAX
},
197 {"OBJECT-TYPE", sizeof("OBJECT-TYPE") - 1, OBJTYPE
},
198 {"{", sizeof("{") - 1, LEFTBRACKET
},
199 {"}", sizeof("}") - 1, RIGHTBRACKET
},
200 {"::=", sizeof("::=") - 1, EQUALS
},
201 {"(", sizeof("(") - 1, LEFTPAREN
},
202 {")", sizeof(")") - 1, RIGHTPAREN
},
203 {",", sizeof(",") - 1, COMMA
},
204 {"DESCRIPTION", sizeof("DESCRIPTION") - 1, DESCRIPTION
},
205 {"INDEX", sizeof("INDEX") - 1, INDEX
},
206 {"\"", sizeof("\"") - 1, QUOTE
},
207 {"END", sizeof("END") - 1, ENDOFFILE
},
208 /* Hacks for easier MIBFILE coercing */
209 {"read-create", sizeof("read-create") - 1, READWRITE
},
214 #define BUCKET(x) (x & 0x01F)
216 static struct tok
*buckets
[HASHSIZE
];
221 register struct tok
*tp
;
222 register const char *cp
;
226 memset((char *) buckets
, '\0', sizeof(buckets
));
227 for (tp
= tokens
; tp
->name
; tp
++) {
228 for (h
= 0, cp
= tp
->name
; *cp
; cp
++)
233 tp
->next
= buckets
[b
]; /* BUG ??? */
238 #define NHASHSIZE 128
239 #define NBUCKET(x) (x & 0x7F)
240 struct node
*nbuckets
[NHASHSIZE
];
243 init_node_hash(struct node
*nodes
)
245 register struct node
*np
, *nextp
;
249 memset((char *) nbuckets
, '\0', sizeof(nbuckets
));
250 for (np
= nodes
; np
;) {
253 for (cp
= np
->parent
; *cp
; cp
++)
255 np
->next
= nbuckets
[NBUCKET(hash
)];
256 nbuckets
[NBUCKET(hash
)] = np
;
262 print_error(const char *string
, const char *token
, int type
)
264 assert(string
!= NULL
);
265 if (type
== ENDOFFILE
)
266 snmplib_debug(0, "%s(EOF): On or around line %d\n", string
, Line
);
268 snmplib_debug(0, "%s(%s): On or around line %d\n", string
, token
, Line
);
270 snmplib_debug(0, "%s: On or around line %d\n", string
, Line
);
274 print_subtree(tree
, count
)
275 struct snmp_mib_tree
*tree
;
278 struct snmp_mib_tree
*tp
;
281 for (i
= 0; i
< count
; i
++)
283 printf("Children of %s:\n", tree
->label
);
285 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
286 for (i
= 0; i
< count
; i
++)
288 printf("%s\n", tp
->label
);
290 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
291 print_subtree(tp
, count
);
296 int translation_table
[40];
299 build_translation_table(void)
303 for (count
= 0; count
< 40; count
++) {
306 translation_table
[count
] = TYPE_OBJID
;
309 translation_table
[count
] = TYPE_OCTETSTR
;
312 translation_table
[count
] = TYPE_INTEGER
;
315 translation_table
[count
] = TYPE_IPADDR
;
318 translation_table
[count
] = TYPE_IPADDR
;
321 translation_table
[count
] = TYPE_COUNTER
;
324 translation_table
[count
] = TYPE_GAUGE
;
327 translation_table
[count
] = TYPE_TIMETICKS
;
330 translation_table
[count
] = TYPE_OPAQUE
;
333 translation_table
[count
] = TYPE_NULL
;
336 translation_table
[count
] = TYPE_OTHER
;
343 * Find all the children of root in the list of nodes. Link them into the
344 * tree and out of the nodes list.
347 do_subtree(struct snmp_mib_tree
*root
, struct node
**nodes
)
349 register struct snmp_mib_tree
*tp
;
350 struct snmp_mib_tree
*peer
= NULL
;
351 register struct node
*np
= NULL
, **headp
= NULL
;
352 struct node
*oldnp
= NULL
, *child_list
= NULL
, *childp
= NULL
;
358 for (cp
= tp
->label
; *cp
; cp
++)
360 headp
= &nbuckets
[NBUCKET(hash
)];
362 * Search each of the nodes for one whose parent is root, and
363 * move each into a separate list.
365 for (np
= *headp
; np
; np
= np
->next
) {
366 if ((*tp
->label
!= *np
->parent
) || strcmp(tp
->label
, np
->parent
)) {
367 if ((*tp
->label
== *np
->label
) && !strcmp(tp
->label
, np
->label
)) {
368 /* if there is another node with the same label, assume that
369 * any children after this point in the list belong to the other node.
370 * This adds some scoping to the table and allows vendors to
371 * reuse names such as "ip".
377 if (child_list
== NULL
) {
378 child_list
= childp
= np
; /* first entry in child list */
383 /* take this node out of the node list */
385 *headp
= np
->next
; /* fix root of node list */
387 oldnp
->next
= np
->next
; /* link around this node */
392 childp
->next
= 0; /* re-terminate list */
394 * Take each element in the child list and place it into the tree.
396 for (np
= child_list
; np
; np
= np
->next
) {
397 tp
= (struct snmp_mib_tree
*) xmalloc(sizeof(struct snmp_mib_tree
));
399 tp
->next_peer
= NULL
;
400 tp
->child_list
= NULL
;
401 strcpy(tp
->label
, np
->label
);
402 tp
->subid
= np
->subid
;
403 tp
->type
= translation_table
[np
->type
];
404 tp
->enums
= np
->enums
;
405 np
->enums
= NULL
; /* so we don't free them later */
406 if (root
->child_list
== NULL
) {
407 root
->child_list
= tp
;
409 peer
->next_peer
= tp
;
412 /* if (tp->type == TYPE_OTHER) */
413 do_subtree(tp
, nodes
); /* recurse on this child if it isn't an end node */
415 /* free all nodes that were copied into tree */
417 for (np
= child_list
; np
; np
= np
->next
) {
429 struct snmp_mib_tree
*
430 build_tree(struct node
*nodes
) {
432 struct snmp_mib_tree
*tp
;
433 int bucket
, nodes_left
= 0;
435 /* build root node */
436 tp
= (struct snmp_mib_tree
*) xmalloc(sizeof(struct snmp_mib_tree
));
438 tp
->next_peer
= NULL
;
439 tp
->child_list
= NULL
;
441 strcpy(tp
->label
, "iso");
444 build_translation_table();
445 /* grow tree from this root node */
446 init_node_hash(nodes
);
447 /* XXX nodes isn't needed in do_subtree() ??? */
448 do_subtree(tp
, &nodes
);
450 print_subtree(tp
, 0);
452 /* If any nodes are left, the tree is probably inconsistent */
453 for (bucket
= 0; bucket
< NHASHSIZE
; bucket
++) {
454 if (nbuckets
[bucket
]) {
460 snmplib_debug(0, "The mib description doesn't seem to be consistent.\n");
461 snmplib_debug(0, "Some nodes couldn't be linked under the \"iso\" tree.\n");
462 snmplib_debug(0, "these nodes are left:\n");
463 for (bucket
= 0; bucket
< NHASHSIZE
; bucket
++) {
464 for (np
= nbuckets
[bucket
]; np
; np
= np
->next
)
465 snmplib_debug(5, "%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
473 * Parses a token from the file. The type of the token parsed is returned,
474 * and the text is placed in the string pointed to by token.
476 static char last
= ' ';
479 get_token(register FILE *fp
, register char *token
)
482 register char *cp
= token
;
483 register int hash
= 0;
484 register struct tok
*tp
;
487 ch
= (unsigned char)last
;
488 /* skip all white space */
489 while (xisspace(ch
) && ch
!= -1) {
498 * Accumulate characters until end of token is found. Then attempt to match this
499 * token as a reserved word. If a match is found, return the type. Else it is
505 if (xisspace(ch
) || ch
== '(' || ch
== ')' ||
506 ch
== '{' || ch
== '}' || ch
== ',' ||
508 if (!xisspace(ch
) && *token
== 0) {
517 for (tp
= buckets
[BUCKET(hash
)]; tp
; tp
= tp
->next
) {
518 if ((tp
->hash
== hash
) && (strcmp(tp
->name
, token
) == 0))
522 if (tp
->token
== CONTINUE
)
526 if (token
[0] == '-' && token
[1] == '-') {
528 while ((ch
= getc(fp
)) != -1)
536 return get_token(fp
, token
);
538 for (cp
= token
; *cp
; cp
++)
549 } while ((ch
= getc(fp
)) != -1);
554 * Takes a list of the form:
555 * { iso org(3) dod(6) 1 }
556 * and creates several nodes, one for each parent-child pair.
557 * Returns NULL on error.
558 * register struct subid *SubOid; an array of subids
559 * int length; the length of the array
562 getoid(register FILE *fp
, register struct subid
*SubOid
, int length
)
569 if ((type
= get_token(fp
, token
)) != LEFTBRACKET
) {
570 print_error("Expected \"{\"", token
, type
);
573 type
= get_token(fp
, token
);
574 for (count
= 0; count
< length
; count
++, SubOid
++) {
577 if (type
== RIGHTBRACKET
) {
579 } else if (type
!= LABEL
&& type
!= NUMBER
) {
580 print_error("Not valid for object identifier", token
, type
);
584 /* this entry has a label */
585 cp
= (char *) xmalloc((unsigned) strlen(token
) + 1);
588 type
= get_token(fp
, token
);
589 if (type
== LEFTPAREN
) {
590 type
= get_token(fp
, token
);
591 if (type
== NUMBER
) {
592 SubOid
->subid
= atoi(token
);
593 if ((type
= get_token(fp
, token
)) != RIGHTPAREN
) {
594 print_error("Unexpected a closing parenthesis", token
, type
);
598 print_error("Expected a number", token
, type
);
605 /* this entry has just an integer sub-identifier */
606 SubOid
->subid
= atoi(token
);
608 type
= get_token(fp
, token
);
615 free_node(struct node
*np
)
617 struct enum_list
*ep
, *tep
;
629 * Parse an entry of the form:
630 * label OBJECT IDENTIFIER ::= { parent 2 }
631 * The "label OBJECT IDENTIFIER" portion has already been parsed.
632 * Returns 0 on error.
635 parse_objectid(FILE *fp
, char *name
) {
639 register struct subid
*op
, *nop
;
641 struct subid SubOid
[32];
642 struct node
*np
, *root
, *oldnp
= NULL
;
644 type
= get_token(fp
, token
);
645 if (type
!= EQUALS
) {
646 print_error("Bad format", token
, type
);
649 if ((length
= getoid(fp
, SubOid
, 32)) != 0) {
650 np
= root
= (struct node
*) xmalloc(sizeof(struct node
));
651 memset((char *) np
, '\0', sizeof(struct node
));
653 * For each parent-child subid pair in the subid array,
654 * create a node and link it into the node list.
656 for (count
= 0, op
= SubOid
, nop
= SubOid
+ 1; count
< (length
- 2); count
++,
658 /* every node must have parent's name and child's name or number */
659 if (op
->label
&& (nop
->label
|| (nop
->subid
!= -1))) {
660 strcpy(np
->parent
, op
->label
);
662 strcpy(np
->label
, nop
->label
);
663 if (nop
->subid
!= -1)
664 np
->subid
= nop
->subid
;
667 /* set up next entry */
668 np
->next
= (struct node
*) xmalloc(sizeof(*np
->next
));
669 memset((char *) np
->next
, '\0', sizeof(struct node
));
674 np
->next
= (struct node
*) NULL
;
676 * The above loop took care of all but the last pair. This pair is taken
677 * care of here. The name for this node is taken from the label for this
679 * np still points to an unused entry.
681 if (count
== (length
- 2)) {
683 strcpy(np
->parent
, op
->label
);
684 strcpy(np
->label
, name
);
685 if (nop
->subid
!= -1)
686 np
->subid
= nop
->subid
;
688 print_error("Warning: This entry is pretty silly", np
->label
, type
);
697 print_error("Missing end of oid", (char *) NULL
, type
);
698 free_node(np
); /* the last node allocated wasn't used */
703 /* free the oid array */
704 for (count
= 0, op
= SubOid
; count
< length
; count
++, op
++) {
711 print_error("Bad object identifier", (char *) NULL
, type
);
717 * Parses an asn type. This structure is ignored by this parser.
718 * Returns NULL on error.
721 parse_asntype(FILE *fp
)
726 type
= get_token(fp
, token
);
727 if (type
!= SEQUENCE
) {
728 print_error("Not a sequence", token
, type
); /* should we handle this */
731 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
732 if (type
== RIGHTBRACKET
)
735 print_error("Expected \"}\"", token
, type
);
740 * Parses an OBJECT TYPE macro.
741 * Returns 0 on error.
744 parse_objecttype(register FILE *fp
, char *name
) {
748 struct subid SubOid
[32];
752 register struct node
*np
= NULL
;
753 register struct enum_list
*ep
= NULL
;
755 type
= get_token(fp
, token
);
756 if (type
!= SYNTAX
) {
757 print_error("Bad format for OBJECT TYPE", token
, type
);
760 np
= (struct node
*) xmalloc(sizeof(struct node
));
763 type
= get_token(fp
, token
);
764 nexttype
= get_token(fp
, nexttoken
);
768 strcpy(syntax
, token
);
769 if (nexttype
== OF
) {
771 strcat(syntax
, nexttoken
);
772 nexttype
= get_token(fp
, nexttoken
);
774 strcat(syntax
, nexttoken
);
775 nexttype
= get_token(fp
, nexttoken
);
779 strcpy(syntax
, token
);
780 if (nexttype
== LEFTBRACKET
) {
781 /* if there is an enumeration list, parse it */
782 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
783 if (type
== RIGHTBRACKET
)
786 /* this is an enumerated label */
787 if (np
->enums
== 0) {
788 ep
= np
->enums
= (struct enum_list
*)
789 xmalloc(sizeof(struct enum_list
));
791 ep
->next
= (struct enum_list
*)
792 xmalloc(sizeof(struct enum_list
));
796 /* a reasonable approximation for the length */
797 ep
->label
= (char *) xmalloc((unsigned) strlen(token
) + 1);
798 strcpy(ep
->label
, token
);
799 type
= get_token(fp
, token
);
800 if (type
!= LEFTPAREN
) {
801 print_error("Expected \"(\"", token
, type
);
805 type
= get_token(fp
, token
);
806 if (type
!= NUMBER
) {
807 print_error("Expected integer", token
, type
);
811 ep
->value
= atoi(token
);
812 type
= get_token(fp
, token
);
813 if (type
!= RIGHTPAREN
) {
814 print_error("Expected \")\"", token
, type
);
820 if (type
== ENDOFFILE
) {
821 print_error("Expected \"}\"", token
, type
);
825 nexttype
= get_token(fp
, nexttoken
);
826 } else if (nexttype
== LEFTPAREN
) {
827 /* ignore the "constrained integer" for now */
828 nexttype
= get_token(fp
, nexttoken
);
829 nexttype
= get_token(fp
, nexttoken
);
830 nexttype
= get_token(fp
, nexttoken
);
843 strcpy(syntax
, token
);
846 print_error("Bad syntax", token
, type
);
850 if (nexttype
!= ACCESS
) {
851 print_error("Should be ACCESS", nexttoken
, nexttype
);
855 type
= get_token(fp
, token
);
856 if (type
!= READONLY
&& type
!= READWRITE
&& type
!= WRITEONLY
857 && type
!= NOACCESS
) {
858 print_error("Bad access type", nexttoken
, nexttype
);
862 type
= get_token(fp
, token
);
863 if (type
!= SNMP_STATUS
) {
864 print_error("Should be STATUS", token
, nexttype
);
868 type
= get_token(fp
, token
);
869 if (type
!= MANDATORY
&& type
!= SNMP_OPTIONAL
&& type
!= OBSOLETE
&& type
!= RECOMMENDED
) {
870 print_error("Bad status", token
, type
);
874 /* Fetch next token. Either:
876 * -> EQUALS (Old MIB format)
877 * -> DESCRIPTION, INDEX (New MIB format)
879 type
= get_token(fp
, token
);
880 if ((type
!= DESCRIPTION
) && (type
!= INDEX
) && (type
!= EQUALS
)) {
881 print_error("Should be DESCRIPTION, INDEX, or EQUALS", token
, nexttype
);
885 if (type
== DESCRIPTION
) {
887 type
= get_token(fp
, token
);
889 print_error("Should be Description open quote", token
, nexttype
);
893 /* Fetch description string */
898 /* skip everything until closing quote */
899 while ((ReadChar
!= '"') && (ReadChar
!= -1)) {
901 if (ReadChar
== '\n')
906 /* ASSERT: Done with description. */
907 type
= get_token(fp
, token
);
909 if ((type
!= INDEX
) && (type
!= EQUALS
)) {
910 print_error("Should be INDEX, or EQUALS", token
, nexttype
);
918 type
= get_token(fp
, token
);
919 if (type
!= LEFTBRACKET
) {
920 print_error("Should be INDEX left brace", token
, type
);
924 /* Fetch description string */
929 /* skip everything until closing quote */
930 while ((ReadChar
!= '}') && (ReadChar
!= -1)) {
932 if (ReadChar
== '\n')
937 /* ASSERT: Done with INDEX. */
938 type
= get_token(fp
, token
);
940 if (type
!= EQUALS
) {
941 print_error("Bad format", token
, type
);
945 length
= getoid(fp
, SubOid
, 32);
946 if (length
> 1 && length
<= 32) {
947 /* just take the last pair in the oid list */
948 if (SubOid
[length
- 2].label
)
949 strncpy(np
->parent
, SubOid
[length
- 2].label
, 64);
950 strcpy(np
->label
, name
);
951 if (SubOid
[length
- 1].subid
!= -1)
952 np
->subid
= SubOid
[length
- 1].subid
;
954 print_error("Warning: This entry is pretty silly", np
->label
, type
);
956 print_error("No end to oid", (char *) NULL
, type
);
961 for (count
= 0; count
< length
; count
++) {
962 if (SubOid
[count
].label
)
963 xfree(SubOid
[count
].label
);
964 SubOid
[count
].label
= 0;
970 * Parses a mib file and returns a linked list of nodes found in the file.
971 * Returns NULL on error.
981 struct node
*np
= NULL
, *root
= NULL
;
985 while (type
!= ENDOFFILE
) {
986 type
= get_token(fp
, token
);
988 if (type
== ENDOFFILE
) {
991 print_error(token
, "is a reserved word", type
);
994 strncpy(name
, token
, 64);
995 type
= get_token(fp
, token
);
996 if (type
== OBJTYPE
) {
998 /* first link in chain */
999 np
= root
= parse_objecttype(fp
, name
);
1001 print_error("Bad parse of object type", (char *) NULL
, type
);
1005 np
->next
= parse_objecttype(fp
, name
);
1006 if (np
->next
== NULL
) {
1007 print_error("Bad parse of objecttype", (char *) NULL
, type
);
1011 /* now find end of chain */
1014 } else if (type
== OBJID
) {
1016 /* first link in chain */
1017 np
= root
= parse_objectid(fp
, name
);
1019 print_error("Bad parse of object id", (char *) NULL
, type
);
1023 np
->next
= parse_objectid(fp
, name
);
1024 if (np
->next
== NULL
) {
1025 print_error("Bad parse of object type", (char *) NULL
, type
);
1029 /* now find end of chain */
1032 } else if (type
== EQUALS
) {
1033 type
= parse_asntype(fp
);
1034 } else if (type
== ENDOFFILE
) {
1037 print_error("Bad operator", (char *) NULL
, type
);
1043 struct enum_list
*ep
;
1045 for (np
= root
; np
; np
= np
->next
) {
1046 printf("%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
1049 printf("Enums: \n");
1050 for (ep
= np
->enums
; ep
; ep
= ep
->next
) {
1051 printf("%s(%d)\n", ep
->label
, ep
->value
);
1060 struct snmp_mib_tree
*
1061 read_mib(char *filename
) {
1064 struct snmp_mib_tree
*tree
;
1068 fp
= fopen(filename
, "r");
1070 snmplib_debug(1, "init_mib: %s: %s\n", filename
, xstrerror());
1074 while ((p
= fgets(mbuf
, 256, fp
)) && strncmp(mbuf
, "DUMMY",
1077 snmplib_debug(0, "Bad MIB version or tag missing, install original!\n");
1080 if (!strcmp(mbuf
, "DUMMY")) {
1081 snmplib_debug(0, "You need to update your MIB!\n");
1086 snmplib_debug(0, "Mib table is bad. Exiting\n");
1089 tree
= build_tree(nodes
);