]>
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"
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 */
127 #define OF 15 /* SEQUENCE OF */
138 #define RECOMMENDED 26
142 #define LEFTBRACKET 30
143 #define RIGHTBRACKET 31
145 #define RIGHTPAREN 33
147 /* For SNMPv2 SMI pseudo-compliance */
148 #define DESCRIPTION 35
153 char *name
; /* token name */
154 int len
; /* length not counting nul */
155 int token
; /* value */
156 int hash
; /* hash of name */
157 struct tok
*next
; /* pointer to next in hash table */
161 struct tok tokens
[] = {
162 { "obsolete", sizeof ("obsolete")-1, OBSOLETE
},
163 { "Opaque", sizeof ("Opaque")-1, OPAQUE
},
164 { "recommended", sizeof("recommended")-1, RECOMMENDED
},
165 { "optional", sizeof ("optional")-1, OPTIONAL
},
166 { "mandatory", sizeof ("mandatory")-1, MANDATORY
},
167 { "current", sizeof ("current")-1, MANDATORY
},
168 { "not-accessible", sizeof ("not-accessible")-1, NOACCESS
},
169 { "write-only", sizeof ("write-only")-1, WRITEONLY
},
170 { "read-write", sizeof ("read-write")-1, READWRITE
},
171 { "TimeTicks", sizeof ("TimeTicks")-1, TIMETICKS
},
172 { "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, OBJID
},
174 * This CONTINUE appends the next word onto OBJECT,
175 * hopefully matching OBJECTIDENTIFIER above.
177 { "OBJECT", sizeof ("OBJECT")-1, CONTINUE
},
178 { "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR
},
179 { "Gauge", sizeof ("Gauge")-1, GAUGE
},
180 { "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR
},
181 { "OCTET", sizeof ("OCTET")-1, -1 },
182 { "OF", sizeof ("OF")-1, OF
},
183 { "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE
},
184 { "NULL", sizeof ("NULL")-1, NUL
},
185 { "IpAddress", sizeof ("IpAddress")-1, IPADDR
},
186 { "INTEGER", sizeof ("INTEGER")-1, INTEGER
},
187 { "Counter", sizeof ("Counter")-1, COUNTER
},
188 { "read-only", sizeof ("read-only")-1, READONLY
},
189 { "ACCESS", sizeof ("ACCESS")-1, ACCESS
},
190 { "MAX-ACCESS", sizeof ("MAX-ACCESS")-1, ACCESS
},
191 { "STATUS", sizeof ("STATUS")-1, STATUS
},
192 { "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX
},
193 { "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE
},
194 { "{", sizeof ("{")-1, LEFTBRACKET
},
195 { "}", sizeof ("}")-1, RIGHTBRACKET
},
196 { "::=", sizeof ("::=")-1, EQUALS
},
197 { "(", sizeof ("(")-1, LEFTPAREN
},
198 { ")", sizeof (")")-1, RIGHTPAREN
},
199 { ",", sizeof (",")-1, COMMA
},
200 { "DESCRIPTION", sizeof ("DESCRIPTION")-1, DESCRIPTION
},
201 { "INDEX", sizeof ("INDEX")-1, INDEX
},
202 { "\"", sizeof ("\"")-1, QUOTE
},
203 { "END", sizeof("END")-1, ENDOFFILE
},
204 /* Hacks for easier MIBFILE coercing */
205 { "read-create", sizeof ("read-create")-1, READWRITE
},
210 #define BUCKET(x) (x & 0x01F)
212 static struct tok
*buckets
[HASHSIZE
];
217 register struct tok
*tp
;
222 memset((char *)buckets
, '\0', sizeof(buckets
));
223 for (tp
= tokens
; tp
->name
; tp
++) {
224 for (h
= 0, cp
= tp
->name
; *cp
; cp
++)
229 tp
->next
= buckets
[b
]; /* BUG ??? */
234 #define NHASHSIZE 128
235 #define NBUCKET(x) (x & 0x7F)
236 struct node
*nbuckets
[NHASHSIZE
];
238 static void init_node_hash(nodes
)
241 register struct node
*np
, *nextp
;
245 memset((char *)nbuckets
, '\0', sizeof(nbuckets
));
246 for(np
= nodes
; np
;){
249 for(cp
= np
->parent
; *cp
; cp
++)
251 np
->next
= nbuckets
[NBUCKET(hash
)];
252 nbuckets
[NBUCKET(hash
)] = np
;
259 print_error(string
, token
, 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];
298 static void build_translation_table(){
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(root
, nodes
)
346 struct snmp_mib_tree
*root
;
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
*
434 struct snmp_mib_tree
*tp
;
435 int bucket
, nodes_left
= 0;
437 /* build root node */
438 tp
= (struct snmp_mib_tree
*)xmalloc(sizeof(struct snmp_mib_tree
));
440 tp
->next_peer
= NULL
;
441 tp
->child_list
= NULL
;
443 strcpy(tp
->label
, "iso");
446 build_translation_table();
447 /* grow tree from this root node */
448 init_node_hash(nodes
);
449 /* XXX nodes isn't needed in do_subtree() ??? */
450 do_subtree(tp
, &nodes
);
452 print_subtree(tp
, 0);
454 /* If any nodes are left, the tree is probably inconsistent */
455 for(bucket
= 0; bucket
< NHASHSIZE
; bucket
++){
456 if (nbuckets
[bucket
]){
462 snmplib_debug(0, "The mib description doesn't seem to be consistent.\n");
463 snmplib_debug(0, "Some nodes couldn't be linked under the \"iso\" tree.\n");
464 snmplib_debug(0, "these nodes are left:\n");
465 for(bucket
= 0; bucket
< NHASHSIZE
; bucket
++){
466 for(np
= nbuckets
[bucket
]; np
; np
= np
->next
)
467 snmplib_debug(0, "%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
= ' ';
484 register char *token
;
487 register char *cp
= token
;
488 register int hash
= 0;
489 register struct tok
*tp
;
493 /* skip all white space */
494 while(isspace(ch
) && ch
!= -1){
503 * Accumulate characters until end of token is found. Then attempt to match this
504 * token as a reserved word. If a match is found, return the type. Else it is
510 if (isspace(ch
) || ch
== '(' || ch
== ')' ||
511 ch
== '{' || ch
== '}' || ch
== ',' ||
513 if (!isspace(ch
) && *token
== 0){
522 for (tp
= buckets
[BUCKET(hash
)]; tp
; tp
= tp
->next
) {
523 if ((tp
->hash
== hash
) && (strcmp(tp
->name
, token
) == 0))
527 if (tp
->token
== CONTINUE
)
532 if (token
[0] == '-' && token
[1] == '-'){
534 while ((ch
= getc(fp
)) != -1)
542 return get_token(fp
, token
);
544 for(cp
= token
; *cp
; cp
++)
555 } while ((ch
= getc(fp
)) != -1);
560 * Takes a list of the form:
561 * { iso org(3) dod(6) 1 }
562 * and creates several nodes, one for each parent-child pair.
563 * Returns NULL on error.
566 getoid(fp
, SubOid
, length
)
568 register struct subid
*SubOid
; /* an array of subids */
569 int length
; /* the length of the array */
576 if ((type
= get_token(fp
, token
)) != LEFTBRACKET
){
577 print_error("Expected \"{\"", token
, type
);
580 type
= get_token(fp
, token
);
581 for(count
= 0; count
< length
; count
++, SubOid
++){
584 if (type
== RIGHTBRACKET
){
586 } else if (type
!= LABEL
&& type
!= NUMBER
){
587 print_error("Not valid for object identifier", token
, type
);
591 /* this entry has a label */
592 cp
= (char *)xmalloc((unsigned)strlen(token
) + 1);
595 type
= get_token(fp
, token
);
596 if (type
== LEFTPAREN
){
597 type
= get_token(fp
, token
);
599 SubOid
->subid
= atoi(token
);
600 if ((type
= get_token(fp
, token
)) != RIGHTPAREN
){
601 print_error("Unexpected a closing parenthesis", token
, type
);
605 print_error("Expected a number", token
, type
);
612 /* this entry has just an integer sub-identifier */
613 SubOid
->subid
= atoi(token
);
615 type
= get_token(fp
, token
);
626 struct enum_list
*ep
, *tep
;
638 * Parse an entry of the form:
639 * label OBJECT IDENTIFIER ::= { parent 2 }
640 * The "label OBJECT IDENTIFIER" portion has already been parsed.
641 * Returns 0 on error.
644 parse_objectid(fp
, name
)
651 register struct subid
*op
, *nop
;
653 struct subid SubOid
[32];
654 struct node
*np
, *root
, *oldnp
= NULL
;
656 type
= get_token(fp
, token
);
658 print_error("Bad format", token
, type
);
661 if ((length
= getoid(fp
, SubOid
, 32)) != 0){
662 np
= root
= (struct node
*)xmalloc(sizeof(struct node
));
663 memset((char *)np
, '\0', sizeof(struct node
));
665 * For each parent-child subid pair in the subid array,
666 * create a node and link it into the node list.
668 for(count
= 0, op
= SubOid
, nop
=SubOid
+1; count
< (length
- 2); count
++,
670 /* every node must have parent's name and child's name or number */
671 if (op
->label
&& (nop
->label
|| (nop
->subid
!= -1))){
672 strcpy(np
->parent
, op
->label
);
674 strcpy(np
->label
, nop
->label
);
675 if (nop
->subid
!= -1)
676 np
->subid
= nop
->subid
;
679 /* set up next entry */
680 np
->next
= (struct node
*)xmalloc(sizeof(*np
->next
));
681 memset((char *)np
->next
, '\0', sizeof(struct node
));
686 np
->next
= (struct node
*)NULL
;
688 * The above loop took care of all but the last pair. This pair is taken
689 * care of here. The name for this node is taken from the label for this
691 * np still points to an unused entry.
693 if (count
== (length
- 2)){
695 strcpy(np
->parent
, op
->label
);
696 strcpy(np
->label
, name
);
697 if (nop
->subid
!= -1)
698 np
->subid
= nop
->subid
;
700 print_error("Warning: This entry is pretty silly", np
->label
, type
);
709 print_error("Missing end of oid", (char *)NULL
, type
);
710 free_node(np
); /* the last node allocated wasn't used */
715 /* free the oid array */
716 for(count
= 0, op
= SubOid
; count
< length
; count
++, op
++){
723 print_error("Bad object identifier", (char *)NULL
, type
);
729 * Parses an asn type. This structure is ignored by this parser.
730 * Returns NULL on error.
739 type
= get_token(fp
, token
);
740 if (type
!= SEQUENCE
){
741 print_error("Not a sequence", token
, type
); /* should we handle this */
744 while((type
= get_token(fp
, token
)) != ENDOFFILE
){
745 if (type
== RIGHTBRACKET
)
748 print_error("Expected \"}\"", token
, type
);
753 * Parses an OBJECT TYPE macro.
754 * Returns 0 on error.
757 parse_objecttype(fp
, name
)
764 struct subid SubOid
[32];
768 register struct node
*np
=NULL
;
769 register struct enum_list
*ep
=NULL
;
771 type
= get_token(fp
, token
);
773 print_error("Bad format for OBJECT TYPE", token
, type
);
776 np
= (struct node
*)xmalloc(sizeof(struct node
));
779 type
= get_token(fp
, token
);
780 nexttype
= get_token(fp
, nexttoken
);
784 strcpy(syntax
, token
);
787 strcat(syntax
, nexttoken
);
788 nexttype
= get_token(fp
, nexttoken
);
790 strcat(syntax
, nexttoken
);
791 nexttype
= get_token(fp
, nexttoken
);
795 strcpy(syntax
, token
);
796 if (nexttype
== LEFTBRACKET
) {
797 /* if there is an enumeration list, parse it */
798 while((type
= get_token(fp
, token
)) != ENDOFFILE
){
799 if (type
== RIGHTBRACKET
)
802 /* this is an enumerated label */
804 ep
= np
->enums
= (struct enum_list
*)
805 xmalloc(sizeof(struct enum_list
));
807 ep
->next
= (struct enum_list
*)
808 xmalloc(sizeof(struct enum_list
));
812 /* a reasonable approximation for the length */
813 ep
->label
= (char *)xmalloc((unsigned)strlen(token
) + 1);
814 strcpy(ep
->label
, token
);
815 type
= get_token(fp
, token
);
816 if (type
!= LEFTPAREN
){
817 print_error("Expected \"(\"", token
, type
);
821 type
= get_token(fp
, token
);
823 print_error("Expected integer", token
, type
);
827 ep
->value
= atoi(token
);
828 type
= get_token(fp
, token
);
829 if (type
!= RIGHTPAREN
){
830 print_error("Expected \")\"", token
, type
);
836 if (type
== ENDOFFILE
){
837 print_error("Expected \"}\"", token
, type
);
841 nexttype
= get_token(fp
, nexttoken
);
842 } else if (nexttype
== LEFTPAREN
){
843 /* ignore the "constrained integer" for now */
844 nexttype
= get_token(fp
, nexttoken
);
845 nexttype
= get_token(fp
, nexttoken
);
846 nexttype
= get_token(fp
, nexttoken
);
859 strcpy(syntax
, token
);
862 print_error("Bad syntax", token
, type
);
866 if (nexttype
!= ACCESS
){
867 print_error("Should be ACCESS", nexttoken
, nexttype
);
871 type
= get_token(fp
, token
);
872 if (type
!= READONLY
&& type
!= READWRITE
&& type
!= WRITEONLY
873 && type
!= NOACCESS
){
874 print_error("Bad access type", nexttoken
, nexttype
);
878 type
= get_token(fp
, token
);
880 print_error("Should be STATUS", token
, nexttype
);
884 type
= get_token(fp
, token
);
885 if (type
!= MANDATORY
&& type
!= OPTIONAL
&& type
!= OBSOLETE
&& type
!= RECOMMENDED
){
886 print_error("Bad status", token
, type
);
890 /* Fetch next token. Either:
892 * -> EQUALS (Old MIB format)
893 * -> DESCRIPTION, INDEX (New MIB format)
895 type
= get_token(fp
, token
);
896 if ((type
!= DESCRIPTION
) && (type
!= INDEX
) && (type
!= EQUALS
)) {
897 print_error("Should be DESCRIPTION, INDEX, or EQUALS", token
, nexttype
);
902 if (type
== DESCRIPTION
) {
904 type
= get_token(fp
, token
);
906 print_error("Should be Description open quote", token
, nexttype
);
911 /* Fetch description string */
916 /* skip everything until closing quote */
917 while((ReadChar
!= '"') && (ReadChar
!= -1)) {
919 if (ReadChar
== '\n')
924 /* ASSERT: Done with description. */
925 type
= get_token(fp
, token
);
928 if ((type
!= INDEX
) && (type
!= EQUALS
)) {
929 print_error("Should be INDEX, or EQUALS", token
, nexttype
);
938 type
= get_token(fp
, token
);
939 if (type
!= LEFTBRACKET
){
940 print_error("Should be INDEX left brace", token
, type
);
945 /* Fetch description string */
950 /* skip everything until closing quote */
951 while((ReadChar
!= '}') && (ReadChar
!= -1)) {
953 if (ReadChar
== '\n')
958 /* ASSERT: Done with INDEX. */
959 type
= get_token(fp
, token
);
963 print_error("Bad format", token
, type
);
967 length
= getoid(fp
, SubOid
, 32);
968 if (length
> 1 && length
<= 32){
969 /* just take the last pair in the oid list */
970 if (SubOid
[length
- 2].label
)
971 strncpy(np
->parent
, SubOid
[length
- 2].label
, 64);
972 strcpy(np
->label
, name
);
973 if (SubOid
[length
- 1].subid
!= -1)
974 np
->subid
= SubOid
[length
- 1].subid
;
976 print_error("Warning: This entry is pretty silly", np
->label
, type
);
978 print_error("No end to oid", (char *)NULL
, type
);
983 for(count
= 0; count
< length
; count
++){
984 if (SubOid
[count
].label
)
985 xfree(SubOid
[count
].label
);
986 SubOid
[count
].label
= 0;
993 * Parses a mib file and returns a linked list of nodes found in the file.
994 * Returns NULL on error.
1006 struct node
*np
=NULL
, *root
= NULL
;
1010 while(type
!= ENDOFFILE
){
1011 type
= get_token(fp
, token
);
1013 if (type
== ENDOFFILE
){
1016 print_error(token
, "is a reserved word", type
);
1019 strncpy(name
, token
, 64);
1020 type
= get_token(fp
, token
);
1021 if (type
== OBJTYPE
){
1023 /* first link in chain */
1024 np
= root
= parse_objecttype(fp
, name
);
1026 print_error("Bad parse of object type", (char *)NULL
, type
);
1030 np
->next
= parse_objecttype(fp
, name
);
1031 if (np
->next
== NULL
){
1032 print_error("Bad parse of objecttype", (char *)NULL
, type
);
1036 /* now find end of chain */
1039 } else if (type
== OBJID
){
1041 /* first link in chain */
1042 np
= root
= parse_objectid(fp
, name
);
1044 print_error("Bad parse of object id", (char *)NULL
, type
);
1048 np
->next
= parse_objectid(fp
, name
);
1049 if (np
->next
== NULL
){
1050 print_error("Bad parse of object type", (char *)NULL
, type
);
1054 /* now find end of chain */
1057 } else if (type
== EQUALS
){
1058 type
= parse_asntype(fp
);
1059 } else if (type
== ENDOFFILE
){
1062 print_error("Bad operator", (char *)NULL
, type
);
1068 struct enum_list
*ep
;
1070 for(np
= root
; np
; np
= np
->next
){
1071 printf("%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
1074 printf("Enums: \n");
1075 for(ep
= np
->enums
; ep
; ep
= ep
->next
){
1076 printf("%s(%d)\n", ep
->label
, ep
->value
);
1085 struct snmp_mib_tree
*
1091 struct snmp_mib_tree
*tree
;
1095 fp
= fopen(filename
, "r");
1097 snmplib_debug(0, "failed to open MIB file: '%s'\n", filename
);
1102 while ( (p
=fgets(mbuf
, 256, fp
)) && strncmp(&mbuf
[4], CURRENT_MIB_VERSION
,
1103 strlen(CURRENT_MIB_VERSION
)));
1105 snmplib_debug(0, "Bad MIB version or tag missing, install original!\n");
1109 if (!strcmp(mbuf
, CURRENT_MIB_VERSION
)) {
1110 snmplib_debug(0, "You need to update your MIB!\n");
1115 snmplib_debug(0, "Mib table is bad. Exiting\n");
1118 tree
= build_tree(nodes
);