]>
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 */
130 #define OF 15 /* SEQUENCE OF */
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 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
[] = {
166 { "obsolete", sizeof ("obsolete")-1, OBSOLETE
},
167 { "Opaque", sizeof ("Opaque")-1, OPAQUE
},
168 { "recommended", sizeof("recommended")-1, RECOMMENDED
},
169 { "optional", sizeof ("optional")-1, 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, 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
;
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
];
242 static void init_node_hash(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
;
263 print_error(string
, token
, type
)
268 assert(string
!= NULL
);
269 if (type
== ENDOFFILE
)
270 snmplib_debug(0, "%s(EOF): On or around line %d\n", string
, Line
);
272 snmplib_debug(0, "%s(%s): On or around line %d\n", string
, token
, Line
);
274 snmplib_debug(0, "%s: On or around line %d\n", string
, Line
);
278 print_subtree(tree
, count
)
279 struct snmp_mib_tree
*tree
;
282 struct snmp_mib_tree
*tp
;
285 for(i
= 0; i
< count
; i
++)
287 printf("Children of %s:\n", tree
->label
);
289 for(tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
){
290 for(i
= 0; i
< count
; i
++)
292 printf("%s\n", tp
->label
);
294 for(tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
){
295 print_subtree(tp
, count
);
300 int translation_table
[40];
302 static void build_translation_table(){
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(root
, nodes
)
350 struct snmp_mib_tree
*root
;
353 register struct snmp_mib_tree
*tp
;
354 struct snmp_mib_tree
*peer
= NULL
;
355 register struct node
*np
=NULL
, **headp
=NULL
;
356 struct node
*oldnp
= NULL
, *child_list
= NULL
, *childp
= NULL
;
362 for(cp
= tp
->label
; *cp
; cp
++)
364 headp
= &nbuckets
[NBUCKET(hash
)];
366 * Search each of the nodes for one whose parent is root, and
367 * move each into a separate list.
369 for(np
= *headp
; np
; np
= np
->next
){
370 if ((*tp
->label
!= *np
->parent
) || strcmp(tp
->label
, np
->parent
)){
371 if ((*tp
->label
== *np
->label
) && !strcmp(tp
->label
, np
->label
)){
372 /* if there is another node with the same label, assume that
373 * any children after this point in the list belong to the other node.
374 * This adds some scoping to the table and allows vendors to
375 * reuse names such as "ip".
381 if (child_list
== NULL
){
382 child_list
= childp
= np
; /* first entry in child list */
387 /* take this node out of the node list */
389 *headp
= np
->next
; /* fix root of node list */
391 oldnp
->next
= np
->next
; /* link around this node */
396 childp
->next
= 0; /* re-terminate list */
398 * Take each element in the child list and place it into the tree.
400 for(np
= child_list
; np
; np
= np
->next
){
401 tp
= (struct snmp_mib_tree
*)xmalloc(sizeof(struct snmp_mib_tree
));
403 tp
->next_peer
= NULL
;
404 tp
->child_list
= NULL
;
405 strcpy(tp
->label
, np
->label
);
406 tp
->subid
= np
->subid
;
407 tp
->type
= translation_table
[np
->type
];
408 tp
->enums
= np
->enums
;
409 np
->enums
= NULL
; /* so we don't free them later */
410 if (root
->child_list
== NULL
){
411 root
->child_list
= tp
;
413 peer
->next_peer
= tp
;
416 /* if (tp->type == TYPE_OTHER) */
417 do_subtree(tp
, nodes
); /* recurse on this child if it isn't an end node */
419 /* free all nodes that were copied into tree */
421 for(np
= child_list
; np
; np
= np
->next
){
433 struct snmp_mib_tree
*
438 struct snmp_mib_tree
*tp
;
439 int bucket
, nodes_left
= 0;
441 /* build root node */
442 tp
= (struct snmp_mib_tree
*)xmalloc(sizeof(struct snmp_mib_tree
));
444 tp
->next_peer
= NULL
;
445 tp
->child_list
= NULL
;
447 strcpy(tp
->label
, "iso");
450 build_translation_table();
451 /* grow tree from this root node */
452 init_node_hash(nodes
);
453 /* XXX nodes isn't needed in do_subtree() ??? */
454 do_subtree(tp
, &nodes
);
456 print_subtree(tp
, 0);
458 /* If any nodes are left, the tree is probably inconsistent */
459 for(bucket
= 0; bucket
< NHASHSIZE
; bucket
++){
460 if (nbuckets
[bucket
]){
466 snmplib_debug(0, "The mib description doesn't seem to be consistent.\n");
467 snmplib_debug(0, "Some nodes couldn't be linked under the \"iso\" tree.\n");
468 snmplib_debug(0, "these nodes are left:\n");
469 for(bucket
= 0; bucket
< NHASHSIZE
; bucket
++){
470 for(np
= nbuckets
[bucket
]; np
; np
= np
->next
)
471 snmplib_debug(0, "%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
480 * Parses a token from the file. The type of the token parsed is returned,
481 * and the text is placed in the string pointed to by token.
483 static char last
= ' ';
488 register char *token
;
491 register char *cp
= token
;
492 register int hash
= 0;
493 register struct tok
*tp
;
497 /* skip all white space */
498 while(isspace(ch
) && ch
!= -1){
507 * Accumulate characters until end of token is found. Then attempt to match this
508 * token as a reserved word. If a match is found, return the type. Else it is
514 if (isspace(ch
) || ch
== '(' || ch
== ')' ||
515 ch
== '{' || ch
== '}' || ch
== ',' ||
517 if (!isspace(ch
) && *token
== 0){
526 for (tp
= buckets
[BUCKET(hash
)]; tp
; tp
= tp
->next
) {
527 if ((tp
->hash
== hash
) && (strcmp(tp
->name
, token
) == 0))
531 if (tp
->token
== CONTINUE
)
536 if (token
[0] == '-' && token
[1] == '-'){
538 while ((ch
= getc(fp
)) != -1)
546 return get_token(fp
, token
);
548 for(cp
= token
; *cp
; cp
++)
559 } while ((ch
= getc(fp
)) != -1);
564 * Takes a list of the form:
565 * { iso org(3) dod(6) 1 }
566 * and creates several nodes, one for each parent-child pair.
567 * Returns NULL on error.
570 getoid(fp
, SubOid
, length
)
572 register struct subid
*SubOid
; /* an array of subids */
573 int length
; /* the length of the array */
580 if ((type
= get_token(fp
, token
)) != LEFTBRACKET
){
581 print_error("Expected \"{\"", token
, type
);
584 type
= get_token(fp
, token
);
585 for(count
= 0; count
< length
; count
++, SubOid
++){
588 if (type
== RIGHTBRACKET
){
590 } else if (type
!= LABEL
&& type
!= NUMBER
){
591 print_error("Not valid for object identifier", token
, type
);
595 /* this entry has a label */
596 cp
= (char *)xmalloc((unsigned)strlen(token
) + 1);
599 type
= get_token(fp
, token
);
600 if (type
== LEFTPAREN
){
601 type
= get_token(fp
, token
);
603 SubOid
->subid
= atoi(token
);
604 if ((type
= get_token(fp
, token
)) != RIGHTPAREN
){
605 print_error("Unexpected a closing parenthesis", token
, type
);
609 print_error("Expected a number", token
, type
);
616 /* this entry has just an integer sub-identifier */
617 SubOid
->subid
= atoi(token
);
619 type
= get_token(fp
, token
);
630 struct enum_list
*ep
, *tep
;
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(fp
, name
)
655 register struct subid
*op
, *nop
;
657 struct subid SubOid
[32];
658 struct node
*np
, *root
, *oldnp
= NULL
;
660 type
= get_token(fp
, token
);
662 print_error("Bad format", token
, type
);
665 if ((length
= getoid(fp
, SubOid
, 32)) != 0){
666 np
= root
= (struct node
*)xmalloc(sizeof(struct node
));
667 memset((char *)np
, '\0', sizeof(struct node
));
669 * For each parent-child subid pair in the subid array,
670 * create a node and link it into the node list.
672 for(count
= 0, op
= SubOid
, nop
=SubOid
+1; count
< (length
- 2); count
++,
674 /* every node must have parent's name and child's name or number */
675 if (op
->label
&& (nop
->label
|| (nop
->subid
!= -1))){
676 strcpy(np
->parent
, op
->label
);
678 strcpy(np
->label
, nop
->label
);
679 if (nop
->subid
!= -1)
680 np
->subid
= nop
->subid
;
683 /* set up next entry */
684 np
->next
= (struct node
*)xmalloc(sizeof(*np
->next
));
685 memset((char *)np
->next
, '\0', sizeof(struct node
));
690 np
->next
= (struct node
*)NULL
;
692 * The above loop took care of all but the last pair. This pair is taken
693 * care of here. The name for this node is taken from the label for this
695 * np still points to an unused entry.
697 if (count
== (length
- 2)){
699 strcpy(np
->parent
, op
->label
);
700 strcpy(np
->label
, name
);
701 if (nop
->subid
!= -1)
702 np
->subid
= nop
->subid
;
704 print_error("Warning: This entry is pretty silly", np
->label
, type
);
713 print_error("Missing end of oid", (char *)NULL
, type
);
714 free_node(np
); /* the last node allocated wasn't used */
719 /* free the oid array */
720 for(count
= 0, op
= SubOid
; count
< length
; count
++, op
++){
727 print_error("Bad object identifier", (char *)NULL
, type
);
733 * Parses an asn type. This structure is ignored by this parser.
734 * Returns NULL on error.
743 type
= get_token(fp
, token
);
744 if (type
!= SEQUENCE
){
745 print_error("Not a sequence", token
, type
); /* should we handle this */
748 while((type
= get_token(fp
, token
)) != ENDOFFILE
){
749 if (type
== RIGHTBRACKET
)
752 print_error("Expected \"}\"", token
, type
);
757 * Parses an OBJECT TYPE macro.
758 * Returns 0 on error.
761 parse_objecttype(fp
, name
)
768 struct subid SubOid
[32];
772 register struct node
*np
=NULL
;
773 register struct enum_list
*ep
=NULL
;
775 type
= get_token(fp
, token
);
777 print_error("Bad format for OBJECT TYPE", token
, type
);
780 np
= (struct node
*)xmalloc(sizeof(struct node
));
783 type
= get_token(fp
, token
);
784 nexttype
= get_token(fp
, nexttoken
);
788 strcpy(syntax
, token
);
791 strcat(syntax
, nexttoken
);
792 nexttype
= get_token(fp
, nexttoken
);
794 strcat(syntax
, nexttoken
);
795 nexttype
= get_token(fp
, nexttoken
);
799 strcpy(syntax
, token
);
800 if (nexttype
== LEFTBRACKET
) {
801 /* if there is an enumeration list, parse it */
802 while((type
= get_token(fp
, token
)) != ENDOFFILE
){
803 if (type
== RIGHTBRACKET
)
806 /* this is an enumerated label */
808 ep
= np
->enums
= (struct enum_list
*)
809 xmalloc(sizeof(struct enum_list
));
811 ep
->next
= (struct enum_list
*)
812 xmalloc(sizeof(struct enum_list
));
816 /* a reasonable approximation for the length */
817 ep
->label
= (char *)xmalloc((unsigned)strlen(token
) + 1);
818 strcpy(ep
->label
, token
);
819 type
= get_token(fp
, token
);
820 if (type
!= LEFTPAREN
){
821 print_error("Expected \"(\"", token
, type
);
825 type
= get_token(fp
, token
);
827 print_error("Expected integer", token
, type
);
831 ep
->value
= atoi(token
);
832 type
= get_token(fp
, token
);
833 if (type
!= RIGHTPAREN
){
834 print_error("Expected \")\"", token
, type
);
840 if (type
== ENDOFFILE
){
841 print_error("Expected \"}\"", token
, type
);
845 nexttype
= get_token(fp
, nexttoken
);
846 } else if (nexttype
== LEFTPAREN
){
847 /* ignore the "constrained integer" for now */
848 nexttype
= get_token(fp
, nexttoken
);
849 nexttype
= get_token(fp
, nexttoken
);
850 nexttype
= get_token(fp
, nexttoken
);
863 strcpy(syntax
, token
);
866 print_error("Bad syntax", token
, type
);
870 if (nexttype
!= ACCESS
){
871 print_error("Should be ACCESS", nexttoken
, nexttype
);
875 type
= get_token(fp
, token
);
876 if (type
!= READONLY
&& type
!= READWRITE
&& type
!= WRITEONLY
877 && type
!= NOACCESS
){
878 print_error("Bad access type", nexttoken
, nexttype
);
882 type
= get_token(fp
, token
);
884 print_error("Should be STATUS", token
, nexttype
);
888 type
= get_token(fp
, token
);
889 if (type
!= MANDATORY
&& type
!= OPTIONAL
&& type
!= OBSOLETE
&& type
!= RECOMMENDED
){
890 print_error("Bad status", token
, type
);
894 /* Fetch next token. Either:
896 * -> EQUALS (Old MIB format)
897 * -> DESCRIPTION, INDEX (New MIB format)
899 type
= get_token(fp
, token
);
900 if ((type
!= DESCRIPTION
) && (type
!= INDEX
) && (type
!= EQUALS
)) {
901 print_error("Should be DESCRIPTION, INDEX, or EQUALS", token
, nexttype
);
906 if (type
== DESCRIPTION
) {
908 type
= get_token(fp
, token
);
910 print_error("Should be Description open quote", token
, nexttype
);
915 /* Fetch description string */
920 /* skip everything until closing quote */
921 while((ReadChar
!= '"') && (ReadChar
!= -1)) {
923 if (ReadChar
== '\n')
928 /* ASSERT: Done with description. */
929 type
= get_token(fp
, token
);
932 if ((type
!= INDEX
) && (type
!= EQUALS
)) {
933 print_error("Should be INDEX, or EQUALS", token
, nexttype
);
942 type
= get_token(fp
, token
);
943 if (type
!= LEFTBRACKET
){
944 print_error("Should be INDEX left brace", token
, type
);
949 /* Fetch description string */
954 /* skip everything until closing quote */
955 while((ReadChar
!= '}') && (ReadChar
!= -1)) {
957 if (ReadChar
== '\n')
962 /* ASSERT: Done with INDEX. */
963 type
= get_token(fp
, token
);
967 print_error("Bad format", token
, type
);
971 length
= getoid(fp
, SubOid
, 32);
972 if (length
> 1 && length
<= 32){
973 /* just take the last pair in the oid list */
974 if (SubOid
[length
- 2].label
)
975 strncpy(np
->parent
, SubOid
[length
- 2].label
, 64);
976 strcpy(np
->label
, name
);
977 if (SubOid
[length
- 1].subid
!= -1)
978 np
->subid
= SubOid
[length
- 1].subid
;
980 print_error("Warning: This entry is pretty silly", np
->label
, type
);
982 print_error("No end to oid", (char *)NULL
, type
);
987 for(count
= 0; count
< length
; count
++){
988 if (SubOid
[count
].label
)
989 xfree(SubOid
[count
].label
);
990 SubOid
[count
].label
= 0;
997 * Parses a mib file and returns a linked list of nodes found in the file.
998 * Returns NULL on error.
1010 struct node
*np
=NULL
, *root
= NULL
;
1014 while(type
!= ENDOFFILE
){
1015 type
= get_token(fp
, token
);
1017 if (type
== ENDOFFILE
){
1020 print_error(token
, "is a reserved word", type
);
1023 strncpy(name
, token
, 64);
1024 type
= get_token(fp
, token
);
1025 if (type
== OBJTYPE
){
1027 /* first link in chain */
1028 np
= root
= parse_objecttype(fp
, name
);
1030 print_error("Bad parse of object type", (char *)NULL
, type
);
1034 np
->next
= parse_objecttype(fp
, name
);
1035 if (np
->next
== NULL
){
1036 print_error("Bad parse of objecttype", (char *)NULL
, type
);
1040 /* now find end of chain */
1043 } else if (type
== OBJID
){
1045 /* first link in chain */
1046 np
= root
= parse_objectid(fp
, name
);
1048 print_error("Bad parse of object id", (char *)NULL
, type
);
1052 np
->next
= parse_objectid(fp
, name
);
1053 if (np
->next
== NULL
){
1054 print_error("Bad parse of object type", (char *)NULL
, type
);
1058 /* now find end of chain */
1061 } else if (type
== EQUALS
){
1062 type
= parse_asntype(fp
);
1063 } else if (type
== ENDOFFILE
){
1066 print_error("Bad operator", (char *)NULL
, type
);
1072 struct enum_list
*ep
;
1074 for(np
= root
; np
; np
= np
->next
){
1075 printf("%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
1078 printf("Enums: \n");
1079 for(ep
= np
->enums
; ep
; ep
= ep
->next
){
1080 printf("%s(%d)\n", ep
->label
, ep
->value
);
1089 struct snmp_mib_tree
*
1090 read_mib(char *filename
)
1094 struct snmp_mib_tree
*tree
;
1098 fp
= fopen(filename
, "r");
1100 snmplib_debug(1, "init_mib: %s: %s\n", filename
, xstrerror());
1105 while ( (p
=fgets(mbuf
, 256, fp
)) && strncmp(mbuf
, CURRENT_MIB_VERSION
,
1106 strlen(CURRENT_MIB_VERSION
)));
1108 snmplib_debug(0, "Bad MIB version or tag missing, install original!\n");
1112 if (!strcmp(mbuf
, CURRENT_MIB_VERSION
)) {
1113 snmplib_debug(0, "You need to update your MIB!\n");
1118 snmplib_debug(0, "Mib table is bad. Exiting\n");
1121 tree
= build_tree(nodes
);