diff options
| author | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2015-06-02 15:52:06 +0200 | 
|---|---|---|
| committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2015-06-02 15:52:06 +0200 | 
| commit | f558ed4bb9c0f00997b8f97c2b251a574c1a64c4 (patch) | |
| tree | 16524d63b63a4c5496a9bc6412c3a9862367cc36 | |
| parent | 91ff17c9ef7dd4a29bb13d6b9995100ffc65b72a (diff) | |
ipa: Properly parse LV stream of a ID_GET request
For some reason the structure is closer to be a LV (length
and value). The value is actually a tag but it is counted
inside the length. Introduce an overload of the parse function
to provide an offset for the length. This will be taken from
the returned length.
| -rw-r--r-- | include/osmocom/gsm/ipa.h | 3 | ||||
| -rw-r--r-- | src/gsm/ipa.c | 16 | ||||
| -rw-r--r-- | tests/Makefile.am | 2 | ||||
| -rw-r--r-- | tests/utils/utils_test.c | 61 | 
4 files changed, 78 insertions, 4 deletions
| diff --git a/include/osmocom/gsm/ipa.h b/include/osmocom/gsm/ipa.h index 1227ee17..0bb01c59 100644 --- a/include/osmocom/gsm/ipa.h +++ b/include/osmocom/gsm/ipa.h @@ -27,6 +27,9 @@ const char *ipa_ccm_idtag_name(uint8_t tag);  /* parse a buffer of ID tags into a osmocom TLV style representation */  int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len); +/* Is the TAG included in the length field? */ +int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset); +  /* parse an Unit ID in string format into the 'ipaccess_unit' data structure */  int ipa_parse_unitid(const char *str, struct ipaccess_unit *unit_data); diff --git a/src/gsm/ipa.c b/src/gsm/ipa.c index 7cff1e81..dac20122 100644 --- a/src/gsm/ipa.c +++ b/src/gsm/ipa.c @@ -89,6 +89,11 @@ const char *ipa_ccm_idtag_name(uint8_t tag)  int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)  { +	return ipa_ccm_idtag_parse_off(dec, buf, len, 0); +} + +int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset) +{  	uint8_t t_len;  	uint8_t t_tag;  	uint8_t *cur = buf; @@ -100,6 +105,11 @@ int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)  		t_len = *cur++;  		t_tag = *cur++; +		if (t_len < len_offset) { +			LOGP(DLMI, LOGL_ERROR, "minimal offset not included: %d\n", t_len); +			return -EINVAL; +		} +  		if (t_len > len + 1) {  			LOGP(DLMI, LOGL_ERROR, "The tag does not fit: %d\n", t_len);  			return -EINVAL; @@ -107,11 +117,11 @@ int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)  		DEBUGPC(DLMI, "%s='%s' ", ipa_ccm_idtag_name(t_tag), cur); -		dec->lv[t_tag].len = t_len; +		dec->lv[t_tag].len = t_len - len_offset;  		dec->lv[t_tag].val = cur; -		cur += t_len; -		len -= t_len; +		cur += t_len - len_offset; +		len -= t_len - len_offset;  	}  	return 0;  } diff --git a/tests/Makefile.am b/tests/Makefile.am index b0701f82..6f76e5a4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -16,7 +16,7 @@ check_PROGRAMS += msgfile/msgfile_test  endif  utils_utils_test_SOURCES = utils/utils_test.c -utils_utils_test_LDADD = $(top_builddir)/src/libosmocore.la +utils_utils_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la  a5_a5_test_SOURCES = a5/a5_test.c ../src/gsm/a5.c  a5_a5_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index b21b074b..1a79baa3 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -20,6 +20,9 @@   *   */ +#include <osmocom/gsm/ipa.h> + +#include <osmocom/core/logging.h>  #include <osmocom/core/utils.h>  #include <stdio.h> @@ -40,8 +43,66 @@ static void hexdump_test(void)  	printf("%s\n", osmo_hexdump_nospc(data, ARRAY_SIZE(data)));  } +static void test_idtag_parsing(void) +{ +	struct tlv_parsed tvp; +	int rc; + +        static uint8_t data[] = { +		0x01, 0x08, +		0x01, 0x07, +		0x01, 0x02, +		0x01, 0x03, +		0x01, 0x04, +		0x01, 0x05, +		0x01, 0x01, +		0x01, 0x00, +		0x11, 0x23, 0x4e, 0x6a, 0x28, 0xd2, 0xa2, 0x53, 0x3a, 0x2a, 0x82, 0xa7, 0x7a, 0xef, 0x29, 0xd4, 0x44, 0x30, +		0x11, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +        }; + +	rc = ipa_ccm_idtag_parse_off(&tvp, data, sizeof(data), 1); +	OSMO_ASSERT(rc == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 8)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 8) == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 7)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 7) == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 2)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 2) == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 3)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 3) == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 4)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 4) == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 5)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 5) == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 1)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 1) == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 0)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 0) == 0); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 0x23)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 0x23) == 16); + +	OSMO_ASSERT(TLVP_PRESENT(&tvp, 0x24)); +	OSMO_ASSERT(TLVP_LEN(&tvp, 0x24) == 16); + +	OSMO_ASSERT(!TLVP_PRESENT(&tvp, 0x25)); +} +  int main(int argc, char **argv)  { +	static const struct log_info log_info = {}; +	log_init(&log_info, NULL); +  	hexdump_test(); +	test_idtag_parsing();  	return 0;  } | 
