]>
git.ipfire.org Git - thirdparty/squid.git/blob - snmplib/parse.c
1 /******************************************************************
2 Copyright 1989, 1991, 1992 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 ******************************************************************/
32 #include <sys/types.h>
41 #include <gnumalloc.h>
42 #elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)
48 /* A quoted string value-- too long for a general "token" */
49 char *quoted_string_buffer
;
52 * This is one element of an object identifier with either an integer
53 * subidentifier, or a textual string label, or both.
54 * The subid is -1 if not present, and label is NULL if not present.
61 /* use large token buffer in case of very long tokens: */
63 struct tc
{ /* textual conventions */
65 char descriptor
[MAXTOKEN
];
66 struct enum_list
*enums
;
73 #define SYNTAX_MASK 0x80
75 * Tokens wiht the SYNTAX_MASK bit set are syntax tokens */
81 #define OBJID (4 | SYNTAX_MASK)
82 #define OCTETSTR (5 | SYNTAX_MASK)
83 #define INTEGER (6 | SYNTAX_MASK)
84 #define NETADDR (7 | SYNTAX_MASK)
85 #define IPADDR (8 | SYNTAX_MASK)
86 #define COUNTER (9 | SYNTAX_MASK)
87 #define GAUGE (10 | SYNTAX_MASK)
88 #define TIMETICKS (11 | SYNTAX_MASK)
89 #define OPAQUE (12 | SYNTAX_MASK)
90 #define NUL (13 | SYNTAX_MASK)
92 #define OF 15 /* SEQUENCE OF */
103 /* #define RECOMMENDED 26 */
107 #define LEFTBRACKET 30
108 #define RIGHTBRACKET 31
110 #define RIGHTPAREN 33
112 #define DESCRIPTION 35
113 #define QUOTESTRING 36
116 #define DEPRECATED 39
118 #define BITSTRING (41 | SYNTAX_MASK)
119 #define NSAPADDRESS (42 | SYNTAX_MASK)
120 #define COUNTER64 (43 | SYNTAX_MASK)
124 #define COMPLIANCE 47
125 #define READCREATE 48
128 #define NUM_ENTRIES 51
129 #define MODULEIDENTITY 52
130 #define LASTUPDATED 53
131 #define ORGANIZATION 54
132 #define CONTACTINFO 55
133 #define UINTEGER32 (56 | SYNTAX_MASK)
135 #define DEFINITIONS 58
140 char *name
; /* token name */
141 int len
; /* length not counting nul */
142 int token
; /* value */
143 int hash
; /* hash of name */
144 struct tok
*next
; /* pointer to next in hash table */
148 struct tok tokens
[] =
150 {"obsolete", sizeof("obsolete") - 1, OBSOLETE
},
151 {"Opaque", sizeof("Opaque") - 1, OPAQUE
},
152 /* { "recommended", sizeof("recommended")-1, RECOMMENDED }, */
153 {"optional", sizeof("optional") - 1, OPTIONAL
},
154 {"LAST-UPDATED", sizeof("LAST-UPDATED") - 1, LASTUPDATED
},
155 {"ORGANIZATION", sizeof("ORGANIZATION") - 1, ORGANIZATION
},
156 {"CONTACT-INFO", sizeof("CONTACT-INFO") - 1, CONTACTINFO
},
157 {"MODULE-IDENTITY", sizeof("MODULE-IDENTITY") - 1, MODULEIDENTITY
},
158 {"MODULE-COMPLIANCE", sizeof("MODULE-COMPLIANCE") - 1, COMPLIANCE
},
159 {"DEFINITIONS", sizeof("DEFINITIONS") - 1, DEFINITIONS
},
160 {"END", sizeof("END") - 1, END
},
161 {";", sizeof(";") - 1, SEMI
},
162 {"AUGMENTS", sizeof("AUGMENTS") - 1, AUGMENTS
},
163 {"not-accessible", sizeof("not-accessible") - 1, NOACCESS
},
164 {"write-only", sizeof("write-only") - 1, WRITEONLY
},
165 {"NsapAddress", sizeof("NsapAddress") - 1, NSAPADDRESS
},
166 {"UNITS", sizeof("Units") - 1, UNITS
},
167 {"REFERENCE", sizeof("REFERENCE") - 1, REFERENCE
},
168 {"NUM-ENTRIES", sizeof("NUM-ENTRIES") - 1, NUM_ENTRIES
},
169 {"BITSTRING", sizeof("BitString") - 1, BITSTRING
},
170 {"BIT", sizeof("BIT") - 1, CONTINUE
},
171 {"Counter64", sizeof("Counter64") - 1, COUNTER64
},
172 {"TimeTicks", sizeof("TimeTicks") - 1, TIMETICKS
},
173 {"NOTIFICATION-TYPE", sizeof("NOTIFICATION-TYPE") - 1, NOTIFTYPE
},
174 {"OBJECT-GROUP", sizeof("OBJECT-GROUP") - 1, OBJGROUP
},
175 {"OBJECTIDENTIFIER", sizeof("OBJECTIDENTIFIER") - 1, OBJID
},
177 * This CONTINUE appends the next word onto OBJECT,
178 * hopefully matching OBJECTIDENTIFIER above.
180 {"OBJECT", sizeof("OBJECT") - 1, CONTINUE
},
181 {"NetworkAddress", sizeof("NetworkAddress") - 1, NETADDR
},
182 {"Gauge", sizeof("Gauge") - 1, GAUGE
},
183 {"read-write", sizeof("read-write") - 1, READWRITE
},
184 {"read-create", sizeof("read-create") - 1, READCREATE
},
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 {"UInteger32", sizeof("UInteger32") - 1, UINTEGER32
},
192 {"INTEGER", sizeof("INTEGER") - 1, INTEGER
},
193 {"Counter", sizeof("Counter") - 1, COUNTER
},
194 {"read-only", sizeof("read-only") - 1, READONLY
},
195 {"DESCRIPTION", sizeof("DESCRIPTION") - 1, DESCRIPTION
},
196 {"INDEX", sizeof("INDEX") - 1, INDEX
},
197 {"DEFVAL", sizeof("DEFVAL") - 1, DEFVAL
},
198 {"deprecated", sizeof("deprecated") - 1, DEPRECATED
},
199 {"SIZE", sizeof("SIZE") - 1, SIZE
},
200 {"MAX-ACCESS", sizeof("MAX-ACCESS") - 1, ACCESS
},
201 {"ACCESS", sizeof("ACCESS") - 1, ACCESS
},
202 {"mandatory", sizeof("mandatory") - 1, MANDATORY
},
203 {"current", sizeof("current") - 1, CURRENT
},
204 {"STATUS", sizeof("STATUS") - 1, STATUS
},
205 {"SYNTAX", sizeof("SYNTAX") - 1, SYNTAX
},
206 {"OBJECT-TYPE", sizeof("OBJECT-TYPE") - 1, OBJTYPE
},
207 {"{", sizeof("{") - 1, LEFTBRACKET
},
208 {"}", sizeof("}") - 1, RIGHTBRACKET
},
209 {"::=", sizeof("::=") - 1, EQUALS
},
210 {"(", sizeof("(") - 1, LEFTPAREN
},
211 {")", sizeof(")") - 1, RIGHTPAREN
},
212 {",", sizeof(",") - 1, COMMA
},
217 #define BUCKET(x) (x & 0x01F)
219 struct tok
*buckets
[HASHSIZE
];
221 static void do_subtree();
222 static int get_token();
223 static int parseQuoteString();
224 static int tossObjectIdentifier();
234 bzero((char *) buckets
, sizeof(buckets
));
235 for (tp
= tokens
; tp
->name
; tp
++) {
236 for (h
= 0, cp
= tp
->name
; *cp
; cp
++)
241 tp
->next
= buckets
[b
]; /* BUG ??? */
246 #define NHASHSIZE 128
247 #define NBUCKET(x) (x & 0x7F)
248 struct node
*nbuckets
[NHASHSIZE
];
251 init_node_hash(nodes
)
254 struct node
*np
, *nextp
;
258 bzero((char *) nbuckets
, sizeof(nbuckets
));
259 for (np
= nodes
; np
;) {
262 for (cp
= np
->parent
; *cp
; cp
++)
264 np
->next
= nbuckets
[NBUCKET(hash
)];
265 nbuckets
[NBUCKET(hash
)] = np
;
274 /* this is to fix (what seems to be) a problem with the IBM RT C
278 return (char *) calloc(1, num
);
282 print_error(string
, token
, type
)
287 if (type
== ENDOFFILE
)
288 fprintf(stderr
, "%s(EOF): On or around line %d\n", string
, Line
);
290 fprintf(stderr
, "%s(%s): On or around line %d\n", string
, token
, Line
);
292 fprintf(stderr
, "%s: On or around line %d\n", string
, Line
);
296 print_subtree(tree
, count
)
303 for (i
= 0; i
< count
; i
++)
305 printf("Children of %s:\n", tree
->label
);
307 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
308 for (i
= 0; i
< count
; i
++)
310 printf("%s\n", tp
->label
);
312 for (tp
= tree
->child_list
; tp
; tp
= tp
->next_peer
) {
313 print_subtree(tp
, count
);
318 int translation_table
[256];
321 build_translation_table()
325 for (count
= 0; count
< 256; count
++) {
328 translation_table
[count
] = TYPE_OBJID
;
331 translation_table
[count
] = TYPE_OCTETSTR
;
334 translation_table
[count
] = TYPE_INTEGER
;
337 translation_table
[count
] = TYPE_IPADDR
;
340 translation_table
[count
] = TYPE_IPADDR
;
343 translation_table
[count
] = TYPE_COUNTER
;
346 translation_table
[count
] = TYPE_GAUGE
;
349 translation_table
[count
] = TYPE_TIMETICKS
;
352 translation_table
[count
] = TYPE_OPAQUE
;
355 translation_table
[count
] = TYPE_NULL
;
358 translation_table
[count
] = TYPE_COUNTER64
;
361 translation_table
[count
] = TYPE_BITSTRING
;
364 translation_table
[count
] = TYPE_NSAPADDRESS
;
367 translation_table
[count
] = TYPE_UINTEGER
;
370 translation_table
[count
] = TYPE_OTHER
;
381 struct tree
*tp
, *lasttp
;
382 int bucket
, nodes_left
= 0;
384 build_translation_table();
385 /* grow tree from this root node */
386 init_node_hash(nodes
);
388 /* build root node */
389 tp
= (struct tree
*) Malloc(sizeof(struct tree
));
391 tp
->next_peer
= NULL
;
392 tp
->child_list
= NULL
;
394 strcpy(tp
->label
, "joint-iso-ccitt");
398 /* XXX nodes isn't needed in do_subtree() ??? */
399 do_subtree(tp
, &nodes
);
402 /* build root node */
403 tp
= (struct tree
*) Malloc(sizeof(struct tree
));
405 tp
->next_peer
= lasttp
;
406 tp
->child_list
= NULL
;
408 strcpy(tp
->label
, "ccitt");
412 /* XXX nodes isn't needed in do_subtree() ??? */
413 do_subtree(tp
, &nodes
);
416 /* build root node */
417 tp
= (struct tree
*) Malloc(sizeof(struct tree
));
419 tp
->next_peer
= lasttp
;
420 tp
->child_list
= NULL
;
422 strcpy(tp
->label
, "iso");
426 /* XXX nodes isn't needed in do_subtree() ??? */
427 do_subtree(tp
, &nodes
);
431 print_subtree(tp
, 0);
433 /* If any nodes are left, the tree is probably inconsistent */
434 for (bucket
= 0; bucket
< NHASHSIZE
; bucket
++) {
435 if (nbuckets
[bucket
]) {
441 fprintf(stderr
, "The mib description doesn't seem to be consistent.\n");
442 fprintf(stderr
, "Some nodes couldn't be linked under the \"iso\" tree.\n");
443 fprintf(stderr
, "these nodes are left:\n");
444 for (bucket
= 0; bucket
< NHASHSIZE
; bucket
++) {
445 for (np
= nbuckets
[bucket
]; np
; np
= np
->next
)
446 fprintf(stderr
, "%s ::= { %s %ld } (%d)\n", np
->label
,
447 np
->parent
, np
->subid
, np
->type
);
454 * Find all the children of root in the list of nodes. Link them into the
455 * tree and out of the nodes list.
458 do_subtree(root
, nodes
)
463 struct tree
*peer
= NULL
;
464 struct node
*np
, **headp
;
465 struct node
*oldnp
= NULL
, *child_list
= NULL
, *childp
= NULL
;
471 for (cp
= tp
->label
; *cp
; cp
++)
473 headp
= &nbuckets
[NBUCKET(hash
)];
475 * Search each of the nodes for one whose parent is root, and
476 * move each into a separate list.
478 for (np
= *headp
; np
; np
= np
->next
) {
479 if ((*tp
->label
!= *np
->parent
) || strcmp(tp
->label
, np
->parent
)) {
480 if ((*tp
->label
== *np
->label
) && !strcmp(tp
->label
, np
->label
)) {
481 /* if there is another node with the same label, assume that
482 * any children after this point in the list belong to the other node.
483 * This adds some scoping to the table and allows vendors to
484 * reuse names such as "ip".
490 if (child_list
== NULL
) {
491 child_list
= childp
= np
; /* first entry in child list */
496 /* take this node out of the node list */
498 *headp
= np
->next
; /* fix root of node list */
500 oldnp
->next
= np
->next
; /* link around this node */
505 childp
->next
= 0; /* re-terminate list */
507 * Take each element in the child list and place it into the tree.
509 for (np
= child_list
; np
; np
= np
->next
) {
510 tp
= (struct tree
*) Malloc(sizeof(struct tree
));
512 tp
->next_peer
= NULL
;
513 tp
->child_list
= NULL
;
514 strcpy(tp
->label
, np
->label
);
515 tp
->subid
= np
->subid
;
516 tp
->type
= translation_table
[np
->type
];
517 tp
->enums
= np
->enums
;
518 np
->enums
= NULL
; /* so we don't free them later */
519 tp
->description
= np
->description
; /* steals memory from np */
520 np
->description
= NULL
; /* so we don't free it later */
521 if (root
->child_list
== NULL
) {
522 root
->child_list
= tp
;
524 peer
->next_peer
= tp
;
527 /* if (tp->type == TYPE_OTHER) */
528 do_subtree(tp
, nodes
); /* recurse on this child if it isn't
531 /* free all nodes that were copied into tree */
533 for (np
= child_list
; np
; np
= np
->next
) {
544 * Takes a list of the form:
545 * { iso org(3) dod(6) 1 }
546 * and creates several nodes, one for each parent-child pair.
547 * Returns NULL on error.
550 getoid(fp
, oid
, length
)
552 struct subid
*oid
; /* an array of subids */
553 int length
; /* the length of the array */
557 char token
[MAXTOKEN
];
560 if ((type
= get_token(fp
, token
)) != LEFTBRACKET
) {
561 print_error("Expected \"{\"", token
, type
);
564 type
= get_token(fp
, token
);
565 for (count
= 0; count
< length
; count
++, oid
++) {
568 if (type
== RIGHTBRACKET
) {
570 } else if (type
!= LABEL
&& type
!= NUMBER
) {
571 print_error("Not valid for object identifier", token
, type
);
575 /* this entry has a label */
576 cp
= (char *) Malloc((unsigned) strlen(token
) + 1);
579 type
= get_token(fp
, token
);
580 if (type
== LEFTPAREN
) {
581 type
= get_token(fp
, token
);
582 if (type
== NUMBER
) {
583 oid
->subid
= atoi(token
);
584 if ((type
= get_token(fp
, token
)) != RIGHTPAREN
) {
585 print_error("Unexpected a closing parenthesis", token
, type
);
589 print_error("Expected a number", token
, type
);
596 /* this entry has just an integer sub-identifier */
597 oid
->subid
= atoi(token
);
599 type
= get_token(fp
, token
);
610 struct enum_list
*ep
, *tep
;
622 * Parse an entry of the form:
623 * label OBJECT IDENTIFIER ::= { parent 2 }
624 * The "label OBJECT IDENTIFIER" portion has already been parsed.
625 * Returns 0 on error.
628 parse_objectid(fp
, name
)
633 char token
[MAXTOKEN
];
635 struct subid
*op
, *nop
;
637 struct subid oid
[32];
638 struct node
*np
, *root
, *oldnp
= NULL
;
640 type
= get_token(fp
, token
);
641 if (type
!= EQUALS
) {
642 print_error("Bad format", token
, type
);
645 if ((length
= getoid(fp
, oid
, 32)) != 0) {
646 np
= root
= (struct node
*) Malloc(sizeof(struct node
));
647 bzero((char *) np
, sizeof(struct node
));
649 * For each parent-child subid pair in the subid array,
650 * create a node and link it into the node list.
652 for (count
= 0, op
= oid
, nop
= oid
+ 1; count
< (length
- 2); count
++,
654 /* every node must have parent's name and child's name or number */
655 if (op
->label
&& (nop
->label
|| (nop
->subid
!= -1))) {
656 strcpy(np
->parent
, op
->label
);
658 strcpy(np
->label
, nop
->label
);
659 if (nop
->subid
!= -1)
660 np
->subid
= nop
->subid
;
663 /* set up next entry */
664 np
->next
= (struct node
*) Malloc(sizeof(*np
->next
));
665 bzero((char *) np
->next
, sizeof(struct node
));
670 np
->next
= (struct node
*) NULL
;
672 * The above loop took care of all but the last pair. This pair is taken
673 * care of here. The name for this node is taken from the label for this
675 * np still points to an unused entry.
677 if (count
== (length
- 2)) {
679 strcpy(np
->parent
, op
->label
);
680 strcpy(np
->label
, name
);
681 if (nop
->subid
!= -1)
682 np
->subid
= nop
->subid
;
684 print_error("Warning: This entry is pretty silly",
694 print_error("Missing end of oid", (char *) NULL
, type
);
695 free_node(np
); /* the last node allocated wasn't used */
700 /* free the oid array */
701 for (count
= 0, op
= oid
; count
< length
; count
++, op
++) {
708 print_error("Bad object identifier", (char *) NULL
, type
);
714 get_tc(descriptor
, ep
)
716 struct enum_list
**ep
;
720 for (i
= 0; i
< MAXTC
; i
++) {
721 if (tclist
[i
].type
== 0)
723 if (!strcmp(descriptor
, tclist
[i
].descriptor
)) {
724 *ep
= tclist
[i
].enums
;
725 return tclist
[i
].type
;
732 * Parses an asn type. Structures are ignored by this parser.
733 * Returns NULL on error.
736 parse_asntype(fp
, name
, ntype
, ntoken
)
743 char token
[MAXTOKEN
];
744 struct enum_list
*ep
= 0;
748 type
= get_token(fp
, token
);
749 if (type
== SEQUENCE
) {
750 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
751 if (type
== RIGHTBRACKET
) {
752 *ntype
= get_token(fp
, ntoken
);
756 print_error("Expected \"}\"", token
, type
);
759 if (!strcmp(token
, "TEXTUAL-CONVENTION")) {
760 while (type
!= SYNTAX
)
761 type
= get_token(fp
, token
);
762 type
= get_token(fp
, token
);
764 /* textual convention */
765 for (i
= 0; i
< MAXTC
; i
++) {
766 if (tclist
[i
].type
== 0)
770 print_error("No more textual conventions possible.", token
, type
);
774 strcpy(tcp
->descriptor
, name
);
775 if (!(type
& SYNTAX_MASK
)) {
776 print_error("Textual convention doesn't map to real type.", token
,
781 *ntype
= get_token(fp
, ntoken
);
782 if (*ntype
== LEFTPAREN
) {
784 /* don't record any constraints for now */
786 *ntype
= get_token(fp
, ntoken
);
787 if (*ntype
== LEFTPAREN
)
789 if (*ntype
== RIGHTPAREN
)
792 *ntype
= get_token(fp
, ntoken
);
793 } else if (*ntype
== LEFTBRACKET
) {
794 /* if there is an enumeration list, parse it */
795 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
796 if (type
== RIGHTBRACKET
)
799 /* this is an enumerated label */
800 if (tcp
->enums
== 0) {
801 ep
= tcp
->enums
= (struct enum_list
*)
802 Malloc(sizeof(struct enum_list
));
804 ep
->next
= (struct enum_list
*)
805 Malloc(sizeof(struct enum_list
));
809 /* a reasonable approximation for the length */
811 (char *) Malloc((unsigned) strlen(token
) + 1);
812 strcpy(ep
->label
, token
);
813 type
= get_token(fp
, token
);
814 if (type
!= LEFTPAREN
) {
815 print_error("Expected \"(\"", token
, type
);
819 type
= get_token(fp
, token
);
820 if (type
!= NUMBER
) {
821 print_error("Expected integer", token
, type
);
825 ep
->value
= atoi(token
);
826 type
= get_token(fp
, token
);
827 if (type
!= RIGHTPAREN
) {
828 print_error("Expected \")\"", token
, type
);
834 if (type
== ENDOFFILE
) {
835 print_error("Expected \"}\"", token
, type
);
839 *ntype
= get_token(fp
, ntoken
);
847 * Parses an OBJECT TYPE macro.
848 * Returns 0 on error.
851 parse_objecttype(fp
, name
)
856 char token
[MAXTOKEN
];
858 struct subid oid
[32];
859 char syntax
[MAXTOKEN
];
860 int nexttype
, tctype
;
861 char nexttoken
[MAXTOKEN
];
863 struct enum_list
*ep
= 0;
865 type
= get_token(fp
, token
);
866 if (type
!= SYNTAX
) {
867 print_error("Bad format for OBJECT TYPE", token
, type
);
870 np
= (struct node
*) Malloc(sizeof(struct node
));
873 np
->description
= NULL
; /* default to an empty description */
874 type
= get_token(fp
, token
);
876 tctype
= get_tc(token
, &(np
->enums
));
878 if (tctype
== LABEL
) {
879 print_error("No known translation for type", token
, type
);
886 nexttype
= get_token(fp
, nexttoken
);
889 strcpy(syntax
, token
);
890 if (nexttype
== OF
) {
892 strcat(syntax
, nexttoken
);
893 nexttype
= get_token(fp
, nexttoken
);
895 strcat(syntax
, nexttoken
);
896 nexttype
= get_token(fp
, nexttoken
);
901 strcpy(syntax
, token
);
902 if (nexttype
== LEFTBRACKET
) {
903 /* if there is an enumeration list, parse it */
904 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
905 if (type
== RIGHTBRACKET
)
908 /* this is an enumerated label */
909 if (np
->enums
== 0) {
910 ep
= np
->enums
= (struct enum_list
*)
911 Malloc(sizeof(struct enum_list
));
913 ep
->next
= (struct enum_list
*)
914 Malloc(sizeof(struct enum_list
));
918 /* a reasonable approximation for the length */
920 (char *) Malloc((unsigned) strlen(token
) + 1);
921 strcpy(ep
->label
, token
);
922 type
= get_token(fp
, token
);
923 if (type
!= LEFTPAREN
) {
924 print_error("Expected \"(\"", token
, type
);
928 type
= get_token(fp
, token
);
929 if (type
!= NUMBER
) {
930 print_error("Expected integer", token
, type
);
934 ep
->value
= atoi(token
);
935 type
= get_token(fp
, token
);
936 if (type
!= RIGHTPAREN
) {
937 print_error("Expected \")\"", token
, type
);
943 if (type
== ENDOFFILE
) {
944 print_error("Expected \"}\"", token
, type
);
948 nexttype
= get_token(fp
, nexttoken
);
949 } else if (nexttype
== LEFTPAREN
) {
950 /* ignore the "constrained integer" for now */
951 nexttype
= get_token(fp
, nexttoken
);
952 nexttype
= get_token(fp
, nexttoken
);
953 nexttype
= get_token(fp
, nexttoken
);
957 strcpy(syntax
, token
);
958 if (nexttype
== LEFTBRACKET
) {
959 /* if there is an enumeration list, parse it */
960 while ((type
= get_token(fp
, token
)) != ENDOFFILE
) {
961 if (type
== RIGHTBRACKET
)
964 /* this is an enumerated label */
965 if (np
->enums
== 0) {
966 ep
= np
->enums
= (struct enum_list
*)
967 Malloc(sizeof(struct enum_list
));
969 ep
->next
= (struct enum_list
*)
970 Malloc(sizeof(struct enum_list
));
974 /* a reasonable approximation for the length */
976 (char *) Malloc((unsigned) strlen(token
) + 1);
977 strcpy(ep
->label
, token
);
978 type
= get_token(fp
, token
);
979 if (type
!= LEFTPAREN
) {
980 print_error("Expected \"(\"", token
, type
);
984 type
= get_token(fp
, token
);
985 if (type
!= NUMBER
) {
986 print_error("Expected integer", token
, type
);
990 ep
->value
= atoi(token
);
991 type
= get_token(fp
, token
);
992 if (type
!= RIGHTPAREN
) {
993 print_error("Expected \")\"", token
, type
);
999 if (type
== ENDOFFILE
) {
1000 print_error("Expected \"}\"", token
, type
);
1004 nexttype
= get_token(fp
, nexttoken
);
1005 } else if (nexttype
== LEFTPAREN
) {
1006 /* ignore the "constrained integer" for now */
1007 nexttype
= get_token(fp
, nexttoken
);
1008 nexttype
= get_token(fp
, nexttoken
);
1009 nexttype
= get_token(fp
, nexttoken
);
1013 strcpy(syntax
, token
);
1014 /* ignore the "constrained octet string" for now */
1015 if (nexttype
== LEFTPAREN
) {
1016 nexttype
= get_token(fp
, nexttoken
);
1017 if (nexttype
== SIZE
) {
1018 nexttype
= get_token(fp
, nexttoken
);
1019 if (nexttype
== LEFTPAREN
) {
1020 nexttype
= get_token(fp
, nexttoken
); /* 0..255 */
1021 nexttype
= get_token(fp
, nexttoken
); /* ) */
1022 nexttype
= get_token(fp
, nexttoken
); /* ) */
1023 if (nexttype
== RIGHTPAREN
) {
1024 nexttype
= get_token(fp
, nexttoken
);
1029 print_error("Bad syntax", token
, type
);
1045 strcpy(syntax
, token
);
1048 print_error("Bad syntax", token
, type
);
1052 if (nexttype
== UNITS
) {
1053 type
= get_token(fp
, token
);
1054 if (type
!= QUOTESTRING
) {
1055 print_error("Bad DESCRIPTION", token
, type
);
1059 nexttype
= get_token(fp
, nexttoken
);
1061 if (nexttype
!= ACCESS
) {
1062 print_error("Should be ACCESS", nexttoken
, nexttype
);
1066 type
= get_token(fp
, token
);
1067 if (type
!= READONLY
&& type
!= READWRITE
&& type
!= WRITEONLY
1068 && type
!= NOACCESS
&& type
!= READCREATE
) {
1069 print_error("Bad access type", nexttoken
, nexttype
);
1073 type
= get_token(fp
, token
);
1074 if (type
!= STATUS
) {
1075 print_error("Should be STATUS", token
, nexttype
);
1079 type
= get_token(fp
, token
);
1080 if (type
!= MANDATORY
&& type
!= CURRENT
&& type
!= OPTIONAL
&& type
!= OBSOLETE
&& type
!= DEPRECATED
) {
1081 print_error("Bad status", token
, type
);
1086 * Optional parts of the OBJECT-TYPE macro
1088 type
= get_token(fp
, token
);
1089 while (type
!= EQUALS
) {
1092 type
= get_token(fp
, token
);
1093 if (type
!= QUOTESTRING
) {
1094 print_error("Bad DESCRIPTION", token
, type
);
1099 printf("Description== \"%.50s\"\n", quoted_string_buffer
);
1101 np
->description
= quoted_string_buffer
;
1102 quoted_string_buffer
= (char *) calloc(1, MAXQUOTESTR
);
1106 type
= get_token(fp
, token
);
1107 if (type
!= QUOTESTRING
) {
1108 print_error("Bad DESCRIPTION", token
, type
);
1117 if (tossObjectIdentifier(fp
) != OBJID
) {
1118 print_error("Bad Object Identifier", token
, type
);
1125 print_error("Bad format of optional clauses", token
, type
);
1130 type
= get_token(fp
, token
);
1132 if (type
!= EQUALS
) {
1133 print_error("Bad format", token
, type
);
1137 length
= getoid(fp
, oid
, 32);
1138 if (length
> 1 && length
<= 32) {
1139 /* just take the last pair in the oid list */
1140 if (oid
[length
- 2].label
)
1141 strncpy(np
->parent
, oid
[length
- 2].label
, MAXLABEL
);
1142 strcpy(np
->label
, name
);
1143 if (oid
[length
- 1].subid
!= -1)
1144 np
->subid
= oid
[length
- 1].subid
;
1146 print_error("Warning: This entry is pretty silly", np
->label
, type
);
1148 print_error("No end to oid", (char *) NULL
, type
);
1152 /* free oid array */
1153 for (count
= 0; count
< length
; count
++) {
1154 if (oid
[count
].label
)
1155 free(oid
[count
].label
);
1156 oid
[count
].label
= 0;
1163 * Parses an OBJECT GROUP macro.
1164 * Returns 0 on error.
1166 static struct node
*
1167 parse_objectgroup(fp
, name
)
1172 char token
[MAXTOKEN
];
1174 struct subid oid
[32];
1177 np
= (struct node
*) Malloc(sizeof(struct node
));
1181 np
->description
= NULL
; /* default to an empty description */
1182 type
= get_token(fp
, token
);
1183 while (type
!= EQUALS
) {
1186 type
= get_token(fp
, token
);
1187 if (type
!= QUOTESTRING
) {
1188 print_error("Bad DESCRIPTION", token
, type
);
1193 printf("Description== \"%.50s\"\n", quoted_string_buffer
);
1195 np
->description
= quoted_string_buffer
;
1196 quoted_string_buffer
= (char *) calloc(1, MAXQUOTESTR
);
1203 type
= get_token(fp
, token
);
1205 length
= getoid(fp
, oid
, 32);
1206 if (length
> 1 && length
<= 32) {
1207 /* just take the last pair in the oid list */
1208 if (oid
[length
- 2].label
)
1209 strncpy(np
->parent
, oid
[length
- 2].label
, MAXLABEL
);
1210 strcpy(np
->label
, name
);
1211 if (oid
[length
- 1].subid
!= -1)
1212 np
->subid
= oid
[length
- 1].subid
;
1214 print_error("Warning: This entry is pretty silly", np
->label
, type
);
1216 print_error("No end to oid", (char *) NULL
, type
);
1220 /* free oid array */
1221 for (count
= 0; count
< length
; count
++) {
1222 if (oid
[count
].label
)
1223 free(oid
[count
].label
);
1224 oid
[count
].label
= 0;
1230 * Parses a NOTIFICATION-TYPE macro.
1231 * Returns 0 on error.
1233 static struct node
*
1234 parse_notificationDefinition(fp
, name
)
1239 char token
[MAXTOKEN
];
1241 struct subid oid
[32];
1244 np
= (struct node
*) Malloc(sizeof(struct node
));
1248 np
->description
= NULL
; /* default to an empty description */
1249 type
= get_token(fp
, token
);
1250 while (type
!= EQUALS
) {
1253 type
= get_token(fp
, token
);
1254 if (type
!= QUOTESTRING
) {
1255 print_error("Bad DESCRIPTION", token
, type
);
1260 printf("Description== \"%.50s\"\n", quoted_string_buffer
);
1262 np
->description
= quoted_string_buffer
;
1263 quoted_string_buffer
= (char *) calloc(1, MAXQUOTESTR
);
1270 type
= get_token(fp
, token
);
1272 length
= getoid(fp
, oid
, 32);
1273 if (length
> 1 && length
<= 32) {
1274 /* just take the last pair in the oid list */
1275 if (oid
[length
- 2].label
)
1276 strncpy(np
->parent
, oid
[length
- 2].label
, MAXLABEL
);
1277 strcpy(np
->label
, name
);
1278 if (oid
[length
- 1].subid
!= -1)
1279 np
->subid
= oid
[length
- 1].subid
;
1281 print_error("Warning: This entry is pretty silly", np
->label
, type
);
1283 print_error("No end to oid", (char *) NULL
, type
);
1287 /* free oid array */
1288 for (count
= 0; count
< length
; count
++) {
1289 if (oid
[count
].label
)
1290 free(oid
[count
].label
);
1291 oid
[count
].label
= 0;
1297 * Parses a compliance macro
1298 * Returns 0 on error.
1300 static struct node
*
1301 parse_compliance(fp
, name
)
1306 char token
[MAXTOKEN
];
1308 struct subid oid
[32];
1311 np
= (struct node
*) Malloc(sizeof(struct node
));
1315 np
->description
= NULL
; /* default to an empty description */
1316 type
= get_token(fp
, token
);
1317 while (type
!= EQUALS
) {
1318 type
= get_token(fp
, token
);
1320 length
= getoid(fp
, oid
, 32);
1321 if (length
> 1 && length
<= 32) {
1322 /* just take the last pair in the oid list */
1323 if (oid
[length
- 2].label
)
1324 strncpy(np
->parent
, oid
[length
- 2].label
, MAXLABEL
);
1325 strcpy(np
->label
, name
);
1326 if (oid
[length
- 1].subid
!= -1)
1327 np
->subid
= oid
[length
- 1].subid
;
1329 print_error("Warning: This entry is pretty silly", np
->label
, type
);
1331 print_error("No end to oid", (char *) NULL
, type
);
1335 /* free oid array */
1336 for (count
= 0; count
< length
; count
++) {
1337 if (oid
[count
].label
)
1338 free(oid
[count
].label
);
1339 oid
[count
].label
= 0;
1347 * Parses a module identity macro
1348 * Returns 0 on error.
1350 static struct node
*
1351 parse_moduleIdentity(fp
, name
)
1356 char token
[MAXTOKEN
];
1358 struct subid oid
[32];
1361 np
= (struct node
*) Malloc(sizeof(struct node
));
1365 np
->description
= NULL
; /* default to an empty description */
1366 type
= get_token(fp
, token
);
1367 while (type
!= EQUALS
) {
1368 type
= get_token(fp
, token
);
1370 length
= getoid(fp
, oid
, 32);
1371 if (length
> 1 && length
<= 32) {
1372 /* just take the last pair in the oid list */
1373 if (oid
[length
- 2].label
)
1374 strncpy(np
->parent
, oid
[length
- 2].label
, MAXLABEL
);
1375 strcpy(np
->label
, name
);
1376 if (oid
[length
- 1].subid
!= -1)
1377 np
->subid
= oid
[length
- 1].subid
;
1379 print_error("Warning: This entry is pretty silly", np
->label
, type
);
1381 print_error("No end to oid", (char *) NULL
, type
);
1385 /* free oid array */
1386 for (count
= 0; count
< length
; count
++) {
1387 if (oid
[count
].label
)
1388 free(oid
[count
].label
);
1389 oid
[count
].label
= 0;
1395 parse_mib_header(fp
, name
)
1399 int type
= DEFINITIONS
;
1400 char token
[MAXTOKEN
];
1402 /* This probably isn't good enough. If there is no
1403 * imports clause we can't go around waiting (forever) for a semicolon.
1404 * We need to check for semi following an EXPORTS clause or an IMPORTS
1405 * clause of both. Look for BEGIN; in my initial MIBs to see those
1406 * that I needed to hack to get to parse because they didn't have
1407 * an IMPORTS or and EXPORTS clause.
1409 while (type
!= SEMI
&& type
!= ENDOFFILE
) {
1410 type
= get_token(fp
, token
);
1412 return (type
== SEMI
);
1418 * Parses a mib file and returns a linked list of nodes found in the file.
1419 * Returns NULL on error.
1421 static struct node
*
1425 char token
[MAXTOKEN
];
1426 char name
[MAXTOKEN
];
1428 #define BETWEEN_MIBS 1
1430 int state
= BETWEEN_MIBS
;
1431 struct node
*np
= 0, *root
= NULL
;
1434 quoted_string_buffer
= (char *) calloc(1, MAXQUOTESTR
); /* free this later */
1435 bzero(tclist
, 64 * sizeof(struct tc
));
1437 while (type
!= ENDOFFILE
) {
1438 type
= get_token(fp
, token
);
1441 if (state
!= IN_MIB
) {
1442 print_error("Error, end before start of MIB.", (char *) NULL
, type
);
1445 state
= BETWEEN_MIBS
;
1447 } else if (type
!= LABEL
) {
1448 if (type
== ENDOFFILE
) {
1451 print_error(token
, "is a reserved word", type
);
1454 strncpy(name
, token
, MAXTOKEN
);
1455 type
= get_token(fp
, token
);
1456 if (type
== DEFINITIONS
) {
1457 if (state
!= BETWEEN_MIBS
) {
1458 print_error("Error, nested MIBS.", (char *) NULL
, type
);
1462 if (!parse_mib_header(fp
, name
)) {
1463 print_error("Bad parse of module header", (char *) NULL
, type
);
1466 } else if (type
== OBJTYPE
) {
1468 /* first link in chain */
1469 np
= root
= parse_objecttype(fp
, name
);
1471 print_error("Bad parse of object type", (char *) NULL
,
1476 np
->next
= parse_objecttype(fp
, name
);
1477 if (np
->next
== NULL
) {
1478 print_error("Bad parse of objecttype", (char *) NULL
,
1483 /* now find end of chain */
1486 } else if (type
== OBJGROUP
) {
1488 /* first link in chain */
1489 np
= root
= parse_objectgroup(fp
, name
);
1491 print_error("Bad parse of object group", (char *) NULL
,
1496 np
->next
= parse_objectgroup(fp
, name
);
1497 if (np
->next
== NULL
) {
1498 print_error("Bad parse of objectgroup", (char *) NULL
,
1503 /* now find end of chain */
1506 } else if (type
== NOTIFTYPE
) {
1508 /* first link in chain */
1509 np
= root
= parse_notificationDefinition(fp
, name
);
1511 print_error("Bad parse of notification definition",
1512 (char *) NULL
, type
);
1516 np
->next
= parse_notificationDefinition(fp
, name
);
1517 if (np
->next
== NULL
) {
1518 print_error("Bad parse of notification definition",
1519 (char *) NULL
, type
);
1523 /* now find end of chain */
1526 } else if (type
== COMPLIANCE
) {
1528 /* first link in chain */
1529 np
= root
= parse_compliance(fp
, name
);
1531 print_error("Bad parse of module compliance", (char *) NULL
,
1536 np
->next
= parse_compliance(fp
, name
);
1537 if (np
->next
== NULL
) {
1538 print_error("Bad parse of module compliance", (char *) NULL
,
1543 /* now find end of chain */
1546 } else if (type
== MODULEIDENTITY
) {
1548 /* first link in chain */
1549 np
= root
= parse_moduleIdentity(fp
, name
);
1551 print_error("Bad parse of module identity", (char *) NULL
,
1556 np
->next
= parse_moduleIdentity(fp
, name
);
1557 if (np
->next
== NULL
) {
1558 print_error("Bad parse of module identity", (char *) NULL
,
1563 /* now find end of chain */
1566 } else if (type
== OBJID
) {
1568 /* first link in chain */
1569 np
= root
= parse_objectid(fp
, name
);
1571 print_error("Bad parse of object id", (char *) NULL
, type
);
1575 np
->next
= parse_objectid(fp
, name
);
1576 if (np
->next
== NULL
) {
1577 print_error("Bad parse of object type", (char *) NULL
,
1582 /* now find end of chain */
1585 } else if (type
== EQUALS
) {
1586 if (!parse_asntype(fp
, name
, &type
, token
)) {
1587 print_error("Bad parse of ASN type definition.", NULL
, EQUALS
);
1591 } else if (type
== ENDOFFILE
) {
1594 print_error("Bad operator", (char *) NULL
, type
);
1600 struct enum_list
*ep
;
1602 for (np
= root
; np
; np
= np
->next
) {
1603 printf("%s ::= { %s %d } (%d)\n", np
->label
, np
->parent
, np
->subid
,
1606 printf("Enums: \n");
1607 for (ep
= np
->enums
; ep
; ep
= ep
->next
) {
1608 printf("%s(%d)\n", ep
->label
, ep
->value
);
1618 * Parses a token from the file. The type of the token parsed is returned,
1619 * and the text is placed in the string pointed to by token.
1622 get_token(fp
, token
)
1626 static char last
= ' ';
1634 /* skip all white space */
1635 while (isspace(ch
) && ch
!= -1) {
1642 } else if (ch
== '"') {
1643 return parseQuoteString(fp
, token
);
1646 * Accumulate characters until end of token is found. Then attempt to
1647 * match this token as a reserved word. If a match is found, return the
1648 * type. Else it is a label.
1653 if (isspace(ch
) || ch
== '(' || ch
== ')' || ch
== '{' || ch
== '}' ||
1654 ch
== ',' || ch
== ';') {
1655 if (!isspace(ch
) && *token
== 0) {
1664 for (tp
= buckets
[BUCKET(hash
)]; tp
; tp
= tp
->next
) {
1665 if ((tp
->hash
== hash
) && (strcmp(tp
->name
, token
) == 0))
1669 if (tp
->token
== CONTINUE
)
1673 if (token
[0] == '-' && token
[1] == '-') {
1676 while ((ch
= getc(fp
)) != -1)
1685 return get_token(fp
, token
);
1687 for (cp
= token
; *cp
; cp
++)
1698 } while ((ch
= getc(fp
)) != -1);
1703 read_mib(const char *filename
)
1709 fp
= fopen(filename
, "r");
1714 fprintf(stderr
, "Mib table is bad. Exiting\n");
1717 tree
= build_tree(nodes
);
1732 fp
= fopen("mib.txt", "r");
1734 fprintf(stderr
, "open failed\n");
1738 tp
= build_tree(nodes
);
1739 print_subtree(tp
, 0);
1746 parseQuoteString(fp
, token
)
1753 *token
= '\0'; /* make the token empty */
1759 else if (ch
== '"') {
1768 * This routine parses a string like { blah blah blah } and returns OBJID if
1769 * it is well formed, and NULL if not.
1772 tossObjectIdentifier(fp
)
1778 /* ch = last; = ' '? */
1779 /* skip all white space */
1780 while (isspace(ch
) && ch
!= -1) {