Review at  https://gerrit.osmocom.org/7677

VTY: add USSD processing back-end configuration

This change is a preparation for the upcoming remote USSD
processing back-end support. It extends the VTY in order
to allow one to choose preferred USSD handler.

At the moment, the following handlers are available:

OsmoMSC# configure terminal
OsmoMSC(config)# ussd
OsmoMSC(config-ussd)# handler <TAB>
  none   Do not handle USSD requests
  local  Built-in USSD handlers (e.g. *#100#)

Please note that the local back-end (good old *#100#)
is still used by default due to the compatibility reasons.

Change-Id: I0b3c5ccea4054113e8e23109b1ab68d9f0e18497
---
M include/osmocom/msc/gsm_data.h
M include/osmocom/msc/ussd.h
M include/osmocom/msc/vty.h
M src/libmsc/msc_vty.c
M src/libmsc/ussd.c
M src/osmo-msc/msc_main.c
M tests/msc_vlr/msc_vlr_tests.c
7 files changed, 170 insertions(+), 19 deletions(-)


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

diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h
index f3e1b94..5194896 100644
--- a/include/osmocom/msc/gsm_data.h
+++ b/include/osmocom/msc/gsm_data.h
@@ -14,6 +14,7 @@
 #include <osmocom/crypt/auth.h>
 #include <osmocom/sigtran/sccp_sap.h>
 
+#include <osmocom/msc/ussd.h>
 #include <osmocom/msc/common.h>
 #include <osmocom/msc/common_cs.h>
 #include <osmocom/mgcp_client/mgcp_client.h>
@@ -321,6 +322,11 @@
                /* MSISDN to which to route MO emergency calls */
                char *route_to_msisdn;
        } emergency;
+
+       struct {
+               /* USSD handler, e.g. local */
+               enum ussd_handler_type handler;
+       } ussd;
 };
 
 struct osmo_esme;
diff --git a/include/osmocom/msc/ussd.h b/include/osmocom/msc/ussd.h
index b41eb8e..7ce27fe 100644
--- a/include/osmocom/msc/ussd.h
+++ b/include/osmocom/msc/ussd.h
@@ -2,5 +2,19 @@
 
 #include <osmocom/core/msgb.h>
 
+enum ussd_handler_type {
+       /* Do not handle USSD requests */
+       USSD_HANDLER_NONE = 0,
+       /* Built-in USSD handlers (e.g. *#100#) */
+       USSD_HANDLER_LOCAL,
+};
+
+/* Forward declarations to avoid mutual include */
+struct gsm_subscriber_connection;
+struct gsm_network;
+
+int ussd_init(struct gsm_network *net);
+void ussd_shutdown(struct gsm_network *net);
+
 /* Handler function for mobile-originated USSD messages */
 int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg);
diff --git a/include/osmocom/msc/vty.h b/include/osmocom/msc/vty.h
index 6a55df7..068683f 100644
--- a/include/osmocom/msc/vty.h
+++ b/include/osmocom/msc/vty.h
@@ -23,6 +23,7 @@
        SMPP_NODE,
        SMPP_ESME_NODE,
        HLR_NODE,
+       USSD_NODE,
 };
 
 int bsc_vty_init_extra(void);
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c
index 33613e9..3a1e512 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -47,6 +47,7 @@
 #include <osmocom/msc/vlr.h>
 #include <osmocom/msc/transaction.h>
 #include <osmocom/msc/db.h>
+#include <osmocom/msc/ussd.h>
 #include <osmocom/msc/sms_queue.h>
 #include <osmocom/msc/silent_call.h>
 #include <osmocom/msc/gsm_04_80.h>
@@ -1380,6 +1381,61 @@
        return CMD_SUCCESS;
 }
 
