pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/42117?usp=email )
(
2 is the latest approved patch-set. No files were changed between the latest approved patch-set and the submitted one. )Change subject: xua_asp_fsm: Error on ASP UP (ACK) with non-unique ASP Identifier ......................................................................
xua_asp_fsm: Error on ASP UP (ACK) with non-unique ASP Identifier
Following RFC4666: """ The "Invalid ASP Identifier" error is sent by an SGP in response to an ASP Up message with an invalid (i.e., non-unique) ASP Identifier """
Change-Id: I2d422acaa2f04c7d1eebd92c3185c4f5476a1789 --- M src/ss7_as.c M src/ss7_as.h M src/ss7_asp.c M src/ss7_asp.h M src/xua_asp_fsm.c 5 files changed, 60 insertions(+), 4 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve
diff --git a/src/ss7_as.c b/src/ss7_as.c index 1cc212f..a25e068 100644 --- a/src/ss7_as.c +++ b/src/ss7_as.c @@ -378,6 +378,29 @@ return !!ss7_as_asp_assoc_find(as, asp); }
+/*! \brief Find ASP with a given announced remote ASP Id + * \param[in] as Application Server in which to look for \ref asp + * \param[in] asp_id M3UA/SUA ASP Identifier + * \param[in] excl_asp If not NULL, skip this asp from the candidates. + * \returns the asp object if found, NULL otherwise */ +struct osmo_ss7_asp *ss7_as_find_asp_by_remote_asp_id(const struct osmo_ss7_as *as, uint32_t asp_id, + const struct osmo_ss7_asp *excl_asp) +{ + struct ss7_as_asp_assoc *assoc; + + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + struct osmo_ss7_asp *asp = assoc->asp; + if (!asp->remote_asp_id_present) + continue; + if (assoc->asp->remote_asp_id != asp_id) + continue; + if (excl_asp == assoc->asp) + continue; + return asp; + } + return NULL; +} + /* Determine which role (SG/ASP/IPSP) we operate in. * return enum osmo_ss7_asp_role on success, negative otherwise. */ int ss7_as_get_local_role(const struct osmo_ss7_as *as) diff --git a/src/ss7_as.h b/src/ss7_as.h index 2e7f484..793cb26 100644 --- a/src/ss7_as.h +++ b/src/ss7_as.h @@ -183,6 +183,8 @@ int ss7_as_add_asp(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp); int ss7_as_del_asp(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp); int ss7_as_get_local_role(const struct osmo_ss7_as *as); +struct osmo_ss7_asp *ss7_as_find_asp_by_remote_asp_id(const struct osmo_ss7_as *as, uint32_t asp_id, + const struct osmo_ss7_asp *excl_asp); void ss7_as_loadshare_binding_table_reset(struct osmo_ss7_as *as);
void ss7_as_del_asp_update_llist_round_robin(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp, struct ss7_as_asp_assoc **state); diff --git a/src/ss7_asp.c b/src/ss7_asp.c index 9b8f164..40433d0 100644 --- a/src/ss7_asp.c +++ b/src/ss7_asp.c @@ -1623,6 +1623,17 @@ return tmode; }
+bool ss7_asp_check_remote_asp_id_unique(const struct osmo_ss7_asp *asp, uint32_t remote_asp_id) +{ + const struct ss7_as_asp_assoc *assoc; + + llist_for_each_entry(assoc, &asp->assoc_as_list, asp_entry) { + if (ss7_as_find_asp_by_remote_asp_id(assoc->as, remote_asp_id, asp)) + return false; + } + return true; +} + /* process a primitive from the xUA Layer Manager (LM) */ int osmo_xlm_sap_down(struct osmo_ss7_asp *asp, struct osmo_prim_hdr *oph) { diff --git a/src/ss7_asp.h b/src/ss7_asp.h index 75be6cc..7bce2d4 100644 --- a/src/ss7_asp.h +++ b/src/ss7_asp.h @@ -196,6 +196,7 @@ struct osmo_ss7_as *ss7_asp_get_first_as(const struct osmo_ss7_asp *asp);
int ss7_asp_determine_traf_mode(const struct osmo_ss7_asp *asp); +bool ss7_asp_check_remote_asp_id_unique(const struct osmo_ss7_asp *asp, uint32_t remote_asp_id);
#define LOGPASP(asp, subsys, level, fmt, args ...) \ _LOGSS7((asp)->inst, subsys, level, "ASP(%s) " fmt, (asp)->cfg.name, ## args) diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c index 34419a4..26247cb 100644 --- a/src/xua_asp_fsm.c +++ b/src/xua_asp_fsm.c @@ -468,6 +468,7 @@ dispatch_to_all_as(asp->fi, XUA_ASPAS_ASP_DOWN_IND, asp);
/* Implicit clean up tasks: */ + asp->remote_asp_id_present = false; llist_for_each_entry_safe(assoc, assoc2, &asp->assoc_as_list, asp_entry) { struct osmo_ss7_as *as = assoc->as; #ifdef WITH_TCAP_LOADSHARING @@ -526,6 +527,7 @@ struct xua_asp_fsm_priv *xafp = fi->priv; struct osmo_ss7_asp *asp = xafp->asp; struct xua_msg_part *asp_id_ie; + uint32_t asp_id;
check_stop_t_ack(fi, event);
@@ -539,7 +541,12 @@ ENSURE_ASP_OR_IPSP(fi, event); /* Optional ASP Identifier */ if ((asp_id_ie = xua_msg_find_tag(data, SUA_IEI_ASP_ID))) { - asp->remote_asp_id = xua_msg_part_get_u32(asp_id_ie); + asp_id = xua_msg_part_get_u32(asp_id_ie); + if (!ss7_asp_check_remote_asp_id_unique(asp, asp_id)) { + peer_send_error(fi, M3UA_ERR_INVAL_ASP_ID); + return; + } + asp->remote_asp_id = asp_id; asp->remote_asp_id_present = true; } osmo_fsm_inst_state_chg(fi, XUA_ASP_S_INACTIVE, 0, 0); @@ -548,9 +555,15 @@ break; case XUA_ASP_E_ASPSM_ASPUP: ENSURE_SG_OR_IPSP(fi, event); - /* Optional ASP Identifier: Store for NTFY */ + /* Optional ASP Identifier */ if ((asp_id_ie = xua_msg_find_tag(data, SUA_IEI_ASP_ID))) { - asp->remote_asp_id = xua_msg_part_get_u32(asp_id_ie); + asp_id = xua_msg_part_get_u32(asp_id_ie); + if (!ss7_asp_check_remote_asp_id_unique(asp, asp_id)) { + peer_send_error(fi, M3UA_ERR_INVAL_ASP_ID); + return; + } + /* Store for NTFY */ + asp->remote_asp_id = asp_id; asp->remote_asp_id_present = true; } /* send ACK */ @@ -606,6 +619,7 @@ struct xua_msg *xua_in; uint32_t traf_mode = 0; struct xua_msg_part *part; + uint32_t asp_id; int i;
check_stop_t_ack(fi, event); @@ -623,7 +637,12 @@ ENSURE_IPSP(fi, event); /* Optional ASP Identifier */ if ((asp_id_ie = xua_msg_find_tag(data, SUA_IEI_ASP_ID))) { - asp->remote_asp_id = xua_msg_part_get_u32(asp_id_ie); + asp_id = xua_msg_part_get_u32(asp_id_ie); + if (!ss7_asp_check_remote_asp_id_unique(asp, asp_id)) { + peer_send_error(fi, M3UA_ERR_INVAL_ASP_ID); + return; + } + asp->remote_asp_id = asp_id; asp->remote_asp_id_present = true; } /* inform layer manager */