diff options
author | Harald Welte <laforge@osmocom.org> | 2021-10-26 09:59:12 +0200 |
---|---|---|
committer | Harald Welte <laforge@osmocom.org> | 2021-10-26 16:27:14 +0200 |
commit | 8aa64eb92a3b147d7184020695d51b440662aa0d (patch) | |
tree | 7f69a5ad34b4685110e51fe249c0847ea93116e9 | |
parent | 8275949838ac29de300b8698fc8bfa7c5ff7a29e (diff) |
sccp: Add minimalistic support for XUDT / XUDTS
XUDT and XUDTS can be used in two situations:
a) because the sender wants to use segmentation
b) because the sender wants to include a hop counter
In this patch, we implement support for case "b" only.
Change-Id: Ic5b9486f1aeb4bb90cfe702a7ce996f5d82ded2c
Related: OS#5281, SYS#5674
-rw-r--r-- | include/osmocom/sccp/sccp_types.h | 6 | ||||
-rw-r--r-- | src/sccp2sua.c | 106 |
2 files changed, 110 insertions, 2 deletions
diff --git a/include/osmocom/sccp/sccp_types.h b/include/osmocom/sccp/sccp_types.h index 616a7ee..4ad7edf 100644 --- a/include/osmocom/sccp/sccp_types.h +++ b/include/osmocom/sccp/sccp_types.h @@ -446,6 +446,9 @@ struct sccp_data_ext_unitdata { data #endif + /* optional */ + uint8_t optional_start; + #if OPTIONAL segmentation importance @@ -475,6 +478,9 @@ struct sccp_data_ext_unitdata_service { data #endif + /* optional */ + uint8_t optional_start; + #if OPTIONAL segmentation importancd diff --git a/src/sccp2sua.c b/src/sccp2sua.c index c937231..51fe00b 100644 --- a/src/sccp2sua.c +++ b/src/sccp2sua.c @@ -1200,9 +1200,16 @@ static struct xua_msg *sccp_to_xua_udt(struct msgb *msg, struct xua_msg *xua) } +static int sua_to_sccp_xudt(struct msgb *msg, struct xua_msg *xua); + static int sua_to_sccp_udt(struct msgb *msg, struct xua_msg *xua) { struct sccp_data_unitdata *udt; + + /* Use XUDT if we have a hop counter on the SUA side */ + if (xua_msg_find_tag(xua, SUA_IEI_S7_HOP_CTR)) + return sua_to_sccp_xudt(msg, xua); + udt = (struct sccp_data_unitdata *) msgb_put(msg, sizeof(*udt)); /* Fixed Part */ @@ -1216,6 +1223,46 @@ static int sua_to_sccp_udt(struct msgb *msg, struct xua_msg *xua) } /*! \returns \ref xua in case of success, NULL on error (xua not freed!) */ +static struct xua_msg *sccp_to_xua_xudt(struct msgb *msg, struct xua_msg *xua) +{ + struct sccp_data_ext_unitdata *xudt = (struct sccp_data_ext_unitdata *)msg->l2h; + + /* Fixed Part */ + xua_msg_add_u32(xua, SUA_IEI_PROTO_CLASS, xudt->proto_class); + xua_msg_add_u32(xua, SUA_IEI_S7_HOP_CTR, xudt->hop_counter); + /* Variable Part */ + if (!sccp_ptr_part_consistent(msg, &xudt->variable_called)) + return NULL; + sccp_addr_to_sua_ptr(xua, SUA_IEI_DEST_ADDR, msg, &xudt->variable_called); + if (!sccp_ptr_part_consistent(msg, &xudt->variable_calling)) + return NULL; + sccp_addr_to_sua_ptr(xua, SUA_IEI_SRC_ADDR, msg, &xudt->variable_calling); + if (!sccp_ptr_part_consistent(msg, &xudt->variable_data)) + return NULL; + sccp_data_to_sua_ptr(xua, SUA_IEI_DATA, msg, &xudt->variable_data); + /* Optional Part */ + return sccp_to_xua_opt(msg, &xudt->optional_start, xua); + +} + +static int sua_to_sccp_xudt(struct msgb *msg, struct xua_msg *xua) +{ + struct sccp_data_ext_unitdata *xudt; + xudt = (struct sccp_data_ext_unitdata *) msgb_put(msg, sizeof(*xudt)); + + /* Fixed Part */ + xudt->type = SCCP_MSG_TYPE_XUDT; + xudt->proto_class = xua_msg_get_u32(xua, SUA_IEI_PROTO_CLASS); + xudt->hop_counter = xua_msg_get_u32(xua, SUA_IEI_S7_HOP_CTR); + /* Variable Part */ + sccp_add_var_addr(msg, &xudt->variable_called, xua, SUA_IEI_DEST_ADDR); + sccp_add_var_addr(msg, &xudt->variable_calling, xua, SUA_IEI_SRC_ADDR); + sccp_add_variable_part(msg, &xudt->variable_data, xua, SUA_IEI_DATA); + /* Optional Part */ + return xua_ies_to_sccp_opts(msg, &xudt->optional_start, xudt->type, xua); +} + +/*! \returns \ref xua in case of success, NULL on error (xua not freed!) */ static struct xua_msg *sccp_to_xua_udts(struct msgb *msg, struct xua_msg *xua) { struct sccp_data_unitdata_service *udts; @@ -1237,9 +1284,16 @@ static struct xua_msg *sccp_to_xua_udts(struct msgb *msg, struct xua_msg *xua) } +static int sua_to_sccp_xudts(struct msgb *msg, struct xua_msg *xua); + static int sua_to_sccp_udts(struct msgb *msg, struct xua_msg *xua) { struct sccp_data_unitdata_service *udts; + + /* Use XUDTS if we have a hop counter */ + if (xua_msg_find_tag(xua, SUA_IEI_S7_HOP_CTR)) + return sua_to_sccp_xudts(msg, xua); + udts = (struct sccp_data_unitdata_service *) msgb_put(msg, sizeof(*udts)); /* Fixed Part */ @@ -1253,6 +1307,46 @@ static int sua_to_sccp_udts(struct msgb *msg, struct xua_msg *xua) } /*! \returns \ref xua in case of success, NULL on error (xua not freed!) */ +static struct xua_msg *sccp_to_xua_xudts(struct msgb *msg, struct xua_msg *xua) +{ + struct sccp_data_ext_unitdata_service *xudts; + xudts = (struct sccp_data_ext_unitdata_service *)msg->l2h; + + /* Fixed Part */ + xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_RETURN | xudts->return_cause); + xua_msg_add_u32(xua, SUA_IEI_S7_HOP_CTR, xudts->hop_counter); + /* Variable Part */ + if (!sccp_ptr_part_consistent(msg, &xudts->variable_called)) + return NULL; + sccp_addr_to_sua_ptr(xua, SUA_IEI_DEST_ADDR, msg, &xudts->variable_called); + if (!sccp_ptr_part_consistent(msg, &xudts->variable_calling)) + return NULL; + sccp_addr_to_sua_ptr(xua, SUA_IEI_SRC_ADDR, msg, &xudts->variable_calling); + if (!sccp_ptr_part_consistent(msg, &xudts->variable_data)) + return NULL; + sccp_data_to_sua_ptr(xua, SUA_IEI_DATA, msg, &xudts->variable_data); + /* Optional Part */ + return sccp_to_xua_opt(msg, &xudts->optional_start, xua); +} + +static int sua_to_sccp_xudts(struct msgb *msg, struct xua_msg *xua) +{ + struct sccp_data_ext_unitdata_service *xudts; + xudts = (struct sccp_data_ext_unitdata_service *) msgb_put(msg, sizeof(*xudts)); + + /* Fixed Part */ + xudts->type = SCCP_MSG_TYPE_XUDTS; + xudts->return_cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE) & 0xff; + xudts->hop_counter = xua_msg_get_u32(xua, SUA_IEI_S7_HOP_CTR); + /* Variable Part */ + sccp_add_var_addr(msg, &xudts->variable_called, xua, SUA_IEI_DEST_ADDR); + sccp_add_var_addr(msg, &xudts->variable_calling, xua, SUA_IEI_SRC_ADDR); + sccp_add_variable_part(msg, &xudts->variable_data, xua, SUA_IEI_DATA); + /* Optional Part */ + return xua_ies_to_sccp_opts(msg, &xudts->optional_start, xudts->type, xua); +} + +/*! \returns \ref xua in case of success, NULL on error (xua not freed!) */ static struct xua_msg *sccp_to_xua_it(struct msgb *msg, struct xua_msg *xua) { struct sccp_data_it *it = (struct sccp_data_it *)msg->l2h; @@ -1376,6 +1470,16 @@ struct xua_msg *osmo_sccp_to_xua(struct msgb *msg) if (!sccp_to_xua_err(msg, xua)) goto malformed; return xua; + case SCCP_MSG_TYPE_XUDT: + xua->hdr = XUA_HDR(SUA_MSGC_CL, SUA_CL_CLDT); + if (!sccp_to_xua_xudt(msg, xua)) + goto malformed; + return xua; + case SCCP_MSG_TYPE_XUDTS: + xua->hdr = XUA_HDR(SUA_MSGC_CL, SUA_CL_CLDR); + if (!sccp_to_xua_xudts(msg, xua)) + goto malformed; + return xua; /* Unsupported Message Types */ case SCCP_MSG_TYPE_DT2: case SCCP_MSG_TYPE_AK: @@ -1383,8 +1487,6 @@ struct xua_msg *osmo_sccp_to_xua(struct msgb *msg) case SCCP_MSG_TYPE_EA: case SCCP_MSG_TYPE_RSR: case SCCP_MSG_TYPE_RSC: - case SCCP_MSG_TYPE_XUDT: - case SCCP_MSG_TYPE_XUDTS: case SCCP_MSG_TYPE_LUDT: case SCCP_MSG_TYPE_LUDTS: LOGP(DLSUA, LOGL_ERROR, "Unsupported SCCP message %s\n", |