osmith has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/28237 )
Change subject: tlv_parser: add tlv_parse_order ......................................................................
tlv_parser: add tlv_parse_order
Add a function to retrieve the TLV order of an existing message, so a new message with the same order can be generated. I'm using this in osmo-bsc-nat I3caa15666f2dde9ee02182a89edc5daa70e8c3fc.
Related: SYS#5560 Change-Id: I3caa15666f2dde9ee02182a89edc5daa70e8c3fc --- M include/osmocom/gsm/tlv.h M src/gsm/libosmogsm.map M src/gsm/tlv_parser.c M tests/tlv/tlv_test.c M tests/tlv/tlv_test.ok 5 files changed, 52 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/37/28237/1
diff --git a/include/osmocom/gsm/tlv.h b/include/osmocom/gsm/tlv.h index 7e6dfb5..4c638eb 100644 --- a/include/osmocom/gsm/tlv.h +++ b/include/osmocom/gsm/tlv.h @@ -534,6 +534,8 @@ int tlv_parse2(struct tlv_parsed *dec, int dec_multiples, const struct tlv_definition *def, const uint8_t *buf, int buf_len, uint8_t lv_tag, uint8_t lv_tag2); +int tlv_parse_order(uint8_t *tag_order, unsigned int tag_order_len, + const struct tlv_definition *def, const uint8_t *buf, int buf_len); /* take a master (src) tlv def and fill up all empty slots in 'dst' */ void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src);
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index b971ca0..7bdb930 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -592,6 +592,7 @@ tlv_dump; tlv_parse; tlv_parse2; +tlv_parse_order; tlv_parse_one; tlv_encode; tlv_encode_ordered; diff --git a/src/gsm/tlv_parser.c b/src/gsm/tlv_parser.c index c5aac97..8c188c5 100644 --- a/src/gsm/tlv_parser.c +++ b/src/gsm/tlv_parser.c @@ -433,6 +433,42 @@ return num_parsed; }
+/*! Parse the order of tags used in a buffer of TLV encoded IEs. + * \param[out] tag_order array of tags determining the IE encoding order + * \param[in] tag_order_len length of tag_order + * \param[in] def structure defining the valid TLV tags / configurations + * \param[in] buf the input data buffer to be parsed + * \param[in] buf_len length of the input data buffer + * \returns number of TLV entries parsed; negative in case of error + */ +int tlv_parse_order(uint8_t *tag_order, unsigned int tag_order_len, const struct tlv_definition *def, + const uint8_t *buf, int buf_len) +{ + int ofs = 0; + int num_parsed = 0; + + while (ofs < buf_len) { + int rv; + uint8_t tag; + const uint8_t *val; + uint16_t len; + + rv = tlv_parse_one(&tag, &len, &val, def, &buf[ofs], buf_len - ofs); + if (rv < 0) + return rv; + + if (num_parsed >= tag_order_len) + return -1; + + tag_order[num_parsed] = tag; + + ofs += rv; + num_parsed++; + } + + return num_parsed; +} + /*! take a master (src) tlv_definition and fill up all empty slots in 'dst' * \param dst TLV parser definition that is to be patched * \param[in] src TLV parser definition whose content is patched into \a dst */ diff --git a/tests/tlv/tlv_test.c b/tests/tlv/tlv_test.c index fdd15ab..84e115b 100644 --- a/tests/tlv/tlv_test.c +++ b/tests/tlv/tlv_test.c @@ -297,6 +297,7 @@ 0x40, 0x42, }; const uint8_t ie_order[] = { 0x2c, 0x40, 0x17 }; + uint8_t ie_order_dec[3]; const uint8_t enc_ies_reordered[] = { 0x2c, 0x04, 0x40, 0x42, @@ -329,6 +330,17 @@ OSMO_ASSERT(rc == ARRAY_SIZE(enc_ies)); OSMO_ASSERT(!memcmp(msgb_data(msg), enc_ies_reordered, ARRAY_SIZE(enc_ies_reordered)));
+ printf("Testing TLV IE order parsing\n"); + + /* parse order: array too short */ + rc = tlv_parse_order(ie_order_dec, 2, gsm0808_att_tlvdef(), enc_ies_reordered, ARRAY_SIZE(enc_ies)); + OSMO_ASSERT(rc == -1); + + /* parse order */ + rc = tlv_parse_order(ie_order_dec, ARRAY_SIZE(ie_order_dec), gsm0808_att_tlvdef(), enc_ies_reordered, ARRAY_SIZE(enc_ies)); + OSMO_ASSERT(rc == 3); + OSMO_ASSERT(!memcmp(ie_order_dec, ie_order, ARRAY_SIZE(ie_order))); + msgb_free(msg); }
diff --git a/tests/tlv/tlv_test.ok b/tests/tlv/tlv_test.ok index e24b889..ed96339 100644 --- a/tests/tlv/tlv_test.ok +++ b/tests/tlv/tlv_test.ok @@ -1,6 +1,7 @@ Test shift functions Testing TLV encoder by decoding + re-encoding binary Testing TLV encoder with IE ordering +Testing TLV IE order parsing Testing TLV_TYPE_T decoder for out-of-bounds Testing TLV_TYPE_TV decoder for out-of-bounds Testing TLV_TYPE_FIXED decoder for out-of-bounds