add USSD handlers to enable/disable 2G access

Change-Id: Ib266bf6ebc7692362a443efbf9b4ae69aee671d6
diff --git a/doc/examples/osmo-hlr.cfg b/doc/examples/osmo-hlr.cfg
index 58166f7..dc683d9 100644
--- a/doc/examples/osmo-hlr.cfg
+++ b/doc/examples/osmo-hlr.cfg
@@ -25,5 +25,7 @@
  ussd route prefix *#100# internal own-msisdn
  ussd route prefix *#101# internal own-imsi
  ussd route prefix *#102# internal get-ran
+ ussd route prefix *#200# internal gsm-off
+ ussd route prefix *#201# internal gsm-on
  ussd route prefix *#300# internal umts-off
  ussd route prefix *#301# internal umts-on
diff --git a/src/hlr_ussd.c b/src/hlr_ussd.c
index 7ef72a4..f356dc4 100644
--- a/src/hlr_ussd.c
+++ b/src/hlr_ussd.c
@@ -343,7 +343,7 @@
 
 		snprintf(response, sizeof(response),
 			 "Now on %s. Available:%s%s."
-			 " (enable 3G: *#301#  disable 3G: *#300#)", rat,
+			 " (2G on: *#201# off: *#200# -- 3G on: *#301# off: *#300#)", rat,
 			 subscr.rat_types[OSMO_RAT_GERAN_A]? " 2G" : "",
 			 subscr.rat_types[OSMO_RAT_UTRAN_IU]? " 3G" : "");
 
@@ -361,6 +361,58 @@
 	return rc;
 }
 
+static int handle_ussd_gsm_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_GERAN_A, true);
+		rc = ss_tx_ussd_7bit(ss, true, req->invoke_id,
+			"Enabled GERAN-A (2G)");
+		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_gsm_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_GERAN_A, false);
+		rc = ss_tx_ussd_7bit(ss, true, req->invoke_id,
+			"Disabled GERAN-A (2G)");
+		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_umts_on(struct osmo_gsup_conn *conn, struct ss_session *ss,
 			       const struct osmo_gsup_message *gsup,
 			       const struct ss_request *req)
@@ -427,6 +479,14 @@
 		.handle_ussd = handle_ussd_get_ran,
 	},
 	{
+		.name = "gsm-on",
+		.handle_ussd = handle_ussd_gsm_on,
+	},
+	{
+		.name = "gsm-off",
+		.handle_ussd = handle_ussd_gsm_off,
+	},
+	{
 		.name = "umts-on",
 		.handle_ussd = handle_ussd_umts_on,
 	},
diff --git a/src/hlr_vty.c b/src/hlr_vty.c
index c373d3a..21dd2d9 100644
--- a/src/hlr_vty.c
+++ b/src/hlr_vty.c
@@ -133,7 +133,7 @@
 #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|umts-on|umts-off)"
+#define INT_CHOICE "(own-msisdn|own-imsi|get-ran|gsm-on|gsm-off|umts-on|umts-off)"
 #define INT_STR "Internal USSD Handler\n" \
 		"Respond with subscribers' own MSISDN\n" \
 		"Respond with subscribers' own IMSI\n" \