laforge has submitted this change. ( 
https://gerrit.osmocom.org/c/libosmo-sigtran/+/43386?usp=email )

Change subject: xua: Validate IE lengths of incoming messages [1/6]
......................................................................

xua: Validate IE lengths of incoming messages [1/6]

Improve the data structures defining M3UA/SUA messages to also include
expected min/max lengths of each IE in a given message.

This way we already cover in one place validation of fixed length IEs.

This patch is the first in a series of patches that go together, since
now that more checks are done some message structure definitions need
to be added in both M3UA and SUA.

xua_dialect_check_all_ies_ext() is split into helper
xua_dialect_check_all_ies_ext() because it will also be used directly
when checking grouped IEs for RKM message Routing key and
(De)Registration Result.

Related: OS#7074
Reported-By: Tristan Madani <[email protected]>
Change-Id: I9b1ae0dbc324123790942c9e6068f6822e3bb957
---
M src/m3ua.c
M src/sua.c
M src/xua_msg.c
M src/xua_msg.h
4 files changed, 435 insertions(+), 128 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved
  osmith: Looks good to me, but someone else must approve




diff --git a/src/m3ua.c b/src/m3ua.c
index c232f02..9b92395 100644
--- a/src/m3ua.c
+++ b/src/m3ua.c
@@ -146,11 +146,71 @@
        { 0, NULL }
 };

-#define MAND_IES(msgt, ies)    [msgt] = (ies)
+#define IES(msgt, ies) \
+       [msgt] = (ies)
+
+/* M3UA/SUA shared: */
+
+#define M3UA_MSG_PART_CLASS_INFO_STRING(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(M3UA_IEI_ROUTE_CTX, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_ROUTE_CTX(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_ROUTE_CTX, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_ROUTE_CTX1(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_ROUTE_CTX, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_DIAG_INFO(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(M3UA_IEI_DIAG_INFO, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_ERR_CODE(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_ERR_CODE, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_STATUS(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_STATUS, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_ASP_ID(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_ASP_ID, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_AFFECTED_PC(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(M3UA_IEI_AFFECTED_PC, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_CORR_ID(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_CORR_ID, (mandatory))
+
+/* M3UA specific: */
+
+#define M3UA_MSG_PART_CLASS_NET_APPEAR(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_NET_APPEAR, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_USER_CAUSE(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_USER_CAUSE, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_CONG_IND(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_CONG_IND, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_CONC_DEST(mandatory) \
+       XUA_MSG_PART_CLASS_U32(M3UA_IEI_CONC_DEST, (mandatory))
+
+#define M3UA_MSG_PART_CLASS_ROUT_KEY(mandatory) \
+       XUA_MSG_PART_CLASS(M3UA_IEI_ROUT_KEY, (mandatory), true, 0, 
XUA_MSG_PART_CLASS_MAX_LEN)
+
+#define M3UA_MSG_PART_CLASS_REG_RESULT(mandatory) \
+       XUA_MSG_PART_CLASS(M3UA_IEI_REG_RESULT, (mandatory), true, 24, 
XUA_MSG_PART_CLASS_MAX_LEN)
+
+#define M3UA_MSG_PART_CLASS_DEREG_RESULT(mandatory) \
+       XUA_MSG_PART_CLASS(M3UA_IEI_DEREG_RESULT, (mandatory), true, 16, 
XUA_MSG_PART_CLASS_MAX_LEN)
+
+#define M3UA_MSG_PART_CLASS_PROT_DATA(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(M3UA_IEI_PROT_DATA, (mandatory))

 /* XFER */
