aboutsummaryrefslogtreecommitdiffstats
path: root/src/gsm
diff options
context:
space:
mode:
Diffstat (limited to 'src/gsm')
-rw-r--r--src/gsm/libosmogsm.map6
-rw-r--r--src/gsm/tlv_parser.c171
2 files changed, 177 insertions, 0 deletions
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 21d3c293..8bd0dbfe 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -278,6 +278,12 @@ tlv_parse_one;
tvlv_att_def;
vtvlv_gan_att_def;
+osmo_shift_v_fixed;
+osmo_match_shift_tv_fixed;
+osmo_shift_tlv;
+osmo_match_shift_tlv;
+osmo_shift_lv;
+
gan_msgt_vals;
gan_pdisc_vals;
diff --git a/src/gsm/tlv_parser.c b/src/gsm/tlv_parser.c
index 19d0c84d..e84edd97 100644
--- a/src/gsm/tlv_parser.c
+++ b/src/gsm/tlv_parser.c
@@ -225,4 +225,175 @@ static __attribute__((constructor)) void on_dso_load_tlv(void)
vtvlv_gan_att_def.def[i].type = TLV_TYPE_vTvLV_GAN;
}
+/*! Advance the data pointer, subtract length and assign value pointer
+ * \param data pointer to the pointer to data
+ * \param data_len pointer to size_t containing \arg data length
+ * \param[in] len the length that we expect the fixed IE to hav
+ * \param[out] value pointer to pointer of value part of IE
+ * \returns length of IE value; negative in case of error
+ */
+int osmo_shift_v_fixed(uint8_t **data, size_t *data_len,
+ size_t len, uint8_t **value)
+{
+ if (len > *data_len)
+ goto fail;
+
+ if (value)
+ *value = *data;
+
+ *data += len;
+ *data_len -= len;
+
+ return len;
+
+fail:
+ *data += *data_len;
+ *data_len = 0;
+ return -1;
+}
+
+/*! Match tag, check length and assign value pointer
+ * \param data pointer to the pointer to data
+ * \param data_len pointer to size_t containing \arg data length
+ * \param[in] tag the tag (IEI) that we expect at \arg data
+ * \param[in] len the length that we expect the fixed IE to have
+ * \param[out] value pointer to pointer of value part of IE
+ * \returns length of IE value; negative in case of error
+ */
+int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len,
+ uint8_t tag, size_t len,
+ uint8_t **value)
+{
+ size_t ie_len;
+
+ if (*data_len == 0)
+ goto fail;
+
+ if ((*data)[0] != tag)
+ return 0;
+
+ if (len > *data_len - 1)
+ goto fail;
+
+ if (value)
+ *value = *data + 1;
+
+ ie_len = len + 1;
+ *data += ie_len;
+ *data_len -= ie_len;
+
+ return ie_len;
+
+fail:
+ *data += *data_len;
+ *data_len = 0;
+ return -1;
+}
+
+/*! Verify TLV header and advance data / subtract length
+ * \param data pointer to the pointer to data
+ * \param data_len pointer to size_t containing \arg data length
+ * \param[in] expected_tag the tag (IEI) that we expect at \arg data
+ * \param[out] value pointer to pointer of value part of IE
+ * \param[out] value_len pointer to length of \arg value
+ * \returns length of IE value; negative in case of error
+ */
+int osmo_match_shift_tlv(uint8_t **data, size_t *data_len,
+ uint8_t expected_tag, uint8_t **value,
+ size_t *value_len)
+{
+ int rc;
+ uint8_t tag;
+ uint8_t *old_data = *data;
+ size_t old_data_len = *data_len;
+
+ rc = osmo_shift_tlv(data, data_len, &tag, value, value_len);
+
+ if (rc > 0 && tag != expected_tag) {
+ *data = old_data;
+ *data_len = old_data_len;
+ return 0;
+ }
+
+ return rc;
+}
+
+/*! Extract TLV and advance data pointer + subtract length
+ * \param data pointer to the pointer to data
+ * \param data_len pointer to size_t containing \arg data lengt
+ * \param[out] tag extract the tag (IEI) at start of \arg data
+ * \param[out] value extracted pointer to value part of TLV
+ * \param[out] value_len extracted length of \arg value
+ * \returns number of bytes subtracted
+ */
+int osmo_shift_tlv(uint8_t **data, size_t *data_len,
+ uint8_t *tag, uint8_t **value, size_t *value_len)
+{
+ size_t len;
+ size_t ie_len;
+
+ if (*data_len < 2)
+ goto fail;
+
+ len = (*data)[1];
+ if (len > *data_len - 2)
+ goto fail;
+
+ if (tag)
+ *tag = (*data)[0];
+ if (value)
+ *value = *data + 2;
+ if (value_len)
+ *value_len = len;
+
+ ie_len = len + 2;
+
+ *data += ie_len;
+ *data_len -= ie_len;
+
+ return ie_len;
+
+fail:
+ *data += *data_len;
+ *data_len = 0;
+ return -1;
+}
+
+/*! Extract LV and advance data pointer + subtract length
+ * \param data pointer to the pointer to data
+ * \param data_len pointer to size_t containing \arg data lengt
+ * \param[out] value extracted pointer to value part of TLV
+ * \param[out] value_len extracted length of \arg value
+ * \returns number of bytes subtracted
+ */
+int osmo_shift_lv(uint8_t **data, size_t *data_len,
+ uint8_t **value, size_t *value_len)
+{
+ size_t len;
+ size_t ie_len;
+
+ if (*data_len < 1)
+ goto fail;
+
+ len = (*data)[0];
+ if (len > *data_len - 1)
+ goto fail;
+
+ if (value)
+ *value = *data + 1;
+ if (value_len)
+ *value_len = len;
+
+ ie_len = len + 1;
+ *data += ie_len;
+ *data_len -= ie_len;
+
+ return ie_len;
+
+fail:
+ *data += *data_len;
+ *data_len = 0;
+ return -1;
+}
+
/*! @} */