aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/osmocom/gtlv/gtlv.h28
-rw-r--r--include/osmocom/gtlv/gtlv_dec_enc.h4
-rw-r--r--include/osmocom/gtlv/gtlv_gen.h12
3 files changed, 37 insertions, 7 deletions
diff --git a/include/osmocom/gtlv/gtlv.h b/include/osmocom/gtlv/gtlv.h
index 7acf558..d800f71 100644
--- a/include/osmocom/gtlv/gtlv.h
+++ b/include/osmocom/gtlv/gtlv.h
@@ -25,10 +25,25 @@
#include <stdint.h>
#include <stdio.h>
+#include <stdbool.h>
struct msgb;
struct osmo_gtlv_load;
struct osmo_gtlv_put;
+struct value_string;
+
+struct osmo_gtlv_tag_inst {
+ unsigned int tag;
+ bool instance_present;
+ unsigned int instance;
+};
+
+int osmo_gtlv_tag_inst_cmp(const struct osmo_gtlv_tag_inst *a, const struct osmo_gtlv_tag_inst *b);
+
+int osmo_gtlv_tag_inst_to_str_buf(char *buf, size_t buflen, const struct osmo_gtlv_tag_inst *ti,
+ const struct value_string *tag_names);
+char *osmo_gtlv_tag_inst_to_str_c(void *ctx, const struct osmo_gtlv_tag_inst *ti,
+ const struct value_string *tag_names);
/*! TL configuration for osmo_gtlv_load*() and osmo_gtlv_put*(). Depending on these implementations provided by the caller,
* osmo_gtlv can load any sizes of tag and length fields (that don't surpass the value range of unsigned int and size_t,
@@ -49,6 +64,7 @@ struct osmo_gtlv_cfg {
/*! Read one TL from the start of src_data.
* \param gtlv Return the T (tag) value read from src_data in gtlv->tag.
* Return the L (length) value read from src_data in gtlv->len.
+ * Return the I (instance) value read from src_data in gtlv->len; ignore if there is no I.
* Return the position just after the TL in gtlv->*val. If there is V data, point at the start of the
* V data in src_data. If there is no V data, point at the byte just after the TL part in src_data.
* \param src_data Part of raw message being decoded.
@@ -68,12 +84,14 @@ struct osmo_gtlv_cfg {
* \param dst_data Write TL data to the start of this buffer.
* \param dst_data_avail Remaining available space in dst_data.
* \param tag The T value to store in dst_data.
+ * \param instance The I value to store in dst_data (if this tag is a TLIV); ignore when not a TLIV.
* \param len The L value to store in dst_data.
* \param gtlv Backpointer to the osmo_gtlv_put struct, including gtlv->dst, the underlying msgb.
* \return the size of the TL part in bytes on success, -EINVAL if tag is invalid, -EMSGSIZE if len is too large
* or dst_data_avail is too small for the TL.
*/
- int (*store_tl)(uint8_t *dst_data, size_t dst_data_avail, unsigned int tag, size_t len, struct osmo_gtlv_put *gtlv);
+ int (*store_tl)(uint8_t *dst_data, size_t dst_data_avail, const struct osmo_gtlv_tag_inst *ti, size_t len,
+ struct osmo_gtlv_put *gtlv);
};
/*! Configuration that allows parsing an 8bit tag and 8bit length TLV. */
@@ -97,7 +115,7 @@ struct osmo_gtlv_load {
} src;
/*! Return value from last invocation of osmo_gtlv_load_next*(): tag value of parsed IE. */
- unsigned int tag;
+ struct osmo_gtlv_tag_inst ti;
/*! Return value from last invocation of osmo_gtlv_load_next*(): Start of the IE's payload data (after tag and
* length). If the end of the src buffer is reached, val == NULL. If a TLV contained no value part, len == 0,
* but this still points just after the TL. */
@@ -114,8 +132,9 @@ static inline void osmo_gtlv_load_start(struct osmo_gtlv_load *gtlv)
}
int osmo_gtlv_load_next(struct osmo_gtlv_load *gtlv);
-int osmo_gtlv_load_peek_tag(const struct osmo_gtlv_load *gtlv);
+int osmo_gtlv_load_peek_tag(const struct osmo_gtlv_load *gtlv, struct osmo_gtlv_tag_inst *ti);
int osmo_gtlv_load_next_by_tag(struct osmo_gtlv_load *gtlv, unsigned int tag);
+int osmo_gtlv_load_next_by_tag_inst(struct osmo_gtlv_load *gtlv, const struct osmo_gtlv_tag_inst *ti);
/* State for storing a TLV structure into a msgb. */
struct osmo_gtlv_put {
@@ -128,10 +147,11 @@ struct osmo_gtlv_put {
/* msgb to append new TL to */
struct msgb *dst;
/* What was the last TL written and where are its TL and V */
- unsigned int last_tag;
+ struct osmo_gtlv_tag_inst last_ti;
uint8_t *last_tl;
uint8_t *last_val;
};
int osmo_gtlv_put_tl(struct osmo_gtlv_put *gtlv, unsigned int tag, size_t len);
+int osmo_gtlv_put_tli(struct osmo_gtlv_put *gtlv, const struct osmo_gtlv_tag_inst *ti, size_t len);
int osmo_gtlv_put_update_tl(struct osmo_gtlv_put *gtlv);
diff --git a/include/osmocom/gtlv/gtlv_dec_enc.h b/include/osmocom/gtlv/gtlv_dec_enc.h
index b861129..132239f 100644
--- a/include/osmocom/gtlv/gtlv_dec_enc.h
+++ b/include/osmocom/gtlv/gtlv_dec_enc.h
@@ -78,8 +78,8 @@ enum osmo_gtlv_coding_nested_ies_ordered {
* that the decoded structs to match the IEs are also generated at the same time and thus always match the message
* definitions. For an example, see tests/libosmo-gtlv/test_gtlv_gen/. */
struct osmo_gtlv_coding {
- /*! the IEI value */
- unsigned int tag;
+ /*! the IEI discriminator, and optional instance number */
+ struct osmo_gtlv_tag_inst ti;
/*! Decoding function callback. Invoked for each defined and present IE encountered in the message.
* Return 0 on success, negative on failure. */
diff --git a/include/osmocom/gtlv/gtlv_gen.h b/include/osmocom/gtlv/gtlv_gen.h
index a2f088b..71cec92 100644
--- a/include/osmocom/gtlv/gtlv_gen.h
+++ b/include/osmocom/gtlv/gtlv_gen.h
@@ -37,6 +37,10 @@ struct osmo_gtlv_gen_ie;
#define OSMO_GTLV_GEN_O_MULTI(MAX, TLV_GEN_IE, MEMB_NAME) { MEMB_NAME, .multi = MAX, .ie = &(TLV_GEN_IE) }
#define OSMO_GTLV_GEN_M_MULTI(MAX, MAND_COUNT, TLV_GEN_IE, MEMB_NAME) \
{ MEMB_NAME, .multi = MAX, .multi_mandatory = MAND_COUNT, .ie = &(TLV_GEN_IE) }
+#define OSMO_GTLV_GEN_O_INST(INSTANCE, TLV_GEN_IE, MEMB_NAME) { MEMB_NAME, .optional = true, .instance = INSTANCE, .ie = &TLV_GEN_IE }
+#define OSMO_GTLV_GEN_M_INST(INSTANCE, TLV_GEN_IE, MEMB_NAME) { MEMB_NAME, .instance = INSTANCE, .ie = &(TLV_GEN_IE) }
+
+#define OSMO_GTLV_GEN_NO_INSTANCE INT_MAX
/*! osmo_gtlv_gen_ie with all members == NULL, so that all are derived from the member name. */
extern const struct osmo_gtlv_gen_ie osmo_gtlv_gen_ie_auto;
@@ -81,6 +85,10 @@ struct osmo_gtlv_gen_ie_o {
/*! Number of mandatory occurences of the IE, only has an effect if .multi > 0. */
unsigned int multi_mandatory;
+ /* If any, the instance nr to match, in C that yields an unsigned int.
+ * e.g. "1" or "MYPROTO_FOO_INST_ONE". */
+ const char *instance;
+
/*! IE decoding / encoding instructions. If NULL, the entire IE definition is derived from .name.
* 'MYPROTO_IEI_NAME', 'myproto_dec_name()', 'myproto_enc_name()', 'myproto_enc_to_str_name()'.
* Your myproto_ies_custom.h needs to define an enum value MYPROTO_IEI_NAME and*/
@@ -96,7 +104,9 @@ struct osmo_gtlv_gen_ie {
* When there are no nested IEs, the type needs to be defined manually by a myproto_ies_custom.h. */
const char *decoded_type;
- /*! C name of this tag value, e.g. "MYPROTO_IEI_FOO". If NULL, take "MYPROTO_IEI_"+upper(name) instead. */
+ /*! C name of this tag value, e.g. "foo" to use tag "MYPROTO_IEI_FOO".
+ * If NULL, take "MYPROTO_IEI_"+upper(memb_name) instead, where memb_name comes from the osmo_gtlv_gen_ie_o.
+ * decoded_type and/or dec_enc may be derived from this, if they are NULL. */
const char *tag_name;
/*! Name suffix of the dec/enc functions. "foo" -> myproto_dec_foo(), myproto_enc_foo(),