#!/bin/sh # This is `snmp2.03' (part 3 of snmp2). # Do not concatenate these parts, unpack them in order with `/bin/sh'. # File `snmp2/snmplib/parse.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" != 3; then echo "Please unpack part $shar_sequence next!" exit 1 fi if test ! -f _sharnew.tmp; then echo 'x - still skipping snmp2/snmplib/parse.c' else echo 'x - continuing file snmp2/snmplib/parse.c' sed 's/^X//' << 'SHAR_EOF' >> 'snmp2/snmplib/parse.c' && X case OPAQUE: X case NUL: X case LABEL: X case NSAPADDRESS: X case COUNTER64: X strcpy(syntax, token); X break; X default: X print_error("Bad syntax", token, type); X free_node(np); X return 0; X } X if (nexttype == UNITS){ X type = get_token(fp, token); X if (type != QUOTESTRING) { X print_error("Bad DESCRIPTION", token, type); X free_node(np); X return 0; X } X nexttype = get_token(fp, nexttoken); X } X if (nexttype != ACCESS){ X print_error("Should be ACCESS", nexttoken, nexttype); X free_node(np); X return 0; X } X type = get_token(fp, token); X if (type != READONLY && type != READWRITE && type != WRITEONLY X && type != NOACCESS && type != READCREATE){ X print_error("Bad access type", nexttoken, nexttype); X free_node(np); X return 0; X } X type = get_token(fp, token); X if (type != STATUS){ X print_error("Should be STATUS", token, nexttype); X free_node(np); X return 0; X } X type = get_token(fp, token); X if (type != MANDATORY && type != CURRENT && type != OPTIONAL && type != OBSOLETE && type != DEPRECATED){ X print_error("Bad status", token, type); X free_node(np); X return 0; X } X /* X * Optional parts of the OBJECT-TYPE macro X */ X type = get_token(fp, token); X while (type != EQUALS) { X switch (type) { X case DESCRIPTION: X type = get_token(fp, token); X if (type != QUOTESTRING) { X print_error("Bad DESCRIPTION", token, type); X free_node(np); X return 0; X } #ifdef TEST printf("Description== \"%.50s\"\n", quoted_string_buffer); #endif X np->description = quoted_string_buffer; X quoted_string_buffer = (char *)malloc(MAXQUOTESTR); X break; X X case REFERENCE: X type = get_token(fp, token); X if (type != QUOTESTRING) { X print_error("Bad DESCRIPTION", token, type); X free_node(np); X return 0; X } X break; X case INDEX: X case DEFVAL: X case AUGMENTS: X case NUM_ENTRIES: X if (tossObjectIdentifier(fp) != OBJID) { X print_error("Bad Object Identifier", token, type); X free_node(np); X return 0; X } X break; X X default: X print_error("Bad format of optional clauses", token,type); X free_node(np); X return 0; X X } X type = get_token(fp, token); X } X if (type != EQUALS){ X print_error("Bad format", token, type); X free_node(np); X return 0; X } X length = getoid(fp, oid, 32); X if (length > 1 && length <= 32){ X /* just take the last pair in the oid list */ X if (oid[length - 2].label) X strncpy(np->parent, oid[length - 2].label, MAXLABEL); X strcpy(np->label, name); X if (oid[length - 1].subid != -1) X np->subid = oid[length - 1].subid; X else X print_error("Warning: This entry is pretty silly", np->label, type); X } else { X print_error("No end to oid", (char *)NULL, type); X free_node(np); X np = 0; X } X /* free oid array */ X for(count = 0; count < length; count++){ X if (oid[count].label) X free(oid[count].label); X oid[count].label = 0; X } X return np; } X X /* X * Parses an OBJECT GROUP macro. X * Returns 0 on error. X */ static struct node * parse_objectgroup(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 np = (struct node *)Malloc(sizeof(struct node)); X np->type = 0; X np->next = 0; X np->enums = 0; X np->description = NULL; /* default to an empty description */ X type = get_token(fp, token); X while (type != EQUALS) { X switch (type) { X case DESCRIPTION: X type = get_token(fp, token); X if (type != QUOTESTRING) { X print_error("Bad DESCRIPTION", token, type); X free_node(np); X return 0; X } #ifdef TEST printf("Description== \"%.50s\"\n", quoted_string_buffer); #endif X np->description = quoted_string_buffer; X quoted_string_buffer = (char *)malloc(MAXQUOTESTR); X break; X X default: X /* NOTHING */ X break; X } X type = get_token(fp, token); X } X length = getoid(fp, oid, 32); X if (length > 1 && length <= 32){ X /* just take the last pair in the oid list */ X if (oid[length - 2].label) X strncpy(np->parent, oid[length - 2].label, MAXLABEL); X strcpy(np->label, name); X if (oid[length - 1].subid != -1) X np->subid = oid[length - 1].subid; X else X print_error("Warning: This entry is pretty silly", np->label, type); X } else { X print_error("No end to oid", (char *)NULL, type); X free_node(np); X np = 0; X } X /* free oid array */ X for(count = 0; count < length; count++){ X if (oid[count].label) X free(oid[count].label); X oid[count].label = 0; X } X return np; } X /* X * Parses a NOTIFICATION-TYPE macro. X * Returns 0 on error. X */ static struct node * parse_notificationDefinition(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 np = (struct node *)Malloc(sizeof(struct node)); X np->type = 0; X np->next = 0; X np->enums = 0; X np->description = NULL; /* default to an empty description */ X type = get_token(fp, token); X while (type != EQUALS) { X switch (type) { X case DESCRIPTION: X type = get_token(fp, token); X if (type != QUOTESTRING) { X print_error("Bad DESCRIPTION", token, type); X free_node(np); X return 0; X } #ifdef TEST printf("Description== \"%.50s\"\n", quoted_string_buffer); #endif X np->description = quoted_string_buffer; X quoted_string_buffer = (char *)malloc(MAXQUOTESTR); X break; X X default: X /* NOTHING */ X break; X } X type = get_token(fp, token); X } X length = getoid(fp, oid, 32); X if (length > 1 && length <= 32){ X /* just take the last pair in the oid list */ X if (oid[length - 2].label) X strncpy(np->parent, oid[length - 2].label, MAXLABEL); X strcpy(np->label, name); X if (oid[length - 1].subid != -1) X np->subid = oid[length - 1].subid; X else X print_error("Warning: This entry is pretty silly", np->label, type); X } else { X print_error("No end to oid", (char *)NULL, type); X free_node(np); X np = 0; X } X /* free oid array */ X for(count = 0; count < length; count++){ X if (oid[count].label) X free(oid[count].label); X oid[count].label = 0; X } X return np; } X /* X * Parses a compliance macro X * Returns 0 on error. X */ static struct node * parse_compliance(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 np = (struct node *)Malloc(sizeof(struct node)); X np->type = 0; X np->next = 0; X np->enums = 0; X np->description = NULL; /* default to an empty description */ X type = get_token(fp, token); X while (type != EQUALS) { X type = get_token(fp, token); X } X length = getoid(fp, oid, 32); X if (length > 1 && length <= 32){ X /* just take the last pair in the oid list */ X if (oid[length - 2].label) X strncpy(np->parent, oid[length - 2].label, MAXLABEL); X strcpy(np->label, name); X if (oid[length - 1].subid != -1) X np->subid = oid[length - 1].subid; X else X print_error("Warning: This entry is pretty silly", np->label, type); X } else { X print_error("No end to oid", (char *)NULL, type); X free_node(np); X np = 0; X } X /* free oid array */ X for(count = 0; count < length; count++){ X if (oid[count].label) X free(oid[count].label); X oid[count].label = 0; X } X return np; } X X X /* X * Parses a module identity macro X * Returns 0 on error. X */ static struct node * parse_moduleIdentity(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 np = (struct node *)Malloc(sizeof(struct node)); X np->type = 0; X np->next = 0; X np->enums = 0; X np->description = NULL; /* default to an empty description */ X type = get_token(fp, token); X while (type != EQUALS) { X type = get_token(fp, token); X } X length = getoid(fp, oid, 32); X if (length > 1 && length <= 32){ X /* just take the last pair in the oid list */ X if (oid[length - 2].label) X strncpy(np->parent, oid[length - 2].label, MAXLABEL); X strcpy(np->label, name); X if (oid[length - 1].subid != -1) X np->subid = oid[length - 1].subid; X else X print_error("Warning: This entry is pretty silly", np->label, type); X } else { X print_error("No end to oid", (char *)NULL, type); X free_node(np); X np = 0; X } X /* free oid array */ X for(count = 0; count < length; count++){ X if (oid[count].label) X free(oid[count].label); X oid[count].label = 0; X } X return np; } X int parse_mib_header(fp, name) X register FILE *fp; X char *name; { X int type = DEFINITIONS; X char token[MAXTOKEN]; X X /* This probably isn't good enough. If there is no X imports clause we can't go around waiting (forever) for a semicolon. X We need to check for semi following an EXPORTS clause or an IMPORTS X clause of both. Look for BEGIN; in my initial MIBs to see those X that I needed to hack to get to parse because they didn't have X an IMPORTS or and EXPORTS clause. X */ X while(type != SEMI){ X type = get_token(fp, token); X } X return 1; } X X X /* X * Parses a mib file and returns a linked list of nodes found in the file. X * Returns NULL on error. X */ static struct node * parse(fp) X FILE *fp; { X char token[MAXTOKEN]; X char name[MAXTOKEN]; X int type = 1; #define BETWEEN_MIBS 1 #define IN_MIB 2 X int state = BETWEEN_MIBS; X struct node *np, *root = NULL; X X hash_init(); X quoted_string_buffer = (char *)malloc(MAXQUOTESTR); /* free this later */ X bzero(tclist, 64 * sizeof(struct tc)); X X while(type != ENDOFFILE){ X type = get_token(fp, token); skipget: X if (type == END){ X if (state != IN_MIB){ X print_error("Error, end before start of MIB.", (char *)NULL, type); X return NULL; X } X state = BETWEEN_MIBS; X continue; X } else if (type != LABEL){ X if (type == ENDOFFILE){ X return root; X } X print_error(token, "is a reserved word", type); X return NULL; X } X strncpy(name, token, MAXTOKEN); X type = get_token(fp, token); X if (type == DEFINITIONS){ X if (state != BETWEEN_MIBS){ X print_error("Error, nested MIBS.", (char *)NULL, type); X return NULL; X } X state = IN_MIB; X if (!parse_mib_header(fp, name)){ X print_error("Bad parse of module header", (char *)NULL, type); X return NULL; X } X } else if (type == OBJTYPE){ X if (root == NULL){ X /* first link in chain */ X np = root = parse_objecttype(fp, name); X if (np == NULL){ X print_error("Bad parse of object type", (char *)NULL, X type); X return NULL; X } X } else { X np->next = parse_objecttype(fp, name); X if (np->next == NULL){ X print_error("Bad parse of objecttype", (char *)NULL, X type); X return NULL; X } X } X /* now find end of chain */ X while(np->next) X np = np->next; X } else if (type == OBJGROUP){ X if (root == NULL){ X /* first link in chain */ X np = root = parse_objectgroup(fp, name); X if (np == NULL){ X print_error("Bad parse of object group", (char *)NULL, X type); X return NULL; X } X } else { X np->next = parse_objectgroup(fp, name); X if (np->next == NULL){ X print_error("Bad parse of objectgroup", (char *)NULL, X type); X return NULL; X } X } X /* now find end of chain */ X while(np->next) X np = np->next; X } else if (type == NOTIFTYPE){ X if (root == NULL){ X /* first link in chain */ X np = root = parse_notificationDefinition(fp, name); X if (np == NULL){ X print_error("Bad parse of notification definition", X (char *)NULL, type); X return NULL; X } X } else { X np->next = parse_notificationDefinition(fp, name); X if (np->next == NULL){ X print_error("Bad parse of notification definition", X (char *)NULL, type); X return NULL; X } X } X /* now find end of chain */ X while(np->next) X np = np->next; X } else if (type == COMPLIANCE){ X if (root == NULL){ X /* first link in chain */ X np = root = parse_compliance(fp, name); X if (np == NULL){ X print_error("Bad parse of module compliance", (char *)NULL, X type); X return NULL; X } X } else { X np->next = parse_compliance(fp, name); X if (np->next == NULL){ X print_error("Bad parse of module compliance", (char *)NULL, X type); X return NULL; X } X } X /* now find end of chain */ X while(np->next) X np = np->next; X } else if (type == MODULEIDENTITY){ X if (root == NULL){ X /* first link in chain */ X np = root = parse_moduleIdentity(fp, name); X if (np == NULL){ X print_error("Bad parse of module identity", (char *)NULL, X type); X return NULL; X } X } else { X np->next = parse_moduleIdentity(fp, name); X if (np->next == NULL){ X print_error("Bad parse of module identity", (char *)NULL, X type); X return NULL; X } X } X /* now find end of chain */ X while(np->next) X np = np->next; X } else if (type == OBJID){ X if (root == NULL){ X /* first link in chain */ X np = root = parse_objectid(fp, name); X if (np == NULL){ X print_error("Bad parse of object id", (char *)NULL, type); X return NULL; X } X } else { X np->next = parse_objectid(fp, name); X if (np->next == NULL){ X print_error("Bad parse of object type", (char *)NULL, X type); X return NULL; X } X } X /* now find end of chain */ X while(np->next) X np = np->next; X } else if (type == EQUALS){ X if (!parse_asntype(fp, name, &type, token)){ X print_error("Bad parse of ASN type definition.", NULL, EQUALS); X return NULL; X } X goto skipget; X } else if (type == ENDOFFILE){ X break; X } else { X print_error("Bad operator", (char *)NULL, type); X return NULL; X } X } #ifdef TEST { X struct enum_list *ep; X X for(np = root; np; np = np->next){ X printf("%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid, X np->type); X if (np->enums){ X printf("Enums: \n"); X for(ep = np->enums; ep; ep = ep->next){ X printf("%s(%d)\n", ep->label, ep->value); X } X } X } } #endif /* TEST */ X return root; } X /* X * Parses a token from the file. The type of the token parsed is returned, X * and the text is placed in the string pointed to by token. X */ static int get_token(fp, token) X register FILE *fp; X register char *token; { X static char last = ' '; X register int ch; X register char *cp = token; X register int hash = 0; X register struct tok *tp; X X *cp = 0; X ch = last; X /* skip all white space */ X while(isspace(ch) && ch != -1){ X ch = getc(fp); X if (ch == '\n') X Line++; X } X if (ch == -1) { X return ENDOFFILE; X } else if (ch == '"') { X return parseQuoteString(fp, token); X } X X /* X * Accumulate characters until end of token is found. Then attempt to X * match this token as a reserved word. If a match is found, return the X * type. Else it is a label. X */ X do { X if (ch == '\n') X Line++; X if (isspace(ch) || ch == '(' || ch == ')' || ch == '{' || ch == '}' || X ch == ',' || ch == ';'){ X if (!isspace(ch) && *token == 0){ X hash += ch; X *cp++ = ch; X last = ' '; X } else { X last = ch; X } X *cp = '\0'; X X for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) { X if ((tp->hash == hash) && (strcmp(tp->name, token) == 0)) X break; X } X if (tp){ X if (tp->token == CONTINUE) X continue; X return (tp->token); X } X X if (token[0] == '-' && token[1] == '-'){ X /* strip comment */ X if (ch != '\n'){ X while ((ch = getc(fp)) != -1) X if (ch == '\n'){ X Line++; X break; X } X } X if (ch == -1) X return ENDOFFILE; X last = ch; X return get_token(fp, token); X } X for(cp = token; *cp; cp++) X if (!isdigit(*cp)) X return LABEL; X return NUMBER; X } else { X hash += ch; X *cp++ = ch; X if (ch == '\n') X Line++; X } X X } while ((ch = getc(fp)) != -1); X return ENDOFFILE; } X struct tree * read_mib(filename) X char *filename; { X FILE *fp; X struct node *nodes; X struct tree *tree; X X fp = fopen(filename, "r"); X if (fp == NULL) X return NULL; X nodes = parse(fp); X if (!nodes){ X fprintf(stderr, "Mib table is bad. Exiting\n"); X exit(1); X } X tree = build_tree(nodes); X fclose(fp); X return tree; } X X #ifdef TEST main(argc, argv) X int argc; X char *argv[]; { X FILE *fp; X struct node *nodes; X struct tree *tp; X X fp = fopen("mib.txt", "r"); X if (fp == NULL){ X fprintf(stderr, "open failed\n"); X return 1; X } X nodes = parse(fp); X tp = build_tree(nodes); X print_subtree(tp, 0); X fclose(fp); } X #endif /* TEST */ X static int parseQuoteString(fp, token) X register FILE *fp; X register char *token; { X register int ch; X int eat_space = 0; X X ch = ' '; X *token = '\0'; /* make the token empty */ X X while(ch != -1) { X ch = getc(fp); X if (ch == '\n') X Line++; X else if (ch == '"') { X return QUOTESTRING; X } X X } X X return NULL; } X /* X * This routine parses a string like { blah blah blah } and returns OBJID if X * it is well formed, and NULL if not. X */ static int tossObjectIdentifier(fp) X register FILE *fp; { X register int ch; X X ch = getc(fp); /* ch = last; = ' '? */ X /* skip all white space */ X while(isspace(ch) && ch != -1){ X ch = getc(fp); X if (ch == '\n') X Line++; X } X if (ch != '{') X return NULL; X X while(ch != -1) { X ch = getc(fp); X X if (ch == '\n') X Line++; X else if (ch == '}') X return OBJID; X } X /* last = ch;*/ X return NULL; } SHAR_EOF echo 'File snmp2/snmplib/parse.c is complete' && $shar_touch -am 1015123593 'snmp2/snmplib/parse.c' && chmod 0644 'snmp2/snmplib/parse.c' || echo 'restore of snmp2/snmplib/parse.c failed' shar_count="`wc -c < 'snmp2/snmplib/parse.c'`" test 45738 -eq "$shar_count" || echo "snmp2/snmplib/parse.c: original size 45738, current size $shar_count" rm -f _sharnew.tmp fi # ============= snmp2/snmplib/snmp.c ============== if test -f 'snmp2/snmplib/snmp.c' && test X"$1" != X"-c"; then echo 'x - skipping snmp2/snmplib/snmp.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting snmp2/snmplib/snmp.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'snmp2/snmplib/snmp.c' && /* X * Simple Network Management Protocol (RFC 1067). X * X */ /********************************************************************** X Copyright 1988, 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 #ifdef KINETICS #include "gw.h" #include "ab.h" #include "inet.h" #include "fp4/cmdmacro.h" #include "fp4/pbuf.h" #include "glob.h" #endif X #if (defined(unix) && !defined(KINETICS)) #include #include #ifndef NULL #define NULL 0 #endif #endif X #ifdef vms #include #endif X #ifdef VXWORKS #include "VXtypes.h" #endif X #include "asn1.h" #include "snmp.h" #include "snmp_impl.h" X #include "mib.h" X #if 0 #define ERROR(string) #endif X X xdump(cp, length, prefix) X u_char *cp; X int length; X char *prefix; { X int col, count; X X count = 0; X while(count < length){ X printf("%s", prefix); X for(col = 0;count + col < length && col < 16; col++){ X if (col != 0 && (col % 4) == 0) X printf(" "); X printf("%02X ", cp[count + col]); X } X while(col++ < 16){ /* pad end of buffer with zeros */ X if ((col % 4) == 0) X printf(" "); X printf(" "); X } X printf(" "); X for(col = 0;count + col < length && col < 16; col++){ X if (isprint(cp[count + col])) X printf("%c", cp[count + col]); X else X printf("."); X } X printf("\n"); X count += col; X } X } X X X u_char * snmp_parse_var_op(data, var_name, var_name_len, var_val_type, var_val_len, var_val, listlength) X register u_char *data; /* IN - pointer to the start of object */ X oid *var_name; /* OUT - object id of variable */ X int *var_name_len; /* IN/OUT - length of variable name */ X u_char *var_val_type; /* OUT - type of variable (int or octet string) (one byte) */ X int *var_val_len; /* OUT - length of variable */ X u_char **var_val; /* OUT - pointer to ASN1 encoded value of variable */ X int *listlength; /* IN/OUT - number of valid bytes left in var_op_list */ { X u_char var_op_type; X int var_op_len = *listlength; X u_char *var_op_start = data; X X data = asn_parse_header(data, &var_op_len, &var_op_type); X if (data == NULL){ X ERROR(""); X return NULL; X } X if (var_op_type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) X return NULL; X data = asn_parse_objid(data, &var_op_len, &var_op_type, var_name, var_name_len); X if (data == NULL){ X ERROR(""); X return NULL; X } X if (var_op_type != (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID)) X return NULL; X *var_val = data; /* save pointer to this object */ X /* find out what type of object this is */ X data = asn_parse_header(data, &var_op_len, var_val_type); X if (data == NULL){ X ERROR(""); X return NULL; X } X *var_val_len = var_op_len; X data += var_op_len; X *listlength -= (int)(data - var_op_start); X return data; } X u_char * snmp_build_var_op(data, var_name, var_name_len, var_val_type, var_val_len, X var_val, listlength) X register u_char *data; /* IN - pointer to the beginning of the output buffer */ X oid *var_name; /* IN - object id of variable */ X int *var_name_len; /* IN - length of object id */ X u_char var_val_type; /* IN - type of variable */ X int var_val_len; /* IN - length of variable */ X u_char *var_val; /* IN - value of variable */ X register int *listlength; /* IN/OUT - number of valid bytes left in X output buffer */ { X int dummyLen, headerLen, header_shift; X u_char *dataPtr; X X dummyLen = *listlength; X dataPtr = data; #if 0 X data = asn_build_sequence(data, &dummyLen, X (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); X if (data == NULL){ X ERROR(""); X return NULL; X } #endif X data += 4; X dummyLen -=4; X if (dummyLen < 0) X return NULL; X X headerLen = data - dataPtr; X *listlength -= headerLen; X data = asn_build_objid(data, listlength, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), X var_name, *var_name_len); X if (data == NULL){ X ERROR(""); X return NULL; X } X switch(var_val_type){ X case ASN_INTEGER: X data = asn_build_int(data, listlength, var_val_type, X (long *)var_val, var_val_len); X break; X case GAUGE: X case COUNTER: X case TIMETICKS: X case UINTEGER: X data = asn_build_unsigned_int(data, listlength, var_val_type, X (u_long *)var_val, var_val_len); X break; X case COUNTER64: X data = asn_build_unsigned_int64(data, listlength, var_val_type, X (struct counter64 *)var_val, X var_val_len); X break; X case ASN_OCTET_STR: X case IPADDRESS: X case OPAQUE: X case NSAP: X data = asn_build_string(data, listlength, var_val_type, X var_val, var_val_len); X break; X case ASN_OBJECT_ID: X data = asn_build_objid(data, listlength, var_val_type, X (oid *)var_val, var_val_len / sizeof(oid)); X break; X case ASN_NULL: X data = asn_build_null(data, listlength, var_val_type); X break; X case ASN_BIT_STR: X data = asn_build_bitstring(data, listlength, var_val_type, X var_val, var_val_len); X break; X case SNMP_NOSUCHOBJECT: X case SNMP_NOSUCHINSTANCE: X case SNMP_ENDOFMIBVIEW: X data = asn_build_null(data, listlength, var_val_type); X break; X default: X ERROR("wrong type"); X return NULL; X } X if (data == NULL){ X ERROR(""); X return NULL; X } X dummyLen = (data - dataPtr) - headerLen; X X asn_build_sequence(dataPtr, &dummyLen, X (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), dummyLen); X return data; } SHAR_EOF $shar_touch -am 1015123593 'snmp2/snmplib/snmp.c' && chmod 0644 'snmp2/snmplib/snmp.c' || echo 'restore of snmp2/snmplib/snmp.c failed' shar_count="`wc -c < 'snmp2/snmplib/snmp.c'`" test 6416 -eq "$shar_count" || echo "snmp2/snmplib/snmp.c: original size 6416, current size $shar_count" rm -f _sharnew.tmp fi # ============= snmp2/snmplib/snmp_api.c ============== if test -f 'snmp2/snmplib/snmp_api.c' && test X"$1" != X"-c"; then echo 'x - skipping snmp2/snmplib/snmp_api.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting snmp2/snmplib/snmp_api.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'snmp2/snmplib/snmp_api.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 * snmp_api.c - API for access to snmp. X */ X #include #include #ifndef VXWORKS #include #endif #ifdef VXWORKS #include "VXtime.h" #else #include #endif #include #include #ifdef VXWORKS #include "VXnetdb.h" #else #include #endif #include "asn1.h" #include "snmp.h" #include "snmp_impl.h" #include "snmp_api.h" X #define PACKET_LENGTH 8000 X #ifndef BSD4_3 #define BSD4_2 #endif X #ifndef FD_SET X typedef long fd_mask; #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ X #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) #endif X oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ X #define DEFAULT_COMMUNITY "public" #define DEFAULT_RETRIES 5 #define DEFAULT_TIMEOUT 1000000L #define DEFAULT_REMPORT SNMP_PORT #define DEFAULT_ENTERPRISE default_enterprise #define DEFAULT_TIME 0 X X /* X * Internal information about the state of the snmp session. X */ struct snmp_internal_session { X int sd; /* socket descriptor for this connection */ X ipaddr addr; /* address of connected peer */ X struct request_list *requests;/* Info about outstanding requests */ X struct request_list *requestsEnd; /* ptr to end of list */ }; X /* X * A list of all the outstanding requests for a particular session. X */ struct request_list { X struct request_list *next_request; X long request_id; /* request id */ X int retries; /* Number of retries */ X u_long timeout; /* length to wait for timeout */ X struct timeval time; /* Time this request was made */ X struct timeval expire; /* time this request is due to expire */ X struct snmp_pdu *pdu; /* The pdu for this request X (saved so it can be retransmitted */ }; X struct internal_variable_list { X struct variable_list *next_variable; /* NULL for last variable */ X oid *name; /* Object identifier of variable */ X int name_length; /* number of subid's in name */ X u_char type; /* ASN type of variable */ X union { /* value of variable */ X long *integer; X u_char *string; X oid *objid; X u_char *bitstring; X struct counter64 *counter64; X } val; X int val_len; X oid name_loc[MAX_NAME_LEN]; X u_char buf[32]; X int usedBuf; }; X struct internal_snmp_pdu { X int version; X X ipaddr address; /* Address of peer */ X oid *srcParty; X int srcPartyLen; X oid *dstParty; X int dstPartyLen; X oid *context; X int contextLen; X X u_char *community; /* community for outgoing requests. */ X int community_len; /* Length of community name. */ X X int command; /* Type of this PDU */ X X long reqid; /* Request id */ X long errstat; /* Error status (non_repeaters in GetBulk) */ X long errindex; /* Error index (max_repetitions in GetBulk) */ X X /* Trap information */ X oid *enterprise;/* System OID */ X int enterprise_length; X ipaddr agent_addr; /* address of object generating trap */ X int trap_type; /* trap type */ X int specific_type; /* specific type */ X u_long time; /* Uptime */ X X struct variable_list *variables; X oid srcPartyBuf[MAX_NAME_LEN]; X oid dstPartyBuf[MAX_NAME_LEN]; X oid contextBuf[MAX_NAME_LEN]; X /* XXX do community later */ X }; X /* X * The list of active/open sessions. X */ struct session_list { X struct session_list *next; X struct snmp_session *session; X struct snmp_internal_session *internal; }; X static struct session_list *Sessions = NULL; X static long Reqid = 0; static int snmp_errno = 0; X static char *api_errors[4] = { X "Unknown session", X "Unknown host", X "Invalid local port", X "Unknown Error" }; X static struct timeval Now; static struct snmp_pdu *SavedPdu = NULL; static struct internal_variable_list *SavedVars = NULL; X static char * api_errstring(snmp_errnumber) X int snmp_errnumber; { X if (snmp_errnumber <= SNMPERR_BAD_SESSION X && snmp_errnumber >= SNMPERR_GENERR){ X return api_errors[snmp_errnumber + 4]; X } else { X return "Unknown Error"; X } } X X /* X * Gets initial request ID for all transactions. X */ static init_snmp(){ X struct timeval tv; X X gettimeofday(&tv, (struct timezone *)0); X Now = tv; X srandom(tv.tv_sec ^ tv.tv_usec); X Reqid = random(); } X /* X * Sets up the session with the snmp_session information provided X * by the user. Then opens and binds the necessary UDP port. X * A handle to the created session is returned (this is different than X * the pointer passed to snmp_open()). On any error, NULL is returned X * and snmp_errno is set to the appropriate error code. X */ struct snmp_session * snmp_open(session) X struct snmp_session *session; { X struct session_list *slp; X struct snmp_internal_session *isp; X u_char *cp; X oid *op; X int sd; X u_long addr; X struct sockaddr_in me; X struct hostent *hp; X struct servent *servp; X X X if (Reqid == 0) X init_snmp(); X X /* Copy session structure and link into list */ X slp = (struct session_list *)malloc(sizeof(struct session_list)); X slp->internal = isp = (struct snmp_internal_session *)malloc(sizeof(struct snmp_internal_session)); X bzero((char *)isp, sizeof(struct snmp_internal_session)); X slp->internal->sd = -1; /* mark it not set */ X slp->session = (struct snmp_session *)malloc(sizeof(struct snmp_session)); X bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); X session = slp->session; X /* now link it in. */ X slp->next = Sessions; X Sessions = slp; X /* X * session now points to the new structure that still contains pointers to X * data allocated elsewhere. Some of this data is copied to space malloc'd X * here, and the pointer replaced with the new one. X */ X X if (session->peername != NULL){ X cp = (u_char *)malloc((unsigned)strlen(session->peername) + 1); X strcpy((char *)cp, session->peername); X session->peername = (char *)cp; X } X X /* Fill in defaults if necessary */ X if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ X cp = (u_char *)malloc((unsigned)session->community_len); X bcopy((char *)session->community, (char *)cp, session->community_len); X } else { X session->community_len = strlen(DEFAULT_COMMUNITY); X cp = (u_char *)malloc((unsigned)session->community_len); X bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); X } X session->community = cp; /* replace pointer with pointer to new data */ X X if (session->srcPartyLen > 0){ X op = (oid *)malloc((unsigned)session->srcPartyLen * sizeof(oid)); X bcopy((char *)session->srcParty, (char *)op, X session->srcPartyLen * sizeof(oid)); X session->srcParty = op; X } else { X session->srcParty = 0; X } X X if (session->dstPartyLen > 0){ X op = (oid *)malloc((unsigned)session->dstPartyLen * sizeof(oid)); X bcopy((char *)session->dstParty, (char *)op, X session->dstPartyLen * sizeof(oid)); X session->dstParty = op; X } else { X session->dstParty = 0; X } X X if (session->contextLen > 0){ X op = (oid *)malloc((unsigned)session->contextLen * sizeof(oid)); X bcopy((char *)session->context, (char *)op, X session->contextLen * sizeof(oid)); X session->context = op; X } else { X session->context = 0; X } X X if (session->retries == SNMP_DEFAULT_RETRIES) X session->retries = DEFAULT_RETRIES; X if (session->timeout == SNMP_DEFAULT_TIMEOUT) X session->timeout = DEFAULT_TIMEOUT; X isp->requests = isp->requestsEnd = NULL; X X /* Set up connections */ X sd = socket(AF_INET, SOCK_DGRAM, 0); X if (sd < 0){ X perror("socket"); X snmp_errno = SNMPERR_GENERR; X if (!snmp_close(session)){ X fprintf(stderr, "Couldn't abort session: %s. Exiting\n", X api_errstring(snmp_errno)); X exit(1); X } X return 0; X } X isp->sd = sd; X if (session->peername != SNMP_DEFAULT_PEERNAME){ X if ((addr = inet_addr(session->peername)) != -1){ X bcopy((char *)&addr, (char *)&isp->addr.sin_addr, X sizeof(isp->addr.sin_addr)); X } else { X hp = gethostbyname(session->peername); X if (hp == NULL){ X fprintf(stderr, "unknown host: %s\n", session->peername); X snmp_errno = SNMPERR_BAD_ADDRESS; X if (!snmp_close(session)){ X fprintf(stderr, "Couldn't abort session: %s. Exiting\n", X api_errstring(snmp_errno)); X exit(2); X } X return 0; X } else { X bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, X hp->h_length); X } X } X isp->addr.sin_family = AF_INET; X if (session->remote_port == SNMP_DEFAULT_REMPORT){ X servp = getservbyname("snmp", "udp"); X if (servp != NULL){ X isp->addr.sin_port = servp->s_port; X } else { X isp->addr.sin_port = htons(SNMP_PORT); X } X } else { X isp->addr.sin_port = htons(session->remote_port); X } X } else { X isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; X } X X me.sin_family = AF_INET; X me.sin_addr.s_addr = INADDR_ANY; X me.sin_port = htons(session->local_port); X if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ X perror("bind"); X snmp_errno = SNMPERR_BAD_LOCPORT; X if (!snmp_close(session)){ X fprintf(stderr, "Couldn't abort session: %s. Exiting\n", X api_errstring(snmp_errno)); X exit(3); X } X return 0; X } X return session; } X X /* X * Free each element in the input request list. X */ static free_request_list(rp) X struct request_list *rp; { X struct request_list *orp; X X while(rp){ X orp = rp; X rp = rp->next_request; X if (orp->pdu != NULL) X snmp_free_pdu(orp->pdu); X free((char *)orp); X } } X /* X * Close the input session. Frees all data allocated for the session, X * dequeues any pending requests, and closes any sockets allocated for X * the session. Returns 0 on error, 1 otherwise. X */ int snmp_close(session) X struct snmp_session *session; { X struct session_list *slp = NULL, *oslp = NULL; X X if (Sessions->session == session){ /* If first entry */ X slp = Sessions; X Sessions = slp->next; X } else { X for(slp = Sessions; slp; slp = slp->next){ X if (slp->session == session){ X if (oslp) /* if we found entry that points here */ X oslp->next = slp->next; /* link around this entry */ X break; X } X oslp = slp; X } X } X /* If we found the session, free all data associated with it */ X if (slp){ X if (slp->session->community != NULL) X free((char *)slp->session->community); X if(slp->session->peername != NULL) X free((char *)slp->session->peername); X if (slp->session->srcParty != NULL) X free((char *)slp->session->srcParty); X if (slp->session->dstParty != NULL) X free((char *)slp->session->dstParty); X if (slp->session->context != NULL) X free((char *)slp->session->context); X free((char *)slp->session); X if (slp->internal->sd != -1) X close(slp->internal->sd); X free_request_list(slp->internal->requests); X free((char *)slp->internal); X free((char *)slp); X } else { X snmp_errno = SNMPERR_BAD_SESSION; X return 0; X } X return 1; } X shift_array(begin, length, shift_amount) X u_char *begin; X register int length; X int shift_amount; { X register u_char *old, *new; X X if (shift_amount >= 0){ X old = begin + length - 1; X new = old + shift_amount; X X while(length--) X *new-- = *old--; X } else { X old = begin; X new = begin + shift_amount; X X while(length--) X *new++ = *old++; X } } X /* X * Takes a session and a pdu and serializes the ASN PDU into the area X * pointed to by packet. out_length is the size of the data area available. X * Returns the length of the completed packet in out_length. If any errors X * occur, -1 is returned. If all goes well, 0 is returned. X */ static int snmp_build(session, pdu, packet, out_length) X struct snmp_session *session; X struct snmp_pdu *pdu; X register u_char *packet; X int *out_length; { X u_char *authEnd, *h1, *h1e, *h2; X register u_char *cp; X struct variable_list *vp; X struct packet_info pkt, *pi = &pkt; X int length, packet_length, header_length; X X if (session->version == SNMP_VERSION_1){ X cp = snmp_auth_build(packet, out_length, pdu->community, X &pdu->community_len, &pdu->version, X 0); X if (cp == NULL) X return -1; X } else if (session->version == SNMP_VERSION_2){ X pi->version = session->version; X pi->srcp = NULL; X pi->dstp = NULL; X cp = snmp_secauth_build(packet, out_length, pi, 0, X pdu->srcParty, pdu->srcPartyLen, X pdu->dstParty, pdu->dstPartyLen, X pdu->context, pdu->contextLen, X 0, FIRST_PASS); X if (cp == NULL) X return -1; X } else { X return -1; X } X authEnd = cp; X X h1 = cp; X if (session->version == SNMP_VERSION_1) X cp = asn_build_header(cp, out_length, (u_char)pdu->command, 0); X else X cp = asn_build_sequence(cp, out_length, (u_char)pdu->command, 0); X if (cp == NULL) X return -1; X h1e = cp; X X if (pdu->command != TRP_REQ_MSG){ X /* request id */ X cp = asn_build_int(cp, out_length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), X &pdu->reqid, sizeof(pdu->reqid)); X if (cp == NULL) X return -1; X /* error status */ X cp = asn_build_int(cp, out_length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), X &pdu->errstat, sizeof(pdu->errstat)); X if (cp == NULL) X return -1; X /* error index */ X cp = asn_build_int(cp, out_length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), X &pdu->errindex, sizeof(pdu->errindex)); X if (cp == NULL) X return -1; X } else { /* this is a trap message */ X /* enterprise */ X cp = asn_build_objid(cp, out_length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), X (oid *)pdu->enterprise, pdu->enterprise_length); X if (cp == NULL) X return -1; X /* agent-addr */ X cp = asn_build_string(cp, out_length, X (u_char)(IPADDRESS | ASN_PRIMITIVE), X (u_char *)&pdu->agent_addr.sin_addr.s_addr, X sizeof(pdu->agent_addr.sin_addr.s_addr)); X if (cp == NULL) X return -1; X /* generic trap */ X cp = asn_build_int(cp, out_length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), X (long *)&pdu->trap_type, sizeof(pdu->trap_type)); X if (cp == NULL) X return -1; X /* specific trap */ X cp = asn_build_int(cp, out_length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), X (long *)&pdu->specific_type, sizeof(pdu->specific_type)); X if (cp == NULL) X return -1; X /* timestamp */ X cp = asn_build_unsigned_int(cp, out_length, X (u_char)(TIMETICKS | ASN_PRIMITIVE), X &pdu->time, sizeof(pdu->time)); X if (cp == NULL) X return -1; X } X X h2 = cp; X cp = asn_build_sequence(cp, out_length, X (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), X 0); X if (cp == NULL) X return -1; X X for(vp = pdu->variables; vp; vp = vp->next_variable){ X cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, X vp->val_len, (u_char *)vp->val.string, X out_length); X if (cp == NULL) X return -1; X } X X length = PACKET_LENGTH; X asn_build_sequence(h2, &length, X (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), X (cp - h2) - 4); X if (session->version == SNMP_VERSION_1){ X if ((cp - h1e) < 0x80) X header_length = 2; X else if ((cp - h1e) <= 0xFF) X header_length = 3; X else X header_length = 4; X shift_array(h1e, cp - h1e, header_length + h1 - h1e); X asn_build_header(h1, &length, (u_char)pdu->command, cp - h1e); X cp += header_length + h1 - h1e; X } else { X asn_build_sequence(h1, &length, (u_char)pdu->command, (cp - h1) - 4); X } X X if (session->version == SNMP_VERSION_1){ X snmp_auth_build(packet, &length, pdu->community, X &pdu->community_len, &pdu->version, X cp - authEnd); X } else if (session->version == SNMP_VERSION_2){ X snmp_secauth_build(packet, &length, pi, cp - authEnd, X pdu->srcParty, pdu->srcPartyLen, X pdu->dstParty, pdu->dstPartyLen, X pdu->context, pdu->contextLen, X &packet_length, LAST_PASS); X cp = packet + packet_length; X /* DES encryption might bump length of packet */ X } X *out_length = cp - packet; X return 0; } X /* X * Parses the packet recieved on the input session, and places the data into X * the input pdu. length is the length of the input packet. If any errors X * are encountered, -1 is returned. Otherwise, a 0 is returned. X */ static int snmp_parse(session, pdu, data, length) X struct snmp_session *session; X struct internal_snmp_pdu *pdu; X u_char *data; X int length; { X u_char msg_type; X u_char type; X struct packet_info pkt, *pi = &pkt; X u_char *var_val; X long version; X int len, four; X u_char community[128]; X int community_length = 128; X struct internal_variable_list *vp; X oid objid[MAX_NAME_LEN], *op; X X len = length; X (void)asn_parse_header(data, &len, &type); X X if (type == (ASN_SEQUENCE | ASN_CONSTRUCTOR)){ X if (session->version != SNMP_VERSION_1) X return -1; X /* authenticates message and returns length if valid */ X data = snmp_auth_parse(data, &length, community, &community_length, X &version); X if (data == NULL) X return -1; X pdu->community_len = community_length; X pdu->community = (u_char *)malloc(community_length); X bcopy(community, pdu->community, community_length); X if (session->authenticator){ X data = session->authenticator(data, &length, X community, community_length); X if (data == NULL) X return 0; X } X X } else if (type == (ASN_CONTEXT | ASN_CONSTRUCTOR | 1)){ X if (session->version != SNMP_VERSION_2) X return -1; X pdu->srcParty = pdu->srcPartyBuf; X pdu->dstParty = pdu->dstPartyBuf; SHAR_EOF : || echo 'restore of snmp2/snmplib/snmp_api.c failed' fi echo 'End of snmp2 part 3' echo 'File snmp2/snmplib/snmp_api.c is continued in part 4' echo 4 > _sharseq.tmp exit 0