aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-06-02 15:52:06 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-06-02 15:52:06 +0200
commitf558ed4bb9c0f00997b8f97c2b251a574c1a64c4 (patch)
tree16524d63b63a4c5496a9bc6412c3a9862367cc36
parent91ff17c9ef7dd4a29bb13d6b9995100ffc65b72a (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.h3
-rw-r--r--src/gsm/ipa.c16
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/utils/utils_test.c61
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;
}