diff --git a/src/apps/snmp/snmp_asn1.c b/src/apps/snmp/snmp_asn1.c index 92c1188d..81a2554f 100644 --- a/src/apps/snmp/snmp_asn1.c +++ b/src/apps/snmp/snmp_asn1.c @@ -169,48 +169,6 @@ snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u3 return ERR_OK; } - -/** - * Encodes u64_t (counter64) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) - * @param value is the host order u32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_u64t_cnt() - */ -err_t -snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value) -{ - if (octets_needed > 9) { - return ERR_ARG; - } - if (octets_needed == 9) { - /* not enough bits in 'value' add leading 0x00 */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); - octets_needed--; - } - - while (octets_needed > 4) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3)))); - } - - /* skip to low u32 */ - value++; - - while (octets_needed > 1) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3)))); - } - - /* always write at least one octet (also in case of value == 0) */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value))); - - return ERR_OK; -} - /** * Encodes s32_t integer into a pbuf chained ASN1 msg. * @@ -329,31 +287,6 @@ snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) } } -/** - * Returns octet count for an u64_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -void -snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed) -{ - /* check if high u32 is 0 */ - if (*value == 0x00) { - /* only low u32 is important */ - value++; - snmp_asn1_enc_u32t_cnt(*value, octets_needed); - } else { - /* low u32 does not matter for length determination */ - snmp_asn1_enc_u32t_cnt(*value, octets_needed); - *octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */ - } -} - /** * Returns octet count for an s32_t. * @@ -512,60 +445,6 @@ snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value return ERR_VAL; } -/** - * Decodes large positive integer (counter64) into 2x u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -err_t -snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) -{ - u8_t data; - - if (len <= 4) { - /* high u32 is 0 */ - *value = 0; - /* directly skip to low u32 */ - value++; - } - - if ((len > 0) && (len <= 9)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - /* expecting sign bit to be zero, only unsigned please! */ - if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) { - *value = data; - len--; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - if (len == 4) { - /* skip to low u32 */ - value++; - *value = 0; - } else { - *value <<= 8; - } - - *value |= data; - len--; - } - - return ERR_OK; - } - } - - return ERR_VAL; -} - /** * Decodes integer into s32_t. * @@ -723,4 +602,126 @@ snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u1 return ERR_OK; } +#if LWIP_HAVE_INT64 +/** + * Returns octet count for an u64_t. + * + * @param value value to be encoded + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed) +{ + /* check if high u32 is 0 */ + if (*value == 0x00) { + /* only low u32 is important */ + value++; + snmp_asn1_enc_u32t_cnt(*value, octets_needed); + } else { + /* low u32 does not matter for length determination */ + snmp_asn1_enc_u32t_cnt(*value, octets_needed); + *octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */ + } +} + +/** + * Decodes large positive integer (counter64) into 2x u32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) +{ + u8_t data; + + if (len <= 4) { + /* high u32 is 0 */ + *value = 0; + /* directly skip to low u32 */ + value++; + } + + if ((len > 0) && (len <= 9)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + /* expecting sign bit to be zero, only unsigned please! */ + if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) { + *value = data; + len--; + + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + if (len == 4) { + /* skip to low u32 */ + value++; + *value = 0; + } else { + *value <<= 8; + } + + *value |= data; + len--; + } + + return ERR_OK; + } + } + + return ERR_VAL; +} + +/** + * Encodes u64_t (counter64) into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u64t_cnt() + */ +err_t +snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value) +{ + if (octets_needed > 9) { + return ERR_ARG; + } + if (octets_needed == 9) { + /* not enough bits in 'value' add leading 0x00 */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); + octets_needed--; + } + + while (octets_needed > 4) { + octets_needed--; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3)))); + } + + /* skip to low u32 */ + value++; + + while (octets_needed > 1) { + octets_needed--; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3)))); + } + + /* always write at least one octet (also in case of value == 0) */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value))); + + return ERR_OK; +} +#endif + #endif /* LWIP_SNMP */ diff --git a/src/apps/snmp/snmp_asn1.h b/src/apps/snmp/snmp_asn1.h index 8520e31f..f57e239b 100644 --- a/src/apps/snmp/snmp_asn1.h +++ b/src/apps/snmp/snmp_asn1.h @@ -84,7 +84,6 @@ struct snmp_asn1_tlv err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); -err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value); err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len); err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len); @@ -93,15 +92,19 @@ err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_t void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); -void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed); void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed); err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len); err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value); err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value); -err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value); err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len); +#if LWIP_HAVE_INT64 +err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); +void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed); +err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value); +#endif + #ifdef __cplusplus } #endif