+static struct cmd_node ussd_node = {
+       USSD_NODE,
+       "%s(config-ussd)# ",
+       1,
+};
+
+DEFUN(cfg_ussd, cfg_ussd_cmd,
+      "ussd", "Configure USSD handling")
+{
+       vty->node = USSD_NODE;
+       return CMD_SUCCESS;
+}
+
+#define USSD_HANDLERS "(none|local)"
+#define USSD_HANDLERS_HELP \
+       "Do not handle USSD requests\n" \
+       "Built-in USSD handlers (e.g. *#100#)\n"
+
+DEFUN(cfg_ussd_handler, cfg_ussd_handler_cmd,
+      "handler " USSD_HANDLERS,
+      "USSD processing back-end\n"
+      USSD_HANDLERS_HELP)
+{
+       const char *handler_str = argv[0];
+
+       /* Parse handler type */
+       if (!strcasecmp(handler_str, "none"))
+               gsmnet->ussd.handler = USSD_HANDLER_NONE;
+       else if (!strcasecmp(handler_str, "local"))
+               gsmnet->ussd.handler = USSD_HANDLER_LOCAL;
+       else {
+               vty_out(vty, "Incorrect USSD handler%s", VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       return CMD_SUCCESS;
+}
+
+static int config_write_ussd(struct vty *vty)
+{
+       vty_out(vty, "ussd%s", VTY_NEWLINE);
+
+       vty_out(vty, " handler ");
+       switch (gsmnet->ussd.handler) {
+       case USSD_HANDLER_NONE:
+               vty_out(vty, "none%s", VTY_NEWLINE);
+               break;
+       case USSD_HANDLER_LOCAL:
+               vty_out(vty, "local%s", VTY_NEWLINE);
+               break;
+       }
+
+       return CMD_SUCCESS;
+}
+
 void msc_vty_init(struct gsm_network *msc_network)
 {
        OSMO_ASSERT(gsmnet == NULL);
@@ -1461,4 +1517,8 @@
        install_node(&hlr_node, config_write_hlr);
        install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
        install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
+
+       install_element(CONFIG_NODE, &cfg_ussd_cmd);
+       install_node(&ussd_node, config_write_ussd);
+       install_element(USSD_NODE, &cfg_ussd_handler_cmd);
 }
diff --git a/src/libmsc/ussd.c b/src/libmsc/ussd.c
index e7f7e5d..4396f97 100644
--- a/src/libmsc/ussd.c
+++ b/src/libmsc/ussd.c
@@ -34,7 +34,11 @@
 #include <osmocom/msc/debug.h>
 #include <osmocom/msc/osmo_msc.h>
 #include <osmocom/msc/vlr.h>
+#include <osmocom/msc/ussd.h>
 #include <osmocom/msc/gsm_04_08.h>
+
+static int (*ussd_handler)(struct gsm_subscriber_connection *conn,
+       const struct ss_request *req) = NULL;
 
 /* Declarations of USSD strings to be recognised */
 const char USSD_TEXT_OWN_NUMBER[] = "*#100#";
@@ -52,6 +56,43 @@
        /* Need trailing CR as EOT character */
        snprintf(response_string, sizeof(response_string), "Your extension is 
%s\r", own_number);
        return gsm0480_send_ussd_response(conn, response_string, req);
+}
+
+static int ussd_handler_local(struct gsm_subscriber_connection *conn,
+       const struct ss_request *req)
+{
+       int rc;
+
+       /* Interrogation or releaseComplete? */
+       if (req->ussd_text[0] == '\0' || req->ussd_text[0] == 0xFF) {
+               if (req->ss_code > 0) {
+                       /* Assume interrogateSS or modification of it and 
reject */
+                       rc = gsm0480_send_ussd_reject(conn, req);
+                       return rc;
+               }
+               /* Still assuming a Release-Complete and returning */
+               return 0;
+       }
+
+       msc_subscr_conn_communicating(conn);
+       if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req->ussd_text)) {
+               DEBUGP(DMM, "USSD: Own number requested\n");
+               rc = send_own_number(conn, req);
+       } else {
+               DEBUGP(DMM, "Unhandled USSD %s\n", req->ussd_text);
+               rc = gsm0480_send_ussd_reject(conn, req);
+       }
+
+       return rc;
+}
+
+static int ussd_handler_dummy(struct gsm_subscriber_connection *conn,
+       const struct ss_request *req)
+{
+       DEBUGP(DMM, "USSD support disabled, rejecting request\n");
+
+       /* FIXME: use a proper problem code */
+       return gsm0480_send_ussd_reject(conn, req);
 }
 
 /* Entrypoint - handler function common to all mobile-originated USSDs */
@@ -77,25 +118,31 @@
                return rc;
        }
 
