#!/bin/sh # This is `snmp2.02' (part 2 of snmp2). # Do not concatenate these parts, unpack them in order with `/bin/sh'. # File `snmp2/snmplib/mib.c' is being continued... # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # if test ! -r _sharseq.tmp; then echo 'Please unpack part 1 first!' exit 1 fi shar_sequence=`cat _sharseq.tmp` if test "$shar_sequence" != 2; then echo "Please unpack part $shar_sequence next!" exit 1 fi if test ! -f _sharnew.tmp; then echo 'x - still skipping snmp2/snmplib/mib.c' else echo 'x - continuing file snmp2/snmplib/mib.c' sed 's/^X//' << 'SHAR_EOF' >> 'snmp2/snmplib/mib.c' && X len = var->val_len; X for(x = 0; x < len; x++){ X sprintf(buf, "%02X", *cp++); X buf += strlen(buf); X if (x < (len - 1)) X *buf++ = ':'; X } } X static void sprint_ipaddress(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { X u_char *ip; X X if (var->type != IPADDRESS){ X sprintf(buf, "Wrong Type (should be Ipaddress): "); X buf += strlen(buf); X sprint_by_type(buf, var, (struct enum_list *)NULL); X return; X } X ip = var->val.string; X sprintf(buf, "IpAddress: %d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]); } X static void sprint_unsigned_short(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { X if (var->type != ASN_INTEGER){ X sprintf(buf, "Wrong Type (should be INTEGER): "); X buf += strlen(buf); X sprint_by_type(buf, var, (struct enum_list *)NULL); X return; X } X sprintf(buf, "INT: %lu", *var->val.integer); } X static void sprint_null(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { X if (var->type != ASN_NULL){ X sprintf(buf, "Wrong Type (should be NULL): "); X buf += strlen(buf); X sprint_by_type(buf, var, (struct enum_list *)NULL); X return; X } X sprintf(buf, "NULL"); } X static void sprint_bitstring(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { X int len, bit; X u_char *cp; X char *enum_string; X X if (var->type != ASN_BIT_STR){ X sprintf(buf, "Wrong Type (should be BIT STRING): "); X buf += strlen(buf); X sprint_by_type(buf, var, (struct enum_list *)NULL); X return; X } X sprintf(buf, "BIT_STRING: "); X buf += strlen(buf); X sprint_hexstring(buf, var->val.bitstring, var->val_len); X buf += strlen(buf); X X cp = var->val.bitstring + 1; X for(len = 0; len < var->val_len - 1; len++){ X for(bit = 0; bit < 8; bit++){ X if (*cp & (0x80 >> bit)){ X enum_string = NULL; X for (; enums; enums = enums->next) X if (enums->value == (len * 8) + bit){ X enum_string = enums->label; X break; X } X if (enum_string == NULL) X sprintf(buf, "%d ", (len * 8) + bit); X else X sprintf(buf, "%s(%d) ", enum_string, (len * 8) + bit); X buf += strlen(buf); X } X } X cp ++; X } } X static void sprint_nsapaddress(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { X if (var->type != NSAP){ X sprintf(buf, "Wrong Type (should be NsapAddress): "); X buf += strlen(buf); X sprint_by_type(buf, var, (struct enum_list *)NULL); X return; X } X sprintf(buf, "NsapAddress: "); X buf += strlen(buf); X sprint_hexstring(buf, var->val.string, var->val_len); } X static void sprint_counter64(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { X struct counter64 *cp; X X if (var->type != COUNTER64){ X sprintf(buf, "Wrong Type (should be Counter64): "); X buf += strlen(buf); X sprint_by_type(buf, var, (struct enum_list *)NULL); X return; X } /* XXX */ X sprintf(buf, "Counter64: "); X buf += strlen(buf); X X sprint_hexstring(buf, &var->val.counter64->high, X sizeof(var->val.counter64->high)); X buf += strlen(buf); X sprint_hexstring(buf, &var->val.counter64->low, X sizeof(var->val.counter64->low)); } X X static void sprint_unknowntype(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { /* sprintf(buf, "Variable has bad type"); */ X sprint_by_type(buf, var, NULL); } X static void sprint_badtype(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { X sprintf(buf, "Variable has bad type"); } X static void sprint_by_type(buf, var, enums) X char *buf; X struct variable_list *var; X struct enum_list *enums; { X switch (var->type){ X case ASN_INTEGER: X sprint_integer(buf, var, enums); X break; X case ASN_OCTET_STR: X sprint_octet_string(buf, var, enums); X break; X case OPAQUE: X sprint_opaque(buf, var, enums); X break; X case ASN_OBJECT_ID: X sprint_object_identifier(buf, var, enums); X break; X case TIMETICKS: X sprint_timeticks(buf, var, enums); X break; X case GAUGE: X sprint_gauge(buf, var, enums); X break; X case COUNTER: X sprint_counter(buf, var, enums); X break; X case IPADDRESS: X sprint_ipaddress(buf, var, enums); X break; X case ASN_NULL: X sprint_null(buf, var, enums); X break; X case UINTEGER: X sprint_uinteger(buf, var, enums); X break; X default: X sprint_badtype(buf, var, enums); X break; X } } X struct tree *get_symbol(); X oid RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 }; unsigned char RFC1213_MIB_text[] = ".iso.org.dod.internet.mgmt.mib-2"; unsigned char EXPERIMENTAL_MIB_text[] = ".iso.org.dod.internet.experimental"; unsigned char PRIVATE_MIB_text[] = ".iso.org.dod.internet.private"; unsigned char PARTY_MIB_text[] = ".iso.org.dod.internet.snmpParties"; unsigned char SECRETS_MIB_text[] = ".iso.org.dod.internet.snmpSecrets"; struct tree *Mib; X char Standard_Prefix[] = ".1.3.6.1.2.1."; char Prefix[128]; int Suffix; X init_mib() { X char *file, *getenv(), *prefix; X X Mib = 0; X file = getenv("MIBFILE"); X if (file) X Mib = read_mib(file); X if (!Mib) X Mib = read_mib("mib.txt"); X if (!Mib) X Mib = read_mib("/etc/mib.txt"); X if (!Mib){ X fprintf(stderr, "Couldn't find mib file\n"); X exit(2); X } X prefix = getenv("PREFIX"); X if (!prefix) X prefix = Standard_Prefix; X if (prefix[strlen(prefix) - 1] != '.') X strcat(prefix, "."); /* add a trailing dot in case user didn't */ X prefix++; /* get past leading dot. */ X strcpy(Prefix, prefix); X X if (getenv("SUFFIX")) X Suffix = TRUE; X else X Suffix = FALSE; X set_functions(Mib); } X static set_functions(subtree) X struct tree *subtree; { X for(; subtree; subtree = subtree->next_peer){ X switch(subtree->type){ X case TYPE_OBJID: X subtree->printer = sprint_object_identifier; X break; X case TYPE_OCTETSTR: X subtree->printer = sprint_octet_string; X break; X case TYPE_INTEGER: X subtree->printer = sprint_integer; X break; X case TYPE_NETADDR: X subtree->printer = sprint_networkaddress; X break; X case TYPE_IPADDR: X subtree->printer = sprint_ipaddress; X break; X case TYPE_COUNTER: X subtree->printer = sprint_counter; X break; X case TYPE_GAUGE: X subtree->printer = sprint_gauge; X break; X case TYPE_TIMETICKS: X subtree->printer = sprint_timeticks; X break; X case TYPE_OPAQUE: X subtree->printer = sprint_opaque; X break; X case TYPE_NULL: X subtree->printer = sprint_null; X break; X case TYPE_BITSTRING: X subtree->printer = sprint_bitstring; X break; X case TYPE_NSAPADDRESS: X subtree->printer = sprint_nsapaddress; X break; X case TYPE_COUNTER64: X subtree->printer = sprint_counter64; X break; X case TYPE_UINTEGER: X subtree->printer = sprint_uinteger; X break; X case TYPE_OTHER: X default: X subtree->printer = sprint_unknowntype; X break; X } X set_functions(subtree->child_list); X } } X #ifdef VXWORKS int snmp_dump_packet = 0; #endif X #ifdef testing X main(argc, argv) X int argc; X char *argv[]; { X oid objid[64]; X int objidlen = sizeof (objid); X int count; X struct variable variable; X X init_mib(&Mib); X if (argc < 2) X print_subtree(Mib, 0); X variable.type = ASN_INTEGER; X variable.val.integer = 3; X variable.val_len = 4; X for (argc--; argc; argc--, argv++) { X objidlen = sizeof (objid); X printf("read_objid(%s) = %d\n", X argv[1], read_objid(argv[1], objid, &objidlen)); X for(count = 0; count < objidlen; count++) X printf("%d.", objid[count]); X printf("\n"); X print_variable(objid, objidlen, &variable); X } } X #endif testing X X static struct tree * find_rfc1213_mib(root) X struct tree *root; { X oid *op = RFC1213_MIB; X struct tree *tp; X int len; X X for(len = sizeof(RFC1213_MIB)/sizeof(oid); len; len--, op++){ X for(tp = root; tp; tp = tp->next_peer){ X if (tp->subid == *op){ X root = tp->child_list; X break; X } X } X if (tp == NULL) X return NULL; X } X return root; } X int read_objid(input, output, out_len) X char *input; X oid *output; X int *out_len; /* number of subid's in "output" */ { X struct tree *root = Mib; X oid *op = output; X char buf[512]; X X X if (*input == '.') X input++; X else { X strcpy(buf, Prefix); X strcat(buf, input); X input = buf; X } X X if (root == NULL){ X fprintf(stderr, "Mib not initialized. Exiting.\n"); X exit(1); X } X if ((*out_len = X parse_subtree(root, input, output, out_len)) == 0) X return (0); X *out_len += output - op; X X return (1); } X #ifdef notdef int read_objid(input, output, out_len) X char *input; X oid *output; X int *out_len; /* number of subid's in "output" */ { X struct tree *root = Mib; X oid *op = output; X int i; X X if (*input == '.') X input++; X else { X root = find_rfc1213_mib(root); X for (i = 0; i < sizeof (RFC1213_MIB)/sizeof(oid); i++) { X if ((*out_len)-- > 0) X *output++ = RFC1213_MIB[i]; X else { X fprintf(stderr, "object identifier too long\n"); X return (0); X } X } X } X X if (root == NULL){ X fprintf(stderr, "Mib not initialized. Exiting.\n"); X exit(1); X } X if ((*out_len = X parse_subtree(root, input, output, out_len)) == 0) X return (0); X *out_len += output - op; X X return (1); } #endif X static parse_subtree(subtree, input, output, out_len) X struct tree *subtree; X char *input; X oid *output; X int *out_len; /* number of subid's */ { X char buf[128], *to = buf; X u_long subid = 0; X struct tree *tp; X X /* X * No empty strings. Can happen if there is a trailing '.' or two '.'s X * in a row, i.e. "..". X */ X if ((*input == '\0') || X (*input == '.')) X return (0); X X if (isdigit(*input)) { X /* X * Read the number, then try to find it in the subtree. X */ X while (isdigit(*input)) { X subid *= 10; X subid += *input++ - '0'; X } X for (tp = subtree; tp; tp = tp->next_peer) { X if (tp->subid == subid) X goto found; X } X tp = NULL; X } X else { X /* X * Read the name into a buffer. X */ X while ((*input != '\0') && X (*input != '.')) { X *to++ = *input++; X } X *to = '\0'; X X /* X * Find the name in the subtree; X */ X for (tp = subtree; tp; tp = tp->next_peer) { X if (lc_cmp(tp->label, buf) == 0) { X subid = tp->subid; X goto found; X } X } X X /* X * If we didn't find the entry, punt... X */ X if (tp == NULL) { X fprintf(stderr, "sub-identifier not found: %s\n", buf); X return (0); X } X } X found: X if(subid > (u_long)MAX_SUBID){ X fprintf(stderr, "sub-identifier too large: %s\n", buf); X return (0); X } X X if ((*out_len)-- <= 0){ X fprintf(stderr, "object identifier too long\n"); X return (0); X } X *output++ = subid; X X if (*input != '.') X return (1); X if ((*out_len = X parse_subtree(tp ? tp->child_list : NULL, ++input, output, out_len)) == 0) X return (0); X return (++*out_len); } X sprint_objid(buf, objid, objidlen) X char *buf; X oid *objid; X int objidlen; /* number of subidentifiers */ { X char tempbuf[2048], *cp; X struct tree *subtree = Mib; X X *tempbuf = '.'; /* this is a fully qualified name */ X get_symbol(objid, objidlen, subtree, tempbuf + 1); X if (Suffix){ X for(cp =tempbuf; *cp; cp++) X ; X while(cp >= tempbuf){ X if (isalpha(*cp)) X break; X cp--; X } X while(cp >= tempbuf){ X if (*cp == '.') X break; X cp--; X } X cp++; X if (cp < tempbuf) X cp = tempbuf; X X } else { X cp = tempbuf; X if ((strlen(tempbuf) > strlen((char *)RFC1213_MIB_text)) X && !bcmp(tempbuf, (char *)RFC1213_MIB_text, X strlen((char *)RFC1213_MIB_text))){ X cp += sizeof(RFC1213_MIB_text); X } X if ((strlen(tempbuf) > strlen((char *)EXPERIMENTAL_MIB_text)) X && !bcmp(tempbuf, (char *) EXPERIMENTAL_MIB_text, X strlen((char *)EXPERIMENTAL_MIB_text))){ X cp += sizeof(EXPERIMENTAL_MIB_text); X } X if ((strlen(tempbuf) > strlen((char *)PRIVATE_MIB_text)) X && !bcmp(tempbuf, (char *) PRIVATE_MIB_text, X strlen((char *)PRIVATE_MIB_text))){ X cp += sizeof(PRIVATE_MIB_text); X } X if ((strlen(tempbuf) > strlen((char *)PARTY_MIB_text)) X && !bcmp(tempbuf, (char *) PARTY_MIB_text, X strlen((char *)PARTY_MIB_text))){ X cp += sizeof(PARTY_MIB_text); X } X if ((strlen(tempbuf) > strlen((char *)SECRETS_MIB_text)) X && !bcmp(tempbuf, (char *) SECRETS_MIB_text, X strlen((char *)SECRETS_MIB_text))){ X cp += sizeof(SECRETS_MIB_text); X } X } X strcpy(buf, cp); } X print_objid(objid, objidlen) X oid *objid; X int objidlen; /* number of subidentifiers */ { X char buf[256]; X X sprint_objid(buf, objid, objidlen); X printf("%s\n", buf); } X X print_variable(objid, objidlen, variable) X oid *objid; X int objidlen; X struct variable_list *variable; { X char buf[2048]; X struct tree *subtree = Mib; X X sprint_variable(buf, objid, objidlen, variable); X printf("%s", buf); } X sprint_variable(buf, objid, objidlen, variable) X char *buf; X oid *objid; X int objidlen; X struct variable_list *variable; { X char tempbuf[2048], *cp; X struct tree *subtree = Mib; X X sprint_objid(buf, objid, objidlen); X buf += strlen(buf); X strcat(buf, " = "); X buf += strlen(buf); X X if (variable->type == SNMP_NOSUCHOBJECT) X sprintf(buf, "No Such Object available on this agent\n"); X else if (variable->type == SNMP_NOSUCHINSTANCE) X sprintf(buf, "No Such Instance currently exists\n"); X else if (variable->type == SNMP_ENDOFMIBVIEW) X sprintf(buf, "No more variables left in this MIB View\n"); X else { X *tempbuf = '.'; /* this is a fully qualified name */ X subtree = get_symbol(objid, objidlen, subtree, tempbuf + 1); X buf += strlen(buf); X if (subtree->printer) X (*subtree->printer)(buf, variable, subtree->enums); X else { X sprint_by_type(buf, variable, subtree->enums); X } X strcat(buf, "\n"); X } } X sprint_value(buf, objid, objidlen, variable) X char *buf; X oid *objid; X int objidlen; X struct variable_list *variable; { X char tempbuf[2048]; X struct tree *subtree = Mib; X X if (variable->type == SNMP_NOSUCHOBJECT) X sprintf(buf, "No Such Object available on this agent\n"); X else if (variable->type == SNMP_NOSUCHINSTANCE) X sprintf(buf, "No Such Instance currently exists\n"); X else if (variable->type == SNMP_ENDOFMIBVIEW) X sprintf(buf, "No more variables left in this MIB View\n"); X else { X subtree = get_symbol(objid, objidlen, subtree, tempbuf); X if (subtree->printer) X (*subtree->printer)(buf, variable, subtree->enums); X else { X sprint_by_type(buf, variable, subtree->enums); X } X } } X print_value(objid, objidlen, variable) X oid *objid; X int objidlen; X struct variable_list *variable; { X char tempbuf[2048]; X struct tree *subtree = Mib; X X sprint_value(tempbuf, objid, objidlen, variable); X printf("%s\n", tempbuf); } X struct tree * get_symbol(objid, objidlen, subtree, buf) X oid *objid; X int objidlen; X struct tree *subtree; X char *buf; { X struct tree *return_tree = NULL; X X for(; subtree; subtree = subtree->next_peer){ X if (*objid == subtree->subid){ X strcpy(buf, subtree->label); X goto found; X } X } X X /* subtree not found */ X while(objidlen--){ /* output rest of name, uninterpreted */ X sprintf(buf, "%u.", *objid++); X while(*buf) X buf++; X } X *(buf - 1) = '\0'; /* remove trailing dot */ X return NULL; X found: X if (objidlen > 1){ X while(*buf) X buf++; X *buf++ = '.'; X *buf = '\0'; X return_tree = get_symbol(objid + 1, objidlen - 1, subtree->child_list, X buf); X } X if (return_tree != NULL) X return return_tree; X else X return subtree; } X X static int lc_cmp(s1, s2) X char *s1, *s2; { X char c1, c2; X X while(*s1 && *s2){ X if (isupper(*s1)) X c1 = tolower(*s1); X else X c1 = *s1; X if (isupper(*s2)) X c2 = tolower(*s2); X else X c2 = *s2; X if (c1 != c2) X return ((c1 - c2) > 0 ? 1 : -1); X s1++; X s2++; X } X X if (*s1) X return -1; X if (*s2) X return 1; X return 0; } X /* X * Clone of get_symbol that doesn't take a buffer argument X */ struct tree * get_tree(objid, objidlen, subtree) X oid *objid; X int objidlen; X struct tree *subtree; { X struct tree *return_tree = NULL; X X for(; subtree; subtree = subtree->next_peer){ X if (*objid == subtree->subid) X goto found; X } X X return NULL; X found: X if (objidlen > 1) X return_tree = get_tree(objid + 1, objidlen - 1, subtree->child_list); X if (return_tree != NULL) X return return_tree; X else X return subtree; } X char *get_description(objid, objidlen) X oid *objid; X int objidlen; /* number of subidentifiers */ { X struct tree *subtree = Mib; X X subtree = get_tree(objid, objidlen, subtree); X if (subtree) X return (subtree->description); X else X return NULL; } X void print_description(objid, objidlen) X oid *objid; X int objidlen; /* number of subidentifiers */ { X char *desc = get_description(objid, objidlen); X X if (desc && desc[0] != '\0') X printf("Description: \"%s\"\n", desc); X else X printf("No description\n"); } X struct tree * find_node(name, subtree) X char *name; X struct tree *subtree; { X struct tree *tp, *ret; X X for(tp = subtree; tp; tp = tp->next_peer){ X if (!strcasecmp(name, tp->label)) X return tp; X ret = find_node(name, tp->child_list); X if (ret) X return ret; X } X return 0; } X X int get_node(name, objid, objidlen) X char *name; X oid *objid; X int *objidlen; { X struct tree *tp; X oid newname[64], *op; X X tp = find_node(name, Mib); X if (tp){ X for(op = newname + 63; op >= newname; op--){ X *op = tp->subid; X tp = tp->parent; X if (tp == NULL) X break; X } X if (newname + 64 - op > *objidlen) X return 0; X *objidlen = newname + 64 - op; X bcopy(op, objid, (newname + 64 - op) * sizeof(oid)); X return 1; X } else { X return 0; X } X X } SHAR_EOF echo 'File snmp2/snmplib/mib.c is complete' && $shar_touch -am 1015123593 'snmp2/snmplib/mib.c' && chmod 0644 'snmp2/snmplib/mib.c' || echo 'restore of snmp2/snmplib/mib.c failed' shar_count="`wc -c < 'snmp2/snmplib/mib.c'`" test 26128 -eq "$shar_count" || echo "snmp2/snmplib/mib.c: original size 26128, current size $shar_count" rm -f _sharnew.tmp fi # ============= snmp2/snmplib/parse.c ============== if test -f 'snmp2/snmplib/parse.c' && test X"$1" != X"-c"; then echo 'x - skipping snmp2/snmplib/parse.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting snmp2/snmplib/parse.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'snmp2/snmplib/parse.c' && /****************************************************************** X Copyright 1989, 1991, 1992 by Carnegie Mellon University X X All Rights Reserved X Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of CMU not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. X CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* X * parse.c X */ #include #include #include #include "parse.h" X /* A quoted string value-- too long for a general "token" */ char *quoted_string_buffer; X /* X * This is one element of an object identifier with either an integer X * subidentifier, or a textual string label, or both. X * The subid is -1 if not present, and label is NULL if not present. X */ struct subid { X int subid; X char *label; }; X #define MAXTC 128 struct tc { /* textual conventions */ X int type; X char descriptor[MAXTOKEN]; X struct enum_list *enums; } tclist[MAXTC]; X X X int Line = 1; X #define SYNTAX_MASK 0x80 /* types of tokens X Tokens wiht the SYNTAX_MASK bit set are syntax tokens */ #define CONTINUE -1 #define ENDOFFILE 0 #define LABEL 1 #define SUBTREE 2 #define SYNTAX 3 #define OBJID (4 | SYNTAX_MASK) #define OCTETSTR (5 | SYNTAX_MASK) #define INTEGER (6 | SYNTAX_MASK) #define NETADDR (7 | SYNTAX_MASK) #define IPADDR (8 | SYNTAX_MASK) #define COUNTER (9 | SYNTAX_MASK) #define GAUGE (10 | SYNTAX_MASK) #define TIMETICKS (11 | SYNTAX_MASK) #define OPAQUE (12 | SYNTAX_MASK) #define NUL (13 | SYNTAX_MASK) #define SEQUENCE 14 #define OF 15 /* SEQUENCE OF */ #define OBJTYPE 16 #define ACCESS 17 #define READONLY 18 #define READWRITE 19 #define WRITEONLY 20 #define NOACCESS 21 #define STATUS 22 #define MANDATORY 23 #define OPTIONAL 24 #define OBSOLETE 25 /* #define RECOMMENDED 26 */ #define PUNCT 27 #define EQUALS 28 #define NUMBER 29 #define LEFTBRACKET 30 #define RIGHTBRACKET 31 #define LEFTPAREN 32 #define RIGHTPAREN 33 #define COMMA 34 #define DESCRIPTION 35 #define QUOTESTRING 36 #define INDEX 37 #define DEFVAL 38 #define DEPRECATED 39 #define SIZE 40 #define BITSTRING (41 | SYNTAX_MASK) #define NSAPADDRESS (42 | SYNTAX_MASK) #define COUNTER64 (43 | SYNTAX_MASK) #define OBJGROUP 44 #define NOTIFTYPE 45 #define AUGMENTS 46 #define COMPLIANCE 47 #define READCREATE 48 #define UNITS 49 #define REFERENCE 50 #define NUM_ENTRIES 51 #define MODULEIDENTITY 52 #define LASTUPDATED 53 #define ORGANIZATION 54 #define CONTACTINFO 55 #define UINTEGER32 (56 | SYNTAX_MASK) #define CURRENT 57 #define DEFINITIONS 58 #define END 59 #define SEMI 60 X struct tok { X char *name; /* token name */ X int len; /* length not counting nul */ X int token; /* value */ X int hash; /* hash of name */ X struct tok *next; /* pointer to next in hash table */ }; X X struct tok tokens[] = { X { "obsolete", sizeof ("obsolete")-1, OBSOLETE }, X { "Opaque", sizeof ("Opaque")-1, OPAQUE }, /* { "recommended", sizeof("recommended")-1, RECOMMENDED }, */ X { "optional", sizeof ("optional")-1, OPTIONAL }, X { "LAST-UPDATED", sizeof ("LAST-UPDATED")-1, LASTUPDATED }, X { "ORGANIZATION", sizeof ("ORGANIZATION")-1, ORGANIZATION }, X { "CONTACT-INFO", sizeof ("CONTACT-INFO")-1, CONTACTINFO }, X { "MODULE-IDENTITY", sizeof ("MODULE-IDENTITY")-1, MODULEIDENTITY }, X { "MODULE-COMPLIANCE", sizeof ("MODULE-COMPLIANCE")-1, COMPLIANCE }, X { "DEFINITIONS", sizeof("DEFINITIONS")-1, DEFINITIONS}, X { "END", sizeof("END")-1, END}, X { ";", sizeof(";")-1, SEMI}, X { "AUGMENTS", sizeof ("AUGMENTS")-1, AUGMENTS }, X { "not-accessible", sizeof ("not-accessible")-1, NOACCESS }, X { "write-only", sizeof ("write-only")-1, WRITEONLY }, X { "NsapAddress", sizeof("NsapAddress")-1, NSAPADDRESS}, X { "UNITS", sizeof("Units")-1, UNITS}, X { "REFERENCE", sizeof("REFERENCE")-1, REFERENCE}, X { "NUM-ENTRIES", sizeof("NUM-ENTRIES")-1, NUM_ENTRIES}, X { "BITSTRING", sizeof("BitString")-1, BITSTRING}, X { "BIT", sizeof("BIT")-1, CONTINUE}, X { "Counter64", sizeof("Counter64")-1, COUNTER64}, X { "TimeTicks", sizeof ("TimeTicks")-1, TIMETICKS }, X { "NOTIFICATION-TYPE", sizeof ("NOTIFICATION-TYPE")-1, NOTIFTYPE }, X { "OBJECT-GROUP", sizeof ("OBJECT-GROUP")-1, OBJGROUP }, X { "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, OBJID }, X /* X * This CONTINUE appends the next word onto OBJECT, X * hopefully matching OBJECTIDENTIFIER above. X */ X { "OBJECT", sizeof ("OBJECT")-1, CONTINUE }, X { "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR }, X { "Gauge", sizeof ("Gauge")-1, GAUGE }, X { "read-write", sizeof ("read-write")-1, READWRITE }, X { "read-create", sizeof ("read-create")-1, READCREATE }, X { "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR }, X { "OCTET", sizeof ("OCTET")-1, -1 }, X { "OF", sizeof ("OF")-1, OF }, X { "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE }, X { "NULL", sizeof ("NULL")-1, NUL }, X { "IpAddress", sizeof ("IpAddress")-1, IPADDR }, X { "UInteger32", sizeof ("UInteger32")-1, UINTEGER32 }, X { "INTEGER", sizeof ("INTEGER")-1, INTEGER }, X { "Counter", sizeof ("Counter")-1, COUNTER }, X { "read-only", sizeof ("read-only")-1, READONLY }, X { "DESCRIPTION", sizeof ("DESCRIPTION")-1, DESCRIPTION }, X { "INDEX", sizeof ("INDEX")-1, INDEX }, X { "DEFVAL", sizeof ("DEFVAL")-1, DEFVAL }, X { "deprecated", sizeof ("deprecated")-1, DEPRECATED }, X { "SIZE", sizeof ("SIZE")-1, SIZE }, X { "MAX-ACCESS", sizeof ("MAX-ACCESS")-1, ACCESS }, X { "ACCESS", sizeof ("ACCESS")-1, ACCESS }, X { "mandatory", sizeof ("mandatory")-1, MANDATORY }, X { "current", sizeof ("current")-1, CURRENT }, X { "STATUS", sizeof ("STATUS")-1, STATUS }, X { "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX }, X { "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE }, X { "{", sizeof ("{")-1, LEFTBRACKET }, X { "}", sizeof ("}")-1, RIGHTBRACKET }, X { "::=", sizeof ("::=")-1, EQUALS }, X { "(", sizeof ("(")-1, LEFTPAREN }, X { ")", sizeof (")")-1, RIGHTPAREN }, X { ",", sizeof (",")-1, COMMA }, X { NULL } }; X #define HASHSIZE 32 #define BUCKET(x) (x & 0x01F) X struct tok *buckets[HASHSIZE]; X static hash_init() { X register struct tok *tp; X register char *cp; X register int h; X register int b; X X bzero((char *)buckets, sizeof(buckets)); X for (tp = tokens; tp->name; tp++) { X for (h = 0, cp = tp->name; *cp; cp++) X h += *cp; X tp->hash = h; X b = BUCKET(h); X if (buckets[b]) X tp->next = buckets[b]; /* BUG ??? */ X buckets[b] = tp; X } } X #define NHASHSIZE 128 #define NBUCKET(x) (x & 0x7F) struct node *nbuckets[NHASHSIZE]; X init_node_hash(nodes) X struct node *nodes; { X register struct node *np, *nextp; X register char *cp; X register int hash; X X bzero((char *)nbuckets,sizeof(nbuckets)); X for(np = nodes; np;){ X nextp = np->next; X hash = 0; X for(cp = np->parent; *cp; cp++) X hash += *cp; X np->next = nbuckets[NBUCKET(hash)]; X nbuckets[NBUCKET(hash)] = np; X np = nextp; X } } X static char * Malloc(num) X unsigned num; { X int malloc(); X X /* this is to fix (what seems to be) a problem with the IBM RT C library malloc */ X if (num < 16) X num = 16; X return (char *)malloc(num); } X static print_error(string, token, type) X char *string; X char *token; X int type; { X if (type == ENDOFFILE) X fprintf(stderr, "%s(EOF): On or around line %d\n", string, Line); X else if (token) X fprintf(stderr, "%s(%s): On or around line %d\n", string, token, Line); X else X fprintf(stderr, "%s: On or around line %d\n", string, Line); } X #ifdef TEST print_subtree(tree, count) X struct tree *tree; X int count; { X struct tree *tp; X int i; X X for(i = 0; i < count; i++) X printf(" "); X printf("Children of %s:\n", tree->label); X count++; X for(tp = tree->child_list; tp; tp = tp->next_peer){ X for(i = 0; i < count; i++) X printf(" "); X printf("%s\n", tp->label); X } X for(tp = tree->child_list; tp; tp = tp->next_peer){ X print_subtree(tp, count); X } } #endif /* TEST */ X int translation_table[256]; X build_translation_table(){ X int count; X X for(count = 0; count < 256; count++){ X switch(count){ X case OBJID: X translation_table[count] = TYPE_OBJID; X break; X case OCTETSTR: X translation_table[count] = TYPE_OCTETSTR; X break; X case INTEGER: X translation_table[count] = TYPE_INTEGER; X break; X case NETADDR: X translation_table[count] = TYPE_IPADDR; X break; X case IPADDR: X translation_table[count] = TYPE_IPADDR; X break; X case COUNTER: X translation_table[count] = TYPE_COUNTER; X break; X case GAUGE: X translation_table[count] = TYPE_GAUGE; X break; X case TIMETICKS: X translation_table[count] = TYPE_TIMETICKS; X break; X case OPAQUE: X translation_table[count] = TYPE_OPAQUE; X break; X case NUL: X translation_table[count] = TYPE_NULL; X break; X case COUNTER64: X translation_table[count] = TYPE_COUNTER64; X break; X case BITSTRING: X translation_table[count] = TYPE_BITSTRING; X break; X case NSAPADDRESS: X translation_table[count] = TYPE_NSAPADDRESS; X break; X case UINTEGER32: X translation_table[count] = TYPE_UINTEGER; X break; X default: X translation_table[count] = TYPE_OTHER; X break; X } X } } X static struct tree * build_tree(nodes) X struct node *nodes; { X struct node *np; X struct tree *tp, *lasttp; X int bucket, nodes_left = 0; X X build_translation_table(); X /* grow tree from this root node */ X init_node_hash(nodes); X X /* build root node */ X tp = (struct tree *)Malloc(sizeof(struct tree)); X tp->parent = NULL; X tp->next_peer = NULL; X tp->child_list = NULL; X tp->enums = NULL; X strcpy(tp->label, "joint-iso-ccitt"); X tp->subid = 2; X tp->type = 0; X tp->description = 0; X /* XXX nodes isn't needed in do_subtree() ??? */ X do_subtree(tp, &nodes); X lasttp = tp; X X /* build root node */ X tp = (struct tree *)Malloc(sizeof(struct tree)); X tp->parent = NULL; X tp->next_peer = lasttp; X tp->child_list = NULL; X tp->enums = NULL; X strcpy(tp->label, "ccitt"); X tp->subid = 0; X tp->type = 0; X tp->description = 0; X /* XXX nodes isn't needed in do_subtree() ??? */ X do_subtree(tp, &nodes); X lasttp = tp; X X /* build root node */ X tp = (struct tree *)Malloc(sizeof(struct tree)); X tp->parent = NULL; X tp->next_peer = lasttp; X tp->child_list = NULL; X tp->enums = NULL; X strcpy(tp->label, "iso"); X tp->subid = 1; X tp->type = 0; X tp->description = 0; X /* XXX nodes isn't needed in do_subtree() ??? */ X do_subtree(tp, &nodes); X X #ifdef TEST X print_subtree(tp, 0); #endif /* TEST */ X /* If any nodes are left, the tree is probably inconsistent */ X for(bucket = 0; bucket < NHASHSIZE; bucket++){ X if (nbuckets[bucket]){ X nodes_left = 1; X break; X } X } X if (nodes_left){ X fprintf(stderr, "The mib description doesn't seem to be consistent.\n"); X fprintf(stderr, "Some nodes couldn't be linked under the \"iso\" tree.\n"); X fprintf(stderr, "these nodes are left:\n"); X for(bucket = 0; bucket < NHASHSIZE; bucket++){ X for(np = nbuckets[bucket]; np; np = np->next) X fprintf(stderr, "%s ::= { %s %d } (%d)\n", np->label, X np->parent, np->subid, np->type); X } X } X return tp; } X /* X * Find all the children of root in the list of nodes. Link them into the X * tree and out of the nodes list. X */ static do_subtree(root, nodes) X struct tree *root; X struct node **nodes; { X register struct tree *tp; X struct tree *peer = NULL; X register struct node *np, **headp; X struct node *oldnp = NULL, *child_list = NULL, *childp = NULL; X char *cp; X int hash; X X tp = root; X hash = 0; X for(cp = tp->label; *cp; cp++) X hash += *cp; X headp = &nbuckets[NBUCKET(hash)]; X /* X * Search each of the nodes for one whose parent is root, and X * move each into a separate list. X */ X for(np = *headp; np; np = np->next){ X if ((*tp->label != *np->parent) || strcmp(tp->label, np->parent)){ X if ((*tp->label == *np->label) && !strcmp(tp->label, np->label)){ X /* if there is another node with the same label, assume that X * any children after this point in the list belong to the other node. X * This adds some scoping to the table and allows vendors to X * reuse names such as "ip". X */ X break; X } X oldnp = np; X } else { X if (child_list == NULL){ X child_list = childp = np; /* first entry in child list */ X } else { X childp->next = np; X childp = np; X } X /* take this node out of the node list */ X if (oldnp == NULL){ X *headp = np->next; /* fix root of node list */ X } else { X oldnp->next = np->next; /* link around this node */ X } X } X } X if (childp) X childp->next = 0; /* re-terminate list */ X /* X * Take each element in the child list and place it into the tree. X */ X for(np = child_list; np; np = np->next){ X tp = (struct tree *)Malloc(sizeof(struct tree)); X tp->parent = root; X tp->next_peer = NULL; X tp->child_list = NULL; X strcpy(tp->label, np->label); X tp->subid = np->subid; X tp->type = translation_table[np->type]; X tp->enums = np->enums; X np->enums = NULL; /* so we don't free them later */ X tp->description = np->description; /* steals memory from np */ X np->description = NULL; /* so we don't free it later */ X if (root->child_list == NULL){ X root->child_list = tp; X } else { X peer->next_peer = tp; X } X peer = tp; /* if (tp->type == TYPE_OTHER) */ X do_subtree(tp, nodes); /* recurse on this child if it isn't X an end node */ X } X /* free all nodes that were copied into tree */ X oldnp = NULL; X for(np = child_list; np; np = np->next){ X if (oldnp) X free(oldnp); X oldnp = np; X } X if (oldnp) X free(oldnp); } X X /* X * Takes a list of the form: X * { iso org(3) dod(6) 1 } X * and creates several nodes, one for each parent-child pair. X * Returns NULL on error. X */ static int getoid(fp, oid, length) X register FILE *fp; X register struct subid *oid; /* an array of subids */ X int length; /* the length of the array */ { X register int count; X int type; X char token[MAXTOKEN]; X register char *cp; X X if ((type = get_token(fp, token)) != LEFTBRACKET){ X print_error("Expected \"{\"", token, type); X return NULL; X } X type = get_token(fp, token); X for(count = 0; count < length; count++, oid++){ X oid->label = 0; X oid->subid = -1; X if (type == RIGHTBRACKET){ X return count; X } else if (type != LABEL && type != NUMBER){ X print_error("Not valid for object identifier", token, type); X return NULL; X } X if (type == LABEL){ X /* this entry has a label */ X cp = (char *)Malloc((unsigned)strlen(token) + 1); X strcpy(cp, token); X oid->label = cp; X type = get_token(fp, token); X if (type == LEFTPAREN){ X type = get_token(fp, token); X if (type == NUMBER){ X oid->subid = atoi(token); X if ((type = get_token(fp, token)) != RIGHTPAREN){ X print_error("Unexpected a closing parenthesis", token, type); X return NULL; X } X } else { X print_error("Expected a number", token, type); X return NULL; X } X } else { X continue; X } X } else { X /* this entry has just an integer sub-identifier */ X oid->subid = atoi(token); X } X type = get_token(fp, token); X } X return count; X X } X static free_node(np) X struct node *np; { X struct enum_list *ep, *tep; X X ep = np->enums; X while(ep){ X tep = ep; X ep = ep->next; X free((char *)tep); X } X free((char *)np); } X /* X * Parse an entry of the form: X * label OBJECT IDENTIFIER ::= { parent 2 } X * The "label OBJECT IDENTIFIER" portion has already been parsed. X * Returns 0 on error. X */ static struct node * parse_objectid(fp, name) X FILE *fp; X char *name; { X int type; X char token[MAXTOKEN]; X register int count; X register struct subid *op, *nop; X int length; X struct subid oid[32]; X struct node *np, *root, *oldnp = NULL; X X type = get_token(fp, token); X if (type != EQUALS){ X print_error("Bad format", token, type); X return 0; X } X if ((length = getoid(fp, oid, 32)) != 0){ X np = root = (struct node *)Malloc(sizeof(struct node)); X bzero((char *)np, sizeof(struct node)); X /* X * For each parent-child subid pair in the subid array, X * create a node and link it into the node list. X */ X for(count = 0, op = oid, nop=oid+1; count < (length - 2); count++, X op++, nop++){ X /* every node must have parent's name and child's name or number */ X if (op->label && (nop->label || (nop->subid != -1))){ X strcpy(np->parent, op->label); X if (nop->label) X strcpy(np->label, nop->label); X if (nop->subid != -1) X np->subid = nop->subid; X np->type = 0; X np->enums = 0; X /* set up next entry */ X np->next = (struct node *)Malloc(sizeof(*np->next)); X bzero((char *)np->next, sizeof(struct node)); X oldnp = np; X np = np->next; X } X } X np->next = (struct node *)NULL; X /* X * The above loop took care of all but the last pair. This pair is taken X * care of here. The name for this node is taken from the label for this X * entry. X * np still points to an unused entry. X */ X if (count == (length - 2)){ X if (op->label){ X strcpy(np->parent, op->label); X strcpy(np->label, name); X if (nop->subid != -1) X np->subid = nop->subid; X else X print_error("Warning: This entry is pretty silly", X np->label, type); X } else { X free_node(np); X if (oldnp) X oldnp->next = NULL; X else X return NULL; X } X } else { X print_error("Missing end of oid", (char *)NULL, type); X free_node(np); /* the last node allocated wasn't used */ X if (oldnp) X oldnp->next = NULL; X return NULL; X } X /* free the oid array */ X for(count = 0, op = oid; count < length; count++, op++){ X if (op->label) X free(op->label); X op->label = 0; X } X return root; X } else { X print_error("Bad object identifier", (char *)NULL, type); X return 0; X } } X static int get_tc(descriptor, ep) X char *descriptor; X struct enum_list **ep; { X int i; X X for(i = 0; i < MAXTC; i++){ X if (tclist[i].type == 0) X break; X if (!strcmp(descriptor, tclist[i].descriptor)){ X *ep = tclist[i].enums; X return tclist[i].type; X } X } X return LABEL; } X /* X * Parses an asn type. Structures are ignored by this parser. X * Returns NULL on error. X */ static int parse_asntype(fp, name, ntype, ntoken) X FILE *fp; X char *name; X int *ntype; X char *ntoken; { X int type, i; X char token[MAXTOKEN]; X struct enum_list *ep; X struct tc *tcp; X int level; X X type = get_token(fp, token); X if (type == SEQUENCE){ X while((type = get_token(fp, token)) != ENDOFFILE){ X if (type == RIGHTBRACKET){ X *ntype = get_token(fp, ntoken); X return 1; X } X } X print_error("Expected \"}\"", token, type); X return 0; X } else { X if (!strcmp(token, "TEXTUAL-CONVENTION")){ X while (type != SYNTAX) X type = get_token(fp, token); X type = get_token(fp, token); X } X /* textual convention */ X for(i = 0; i < MAXTC; i++){ X if (tclist[i].type == 0) X break; X } X if (i == MAXTC){ X print_error("No more textual conventions possible.", token, type); X return 0; X } X tcp = &tclist[i]; X strcpy(tcp->descriptor, name); X if (!(type & SYNTAX_MASK)){ X print_error("Textual convention doesn't map to real type.", token, X type); X return 0; X } X tcp->type = type; X *ntype = get_token(fp, ntoken); X if (*ntype == LEFTPAREN){ X level = 1; X /* don't record any constraints for now */ X while(level > 0){ X *ntype = get_token(fp, ntoken); X if (*ntype == LEFTPAREN) X level++; X if (*ntype == RIGHTPAREN) X level--; X } X *ntype = get_token(fp, ntoken); X } else if (*ntype == LEFTBRACKET) { X /* if there is an enumeration list, parse it */ X while((type = get_token(fp, token)) != ENDOFFILE){ X if (type == RIGHTBRACKET) X break; X if (type == LABEL){ X /* this is an enumerated label */ X if (tcp->enums == 0){ X ep = tcp->enums = (struct enum_list *) X Malloc(sizeof(struct enum_list)); X } else { X ep->next = (struct enum_list *) X Malloc(sizeof(struct enum_list)); X ep = ep->next; X } X ep->next = 0; X /* a reasonable approximation for the length */ X ep->label = X (char *)Malloc((unsigned)strlen(token) + 1); X strcpy(ep->label, token); X type = get_token(fp, token); X if (type != LEFTPAREN){ X print_error("Expected \"(\"", token, type); X /* free_node(np); */ X return 0; X } X type = get_token(fp, token); X if (type != NUMBER){ X print_error("Expected integer", token, type); X /* free_node(np); */ X return 0; X } X ep->value = atoi(token); X type = get_token(fp, token); X if (type != RIGHTPAREN){ X print_error("Expected \")\"", token, type); X /* free_node(np); */ X return 0; X } X } X } X if (type == ENDOFFILE){ X print_error("Expected \"}\"", token, type); X /* free_node(np); */ X return 0; X } X *ntype = get_token(fp, ntoken); X } X return 1; X } } X X /* X * Parses an OBJECT TYPE macro. X * Returns 0 on error. X */ static struct node * parse_objecttype(fp, name) X register FILE *fp; X char *name; { X register int type; X char token[MAXTOKEN]; X int count, length; X struct subid oid[32]; X char syntax[MAXTOKEN]; X int nexttype, tctype; X char nexttoken[MAXTOKEN]; X register struct node *np; X register struct enum_list *ep; X X type = get_token(fp, token); X if (type != SYNTAX){ X print_error("Bad format for OBJECT TYPE", token, type); X return 0; X } X np = (struct node *)Malloc(sizeof(struct node)); X np->next = 0; X np->enums = 0; X np->description = NULL; /* default to an empty description */ X type = get_token(fp, token); X if (type == LABEL){ X tctype = get_tc(token, &(np->enums)); #if 0 X if (tctype == LABEL){ X print_error("No known translation for type", token, type); X return 0; X } #endif X type = tctype; X } X np->type = type; X nexttype = get_token(fp, nexttoken); X switch(type){ X case SEQUENCE: X strcpy(syntax, token); X if (nexttype == OF){ X strcat(syntax, " "); X strcat(syntax, nexttoken); X nexttype = get_token(fp, nexttoken); X strcat(syntax, " "); X strcat(syntax, nexttoken); X nexttype = get_token(fp, nexttoken); X } X break; X case INTEGER: X case UINTEGER32: X strcpy(syntax, token); X if (nexttype == LEFTBRACKET) { X /* if there is an enumeration list, parse it */ X while((type = get_token(fp, token)) != ENDOFFILE){ X if (type == RIGHTBRACKET) X break; X if (type == LABEL){ X /* this is an enumerated label */ X if (np->enums == 0){ X ep = np->enums = (struct enum_list *) X Malloc(sizeof(struct enum_list)); X } else { X ep->next = (struct enum_list *) X Malloc(sizeof(struct enum_list)); X ep = ep->next; X } X ep->next = 0; X /* a reasonable approximation for the length */ X ep->label = X (char *)Malloc((unsigned)strlen(token) + 1); X strcpy(ep->label, token); X type = get_token(fp, token); X if (type != LEFTPAREN){ X print_error("Expected \"(\"", token, type); X free_node(np); X return 0; X } X type = get_token(fp, token); X if (type != NUMBER){ X print_error("Expected integer", token, type); X free_node(np); X return 0; X } X ep->value = atoi(token); X type = get_token(fp, token); X if (type != RIGHTPAREN){ X print_error("Expected \")\"", token, type); X free_node(np); X return 0; X } X } X } X if (type == ENDOFFILE){ X print_error("Expected \"}\"", token, type); X free_node(np); X return 0; X } X nexttype = get_token(fp, nexttoken); X } else if (nexttype == LEFTPAREN){ X /* ignore the "constrained integer" for now */ X nexttype = get_token(fp, nexttoken); X nexttype = get_token(fp, nexttoken); X nexttype = get_token(fp, nexttoken); X } X break; X case BITSTRING: X strcpy(syntax, token); X if (nexttype == LEFTBRACKET) { X /* if there is an enumeration list, parse it */ X while((type = get_token(fp, token)) != ENDOFFILE){ X if (type == RIGHTBRACKET) X break; X if (type == LABEL){ X /* this is an enumerated label */ X if (np->enums == 0){ X ep = np->enums = (struct enum_list *) X Malloc(sizeof(struct enum_list)); X } else { X ep->next = (struct enum_list *) X Malloc(sizeof(struct enum_list)); X ep = ep->next; X } X ep->next = 0; X /* a reasonable approximation for the length */ X ep->label = X (char *)Malloc((unsigned)strlen(token) + 1); X strcpy(ep->label, token); X type = get_token(fp, token); X if (type != LEFTPAREN){ X print_error("Expected \"(\"", token, type); X free_node(np); X return 0; X } X type = get_token(fp, token); X if (type != NUMBER){ X print_error("Expected integer", token, type); X free_node(np); X return 0; X } X ep->value = atoi(token); X type = get_token(fp, token); X if (type != RIGHTPAREN){ X print_error("Expected \")\"", token, type); X free_node(np); X return 0; X } X } X } X if (type == ENDOFFILE){ X print_error("Expected \"}\"", token, type); X free_node(np); X return 0; X } X nexttype = get_token(fp, nexttoken); X } else if (nexttype == LEFTPAREN){ X /* ignore the "constrained integer" for now */ X nexttype = get_token(fp, nexttoken); X nexttype = get_token(fp, nexttoken); X nexttype = get_token(fp, nexttoken); X } X break; X case OCTETSTR: X strcpy(syntax, token); X /* ignore the "constrained octet string" for now */ X if (nexttype == LEFTPAREN) { X nexttype = get_token(fp, nexttoken); X if (nexttype == SIZE) { X nexttype = get_token(fp, nexttoken); X if (nexttype == LEFTPAREN) { X nexttype = get_token(fp, nexttoken); /* 0..255 */ X nexttype = get_token(fp, nexttoken); /* ) */ X nexttype = get_token(fp, nexttoken); /* ) */ X if (nexttype == RIGHTPAREN) X { X nexttype = get_token(fp, nexttoken); X break; X } X } X } X print_error("Bad syntax", token, type); X free_node(np); X return 0; X } X break; X case OBJID: X case NETADDR: X case IPADDR: X case COUNTER: X case GAUGE: X case TIMETICKS: SHAR_EOF : || echo 'restore of snmp2/snmplib/parse.c failed' fi echo 'End of snmp2 part 2' echo 'File snmp2/snmplib/parse.c is continued in part 3' echo 3 > _sharseq.tmp exit 0