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]>
