falconia has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hlr/+/34449?usp=email )
Change subject: SMS over GSUP: implement forwarding of MO SMS ......................................................................
SMS over GSUP: implement forwarding of MO SMS
MO-forwardSM.req messages are now forwarded to a connected SMSC based on the SMSC address (SM-RP-DA) in the MO SM and the vty-defined mapping from SMSC numeric addresses to IPA names.
Related: OS#6135 Depends: Iea5c29909c5be80f81dbbc2873656ff5cf590a5d (libosmocore) Change-Id: Iaad4531922c41583d261c79f42561a1bdbe03521 --- M TODO-RELEASE M include/osmocom/hlr/hlr_sms.h M src/hlr.c M src/hlr_sms.c 4 files changed, 111 insertions(+), 0 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/TODO-RELEASE b/TODO-RELEASE index cbfda24..d8e3568 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,3 +7,4 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line +libosmogsm >1.9.0 <osmocom/gsm/protocol/gsm_04_11.h> additions diff --git a/include/osmocom/hlr/hlr_sms.h b/include/osmocom/hlr/hlr_sms.h index 0570aca..727e408 100644 --- a/include/osmocom/hlr/hlr_sms.h +++ b/include/osmocom/hlr/hlr_sms.h @@ -27,3 +27,5 @@ struct hlr_smsc_route *smsc_route_alloc(struct hlr *hlr, const char *num_addr, struct hlr_smsc *smsc); void smsc_route_free(struct hlr_smsc_route *rt); + +void forward_mo_sms(struct osmo_gsup_req *req); diff --git a/src/hlr.c b/src/hlr.c index 17acdab..501eabc 100644 --- a/src/hlr.c +++ b/src/hlr.c @@ -49,6 +49,7 @@ #include <osmocom/hlr/rand.h> #include <osmocom/hlr/hlr_vty.h> #include <osmocom/hlr/hlr_ussd.h> +#include <osmocom/hlr/hlr_sms.h> #include <osmocom/hlr/dgsm.h> #include <osmocom/hlr/proxy.h> #include <osmocom/hlr/lu_fsm.h> @@ -556,6 +557,9 @@ case OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST: rx_check_imei_req(req); break; + case OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST: + forward_mo_sms(req); + break; default: LOGP(DMAIN, LOGL_DEBUG, "Unhandled GSUP message type %s\n", osmo_gsup_message_type_name(req->gsup.message_type)); diff --git a/src/hlr_sms.c b/src/hlr_sms.c index 5866afa..672d6c9 100644 --- a/src/hlr_sms.c +++ b/src/hlr_sms.c @@ -26,6 +26,8 @@
#include <osmocom/core/talloc.h> #include <osmocom/gsm/gsup.h> +#include <osmocom/gsm/gsm48_ie.h> +#include <osmocom/gsm/protocol/gsm_04_11.h>
#include <osmocom/hlr/hlr.h> #include <osmocom/hlr/hlr_sms.h> @@ -101,3 +103,90 @@ llist_del(&rt->list); talloc_free(rt); } + +/*********************************************************************** + * forwarding of MO SMS to SMSCs based on SM-RP-DA + ***********************************************************************/ + +static const struct hlr_smsc *find_smsc_route(const char *smsc_addr) +{ + const struct hlr_smsc_route *rt; + + rt = smsc_route_find(g_hlr, smsc_addr); + if (rt) + return rt->smsc; + return g_hlr->smsc_default; +} + +static void respond_with_sm_rp_cause(struct osmo_gsup_req *req, + uint8_t sm_rp_cause) +{ + struct osmo_gsup_message rsp_msg = { }; + + rsp_msg.sm_rp_cause = &sm_rp_cause; + osmo_gsup_req_respond(req, &rsp_msg, true, true); +} + +/* Short Message from MSC/VLR towards SMSC */ +void forward_mo_sms(struct osmo_gsup_req *req) +{ + uint8_t gsm48_decode_buffer[GSM411_SMSC_ADDR_MAX_OCTETS]; + char smsc_addr[GSM411_SMSC_ADDR_MAX_DIGITS+1]; + const struct hlr_smsc *smsc; + struct osmo_cni_peer_id dest_peer; + + /* Make sure SM-RP-DA (SMSC address) is present */ + if (req->gsup.sm_rp_da == NULL || !req->gsup.sm_rp_da_len) { + osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO, + "missing SM-RP-DA"); + return; + } + + if (req->gsup.sm_rp_da_type != OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR) { + osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO, + "SM-RP-DA type is not SMSC"); + return; + } + + /* Enforce the length constrainst on SM-RP-DA, as specified in + * GSM 04.11 section 8.2.5.2. Also enforce absence of ToN/NPI + * extension octets at the same time. */ + if (req->gsup.sm_rp_da_len < GSM411_SMSC_ADDR_MIN_OCTETS || + req->gsup.sm_rp_da_len > GSM411_SMSC_ADDR_MAX_OCTETS || + !(req->gsup.sm_rp_da[0] & 0x80)) { + /* This form of bogosity originates from the MS, + * not from OsmoMSC or any other Osmocom network elements! */ + LOGP(DLSMS, LOGL_NOTICE, + "Rx '%s' (IMSI-%s) contains invalid SM-RP-DA from MS\n", + osmo_gsup_message_type_name(req->gsup.message_type), + req->gsup.imsi); + respond_with_sm_rp_cause(req, GSM411_RP_CAUSE_SEMANT_INC_MSG); + return; + } + + /* Decode SMSC address from SM-RP-DA */ + gsm48_decode_buffer[0] = req->gsup.sm_rp_da_len - 1; + memcpy(gsm48_decode_buffer + 1, req->gsup.sm_rp_da + 1, + req->gsup.sm_rp_da_len - 1); + gsm48_decode_bcd_number2(smsc_addr, sizeof(smsc_addr), + gsm48_decode_buffer, + req->gsup.sm_rp_da_len, 0); + + /* Look for a route to this SMSC */ + smsc = find_smsc_route(smsc_addr); + if (smsc == NULL) { + LOGP(DLSMS, LOGL_NOTICE, + "Failed to find a route for '%s' (IMSI-%s, SMSC-Addr-%s)\n", + osmo_gsup_message_type_name(req->gsup.message_type), + req->gsup.imsi, smsc_addr); + respond_with_sm_rp_cause(req, + GSM411_RP_CAUSE_MO_NUM_UNASSIGNED); + return; + } + + /* We got the IPA name of our SMSC - forward the message */ + osmo_cni_peer_id_set(&dest_peer, OSMO_CNI_PEER_ID_IPA_NAME, + (const uint8_t *) smsc->name, + strlen(smsc->name) + 1); + osmo_gsup_forward_to_local_peer(req->cb_data, &dest_peer, req, NULL); +}