Change in osmo-msc[master]: libmsc/gsm_09_11.c: WIP: forward SS/USSD-requests to HLR

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Vadim Yanitskiy gerrit-no-reply at lists.osmocom.org
Sat Jun 16 21:01:18 UTC 2018


Vadim Yanitskiy has uploaded this change for review. ( https://gerrit.osmocom.org/9658


Change subject: libmsc/gsm_09_11.c: WIP: forward SS/USSD-requests to HLR
......................................................................

libmsc/gsm_09_11.c: WIP: forward SS/USSD-requests to HLR

Change-Id: Ide5f7e350b537db80cd8326fc59c8bf2e01cb68c
---
M include/osmocom/msc/gsm_09_11.h
M src/libmsc/gsm_09_11.c
M src/libvlr/vlr.c
M tests/msc_vlr/msc_vlr_test_ss.c
M tests/msc_vlr/msc_vlr_test_ss.err
5 files changed, 238 insertions(+), 64 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/58/9658/1

diff --git a/include/osmocom/msc/gsm_09_11.h b/include/osmocom/msc/gsm_09_11.h
index 4e7a5b6..f1c33e7 100644
--- a/include/osmocom/msc/gsm_09_11.h
+++ b/include/osmocom/msc/gsm_09_11.h
@@ -1,5 +1,7 @@
 #pragma once
 
 #include <osmocom/core/msgb.h>
+#include <osmocom/gsm/gsup.h>
 
 int gsm0911_rcv_nc_ss(struct gsm_subscriber_connection *conn, struct msgb *msg);
+int gsm0911_gsup_handler(struct vlr_instance *vlr, struct osmo_gsup_message *gsup);
diff --git a/src/libmsc/gsm_09_11.c b/src/libmsc/gsm_09_11.c
index 799dfaa..67ea09e 100644
--- a/src/libmsc/gsm_09_11.c
+++ b/src/libmsc/gsm_09_11.c
@@ -26,10 +26,12 @@
  */
 
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <errno.h>
 
+#include <osmocom/core/utils.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+
 #include <osmocom/msc/gsm_04_80.h>
 #include <osmocom/msc/gsm_subscriber.h>
 #include <osmocom/msc/debug.h>
@@ -37,34 +39,21 @@
 #include <osmocom/msc/vlr.h>
 #include <osmocom/msc/gsm_04_08.h>
 #include <osmocom/msc/transaction.h>
+#include <osmocom/msc/gsup_client.h>
+#include <osmocom/msc/msc_ifaces.h>
 
 /* FIXME: choose a proper range */
 static uint32_t new_callref = 0x20000001;
 
-/* Declarations of USSD strings to be recognised */
-const char USSD_TEXT_OWN_NUMBER[] = "*#100#";
-
-/* A network-specific handler function */
-static int send_own_number(struct gsm_subscriber_connection *conn,
-			   uint8_t tid, uint8_t invoke_id)
-{
-	char *own_number = conn->vsub->msisdn;
-	char response_string[GSM_EXTENSION_LENGTH + 20];
-
-	DEBUGP(DMM, "%s: MSISDN = %s\n", vlr_subscr_name(conn->vsub),
-	       own_number);
-
-	/* Need trailing CR as EOT character */
-	snprintf(response_string, sizeof(response_string), "Your extension is %s\r", own_number);
-	return gsm0480_send_ussd_response(conn, tid, invoke_id, response_string);
-}
-
 /* Entry point for call independent MO SS messages */
 int gsm0911_rcv_nc_ss(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
+	struct osmo_gsup_message gsup_msg;
 	struct gsm_trans *trans;
-	struct ss_request req;
+	struct msgb *gsup_msgb;
+	uint16_t facility_ie_len;
+	uint8_t *facility_ie;
 	uint8_t pdisc, tid;
 	uint8_t msg_type;
 	int rc;
@@ -116,47 +105,203 @@
 		cm_service_request_concludes(conn, msg);
 	}
 
-	memset(&req, 0, sizeof(req));
-	rc = gsm0480_decode_ss_request(gh, msgb_l3len(msg), &req);
-	if (!rc) {
-		LOGP(DMM, LOGL_ERROR, "SS/USSD message parsing error, "
-			"rejecting request...\n");
-		gsm0480_send_ussd_reject(conn, tid, -1,
-			GSM_0480_PROBLEM_CODE_TAG_GENERAL,
-			GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
-		/* The GSM 04.80 API uses inverted codes (0 means error) */
-		return -EPROTO;
+	/* Attempt to extract Facility IE */
+	rc = gsm0480_extract_ie_by_tag(gh, msgb_l3len(msg),
+		&facility_ie, &facility_ie_len, GSM0480_IE_FACILITY);
+	if (rc) {
+		LOGP(DMM, LOGL_ERROR, "GSM 04.80 message parsing error, "
+			"couldn't extract Facility IE\n");
+		goto error;
 	}
 
-	/* Interrogation or releaseComplete? */
-	if (req.ussd_text[0] == '\0' || req.ussd_text[0] == 0xFF) {
-		if (req.ss_code > 0) {
-			/* Assume interrogateSS or modification of it and reject */
-			return gsm0480_send_ussd_return_error(conn, tid,
-				req.invoke_id, GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION);
+	/* Facility IE is optional for RELEASE COMPLETE */
+	if (msg_type != GSM0480_MTYPE_RELEASE_COMPLETE) {
+		if (!facility_ie || facility_ie_len < 2) {
+			LOGP(DMM, LOGL_ERROR, "GSM 04.80 message parsing error, "
+				"missing mandatory Facility IE\n");
+			rc = -EINVAL;
+			goto error;
 		}
-		/* Still assuming a Release-Complete and returning */
+	}
+
+	/* Compose a mew GSUP message */
+	memset(&gsup_msg, 0x00, sizeof(gsup_msg));
+	gsup_msg.message_type = OSMO_GSUP_MSGT_PROC_SS_REQUEST;
+	gsup_msg.session_id = trans->callref;
+
+	/**
+	 * Perform A-interface to GSUP-interface mapping,
+	 * according to GSM TS 09.11, table 4.2.
+	 */
+	switch (msg_type) {
+	case GSM0480_MTYPE_REGISTER:
+		gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_BEGIN;
+		break;
+	case GSM0480_MTYPE_FACILITY:
+		gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_CONTINUE;
+		break;
+	case GSM0480_MTYPE_RELEASE_COMPLETE:
+		gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_END;
+		break;
+	}
+
+	/* Fill in the (optional) message payload */
+	if (facility_ie) {
+		gsup_msg.ss_info_len = facility_ie_len;
+		gsup_msg.ss_info = facility_ie;
+	}
+
+	/* Fill in subscriber's IMSI */
+	OSMO_STRLCPY_ARRAY(gsup_msg.imsi, conn->vsub->imsi);
+
+	/* Allocate GSUP message buffer */
+	gsup_msgb = gsup_client_msgb_alloc();
+	if (!gsup_msgb) {
+		LOGP(DMM, LOGL_ERROR, "Couldn't allocate GSUP message\n");
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	/* Encode GSUP message */
+	rc = osmo_gsup_encode(gsup_msgb, &gsup_msg);
+	if (rc) {
+		LOGP(DMM, LOGL_ERROR, "Couldn't encode GSUP message\n");
+		goto error;
+	}
+
+	/* Finally send */
+	rc = gsup_client_send(conn->network->vlr->gsup_client, gsup_msgb);
+	if (rc) {
+		LOGP(DMM, LOGL_ERROR, "Couldn't send GSUP message\n");
+		goto error;
+	}
+
+	/* Don't release connection, wait for response */
+	msc_subscr_conn_communicating(conn);
+
+	return 0;
+
+error:
+	/* Abort transaction on DTAP-interface */
+	gsm0480_send_ussd_reject(conn, tid, -1,
+		GSM_0480_PROBLEM_CODE_TAG_GENERAL,
+		GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
+	if (trans)
+		trans_free(trans);
+
+	/* TODO: abort transaction on GSUP interface if any */
+	return rc;
+}
+
+int gsm0911_gsup_handler(struct vlr_instance *vlr,
+			 struct osmo_gsup_message *gsup_msg)
+{
+	struct gsm_network *net;
+	struct vlr_subscr *vsub;
+	struct gsm_trans *trans;
+	struct gsm48_hdr *gh;
+	struct msgb *ss_msg;
+
+	/* Obtain pointer to gsm_network */
+	net = (struct gsm_network *) vlr->user_ctx;
+	OSMO_ASSERT(net);
+
+	/**
+	 * Persistence of IMSI and existence of subscriber
+	 * is already checked by VLR code, but let's assert
+	 * here, just to be sure...
+	 */
+	vsub = vlr_subscr_find_by_imsi(vlr, gsup_msg->imsi);
+	OSMO_ASSERT(vsub);
+
+	/* Associate logging messages with this subscriber */
+	log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
+
+	/* Handle errors */
+	if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
+		/* FIXME: do something! */
 		return 0;
 	}
 
-	msc_subscr_conn_communicating(conn);
-	if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.ussd_text)) {
-		DEBUGP(DMM, "USSD: Own number requested\n");
-		rc = send_own_number(conn, tid, req.invoke_id);
-	} else {
-		DEBUGP(DMM, "Unhandled USSD %s\n", req.ussd_text);
-		rc = gsm0480_send_ussd_return_error(conn,
-			tid, req.invoke_id,
-			GSM0480_ERR_CODE_UNEXPECTED_DATA_VALUE);
+	/* Attempt to find DTAP-transaction */
+	trans = trans_find_by_callref(net, gsup_msg->session_id);
+	if (!trans) {
+		if (gsup_msg->session_state == OSMO_GSUP_SESSION_STATE_BEGIN) {
+			/* FIXME: network-originated sessions are not supported yet */
+			LOGP(DMM, LOGL_ERROR, "Network-originated sessions "
+				"are not supported, dropping request...\n");
+			/* TODO: send ERROR back to the HLR */
+			return -ENOTSUP;
+		} else {
+			LOGP(DMM, LOGL_ERROR, "Received non-BEGIN message "
+				"for non-existing transaction\n");
+			/* TODO: send ERROR back to the HLR */
+			return -EINVAL;
+		}
 	}
 
-	/**
-	 * TODO: as we only handle *#100# for now, and always
-	 * respond with RELEASE COMPLETE, let's manually free
-	 * the transaction here, until the external interface
-	 * is implemented.
-	 */
-	trans_free(trans);
+	/* Allocate and prepare a new MT message */
+	ss_msg = gsm48_msgb_alloc_name("GSM 04.08 SS/USSD");
+	gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh));
+	gh->proto_discr  = GSM48_PDISC_NC_SS;
+	gh->proto_discr |= trans->transaction_id << 4;
 
-	return rc;
+	/**
+	 * Perform GSUP-interface to A-interface mapping,
+	 * according to GSM TS 09.11, table 4.1.
+	 *
+	 * TODO: see (note 3), both CONTINUE and END may
+	 * be also mapped to REGISTER if a new transaction
+	 * has to be established.
+	 */
+	switch (gsup_msg->session_state) {
+	case OSMO_GSUP_SESSION_STATE_BEGIN:
+		gh->msg_type = GSM0480_MTYPE_REGISTER;
+		break;
+	case OSMO_GSUP_SESSION_STATE_CONTINUE:
+		gh->msg_type = GSM0480_MTYPE_FACILITY;
+		break;
+	case OSMO_GSUP_SESSION_STATE_END:
+		gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
+		break;
+
+	/* Missing or incorrect session state */
+	case OSMO_GSUP_SESSION_STATE_NONE:
+	default:
+		LOGP(DMM, LOGL_ERROR, "Unexpected session state %d\n",
+			gsup_msg->session_state);
+		/* FIXME: send ERROR back to the HLR */
+		msgb_free(ss_msg);
+		return -EINVAL;
+	}
+
+	/* Facility IE is optional only for RELEASE COMPLETE */
+	if (gh->msg_type != GSM0480_MTYPE_RELEASE_COMPLETE) {
+		if (!gsup_msg->ss_info || gsup_msg->ss_info_len < 2) {
+			LOGP(DMM, LOGL_ERROR, "Missing mandatory Facility IE "
+				"for mapped 0x%02x message\n", gh->msg_type);
+			/* FIXME: send ERROR back to the HLR */
+			msgb_free(ss_msg);
+			return -EINVAL;
+		}
+	}
+
+	/* Append Facility IE if preset */
+	if (gsup_msg->ss_info && gsup_msg->ss_info_len > 2) {
+		/* Facility IE carries LV, others carry TLV */
+		if (gh->msg_type == GSM0480_MTYPE_FACILITY)
+			msgb_lv_put(ss_msg, gsup_msg->ss_info_len, gsup_msg->ss_info);
+		else
+			msgb_tlv_put(ss_msg, GSM0480_IE_FACILITY,
+				gsup_msg->ss_info_len, gsup_msg->ss_info);
+	}
+
+	/* Sent to the MS */
+	msc_tx_dtap(trans->conn, ss_msg);
+
+	/* Release transaction if required */
+	if (gh->msg_type == GSM0480_MTYPE_RELEASE_COMPLETE)
+		trans_free(trans);
+
+	return 0;
 }
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c
index fc5bc07..8bee23f 100644
--- a/src/libvlr/vlr.c
+++ b/src/libvlr/vlr.c
@@ -966,11 +966,21 @@
 	return rc;
 }
 
+/* Forward-declaration of message handlers */
+int gsm0911_gsup_handler(struct vlr_instance *vlr,
+			 struct osmo_gsup_message *gsup_msg);
+
 static int vlr_route_gsup_msg(struct vlr_instance *vlr,
 			      struct osmo_gsup_message *gsup_msg)
 {
 	switch (gsup_msg->message_type) {
-	/* Nowhere to route for now */
+	/* GSM 09.11 code implementing SS/USSD */
+	case OSMO_GSUP_MSGT_PROC_SS_REQUEST:
+	case OSMO_GSUP_MSGT_PROC_SS_RESULT:
+	case OSMO_GSUP_MSGT_PROC_SS_ERROR:
+		DEBUGP(DMSC, "Routed to GSM 09.11 SS/USSD handler\n");
+		return gsm0911_gsup_handler(vlr, gsup_msg);
+
 	default:
 		LOGP(DVLR, LOGL_ERROR, "No handler found for %s, dropping message...\n",
 			osmo_gsup_message_type_name(gsup_msg->message_type));
diff --git a/tests/msc_vlr/msc_vlr_test_ss.c b/tests/msc_vlr/msc_vlr_test_ss.c
index de7b1e1..980b7ed 100644
--- a/tests/msc_vlr/msc_vlr_test_ss.c
+++ b/tests/msc_vlr/msc_vlr_test_ss.c
@@ -88,11 +88,21 @@
 	"0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d"
 
 	/* MT: GSM 04.80 RELEASE COMPLETE with Facility IE */
+	gsup_expect_tx("20" /* OSMO_GSUP_MSGT_PROC_SS_REQUEST */
+		"0108" "09710000004026f0" /* IMSI TLV */
+		"3004" "20000001" /* Session ID TLV */
+		"3101" "01" /* Session state: BEGIN */
+		"3515" FACILITY_IE_REQ);
 	dtap_expect_tx("8b2a" "1c27" FACILITY_IE_RSP);
 	expect_release_clear(via_ran);
 
 	/* MO: GSM 04.80 REGISTER with Facility IE and SS version IE */
 	ms_sends_msg("0b7b" "1c15" FACILITY_IE_REQ "7f0100");
+	gsup_rx("20" /* OSMO_GSUP_MSGT_PROC_SS_REQUEST */
+		"0108" "09710000004026f0" /* IMSI TLV */
+		"3004" "20000001" /* Session ID TLV */
+		"3101" "03" /* Session state: END */
+		"3527" FACILITY_IE_RSP, NULL);
 	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
 	ASSERT_RELEASE_CLEAR(via_ran);
 
diff --git a/tests/msc_vlr/msc_vlr_test_ss.err b/tests/msc_vlr/msc_vlr_test_ss.err
index c7f7711..a5ce138 100644
--- a/tests/msc_vlr/msc_vlr_test_ss.err
+++ b/tests/msc_vlr/msc_vlr_test_ss.err
@@ -162,22 +162,29 @@
 DREF MSISDN:46071: MSC conn use + trans_nc_ss == 3 (0x4a: dtap,cm_service,trans_nc_ss)
 DMM MSISDN:46071: rx msg GSM0480_MTYPE_REGISTER: received_cm_service_request changes to false
 DREF MSISDN:46071: MSC conn use - cm_service == 2 (0x42: dtap,trans_nc_ss)
+GSUP --> HLR: OSMO_GSUP_MSGT_PROC_SS_REQUEST: 20010809710000004026f03004200000013101013515a11302010102013b300b04010f0406aa510c061b01
 DMM Subscr_Conn(CM_SERVICE_REQ:901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
 DMM Subscr_Conn(CM_SERVICE_REQ:901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:46071: MSISDN = 46071
+DREF MSISDN:46071: MSC conn use - dtap == 1 (0x40: trans_nc_ss)
+<-- GSUP rx OSMO_GSUP_MSGT_PROC_SS_REQUEST: 20010809710000004026f03004200000013101033527a225020101302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
+DVLR GSUP rx 61: 20010809710000004026f03004200000013101033527a225020101302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
+DREF VLR subscr MSISDN:46071 usage increases to: 4
+DVLR SUBSCR(MSISDN:46071) Rx GSUP msg_type=32 not handled at VLR, forwarding to the router at MSC
+DMSC Routed to GSM 09.11 SS/USSD handler
+DREF VLR subscr MSISDN:46071 usage increases to: 5
 DMSC msc_tx 43 bytes to MSISDN:46071 via RAN_GERAN_A
 - DTAP --RAN_GERAN_A--> MS: GSM0480_MTYPE_RELEASE_COMPLETE: 8b2a1c27a225020101302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
 - DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - trans_nc_ss == 1 (0x2: dtap)
-DREF MSISDN:46071: MSC conn use - dtap == 0 (0x0: )
+DREF VLR subscr MSISDN:46071 usage decreases to: 4
+DREF MSISDN:46071: MSC conn use - trans_nc_ss == 0 (0x0: )
 DMM Subscr_Conn(CM_SERVICE_REQ:901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_UNUSED
 DMM Subscr_Conn(CM_SERVICE_REQ:901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASING
 DREF MSISDN:46071: MSC conn use + release == 1 (0x100: release)
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
+DREF VLR subscr MSISDN:46071 usage increases to: 5
+DREF VLR subscr MSISDN:46071 usage decreases to: 4
 - BSSAP Clear --RAN_GERAN_A--> MS
+DREF VLR subscr MSISDN:46071 usage decreases to: 3
+<-- GSUP rx OSMO_GSUP_MSGT_PROC_SS_REQUEST: vlr_gsupc_read_cb() returns 0
   dtap_tx_confirmed == 1
   bssap_clear_sent == 1
 - all requests serviced, conn has been released
@@ -191,7 +198,7 @@
 DVLR Process_Access_Request_VLR(CM_SERVICE_REQ:901700000004620){PR_ARQ_S_DONE}: Freeing instance
 DVLR Process_Access_Request_VLR(CM_SERVICE_REQ:901700000004620){PR_ARQ_S_DONE}: Deallocated
 DRLL MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
+DREF VLR subscr MSISDN:46071 usage decreases to: 2
 DMM Subscr_Conn(CM_SERVICE_REQ:901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
 DMM Subscr_Conn(CM_SERVICE_REQ:901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
   llist_count(&net->subscr_conns) == 0

-- 
To view, visit https://gerrit.osmocom.org/9658
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ide5f7e350b537db80cd8326fc59c8bf2e01cb68c
Gerrit-Change-Number: 9658
Gerrit-PatchSet: 1
Gerrit-Owner: Vadim Yanitskiy <axilirator at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20180616/101c4e71/attachment.htm>


More information about the gerrit-log mailing list