-static const uint16_t data_mand_ies[] = {
-       M3UA_IEI_PROT_DATA, 0
+static const struct xua_msg_part_class data_ies[] = {
+       M3UA_MSG_PART_CLASS_NET_APPEAR(false),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX1(false),
+       M3UA_MSG_PART_CLASS_PROT_DATA(true),
+       M3UA_MSG_PART_CLASS_CORR_ID(false),
+       XUA_MSG_PART_CLASS_EOF
 };
 static const struct value_string m3ua_xfer_msgt_names[] = {
        { M3UA_XFER_DATA,       "DATA" },
@@ -160,29 +220,56 @@
        .name = "XFER",
        .msgt_names = m3ua_xfer_msgt_names,
        .iei_names = m3ua_iei_names,
-       .mand_ies = {
-               MAND_IES(M3UA_XFER_DATA, data_mand_ies),
+       .ies = {
+               IES(M3UA_XFER_DATA, data_ies),
        },
 };

 /* SNM */
-static const uint16_t duna_mand_ies[] = {
-       M3UA_IEI_AFFECTED_PC, 0
+static const struct xua_msg_part_class duna_ies[] = {
+       M3UA_MSG_PART_CLASS_NET_APPEAR(false),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(false),
+       M3UA_MSG_PART_CLASS_AFFECTED_PC(true),
+       M3UA_MSG_PART_CLASS_INFO_STRING(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t dava_mand_ies[] = {
-       M3UA_IEI_AFFECTED_PC, 0
+static const struct xua_msg_part_class dava_ies[] = {
+       M3UA_MSG_PART_CLASS_NET_APPEAR(false),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(false),
+       M3UA_MSG_PART_CLASS_AFFECTED_PC(true),
+       M3UA_MSG_PART_CLASS_INFO_STRING(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t daud_mand_ies[] = {
-       M3UA_IEI_AFFECTED_PC, 0
+static const struct xua_msg_part_class daud_ies[] = {
+       M3UA_MSG_PART_CLASS_NET_APPEAR(false),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(false),
+       M3UA_MSG_PART_CLASS_AFFECTED_PC(true),
+       M3UA_MSG_PART_CLASS_INFO_STRING(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t scon_mand_ies[] = {
-       M3UA_IEI_AFFECTED_PC, 0
+static const struct xua_msg_part_class scon_ies[] = {
+       M3UA_MSG_PART_CLASS_NET_APPEAR(false),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(false),
+       M3UA_MSG_PART_CLASS_AFFECTED_PC(true),
+       M3UA_MSG_PART_CLASS_CONC_DEST(false),
+       M3UA_MSG_PART_CLASS_CONG_IND(false),
+       M3UA_MSG_PART_CLASS_INFO_STRING(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t dupu_mand_ies[] = {
-       M3UA_IEI_AFFECTED_PC, M3UA_IEI_USER_CAUSE, 0
+static const struct xua_msg_part_class dupu_ies[] = {
+       M3UA_MSG_PART_CLASS_NET_APPEAR(false),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(false),
+       M3UA_MSG_PART_CLASS_AFFECTED_PC(true),
+       M3UA_MSG_PART_CLASS_USER_CAUSE(true),
+       M3UA_MSG_PART_CLASS_INFO_STRING(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t drst_mand_ies[] = {
-       M3UA_IEI_AFFECTED_PC, 0
+static const struct xua_msg_part_class drst_ies[] = {
+       M3UA_MSG_PART_CLASS_NET_APPEAR(false),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(false),
+       M3UA_MSG_PART_CLASS_AFFECTED_PC(true),
+       M3UA_MSG_PART_CLASS_INFO_STRING(false),
+       XUA_MSG_PART_CLASS_EOF
 };
 const struct value_string m3ua_snm_msgt_names[] = {
        { M3UA_SNM_DUNA,        "DUNA" },
@@ -197,13 +284,13 @@
        .name = "SNM",
        .msgt_names = m3ua_snm_msgt_names,
        .iei_names = m3ua_iei_names,
-       .mand_ies = {
-               MAND_IES(M3UA_SNM_DUNA, duna_mand_ies),
-               MAND_IES(M3UA_SNM_DAVA, dava_mand_ies),
-               MAND_IES(M3UA_SNM_DAUD, daud_mand_ies),
-               MAND_IES(M3UA_SNM_SCON, scon_mand_ies),
-               MAND_IES(M3UA_SNM_DUPU, dupu_mand_ies),
-               MAND_IES(M3UA_SNM_DRST, drst_mand_ies),
+       .ies = {
+               IES(M3UA_SNM_DUNA, duna_ies),
+               IES(M3UA_SNM_DAVA, dava_ies),
+               IES(M3UA_SNM_DAUD, daud_ies),
+               IES(M3UA_SNM_SCON, scon_ies),
+               IES(M3UA_SNM_DUPU, dupu_ies),
+               IES(M3UA_SNM_DRST, drst_ies),
        },
 };

@@ -238,11 +325,20 @@
 };

 /* MGMT */
-static const uint16_t err_req_ies[] = {
-       M3UA_IEI_ERR_CODE, 0
+static const struct xua_msg_part_class err_req_ies[] = {
+       M3UA_MSG_PART_CLASS_ERR_CODE(true),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(false),
+       M3UA_MSG_PART_CLASS_NET_APPEAR(false),
+       M3UA_MSG_PART_CLASS_AFFECTED_PC(false),
+       M3UA_MSG_PART_CLASS_DIAG_INFO(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t ntfy_req_ies[] = {
-       M3UA_IEI_STATUS, 0
+static const struct xua_msg_part_class ntfy_req_ies[] = {
+       M3UA_MSG_PART_CLASS_STATUS(true),
+       M3UA_MSG_PART_CLASS_ASP_ID(false),
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(false),
+       M3UA_MSG_PART_CLASS_INFO_STRING(false),
+       XUA_MSG_PART_CLASS_EOF
 };
 static const struct value_string m3ua_mgmt_msgt_names[] = {
        { M3UA_MGMT_ERR,        "ERROR" },
@@ -253,24 +349,28 @@
        .name = "MGMT",
        .msgt_names = m3ua_mgmt_msgt_names,
        .iei_names = m3ua_iei_names,
-       .mand_ies = {
-               MAND_IES(M3UA_MGMT_ERR, err_req_ies),
-               MAND_IES(M3UA_MGMT_NTFY, ntfy_req_ies),
+       .ies = {
+               IES(M3UA_MGMT_ERR, err_req_ies),
+               IES(M3UA_MGMT_NTFY, ntfy_req_ies),
        },
 };

 /* RKM */
-static const uint16_t reg_req_ies[] = {
-       M3UA_IEI_ROUT_KEY, 0
+static const struct xua_msg_part_class reg_req_ies[] = {
+       M3UA_MSG_PART_CLASS_ROUT_KEY(true),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t reg_rsp_ies[] = {
-       M3UA_IEI_REG_RESULT, 0
+static const struct xua_msg_part_class reg_rsp_ies[] = {
+       M3UA_MSG_PART_CLASS_REG_RESULT(true),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t dereg_req_ies[] = {
-       M3UA_IEI_ROUTE_CTX, 0
+static const struct xua_msg_part_class dereg_req_ies[] = {
+       M3UA_MSG_PART_CLASS_ROUTE_CTX(true),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t dereg_rsp_ies[] = {
-       M3UA_IEI_DEREG_RESULT, 0
+static const struct xua_msg_part_class dereg_rsp_ies[] = {
+       M3UA_MSG_PART_CLASS_DEREG_RESULT(true),
+       XUA_MSG_PART_CLASS_EOF
 };
 const struct value_string m3ua_rkm_msgt_names[] = {
        { M3UA_RKM_REG_REQ,     "REG-REQ" },
@@ -283,11 +383,11 @@
        .name = "RKM",
        .msgt_names = m3ua_rkm_msgt_names,
        .iei_names = m3ua_iei_names,
-       .mand_ies = {
-               MAND_IES(M3UA_RKM_REG_REQ, reg_req_ies),
-               MAND_IES(M3UA_RKM_REG_RSP, reg_rsp_ies),
-               MAND_IES(M3UA_RKM_DEREG_REQ, dereg_req_ies),
-               MAND_IES(M3UA_RKM_DEREG_RSP, dereg_rsp_ies),
+       .ies = {
+               IES(M3UA_RKM_REG_REQ, reg_req_ies),
+               IES(M3UA_RKM_REG_RSP, reg_rsp_ies),
+               IES(M3UA_RKM_DEREG_REQ, dereg_req_ies),
+               IES(M3UA_RKM_DEREG_RSP, dereg_rsp_ies),
        },
 };

@@ -615,7 +715,7 @@
        struct m3ua_data_hdr *dh;
        uint32_t pc;

-       /* As already checked by xua_dialect_check_all_mand_ies(): */
+       /* As already checked by xua_dialect_check_all_ies(): */
        OSMO_ASSERT(data_ie);

        if (data_ie->len < sizeof(struct m3ua_data_hdr)) {
@@ -702,14 +802,10 @@
        /* Reject unsupported Network Appearance IE. */
        if (na_ie) {
                uint32_t na = xua_msg_part_get_u32(na_ie);
-
                LOGPASP(asp, DLM3UA, LOGL_NOTICE,
                        "Unsupported 'Network Appearance' IE '0x%08x' in 
message type '%s', sending 'Error'.\n",
                        na, get_value_string(m3ua_xfer_msgt_names, 
xua->hdr.msg_type));
-               if (na_ie->len != 4)
-                       rc = M3UA_ERR_PARAM_FIELD_ERR;
-               else
-                       rc = M3UA_ERR_INVAL_NET_APPEAR;
+               rc = M3UA_ERR_INVAL_NET_APPEAR;
                goto ret_free;
        }
 
@@ -897,7 +993,7 @@
        LOGPASP(asp, DLM3UA, LOGL_DEBUG, "Received M3UA Message (%s)\n",
                xua_hdr_dump(xua, &xua_dialect_m3ua));

-       rc = xua_dialect_check_all_mand_ies(&xua_dialect_m3ua, xua);
+       rc = xua_dialect_check_all_ies(&xua_dialect_m3ua, xua);
        if (rc > 0) {
                xua_msg_free(xua);
                goto out;
diff --git a/src/sua.c b/src/sua.c
index 8578647..af4b1f3 100644
--- a/src/sua.c
+++ b/src/sua.c
@@ -121,15 +121,111 @@
        { 0, NULL }
 };

-#define MAND_IES(msgt, ies)    [msgt] = (ies)
+#define IES(msgt, ies) \
+       [msgt] = (ies)

-static const uint16_t cldt_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_PROTO_CLASS, SUA_IEI_SRC_ADDR,
-       SUA_IEI_DEST_ADDR, SUA_IEI_SEQ_CTRL, SUA_IEI_DATA, 0
+/* M3UA/SUA shared: */
+
+#define SUA_MSG_PART_CLASS_INFO_STRING(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(SUA_IEI_ROUTE_CTX, (mandatory))
+
+#define SUA_MSG_PART_CLASS_ROUTE_CTX(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_ROUTE_CTX, (mandatory))
+
+#define SUA_MSG_PART_CLASS_ROUTE_CTX1(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_ROUTE_CTX, (mandatory))
+
+#define SUA_MSG_PART_CLASS_DIAG_INFO(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(SUA_IEI_DIAG_INFO, (mandatory))
+
+#define SUA_MSG_PART_CLASS_ERR_CODE(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_ERR_CODE, (mandatory))
+
+#define SUA_MSG_PART_CLASS_STATUS(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_STATUS, (mandatory))
+
+#define SUA_MSG_PART_CLASS_ASP_ID(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_ASP_ID, (mandatory))
+
+#define SUA_MSG_PART_CLASS_AFFECTED_PC(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(SUA_IEI_AFFECTED_PC, (mandatory))
+
+#define SUA_MSG_PART_CLASS_CORR_ID(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_CORR_ID, (mandatory))
+
+/* SUA specific: */
+
+#define SUA_MSG_PART_CLASS_HOP_CTR(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_S7_HOP_CTR, (mandatory))
+
+#define SUA_MSG_PART_CLASS_SRC_ADDR(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(SUA_IEI_SRC_ADDR, (mandatory))
+
+#define SUA_MSG_PART_CLASS_DEST_ADDR(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(SUA_IEI_DEST_ADDR, (mandatory))
+
+#define SUA_MSG_PART_CLASS_SEQ_CTRL(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_SEQ_CTRL, (mandatory))
+
+#define SUA_MSG_PART_CLASS_SEQ_NR(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_SEQ_NR, (mandatory))
+
+#define SUA_MSG_PART_CLASS_RX_SEQ_NR(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_RX_SEQ_NR, (mandatory))
+
+#define SUA_MSG_PART_CLASS_CREDIT(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_CREDIT, (mandatory))
+
+#define SUA_MSG_PART_CLASS_SRC_REF(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_SRC_REF, (mandatory))
+
+#define SUA_MSG_PART_CLASS_DEST_REF(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_DEST_REF, (mandatory))
+
+#define SUA_MSG_PART_CLASS_CAUSE(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_CAUSE, (mandatory))
+
+#define SUA_MSG_PART_CLASS_DATA(mandatory) \
+       XUA_MSG_PART_CLASS_UNBOUND(SUA_IEI_DATA, (mandatory))
+
+#define SUA_MSG_PART_CLASS_IMPORTANCE(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_IMPORTANCE, (mandatory))
+
+#define SUA_MSG_PART_CLASS_MSG_PRIO(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_MSG_PRIO, (mandatory))
+
+#define SUA_MSG_PART_CLASS_PROTO_CLASS(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_PROTO_CLASS, (mandatory))
+
+#define SUA_MSG_PART_CLASS_SEGMENTATION(mandatory) \
+       XUA_MSG_PART_CLASS_U32(SUA_IEI_SEGMENTATION, (mandatory))
+
+static const struct xua_msg_part_class cldt_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_PROTO_CLASS(true),
+       SUA_MSG_PART_CLASS_SRC_ADDR(true),
+       SUA_MSG_PART_CLASS_DEST_ADDR(true),
+       SUA_MSG_PART_CLASS_SEQ_CTRL(true),
+       SUA_MSG_PART_CLASS_HOP_CTR(false),
+       SUA_MSG_PART_CLASS_IMPORTANCE(false),
+       SUA_MSG_PART_CLASS_MSG_PRIO(false),
+       SUA_MSG_PART_CLASS_CORR_ID(false),
+       SUA_MSG_PART_CLASS_SEGMENTATION(false),
+       SUA_MSG_PART_CLASS_DATA(true),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t cldr_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_CAUSE, SUA_IEI_SRC_ADDR,
-       SUA_IEI_DEST_ADDR, 0
+static const struct xua_msg_part_class cldr_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_CAUSE(true),
+       SUA_MSG_PART_CLASS_SRC_ADDR(true),
+       SUA_MSG_PART_CLASS_DEST_ADDR(true),
+       SUA_MSG_PART_CLASS_HOP_CTR(false),
+       SUA_MSG_PART_CLASS_IMPORTANCE(false),
+       SUA_MSG_PART_CLASS_MSG_PRIO(false),
+       SUA_MSG_PART_CLASS_CORR_ID(false),
+       SUA_MSG_PART_CLASS_SEGMENTATION(false),
+       SUA_MSG_PART_CLASS_DATA(false),
+       XUA_MSG_PART_CLASS_EOF
 };
 static const struct value_string sua_cl_msgt_names[] = {
        { SUA_CL_CLDT,          "CLDT" },
@@ -140,49 +236,110 @@
        .name = "CL",
        .msgt_names = sua_cl_msgt_names,
        .iei_names = sua_iei_names,
-       .mand_ies = {
-               MAND_IES(SUA_CL_CLDT, cldt_mand_ies),
-               MAND_IES(SUA_CL_CLDR, cldr_mand_ies),
+       .ies = {
+               IES(SUA_CL_CLDT, cldt_ies),
+               IES(SUA_CL_CLDR, cldr_ies),
        },
 };

-static const uint16_t codt_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_DATA, 0
+static const struct xua_msg_part_class codt_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_SEQ_NR(false),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_MSG_PRIO(false),
+       SUA_MSG_PART_CLASS_CORR_ID(false),
+       SUA_MSG_PART_CLASS_DATA(true),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t coda_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, 0
+static const struct xua_msg_part_class coda_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_RX_SEQ_NR(false),
+       SUA_MSG_PART_CLASS_RX_SEQ_NR(false),
+       SUA_MSG_PART_CLASS_CREDIT(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t core_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_PROTO_CLASS, SUA_IEI_SRC_REF,
-       SUA_IEI_DEST_ADDR, SUA_IEI_SEQ_CTRL, 0
+static const struct xua_msg_part_class core_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_PROTO_CLASS(true),
+       SUA_MSG_PART_CLASS_SRC_REF(true),
+       SUA_MSG_PART_CLASS_SEQ_CTRL(true),
+       SUA_MSG_PART_CLASS_SEQ_NR(false),
+       SUA_MSG_PART_CLASS_SRC_ADDR(false),
+       SUA_MSG_PART_CLASS_HOP_CTR(false),
+       SUA_MSG_PART_CLASS_IMPORTANCE(false),
+       SUA_MSG_PART_CLASS_MSG_PRIO(false),
+       SUA_MSG_PART_CLASS_CREDIT(false),
+       SUA_MSG_PART_CLASS_DATA(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t coak_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_PROTO_CLASS, SUA_IEI_DEST_REF,
-       SUA_IEI_SRC_REF, SUA_IEI_SEQ_CTRL, 0
+static const struct xua_msg_part_class coak_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_PROTO_CLASS(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_SRC_REF(true),
+       SUA_MSG_PART_CLASS_SEQ_CTRL(true),
+       SUA_MSG_PART_CLASS_CREDIT(false),
+       SUA_MSG_PART_CLASS_SRC_ADDR(false),
+       SUA_MSG_PART_CLASS_IMPORTANCE(false),
+       SUA_MSG_PART_CLASS_MSG_PRIO(false),
+       SUA_MSG_PART_CLASS_DEST_ADDR(false),
+       SUA_MSG_PART_CLASS_DATA(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t coref_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_CAUSE, 0
+static const struct xua_msg_part_class coref_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_CAUSE(true),
+       SUA_MSG_PART_CLASS_SRC_ADDR(false),
+       SUA_MSG_PART_CLASS_DEST_ADDR(false),
+       SUA_MSG_PART_CLASS_IMPORTANCE(false),
+       SUA_MSG_PART_CLASS_DATA(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t relre_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_SRC_REF,
-       SUA_IEI_CAUSE, 0
+static const struct xua_msg_part_class relre_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_SRC_REF(true),
+       SUA_MSG_PART_CLASS_CAUSE(true),
+       SUA_MSG_PART_CLASS_IMPORTANCE(false),
+       SUA_MSG_PART_CLASS_DATA(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t relco_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_SRC_REF, 0
+static const struct xua_msg_part_class relco_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_SRC_REF(true),
+       SUA_MSG_PART_CLASS_IMPORTANCE(false),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t resre_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_SRC_REF,
-       SUA_IEI_CAUSE, 0
+static const struct xua_msg_part_class resre_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_SRC_REF(true),
+       SUA_MSG_PART_CLASS_CAUSE(true),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t resco_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_SRC_REF, 0
+static const struct xua_msg_part_class resco_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_SRC_REF(true),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t coerr_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_CAUSE, 0
+static const struct xua_msg_part_class coerr_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_CAUSE(true),
+       XUA_MSG_PART_CLASS_EOF
 };
-static const uint16_t coit_mand_ies[] = {
-       SUA_IEI_ROUTE_CTX, SUA_IEI_PROTO_CLASS, SUA_IEI_SRC_REF,
-       SUA_IEI_DEST_REF, 0
+static const struct xua_msg_part_class coit_ies[] = {
+       SUA_MSG_PART_CLASS_ROUTE_CTX(true),
+       SUA_MSG_PART_CLASS_PROTO_CLASS(true),
+       SUA_MSG_PART_CLASS_SRC_REF(true),
+       SUA_MSG_PART_CLASS_DEST_REF(true),
+       SUA_MSG_PART_CLASS_SEQ_NR(false),
+       SUA_MSG_PART_CLASS_CREDIT(false),
+       XUA_MSG_PART_CLASS_EOF
 };

 /* ITU-T Rec Q.713 */
@@ -204,18 +361,18 @@
        .name = "CO",
        .msgt_names = sua_co_msgt_names,
        .iei_names = sua_iei_names,
-       .mand_ies = {
-               MAND_IES(SUA_CO_CODT, codt_mand_ies),
-               MAND_IES(SUA_CO_CODA, coda_mand_ies),
-               MAND_IES(SUA_CO_CORE, core_mand_ies),
-               MAND_IES(SUA_CO_COAK, coak_mand_ies),
-               MAND_IES(SUA_CO_COREF, coref_mand_ies),
-               MAND_IES(SUA_CO_RELRE, relre_mand_ies),
-               MAND_IES(SUA_CO_RELCO, relco_mand_ies),
-               MAND_IES(SUA_CO_RESRE, resre_mand_ies),
-               MAND_IES(SUA_CO_RESCO, resco_mand_ies),
-               MAND_IES(SUA_CO_COERR, coerr_mand_ies),
-               MAND_IES(SUA_CO_COIT, coit_mand_ies),
+       .ies = {
+               IES(SUA_CO_CODT, codt_ies),
+               IES(SUA_CO_CODA, coda_ies),
+               IES(SUA_CO_CORE, core_ies),
+               IES(SUA_CO_COAK, coak_ies),
+               IES(SUA_CO_COREF, coref_ies),
+               IES(SUA_CO_RELRE, relre_ies),
+               IES(SUA_CO_RELCO, relco_ies),
+               IES(SUA_CO_RESRE, resre_ies),
+               IES(SUA_CO_RESCO, resco_ies),
+               IES(SUA_CO_COERR, coerr_ies),
+               IES(SUA_CO_COIT, coit_ies),
        },
 };

@@ -225,13 +382,13 @@
        .port = SUA_PORT,
        .log_subsys = DLSUA,
        .class = {
-               [SUA_MSGC_MGMT] = &m3ua_msg_class_mgmt,
-               [SUA_MSGC_SNM] = &m3ua_msg_class_snm,
-               [SUA_MSGC_ASPSM] = &m3ua_msg_class_aspsm,
-               [SUA_MSGC_ASPTM] = &m3ua_msg_class_asptm,
+               [SUA_MSGC_MGMT] = &m3ua_msg_class_mgmt, /* TODO: different than 
M3UA */
+               [SUA_MSGC_SNM] = &m3ua_msg_class_snm, /* TODO: different than 
M3UA */
+               [SUA_MSGC_ASPSM] = &m3ua_msg_class_aspsm, /* Same as M3UA */
+               [SUA_MSGC_ASPTM] = &m3ua_msg_class_asptm, /* TODO: different 
than M3UA */
                [SUA_MSGC_CL] = &sua_msg_class_cl,
                [SUA_MSGC_CO] = &sua_msg_class_co,
-               [SUA_MSGC_RKM] = &m3ua_msg_class_rkm,
+               [SUA_MSGC_RKM] = &m3ua_msg_class_rkm, /* TODO: different than 
M3UA */
        },
 };

@@ -780,7 +937,7 @@
        LOGPASP(asp, DLSUA, LOGL_DEBUG, "Received SUA Message (%s)\n",
                xua_hdr_dump(xua, &xua_dialect_sua));

-       rc = xua_dialect_check_all_mand_ies(&xua_dialect_sua, xua);
+       rc = xua_dialect_check_all_ies(&xua_dialect_sua, xua);
        if (rc > 0) {
                err = sua_gen_error_msg(rc, msg);
                goto out;
diff --git a/src/xua_msg.c b/src/xua_msg.c
index 8364a48..59e5995 100644
--- a/src/xua_msg.c
+++ b/src/xua_msg.c
@@ -32,6 +32,7 @@

 #include <string.h>
 #include <errno.h>
+#include <inttypes.h>

 static void *tall_xua = NULL;

@@ -535,31 +536,38 @@
 }

 /* Validate incoming xua_msg. returns 0 on success, M3UA_ERR_* on failure. */
-int xua_dialect_check_all_mand_ies(const struct xua_dialect *dialect, const 
struct xua_msg *xua)
+static int xua_dialect_check_all_ies_ext(const struct xua_dialect *dialect, 
const struct xua_msg_class *xmc,
+                                        uint8_t msg_type, const struct 
xua_msg_part_class *ies,
+                                        const struct xua_msg *xua)
 {
-       uint8_t msg_class = xua->hdr.msg_class;
-       uint8_t msg_type = xua->hdr.msg_type;
-       const struct xua_msg_class *xmc = dialect->class[msg_class];
-       const uint16_t *ies;
-       uint16_t ie;
+       const struct xua_msg_part_class *ie;

-       /* unknown class? */
-       if (!xmc)
-               return 0;
-
-       ies = xmc->mand_ies[msg_type];
-       /* no mandatory IEs? */
-       if (!ies)
-               return 0;
-
-       for (ie = *ies; ie; ie = *ies++) {
-               if (!xua_msg_find_tag(xua, ie)) {
+       for (ie = ies; ie->tag; ie++) {
+               struct xua_msg_part *part;
+               bool found = false;
+               llist_for_each_entry(part, &xua->headers, entry) {
+                       if (part->tag != ie->tag)
+                               continue;
+                       found = true;
+                       if (part->len < ie->len_min || part->len > ie->len_max) 
{
+                               LOGP(dialect->log_subsys, LOGL_ERROR,
+                                       "%s Message %s:%s IE %s length %" PRIu16
+                                       " out of range [%" PRIu16 ", %" PRIu16 
"]\n",
+                                       dialect->name, xmc->name,
+                                       xua_class_msg_name(xmc, msg_type),
+                                       xua_class_iei_name(xmc, ie->tag),
+                                       part->len, ie->len_min, ie->len_max);
+                               return M3UA_ERR_PARAM_FIELD_ERR;
+                       }
+                       if (!ie->multiple)
+                               break;
+               }
+               if (ie->mandatory && !found) {
                        LOGP(dialect->log_subsys, LOGL_ERROR,
-                               "%s Message %s:%s should "
-                               "contain IE %s, but doesn't\n",
+                               "%s Message %s:%s should contain IE %s, but 
doesn't\n",
                                dialect->name, xmc->name,
                                xua_class_msg_name(xmc, msg_type),
-                               xua_class_iei_name(xmc, ie));
+                               xua_class_iei_name(xmc, ie->tag));
                        return M3UA_ERR_MISSING_PARAM;
                }
        }
@@ -567,6 +575,26 @@
        return 0;
 }

+/* Validate incoming xua_msg. returns 0 on success, M3UA_ERR_* on failure. */
+int xua_dialect_check_all_ies(const struct xua_dialect *dialect, const struct 
xua_msg *xua)
+{
+       uint8_t msg_class = xua->hdr.msg_class;
+       uint8_t msg_type = xua->hdr.msg_type;
+       const struct xua_msg_class *xmc = dialect->class[msg_class];
+       const struct xua_msg_part_class *ies;
+
+       /* unknown class? */
+       if (!xmc)
+               return 0;
+
+       ies = &xmc->ies[msg_type][0];
+       /* no mandatory IEs? */
+       if (!ies)
+               return 0;
+
+       return xua_dialect_check_all_ies_ext(dialect, xmc, msg_type, ies, xua);
+}
+
 char *xua_msg_dump(const struct xua_msg *xua, const struct xua_dialect 
*dialect)
 {
        static char buf[1024];
diff --git a/src/xua_msg.h b/src/xua_msg.h
index dd9551a..3c6a8aa 100644
--- a/src/xua_msg.h
+++ b/src/xua_msg.h
@@ -21,6 +21,8 @@

 #include <osmocom/core/linuxlist.h>
 #include <osmocom/sigtran/mtp_sap.h>
+#include <stdint.h>
+#include <stdint.h>

 #define XUA_HDR(class, type)   ((struct xua_common_hdr) { .spare = 0, 
.msg_class = (class), .msg_type = (type) })

@@ -46,11 +48,35 @@
        /* TODO: keep small data in the struct for perf reasons */
 };

+#define XUA_MSG_PART_CLASS_MAX_LEN UINT16_MAX
+struct xua_msg_part_class {
+       uint16_t tag;
+       bool mandatory;
+       bool multiple; /* whether more than one IE are possible in the msg */
+       uint16_t len_min;
+       uint16_t len_max;
+};
+#define XUA_MSG_PART_CLASS(tag_, mandatory_, multiple_, len_min_, len_max_) \
+       { .tag = (tag_), \
+         .mandatory = (mandatory_), \
+         .multiple = (multiple_), \
+         .len_min = (len_min_), \
+         .len_max = (len_max_) \
+       }
+#define XUA_MSG_PART_CLASS_UNBOUND(tag, mandatory) \
+       XUA_MSG_PART_CLASS((tag), (mandatory), false, 0, 
XUA_MSG_PART_CLASS_MAX_LEN)
+#define XUA_MSG_PART_CLASS_FIXED(tag, mandatory, len) \
+       XUA_MSG_PART_CLASS((tag), (mandatory), false, (len), (len))
+#define XUA_MSG_PART_CLASS_U32(tag, mandatory) \
+       XUA_MSG_PART_CLASS_FIXED((tag), (mandatory), sizeof(uint32_t))
+#define XUA_MSG_PART_CLASS_EOF \
+       XUA_MSG_PART_CLASS(0, false, false, 0, 0)
+
 struct xua_msg_class {
        const char *name;
        const struct value_string *msgt_names;
        const struct value_string *iei_names;
-       const uint16_t *mand_ies[256];
+       const struct xua_msg_part_class *ies[256];
 };

 struct xua_dialect {
@@ -105,7 +131,7 @@
 const char *xua_class_iei_name(const struct xua_msg_class *xmc, uint16_t iei);
 char *xua_hdr_dump(const struct xua_msg *xua, const struct xua_dialect 
*dialect);
 char *xua_msg_dump(const struct xua_msg *xua, const struct xua_dialect 
*dialect);
-int xua_dialect_check_all_mand_ies(const struct xua_dialect *dialect, const 
struct xua_msg *xua);
+int xua_dialect_check_all_ies(const struct xua_dialect *dialect, const struct 
xua_msg *xua);

 int xua_msg_event_map(const struct xua_msg *xua,
                      const struct xua_msg_event_map *maps,

--
To view, visit https://gerrit.osmocom.org/c/libosmo-sigtran/+/43386?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I9b1ae0dbc324123790942c9e6068f6822e3bb957
Gerrit-Change-Number: 43386
Gerrit-PatchSet: 7
Gerrit-Owner: pespin <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: osmith <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to