-       /* Interrogation or releaseComplete? */
-       if (req.ussd_text[0] == '\0' || req.ussd_text[0] == 0xFF) {
-               if (req.ss_code > 0) {
-                       /* Assume interrogateSS or modification of it and 
reject */
-                       rc = gsm0480_send_ussd_reject(conn, &req);
-                       return rc;
-               }
-               /* Still assuming a Release-Complete and returning */
-               return 0;
+       OSMO_ASSERT(ussd_handler);
+       return ussd_handler(conn, &req);
+}
+
+int ussd_init(struct gsm_network *net)
+{
+       /* Choose USSD connection handler */
+       switch (net->ussd.handler) {
+       case USSD_HANDLER_LOCAL:
+               ussd_handler = ussd_handler_local;
+               break;
+       case USSD_HANDLER_NONE:
+       default:
+               ussd_handler = ussd_handler_dummy;
+               break;
        }
 
-       msc_subscr_conn_communicating(conn);
-       if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.ussd_text)) {
-               DEBUGP(DMM, "USSD: Own number requested\n");
-               rc = send_own_number(conn, &req);
-       } else {
-               DEBUGP(DMM, "Unhandled USSD %s\n", req.ussd_text);
-               rc = gsm0480_send_ussd_reject(conn, &req);
-       }
+       return 0;
+}
 
-       return rc;
+void ussd_shutdown(struct gsm_network *net)
+{
+       /**
+        * Do nothing for now
+        * TODO: close connection with external USSD gateway
+        * TODO: close all active USSD connections
+        */
 }
diff --git a/src/osmo-msc/msc_main.c b/src/osmo-msc/msc_main.c
index 85a8fe1..d1f731f 100644
--- a/src/osmo-msc/msc_main.c
+++ b/src/osmo-msc/msc_main.c
@@ -55,6 +55,7 @@
 #include <osmocom/msc/vty.h>
 #include <osmocom/msc/mncc.h>
 #include <osmocom/msc/rrlp.h>
+#include <osmocom/msc/ussd.h>
 #include <osmocom/ctrl/control_if.h>
 #include <osmocom/ctrl/control_vty.h>
 #include <osmocom/ctrl/ports.h>
@@ -215,12 +216,22 @@
 
        mgcp_client_conf_init(&net->mgw.conf);
 
+       /* USSD: let's keep *#100# available by default */
+       net->ussd.handler = USSD_HANDLER_LOCAL;
+
        return net;
 }
 
 void msc_network_shutdown(struct gsm_network *net)
 {
-       /* nothing here yet */
+       /**
+        * Prevent NULL pointer dereference,
+        * e.g. when called before initialization...
+        */
+       OSMO_ASSERT(net);
+
+       /* Shutdown USSD */
+       ussd_shutdown(net);
 }
 
 static struct gsm_network *msc_network = NULL;
@@ -620,6 +631,13 @@
                return -1;
        }
 
+       /* Initialize USSD */
+       rc = ussd_init(msc_network);
+       if (rc) {
+               printf("Failed to initialize USSD.\n");
+               return -1;
+       }
+
        /* seed the PRNG */
        srand(time(NULL));
        /* TODO: is this used for crypto?? Improve randomness, at least we
diff --git a/tests/msc_vlr/msc_vlr_tests.c b/tests/msc_vlr/msc_vlr_tests.c
index 7c54057..828963c 100644
--- a/tests/msc_vlr/msc_vlr_tests.c
+++ b/tests/msc_vlr/msc_vlr_tests.c
@@ -926,6 +926,9 @@
        net->vlr->ops.tx_auth_rej = fake_vlr_tx_auth_rej;
        net->vlr->ops.set_ciph_mode = fake_vlr_tx_ciph_mode_cmd;
 
+       /* USSD: let's keep *#100# available by default */
+       net->ussd.handler = USSD_HANDLER_LOCAL;
+
        return net;
 }
 
@@ -954,6 +957,8 @@
 
        msc_subscr_conn_init();
 
+       ussd_init(net);
+
        clear_vlr();
 
        if (optind >= argc)

-- 
To view, visit https://gerrit.osmocom.org/7677
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0b3c5ccea4054113e8e23109b1ab68d9f0e18497
Gerrit-PatchSet: 1
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Owner: Vadim Yanitskiy <axilira...@gmail.com>

Reply via email to