laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/41524?usp=email )
Change subject: mtp3: Implement RTPC transfer prohibited to concerned SP or STP ......................................................................
mtp3: Implement RTPC transfer prohibited to concerned SP or STP
Send Transfer prohibited (DUNA in M3UA) to originator upon trying to route message to inaccessible DPC, as explained in Q.704 Figure 44 and section 13.2.
Related: OS#6892 Change-Id: I7e89db3d82374ca03a2e71fb558c7cec9bd651c4 --- M src/Makefile.am M src/m3ua.c M src/mtp3_hmrt.c A src/mtp3_rtpc.c A src/mtp3_rtpc.h M src/xua_internal.h 6 files changed, 155 insertions(+), 5 deletions(-)
Approvals: Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve laforge: Looks good to me, approved daniel: Looks good to me, but someone else must approve
diff --git a/src/Makefile.am b/src/Makefile.am index 29cf10a..f51819e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,6 +6,7 @@ mtp3_hmdc.h \ mtp3_hmdt.h \ mtp3_hmrt.h \ + mtp3_rtpc.h \ sccp_connection.h \ sccp_scoc_fsm.h \ sccp_instance.h \ @@ -53,6 +54,7 @@ mtp3_hmdc.c \ mtp3_hmdt.c \ mtp3_hmrt.c \ + mtp3_rtpc.c \ sccp2sua.c \ sccp_connection.c \ sccp_helpers.c \ diff --git a/src/m3ua.c b/src/m3ua.c index 36018e1..2b7c1e7 100644 --- a/src/m3ua.c +++ b/src/m3ua.c @@ -864,9 +864,9 @@ ***********************************************************************/
/* 3.4.1 Destination Unavailable (DUNA) */ -static struct xua_msg *m3ua_encode_duna(const uint32_t *rctx, unsigned int num_rctx, - const uint32_t *aff_pc, unsigned int num_aff_pc, - const char *info_string) +struct xua_msg *m3ua_encode_duna(const uint32_t *rctx, unsigned int num_rctx, + const uint32_t *aff_pc, unsigned int num_aff_pc, + const char *info_string) { struct xua_msg *xua = xua_msg_alloc();
diff --git a/src/mtp3_hmrt.c b/src/mtp3_hmrt.c index 9ab7e33..25b2bc4 100644 --- a/src/mtp3_hmrt.c +++ b/src/mtp3_hmrt.c @@ -36,6 +36,7 @@ #include <osmocom/sigtran/protocol/m3ua.h>
#include "mtp3_hmdc.h" +#include "mtp3_rtpc.h" #include "xua_internal.h" #include "ss7_as.h" #include "ss7_asp.h" @@ -111,8 +112,9 @@ } else { LOGSS7(inst, LOGL_ERROR, "MTP-TRANSFER.req for dpc=%u=%s: no route!\n", dpc, osmo_ss7_pointcode_print(inst, dpc)); - /* DPC unknown HMRT -> MGMT */ - /* Message Received for inaccesible SP HMRT ->RTPC */ + /* "Message received for unknown SP HMRT -> MGMT"*/ + /* "Message received for inaccessible SP HMRT -> RTPC" */ + mtp3_rtpc_rx_msg_for_inaccessible_sp(inst, xua); /* Discard Message */ } xua_msg_free(xua); diff --git a/src/mtp3_rtpc.c b/src/mtp3_rtpc.c new file mode 100644 index 0000000..1ce5c25 --- /dev/null +++ b/src/mtp3_rtpc.c @@ -0,0 +1,131 @@ +/*********************************************************************** + * MTP Level 3 - Transfer prohibited control (RTPC), ITU Q.704 Figure 44 + ***********************************************************************/ + +/* (C) 2025 by sysmocom s.f.m.c. GmbH info@sysmocom.de + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +#include <stdint.h> + +#include <osmocom/sigtran/protocol/m3ua.h> +#include <osmocom/sigtran/osmo_ss7.h> + +#include "mtp3_hmdt.h" +#include "mtp3_rtpc.h" +#include "ss7_as.h" +#include "ss7_internal.h" +#include "ss7_route.h" +#include "ss7_route_table.h" +#include "xua_internal.h" +#include "xua_msg.h" + +/* Generate a DUNA message to be sent back to originator. */ +static struct xua_msg *gen_duna_ret_msg(struct osmo_ss7_instance *inst, const struct xua_msg *orig_xua) +{ + struct xua_msg *xua; + struct xua_msg_part *rctx_ie; + unsigned int num_rctx = 0; + uint32_t rctx = 0; + uint32_t aff_pc = htonl(orig_xua->mtp.dpc); + + if ((rctx_ie = xua_msg_find_tag(orig_xua, M3UA_IEI_ROUTE_CTX))) { + rctx = xua_msg_part_get_u32(rctx_ie); + num_rctx = 1; + } + xua = m3ua_encode_duna(&rctx, num_rctx, &aff_pc, 1, + "transfer prohibited (inaccessible SP)"); + OSMO_ASSERT(xua); + + xua->mtp = orig_xua->mtp; + xua->mtp.opc = orig_xua->mtp.dpc; + xua->mtp.dpc = orig_xua->mtp.opc; + return xua; +} + + /* Figure 44/Q.704 (sheet 1 of 3), "Message received for inaccessible SP HMRT -> RTPC" */ +int mtp3_rtpc_rx_msg_for_inaccessible_sp(struct osmo_ss7_instance *inst, const struct xua_msg *orig_xua) +{ + struct xua_msg *xua; + char buf_orig_opc[MAX_PC_STR_LEN]; + char buf_orig_dpc[MAX_PC_STR_LEN]; + struct osmo_ss7_route_label rtlabel; + struct osmo_ss7_route *rt; + + /* TODO: Start T8 */ + + /* "transfer prohibited RTPC -> HMRT", "To concerned SP or STP". + * See also Q.704 13.2 Transfer-prohibited. */ + + /* Note: There's no explicit mention of MTP3 TFP equivalent in RFC4666 (M3UA) specs, + * but section 1.4.3.2 explicitly mentions: "TFP ... MUST NOT be encapsulated as + * Data message Payload Data and sent either from SG to ASP or from ASP to + * SG. The SG MUST terminate these messages and generate M3UA messages, + * as appropriate." + * Best match for it is DUNA, so DUNA we send. + */ + + if (osmo_ss7_pc_is_local(inst, orig_xua->mtp.opc)) { + xua = gen_duna_ret_msg(inst, orig_xua); + return mtp3_hmdt_message_for_distribution(inst, xua); + } + + /* We should only be sending DUNA to M3UA peers, hence why we don't + * simply call mtp3_hmrt_message_for_routing() here. */ + rtlabel = (struct osmo_ss7_route_label){ + .opc = orig_xua->mtp.dpc, + .dpc = orig_xua->mtp.opc, + .sls = orig_xua->mtp.sls, + }; + rt = ss7_instance_lookup_route(inst, &rtlabel); + if (!rt) { + LOGSS7(inst, LOGL_NOTICE, "Tx TFP (DUNA) inaccessible SP %u=%s to concerned SP %u=%s: no route!\n", + orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc), + orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc)); + return 0; + } + if (!rt->dest.as) { + LOGSS7(inst, LOGL_ERROR, "Tx TFP (DUNA) inaccessible SP %u=%s to concerned SP %u=%s: unsupported for linkset!\n", + orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc), + orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc)); + return 0; + } + + switch (rt->dest.as->cfg.proto) { + case OSMO_SS7_ASP_PROT_M3UA: + LOGSS7(inst, LOGL_INFO, "Message received for inaccessible SP %u=%s. Tx TFP (DUNA) to concerned SP %u=%s\n", + orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc), + orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc)); + xua = gen_duna_ret_msg(inst, orig_xua); + return m3ua_tx_xua_as(rt->dest.as, xua); + case OSMO_SS7_ASP_PROT_IPA: + /* FIXME: No DUNA in IPA, maybe send SUA CLDR (SCCP UDTS) instead? */ + LOGSS7(inst, LOGL_INFO, "Message received for inaccessible SP %u=%s, " + "but concerned SP %u=%s is IPA-based and doesn't support TFP (DUNA)\n", + orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc), + orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc)); + return 0; + default: + LOGSS7(inst, LOGL_ERROR, "DUNA message for ASP of unknown protocol %u\n", + rt->dest.as->cfg.proto); + return 0; + } + + return 0; +} diff --git a/src/mtp3_rtpc.h b/src/mtp3_rtpc.h new file mode 100644 index 0000000..8a0569d --- /dev/null +++ b/src/mtp3_rtpc.h @@ -0,0 +1,11 @@ +#pragma once + +#include <stdint.h> +#include <unistd.h> + +#include <osmocom/sigtran/mtp_sap.h> + +#include "ss7_instance.h" +#include "xua_msg.h" + +int mtp3_rtpc_rx_msg_for_inaccessible_sp(struct osmo_ss7_instance *inst, const struct xua_msg *xua); diff --git a/src/xua_internal.h b/src/xua_internal.h index a1023c1..8674ef5 100644 --- a/src/xua_internal.h +++ b/src/xua_internal.h @@ -53,6 +53,10 @@ void m3ua_tx_dupu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx, uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str);
+struct xua_msg *m3ua_encode_duna(const uint32_t *rctx, unsigned int num_rctx, + const uint32_t *aff_pc, unsigned int num_aff_pc, + const char *info_string); + void xua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx, const uint32_t *aff_pc, unsigned int num_aff_pc, const char *info_str, bool available);