Enabling/disabling 4G RAN for given subscriber

The change adds support for enabling and disabling connection
through 4G RAN by a subscriber with use of USSD codes.

Change-Id: Idf964d9c770a0a1cb5c486eb2a7592d6bf44171c
diff --git a/doc/examples/osmo-hlr.cfg b/doc/examples/osmo-hlr.cfg
index dc683d9..dee200b 100644
--- a/doc/examples/osmo-hlr.cfg
+++ b/doc/examples/osmo-hlr.cfg
@@ -29,3 +29,5 @@
  ussd route prefix *#201# internal gsm-on
  ussd route prefix *#300# internal umts-off
  ussd route prefix *#301# internal umts-on
+ ussd route prefix *#400# internal lte-off
+ ussd route prefix *#401# internal lte-on
diff --git a/sql/hlr.sql b/sql/hlr.sql
index 65c20c6..fd56669 100644
--- a/sql/hlr.sql
+++ b/sql/hlr.sql
@@ -81,7 +81,7 @@
 -- If a subscriber has no entry, that means that all RATs are allowed (backwards compat).
 CREATE TABLE subscriber_rat (
 	subscriber_id	INTEGER,		-- subscriber.id
-	rat		TEXT CHECK(rat in ('GERAN-A', 'UTRAN-Iu')) NOT NULL,	-- Radio Access Technology, see enum ran_type
+	rat		TEXT CHECK(rat in ('GERAN-A', 'UTRAN-Iu','EUTRAN-SGs')) NOT NULL,	-- Radio Access Technology, see enum ran_type
 	allowed		BOOLEAN CHECK(allowed in (0, 1)) NOT NULL DEFAULT 0
 );
 
diff --git a/src/hlr_ussd.c b/src/hlr_ussd.c
index 7ca882d..de4d34b 100644
--- a/src/hlr_ussd.c
+++ b/src/hlr_ussd.c
@@ -373,14 +373,17 @@
 			rat = "2G";
 		else if (!strcmp(subscr.last_lu_rat, "UTRAN-Iu"))
 			rat = "3G";
+		else if (!strcmp(subscr.last_lu_rat, "EUTRAN-SGs"))
+			rat = "4G";
 		else
 			rat = subscr.last_lu_rat;
 
 		snprintf(response, sizeof(response),
-			 "Now on %s. Available:%s%s.",
+			 "Now on %s. Available:%s%s%s.",
 			 rat,
 			 subscr.rat_types[OSMO_RAT_GERAN_A]? " 2G" : "",
-			 subscr.rat_types[OSMO_RAT_UTRAN_IU]? " 3G" : "");
+			 subscr.rat_types[OSMO_RAT_UTRAN_IU]? " 3G" : "",
+			 subscr.rat_types[OSMO_RAT_EUTRAN_SGS]? " 4G" : "");
 
 		rc = ss_tx_ussd_7bit(ss, true, req->invoke_id, response);
 		break;
@@ -500,6 +503,59 @@
 	return rc;
 }
 
+static int handle_ussd_lte_on(struct osmo_gsup_conn *conn, struct ss_session *ss,
+			       const struct osmo_gsup_message *gsup,
+			       const struct ss_request *req)
+{
+	struct hlr_subscriber subscr;
+	int rc;
+
+	rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
+	switch (rc) {
+	case 0:
+		hlr_subscr_rat_flag(g_hlr, &subscr, OSMO_RAT_EUTRAN_SGS, true);
+		rc = ss_tx_ussd_7bit(ss, true, req->invoke_id,
+			"Enabled EUTRAN-SGs (4G)");
+		break;
+	case -ENOENT:
+		rc = ss_tx_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
+		break;
+	case -EIO:
+	default:
+		rc = ss_tx_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
+		break;
+	}
+
+	return rc;
+}
+
+static int handle_ussd_lte_off(struct osmo_gsup_conn *conn, struct ss_session *ss,
+				const struct osmo_gsup_message *gsup,
+				const struct ss_request *req)
+{
+	struct hlr_subscriber subscr;
+	int rc;
+
+	rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
+	switch (rc) {
+	case 0:
+		hlr_subscr_rat_flag(g_hlr, &subscr, OSMO_RAT_EUTRAN_SGS, false);
+		rc = ss_tx_ussd_7bit(ss, true, req->invoke_id,
+			"Disabled EUTRAN-SGs (4G)");
+		break;
+	case -ENOENT:
+		rc = ss_tx_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
+		break;
+	case -EIO:
+	default:
+		rc = ss_tx_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
+		break;
+	}
+
+	return rc;
+}
+
+
 static const struct hlr_iuse hlr_iuses[] = {
 	{
 		.name = "own-msisdn",
@@ -529,6 +585,14 @@
 		.name = "umts-off",
 		.handle_ussd = handle_ussd_umts_off,
 	},
+	{
+		.name = "lte-on",
+		.handle_ussd = handle_ussd_lte_on,
+	},
+	{
+		.name = "lte-off",
+		.handle_ussd = handle_ussd_lte_off,
+	},
 };
 
 const struct hlr_iuse *iuse_find(const char *name)
