diff options
author | Max <msuraev@sysmocom.de> | 2017-01-02 14:10:30 +0100 |
---|---|---|
committer | Max <msuraev@sysmocom.de> | 2017-01-06 10:21:11 +0000 |
commit | dbd3a92f70325b7a02d0a637929732f297fb2612 (patch) | |
tree | b89e89d4bf066323a010a7ee5415ca6cc25e74ef | |
parent | 0bee65c0d89f81a4b90aa3d484016d9ba680dd46 (diff) |
Add parsed TLV helpers from OsmoBTS
Add functions to copy and merge parsed TLV structures from OsmoBTS.
Change-Id: Ieaaaed19da9c069fe451faa53d24c5b84d7d5615
-rw-r--r-- | include/osmocom/gsm/tlv.h | 2 | ||||
-rw-r--r-- | src/gsm/libosmogsm.map | 2 | ||||
-rw-r--r-- | src/gsm/tlv_parser.c | 60 |
3 files changed, 64 insertions, 0 deletions
diff --git a/include/osmocom/gsm/tlv.h b/include/osmocom/gsm/tlv.h index cf09969d..701fe688 100644 --- a/include/osmocom/gsm/tlv.h +++ b/include/osmocom/gsm/tlv.h @@ -436,6 +436,8 @@ static inline uint32_t tlvp_val32_unal(const struct tlv_parsed *tp, int pos) return res; } +struct tlv_parsed *osmo_tlvp_copy(const struct tlv_parsed *tp_orig, void *ctx); +int osmo_tlvp_merge(struct tlv_parsed *dst, const struct tlv_parsed *src); int osmo_shift_v_fixed(uint8_t **data, size_t *data_len, size_t len, uint8_t **value); int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len, diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 199d05af..b84f859f 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -324,6 +324,8 @@ tlv_parse_one; tvlv_att_def; vtvlv_gan_att_def; +osmo_tlvp_copy; +osmo_tlvp_merge; osmo_shift_v_fixed; osmo_match_shift_tv_fixed; osmo_shift_tlv; diff --git a/src/gsm/tlv_parser.c b/src/gsm/tlv_parser.c index e84edd97..4cc43f67 100644 --- a/src/gsm/tlv_parser.c +++ b/src/gsm/tlv_parser.c @@ -19,6 +19,7 @@ #include <stdio.h> #include <stdint.h> +#include <errno.h> #include <osmocom/core/utils.h> #include <osmocom/gsm/tlv.h> @@ -43,6 +44,65 @@ int tlv_dump(struct tlv_parsed *dec) return 0; } +/*! \brief Copy \ref tlv_parsed using given talloc context + * \param[in] tp_orig Parsed TLV structure + * \param[in] ctx Talloc context for allocations + * \returns NULL on errors, \ref tlv_parsed pointer otherwise + */ +struct tlv_parsed *osmo_tlvp_copy(const struct tlv_parsed *tp_orig, void *ctx) +{ + struct tlv_parsed *tp_out; + size_t i, len; + + tp_out = talloc_zero(ctx, struct tlv_parsed); + if (!tp_out) + return NULL; + + /* if the original is NULL, return empty tlvp */ + if (!tp_orig) + return tp_out; + + for (i = 0; i < ARRAY_SIZE(tp_orig->lv); i++) { + len = tp_orig->lv[i].len; + tp_out->lv[i].len = len; + if (len && tp_out->lv[i].val) { + tp_out->lv[i].val = talloc_zero_size(tp_out, len); + if (!tp_out->lv[i].val) { + talloc_free(tp_out); + return NULL; + } + memcpy((uint8_t *)tp_out->lv[i].val, tp_orig->lv[i].val, + len); + } + } + + return tp_out; +} + +/*! \brief Merge all \ref tlv_parsed attributes of 'src' into 'dst' + * \param[in] dst Parsed TLV structure to merge into + * \param[in] src Parsed TLV structure to merge from + * \returns 0 on success, negative on error + */ +int osmo_tlvp_merge(struct tlv_parsed *dst, const struct tlv_parsed *src) +{ + size_t i, len; + for (i = 0; i < ARRAY_SIZE(dst->lv); i++) { + len = src->lv[i].len; + if (len == 0 || src->lv[i].val == NULL) + continue; + if (dst->lv[i].val) { + talloc_free((uint8_t *) dst->lv[i].val); + dst->lv[i].len = 0; + } + dst->lv[i].val = talloc_zero_size(dst, len); + if (!dst->lv[i].val) + return -ENOMEM; + memcpy((uint8_t *) dst->lv[i].val, src->lv[i].val, len); + } + return 0; +} + /*! \brief Parse a single TLV encoded IE * \param[out] o_tag the tag of the IE that was found * \param[out] o_len length of the IE that was found |