diff --git a/src/core/snmp/asn1_dec.c b/src/core/snmp/asn1_dec.c index 39b70bcd..f87f578e 100644 --- a/src/core/snmp/asn1_dec.c +++ b/src/core/snmp/asn1_dec.c @@ -654,4 +654,51 @@ snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw } } +/** + * Decodes BITS pseudotype value from ASN.1 OctetString. + * + * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly + * be encoded/decoded by the agent. Instead call this function as required from + * get/test/set methods. + * + * @param buf points to a buffer holding the ASN1 octet string + * @param buf_len length of octet string + * @param bit_value decoded Bit value with Bit0 == LSB + * @return ERR_OK if successful, ERR_ARG if bit value contains more than 32 bit + */ +err_t +snmp_asn1_dec_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value) +{ + u8_t b; + u8_t bits_processed = 0; + *bit_value = 0; + + while (buf_len > 0) { + /* any bit set in this byte? */ + if (*buf != 0x00) { + if (bits_processed >= 32) { + /* accept more than 4 bytes, but only when no bits are set */ + return ERR_ARG; + } + + b = *buf; + do { + if (b & 0x80) { + *bit_value |= (1 << bits_processed); + } + bits_processed++; + b <<= 1; + } + while ((bits_processed % 8) != 0); + } else { + bits_processed += 8; + } + + buf_len--; + buf++; + } + + return ERR_OK; +} + #endif /* LWIP_SNMP */ diff --git a/src/core/snmp/asn1_enc.c b/src/core/snmp/asn1_enc.c index e8ffaf2f..aa5e8aee 100644 --- a/src/core/snmp/asn1_enc.c +++ b/src/core/snmp/asn1_enc.c @@ -608,4 +608,44 @@ snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, const u8_t *raw) return ERR_ARG; } +/** + * Encodes BITS pseudotype value into ASN.1 OctetString. + * + * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly + * be encoded/decoded by the agent. Instead call this function as required from + * get/test/set methods. + * + * @param buf points to a buffer where the resulting ASN1 octet string is stored to + * @param buf_len max length of the bufffer + * @param bit_value Bit value to encode with Bit0 == LSB + * @return number of bytes used from buffer to store the resulting OctetString + */ +u8_t +snmp_asn1_enc_bits(u8_t *buf, u32_t buf_len, u32_t bit_value) +{ + int i = 0; + u8_t len = 0; + u8_t *buf_ptr = (u8_t *)buf; + + while ((buf_len > 0) && (bit_value != 0x00)) { + *buf_ptr = 0x00; + i = 8; + while (i > 0) { + if (bit_value & 0x01) { + *buf_ptr |= 0x01; + } + + bit_value >>= 1; + *buf_ptr <<= 1; + i--; + } + + buf_ptr++; + buf_len--; + len++; + } + + return len; +} + #endif /* LWIP_SNMP */ diff --git a/src/include/lwip/snmp_asn1.h b/src/include/lwip/snmp_asn1.h index 820d6f6e..6788866c 100644 --- a/src/include/lwip/snmp_asn1.h +++ b/src/include/lwip/snmp_asn1.h @@ -53,26 +53,27 @@ extern "C" { #define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */ #define SNMP_ASN1_PRIMIT (0) /* (!0x20) */ -/* universal tags */ +/* universal tags (from ASN.1 spec.) */ #define SNMP_ASN1_INTEG 2 #define SNMP_ASN1_OC_STR 4 #define SNMP_ASN1_NUL 5 #define SNMP_ASN1_OBJ_ID 6 #define SNMP_ASN1_SEQ 16 -/* application specific (SNMP) tags */ -#define SNMP_ASN1_IPADDR 0 /* octet string size(4) */ -#define SNMP_ASN1_COUNTER 1 /* u32_t */ -#define SNMP_ASN1_GAUGE 2 /* u32_t */ -#define SNMP_ASN1_TIMETICKS 3 /* u32_t */ -#define SNMP_ASN1_OPAQUE 4 /* octet string */ +/* application specific (SNMP) tags (from SNMPv2-SMI) */ +#define SNMP_ASN1_IPADDR 0 /* [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) */ +#define SNMP_ASN1_COUNTER 1 /* [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_GAUGE 2 /* [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_TIMETICKS 3 /* [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_OPAQUE 4 /* [APPLICATION 4] IMPLICIT OCTET STRING */ +#define SNMP_ASN1_COUNTER64 6 /* [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) */ -/* context specific (SNMP) tags */ -#define SNMP_ASN1_PDU_GET_REQ 0 +/* context specific (SNMP) tags (from SNMP spec. RFC1157) */ +#define SNMP_ASN1_PDU_GET_REQ 0 #define SNMP_ASN1_PDU_GET_NEXT_REQ 1 -#define SNMP_ASN1_PDU_GET_RESP 2 -#define SNMP_ASN1_PDU_SET_REQ 3 -#define SNMP_ASN1_PDU_TRAP 4 +#define SNMP_ASN1_PDU_GET_RESP 2 +#define SNMP_ASN1_PDU_SET_REQ 3 +#define SNMP_ASN1_PDU_TRAP 4 err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type); err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length); @@ -92,6 +93,9 @@ err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t v err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u16_t ident_len, const s32_t *ident); err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, const u8_t *raw); +err_t snmp_asn1_dec_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value); +u8_t snmp_asn1_enc_bits(u8_t *buf, u32_t buf_len, u32_t bit_value); + #ifdef __cplusplus } #endif