diff --git a/src/hlr_vty.c b/src/hlr_vty.c
index 46bbb28..529b7a5 100644
--- a/src/hlr_vty.c
+++ b/src/hlr_vty.c
@@ -156,13 +156,17 @@
 #define UROUTE_STR "Routing Configuration\n"
 #define PREFIX_STR "Prefix-Matching Route\n" "USSD Prefix\n"
 
-#define INT_CHOICE "(own-msisdn|own-imsi|get-ran|gsm-on|gsm-off|umts-on|umts-off)"
+#define INT_CHOICE "(own-msisdn|own-imsi|get-ran|gsm-on|gsm-off|umts-on|umts-off|lte-on|lte-off)"
 #define INT_STR "Internal USSD Handler\n" \
 		"Respond with subscribers' own MSISDN\n" \
 		"Respond with subscribers' own IMSI\n" \
 		"Respond with available RAN types\n" \
+		"Enable GSM service\n" \
+		"Disable GSM service\n" \
 		"Enable UMTS service\n" \
-		"Disable UMTS service\n"
+		"Disable UMTS service\n" \
+		"Enable LTE service\n" \
+		"Disable LTE service\n"
 
 #define EXT_STR "External USSD Handler\n" \
 		"Name of External USSD Handler (IPA CCM ID)\n"
diff --git a/src/hlr_vty_subscr.c b/src/hlr_vty_subscr.c
index f7089c4..02a1d33 100644
--- a/src/hlr_vty_subscr.c
+++ b/src/hlr_vty_subscr.c
@@ -615,11 +615,12 @@
 
 DEFUN(subscriber_rat,
       subscriber_rat_cmd,
-      SUBSCR_UPDATE "rat (geran-a|utran-iu) (allowed|forbidden)",
+      SUBSCR_UPDATE "rat (geran-a|utran-iu|eutran-sgs) (allowed|forbidden)",
       SUBSCR_UPDATE_HELP
       "Allow or forbid specific Radio Access Types\n"
       "Set access to GERAN-A\n"
       "Set access to UTRAN-Iu\n"
+      "Set access to EUTRAN-SGs\n"
       "Allow access\n"
       "Forbid access\n")
 {
@@ -636,7 +637,7 @@
 		rat = OSMO_RAT_GERAN_A;
 	else if (strcmp(rat_str, "utran-iu") == 0)
 		rat = OSMO_RAT_UTRAN_IU;
-	else if (strcmp(rat_str, "eutran") == 0)
+	else if (strcmp(rat_str, "eutran-sgs") == 0)
 		rat = OSMO_RAT_EUTRAN_SGS;
 
 	allowed = (strcmp(allowed_forbidden, "allowed") == 0);
diff --git a/src/luop.h b/src/luop.h
index 5a79722..51908b4 100644
--- a/src/luop.h
+++ b/src/luop.h
@@ -54,7 +54,7 @@
 	enum lu_state state;
 	/*! CS (false) or PS (true) Location Update? */
 	bool is_ps;
-	/*! RAT type indicator: coming in on GERAN-A? UTRAN-Iu? */
+	/*! RAT type indicator: coming in on GERAN-A? UTRAN-Iu? E-UTRAN?*/
 	enum osmo_rat_type via_rat;
 
 	/*! currently running timer */