1/* 2 * Copyright 1999 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5#pragma ident "%Z%%M% %I% %E% SMI" 6 7/****************************************************************** 8 Copyright 1989, 1991, 1992 by Carnegie Mellon University 9 10 All Rights Reserved 11 12Permission to use, copy, modify, and distribute this software and its 13documentation for any purpose and without fee is hereby granted, 14provided that the above copyright notice appear in all copies and that 15both that copyright notice and this permission notice appear in 16supporting documentation, and that the name of CMU not be 17used in advertising or publicity pertaining to distribution of the 18software without specific, written prior permission. 19 20CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 21ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 22CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 23ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 24WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 25ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 26SOFTWARE. 27******************************************************************/ 28/* 29 * parse.c 30 */ 31 32/* HISTORY 33 * Jerry Yeung 6-6-96 34 * Jerry Yeung 1-9-97 fix 4019317 35 */ 36 37#include <stdio.h> 38#include <ctype.h> 39#include <stdlib.h> 40#include <sys/types.h> 41#include "parse.h" 42 43struct trap_item *trap_list = NULL; 44 45/* A quoted string value-- too long for a general "token" */ 46char *quoted_string_buffer; 47 48/* 49 * This is one element of an object identifier with either an integer 50 * subidentifier, or a textual string label, or both. 51 * The subid is -1 if not present, and label is NULL if not present. 52 */ 53struct subid { 54 int subid; 55 char *label; 56}; 57 58#define MAXTC 128 59struct tc { /* textual conventions */ 60 int type; 61 char descriptor[MAXTOKEN]; 62 struct enum_list *enums; 63} tclist[MAXTC]; 64 65 66 67int Line = 1; 68 69#define SYNTAX_MASK 0x80 70/* types of tokens 71 Tokens wiht the SYNTAX_MASK bit set are syntax tokens */ 72#define CONTINUE -1 73#define ENDOFFILE 0 74#define LABEL 1 75#define SUBTREE 2 76#define SYNTAX 3 77#define PARSE_OBJID (4 | SYNTAX_MASK) 78#define OCTETSTR (5 | SYNTAX_MASK) 79#define PARSE_INTEGER (6 | SYNTAX_MASK) 80#define NETADDR (7 | SYNTAX_MASK) 81#define IPADDR (8 | SYNTAX_MASK) 82#define PARSE_COUNTER (9 | SYNTAX_MASK) 83#define PARSE_GUAGE (10 | SYNTAX_MASK) 84#define PARSE_TIMETICKS (11 | SYNTAX_MASK) 85#define PARSE_OPAQUE (12 | SYNTAX_MASK) 86#define NUL (13 | SYNTAX_MASK) 87#define SEQUENCE 14 88#define OF 15 /* SEQUENCE OF */ 89#define OBJTYPE 16 90#define ACCESS 17 91#define READONLY 18 92#define READWRITE 19 93#define WRITEONLY 20 94#define NOACCESS 21 95#define STATUS 22 96#define MANDATORY 23 97#define OPTIONAL 24 98#define OBSOLETE 25 99/* #define RECOMMENDED 26 */ 100#define PUNCT 27 101#define EQUALS 28 102#define NUMBER 29 103#define LEFTBRACKET 30 104#define RIGHTBRACKET 31 105#define LEFTPAREN 32 106#define RIGHTPAREN 33 107#define COMMA 34 108#define DESCRIPTION 35 109#define QUOTESTRING 36 110#define INDEX 37 111#define DEFVAL 38 112#define DEPRECATED 39 113#define SIZE 40 114#define BITSTRING (41 | SYNTAX_MASK) 115#define NSAPADDRESS (42 | SYNTAX_MASK) 116#define PARSE_COUNTER64 (43 | SYNTAX_MASK) 117#define OBJGROUP 44 118#define NOTIFTYPE 45 119#define AUGMENTS 46 120#define COMPLIANCE 47 121#define READCREATE 48 122#define UNITS 49 123#define REFERENCE 50 124#define NUM_ENTRIES 51 125#define MODULEIDENTITY 52 126#define LASTUPDATED 53 127#define ORGANIZATION 54 128#define CONTACTINFO 55 129#define UINTEGER32 (56 | SYNTAX_MASK) 130#define CURRENT 57 131#define DEFINITIONS 58 132#define END 59 133#define SEMI 60 134 135/* 136-- Olivier Reisacher 95/2/14 137*/ 138#define PSEUDO_TOKEN_TABLE 61 139#define PSEUDO_TOKEN_ENTRY 62 140 141/* Jerry Yeung 6-6-96 (trap-support) */ 142#define TRAPTYPE 63 143#define ENTERPRISE 64 144#define VARIABLES 65 145 146struct tok { 147 char *name; /* token name */ 148 int len; /* length not counting nul */ 149 int token; /* value */ 150 int hash; /* hash of name */ 151 struct tok *next; /* pointer to next in hash table */ 152}; 153 154 155struct tok tokens[] = { 156 { "obsolete", sizeof ("obsolete")-1, OBSOLETE }, 157 { "Opaque", sizeof ("Opaque")-1, PARSE_OPAQUE }, 158/* { "recommended", sizeof("recommended")-1, RECOMMENDED }, */ 159 { "optional", sizeof ("optional")-1, OPTIONAL }, 160 { "LAST-UPDATED", sizeof ("LAST-UPDATED")-1, LASTUPDATED }, 161 { "ORGANIZATION", sizeof ("ORGANIZATION")-1, ORGANIZATION }, 162 { "CONTACT-INFO", sizeof ("CONTACT-INFO")-1, CONTACTINFO }, 163 { "MODULE-IDENTITY", sizeof ("MODULE-IDENTITY")-1, MODULEIDENTITY }, 164 { "MODULE-COMPLIANCE", sizeof ("MODULE-COMPLIANCE")-1, COMPLIANCE }, 165 { "DEFINITIONS", sizeof("DEFINITIONS")-1, DEFINITIONS}, 166 { "END", sizeof("END")-1, END}, 167 { ";", sizeof(";")-1, SEMI}, 168 { "AUGMENTS", sizeof ("AUGMENTS")-1, AUGMENTS }, 169 { "not-accessible", sizeof ("not-accessible")-1, NOACCESS }, 170 { "write-only", sizeof ("write-only")-1, WRITEONLY }, 171 { "NsapAddress", sizeof("NsapAddress")-1, NSAPADDRESS}, 172 { "UNITS", sizeof("Units")-1, UNITS}, 173 { "REFERENCE", sizeof("REFERENCE")-1, REFERENCE}, 174 { "NUM-ENTRIES", sizeof("NUM-ENTRIES")-1, NUM_ENTRIES}, 175 { "BITSTRING", sizeof("BitString")-1, BITSTRING}, 176 { "BIT", sizeof("BIT")-1, CONTINUE}, 177 { "Counter64", sizeof("Counter64")-1, PARSE_COUNTER64}, 178 { "TimeTicks", sizeof ("TimeTicks")-1, PARSE_TIMETICKS }, 179 { "NOTIFICATION-TYPE", sizeof ("NOTIFICATION-TYPE")-1, NOTIFTYPE }, 180 { "OBJECT-GROUP", sizeof ("OBJECT-GROUP")-1, OBJGROUP }, 181 { "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, PARSE_OBJID }, 182 /* 183 * This CONTINUE appends the next word onto OBJECT, 184 * hopefully matching OBJECTIDENTIFIER above. 185 */ 186 { "OBJECT", sizeof ("OBJECT")-1, CONTINUE }, 187 { "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR }, 188 { "Gauge", sizeof ("Gauge")-1, PARSE_GUAGE }, 189 { "read-write", sizeof ("read-write")-1, READWRITE }, 190 { "read-create", sizeof ("read-create")-1, READCREATE }, 191 { "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR }, 192 { "OCTET", sizeof ("OCTET")-1, -1 }, 193 { "OF", sizeof ("OF")-1, OF }, 194 { "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE }, 195 { "NULL", sizeof ("NULL")-1, NUL }, 196 { "IpAddress", sizeof ("IpAddress")-1, IPADDR }, 197 { "UInteger32", sizeof ("UInteger32")-1, UINTEGER32 }, 198 { "INTEGER", sizeof ("INTEGER")-1, PARSE_INTEGER }, 199 { "Counter", sizeof ("Counter")-1, PARSE_COUNTER }, 200 { "read-only", sizeof ("read-only")-1, READONLY }, 201 { "DESCRIPTION", sizeof ("DESCRIPTION")-1, DESCRIPTION }, 202 { "INDEX", sizeof ("INDEX")-1, INDEX }, 203 { "DEFVAL", sizeof ("DEFVAL")-1, DEFVAL }, 204 { "deprecated", sizeof ("deprecated")-1, DEPRECATED }, 205 { "SIZE", sizeof ("SIZE")-1, SIZE }, 206 { "MAX-ACCESS", sizeof ("MAX-ACCESS")-1, ACCESS }, 207 { "ACCESS", sizeof ("ACCESS")-1, ACCESS }, 208 { "mandatory", sizeof ("mandatory")-1, MANDATORY }, 209 { "current", sizeof ("current")-1, CURRENT }, 210 { "STATUS", sizeof ("STATUS")-1, STATUS }, 211 { "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX }, 212 { "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE }, 213 { "{", sizeof ("{")-1, LEFTBRACKET }, 214 { "}", sizeof ("}")-1, RIGHTBRACKET }, 215 { "::=", sizeof ("::=")-1, EQUALS }, 216 { "(", sizeof ("(")-1, LEFTPAREN }, 217 { ")", sizeof (")")-1, RIGHTPAREN }, 218 { ",", sizeof (",")-1, COMMA }, 219 { "TRAP-TYPE", sizeof ("TRAP-TYPE")-1, TRAPTYPE }, 220 { "ENTERPRISE", sizeof ("ENTERPRISE")-1, ENTERPRISE }, 221 { "VARIABLES", sizeof ("VARIABLES")-1, VARIABLES }, 222 { NULL } 223}; 224 225#define HASHSIZE 32 226#define BUCKET(x) (x & 0x01F) 227 228struct tok *buckets[HASHSIZE]; 229static void 230do_subtree(struct tree *root, struct node **nodes); 231static int 232get_token(register FILE *fp, register char *token); 233static int 234parseQuoteString(register FILE *fp, register char *token); 235static int 236tossObjectIdentifier(register FILE *fp); 237 238int number_value; 239 240static void 241hash_init() 242{ 243 register struct tok *tp; 244 register char *cp; 245 register int h; 246 register int b; 247 248/* 249-- Olivier Reisacher 95/2/14 250 bzero((char *)buckets, sizeof(buckets)); 251*/ 252 memset((void *) buckets, 0, sizeof(buckets)); 253 254 for (tp = tokens; tp->name; tp++) { 255 for (h = 0, cp = tp->name; *cp; cp++) 256 h += *cp; 257 tp->hash = h; 258 b = BUCKET(h); 259 if (buckets[b]) 260 tp->next = buckets[b]; /* BUG ??? */ 261 buckets[b] = tp; 262 } 263} 264 265#define NHASHSIZE 128 266#define NBUCKET(x) (x & 0x7F) 267struct node *nbuckets[NHASHSIZE]; 268 269void init_node_hash(nodes) 270 struct node *nodes; 271{ 272 register struct node *np, *nextp; 273 register char *cp; 274 register int hash; 275 276/* 277-- Olivier Reisacher 95/2/14 278 bzero((char *)nbuckets,sizeof(nbuckets)); 279*/ 280 memset((void *) nbuckets, 0, sizeof(nbuckets)); 281 282 for(np = nodes; np;){ 283 nextp = np->next; 284 hash = 0; 285 for(cp = np->parent; *cp; cp++) 286 hash += *cp; 287 np->next = nbuckets[NBUCKET(hash)]; 288 nbuckets[NBUCKET(hash)] = np; 289 np = nextp; 290 } 291} 292 293static char * 294Malloc(num) 295 unsigned num; 296{ 297 char *buf; 298 299 /* this is to fix (what seems to be) a problem with the IBM RT C 300library malloc */ 301 if (num < 16) 302 num = 16; 303 buf = (char *)malloc (num); 304 if (buf == NULL) { 305 fprintf(stderr, "malloc failed. Exiting\n"); 306 exit(1); 307 } 308 return (char *)buf; 309} 310 311static void 312print_error(string, token, type) 313 char *string; 314 char *token; 315 int type; 316{ 317 if (type == ENDOFFILE) 318 fprintf(stderr, "%s(EOF): On or around line %d\n", string, Line); 319 else if (token) 320 fprintf(stderr, "%s(%s): On or around line %d\n", string, token, Line); 321 else 322 fprintf(stderr, "%s: On or around line %d\n", string, Line); 323} 324 325/* 326-- Olivier Reisacher 95/2/14 327#ifdef TEST 328print_subtree(tree, count) 329*/ 330void print_subtree(tree, count) 331 struct tree *tree; 332 int count; 333{ 334 struct tree *tp; 335 int i; 336 337 for(i = 0; i < count; i++) 338 printf(" "); 339 printf("Children of %s:\n", tree->label); 340 count++; 341 for(tp = tree->child_list; tp; tp = tp->next_peer){ 342 for(i = 0; i < count; i++) 343 printf(" "); 344 printf("%s\n", tp->label); 345 } 346 for(tp = tree->child_list; tp; tp = tp->next_peer){ 347 print_subtree(tp, count); 348 } 349} 350/* 351-- Olivier Reisacher 95/2/14 352#endif 353*/ 354 355int translation_table[256]; 356 357void build_translation_table(){ 358 int count; 359 360 for(count = 0; count < 256; count++){ 361 switch(count){ 362 case PARSE_OBJID: 363 translation_table[count] = TYPE_OBJID; 364 break; 365 case OCTETSTR: 366 translation_table[count] = TYPE_OCTETSTR; 367 break; 368 case PARSE_INTEGER: 369 translation_table[count] = TYPE_INTEGER; 370 break; 371 case NETADDR: 372 translation_table[count] = TYPE_IPADDR; 373 break; 374 case IPADDR: 375 translation_table[count] = TYPE_IPADDR; 376 break; 377 case PARSE_COUNTER: 378 translation_table[count] = TYPE_COUNTER; 379 break; 380 case PARSE_GUAGE: 381 translation_table[count] = TYPE_GAUGE; 382 break; 383 case PARSE_TIMETICKS: 384 translation_table[count] = TYPE_TIMETICKS; 385 break; 386 case PARSE_OPAQUE: 387 translation_table[count] = TYPE_OPAQUE; 388 break; 389 case NUL: 390 translation_table[count] = TYPE_NULL; 391 break; 392 case PARSE_COUNTER64: 393 translation_table[count] = TYPE_COUNTER64; 394 break; 395 case BITSTRING: 396 translation_table[count] = TYPE_BITSTRING; 397 break; 398 case NSAPADDRESS: 399 translation_table[count] = TYPE_NSAPADDRESS; 400 break; 401 case UINTEGER32: 402 translation_table[count] = TYPE_UINTEGER; 403 break; 404 405/* 406-- Olivier Reisacher 95/2/14 407*/ 408 case PSEUDO_TOKEN_TABLE: 409 translation_table[count] = TYPE_TABLE; 410 break; 411 case PSEUDO_TOKEN_ENTRY: 412 translation_table[count] = TYPE_ENTRY; 413 break; 414 415 default: 416 translation_table[count] = TYPE_OTHER; 417 break; 418 } 419 } 420} 421 422/* 423-- Olivier Reisacher 95/2/14 424static struct tree * 425*/ 426struct tree * 427build_tree(nodes) 428 struct node *nodes; 429{ 430 struct node *np; 431 struct tree *tp; 432 int bucket, nodes_left = 0; 433 434 build_translation_table(); 435 /* grow tree from this root node */ 436 init_node_hash(nodes); 437 438/* 439-- Olivier Reisacher 95/2/14 440 build root node 441 tp = (struct tree *)Malloc(sizeof(struct tree)); 442 tp->parent = NULL; 443 tp->next_peer = NULL; 444 tp->child_list = NULL; 445 tp->enums = NULL; 446 strcpy(tp->label, "joint-iso-ccitt"); 447 tp->subid = 2; 448 tp->type = 0; 449 tp->description = 0; 450 XXX nodes isn't needed in do_subtree() ??? 451 do_subtree(tp, &nodes); 452 lasttp = tp; 453 454 build root node 455 tp = (struct tree *)Malloc(sizeof(struct tree)); 456 tp->parent = NULL; 457 tp->next_peer = lasttp; 458 tp->child_list = NULL; 459 tp->enums = NULL; 460 strcpy(tp->label, "ccitt"); 461 tp->subid = 0; 462 tp->type = 0; 463 tp->description = 0; 464 XXX nodes isn't needed in do_subtree() ??? 465 do_subtree(tp, &nodes); 466 lasttp = tp; 467*/ 468 469 /* build root node */ 470 tp = (struct tree *)Malloc(sizeof(struct tree)); 471 tp->parent = NULL; 472/* 473-- Olivier Reisacher 95/2/14 474 tp->next_peer = lasttp; 475*/ 476 tp->next_peer = NULL; 477 tp->child_list = NULL; 478 tp->enums = NULL; 479 strcpy(tp->label, "iso"); 480 tp->subid = 1; 481 tp->type = 0; 482 tp->description = 0; 483 /* XXX nodes isn't needed in do_subtree() ??? */ 484 do_subtree(tp, &nodes); 485/* 486-- Olivier Reisacher 95/2/14 487*/ 488 tp->access = 0; 489 tp->indexs = NULL; 490 tp->n_indexs = 0; 491 492 493#ifdef TEST 494 print_subtree(tp, 0); 495#endif /* TEST */ 496 /* If any nodes are left, the tree is probably inconsistent */ 497 for(bucket = 0; bucket < NHASHSIZE; bucket++){ 498 if (nbuckets[bucket]){ 499 nodes_left = 1; 500 break; 501 } 502 } 503 if (nodes_left){ 504 fprintf(stderr, "The mib description doesn't seem to be consistent.\n"); 505 fprintf(stderr, "Some nodes couldn't be linked under the \"iso\" tree.\n"); 506 fprintf(stderr, "these nodes are left:\n"); 507 for(bucket = 0; bucket < NHASHSIZE; bucket++){ 508 for(np = nbuckets[bucket]; np; np = np->next) 509 fprintf(stderr, "%s ::= { %s %d } (%d)\n", np->label, 510 np->parent, np->subid, np->type); 511 } 512 } 513 return tp; 514} 515 516/* 517 * Find all the children of root in the list of nodes. Link them into the 518 * tree and out of the nodes list. 519 */ 520static void 521do_subtree(root, nodes) 522 struct tree *root; 523 struct node **nodes; 524{ 525 register struct tree *tp; 526 register struct node *np, **headp; 527 struct node *oldnp = NULL, *child_list = NULL, *childp = NULL; 528 char *cp; 529 int hash; 530 531 tp = root; 532 hash = 0; 533 for(cp = tp->label; *cp; cp++) 534 hash += *cp; 535 headp = &nbuckets[NBUCKET(hash)]; 536 /* 537 * Search each of the nodes for one whose parent is root, and 538 * move each into a separate list. 539 */ 540 for(np = *headp; np; np = np->next){ 541 if ((*tp->label != *np->parent) || strcmp(tp->label, np->parent)){ 542 if ((*tp->label == *np->label) && !strcmp(tp->label, np->label)){ 543 /* if there is another node with the same label, assume that 544 * any children after this point in the list belong to the other node. 545 * This adds some scoping to the table and allows vendors to 546 * reuse names such as "ip". 547 */ 548 break; 549 } 550 oldnp = np; 551 } else { 552 if (child_list == NULL){ 553 child_list = childp = np; /* first entry in child list */ 554 } else { 555 childp->next = np; 556 childp = np; 557 } 558 /* take this node out of the node list */ 559 if (oldnp == NULL){ 560 *headp = np->next; /* fix root of node list */ 561 } else { 562 oldnp->next = np->next; /* link around this node */ 563 } 564 } 565 } 566 if (childp) 567 childp->next = 0; /* re-terminate list */ 568 /* 569 * Take each element in the child list and place it into the tree. 570 */ 571 for(np = child_list; np; np = np->next){ 572 tp = (struct tree *)Malloc(sizeof(struct tree)); 573 tp->parent = root; 574 tp->next_peer = NULL; 575 tp->child_list = NULL; 576 strcpy(tp->label, np->label); 577 tp->subid = np->subid; 578 tp->type = translation_table[np->type]; 579 tp->oct_str_len = np->oct_str_len; 580 tp->enums = np->enums; 581 np->enums = NULL; /* so we don't free them later */ 582 tp->description = np->description; /* steals memory from np */ 583 np->description = NULL; /* so we don't free it later */ 584/* 585-- Olivier Reisacher 95/2/14 586*/ 587 tp->access = np->access; 588 tp->indexs = np->indexs; 589 np->indexs = NULL; 590 tp->n_indexs = np->n_indexs; 591/* 592-- Olivier Reisacher 95/2/14 593-- The goal of this modification is to order the 594-- tree according to the subid 595 596 if (root->child_list == NULL){ 597 root->child_list = tp; 598 } else { 599 peer->next_peer = tp; 600 } 601 peer = tp; 602*/ 603 if(root->child_list == NULL) 604 { 605 root->child_list = tp; 606 } 607 else 608 { 609 struct tree *t = root->child_list; 610 struct tree *l = NULL; 611 612 while(t) 613 { 614 if(tp->subid < t->subid) 615 { 616 break; 617 } 618 l = t; 619 t = t->next_peer; 620 } 621 if(l == NULL) 622 { 623 tp->next_peer = root->child_list; 624 root->child_list = tp; 625 } 626 else 627 { 628 tp->next_peer = l->next_peer; 629 l->next_peer = tp; 630 } 631 } 632 633/* if (tp->type == TYPE_OTHER) */ 634 do_subtree(tp, nodes); /* recurse on this child if it isn't 635 an end node */ 636 } 637 /* free all nodes that were copied into tree */ 638 oldnp = NULL; 639 for(np = child_list; np; np = np->next){ 640 if (oldnp) 641 free(oldnp); 642 oldnp = np; 643 } 644 if (oldnp) 645 free(oldnp); 646} 647 648 649/* 650 * Takes a list of the form: 651 * { iso org(3) dod(6) 1 } 652 * and creates several nodes, one for each parent-child pair. 653 * Returns NULL on error. 654 */ 655static int 656getoid(fp, oid, length) 657 register FILE *fp; 658 register struct subid *oid; /* an array of subids */ 659 int length; /* the length of the array */ 660{ 661 register int count; 662 int type; 663 char token[MAXTOKEN]; 664 register char *cp; 665 666#ifdef TRACE_PROC 667printf("getoid() invoked\n"); 668#endif 669 670 if ((type = get_token(fp, token)) != LEFTBRACKET){ 671 print_error("Expected \"{\"", token, type); 672 return NULL; 673 } 674 type = get_token(fp, token); 675 for(count = 0; count < length; count++, oid++){ 676 oid->label = 0; 677 oid->subid = -1; 678 if (type == RIGHTBRACKET){ 679 return count; 680 } else if (type != LABEL && type != NUMBER){ 681 print_error("Not valid for object identifier", token, type); 682 return NULL; 683 } 684 if (type == LABEL){ 685 /* this entry has a label */ 686 cp = (char *)Malloc((unsigned)strlen(token) + 1); 687 strcpy(cp, token); 688 oid->label = cp; 689 type = get_token(fp, token); 690 if (type == LEFTPAREN){ 691 type = get_token(fp, token); 692 if (type == NUMBER){ 693 oid->subid = atoi(token); 694 if ((type = get_token(fp, token)) != RIGHTPAREN){ 695 print_error("Unexpected a closing parenthesis", token, type); 696 return NULL; 697 } 698 } else { 699 print_error("Expected a number", token, type); 700 return NULL; 701 } 702 } else { 703 continue; 704 } 705 } else { 706 /* this entry has just an integer sub-identifier */ 707 oid->subid = atoi(token); 708 } 709 type = get_token(fp, token); 710 } 711 return count; 712 713 714} 715 716static void 717free_node(np) 718 struct node *np; 719{ 720 struct enum_list *ep, *tep; 721/* 722-- Olivier Reisacher 95/2/14 723*/ 724 struct index_list *ip, *tip; 725 726 ip = np->indexs; 727 while(ip) 728 { 729 tip = ip; 730 ip = ip->next; 731 free((char *)tip); 732 } 733 734 735 ep = np->enums; 736 while(ep){ 737 tep = ep; 738 ep = ep->next; 739 free((char *)tep); 740 } 741 free((char *)np); 742} 743 744int parse_traptype(fp,name) 745FILE *fp; 746char *name; 747{ 748 int type; 749 char token[MAXTOKEN]; 750 struct trap_item *ti; 751 struct index_list *ip; 752 static struct trap_item *last_trap_item=NULL; 753 754#ifdef TRACE_PROC 755printf("parse_traptype() invoked\n"); 756#endif 757 758 type = get_token(fp,token); 759 if( type == ENTERPRISE){ 760 if( (type = get_token(fp,token)) == LABEL){ 761 /* create a trap item */ 762 ti = (struct trap_item*)calloc(1, sizeof(struct trap_item)); 763 if(ti==NULL){ 764 fprintf(stderr,"calloc failed\n"); 765 return 0; 766 } 767 strcpy(ti->label,name); 768 strcpy(ti->enterprise_label,token); 769 ti->enterprise_subids[0] = (u_long)-1; 770 771 type = get_token(fp,token); 772 while(type != EQUALS){ 773 switch(type){ 774 case VARIABLES: 775 type = get_token(fp,token); 776 if(type != LEFTBRACKET){ 777 print_error("{ expected in VARIABLES clause",token,type); 778 free(ti); 779 return 0; 780 } 781 type = get_token(fp,token); 782 while(type != RIGHTBRACKET) 783 { 784 if(type != LABEL) 785 { 786 print_error("LABEL expected in VARIABLES1 clause",token,type); 787 free(ti); 788 return 0; 789 } 790 791 792 (ti->n_variables)++; 793 if(ti->var_list == NULL) 794 { 795 ip = ti->var_list = (struct index_list *) 796 Malloc(sizeof(struct index_list)); 797 } 798 else 799 { 800 ip->next = (struct index_list *) 801 Malloc(sizeof(struct enum_list)); 802 ip = ip->next; 803 } 804 ip->next = 0; 805 ip->tp = NULL; 806 807 ip->label = 808 (char *)Malloc((unsigned)strlen(token) + 1); 809 strcpy(ip->label, token); 810 811 type = get_token(fp, token); 812 813 switch(type) 814 { 815 case COMMA: 816 type = get_token(fp, token); 817 break; 818 819 case RIGHTBRACKET: 820 break; 821 822 default: 823 print_error(", or } expected in VARIABLES clause",token,type); 824 free(ti); 825 return 0; 826 827 } 828 } 829 break; 830 831 case DESCRIPTION: 832 type = get_token(fp,token); 833 if(type != QUOTESTRING){ 834 print_error("Bad DESCRIPTION",token,type); 835 free(ti); 836 return 0; 837 } 838 ti->description = quoted_string_buffer; 839 quoted_string_buffer = (char*)malloc(MAXQUOTESTR); 840 if(quoted_string_buffer==NULL){ 841 fprintf(stderr,"malloc failed\n"); 842 return 0; 843 } 844 break; 845 case REFERENCE: 846 type = get_token(fp,token); 847 if(type != QUOTESTRING){ 848 print_error("Bad DESCRIPTION",token,type); 849 free(ti); 850 return 0; 851 } 852 break; 853 default: 854 /* NOTHING*/ 855 break; 856 } 857 type = get_token(fp,token); 858 } 859 /* get the integer */ 860 if( (type = get_token(fp,token)) == NUMBER){ 861 ti->value = atoi(token); 862 /* attach the item to list */ 863 864 865 866 }else{ 867 print_error("Expected a number",token,type); 868 free(ti); 869 return 0; 870 } 871 }else{ 872 print_error("Expected \"enterprise name\"",token,type); 873 return 0; 874 } 875 }else{ 876 print_error("Expected \"ENTERPRISE\"",token,type); 877 return 0; 878 } 879 if(trap_list == NULL){ 880 last_trap_item = trap_list = ti; 881 }else{ 882 last_trap_item->next = ti; 883 last_trap_item = ti; 884 } 885 return 1; 886} 887 888/* 889 * Parse an entry of the form: 890 * label OBJECT IDENTIFIER ::= { parent 2 } 891 * The "label OBJECT IDENTIFIER" portion has already been parsed. 892 * Returns 0 on error. 893 */ 894static struct node * 895parse_objectid(fp, name) 896 FILE *fp; 897 char *name; 898{ 899 int type; 900 char token[MAXTOKEN]; 901 register int count; 902 register struct subid *op, *nop; 903 int length; 904 struct subid oid[32]; 905 struct node *np, *root, *oldnp = NULL; 906 907 type = get_token(fp, token); 908 if (type != EQUALS){ 909 print_error("Bad format", token, type); 910 return 0; 911 } 912 if ((length = getoid(fp, oid, 32)) != 0){ 913 np = root = (struct node *)Malloc(sizeof(struct node)); 914 915/* 916-- Olivier Reisacher 95/2/14 917 bzero((char *)np, sizeof(struct node)); 918*/ 919 memset((void *) np, 0, sizeof(struct node)); 920 921 /* 922 * For each parent-child subid pair in the subid array, 923 * create a node and link it into the node list. 924 */ 925 for(count = 0, op = oid, nop=oid+1; count < (length - 2); count++, 926 op++, nop++){ 927 /* every node must have parent's name and child's name or number */ 928 if (op->label && (nop->label || (nop->subid != -1))){ 929 strcpy(np->parent, op->label); 930 if (nop->label) 931 strcpy(np->label, nop->label); 932 if (nop->subid != -1) 933 np->subid = nop->subid; 934 np->type = 0; 935 np->enums = 0; 936/* 937-- Olivier Reisacher 95/2/14 938*/ 939 np->access = 0; 940 np->n_indexs = 0; 941 np->indexs = NULL; 942 943 /* set up next entry */ 944 np->next = (struct node *)Malloc(sizeof(*np->next)); 945 946/* 947-- Olivier Reisacher 95/2/14 948 bzero((char *)np->next, sizeof(struct node)); 949*/ 950 memset((void *) np->next, 0, sizeof(struct node)); 951 952 oldnp = np; 953 np = np->next; 954 } 955 } 956 np->next = (struct node *)NULL; 957 /* 958 * The above loop took care of all but the last pair. This pair is taken 959 * care of here. The name for this node is taken from the label for this 960 * entry. 961 * np still points to an unused entry. 962 */ 963 if (count == (length - 2)){ 964 if (op->label){ 965 strcpy(np->parent, op->label); 966 strcpy(np->label, name); 967 if (nop->subid != -1) 968 np->subid = nop->subid; 969 else 970 print_error("Warning: This entry is pretty silly", 971 np->label, type); 972 } else { 973 free_node(np); 974 if (oldnp) 975 oldnp->next = NULL; 976 else 977 return NULL; 978 } 979 } else { 980 print_error("Missing end of oid", (char *)NULL, type); 981 free_node(np); /* the last node allocated wasn't used */ 982 if (oldnp) 983 oldnp->next = NULL; 984 return NULL; 985 } 986 /* free the oid array */ 987 for(count = 0, op = oid; count < length; count++, op++){ 988 if (op->label) 989 free(op->label); 990 op->label = 0; 991 } 992 return root; 993 } else { 994 print_error("Bad object identifier", (char *)NULL, type); 995 return 0; 996 } 997} 998 999static int 1000get_tc(descriptor, ep) 1001 char *descriptor; 1002 struct enum_list **ep; 1003{ 1004 int i; 1005 1006 for(i = 0; i < MAXTC; i++){ 1007 if (tclist[i].type == 0) 1008 break; 1009 if (!strcmp(descriptor, tclist[i].descriptor)){ 1010 *ep = tclist[i].enums; 1011 return tclist[i].type; 1012 } 1013 } 1014 return LABEL; 1015} 1016 1017/* 1018 * Parses an asn type. Structures are ignored by this parser. 1019 * Returns NULL on error. 1020 */ 1021static int 1022parse_asntype(fp, name, ntype, ntoken) 1023 FILE *fp; 1024 char *name; 1025 int *ntype; 1026 char *ntoken; 1027{ 1028 int type, i; 1029 char token[MAXTOKEN]; 1030 struct enum_list *ep; 1031 struct tc *tcp; 1032 int level; 1033 1034#ifdef TRACE_PROC 1035printf("parse_asntype() invoked\n"); 1036#endif 1037 1038 type = get_token(fp, token); 1039 if (type == SEQUENCE){ 1040 while((type = get_token(fp, token)) != ENDOFFILE){ 1041 if (type == RIGHTBRACKET){ 1042 *ntype = get_token(fp, ntoken); 1043 return 1; 1044 } 1045 } 1046 print_error("Expected \"}\"", token, type); 1047 return 0; 1048 } else { 1049 if (!strcmp(token, "TEXTUAL-CONVENTION")){ 1050 while (type != SYNTAX) 1051 type = get_token(fp, token); 1052 type = get_token(fp, token); 1053 } 1054 /* textual convention */ 1055 for(i = 0; i < MAXTC; i++){ 1056 if (tclist[i].type == 0) 1057 break; 1058 } 1059 if (i == MAXTC){ 1060 print_error("No more textual conventions possible.", token, type); 1061 return 0; 1062 } 1063 tcp = &tclist[i]; 1064 strcpy(tcp->descriptor, name); 1065 if (!(type & SYNTAX_MASK)){ 1066 1067/* 1068-- Olivier Reisacher 95/2/14 1069 print_error("Textual convention doesn't map to real type.", token, 1070 type); 1071 return 0; 1072 } 1073*/ 1074 int w; 1075 1076 w = get_tc(token, &ep); 1077 if(!(w & SYNTAX_MASK)) 1078 { 1079 print_error("Textual convention doesn't map to real type.", token, type); 1080 return 0; 1081 } 1082 type = w; 1083 } 1084 1085 tcp->type = type; 1086 *ntype = get_token(fp, ntoken); 1087 if (*ntype == LEFTPAREN){ 1088 level = 1; 1089 /* don't record any constraints for now */ 1090 while(level > 0){ 1091 *ntype = get_token(fp, ntoken); 1092 if (*ntype == LEFTPAREN) 1093 level++; 1094 if (*ntype == RIGHTPAREN) 1095 level--; 1096 } 1097 *ntype = get_token(fp, ntoken); 1098 } else if (*ntype == LEFTBRACKET) { 1099 /* if there is an enumeration list, parse it */ 1100 while((type = get_token(fp, token)) != ENDOFFILE){ 1101 if (type == RIGHTBRACKET) 1102 break; 1103 if (type == LABEL){ 1104 /* this is an enumerated label */ 1105 if (tcp->enums == 0){ 1106 ep = tcp->enums = (struct enum_list *) 1107 Malloc(sizeof(struct enum_list)); 1108 } else { 1109 ep->next = (struct enum_list *) 1110 Malloc(sizeof(struct enum_list)); 1111 ep = ep->next; 1112 } 1113 ep->next = 0; 1114 /* a reasonable approximation for the length */ 1115 ep->label = 1116 (char *)Malloc((unsigned)strlen(token) + 1); 1117 strcpy(ep->label, token); 1118 type = get_token(fp, token); 1119 if (type != LEFTPAREN){ 1120 print_error("Expected \"(\"", token, type); 1121 /* free_node(np); */ 1122 return 0; 1123 } 1124 type = get_token(fp, token); 1125 if (type != NUMBER){ 1126 print_error("Expected integer", token, type); 1127 /* free_node(np); */ 1128 return 0; 1129 } 1130 ep->value = atoi(token); 1131 type = get_token(fp, token); 1132 if (type != RIGHTPAREN){ 1133 print_error("Expected \")\"", token, type); 1134 /* free_node(np); */ 1135 return 0; 1136 } 1137 } 1138 } 1139 if (type == ENDOFFILE){ 1140 print_error("Expected \"}\"", token, type); 1141 /* free_node(np); */ 1142 return 0; 1143 } 1144 *ntype = get_token(fp, ntoken); 1145 } 1146 return 1; 1147 } 1148} 1149 1150 1151/* 1152 * Parses an OBJECT TYPE macro. 1153 * Returns 0 on error. 1154 */ 1155static struct node * 1156parse_objecttype(fp, name) 1157 register FILE *fp; 1158 char *name; 1159{ 1160 register int type; 1161 char token[MAXTOKEN]; 1162 int count, length; 1163 struct subid oid[32]; 1164 char syntax[MAXTOKEN]; 1165 int nexttype, tctype; 1166 char nexttoken[MAXTOKEN]; 1167 register struct node *np; 1168 register struct enum_list *ep; 1169/* 1170-- Olivier Reisacher 95/2/14 1171*/ 1172 struct index_list *ip; 1173 1174 type = get_token(fp, token); 1175 if (type != SYNTAX){ 1176 print_error("Bad format for OBJECT TYPE", token, type); 1177 return 0; 1178 } 1179 np = (struct node *)Malloc(sizeof(struct node)); 1180 np->next = 0; 1181 np->enums = 0; 1182 np->description = NULL; /* default to an empty description */ 1183/* 1184-- Olivier Reisacher 95/2/14 1185*/ 1186 np->access = 0; 1187 np->n_indexs = 0; 1188 np->indexs = 0; 1189 1190 type = get_token(fp, token); 1191 if (type == LABEL){ 1192 tctype = get_tc(token, &(np->enums)); 1193#if 0 1194 if (tctype == LABEL){ 1195 print_error("No known translation for type", token, type); 1196 return 0; 1197 } 1198#endif 1199 type = tctype; 1200 } 1201 np->type = type; 1202 np->oct_str_len = 0; 1203 nexttype = get_token(fp, nexttoken); 1204 switch(type){ 1205 case SEQUENCE: 1206 strcpy(syntax, token); 1207 if (nexttype == OF){ 1208 strcat(syntax, " "); 1209 strcat(syntax, nexttoken); 1210 nexttype = get_token(fp, nexttoken); 1211 strcat(syntax, " "); 1212 strcat(syntax, nexttoken); 1213 nexttype = get_token(fp, nexttoken); 1214 1215/* 1216-- Olivier Reisacher 95/2/14 1217*/ 1218 np->type = PSEUDO_TOKEN_TABLE; 1219 } 1220 1221 break; 1222 case PARSE_INTEGER: 1223 case UINTEGER32: 1224 strcpy(syntax, token); 1225 if (nexttype == LEFTBRACKET) { 1226 /* if there is an enumeration list, parse it */ 1227 while((type = get_token(fp, token)) != ENDOFFILE){ 1228 if (type == RIGHTBRACKET) 1229 break; 1230 if (type == LABEL){ 1231 /* this is an enumerated label */ 1232 if (np->enums == 0){ 1233 ep = np->enums = (struct enum_list *) 1234 Malloc(sizeof(struct enum_list)); 1235 } else { 1236 ep->next = (struct enum_list *) 1237 Malloc(sizeof(struct enum_list)); 1238 ep = ep->next; 1239 } 1240 ep->next = 0; 1241 /* a reasonable approximation for the length */ 1242 ep->label = 1243 (char *)Malloc((unsigned)strlen(token) + 1); 1244 strcpy(ep->label, token); 1245 type = get_token(fp, token); 1246 if (type != LEFTPAREN){ 1247 print_error("Expected \"(\"", token, type); 1248 free_node(np); 1249 return 0; 1250 } 1251 type = get_token(fp, token); 1252 if (type != NUMBER){ 1253 print_error("Expected integer", token, type); 1254 free_node(np); 1255 return 0; 1256 } 1257 ep->value = atoi(token); 1258 type = get_token(fp, token); 1259 if (type != RIGHTPAREN){ 1260 print_error("Expected \")\"", token, type); 1261 free_node(np); 1262 return 0; 1263 } 1264 } 1265 } 1266 if (type == ENDOFFILE){ 1267 print_error("Expected \"}\"", token, type); 1268 free_node(np); 1269 return 0; 1270 } 1271 nexttype = get_token(fp, nexttoken); 1272 } else if (nexttype == LEFTPAREN){ 1273 /* ignore the "constrained integer" for now */ 1274 nexttype = get_token(fp, nexttoken); 1275 nexttype = get_token(fp, nexttoken); 1276 nexttype = get_token(fp, nexttoken); 1277 } 1278 break; 1279 case BITSTRING: 1280 strcpy(syntax, token); 1281 if (nexttype == LEFTBRACKET) { 1282 /* if there is an enumeration list, parse it */ 1283 while((type = get_token(fp, token)) != ENDOFFILE){ 1284 if (type == RIGHTBRACKET) 1285 break; 1286 if (type == LABEL){ 1287 /* this is an enumerated label */ 1288 if (np->enums == 0){ 1289 ep = np->enums = (struct enum_list *) 1290 Malloc(sizeof(struct enum_list)); 1291 } else { 1292 ep->next = (struct enum_list *) 1293 Malloc(sizeof(struct enum_list)); 1294 ep = ep->next; 1295 } 1296 ep->next = 0; 1297 /* a reasonable approximation for the length */ 1298 ep->label = 1299 (char *)Malloc((unsigned)strlen(token) + 1); 1300 strcpy(ep->label, token); 1301 type = get_token(fp, token); 1302 if (type != LEFTPAREN){ 1303 print_error("Expected \"(\"", token, type); 1304 free_node(np); 1305 return 0; 1306 } 1307 type = get_token(fp, token); 1308 if (type != NUMBER){ 1309 print_error("Expected integer", token, type); 1310 free_node(np); 1311 return 0; 1312 } 1313 ep->value = atoi(token); 1314 type = get_token(fp, token); 1315 if (type != RIGHTPAREN){ 1316 print_error("Expected \")\"", token, type); 1317 free_node(np); 1318 return 0; 1319 } 1320 } 1321 } 1322 if (type == ENDOFFILE){ 1323 print_error("Expected \"}\"", token, type); 1324 free_node(np); 1325 return 0; 1326 } 1327 nexttype = get_token(fp, nexttoken); 1328 } else if (nexttype == LEFTPAREN){ 1329 /* ignore the "constrained integer" for now */ 1330 nexttype = get_token(fp, nexttoken); 1331 nexttype = get_token(fp, nexttoken); 1332 nexttype = get_token(fp, nexttoken); 1333 } 1334 break; 1335 case OCTETSTR: 1336 strcpy(syntax, token); 1337 /* ignore the "constrained octet string" for now */ 1338 if (nexttype == LEFTPAREN) { 1339 nexttype = get_token(fp, nexttoken); 1340 if (nexttype == SIZE) { 1341 nexttype = get_token(fp, nexttoken); 1342 if (nexttype == LEFTPAREN) { 1343 nexttype = get_token(fp, nexttoken); /* 0..255 */ 1344 np->oct_str_len = number_value; 1345 number_value = 0; 1346 nexttype = get_token(fp, nexttoken); /* ) */ 1347 nexttype = get_token(fp, nexttoken); /* ) */ 1348 if (nexttype == RIGHTPAREN) 1349 { 1350 nexttype = get_token(fp, nexttoken); 1351 break; 1352 } 1353 } 1354 } 1355 print_error("Bad syntax", token, type); 1356 free_node(np); 1357 return 0; 1358 } 1359 break; 1360 case PARSE_OBJID: 1361 case NETADDR: 1362 case IPADDR: 1363 case PARSE_COUNTER: 1364 case PARSE_GUAGE: 1365 case PARSE_TIMETICKS: 1366 case PARSE_OPAQUE: 1367 case NUL: 1368 case LABEL: 1369 case NSAPADDRESS: 1370 case PARSE_COUNTER64: 1371 strcpy(syntax, token); 1372 break; 1373 default: 1374 print_error("Bad syntax", token, type); 1375 free_node(np); 1376 return 0; 1377 } 1378 if (nexttype == UNITS){ 1379 type = get_token(fp, token); 1380 if (type != QUOTESTRING) { 1381 print_error("Bad DESCRIPTION", token, type); 1382 free_node(np); 1383 return 0; 1384 } 1385 nexttype = get_token(fp, nexttoken); 1386 } 1387 if (nexttype != ACCESS){ 1388 print_error("Should be ACCESS", nexttoken, nexttype); 1389 free_node(np); 1390 return 0; 1391 } 1392 type = get_token(fp, token); 1393 if (type != READONLY && type != READWRITE && type != WRITEONLY 1394 && type != NOACCESS && type != READCREATE){ 1395 print_error("Bad access type", nexttoken, nexttype); 1396 free_node(np); 1397 return 0; 1398 } 1399 1400/* 1401-- Olivier Reisacher 95/2/14 1402*/ 1403 switch(type) 1404 { 1405 case READONLY: 1406 np->access = READ_FLAG; 1407 break; 1408 1409 case READWRITE: 1410 np->access = READ_FLAG | WRITE_FLAG; 1411 break; 1412 1413 case WRITEONLY: 1414 np->access = WRITE_FLAG; 1415 break; 1416 1417 case NOACCESS: 1418 np->access = 0; 1419 break; 1420 1421 case READCREATE: 1422 np->access = READ_FLAG | CREATE_FLAG; 1423 break; 1424 } 1425 1426 type = get_token(fp, token); 1427 if (type != STATUS){ 1428 print_error("Should be STATUS", token, nexttype); 1429 free_node(np); 1430 return 0; 1431 } 1432 type = get_token(fp, token); 1433 if (type != MANDATORY && type != CURRENT && type != OPTIONAL && type != OBSOLETE && type != DEPRECATED){ 1434 print_error("Bad status", token, type); 1435 free_node(np); 1436 return 0; 1437 } 1438 /* 1439 * Optional parts of the OBJECT-TYPE macro 1440 */ 1441 type = get_token(fp, token); 1442 while (type != EQUALS) { 1443 switch (type) { 1444 case DESCRIPTION: 1445 type = get_token(fp, token); 1446 if (type != QUOTESTRING) { 1447 print_error("Bad DESCRIPTION", token, type); 1448 free_node(np); 1449 return 0; 1450 } 1451#ifdef TEST 1452printf("Description== \"%.50s\"\n", quoted_string_buffer); 1453#endif 1454 np->description = quoted_string_buffer; 1455 quoted_string_buffer = (char *)malloc(MAXQUOTESTR); 1456 if (!quoted_string_buffer){ 1457 fprintf(stderr, "malloc failed. Exiting\n"); 1458 exit(1); 1459 } 1460 break; 1461 1462 case REFERENCE: 1463 type = get_token(fp, token); 1464 if (type != QUOTESTRING) { 1465 print_error("Bad DESCRIPTION", token, type); 1466 free_node(np); 1467 return 0; 1468 } 1469 break; 1470/* 1471-- Olivier Reisacher 95/2/14 1472*/ 1473 case INDEX: 1474 np->type = PSEUDO_TOKEN_ENTRY; 1475 1476 type = get_token(fp, token); 1477 if(type != LEFTBRACKET) 1478 { 1479 print_error("{ expected in INDEX clause",token,type); 1480 free_node(np); 1481 return 0; 1482 } 1483 type = get_token(fp, token); 1484 while(type != RIGHTBRACKET) 1485 { 1486 if(type != LABEL) 1487 { 1488 print_error("LABEL expected in INDEX clause",token,type); 1489 free_node(np); 1490 return 0; 1491 } 1492 1493 1494 (np->n_indexs)++; 1495 if(np->indexs == NULL) 1496 { 1497 ip = np->indexs = (struct index_list *) 1498 Malloc(sizeof(struct index_list)); 1499 } 1500 else 1501 { 1502 ip->next = (struct index_list *) 1503 Malloc(sizeof(struct enum_list)); 1504 ip = ip->next; 1505 } 1506 ip->next = 0; 1507 ip->tp = NULL; 1508 1509 ip->label = 1510 (char *)Malloc((unsigned)strlen(token) + 1); 1511 strcpy(ip->label, token); 1512 1513 type = get_token(fp, token); 1514 1515 switch(type) 1516 { 1517 case COMMA: 1518 type = get_token(fp, token); 1519 break; 1520 1521 case RIGHTBRACKET: 1522 break; 1523 1524 default: 1525 print_error(", or } expected in INDEX clause",token,type); 1526 free_node(np); 1527 return 0; 1528 1529 } 1530 } 1531 break; 1532 1533 case DEFVAL: 1534 case AUGMENTS: 1535 case NUM_ENTRIES: 1536 if (tossObjectIdentifier(fp) != PARSE_OBJID) { 1537 print_error("Bad Object Identifier", token, type); 1538 free_node(np); 1539 return 0; 1540 } 1541 break; 1542 1543 default: 1544 print_error("Bad format of optional clauses", token,type); 1545 free_node(np); 1546 return 0; 1547 1548 } 1549 type = get_token(fp, token); 1550 } 1551 if (type != EQUALS){ 1552 print_error("Bad format", token, type); 1553 free_node(np); 1554 return 0; 1555 } 1556 length = getoid(fp, oid, 32); 1557 if (length > 1 && length <= 32){ 1558 /* just take the last pair in the oid list */ 1559 if (oid[length - 2].label) 1560 strncpy(np->parent, oid[length - 2].label, MAXLABEL); 1561 strcpy(np->label, name); 1562 if (oid[length - 1].subid != -1) 1563 np->subid = oid[length - 1].subid; 1564 else 1565 print_error("Warning: This entry is pretty silly", np->label, type); 1566 } else { 1567 print_error("No end to oid", (char *)NULL, type); 1568 free_node(np); 1569 np = 0; 1570 } 1571 /* free oid array */ 1572 for(count = 0; count < length; count++){ 1573 if (oid[count].label) 1574 free(oid[count].label); 1575 oid[count].label = 0; 1576 } 1577 return np; 1578} 1579 1580 1581/* 1582 * Parses an OBJECT GROUP macro. 1583 * Returns 0 on error. 1584 */ 1585static struct node * 1586parse_objectgroup(fp, name) 1587 register FILE *fp; 1588 char *name; 1589{ 1590 register int type; 1591 char token[MAXTOKEN]; 1592 int count, length; 1593 struct subid oid[32]; 1594 register struct node *np; 1595 1596 np = (struct node *)Malloc(sizeof(struct node)); 1597 np->type = 0; 1598 np->next = 0; 1599 np->enums = 0; 1600 np->description = NULL; /* default to an empty description */ 1601 1602/* 1603-- Olivier Reisacher 95/2/14 1604*/ 1605 np->access = 0; 1606 np->n_indexs = 0; 1607 np->indexs = 0; 1608 1609 type = get_token(fp, token); 1610 while (type != EQUALS) { 1611 switch (type) { 1612 case DESCRIPTION: 1613 type = get_token(fp, token); 1614 if (type != QUOTESTRING) { 1615 print_error("Bad DESCRIPTION", token, type); 1616 free_node(np); 1617 return 0; 1618 } 1619#ifdef TEST 1620printf("Description== \"%.50s\"\n", quoted_string_buffer); 1621#endif 1622 np->description = quoted_string_buffer; 1623 quoted_string_buffer = (char *)malloc(MAXQUOTESTR); 1624 if (!quoted_string_buffer){ 1625 fprintf(stderr, "malloc failed. Exiting\n"); 1626 exit(1); 1627 } 1628 break; 1629 1630 default: 1631 /* NOTHING */ 1632 break; 1633 } 1634 type = get_token(fp, token); 1635 } 1636 length = getoid(fp, oid, 32); 1637 if (length > 1 && length <= 32){ 1638 /* just take the last pair in the oid list */ 1639 if (oid[length - 2].label) 1640 strncpy(np->parent, oid[length - 2].label, MAXLABEL); 1641 strcpy(np->label, name); 1642 if (oid[length - 1].subid != -1) 1643 np->subid = oid[length - 1].subid; 1644 else 1645 print_error("Warning: This entry is pretty silly", np->label, type); 1646 } else { 1647 print_error("No end to oid", (char *)NULL, type); 1648 free_node(np); 1649 np = 0; 1650 } 1651 /* free oid array */ 1652 for(count = 0; count < length; count++){ 1653 if (oid[count].label) 1654 free(oid[count].label); 1655 oid[count].label = 0; 1656 } 1657 return np; 1658} 1659 1660/* 1661 * Parses a NOTIFICATION-TYPE macro. 1662 * Returns 0 on error. 1663 */ 1664static struct node * 1665parse_notificationDefinition(fp, name) 1666 register FILE *fp; 1667 char *name; 1668{ 1669 register int type; 1670 char token[MAXTOKEN]; 1671 int count, length; 1672 struct subid oid[32]; 1673 register struct node *np; 1674 1675 np = (struct node *)Malloc(sizeof(struct node)); 1676 np->type = 0; 1677 np->next = 0; 1678 np->enums = 0; 1679 np->description = NULL; /* default to an empty description */ 1680/* 1681-- Olivier Reisacher 95/2/14 1682*/ 1683 np->access = 0; 1684 np->n_indexs = 0; 1685 np->indexs = 0; 1686 1687 type = get_token(fp, token); 1688 while (type != EQUALS) { 1689 switch (type) { 1690 case DESCRIPTION: 1691 type = get_token(fp, token); 1692 if (type != QUOTESTRING) { 1693 print_error("Bad DESCRIPTION", token, type); 1694 free_node(np); 1695 return 0; 1696 } 1697#ifdef TEST 1698printf("Description== \"%.50s\"\n", quoted_string_buffer); 1699#endif 1700 np->description = quoted_string_buffer; 1701 quoted_string_buffer = (char *)malloc(MAXQUOTESTR); 1702 if (!quoted_string_buffer){ 1703 fprintf(stderr, "malloc failed. Exiting\n"); 1704 exit(1); 1705 } 1706 break; 1707 1708 default: 1709 /* NOTHING */ 1710 break; 1711 } 1712 type = get_token(fp, token); 1713 } 1714 length = getoid(fp, oid, 32); 1715 if (length > 1 && length <= 32){ 1716 /* just take the last pair in the oid list */ 1717 if (oid[length - 2].label) 1718 strncpy(np->parent, oid[length - 2].label, MAXLABEL); 1719 strcpy(np->label, name); 1720 if (oid[length - 1].subid != -1) 1721 np->subid = oid[length - 1].subid; 1722 else 1723 print_error("Warning: This entry is pretty silly", np->label, type); 1724 } else { 1725 print_error("No end to oid", (char *)NULL, type); 1726 free_node(np); 1727 np = 0; 1728 } 1729 /* free oid array */ 1730 for(count = 0; count < length; count++){ 1731 if (oid[count].label) 1732 free(oid[count].label); 1733 oid[count].label = 0; 1734 } 1735 return np; 1736} 1737 1738/* 1739 * Parses a compliance macro 1740 * Returns 0 on error. 1741 */ 1742static struct node * 1743parse_compliance(fp, name) 1744 register FILE *fp; 1745 char *name; 1746{ 1747 register int type; 1748 char token[MAXTOKEN]; 1749 int count, length; 1750 struct subid oid[32]; 1751 register struct node *np; 1752 1753 np = (struct node *)Malloc(sizeof(struct node)); 1754 np->type = 0; 1755 np->next = 0; 1756 np->enums = 0; 1757 np->description = NULL; /* default to an empty description */ 1758/* 1759-- Olivier Reisacher 95/2/14 1760*/ 1761 np->access = 0; 1762 np->n_indexs = 0; 1763 np->indexs = 0; 1764 1765 type = get_token(fp, token); 1766 while (type != EQUALS) { 1767 type = get_token(fp, token); 1768 } 1769 length = getoid(fp, oid, 32); 1770 if (length > 1 && length <= 32){ 1771 /* just take the last pair in the oid list */ 1772 if (oid[length - 2].label) 1773 strncpy(np->parent, oid[length - 2].label, MAXLABEL); 1774 strcpy(np->label, name); 1775 if (oid[length - 1].subid != -1) 1776 np->subid = oid[length - 1].subid; 1777 else 1778 print_error("Warning: This entry is pretty silly", np->label, type); 1779 } else { 1780 print_error("No end to oid", (char *)NULL, type); 1781 free_node(np); 1782 np = 0; 1783 } 1784 /* free oid array */ 1785 for(count = 0; count < length; count++){ 1786 if (oid[count].label) 1787 free(oid[count].label); 1788 oid[count].label = 0; 1789 } 1790 return np; 1791} 1792 1793 1794 1795/* 1796 * Parses a module identity macro 1797 * Returns 0 on error. 1798 */ 1799static struct node * 1800parse_moduleIdentity(fp, name) 1801 register FILE *fp; 1802 char *name; 1803{ 1804 register int type; 1805 char token[MAXTOKEN]; 1806 int count, length; 1807 struct subid oid[32]; 1808 register struct node *np; 1809 1810 np = (struct node *)Malloc(sizeof(struct node)); 1811 np->type = 0; 1812 np->next = 0; 1813 np->enums = 0; 1814 np->description = NULL; /* default to an empty description */ 1815/* 1816-- Olivier Reisacher 95/2/14 1817*/ 1818 np->n_indexs = 0; 1819 np->indexs = 0; 1820 np->access = 0; 1821 1822 type = get_token(fp, token); 1823 while (type != EQUALS) { 1824 type = get_token(fp, token); 1825 } 1826 length = getoid(fp, oid, 32); 1827 if (length > 1 && length <= 32){ 1828 /* just take the last pair in the oid list */ 1829 if (oid[length - 2].label) 1830 strncpy(np->parent, oid[length - 2].label, MAXLABEL); 1831 strcpy(np->label, name); 1832 if (oid[length - 1].subid != -1) 1833 np->subid = oid[length - 1].subid; 1834 else 1835 print_error("Warning: This entry is pretty silly", np->label, type); 1836 } else { 1837 print_error("No end to oid", (char *)NULL, type); 1838 free_node(np); 1839 np = 0; 1840 } 1841 /* free oid array */ 1842 for(count = 0; count < length; count++){ 1843 if (oid[count].label) 1844 free(oid[count].label); 1845 oid[count].label = 0; 1846 } 1847 return np; 1848} 1849 1850int parse_mib_header(fp, name) 1851 register FILE *fp; 1852 char *name; 1853{ 1854 int type = DEFINITIONS; 1855 char token[MAXTOKEN]; 1856 1857#ifdef TRACE_PROC 1858printf("parse_mib_header() invoked\n"); 1859#endif 1860 1861 /* This probably isn't good enough. If there is no 1862 imports clause we can't go around waiting (forever) for a semicolon. 1863 We need to check for semi following an EXPORTS clause or an IMPORTS 1864 clause of both. Look for BEGIN; in my initial MIBs to see those 1865 that I needed to hack to get to parse because they didn't have 1866 an IMPORTS or and EXPORTS clause. 1867 */ 1868 while(type != SEMI){ 1869 type = get_token(fp, token); 1870 } 1871 return 1; 1872} 1873 1874 1875/* 1876-- Olivier Reisacher 95/2/14 1877*/ 1878void parse_init() 1879{ 1880 hash_init(); 1881 memset((void *) tclist, 0, 64 * sizeof(struct tc)); 1882} 1883 1884 1885/* 1886 * Parses a mib file and returns a linked list of nodes found in the file. 1887 * Returns NULL on error. 1888 */ 1889/* 1890-- Olivier Reisacher 95/2/14 1891static struct node * 1892*/ 1893struct node * 1894parse(fp) 1895 FILE *fp; 1896{ 1897 char token[MAXTOKEN]; 1898 char name[MAXTOKEN]; 1899 int type = 1; 1900#define BETWEEN_MIBS 1 1901#define IN_MIB 2 1902 int state = BETWEEN_MIBS; 1903 struct node *np, *root = NULL; 1904 1905#ifdef TRACE_PROC 1906printf("parse() invoked\n"); 1907#endif 1908 1909/* 1910-- Olivier Reisacher 95/2/14 1911 hash_init(); 1912*/ 1913 Line = 1; 1914 1915 quoted_string_buffer = (char *)malloc(MAXQUOTESTR); /* free this later */ 1916 if (!quoted_string_buffer){ 1917 fprintf(stderr, "malloc failed. Exiting\n"); 1918 exit(1); 1919 } 1920 1921/* 1922-- Olivier Reisacher 95/2/14 1923 bzero(tclist, 64 * sizeof(struct tc)); 1924*/ 1925 1926 while(type != ENDOFFILE){ 1927 type = get_token(fp, token); 1928skipget: 1929 if (type == END){ 1930 if (state != IN_MIB){ 1931 print_error("Error, end before start of MIB.", (char *)NULL, type); 1932 return NULL; 1933 } 1934 state = BETWEEN_MIBS; 1935 continue; 1936 } else if (type != LABEL){ 1937 if (type == ENDOFFILE){ 1938 return root; 1939 } 1940 print_error(token, "is a reserved word", type); 1941 return NULL; 1942 } 1943 strncpy(name, token, MAXTOKEN); 1944 type = get_token(fp, token); 1945 if (type == DEFINITIONS){ 1946 if (state != BETWEEN_MIBS){ 1947 print_error("Error, nested MIBS.", (char *)NULL, type); 1948 return NULL; 1949 } 1950 state = IN_MIB; 1951 if (!parse_mib_header(fp, name)){ 1952 print_error("Bad parse of module header", (char *)NULL, type); 1953 return NULL; 1954 } 1955 } else if (type == OBJTYPE){ 1956 if (root == NULL){ 1957 /* first link in chain */ 1958 np = root = parse_objecttype(fp, name); 1959 if (np == NULL){ 1960 print_error("Bad parse of object type", (char *)NULL, 1961 type); 1962 return NULL; 1963 } 1964 } else { 1965 np->next = parse_objecttype(fp, name); 1966 if (np->next == NULL){ 1967 print_error("Bad parse of objecttype", (char *)NULL, 1968 type); 1969 return NULL; 1970 } 1971 } 1972 /* now find end of chain */ 1973 while(np->next) 1974 np = np->next; 1975 } else if (type == OBJGROUP){ 1976 if (root == NULL){ 1977 /* first link in chain */ 1978 np = root = parse_objectgroup(fp, name); 1979 if (np == NULL){ 1980 print_error("Bad parse of object group", (char *)NULL, 1981 type); 1982 return NULL; 1983 } 1984 } else { 1985 np->next = parse_objectgroup(fp, name); 1986 if (np->next == NULL){ 1987 print_error("Bad parse of objectgroup", (char *)NULL, 1988 type); 1989 return NULL; 1990 } 1991 } 1992 /* now find end of chain */ 1993 while(np->next) 1994 np = np->next; 1995 } else if (type == NOTIFTYPE){ 1996 if (root == NULL){ 1997 /* first link in chain */ 1998 np = root = parse_notificationDefinition(fp, name); 1999 if (np == NULL){ 2000 print_error("Bad parse of notification definition", 2001 (char *)NULL, type); 2002 return NULL; 2003 } 2004 } else { 2005 np->next = parse_notificationDefinition(fp, name); 2006 if (np->next == NULL){ 2007 print_error("Bad parse of notification definition", 2008 (char *)NULL, type); 2009 return NULL; 2010 } 2011 } 2012 /* now find end of chain */ 2013 while(np->next) 2014 np = np->next; 2015 } else if (type == COMPLIANCE){ 2016 if (root == NULL){ 2017 /* first link in chain */ 2018 np = root = parse_compliance(fp, name); 2019 if (np == NULL){ 2020 print_error("Bad parse of module compliance", (char *)NULL, 2021 type); 2022 return NULL; 2023 } 2024 } else { 2025 np->next = parse_compliance(fp, name); 2026 if (np->next == NULL){ 2027 print_error("Bad parse of module compliance", (char *)NULL, 2028 type); 2029 return NULL; 2030 } 2031 } 2032 /* now find end of chain */ 2033 while(np->next) 2034 np = np->next; 2035 } else if (type == MODULEIDENTITY){ 2036 if (root == NULL){ 2037 /* first link in chain */ 2038 np = root = parse_moduleIdentity(fp, name); 2039 if (np == NULL){ 2040 print_error("Bad parse of module identity", (char *)NULL, 2041 type); 2042 return NULL; 2043 } 2044 } else { 2045 np->next = parse_moduleIdentity(fp, name); 2046 if (np->next == NULL){ 2047 print_error("Bad parse of module identity", (char *)NULL, 2048 type); 2049 return NULL; 2050 } 2051 } 2052 /* now find end of chain */ 2053 while(np->next) 2054 np = np->next; 2055 } else if (type == PARSE_OBJID){ 2056 if (root == NULL){ 2057 /* first link in chain */ 2058 np = root = parse_objectid(fp, name); 2059 if (np == NULL){ 2060 print_error("Bad parse of object id", (char *)NULL, type); 2061 return NULL; 2062 } 2063 } else { 2064 np->next = parse_objectid(fp, name); 2065 if (np->next == NULL){ 2066 print_error("Bad parse of object type", (char *)NULL, 2067 type); 2068 return NULL; 2069 } 2070 } 2071 /* now find end of chain */ 2072 while(np->next) 2073 np = np->next; 2074 } else if (type == EQUALS){ 2075 if (!parse_asntype(fp, name, &type, token)){ 2076 print_error("Bad parse of ASN type definition.", (char*)NULL, EQUALS); 2077 return NULL; 2078 } 2079 goto skipget; 2080 } else if (type == TRAPTYPE){ /* Jerry Yeung 6-6-96 */ 2081 if(!parse_traptype(fp,name)){ 2082 print_error("Bad parse of TRAP type",(char*)NULL,type); 2083 return NULL; 2084 } 2085 } else if (type == ENDOFFILE){ 2086 break; 2087 } else { 2088 print_error("Bad operator", (char *)NULL, type); 2089 return NULL; 2090 } 2091 } 2092#ifdef TEST 2093{ 2094 struct enum_list *ep; 2095 2096 for(np = root; np; np = np->next){ 2097 printf("%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid, 2098 np->type); 2099 if (np->enums){ 2100 printf("Enums: \n"); 2101 for(ep = np->enums; ep; ep = ep->next){ 2102 printf("%s(%d)\n", ep->label, ep->value); 2103 } 2104 } 2105 } 2106} 2107#endif /* TEST */ 2108 return root; 2109} 2110 2111/* 2112 * Parses a token from the file. The type of the token parsed is returned, 2113 * and the text is placed in the string pointed to by token. 2114 */ 2115static int 2116get_token(fp, token) 2117 register FILE *fp; 2118 register char *token; 2119{ 2120 static char last = ' '; 2121 register int ch; 2122 register char *cp = token; 2123 register int hash = 0; 2124 register struct tok *tp; 2125 2126 *cp = 0; 2127 ch = last; 2128 /* skip all white space */ 2129 while(isspace(ch) && ch != -1){ 2130 ch = getc(fp); 2131 if (ch == '\n') 2132 Line++; 2133 } 2134 if (ch == -1) { 2135#ifdef TRACE_GET_TOKEN 2136print_error("TRACE", token, ENDOFFILE); 2137#endif 2138 return ENDOFFILE; 2139 } else if (ch == '"') { 2140 return parseQuoteString(fp, token); 2141 } 2142 2143 /* 2144 * Accumulate characters until end of token is found. Then attempt to 2145 * match this token as a reserved word. If a match is found, return the 2146 * type. Else it is a label. 2147 */ 2148 do { 2149 if (ch == '\n') 2150 Line++; 2151 if (isspace(ch) || ch == '(' || ch == ')' || ch == '{' || ch == '}' || 2152 ch == ',' || ch == ';'){ 2153 if (!isspace(ch) && *token == 0){ 2154 hash += ch; 2155 *cp++ = ch; 2156 last = ' '; 2157 } else { 2158 last = ch; 2159 } 2160 *cp = '\0'; 2161 2162 for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) { 2163 if ((tp->hash == hash) && (strcmp(tp->name, token) == 0)) 2164 break; 2165 } 2166 if (tp){ 2167 if (tp->token == CONTINUE) 2168 continue; 2169#ifdef TRACE_GET_TOKEN 2170print_error("TRACE", token, tp->token); 2171#endif 2172 return (tp->token); 2173 } 2174 2175 if (token[0] == '-' && token[1] == '-'){ 2176 /* strip comment */ 2177 if (ch != '\n'){ 2178 while ((ch = getc(fp)) != -1) 2179 if (ch == '\n'){ 2180 Line++; 2181 break; 2182 } 2183 } 2184 if (ch == -1) 2185{ 2186#ifdef TRACE_GET_TOKEN 2187print_error("TRACE", token, ENDOFFILE); 2188#endif 2189 return ENDOFFILE; 2190} 2191 last = ch; 2192 return get_token(fp, token); 2193 } 2194 for(cp = token; *cp; cp++) 2195 if (!isdigit(*cp)) 2196{ 2197#ifdef TRACE_GET_TOKEN 2198print_error("TRACE", token, LABEL); 2199#endif 2200 return LABEL; 2201} 2202#ifdef TRACE_GET_TOKEN 2203print_error("TRACE", token, NUMBER); 2204#endif 2205 number_value = atoi(token); /* octet string size */ 2206 return NUMBER; 2207 } else { 2208 hash += ch; 2209 *cp++ = ch; 2210 if (ch == '\n') 2211 Line++; 2212 } 2213 2214 } while ((ch = getc(fp)) != -1); 2215#ifdef TRACE_GET_TOKEN 2216print_error("TRACE", token, ENDOFFILE); 2217#endif 2218 return ENDOFFILE; 2219} 2220 2221struct tree * 2222read_mib(filename) 2223 char *filename; 2224{ 2225 FILE *fp; 2226 struct node *nodes; 2227 struct tree *tree; 2228 2229 fp = fopen(filename, "r"); 2230 if (fp == NULL) 2231 return NULL; 2232 nodes = parse(fp); 2233 if (!nodes){ 2234 fprintf(stderr, "Mib table is bad. Exiting\n"); 2235 exit(1); 2236 } 2237 tree = build_tree(nodes); 2238 fclose(fp); 2239 return tree; 2240} 2241 2242 2243#ifdef TEST 2244main(argc, argv) 2245 int argc; 2246 char *argv[]; 2247{ 2248 FILE *fp; 2249 struct node *nodes; 2250 struct tree *tp; 2251 2252 fp = fopen("mib.txt", "r"); 2253 if (fp == NULL){ 2254 fprintf(stderr, "open failed\n"); 2255 return 1; 2256 } 2257 nodes = parse(fp); 2258 if (!nodes){ 2259 fprintf(stderr, "Mib table is bad. \n"); 2260 return (1); 2261 } 2262 tp = build_tree(nodes); 2263 print_subtree(tp, 0); 2264 fclose(fp); 2265} 2266 2267#endif /* TEST */ 2268 2269static int 2270parseQuoteString(fp, token) 2271 register FILE *fp; 2272 register char *token; 2273{ 2274 register int ch; 2275 register char *ptr, *ptr1; 2276 register int len = 0; 2277 2278 ch = ' '; 2279 *token = '\0'; /* make the token empty */ 2280 2281 ptr = quoted_string_buffer; 2282 if (ptr) 2283 *ptr = 0; 2284 2285 2286 while(ch != -1) { 2287 ch = getc(fp); 2288 if (ch != '"') { 2289 if (ptr) { 2290 * ptr ++ = ch; 2291 len ++; 2292 if (len % MAXQUOTESTR == 0) { 2293 ptr1 = (char *) malloc (len + MAXQUOTESTR); 2294 if (!ptr1){ 2295 fprintf(stderr, "malloc failed. Exiting\n"); 2296 exit(1); 2297 } 2298 memcpy (ptr1, quoted_string_buffer, len); 2299 free (quoted_string_buffer); 2300 quoted_string_buffer = ptr1; 2301 ptr = ptr1 + len; 2302 } 2303 } 2304 } else { 2305 if (ptr) 2306 * ptr = 0; 2307 } 2308 if (ch == '\n') 2309 Line++; 2310 else if (ch == '"') { 2311#ifdef TRACE_GET_TOKEN 2312print_error("TRACE", token, QUOTESTRING); 2313#endif 2314 return QUOTESTRING; 2315 } 2316 2317 } 2318 2319#ifdef TRACE_GET_TOKEN 2320print_error("TRACE", token, NULL); 2321#endif 2322 return NULL; 2323} 2324 2325/* 2326 * This routine parses a string like { blah blah blah } and returns PARSE_OBJID if 2327 * it is well formed, and NULL if not. 2328 */ 2329static int 2330tossObjectIdentifier(fp) 2331 register FILE *fp; 2332{ 2333 register int ch; 2334 2335 ch = getc(fp); 2336/* ch = last; = ' '? */ 2337 /* skip all white space */ 2338 while(isspace(ch) && ch != -1){ 2339 ch = getc(fp); 2340 if (ch == '\n') 2341 Line++; 2342 } 2343 if (ch != '{') 2344 return NULL; 2345 2346 while(ch != -1) { 2347 ch = getc(fp); 2348 2349 if (ch == '\n') 2350 Line++; 2351 else if (ch == '}') 2352 return PARSE_OBJID; 2353 } 2354 2355/* last = ch;*/ 2356 return NULL; 2357} 2358