]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/snmplib/parse.c
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /***********************************************************
10 Copyright 1989 by Carnegie Mellon University
14 Permission to use, copy, modify, and distribute this software and its
15 documentation for any purpose and without fee is hereby granted,
16 provided that the above copyright notice appear in all copies and that
17 both that copyright notice and this permission notice appear in
18 supporting documentation, and that the name of CMU not be
19 used in advertising or publicity pertaining to distribution of the
20 software without specific, written prior permission.
22 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
23 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
24 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
25 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
26 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
27 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29 ******************************************************************/
33 #include "cache_snmp.h"
35 #include "snmp_debug.h"
37 #include "snmp_vars.h"
47 #include <sys/types.h>
53 #include <gnumalloc.h>
70 #include <sys/socket.h>
73 #include <netinet/in.h>
76 #include <arpa/inet.h>
92 * This is one element of an object identifier with either an integer subidentifier,
93 * or a textual string label, or both.
94 * The subid is -1 if not present, and label is NULL if not present.
102 * A linked list of nodes.
106 char label
[64]; /* This node's (unique) textual name */
107 u_int subid
; /* This node's integer subidentifier */
108 char parent
[64]; /* The parent's textual name */
109 int type
; /* The type of object this represents */
110 struct enum_list
*enums
; /* (optional) list of enumerated integers (otherwise NULL) */
115 /* types of tokens */
131 #define SNMP_OPAQUE 12
134 #define OF 15 /* SEQUENCE OF */
142 #define SNMP_STATUS 22
144 #define SNMP_OPTIONAL 24
146 #define RECOMMENDED 26
150 #define LEFTBRACKET 30
151 #define RIGHTBRACKET 31
153 #define RIGHTPAREN 33
155 /* For SNMPv2 SMI pseudo-compliance */
156 #define DESCRIPTION 35
161 const char *name
; /* token name */
162 int len
; /* length not counting nul */
163 int token
; /* value */
164 int hash
; /* hash of name */
165 struct tok
*next
; /* pointer to next in hash table */
168 struct tok tokens
[] = {
169 {"obsolete", sizeof("obsolete") - 1, OBSOLETE
},
170 {"Opaque", sizeof("Opaque") - 1, SNMP_OPAQUE
},
171 {"recommended", sizeof("recommended") - 1, RECOMMENDED
},
172 {"optional", sizeof("optional") - 1, SNMP_OPTIONAL
},
173 {"mandatory", sizeof("mandatory") - 1, MANDATORY
},
174 {"current", sizeof("current") - 1, MANDATORY
},
175 {"not-accessible", sizeof("not-accessible") - 1, NOACCESS
},
176 {"write-only", sizeof("write-only") - 1, WRITEONLY
},
177 {"read-write", sizeof("read-write") - 1, READWRITE
},
178 {"TimeTicks", sizeof("TimeTicks") - 1, TIMETICKS
},
179 {"OBJECTIDENTIFIER", sizeof("OBJECTIDENTIFIER") - 1, OBJID
},
181 * This CONTINUE appends the next word onto OBJECT,
182 * hopefully matching OBJECTIDENTIFIER above.
184 {"OBJECT", sizeof("OBJECT") - 1, CONTINUE
},
185 {"NetworkAddress", sizeof("NetworkAddress") - 1, NETADDR
},
186 {"Gauge", sizeof("Gauge") - 1, GAUGE
},
187 {"OCTETSTRING", sizeof("OCTETSTRING") - 1, OCTETSTR
},
188 {"OCTET", sizeof("OCTET") - 1, -1},
189 {"OF", sizeof("OF") - 1, OF
},
190 {"SEQUENCE", sizeof("SEQUENCE") - 1, SEQUENCE
},
191 {"NULL", sizeof("NULL") - 1, NUL
},
192 {"IpAddress", sizeof("IpAddress") - 1, IPADDR
},
193 {"INTEGER", sizeof("INTEGER") - 1, INTEGER
},
194 {"Counter", sizeof("Counter") - 1, COUNTER
},
195 {"read-only", sizeof("read-only") - 1, READONLY
},
196 {"ACCESS", sizeof("ACCESS") - 1, ACCESS
},
197 {"MAX-ACCESS", sizeof("MAX-ACCESS") - 1, ACCESS
},
198 {"STATUS", sizeof("STATUS") - 1, SNMP_STATUS
},
199 {"SYNTAX", sizeof("SYNTAX") - 1, SYNTAX
},
200 {"OBJECT-TYPE", sizeof("OBJECT-TYPE") - 1, OBJTYPE
},
201 {"{", sizeof("{") - 1, LEFTBRACKET
},
202 {"}", sizeof("}") - 1, RIGHTBRACKET
},
203 {"::=", sizeof("::=") - 1, EQUALS
},
204 {"(", sizeof("(") - 1, LEFTPAREN
},
205 {")", sizeof(")") - 1, RIGHTPAREN
},
206 {",", sizeof(",") - 1, COMMA
},
207 {"DESCRIPTION", sizeof("DESCRIPTION") - 1, DESCRIPTION
},
208 {"INDEX", sizeof("INDEX") - 1, INDEX
},
209 {"\"", sizeof("\"") - 1, QUOTE
},
210 {"END", sizeof("END") - 1, ENDOFFILE
},
211 /* Hacks for easier MIBFILE coercing */
212 {"read-create", sizeof("read-create") - 1, READWRITE
},
217 #define BUCKET(x) (x & 0x01F)
219 static struct tok
*buckets
[HASHSIZE
];
224 register struct tok
*tp
;
225 register const char *cp
;
229 memset((char *) buckets
, '\0', sizeof(buckets
));
230 for (tp
= tokens
; tp
->name
; tp
++) {
231 for (h
= 0, cp
= tp
->name
; *cp
; cp
++)
236 tp
->next
= buckets
[b
]; /* BUG ??? */
241 #define NHASHSIZE 128
242 #define NBUCKET(x) (x & 0x7F)
243 struct node
*nbuckets
[NHASHSIZE
];
246 init_node_hash(struct node
*nodes
)
248 register struct node
*np
, *nextp
;
252 memset((char *) nbuckets
, '\0', sizeof(nbuckets
));
253 for (np
= nodes
; np
;) {
256 for (cp
= np
->parent
; *cp
; cp
++)
258 np
->next
= nbuckets
[NBUCKET(hash
)];
259 nbuckets
[NBUCKET(hash
)] = np
;
265 print_error(const char *string
, const char *token
, int type
)
267 assert(string
!= NULL
);
268 if (type
== ENDOFFILE
)
269 snmplib_debug(0, "%s(EOF): On or around line %d\n", string
, Line
);
271 snmplib_debug(0, "%s(%s): On or around line %d\n", string
, token
, Line
);
273 snmplib_debug(0, "%s: On or around line %d\n", string
, Line
);
277 print_subtree(tree
, count
)
278 struct snmp_mib_tree
*tree
;
281 struct snmp_mib_tree
*tp
;
284 for (i
= 0; i
< count
; i
++)
286 printf("Children of %s:\n", tree
->label
);
288 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
289 for (i
= 0; i
< count
; i
++)
291 printf("%s\n", tp
->label
);
293 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
294 print_subtree(tp
, count
);
299 int translation_table
[40];
302 build_translation_table(void)
306 for (count
= 0; count
< 40; count
++) {
309 translation_table
[count
] = TYPE_OBJID
;
312 translation_table
[count
] = TYPE_OCTETSTR
;
315 translation_table
[count
] = TYPE_INTEGER
;
318 translation_table
[count
] = TYPE_IPADDR
;
321 translation_table
[count
] = TYPE_IPADDR
;
324 translation_table
[count
] = TYPE_COUNTER
;
327 translation_table
[count
] = TYPE_GAUGE
;
330 translation_table
[count
] = TYPE_TIMETICKS
;
333 translation_table
[count
] = TYPE_OPAQUE
;
336 translation_table
[count
] = TYPE_NULL
;
339 translation_table
[count
] = TYPE_OTHER
;
346 * Find all the children of root in the list of nodes. Link them into the
347 * tree and out of the nodes list.
350 do_subtree(struct snmp_mib_tree
*root
, struct node
**nodes
)
352 register struct snmp_mib_tree
*tp
;
353 struct snmp_mib_tree
*peer
= NULL
;
354 register struct node
*np
= NULL
, **headp
= NULL
;
355 struct node
*oldnp
= NULL
, *child_list
= NULL
, *childp
= NULL
;
361 for (cp
= tp
->label
; *cp
; cp
++)
363 headp
= &nbuckets
[NBUCKET(hash
)];
365 * Search each of the nodes for one whose parent is root, and
366 * move each into a separate list.
368 for (np
= *headp
; np
; np
= np
->next
) {
369 if ((*tp
->label
!= *np
->parent
) || strcmp(tp
->label
, np
->parent
)) {
370 if ((*tp
->label
== *np
->label
) && !strcmp(tp
->label
, np
->label
)) {
371 /* if there is another node with the same label, assume that
372 * any children after this point in the list belong to the other node.
373 * This adds some scoping to the table and allows vendors to
374 * reuse names such as "ip".
380 if (child_list
== NULL
) {
381 child_list
= childp
= np
; /* first entry in child list */
386 /* take this node out of the node list */
388 *headp
= np
->next
; /* fix root of node list */
390 oldnp
->next
= np
->next
; /* link around this node */
395 childp
->next
= 0; /* re-terminate list */
397 * Take each element in the child list and place it into the tree.
399 for (np
= child_list
; np
; np
= np
->next
) {
400 tp
= (struct snmp_mib_tree
*) xmalloc(sizeof(struct snmp_mib_tree
));
402 tp
->next_peer
= NULL
;
403 tp
->child_list
= NULL
;
404 strcpy(tp
->label
, np
->label
);
405 tp
->subid
= np
->subid
;
406 tp
->type
= translation_table
[np
->type
];
407 tp
->enums
= np
->enums
;
408 np
->enums
= NULL
; /* so we don't free them later */
409 if (root
->child_list
== NULL
) {
410 root
->child_list
= tp
;
412 peer
->next_peer
= tp
;
415 /* if (tp->type == TYPE_OTHER) */
416 do_subtree(tp
, nodes
); /* recurse on this child if it isn't an end node */
418 /* free all nodes that were copied into tree */
420 for (np
= child_list
; np
; np
= np
->next
) {
432 struct snmp_mib_tree
*
433 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
,
476 * Parses a token from the file. The type of the token parsed is returned,
477 * and the text is placed in the string pointed to by token.
479 static char last
= ' ';
482 get_token(register FILE *fp
, register char *token
)
485 register char *cp
= token
;
486 register int hash
= 0;
487 register struct tok
*tp
;
490 ch
= (unsigned char)last
;
491 /* skip all white space */
492 while (xisspace(ch
) && ch
!= -1) {
501 * Accumulate characters until end of token is found. Then attempt to match this
502 * token as a reserved word. If a match is found, return the type. Else it is
508 if (xisspace(ch
) || ch
== '(' || ch
== ')' ||
509 ch
== '{' || ch
== '}' || ch
== ',' ||
511 if (!xisspace(ch
) && *token
== 0) {
520 for (tp
= buckets
[BUCKET(hash
)]; tp
; tp
= tp
->next
) {
521 if ((tp
->hash
== hash
) && (strcmp(tp
->name
, token
) == 0))
525 if (tp
->token
== CONTINUE
)
529 if (token
[0] == '-' && token
[1] == '-') {
531 while ((ch
= getc(fp
)) != -1)
539 return get_token(fp
, token
);
541 for (cp
= token
; *cp
; cp
++)
552 } while ((ch
= getc(fp
)) != -1);
557 * Takes a list of the form:
558 * { iso org(3) dod(6) 1 }
559 * and creates several nodes, one for each parent-child pair.
560 * Returns NULL on error.
561 * register struct subid *SubOid; an array of subids
562 * int length; the length of the array
565 getoid(register FILE *fp
, register struct subid
*SubOid
, int length
)
572 if ((type
= get_token(fp
, token
)) != LEFTBRACKET
) {
573 print_error("Expected \"{\"", token
, type
);
576 type
= get_token(fp
, token
);
577 for (count
= 0; count
< length
; count
++, SubOid
++) {
580 if (type
== RIGHTBRACKET
) {
582 } else if (type
!= LABEL
&& type
!= NUMBER
) {
583 print_error("Not valid for object identifier", token
, type
);
587 /* this entry has a label */
588 cp
= (char *) xmalloc((unsigned) strlen(token
) + 1);
591 type
= get_token(fp
, token
);
592 if (type
== LEFTPAREN
) {
593 type
= get_token(fp
, token
);
594 if (type
== NUMBER
) {
595 SubOid
->subid
= atoi(token
);
596 if ((type
= get_token(fp
, token
)) != RIGHTPAREN
) {
597 print_error("Unexpected a closing parenthesis", token
, type
);
601 print_error("Expected a number", token
, type
);
608 /* this entry has just an integer sub-identifier */
609 SubOid
->subid
= atoi(token
);
611 type
= get_token(fp
, token
);
618 free_node(struct node
*np
)
620 struct enum_list
*ep
, *tep
;
632 free_node_list(struct node
*nl
)
635 struct node
*t
= nl
->next
;
642 * Parse an entry of the form:
643 * label OBJECT IDENTIFIER ::= { parent 2 }
644 * The "label OBJECT IDENTIFIER" portion has already been parsed.
645 * Returns 0 on error.
648 parse_objectid(FILE *fp
, char *name
) {
652 register struct subid
*op
, *nop
;
654 struct subid SubOid
[32];
655 struct node
*np
, *root
, *oldnp
= NULL
;
657 type
= get_token(fp
, token
);
658 if (type
!= EQUALS
) {
659 print_error("Bad format", token
, type
);
662 if ((length
= getoid(fp
, SubOid
, 32)) != 0) {
663 np
= root
= (struct node
*) xmalloc(sizeof(struct node
));
664 memset((char *) np
, '\0', sizeof(struct node
));
666 * For each parent-child subid pair in the subid array,
667 * create a node and link it into the node list.
669 for (count
= 0, op
= SubOid
, nop
= SubOid
+ 1; count
< (length
- 2); count
++,
671 /* every node must have parent's name and child's name or number */
672 if (op
->label
&& (nop
->label
|| (nop
->subid
!= -1))) {
673 strncpy(np
->parent
, op
->label
, sizeof(np
->parent
) - 1);
675 strncpy(np
->label
, nop
->label
, sizeof(np
->label
) - 1);
676 if (nop
->subid
!= -1)
677 np
->subid
= nop
->subid
;
680 /* set up next entry */
681 np
->next
= (struct node
*) xmalloc(sizeof(*np
->next
));
682 memset((char *) np
->next
, '\0', sizeof(struct node
));
687 np
->next
= (struct node
*) NULL
;
689 * The above loop took care of all but the last pair. This pair is taken
690 * care of here. The name for this node is taken from the label for this
692 * np still points to an unused entry.
694 if (count
== (length
- 2)) {
696 strncpy(np
->parent
, op
->label
, sizeof(np
->parent
)-1);
697 strncpy(np
->label
, name
, sizeof(np
->label
)-1);
698 if (nop
->subid
!= -1)
699 np
->subid
= nop
->subid
;
701 print_error("Warning: This entry is pretty silly", np
->label
, type
);
707 free_node_list(root
); // we need to clear the newly allocated list
712 print_error("Missing end of oid", (char *) NULL
, type
);
713 free_node_list(root
); // we need to clear the newly allocated list
718 /* free the oid array */
719 for (count
= 0, op
= SubOid
; count
< length
; count
++, op
++) {
726 print_error("Bad object identifier", (char *) NULL
, type
);
732 * Parses an asn type. This structure is ignored by this parser.
733 * Returns NULL on error.
736 parse_asntype(FILE *fp
)
741 type
= get_token(fp
, token
);
742 if (type
!= SEQUENCE
) {
743 print_error("Not a sequence", token
, type
); /* should we handle this */
746 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
747 if (type
== RIGHTBRACKET
)
750 print_error("Expected \"}\"", token
, type
);
755 * Parses an OBJECT TYPE macro.
756 * Returns 0 on error.
759 parse_objecttype(register FILE *fp
, char *name
) {
763 struct subid SubOid
[32];
767 register struct node
*np
= NULL
;
768 register struct enum_list
*ep
= NULL
;
770 type
= get_token(fp
, token
);
771 if (type
!= SYNTAX
) {
772 print_error("Bad format for OBJECT TYPE", token
, type
);
775 np
= (struct node
*) xmalloc(sizeof(struct node
));
778 type
= get_token(fp
, token
);
779 nexttype
= get_token(fp
, nexttoken
);
783 strcpy(syntax
, token
);
784 if (nexttype
== OF
) {
786 strcat(syntax
, nexttoken
);
787 nexttype
= get_token(fp
, nexttoken
);
789 strcat(syntax
, nexttoken
);
790 nexttype
= get_token(fp
, nexttoken
);
794 strcpy(syntax
, token
);
795 if (nexttype
== LEFTBRACKET
) {
796 /* if there is an enumeration list, parse it */
797 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
798 if (type
== RIGHTBRACKET
)
801 /* this is an enumerated label */
802 if (np
->enums
== 0) {
803 ep
= np
->enums
= (struct enum_list
*)
804 xmalloc(sizeof(struct enum_list
));
806 ep
->next
= (struct enum_list
*)
807 xmalloc(sizeof(struct enum_list
));
811 /* a reasonable approximation for the length */
812 ep
->label
= (char *) xmalloc((unsigned) strlen(token
) + 1);
813 strcpy(ep
->label
, token
);
814 type
= get_token(fp
, token
);
815 if (type
!= LEFTPAREN
) {
816 print_error("Expected \"(\"", token
, type
);
820 type
= get_token(fp
, token
);
821 if (type
!= NUMBER
) {
822 print_error("Expected integer", token
, type
);
826 ep
->value
= atoi(token
);
827 type
= get_token(fp
, token
);
828 if (type
!= RIGHTPAREN
) {
829 print_error("Expected \")\"", token
, type
);
835 if (type
== ENDOFFILE
) {
836 print_error("Expected \"}\"", token
, type
);
840 nexttype
= get_token(fp
, nexttoken
);
841 } else if (nexttype
== LEFTPAREN
) {
842 /* ignore the "constrained integer" for now */
843 nexttype
= get_token(fp
, nexttoken
);
844 nexttype
= get_token(fp
, nexttoken
);
845 nexttype
= get_token(fp
, nexttoken
);
858 strcpy(syntax
, token
);
861 print_error("Bad syntax", token
, type
);
865 if (nexttype
!= ACCESS
) {
866 print_error("Should be ACCESS", nexttoken
, nexttype
);
870 type
= get_token(fp
, token
);
871 if (type
!= READONLY
&& type
!= READWRITE
&& type
!= WRITEONLY
872 && type
!= NOACCESS
) {
873 print_error("Bad access type", nexttoken
, nexttype
);
877 type
= get_token(fp
, token
);
878 if (type
!= SNMP_STATUS
) {
879 print_error("Should be STATUS", token
, nexttype
);
883 type
= get_token(fp
, token
);
884 if (type
!= MANDATORY
&& type
!= SNMP_OPTIONAL
&& type
!= OBSOLETE
&& type
!= RECOMMENDED
) {
885 print_error("Bad status", token
, type
);
889 /* Fetch next token. Either:
891 * -> EQUALS (Old MIB format)
892 * -> DESCRIPTION, INDEX (New MIB format)
894 type
= get_token(fp
, token
);
895 if ((type
!= DESCRIPTION
) && (type
!= INDEX
) && (type
!= EQUALS
)) {
896 print_error("Should be DESCRIPTION, INDEX, or EQUALS", token
, nexttype
);
900 if (type
== DESCRIPTION
) {
902 type
= get_token(fp
, token
);
904 print_error("Should be Description open quote", token
, nexttype
);
908 /* Fetch description string */
913 /* skip everything until closing quote */
914 while ((ReadChar
!= '"') && (ReadChar
!= -1)) {
916 if (ReadChar
== '\n')
921 /* ASSERT: Done with description. */
922 type
= get_token(fp
, token
);
924 if ((type
!= INDEX
) && (type
!= EQUALS
)) {
925 print_error("Should be INDEX, or EQUALS", token
, nexttype
);
933 type
= get_token(fp
, token
);
934 if (type
!= LEFTBRACKET
) {
935 print_error("Should be INDEX left brace", token
, type
);
939 /* Fetch description string */
944 /* skip everything until closing quote */
945 while ((ReadChar
!= '}') && (ReadChar
!= -1)) {
947 if (ReadChar
== '\n')
952 /* ASSERT: Done with INDEX. */
953 type
= get_token(fp
, token
);
955 if (type
!= EQUALS
) {
956 print_error("Bad format", token
, type
);
960 length
= getoid(fp
, SubOid
, 32);
961 if (length
> 1 && length
<= 32) {
962 /* just take the last pair in the oid list */
963 if (SubOid
[length
- 2].label
) {
964 strncpy(np
->parent
, SubOid
[length
- 2].label
, 64);
965 np
->parent
[63] = '\0';
967 strncpy(np
->label
, name
, sizeof(np
->label
));
968 np
->label
[sizeof(np
->label
) - 1] = '\0';
969 if (SubOid
[length
- 1].subid
!= -1)
970 np
->subid
= SubOid
[length
- 1].subid
;
972 print_error("Warning: This entry is pretty silly", np
->label
, type
);
974 print_error("No end to oid", (char *) NULL
, type
);
979 for (count
= 0; count
< length
; count
++) {
980 if (SubOid
[count
].label
)
981 xfree(SubOid
[count
].label
);
982 SubOid
[count
].label
= 0;
988 * Parses a mib file and returns a linked list of nodes found in the file.
989 * Returns NULL on error.
999 struct node
*np
= NULL
, *root
= NULL
;
1003 while (type
!= ENDOFFILE
) {
1004 type
= get_token(fp
, token
);
1005 if (type
!= LABEL
) {
1006 if (type
== ENDOFFILE
) {
1009 print_error(token
, "is a reserved word", type
);
1010 free_node_list(root
);
1013 strncpy(name
, token
, 64);
1015 type
= get_token(fp
, token
);
1016 if (type
== OBJTYPE
) {
1018 /* first link in chain */
1019 np
= root
= parse_objecttype(fp
, name
);
1021 print_error("Bad parse of object type", (char *) NULL
, type
);
1025 np
->next
= parse_objecttype(fp
, name
);
1026 if (np
->next
== NULL
) {
1027 print_error("Bad parse of objecttype", (char *) NULL
, type
);
1028 free_node_list(root
);
1032 /* now find end of chain */
1035 } else if (type
== OBJID
) {
1037 /* first link in chain */
1038 np
= root
= parse_objectid(fp
, name
);
1040 print_error("Bad parse of object id", (char *) NULL
, type
);
1044 np
->next
= parse_objectid(fp
, name
);
1045 if (np
->next
== NULL
) {
1046 print_error("Bad parse of object type", (char *) NULL
, type
);
1047 free_node_list(root
);
1051 /* now find end of chain */
1054 } else if (type
== EQUALS
) {
1055 type
= parse_asntype(fp
);
1056 } else if (type
== ENDOFFILE
) {
1059 print_error("Bad operator", (char *) NULL
, type
);
1060 free_node_list(root
);
1066 struct enum_list
*ep
;
1068 for (np
= root
; np
; np
= np
->next
) {
1069 printf("%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
1072 printf("Enums: \n");
1073 for (ep
= np
->enums
; ep
; ep
= ep
->next
) {
1074 printf("%s(%d)\n", ep
->label
, ep
->value
);
1083 struct snmp_mib_tree
*
1084 read_mib(char *filename
) {
1087 struct snmp_mib_tree
*tree
;
1091 fp
= fopen(filename
, "r");
1093 snmplib_debug(1, "init_mib: %s: %s\n", filename
, xstrerror());
1097 while ((p
= fgets(mbuf
, 256, fp
)) && strncmp(mbuf
, "DUMMY",
1100 snmplib_debug(0, "Bad MIB version or tag missing, install original!\n");
1104 if (!strcmp(mbuf
, "DUMMY")) {
1105 snmplib_debug(0, "You need to update your MIB!\n");
1112 snmplib_debug(0, "Mib table is bad. Exiting\n");
1115 tree
= build_tree(nodes
);