<p>Harald Welte has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/10245">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">USSD: Add basic dispatch + decode of GSUP-encapsulated SS/USSD<br><br>We don't want any SS session to run for more than 30s.  The timeout<br>is currently not refreshed.<br><br>If we need more comprehensive timeout handling, using osmo_fsm for SS<br>sessions might make sense.<br><br>Change-Id: I5c9fb6b619402d2a23fea9db99590143d85ac11a<br>---<br>M src/hlr.c<br>M src/hlr.h<br>M src/hlr_ussd.c<br>M src/hlr_ussd.h<br>4 files changed, 323 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-hlr refs/changes/45/10245/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/hlr.c b/src/hlr.c</span><br><span>index 79c4c86..74b65c4 100644</span><br><span>--- a/src/hlr.c</span><br><span>+++ b/src/hlr.c</span><br><span>@@ -42,6 +42,7 @@</span><br><span> #include "rand.h"</span><br><span> #include "luop.h"</span><br><span> #include "hlr_vty.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "hlr_ussd.h"</span><br><span> </span><br><span> struct hlr *g_hlr;</span><br><span> static int quit = 0;</span><br><span>@@ -402,6 +403,13 @@</span><br><span>          LOGP(DMAIN, LOGL_ERROR, "Deleting subscriber data for IMSI %s\n",</span><br><span>               gsup.imsi);</span><br><span>             break;</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%);">+           rx_proc_ss_req(conn, &gsup);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</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%);">+            rx_proc_ss_error(conn, &gsup);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span>       case OSMO_GSUP_MSGT_INSERT_DATA_ERROR:</span><br><span>       case OSMO_GSUP_MSGT_INSERT_DATA_RESULT:</span><br><span>      case OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR:</span><br><span>@@ -560,6 +568,7 @@</span><br><span> </span><br><span>         g_hlr = talloc_zero(hlr_ctx, struct hlr);</span><br><span>    INIT_LLIST_HEAD(&g_hlr->euse_list);</span><br><span style="color: hsl(120, 100%, 40%);">+    INIT_LLIST_HEAD(&g_hlr->ss_sessions);</span><br><span> </span><br><span>     rc = osmo_init_logging2(hlr_ctx, &hlr_log_info);</span><br><span>         if (rc < 0) {</span><br><span>diff --git a/src/hlr.h b/src/hlr.h</span><br><span>index 938f7f9..7112352 100644</span><br><span>--- a/src/hlr.h</span><br><span>+++ b/src/hlr.h</span><br><span>@@ -43,6 +43,8 @@</span><br><span> </span><br><span>    struct llist_head euse_list;</span><br><span>         struct hlr_euse *euse_default;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      struct llist_head ss_sessions;</span><br><span> };</span><br><span> </span><br><span> extern struct hlr *g_hlr;</span><br><span>diff --git a/src/hlr_ussd.c b/src/hlr_ussd.c</span><br><span>index 785eafd..41fba34 100644</span><br><span>--- a/src/hlr_ussd.c</span><br><span>+++ b/src/hlr_ussd.c</span><br><span>@@ -1,4 +1,4 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/* OsmoHLR VTY implementation */</span><br><span style="color: hsl(120, 100%, 40%);">+/* OsmoHLR SS/USSD implementation */</span><br><span> </span><br><span> /* (C) 2018 Harald Welte <laforge@gnumonks.org></span><br><span>  *</span><br><span>@@ -21,11 +21,22 @@</span><br><span> </span><br><span> </span><br><span> #include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsup.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm0480.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_04_80.h></span><br><span> #include <stdint.h></span><br><span> #include <string.h></span><br><span> </span><br><span> #include "hlr.h"</span><br><span> #include "hlr_ussd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "gsup_server.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "gsup_router.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "logging.h"</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%);">+ * core data structures expressing config from VTY</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span> </span><br><span> struct hlr_euse *euse_find(struct hlr *hlr, const char *name)</span><br><span> {</span><br><span>@@ -91,3 +102,293 @@</span><br><span>      llist_del(&rt->list);</span><br><span>         talloc_free(rt);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct hlr_euse *ussd_euse_find_7bit_gsm(struct hlr *hlr, const char *ussd_code)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct hlr_euse *euse;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      llist_for_each_entry(euse, &hlr->euse_list, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+            struct hlr_euse_route *rt;</span><br><span style="color: hsl(120, 100%, 40%);">+            llist_for_each_entry(rt, &euse->routes, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (!strncmp(ussd_code, rt->prefix, strlen(rt->prefix))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              LOGP(DMAIN, LOGL_DEBUG, "Found EUSE %s (prefix %s) for USSD Code '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                   rt->euse->name, rt->prefix, ussd_code);</span><br><span style="color: hsl(120, 100%, 40%);">+                              return rt->euse;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   LOGP(DMAIN, LOGL_DEBUG, "Could not find Route/EUSE for USSD Code '%s'\n", ussd_code);</span><br><span style="color: hsl(120, 100%, 40%);">+       return NULL;</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%);">+ * handling functions for individual GSUP messages</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%);">+struct ss_session {</span><br><span style="color: hsl(120, 100%, 40%);">+     /* link us to hlr->ss_sessions */</span><br><span style="color: hsl(120, 100%, 40%);">+  struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* imsi of this session */</span><br><span style="color: hsl(120, 100%, 40%);">+    char imsi[GSM23003_IMSI_MAX_DIGITS+2];</span><br><span style="color: hsl(120, 100%, 40%);">+        /* ID of this session (unique per IMSI) */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t session_id;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* state of the session */</span><br><span style="color: hsl(120, 100%, 40%);">+    enum osmo_gsup_session_state state;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* time-out when we will delete the session */</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_timer_list timeout;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* external USSD Entity responsible for this session */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct hlr_euse *euse;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* we don't keep a pointer to the osmo_gsup_{route,conn} towards the MSC/VLR here,</span><br><span style="color: hsl(120, 100%, 40%);">+         * as this might change during inter-VLR hand-over, and we simply look-up the serving MSC/VLR</span><br><span style="color: hsl(120, 100%, 40%);">+  * every time we receive an USSD component from the EUSE */</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%);">+struct ss_session *ss_session_find(struct hlr *hlr, const char *imsi, uint32_t session_id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ss_session *ss;</span><br><span style="color: hsl(120, 100%, 40%);">+        llist_for_each_entry(ss, &hlr->ss_sessions, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!strcmp(ss->imsi, imsi) && ss->session_id == session_id)</span><br><span style="color: hsl(120, 100%, 40%);">+                    return ss;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     return NULL;</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%);">+void ss_session_free(struct ss_session *ss)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_timer_del(&ss->timeout);</span><br><span style="color: hsl(120, 100%, 40%);">+  llist_del(&ss->list);</span><br><span style="color: hsl(120, 100%, 40%);">+  talloc_free(ss);</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%);">+static void ss_session_timeout(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ss_session *ss = data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       LOGP(DMAIN, LOGL_NOTICE, "%s/0x%08x: SS Session Timeout, destroying\n", ss->imsi, ss->session_id);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* FIXME: should we send a ReturnError component to the MS? */</span><br><span style="color: hsl(120, 100%, 40%);">+        ss_session_free(ss);</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%);">+struct ss_session *ss_session_alloc(struct hlr *hlr, const char *imsi, uint32_t session_id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ss_session *ss;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(!ss_session_find(hlr, imsi, session_id));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ss = talloc_zero(hlr, struct ss_session);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(ss);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_STRLCPY_ARRAY(ss->imsi, imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+        ss->session_id = session_id;</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_timer_setup(&ss->timeout, ss_session_timeout, ss);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* NOTE: The timeout is currently global and not refreshed with subsequent messages</span><br><span style="color: hsl(120, 100%, 40%);">+    * within the SS/USSD session.  So 30s after the initial SS message, the session will</span><br><span style="color: hsl(120, 100%, 40%);">+  * timeout! */</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_timer_schedule(&ss->timeout, 30, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    llist_add_tail(&ss->list, &hlr->ss_sessions);</span><br><span style="color: hsl(120, 100%, 40%);">+   return ss;</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%);">+ * handling functions for individual GSUP messages</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%);">+static bool ss_op_is_ussd(uint8_t opcode)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (opcode) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM0480_OP_CODE_PROCESS_USS_DATA:</span><br><span style="color: hsl(120, 100%, 40%);">+        case GSM0480_OP_CODE_PROCESS_USS_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM0480_OP_CODE_USS_REQUEST:</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM0480_OP_CODE_USS_NOTIFY:</span><br><span style="color: hsl(120, 100%, 40%);">+              return true;</span><br><span style="color: hsl(120, 100%, 40%);">+  default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return false;</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%);">+/* is this GSUP connection an EUSE (true) or not (false)? */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool conn_is_euse(struct osmo_gsup_conn *conn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t *addr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      rc = osmo_gsup_conn_ccm_get(conn, &addr, IPAC_IDTAG_SERNR);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc <= 5)</span><br><span style="color: hsl(120, 100%, 40%);">+               return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strncmp((char *)addr, "EUSE-", 5))</span><br><span style="color: hsl(120, 100%, 40%);">+             return true;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+          return false;</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%);">+static struct hlr_euse *euse_by_conn(struct osmo_gsup_conn *conn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       char *addr;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct hlr *hlr = conn->server->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_gsup_conn_ccm_get(conn, (uint8_t **) &addr, IPAC_IDTAG_SERNR);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc <= 5)</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (strncmp(addr, "EUSE-", 5))</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return euse_find(hlr, addr+5);</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%);">+static int handle_ss(struct ss_session *ss, const struct osmo_gsup_message *gsup,</span><br><span style="color: hsl(120, 100%, 40%);">+                        const struct ss_request *req)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t comp_type = gsup->ss_info[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGP(DMAIN, LOGL_INFO, "%s: SS CompType=%s, OpCode=%s\n", gsup->imsi,</span><br><span style="color: hsl(120, 100%, 40%);">+            gsm0480_comp_type_name(comp_type), gsm0480_op_code_name(req->opcode));</span><br><span style="color: hsl(120, 100%, 40%);">+     /* FIXME */</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int handle_ussd(struct osmo_gsup_conn *conn, struct ss_session *ss,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const struct osmo_gsup_message *gsup, const struct ss_request *req)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t comp_type = gsup->ss_info[0];</span><br><span style="color: hsl(120, 100%, 40%);">+      struct msgb *msg_out;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool is_euse_originated = conn_is_euse(conn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       LOGP(DMAIN, LOGL_INFO, "%s: USSD CompType=%s, OpCode=%s '%s'\n", gsup->imsi,</span><br><span style="color: hsl(120, 100%, 40%);">+             gsm0480_comp_type_name(comp_type), gsm0480_op_code_name(req->opcode),</span><br><span style="color: hsl(120, 100%, 40%);">+              req->ussd_text);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP USSD FW");</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(msg_out);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ss->euse) {</span><br><span style="color: hsl(120, 100%, 40%);">+           LOGP(DMAIN, LOGL_NOTICE, "%s: USSD for unknown code '%s'\n", gsup->imsi, req->ussd_text);</span><br><span style="color: hsl(120, 100%, 40%);">+             /* FIXME: send proper error */</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (is_euse_originated) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Received from EUSE, Forward to VLR */</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_gsup_encode(msg_out, gsup);</span><br><span style="color: hsl(120, 100%, 40%);">+              /* FIXME: resolve this based on the database vlr_addr */</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_gsup_addr_send(conn->server, (uint8_t *)"MSC-00-00-00-00-00-00", 22, msg_out);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Received from VLR, Forward to EUSE */</span><br><span style="color: hsl(120, 100%, 40%);">+              char addr[128];</span><br><span style="color: hsl(120, 100%, 40%);">+               strcpy(addr, "EUSE-");</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_strlcpy(addr+5, ss->euse->name, sizeof(addr)-5);</span><br><span style="color: hsl(120, 100%, 40%);">+           conn = gsup_route_find(conn->server, (uint8_t *)addr, strlen(addr)+1);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  LOGP(DMAIN, LOGL_ERROR, "Cannot find conn for EUSE %s\n", addr);</span><br><span style="color: hsl(120, 100%, 40%);">+                    /* FIXME: send proper error */</span><br><span style="color: hsl(120, 100%, 40%);">+                        return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_gsup_encode(msg_out, gsup);</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_gsup_conn_send(conn, msg_out);</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%);">+   return 0;</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%);">+/* this function is called for any SS_REQ/SS_RESP messages from both the MSC/VLR side as well</span><br><span style="color: hsl(120, 100%, 40%);">+ * as from the EUSE side */</span><br><span style="color: hsl(120, 100%, 40%);">+int rx_proc_ss_req(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct hlr *hlr = conn->server->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ss_session *ss;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ss_request req = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGP(DMAIN, LOGL_INFO, "%s: Process SS (0x%08x, %s)\n", gsup->imsi, gsup->session_id,</span><br><span style="color: hsl(120, 100%, 40%);">+         osmo_gsup_session_state_name(gsup->session_state));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* decode and find out what kind of SS message it is */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (gsup->ss_info && gsup->ss_info_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (gsm0480_parse_facility_ie(gsup->ss_info, gsup->ss_info_len, &req)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    LOGP(DMAIN, LOGL_ERROR, "%s: Unable to parse SS request for 0x%08x: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                          gsup->imsi, gsup->session_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                           osmo_hexdump(gsup->ss_info, gsup->ss_info_len));</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto out_err;</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%);">+   switch (gsup->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%);">+           /* Check for overlapping Session ID usage */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (ss_session_find(hlr, gsup->imsi, gsup->session_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       LOGP(DMAIN, LOGL_ERROR, "%s/0x%08x: BEGIN with non-uinque session ID!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           gsup->imsi, gsup->session_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                  goto out_err;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             ss = ss_session_alloc(hlr, gsup->imsi, gsup->session_id);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!ss) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    LOGP(DMAIN, LOGL_ERROR, "%s: Unable to allocate SS session for 0x%08x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           gsup->imsi, gsup->session_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                  goto out_err;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (ss_op_is_ussd(req.opcode)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (conn_is_euse(conn)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             /* EUSE->VLR: MT USSD. EUSE is known ('conn'), VLR is to be resolved */</span><br><span style="color: hsl(120, 100%, 40%);">+                            ss->euse = euse_by_conn(conn);</span><br><span style="color: hsl(120, 100%, 40%);">+                     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              /* VLR->EUSE: MO USSD. VLR is known ('conn'), EUSE is to be resolved */</span><br><span style="color: hsl(120, 100%, 40%);">+                            ss->euse = ussd_euse_find_7bit_gsm(hlr, (const char *) req.ussd_text);</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* dispatch unstructured SS to routing */</span><br><span style="color: hsl(120, 100%, 40%);">+                     handle_ussd(conn, ss, gsup, &req);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* dispatch non-call SS to internal code */</span><br><span style="color: hsl(120, 100%, 40%);">+                   handle_ss(ss, gsup, &req);</span><br><span style="color: hsl(120, 100%, 40%);">+                }</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%);">+                ss = ss_session_find(hlr, gsup->imsi, gsup->session_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!ss) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    LOGP(DMAIN, LOGL_ERROR, "%s: CONTINUE for unknwon SS session 0x%08x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                             gsup->imsi, gsup->session_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                  goto out_err;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (ss_op_is_ussd(req.opcode)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* dispatch unstructured SS to routing */</span><br><span style="color: hsl(120, 100%, 40%);">+                     handle_ussd(conn, ss, gsup, &req);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* dispatch non-call SS to internal code */</span><br><span style="color: hsl(120, 100%, 40%);">+                   handle_ss(ss, gsup, &req);</span><br><span style="color: hsl(120, 100%, 40%);">+                }</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%);">+             ss = ss_session_find(hlr, gsup->imsi, gsup->session_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!ss) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    LOGP(DMAIN, LOGL_ERROR, "%s: END for unknwon SS session 0x%08x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                          gsup->imsi, gsup->session_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                  goto out_err;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (ss_op_is_ussd(req.opcode)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* dispatch unstructured SS to routing */</span><br><span style="color: hsl(120, 100%, 40%);">+                     handle_ussd(conn, ss, gsup, &req);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* dispatch non-call SS to internal code */</span><br><span style="color: hsl(120, 100%, 40%);">+                   handle_ss(ss, gsup, &req);</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             ss_session_free(ss);</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DMAIN, LOGL_ERROR, "%s: Unknown SS State %d\n", gsup->imsi, gsup->session_state);</span><br><span style="color: hsl(120, 100%, 40%);">+                goto out_err;</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%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+out_err:</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int rx_proc_ss_error(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGP(DMAIN, LOGL_NOTICE, "%s: Process SS ERROR (0x%08x, %s)\n", gsup->imsi, gsup->session_id,</span><br><span style="color: hsl(120, 100%, 40%);">+         osmo_gsup_session_state_name(gsup->session_state));</span><br><span style="color: hsl(120, 100%, 40%);">+        return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/hlr_ussd.h b/src/hlr_ussd.h</span><br><span>index 05d2099..433a7f2 100644</span><br><span>--- a/src/hlr_ussd.h</span><br><span>+++ b/src/hlr_ussd.h</span><br><span>@@ -1,5 +1,9 @@</span><br><span> #include <stdint.h></span><br><span> #include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsup.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "gsup_server.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_gsup_conn;</span><br><span> </span><br><span> struct hlr_euse_route {</span><br><span>      /* hlr_euse.routes */</span><br><span>@@ -18,6 +22,9 @@</span><br><span>    const char *description;</span><br><span>     /* list of hlr_euse_route */</span><br><span>         struct llist_head routes;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* GSUP connection to the EUSE, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct osmo_gsup_conn *conn;</span><br><span> };</span><br><span> </span><br><span> </span><br><span>@@ -28,3 +35,6 @@</span><br><span> struct hlr_euse_route *euse_route_find(struct hlr_euse *euse, const char *prefix);</span><br><span> struct hlr_euse_route *euse_route_prefix_alloc(struct hlr_euse *euse, const char *prefix);</span><br><span> void euse_route_del(struct hlr_euse_route *rt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int rx_proc_ss_req(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup);</span><br><span style="color: hsl(120, 100%, 40%);">+int rx_proc_ss_error(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/10245">change 10245</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/10245"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-hlr </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I5c9fb6b619402d2a23fea9db99590143d85ac11a </div>
<div style="display:none"> Gerrit-Change-Number: 10245 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>