pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/43763?usp=email )
Change subject: sccp: Introduce N-DISCONNECT.req Release/Refusal reason ......................................................................
sccp: Introduce N-DISCONNECT.req Release/Refusal reason
N-DISCONNECT.req has a "Reason" Parameter. the "Reason" Parameter is mandatory according to Table 6/Q.711. The options possible for the "Reason" can be found in ITU Q.711 "6.1.1.2.4 Release phase", and contain no explicit value. That enum is different from the wire-format defined in: * ITU-T Q.713, Section 3.11 Release cause * ITU-T Q.713 Section 3.15 Refusal cause
Actually, ITU-T Q.713 "ANNEX A" describes a mapping between the former (N-DISCONNECT.req Reason) and the later (SCCP Release/Refusal cause).
Use that table to translate as much as possible between the two (despite the mapping is described as being one-to-one, well, it leaves a lot to interpretation due to missing enums, N-to-M mappings, etc.).
Related: OS#2601 Change-Id: I158463c2e9b34abe06554371d628e4fa7ea8c5c1 --- M include/osmocom/sigtran/sccp_sap.h M src/sccp_connection.c M src/sccp_sap.c M src/sccp_scoc.c M src/sccp_scoc_fsm.c M src/sccp_user.h 6 files changed, 422 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/63/43763/1
diff --git a/include/osmocom/sigtran/sccp_sap.h b/include/osmocom/sigtran/sccp_sap.h index 7399b3d..d8ee43e 100644 --- a/include/osmocom/sigtran/sccp_sap.h +++ b/include/osmocom/sigtran/sccp_sap.h @@ -137,6 +137,67 @@ OSMO_SCCP_SSN_BSSAP = 254, };
+/* Q.711 6.1.1.2.3, "Table 5/Q.711" and paragrapgs below it */ +enum osmo_sccp_reset_reason_nsp { + OSMO_SCCP_RESET_REASON_NSP_UNSPEC = 0x0, + OSMO_SCCP_RESET_REASON_NSP_LOCAL_SCCP_ORIGIN, +}; + +enum osmo_sccp_reset_reason_nsu { + OSMO_SCCP_RESET_REASON_NSU_USER_SYNCHRONIZATION = 0x0, +}; + +enum osmo_sccp_reset_reason_undefined { + OSMO_SCCP_RESET_REASON_UNDEFINED = 0x0, +}; + +/* Q.711 6.1.1.2.4 1) When the "originator" parameter indicates the "network service provider" */ +enum osmo_sccp_release_reason_nsp { + OSMO_SCCP_REL_REASON_NSP_DISC_NT = 0x100, + OSMO_SCCP_REL_REASON_NSP_DISC_T, + OSMO_SCCP_REL_REASON_NSP_DISC_INVALID_STATE, + OSMO_SCCP_REL_REASON_NSP_DISC_RELEASE_IN_PROGRESS, + OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT, + OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_NT, + OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_T, + OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_NT, + OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_T, + OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_NT, + OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T, + OSMO_SCCP_REL_REASON_NSP_CREF_LOCAL_ERROR, + OSMO_SCCP_REL_REASON_NSP_CREF_INVALID_STATE, + OSMO_SCCP_REL_REASON_NSP_CREF_NO_TRANSITION, + OSMO_SCCP_REL_REASON_NSP_CREF_IN_RESTART_PHASE, + OSMO_SCCP_REL_REASON_NSP_CREF_HOP_COUNTER_VIOLATION, +}; + +/* Q.711 6.1.1.2.4 2) When the "originator" parameter indicates the "network service user" */ +enum osmo_sccp_release_reason_nsu { + OSMO_SCCP_REL_REASON_NSU_DISC_NORMAL = 0x100, + OSMO_SCCP_REL_REASON_NSU_DISC_ABNORMAL, + OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_CONGESTION, + OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_FAILURE, + OSMO_SCCP_REL_REASON_NSU_DISC_SCCP_USER_ORIGIN, + OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION, + OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE, + OSMO_SCCP_REL_REASON_NSU_DISC_SUBSYS_CONGESTION, + OSMO_SCCP_REL_REASON_NSU_CREF_NT_CONDITION, + OSMO_SCCP_REL_REASON_NSU_CREF_T_CONDITION, + OSMO_SCCP_REL_REASON_NSU_CREF_INCOMPAT_INFO_NSDU, + OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_ORIGIN, + OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_CONGESTION, + OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_FAILURE, + OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED, + OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_CONGESTION, + OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_FAILURE, + OSMO_SCCP_REL_REASON_NSU_CREF_SUBSYS_CONGESTION, +}; + +/* Q.711 6.1.1.2.4 2) When the "originator" parameter indicates the "network service user" */ +enum osmo_sccp_release_reason_undefined { + OSMO_SCCP_REL_REASON_UNDEFINED = 0x100, +}; + /* Q.711 6.3.2.2.5 Signalling point status */ enum osmo_sccp_sp_status { OSMO_SCCP_SP_S_INACCESSIBLE = 1, @@ -222,6 +283,8 @@ struct osmo_scu_disconn_param { enum osmo_sccp_originator originator; struct osmo_sccp_addr responding_addr; + /* enum osmo_sccp_release_reason_* (value > 19), + * enum sccp_refusal_cause (ITU-T Q.713 Section 3.15 Refusal cause) value <= 19, backward compatibility */ uint32_t cause; uint32_t conn_id; uint32_t importance; @@ -231,6 +294,7 @@ /* OSMO_SCU_PRIM_N_RESET */ struct osmo_scu_reset_param { enum osmo_sccp_originator originator; + /* enum osmo_sccp_reset_reason_*, "Table 5/Q.711" and paragraphs below it */ uint32_t cause; uint32_t conn_id; }; diff --git a/src/sccp_connection.c b/src/sccp_connection.c index 10c2760..abf13d0 100644 --- a/src/sccp_connection.c +++ b/src/sccp_connection.c @@ -231,6 +231,7 @@ struct osmo_scu_connect_param *uconp; struct osmo_scu_data_param *udatp; struct xua_msg_part *data_ie; + uint32_t cause;
scu_prim = scu_prim_alloc(primitive, operation);
@@ -243,7 +244,19 @@ udisp->originator = OSMO_SCCP_ORIG_UNDEFINED; //udisp->in_sequence_control; if (xua) { - udisp->cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE); + cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE); + switch (cause & SUA_CAUSE_T_MASK) { + case SUA_CAUSE_T_REFUSAL: + sccp_refusal_cause_to_scu_rel_reason(&udisp->originator, &udisp->cause, cause & 0xff); + break; + case SUA_CAUSE_T_RELEASE: + sccp_release_cause_to_scu_rel_reason(&udisp->originator, &udisp->cause, cause & 0xff); + break; + default: + udisp->originator = OSMO_SCCP_ORIG_UNDEFINED; + udisp->cause = OSMO_SCCP_REL_REASON_UNDEFINED; + break; + } if (xua_msg_find_tag(xua, SUA_IEI_SRC_ADDR)) { if (sua_addr_parse(&udisp->responding_addr, xua, SUA_IEI_SRC_ADDR) < 0) { LOGPSCC(conn, LOGL_ERROR, "XUA Message %s without valid SRC_ADDR\n", diff --git a/src/sccp_sap.c b/src/sccp_sap.c index 00b2563..95d2070 100644 --- a/src/sccp_sap.c +++ b/src/sccp_sap.c @@ -25,6 +25,8 @@
#include <osmocom/sigtran/sccp_sap.h>
+#include <osmocom/sccp/sccp_types.h> + #include "ss7_instance.h" #include "sccp_connection.h" #include "sccp_scoc_fsm.h" @@ -174,6 +176,337 @@ { 0, NULL } };
+/* Table A.1/Q.713 */ +static enum sccp_refusal_cause scu_rel_reason_nsp_to_sccp_refusal_cause(uint32_t reason) +{ + switch (reason) { + case OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT: + return SCCP_REFUSAL_DESTINATION_ADDRESS_UKNOWN; + case OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_NT: + return SCCP_REFUSAL_SUBSYSTEM_FAILURE; + case OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_T: + return SCCP_REFUSAL_DESTINATION_INACCESSIBLE; + case OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_NT: + return SCCP_REFUSAL_NET_QOS_NON_TRANSIENT; + case OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_T: + return SCCP_REFUSAL_NET_QOS_TRANSIENT; + case OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_NT: + return SCCP_REFUSAL_UNQUALIFIED; + case OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T: + return SCCP_REFUSAL_EXPIRATION; + case OSMO_SCCP_REL_REASON_NSP_CREF_HOP_COUNTER_VIOLATION: + return SCCP_REFUSAL_HOP_COUNTER_VIOLATION; + /* Not specified in the table... */ + case OSMO_SCCP_REL_REASON_NSP_DISC_NT: + case OSMO_SCCP_REL_REASON_NSP_DISC_T: + case OSMO_SCCP_REL_REASON_NSP_DISC_INVALID_STATE: + case OSMO_SCCP_REL_REASON_NSP_DISC_RELEASE_IN_PROGRESS: + case OSMO_SCCP_REL_REASON_NSP_CREF_LOCAL_ERROR: + case OSMO_SCCP_REL_REASON_NSP_CREF_INVALID_STATE: + case OSMO_SCCP_REL_REASON_NSP_CREF_NO_TRANSITION: + case OSMO_SCCP_REL_REASON_NSP_CREF_IN_RESTART_PHASE: + default: + return SCCP_REFUSAL_UNQUALIFIED; + } +} + +/* Table A.1/Q.713 */ +static enum sccp_refusal_cause scu_rel_reason_nsu_to_sccp_refusal_cause(uint32_t reason) +{ + switch (reason) { + case OSMO_SCCP_REL_REASON_NSU_CREF_INCOMPAT_INFO_NSDU: + return SCCP_REFUSAL_INCOMPATIBLE_USER_DATA; + case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_ORIGIN: + return SCCP_REFUSAL_END_USER_ORIGINATED; + case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_CONGESTION: + return SCCP_REFUSAL_END_USER_CONGESTION; + case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_FAILURE: + return SCCP_REFUSAL_END_USER_FAILURE; + case OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED: + return SCCP_REFUSAL_SCCP_USER_ORIGINATED; + case OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_CONGESTION: + return SCCP_REFUSAL_ACCESS_CONGESTION; + case OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_FAILURE: + return SCCP_REFUSAL_ACCESS_FAILURE; + case OSMO_SCCP_REL_REASON_NSU_CREF_SUBSYS_CONGESTION: + return SCCP_REFUSAL_SUBSYTEM_CONGESTION; + /* Not specified in the table... */ + case OSMO_SCCP_REL_REASON_NSU_DISC_NORMAL: + case OSMO_SCCP_REL_REASON_NSU_DISC_ABNORMAL: + case OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_CONGESTION: + case OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_FAILURE: + case OSMO_SCCP_REL_REASON_NSU_DISC_SCCP_USER_ORIGIN: + case OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION: + case OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE: + case OSMO_SCCP_REL_REASON_NSU_DISC_SUBSYS_CONGESTION: + case OSMO_SCCP_REL_REASON_NSU_CREF_NT_CONDITION: + case OSMO_SCCP_REL_REASON_NSU_CREF_T_CONDITION: + default: + return SCCP_REFUSAL_UNQUALIFIED; + } +} + +/* Table A.1/Q.713 */ +enum sccp_refusal_cause scu_rel_reason_to_sccp_refusal_cause(enum osmo_sccp_originator originator, uint32_t reason) +{ + if (reason <= SCCP_REFUSAL_UNEQUIPPED_USER) /* direct wire-format as backward compatibility */ + return (enum sccp_refusal_cause)reason; + + switch (originator) { + case OSMO_SCCP_ORIG_NS_PROVIDER: + return scu_rel_reason_nsp_to_sccp_refusal_cause(reason); + case OSMO_SCCP_ORIG_NS_USER: + return scu_rel_reason_nsu_to_sccp_refusal_cause(reason); + case OSMO_SCCP_ORIG_UNDEFINED: + default: + return SCCP_REFUSAL_UNQUALIFIED; + } +} + +/* Table A.1/Q.713 */ +void sccp_refusal_cause_to_scu_rel_reason(enum osmo_sccp_originator *originator, uint32_t *reason, uint32_t sccp_cause) +{ + switch (sccp_cause) { + case SCCP_REFUSAL_END_USER_ORIGINATED: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_ORIGIN; + break; + case SCCP_REFUSAL_END_USER_CONGESTION: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_CONGESTION; + break; + case SCCP_REFUSAL_END_USER_FAILURE: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_FAILURE; + break; + case SCCP_REFUSAL_SCCP_USER_ORIGINATED: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED; + break; + case SCCP_REFUSAL_DESTINATION_ADDRESS_UKNOWN: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT; + break; + case SCCP_REFUSAL_DESTINATION_INACCESSIBLE: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_T; + break; + case SCCP_REFUSAL_NET_QOS_NON_TRANSIENT: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_NT; + break; + case SCCP_REFUSAL_NET_QOS_TRANSIENT: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_T; + break; + case SCCP_REFUSAL_ACCESS_FAILURE: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE; + break; + case SCCP_REFUSAL_ACCESS_CONGESTION: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION; + break; + case SCCP_REFUSAL_SUBSYSTEM_FAILURE: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_NT; + break; + case SCCP_REFUSAL_SUBSYTEM_CONGESTION: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_CREF_SUBSYS_CONGESTION; + break; + case SCCP_REFUSAL_EXPIRATION: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T; + break; + case SCCP_REFUSAL_INCOMPATIBLE_USER_DATA: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_CREF_INCOMPAT_INFO_NSDU; + break; + case SCCP_REFUSAL_UNQUALIFIED: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T; + break; + case SCCP_REFUSAL_HOP_COUNTER_VIOLATION: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_HOP_COUNTER_VIOLATION; + break; + case SCCP_REFUSAL_NO_TRANS_FOR_ADDRESS_NATURE: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT; + break; + case SCCP_REFUSAL_UNEQUIPPED_USER: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT; + break; + /* Not specified in table... */ + case SCCP_REFUSAL_RESERVED: + case SCCP_REFUSAL_SCCP_FAILURE: + default: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_NT; + break; + } +} + + +/* Table A.2/Q.713 */ +static enum sccp_release_cause scu_rel_reason_nsp_to_sccp_release_cause(uint32_t reason) +{ + switch (reason) { + case OSMO_SCCP_REL_REASON_NSP_DISC_NT: + return SCCP_RELEASE_CAUSE_SUBSYSTEM_FAILURE; + case OSMO_SCCP_REL_REASON_NSP_DISC_T: + return SCCP_RELEASE_CAUSE_REMOTE_PROCEDURE_ERROR; + /* Not specified in the table... */ + case OSMO_SCCP_REL_REASON_NSP_DISC_INVALID_STATE: + case OSMO_SCCP_REL_REASON_NSP_DISC_RELEASE_IN_PROGRESS: + case OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT: + case OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_NT: + case OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_T: + case OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_NT: + case OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_T: + case OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_NT: + case OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T: + case OSMO_SCCP_REL_REASON_NSP_CREF_LOCAL_ERROR: + case OSMO_SCCP_REL_REASON_NSP_CREF_INVALID_STATE: + case OSMO_SCCP_REL_REASON_NSP_CREF_NO_TRANSITION: + case OSMO_SCCP_REL_REASON_NSP_CREF_IN_RESTART_PHASE: + case OSMO_SCCP_REL_REASON_NSP_CREF_HOP_COUNTER_VIOLATION: + default: + return SCCP_RELEASE_CAUSE_UNQUALIFIED; + } +} + +/* Table A.2/Q.713 */ +static enum sccp_release_cause scu_rel_reason_nsu_to_sccp_release_cause(uint32_t reason) +{ + switch (reason) { + case OSMO_SCCP_REL_REASON_NSU_DISC_NORMAL: + return SCCP_RELEASE_CAUSE_END_USER_ORIGINATED; + case OSMO_SCCP_REL_REASON_NSU_DISC_ABNORMAL: + return SCCP_RELEASE_CAUSE_UNQUALIFIED; + case OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_CONGESTION: + return SCCP_RELEASE_CAUSE_END_USER_CONGESTION; + case OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_FAILURE: + return SCCP_RELEASE_CAUSE_END_USER_FAILURE; + case OSMO_SCCP_REL_REASON_NSU_DISC_SCCP_USER_ORIGIN: + return SCCP_RELEASE_CAUSE_SCCP_USER_ORIGINATED; + case OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION: + return SCCP_RELEASE_CAUSE_ACCESS_CONGESTION; + case OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE: + return SCCP_RELEASE_CAUSE_ACCESS_FAILURE; + case OSMO_SCCP_REL_REASON_NSU_CREF_SUBSYS_CONGESTION: + return SCCP_RELEASE_CAUSE_SUBSYSTEM_CONGESTION; + /* Not specified in the table... */ + case OSMO_SCCP_REL_REASON_NSU_DISC_SUBSYS_CONGESTION: + case OSMO_SCCP_REL_REASON_NSU_CREF_NT_CONDITION: + case OSMO_SCCP_REL_REASON_NSU_CREF_T_CONDITION: + case OSMO_SCCP_REL_REASON_NSU_CREF_INCOMPAT_INFO_NSDU: + case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_ORIGIN: + case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_CONGESTION: + case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_FAILURE: + case OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED: + case OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_CONGESTION: + case OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_FAILURE: + default: + return SCCP_RELEASE_CAUSE_UNQUALIFIED; + } +} + +/* Table A.2/Q.713 */ +enum sccp_release_cause scu_rel_reason_to_sccp_release_cause(enum osmo_sccp_originator originator, uint32_t reason) +{ + if (reason <= SCCP_RELEASE_CAUSE_SCCP_FAILURE) /* direct wire-format as backward compatibility */ + return (enum sccp_refusal_cause)reason; + + switch (originator) { + case OSMO_SCCP_ORIG_NS_PROVIDER: + return scu_rel_reason_nsp_to_sccp_release_cause(reason); + case OSMO_SCCP_ORIG_NS_USER: + return scu_rel_reason_nsu_to_sccp_release_cause(reason); + case OSMO_SCCP_ORIG_UNDEFINED: + default: + return SCCP_RELEASE_CAUSE_UNQUALIFIED; + } +} + +void sccp_release_cause_to_scu_rel_reason(enum osmo_sccp_originator *originator, uint32_t *reason, uint32_t sccp_cause) +{ + switch (sccp_cause) { + case SCCP_RELEASE_CAUSE_END_USER_ORIGINATED: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_NORMAL; + break; + case SCCP_RELEASE_CAUSE_END_USER_CONGESTION: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_CONGESTION; + break; + case SCCP_RELEASE_CAUSE_END_USER_FAILURE: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_FAILURE; + break; + case SCCP_RELEASE_CAUSE_SCCP_USER_ORIGINATED: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED; + break; + case SCCP_RELEASE_CAUSE_REMOTE_PROCEDURE_ERROR: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T; + break; + case SCCP_RELEASE_CAUSE_INCONSISTENT_CONN_DATA: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T; + break; + case SCCP_RELEASE_CAUSE_ACCESS_FAILURE: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE; + break; + case SCCP_RELEASE_CAUSE_ACCESS_CONGESTION: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION; + break; + case SCCP_RELEASE_CAUSE_SUBSYSTEM_FAILURE: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_NT; + break; + case SCCP_RELEASE_CAUSE_SUBSYSTEM_CONGESTION: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_SUBSYS_CONGESTION; + break; + case SCCP_RELEASE_CAUSE_MTP_FAILURE: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_NT; + break; + case SCCP_RELEASE_CAUSE_NETWORK_CONGESTION: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T; + break; + case SCCP_RELEASE_CAUSE_EXPIRATION_RESET: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T; + break; + case SCCP_RELEASE_CAUSE_EXPIRATION_INACTIVE: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T; + break; + case SCCP_RELEASE_CAUSE_UNQUALIFIED: + *originator = OSMO_SCCP_ORIG_NS_USER; + *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ABNORMAL; + break; + case SCCP_RELEASE_CAUSE_SCCP_FAILURE: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_NT; + break; + case SCCP_RELEASE_CAUSE_RESERVED: + default: + *originator = OSMO_SCCP_ORIG_NS_PROVIDER; + *reason = OSMO_SCCP_REL_REASON_NSP_DISC_NT; + break; + } +} + + /* get the Connection ID of the given SCU primitive */ static uint32_t scu_prim_conn_id(const struct osmo_scu_prim *prim) { diff --git a/src/sccp_scoc.c b/src/sccp_scoc.c index 817f785..bbc4ed6 100644 --- a/src/sccp_scoc.c +++ b/src/sccp_scoc.c @@ -338,7 +338,7 @@ xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx); xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref); xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->conn_id); - xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_RELEASE | prim->u.disconnect.cause); + xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_RELEASE | scu_rel_reason_to_sccp_release_cause(prim->u.disconnect.originator, prim->u.disconnect.cause)); /* optional: data */ if (encode_opt_data) xua_msg_add_data(xua, SUA_IEI_DATA, msgb_l2len(prim->oph.msg), msgb_l2(prim->oph.msg)); @@ -373,8 +373,7 @@ xua->hdr = XUA_HDR(SUA_MSGC_CO, SUA_CO_COREF); xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx); xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref); - //xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_REFUSAL | prim->u.disconnect.cause); - xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_REFUSAL | SCCP_REFUSAL_UNEQUIPPED_USER); + xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_REFUSAL | scu_rel_reason_to_sccp_refusal_cause(prim->u.disconnect.originator, prim->u.disconnect.cause)); /* optional: source addr */ if (conn->called_addr.presence) xua_msg_add_sccp_addr(xua, SUA_IEI_SRC_ADDR, &conn->called_addr); diff --git a/src/sccp_scoc_fsm.c b/src/sccp_scoc_fsm.c index 1833b89..895435c 100644 --- a/src/sccp_scoc_fsm.c +++ b/src/sccp_scoc_fsm.c @@ -225,7 +225,8 @@ switch (event) { case SCOC_E_SCU_N_DISC_REQ: prim = data; - conn->release_cause = prim->u.disconnect.cause; + conn->release_cause = scu_rel_reason_to_sccp_release_cause(prim->u.disconnect.originator, + prim->u.disconnect.cause); osmo_fsm_inst_state_chg(fi, S_WAIT_CONN_CONF, 0, 0); /* keep conn timer running(!) */ break; diff --git a/src/sccp_user.h b/src/sccp_user.h index 47c8aa4..cb8ec90 100644 --- a/src/sccp_user.h +++ b/src/sccp_user.h @@ -8,6 +8,8 @@ #include <osmocom/sigtran/sccp_sap.h>
struct osmo_sccp_instance; +enum sccp_refusal_cause; +enum osmo_sccp_originator;
struct osmo_sccp_user { /*! \brief entry in list of sccp users of \ref osmo_sccp_instance */ @@ -38,6 +40,11 @@
int sccp_user_prim_up(struct osmo_sccp_user *scut, struct osmo_scu_prim *prim);
+enum sccp_refusal_cause scu_rel_reason_to_sccp_refusal_cause(enum osmo_sccp_originator originator, uint32_t reason); +enum sccp_release_cause scu_rel_reason_to_sccp_release_cause(enum osmo_sccp_originator originator, uint32_t reason); +void sccp_refusal_cause_to_scu_rel_reason(enum osmo_sccp_originator *originator, uint32_t *reason, uint32_t sccp_cause); +void sccp_release_cause_to_scu_rel_reason(enum osmo_sccp_originator *originator, uint32_t *reason, uint32_t sccp_cause); + #define _LOGPSCU(scu, subsys, level, fmt, args ...) \ _LOGPSCI((scu)->inst, subsys, level, "SCU(%s) " fmt, osmo_sccp_user_name(scu), ## args) #define LOGPSCU(scu, level, fmt, args ...) \