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