Introduce 'osmo_tlv_prot' abstraction for validation of TLV protocols

This extends our existing TLV parser with the ability to
* validate that mandatory IEs of a given message are present
* validate that all present IEs are of required minimum length

Introducing this generic layer will help us to reduce open-coded
imperative verification across virtually all the protocols we
implement, as well as add validation to those protocols where we
don't properly perform related input validation yet.

Change-Id: If1e1d9adfa141ca86001dbd62a6a339f9bf9a912
diff --git a/include/osmocom/gsm/tlv.h b/include/osmocom/gsm/tlv.h
index 254c21b..a307b3d 100644
--- a/include/osmocom/gsm/tlv.h
+++ b/include/osmocom/gsm/tlv.h
@@ -620,4 +620,54 @@
 int osmo_shift_lv(uint8_t **data, size_t *data_len,
 		  uint8_t **value, size_t *value_len);
 
+#define MSG_DEF(name, mand_ies, flags) { name, mand_ies, ARRAY_SIZE(mand_ies), flags }
+
+struct osmo_tlv_prot_msg_def {
+	/*! human-readable name of message type (optional) */
+	const char *name;
+	/*! array of mandatory IEs */
+	const uint8_t *mand_ies;
+	/*! number of entries in 'mand_ies' above */
+	uint8_t mand_count;
+	/*! user-defined flags (like uplink/downlink/...) */
+	uint32_t flags;
+};
+struct osmo_tlv_prot_ie_def {
+	/*! minimum length of IE value part, in octets */
+	uint16_t min_len;
+	/*! huamn-readable name (optional) */
+	const char *name;
+};
+
+/*! Osmocom TLV protocol definition */
+struct osmo_tlv_prot_def {
+	/*! human-readable name of protocol */
+	const char *name;
+	/*! TLV parser definition (optional) */
+	const struct tlv_definition *tlv_def;
+	/*! definition of each message (8-bit message type) */
+	struct osmo_tlv_prot_msg_def msg_def[256];
+	/*! definition of IE for each 8-bit tag */
+	struct osmo_tlv_prot_ie_def ie_def[256];
+	/*! value_string array of message type names (legacy, if not populated in msg_def) */
+	const struct value_string *msgt_names;
+};
+
+const char *osmo_tlv_prot_msg_name(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type);
+const char *osmo_tlv_prot_ie_name(const struct osmo_tlv_prot_def *pdef, uint8_t iei);
+
+int osmo_tlv_prot_validate_tp(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type,
+			      const struct tlv_parsed *tp, int log_subsys, const char *log_pfx);
+
+int osmo_tlv_prot_parse(const struct osmo_tlv_prot_def *pdef,
+			struct tlv_parsed *dec, unsigned int dec_multiples, uint8_t msg_type,
+			const uint8_t *buf, unsigned int buf_len, uint8_t lv_tag, uint8_t lv_tag2,
+			int log_subsys, const char *log_pfx);
+
+static inline uint32_t osmo_tlv_prot_msgt_flags(const struct osmo_tlv_prot_def *pdef, uint8_t msg_type)
+{
+	return pdef->msg_def[msg_type].flags;
+}
+
+
 /*! @} */