<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>