falconia submitted this change.
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(-)
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);
+}
To view, visit change 34449. To unsubscribe, or for help writing mail filters, visit settings.