/***************************************************************************/ /* Module: $Id: osuasn.c,v 1.3 1999/05/07 04:15:26 maf Exp $ /* Description: Modules for ASN (Abstract Syntax Notation) Encoding/Decoding. /* Author: Shamim Ahmed /* Notes: doesn't fully work on BIG_ENDIAN - maf /* References: /* 1. Structure and Identification of Management Information /* for TCP/IP-based Internets. RFC 1155. /* ( Appendix F of Dowty SNMP project Notebook ). /* 2. The Simple Book by Marshall T.Rose. Prentic Hall. /* ( Appendix B of Dowty SNMP project Notebook ). /* 3. The Open Book by Marshall T.Rose. Prentice Hall /* (page 290 - 322) /***************************************************************************/ /* $Log: osuasn.c,v $ Revision 1.3 1999/05/07 04:15:26 maf pr -e2 Revision 1.2 1997/11/04 16:30:47 maf *** empty log message *** Revision 1.1 1997/02/23 18:05:09 maf Initial revision * Revision 2.3 1994/02/04 21:36:38 maf * *** empty log message *** * * Revision 2.2 1994/01/02 19:57:53 maf * memcpy > bcopy, fixed MAXOIDVAL bug (<= not <) * * Revision 2.1 1993/10/19 19:37:14 maf * kbconfig 1.7+ * * Revision 1.2 1993/09/02 18:30:45 maf * decodeint and decodetaglen no longer care about word/longword boundries * * Revision 1.1 1993/08/29 01:41:46 maf * Initial revision * */ #include #include #include "snmpdbg.h" #include "osusnmp.h" #ifdef MSDOS #define bcopy(a,b,c) memcpy(b,a,c) #endif /* MSDOS */ /* ASN uses tag-length-value fields for encoding */ #define MAX_LENGTH_FIELD_LENGTH 3 /* max. bytes for length field */ SnmpErrorType decodeAsnLen(); SnmpErrorType encodeAsnLen(); SnmpErrorType decodePosVal(); SnmpErrorType encodePosVal(); /*-------------------------------------------------------------------- ** asnDecodeLen: Decodes length field . ** ** DESCRIPTION: ** Decoded the length field. Length field is a part of ** Tag-Length-Vale fields used by ASN to encode objects. ** Also returns the bytes used while decoding. ** ** PARAMETERS: ** u_char *bp: pointer length field (input). ** short *len: length in number of bytes (output). ** short *bUse: bytes used while decoding length (output). ** ** RETURNS: ** snmpErrorNone: if no error. ** snmpErrorTooBig: if more than MAX_LENGTH_FIELD_LENGTH bytes ** are used while decoding. ** ** EXAMPLE: ** length = 144 is encoded as: ** 0x130,0x01,0x06. ** If bp points to 0x130 then *len = 144 and *bUsed = 3. ** ** REFERENCE: ** see Appendix B Dowty SNMP notebook page 172-173. **------------------------------------------------------------------*/ SnmpErrorType decodeAsnLen(bp,llen,bUse) u_char *bp; short *llen; short *bUse; { short lenSize; /* size of length in bytes */ short len; DEBUG_MSG2("decodeAsnLen bp=%p",bp); *bUse = 1; /* minimum one byte is used */ /* if MSB (bit 8) is zero then 7 LSB are the length */ if (!(*bp & 0x80)){ len = (short) *bp; } else { /* else if MSB = 1 then 7 LSB is the size of length */ lenSize = (short) (*bp++ & 0x7F); len = (short) 0; /* compute length. shift and add lenSize bytes */ for (; lenSize>0; lenSize--){ len = (len << 8) + (short) *bp++; *bUse = *bUse + 1; } } if (*bUse > MAX_LENGTH_FIELD_LENGTH) return(snmpErrorTooBig); /* FIXME this is still having alignment problems */ /* memcpy((char*)llen, (char*)&len, sizeof(short)); */ bcopy((char*)&len, (char*)llen, sizeof(short)); DEBUG_MSG2("decodeAsnLen OK Len=%u",*len); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** encodeAsnLen: Encodes length field . ** ** DESCRIPTION: ** Encodes length field for the Tag-Length-Value encoding. ** Also returns the bytes used while Encoding. ** ** PARAMETERS: ** u_char *bp: buffer receiving encoded length. ** short *len: length in number of bytes (input). ** short *bUse: length of encoded length (output). ** ** RETURNS: ** snmpErrorNone: no error. ** ** REFERENCE: ** see Appendix B Dowty SNMP notebook page 172-173. **------------------------------------------------------------------*/ SnmpErrorType encodeAsnLen(bp,len,bUse) u_char *bp; short len; short *bUse; { DEBUG_MSG2("encodeAsnLen bp=%p",bp); /* encoding length < 128 is simple */ if (len < 128){ *bp = (u_char) len; *bUse = 1; } else if (len < 256) { /* one full byte is needed for length. */ /* MSB=1: its number of bytes for length*/ *bp++ = (u_char) 0x081; /* put the length in next byte */ /* *bp++ = (u_char) (len & 0xFF); */ *bp = (u_char) len; *bUse = 2; } else { /* length in two bytes */ *bp++ = (u_char) 0x82; *bp++ = (u_char) ((len & 0xFF00) >> 8); *bp = (u_char) (len & (unsigned) 0x00FF); *bUse = 3; } DEBUG_MSG1("encodeAsnLen OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeInteger: Decodes Integer ** ** DESCRIPTION: ** Decodes an ASN encoded Integer into a Long Integer. ** ** PARAMETERS: ** u_char *bp = Pointer to an ASN interger (input). ** long *value = Pointer to decoded long integer (output). ** short *bUse = Bytes used while decoding(output). ** ** RETURNS: ** snmpErrorNone: If no error . ** snmpErrorBadValue: If tag is not ASN integer. ** snmpErrorTooBig: if value exceeds the range of 4 bytes. ** ** EXAMPLE: ** Asn Integer is Encoded as: ** | tag | length of value | value high-low byte order. | ** | 1 byte | 1 byte | 2'copmlement value in n bytes | ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 174. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeInt(bp,lvalue,bUse) u_char *bp; long *lvalue; short *bUse; { short len; /* length of value field */ long value; DEBUG_MSG2("asnDecodeInteger bp=%p",bp); /* check if tag is integer */ if (*bp++ != (Asn_Primitive | Asn_Universal | Asn_Integer)){ return(snmpErrorBadValue); } /* if value exceeds range of 4 bytes */ if ((len = (short) *bp++) > sizeof(long)){ return(snmpErrorTooBig); } /* bytes used = 1 for tag + 1 for length + len for value*/ *bUse = len + 2; value = 0L; /* if MSB = 1 then negative integer */ if (*bp & 0x80) value = (long) -1; /* shift and add value field */ for(;len > 0; len--){ value = (value << 8) + (long) *bp++; } /* FIXME this is still not workint - alignment problems */ /* memcpy((char*)lvalue, (char*)&value, sizeof(long)); */ bcopy((char*)&value, (char*)lvalue, sizeof(long)); DEBUG_MSG2("asnDecodeInteger OK val=%lu",*value); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeInteger: Encode Integer using ASN ** ** DESCRIPTION: ** Encodes a long integer to ASN form. ** ** PARAMETERS: ** u_char *bp = Pointer to buffer receiving ASN integer(output). ** long value = Value of long Integer (input). ** short *bUse = length of ASN integer(output). ** ** RETURNS: ** snmpErrorNone: No error . ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 174. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeInt(bp,value,bUse) u_char *bp; long value; short *bUse; { short vlen; /* # bytes for encoding value */ u_char *tp; /* temp. byte pointer */ u_long mask = 0xFF800000L; /* mask used for testing 9 leading ones/zeros */ DEBUG_MSG2("asnEncodeInt bp=%p",bp); /* Compute minimum number of bytes needed by discarding 9 leading 0's for positive numbers or 9 leading 1's for negative number */ vlen = sizeof(long); #if BYTE_ORDER == BIG_ENDIAN tp = (u_char *) &value; /* set tp to lowest byte */ #endif /* BIG_ENDIAN */ #if BYTE_ORDER == LITTLE_ENDIAN tp = (u_char *) &value + vlen-1; /* set tp to highest byte */ #endif /* LITTLE_ENDIAN */ while (((( mask & value) == 0)||((mask & value) == mask)) && (vlen > 1)) { #if BYTE_ORDER == BIG_ENDIAN tp++; #endif #if BYTE_ORDER == LITTLE_ENDIAN tp--; #endif vlen--; mask >>= 8; } *bUse = vlen + 2; /* need two bytes for tag + length */ *bp++ = (u_char)(Asn_Primitive | Asn_Universal | Asn_Integer); /* tag */ #if BYTE_ORDER == BIG_ENDIAN *bp = (u_char) vlen; /* length */ bp += vlen; /* SUN */ tp += (vlen -1); while (vlen--) *bp-- = *tp--; #endif #if BYTE_ORDER == LITTLE_ENDIAN *bp++ = (u_char) vlen; /* length */ while (vlen--) *bp++ = *tp--; #endif; DEBUG_MSG1("asnEncodeInt OK"); return (snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeOctString: Decode ASN octect string. ** ** DESCRIPTION: ** Decode ASN Octect String. Copies the string to a given buffer. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN octect string(input). ** u_char *stringp = pointer to buffer receiving the string(output). ** short *vlen = length of string in bytes (output). ** short *bUse = Bytes used while decoding (output). ** ** RETURNS: ** snmpErrorNone: No error . ** snmpErrorBadValue: if tag is not ASN ostect string. ** SNMPErrorTooBig: if string is too big ( > MAX_OBJ_LEN). ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 174. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeOctString(bp,stringp,len,bUse) u_char *bp; u_char *stringp; short *len; short *bUse; { short i; /* temp. loop counter */ SnmpErrorType error; /* temp. error status */ DEBUG_MSG2("asnDecodeOctString bp=%p",bp); /* check if tag is ASN octect string */ if (*bp++ != (Asn_Primitive | Asn_Universal | Asn_Octect)) { return(snmpErrorBadValue); } /* compute length field */ if ((error = decodeAsnLen(bp, len, bUse)) != snmpErrorNone) return(error); /* if string too big */ if (*len > MAX_OBJ_LEN) return(snmpErrorTooBig); bp = bp + *bUse; /* move bp to value field */ *bUse = 1 + *bUse + *len; /* total bytes used */ for (i=0; i<*len; i++) *stringp++ = *bp++; /* copy string */ DEBUG_MSG1("asnDecodeOctString OK "); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeOctString: Encode ASN octect string. ** ** DESCRIPTION: ** Encode a String into ASN Octect String. ** String length is limited to MAX_OBJ_LEN bytes. ** ** PARAMETERS: ** u_char *bp = pointer to buffer receiving ASN octect string. ** u_char *stringp = pointer to string (input). ** short vlen = length of string in bytes (input). ** short *bUse = length of ASN octect string (output). ** ** RETURNS: ** snmpErrorNone: No error . ** snmpErrorTooBig: if string is too big ( > MAX_OBJ_LEN). ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 174. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeOctString(bp,stringp,strLen,bUse) u_char *bp; u_char *stringp; short strLen; short *bUse; { short i; /* temp. loop counter */ DEBUG_MSG2("ansEncodingOctString bp=%p",bp); /* put tag */ *bp++ = (u_char)(Asn_Primitive | Asn_Universal | Asn_Octect); if (strLen > MAX_OBJ_LEN) return(snmpErrorTooBig); /* encode length */ (void) encodeAsnLen(bp, strLen, &i); bp = bp + i; /* check if ASN octect string is within limits */ if ( (*bUse = strLen + i + 1) > MAX_OBJ_ASN_LEN) return(snmpErrorTooBig); /* copy given string to ASN value field */ for (i=0; i< strLen; i++) *bp++ = *stringp++; DEBUG_MSG1("asnEncodeOctString OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeNull: Decode ASN Null type. ** ** DESCRIPTION: ** Decode ASN Null type. Null types are place holders for ASN ** objects with no value. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN Null type(input). ** short *bUse = Bytes used while decoding (output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not ASN null. ** snmpErrorTooBig: if object is too big ( > MAX_OBJ_LEN). ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 175. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeNull(bp,bUse) u_char *bp; short *bUse; { short len; /* length of value field */ SnmpErrorType error; DEBUG_MSG2("ansDecodeNull bp=%p",bp); /* check if tag is ASN null */ if (*bp++ != (Asn_Primitive | Asn_Universal | Asn_Null)) { return(snmpErrorBadValue); } /* compute length */ if ((error = decodeAsnLen(bp, &len, bUse)) != snmpErrorNone) return(error); /* if length too big */ if ( len > MAX_OBJ_LEN ) return(snmpErrorTooBig); *bUse = len + 2; /* total bytes in tag-length-value */ DEBUG_MSG1("asnDecodeNUll OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeNull: Encode ASN Null type. ** ** DESCRIPTION: ** Encode ASN Null type. Null types are place holders for ASN ** objects with no value. ** ** PARAMETERS: ** u_char *bp = Buffer for ASN null type. ** short *bUse = Length of ASN null type(output). ** ** RETURNS: ** snmpErrorNone: no error. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 175. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeNull(bp,bUse) u_char *bp; short *bUse; { /* tag is ASN null */ DEBUG_MSG2("ansEncodeNull bp=%p",bp); *bp++ = (Asn_Primitive | Asn_Universal | Asn_Null); /* length is zero */ *bp++ = (u_char) 0; *bUse = 2; DEBUG_MSG1("asnEncodeNull OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodOid: Decode ASN Object ID. ** ** DESCRIPTION: ** Input is ASN Object ID. Copies the decoded OID into oid array. ** ELements of oid array are defined by OidEleType. If OidEleType ** is u_char type then each OID digit has a range of 0..255. ** Similarly is OidEleType Unsigned short then range is 0..2^32. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN OID(input). ** OidEleType *oid = pointer to buffer receiving decoded OID. ** short *oidLen = length of oid array (output). ** short *bUse = Bytes used while decoding (output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not ASN Oid. ** snmpErrorTooBig: ** if oid in ASN form is too big > MAX_OID_ASN_LEN. ** if oid array is too big > MAX_OID_LEN. ** if each oid digit exceeds the range of OidEleType. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 175-176. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeOid(bp, oid, oidLen, bUse) u_char *bp; OidEleType *oid; short *oidLen; short *bUse; { short len; /* length of ASN value field */ short lbuse; /* temp counter for bytes used*/ unsigned long val; /* keeps one OID digit */ SnmpErrorType error; /* temp. error */ OidEleType val2; /* tmp oid */ DEBUG_MSG2("ansDecodeOid bp=%p",bp); /* ckeck tag if type oid */ if (*bp++ != (Asn_Primitive | Asn_Universal | Asn_Oid )){ return(snmpErrorBadValue); } /* determine length */ if (( error = decodeAsnLen(bp,&len,&lbuse)) != snmpErrorNone) return(error); bp += lbuse; /* move bp to value field */ /* length = length of tag + length + value fields */ if ((*bUse = 1 + lbuse + len) > MAX_OID_ASN_LEN) return(snmpErrorTooBig); /* now decode the oid */ *oidLen = 0; while (len > 0){ val = 0; /* add-and-shift value as long as MSB=1 */ while ( *bp & 0x80 ){ val = val + (unsigned long)( *bp++ & 0x7F); val = val << 7; len--; } /* add the last byte */ val = val + (unsigned long) *bp++; len--; *oidLen = *oidLen + 1; /* increment OID length */ if (*oidLen > MAX_OID_LEN) return(snmpErrorTooBig); /* check if val is within range of OidEleType */ if ( val <= MAX_OID_VAL) { val2 = val; bcopy(&val2, oid, sizeof(OidEleType)); oid ++; } else return(snmpErrorTooBig); } /* all bytes from the length field should be used */ if (len != 0) return(snmpErrorBadValue); DEBUG_MSG1("ansDecodeOid OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodOid: Encode ASN Object ID. ** ** DESCRIPTION: ** Input is Object ID. Copies the ASN encoded OID into buffer bp. ** ELements of oid array are defined by OidEleType. If OidEleType ** is u_char type then each OID digit has a range of 0..255. ** Similarly is OidEleType unsigned short then range is 0..2^32. ** Note: OID's using more than 127 bytes are not supported. ** ** PARAMETERS: ** u_char *bp = Pointer to buffer receiving ASN OID. ** OidEleType *oid = pointer to array containing OID(input). ** short oidLen = length of the oid array (input). ** short *bUse = length of ASN encoded OID (output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorTooBig: ** if input oid array is too big > MAX_OID_LEN. ** if encoded oid in ASN form is too big > MAX_OID_ASN_LEN. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 175-176. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeOid(bp,oid,oidlen,bUse) u_char *bp; OidEleType *oid; short oidlen; short *bUse; { short i,j; /* temp loop counter */ short len; /* length of bp used */ short nbytes; /* bytes for one OID element */ unsigned long val; /* copy of one OID element */ u_char tempb[5]; /* temp. buffer */ u_char *tp; /* temp. pointer */ unsigned long mask; /* mask for taking 7 bits */ DEBUG_MSG2("asnEncodingOid bp=%p",bp); /* check oidLen */ #ifdef SNMP_DEBUG fprintf(stderr, "%d\n", oidlen); fprintf(stderr, "%d\n", *bUse); #endif if (oidlen > MAX_OID_LEN) return(snmpErrorTooBig); /* put tag = ASN Oid. */ *bp++ = (u_char) ( Asn_Primitive | Asn_Universal | Asn_Oid); tp = bp++; /* save bp. compute length later */ len = 2; /* 2 bytes so far */ /* now encode the ID from oid array */ for (i = oidlen; i>0; i--){ /* do all OID elements */ val = (unsigned long) *oid++; /* usually val < 128. simply put it as a byte */ if (val < 128){ /* if output buffer is full */ if (++len > MAX_OID_ASN_LEN) return (snmpErrorTooBig); *bp++ = (u_char) val; }else{ /* if val is >= 128 */ mask = 0x0000007FL; /* mask for testing 7 bits */ /* compute number of bytes needed. 7 bits/byte used*/ for (j=1; j<6; j++){ if ((val & mask) != 0) nbytes = j; mask = mask << 7; } mask = 0x0000007FL; for (j=0; j> 7; } /* copy tempb in network byte order. reverse */ for (j =nbytes; j>0; j--){ if (++len > MAX_OID_ASN_LEN) /*if buffer full */ return (snmpErrorTooBig); *bp++ = tempb[j-1]; } /* set MSB = 0 indicating last byte */ bp--; *bp = *bp & (u_char) 0x7F; bp++; } } *bUse = len; /* total length of ASN encoded OID */ if (len > 127) { /* oid larger than 127 bytes not supported */ return(snmpErrorTooBig); } else { *tp = (u_char) (len -2); } DEBUG_MSG1("ansEncodeOid OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeSeq: Decode ASN Sequence. ** ** DESCRIPTION: ** Decode Tag and length fields only. ** Check if the tag ASN Sequence and return the length of ** the sequence. Also return the bytes used while decoding. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN Sequence(input). ** short *len = Length of the sequence(output). ** short *bUse = Bytes used while decoding (output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not ASN Sequence. ** snmpErrorTooBig: ** if Sequence if too big > MAX_SEQ_LEN. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 177. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeSeq(bp,len,bUse) u_char *bp; short *len; short *bUse; { SnmpErrorType error; DEBUG_MSG2("ansDecodeSeq bp=%p",bp); /* check if tag is sequence */ if (*bp++ != (u_char) (Asn_Constructor | Asn_Universal | Asn_Sequence )){ return(snmpErrorBadValue); } /* compute length of the sequence */ if (( error = decodeAsnLen(bp, len, bUse)) != snmpErrorNone) return(error); if ( *len > MAX_SEQ_LEN) return(snmpErrorTooBig); *bUse = *bUse + 1; /* bytes used */ DEBUG_MSG1("asnDecodeSeq OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeSeq: Encode ASN Sequence. ** ** DESCRIPTION: ** Encode Tag and length fields only. ** ** PARAMETERS: ** u_char *bp = Buffer receiving ASN Sequence. ** short len = Length of the sequence (input). ** short *bUse = Bytes used (output). ** ** RETURNS: ** snmpErrorNone: no error. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 177. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeSeq(bp,len,bUse) u_char *bp; short len; short *bUse; { SnmpErrorType error; DEBUG_MSG2("asnEncodeSeq bp=%p",bp); /* tag is sequence */ *bp++ = (u_char) (Asn_Constructor | Asn_Universal | Asn_Sequence ); /* encode length of the sequence */ if (( error = encodeAsnLen(bp, len, bUse)) != snmpErrorNone) return(error); *bUse = *bUse + 1; /* bytes used */ DEBUG_MSG1("asnEncodeSeq OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeSmpIpAddr: Decode IP Address. ** ** DESCRIPTION: ** Decode SNMP IP Address. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN SNMP IP Address(input). ** u_char *IpAdd = lP Address(output). ** short *bUse = Bytes used while decoding (output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not SNMP IP Address. ** if exactly 4 bytes are not in the value field. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 177. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeSmpIpAddr(bp,ipAddr,bUse) u_char *bp; u_char *ipAddr; short *bUse; { short i; /* temp. loop counter */ DEBUG_MSG2("asnDecodeIpAdd bp=%p",bp); /* check tag */ if (*bp++ != (u_char)( Asn_Primitive | Asn_Application | Smp_IpAddr)) return(snmpErrorBadValue); /* length should be 4 for IP address */ if (*bp++ != 4) return(snmpErrorBadValue); for (i=0; i < 4; i++) *ipAddr++ = *bp++; *bUse = 6; DEBUG_MSG1("asnDecodeIpAdd OK "); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeSmpIpAddr: Encode IP Address. ** ** DESCRIPTION: ** Encode SNMP IP Address. IP Address is encoded as ** tag = SNMP IP, length = 4 and the 4 bytes for IP. ** ** PARAMETERS: ** u_char *bp = Bufer receiving encoded IP Address. ** long *IpAdd = lP Address (input). ** short *bUse = length of encoded IP address (output). ** ** RETURNS: ** snmpErrorNone: no error. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page ??. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeSmpIpAddr(bp,ipAddr,bUse) u_char *bp; u_char *ipAddr; short *bUse; { short i; /* temp. loop counter */ DEBUG_MSG2("asnEncodeIpAdd bp=%p",bp); /* put tag = SNMP IP Address */ *bp++ = ( Asn_Primitive | Asn_Application | Smp_IpAddr); /* length is 4 for IP address */ *bp++ = 4; for (i=0; i < 4; i++) *bp++ = *ipAddr++; *bUse = 6; DEBUG_MSG1("asnEncodeIpAdd OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** decodeLenPosVal: Decoded Length and Value fields. ** ** DESCRIPTION: ** decodes a psitive number from length and value field. **------------------------------------------------------------------*/ SnmpErrorType decodePosVal(bp,vlen,value,bUse) u_char *bp; short vlen; u_char *value; short *bUse; { short j; short len; len = *bp++; *bUse = len + 1; /* discard if there are zeros in the value*/ while ((len > 0) && (*bp == 0)){ len--; bp++; } /* if value exceeds the allowd length */ if (len > vlen) return(snmpErrorTooBig); /* set value = 0 */ #if BYTE_ORDER == LITTLE_ENDIAN for (j=0; j < vlen; j++) *value++ = (u_char) 0; /* move value pointer to the first MSB */ for (j=0; j < (vlen - len); j++) --value; /* copy value first MSB then LSB */ for (j=len; j>0; j--) *(--value) = *bp++; #endif /* LITTLE_ENDIAN */ #if BYTE_ORDER == BIG_ENDIAN /* set value = 0 */ for (j=0; j < vlen; j++) *(value+j) = (u_char) 0; /* move pointer past high bits we aren't going to use (zero'd above) */ for (j=0; j < (vlen - len); j++) ++value; /* copy in */ for (j=len; j>0; j--) *(value++) = *bp++; #endif /* BIG_ENDIAN */ return(snmpErrorNone); } /*-------------------------------------------------------------------- ** EncodeLenPosVal: Encoded Length and Value fields. ** ** DESCRIPTION: ** Encodes a psitive number into length and value fields. **------------------------------------------------------------------*/ SnmpErrorType encodePosVal(bp,vlen,value,bUse) u_char *bp; short vlen; u_char *value; short *bUse; { u_char *tp; tp = value + vlen - 1; while ((*tp == (u_char) 0) && (vlen > 1)) { tp--; vlen--; } if (*tp & 0x80) { *bp++ = (u_char) (++vlen); *bp++ = 0; *bUse = vlen + 1; vlen--; for ( ;vlen > 0; vlen--) *bp++ = *tp--; } else { *bp++ =(u_char) vlen; *bUse = vlen + 1; for ( ; vlen > 0;vlen--) *bp++ = *tp--; } return (snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeSmpCount: Decode SNMP Counter. ** ** DESCRIPTION: ** SNMP counter is encoded same as integer except tag=4 and the ** value is always positive. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN SNMP Counter(input). ** short vtype = value type(input). ** = PC_Counter2: decoded as unsigned. ** = PC_Counter4: decoded as unsigned long. ** = PC_Counter6: decoded as 6 byte counter. ** UncChar *value = Decoded counter value (output). ** short *bUse = Bytes used while decoding (output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not SNMP Counter. ** snmpErrorTooBig: if value is too large. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page ??. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeSmpCount(bp,vtype,value,bUse) u_char *bp; PCTypes *vtype; u_char *value; short *bUse; { short vlen; SnmpErrorType error; DEBUG_MSG2("asnDecodeSmpCount bp=%p", bp); /* check if tag = SNMP counter */ if (*bp++ != (u_char) (Asn_Primitive | Smp_Counter )) { return(snmpErrorBadValue); } /* set counter size */ switch (*vtype){ case PC_Counter2: vlen = 2; break; case PC_Counter4: vlen = 4; break; case PC_Counter6: vlen = 6; break; default: *vtype = PC_Counter4; vlen = 4; } if ((error = decodePosVal(bp,vlen,value,bUse)) != snmpErrorNone){ return(error); } *bUse = *bUse + 1; DEBUG_MSG1("asnDecodeSmpCount OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeSmpCount: Encode SNMP Counter. ** ** DESCRIPTION: ** SNMP counter is encoded same as integer except tag=4 and the ** value is always positive. ** ** PARAMETERS: ** u_char *bp = buffer receiving encoded Counter. ** short vtype = value is of type(input). ** = PC_Counter2: unsigned. ** = PC_Counter4: unsigned long. ** = PC_Counter6: 6 byte counter. ** UncChar *value = counter value (input). ** short *bUse = Length of ASN encoded counter (output). ** ** RETURNS: ** snmpErrorNone: no error. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page ??. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeSmpCount(bp,vtype,value,bUse) u_char *bp; PCTypes vtype; u_char *value; short *bUse; { SnmpErrorType error; short vlen; /* value size in bytes */ DEBUG_MSG2("asnEncodeSmpCount bp=%p", bp); /* determine value size */ switch (vtype) { case PC_Counter2: vlen = 2; break; case PC_Counter4: vlen = 4; break; case PC_Counter6: vlen = 6; break; default: return(snmpErrorBadValue); } *bp++ = (u_char)( Asn_Primitive | Asn_Application | Smp_Counter); if ((error = encodePosVal(bp, vlen, value,bUse)) != snmpErrorNone) return(error); *bUse = *bUse + 1; DEBUG_MSG1("asnEncodeSmpCount OK"); return (snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeSmpGuage: Decode SNMP Guage. ** ** DESCRIPTION: ** SNMP guage is encoded same as integer except tag is differnet ** and value is always positive. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN SNMP Guage(input). ** UncChar *value = Decoded Guage value (output). ** short *bUse = Bytes used while decoding (output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not SNMP Guage. ** snmpErrorTooBig: if value exceeds range of long. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page ??. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeSmpGuage(bp,value,bUse) u_char *bp; u_char *value; short *bUse; { SnmpErrorType error; DEBUG_MSG2("asnDecodeSmpGuage bp=%p", bp); /* check tag */ if (*bp++ != (u_char) (Asn_Primitive | Smp_Guage )) return(snmpErrorBadValue); if ((error = decodePosVal(bp,4,value,bUse))!= snmpErrorNone) return(error); *bUse = *bUse + 1; /* bytes used */ DEBUG_MSG1("asnDecodeSmpGuage OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeSmpGuage: Encode SNMP Guage. ** ** DESCRIPTION: ** SNMP guage is encoded same as integer except tag is different ** and the value is always positive. ** ** PARAMETERS: ** u_char *bp = buffer receiving encoded Guage. ** UncChar *value = Guage value (input). ** short *bUse = Length of ASN encoded guage (output). ** ** RETURNS: ** snmpErrorNone: no error. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 177. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeSmpGuage(bp,value,bUse) u_char *bp; u_char *value; short *bUse; { SnmpErrorType error; *bp++ = (u_char)( Asn_Primitive | Asn_Application | Smp_Guage); if ((error = encodePosVal(bp, 4 , value,bUse)) != snmpErrorNone) return(error); *bUse = *bUse + 1; DEBUG_MSG1("asnEncodingGuage OK"); return (snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeSmpTicks: Decode SNMP Ticks. ** ** DESCRIPTION: ** SNMP Ticks is encoded same as integer except tag is differnet ** and the value is always positive. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN SNMP Ticks(input). ** UncChar *value = Decoded Ticks value (output). ** short *bUse = Bytes used while decoding (output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not SNMP Ticks. ** snmpErrorTooBig: if value exceeds range of long. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 177. **------------------------------------------------------------------*/ SnmpErrorType asnDecodeSmpTicks(bp,value,bUse) u_char *bp; u_char *value; short *bUse; { SnmpErrorType error; /* ckeck tag */ if (*bp++ != (u_char) (Asn_Primitive | Smp_Ticks )) { return(snmpErrorBadValue); } if ((error = decodePosVal(bp,4,value,bUse))!= snmpErrorNone) return(error); *bUse = *bUse + 1; /* bytes used */ DEBUG_MSG1("asnDecodeTicks OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeSmpTicks: Encode SNMP Ticks. ** ** DESCRIPTION: ** SNMP Ticks is encoded same as integer except tag is different ** and the value is always positive. ** ** PARAMETERS: ** u_char *bp = buffer receiving encoded Ticks. ** UncChar *value = Ticks value (input). ** short *bUse = Length of ASN encoded ticks (output). ** ** RETURNS: ** snmpErrorNone: no error. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 177. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeSmpTicks(bp,value,bUse) u_char *bp; u_char *value; short *bUse; { SnmpErrorType error; *bp++ = (u_char)( Asn_Primitive | Asn_Application | Smp_Ticks); if ((error = encodePosVal(bp, 4, value,bUse)) != snmpErrorNone) return(error); *bUse = *bUse + 1; DEBUG_MSG1("asnEncodingTicks OK"); return (snmpErrorNone); } /*-------------------------------------------------------------------- ** Decode SNMP command (or request). ** command is encoded as ** | tag = command | length | ** length is the total number of remaining bytes in the packet. ** Strickly speaking length represent the nember of bytes in this ** command. but if each packet contains only one command the length ** is alose equal to bytes in the packet. ** In this implementation only one command per packect is supported. ** ** bp = pointer to command in Asn form (input). ** command = command, either get, next, get response, ** set or trap (output). ** len = number of in the command (output). ** bUse = bytes used for tag and length filed, **------------------------------------------------------------------*/ SnmpErrorType asnDecodeCommand(bp,command,len,bUse) u_char *bp; SnmpRequestType *command; short *len; short *bUse; { SnmpErrorType error; /* check if tag has proper high bytes */ if ((*bp & 0xE0) != (u_char)( Asn_Context | Asn_Constructor)) return(snmpErrorBadValue); /* five LSB's are the command */ *command = (SnmpRequestType) *bp++ & 0x1F; if (( error = decodeAsnLen(bp, len, bUse)) != snmpErrorNone) return(error); *bUse = *bUse + 1; /* bytes used */ DEBUG_MSG1("asnDecodeCommand OK"); return(snmpErrorNone); } SnmpErrorType asnEncodeCommand(bp,command,len,bUse) u_char *bp; SnmpRequestType command; short len; short *bUse; { u_char tempc; SnmpErrorType error; /* put tag */ switch (command){ case snmpGetRequest: tempc = 0xA0; break; case snmpNextRequest: tempc = 0xA1; break; case snmpGetResponse: tempc = 0xA2; break; case snmpSetRequest: tempc = 0xA3; break; case snmpTrap: tempc = 0xA4; break; default: return(snmpErrorBadValue); } *bp++ = tempc | (u_char)( Asn_Context | Asn_Constructor); if (( error = encodeAsnLen(bp, len, bUse)) != snmpErrorNone) return(error); *bUse = *bUse + 1; /* bytes used */ DEBUG_MSG1("asnEncodeCommand OK"); return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnDecodeAny: Decode Any Asn Type. ** ** DESCRIPTION: ** Decode any ASN object types (limited types are impleted). ** Returns type of object, value, length of value in bytes. ** ** PARAMETERS: ** u_char *bp = Pointer to ASN encoded value(input). ** UncChar *value = buffer receiving value (output). ** PC_Types *type = type of value (output). ** short *len = length of value in bytes (output). ** short *bUse = Bytes used while decoding (output). *** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not SNMP simple type.. ** snmpErrorTooBig: if value exceeds range of long. ** **------------------------------------------------------------------*/ SnmpErrorType asnDecodeAny(bp, val, type, len, buse) u_char *bp; u_char *val; PCTypes *type; short *len; short *buse; { short lbuse; AsnVarType class; SnmpErrorType error; lbuse = *buse; class = (AsnVarType) *bp; /* get tag */ /* should be simple type not constructor type */ if (class & Asn_Constructor) return(snmpErrorBadValue); switch (class & 0x7F){ case Asn_Integer: /**** ASN Integer Type ***/ if ((error = asnDecodeInt(bp, (long *) val, &lbuse)) != snmpErrorNone) return(error); *type = PC_Integer4; *len = sizeof(long); break; case Asn_Octect: /***** ASN octect string ****/ if ((error = asnDecodeOctString(bp, val, len ,&lbuse)) != 0) return(error); *type = PC_OctectString; break; case Asn_Null: if ((error = asnDecodeNull(bp,&lbuse)) != 0) return(error); *type = PC_Null; *val = (u_char) 0; *len = 0; break; case Asn_Oid: if ((error = asnDecodeOid(bp,(OidEleType *)val,len,&lbuse)) != 0) return(error); *type = PC_Oid; break; case Smp_IpAddr: if ((error = asnDecodeSmpIpAddr(bp,val, &lbuse)) != 0) return(error); *len = 4; *type = PC_IpAddr; break; case Smp_Guage: if ((error = asnDecodeSmpGuage(bp,val,&lbuse)) != 0) return(error); *len = 4; /*length is 4 */ *type = PC_Guage; break; case Smp_Ticks: if ((error = asnDecodeSmpTicks(bp,val,&lbuse)) != 0) return(error); *len = 4; /* length is 4 */ *type = PC_Ticks; break; case Smp_Counter: if ((error = asnDecodeSmpCount(bp,type,val,&lbuse)) != 0) return(error); switch(*type) { case PC_Counter2: *len = 2; break; case PC_Counter4: *len = 4; break; case PC_Counter6: *len = 6; break; } break; case Smp_Opaque: default: return(snmpErrorBadValue); } *buse = lbuse; return(snmpErrorNone); } /*-------------------------------------------------------------------- ** asnEncodeAny: Encode Any Asn Type. ** ** DESCRIPTION: ** Encode any ASN object types (limited types are impleted). ** Given type of object, value and length of value in bytes. ** ** PARAMETERS: ** u_char *bp = buffer for ASN encoded value. ** UncChar *value = value (input). ** PC_Types type = type of value (input). ** short len = length of value in bytes (input). ** short *bUse = length of ASN encoded value(output). ** ** RETURNS: ** snmpErrorNone: no error. ** snmpErrorBadValue: if tag is not SNMP simple type.. ** snmpErrorTooBig: if value exceeds range of long. ** ** REFERENCE: ** See Appendix B Dowty SNMP notebook page 177. **------------------------------------------------------------------*/ SnmpErrorType asnEncodeAny(bp, val, type, len, buse) u_char *bp; u_char *val; PCTypes type; short len; short *buse; { SnmpErrorType error; #ifdef SNMP_XDEBUG fprintf(stderr, "type == %d\n", (int)type); #endif /* SNMP_XDEBUG */ switch (type) { case PC_Null: #ifdef SNMP_XDEBUG fprintf(stderr, "at encode NULL\n"); #endif /* SNMP_XDEBUG */ if ((error = asnEncodeNull(bp,buse)) != snmpErrorNone) return(error); break; case PC_Integer4: if ((error = asnEncodeInt(bp,*((long *)val),buse)) != snmpErrorNone) return(error); break; case PC_Counter2: case PC_Counter4: case PC_Counter6: if ((error = asnEncodeSmpCount(bp,type,val,buse)) != snmpErrorNone) return(error); break; case PC_OctectString: if ((error = asnEncodeOctString(bp, val, len, buse)) != snmpErrorNone) return(error); break; case PC_Oid: if ((error=asnEncodeOid(bp,(OidEleType *)val, len/sizeof(OidEleType),buse)) != snmpErrorNone) return(error); break; case PC_Ticks: if ((error = asnEncodeSmpTicks(bp, val, buse)) != snmpErrorNone) return(error); break; case PC_Guage: if ((error = asnEncodeSmpGuage(bp, val, buse)) != snmpErrorNone) return(error); break; case PC_IpAddr: if ((error = asnEncodeSmpIpAddr(bp, val, buse)) != snmpErrorNone) return(error); break; default: return(snmpErrorBadValue); } /* switch */ return (snmpErrorNone); } /* asnEncodeAny */ /*----------------------- END OSUASN.C -------------------------------*/