aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-11-11 14:01:48 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-12-09 10:00:41 +0100
commit207f4a5deba610b34d5e140f512e538e34a7115f (patch)
treec71639dda123271986b4b1e8a7424895bb775dae
parent98647ca0ef59430f3cd7ddb7530d85db7fa2688f (diff)
sgsn: Add VTY commands to manage subscriber cache
This adds the following commands to the ENABLE node: - show subscriber cache - update-subscriber imsi IMSI insert authorized (0|1) - update-subscriber imsi IMSI cancel - update-subscriber imsi IMSI commit These commands are mainly testing tools and maintenance helpers. The update commands work asynchronously and can be used to complete a pending update request or to terminate an existing connection. The 'insert' command just update the subscriber records but does not notify the GMM layer. Invoke the 'commit' command to continue with pending procedures. Note that the subscriber cache is not stored persistently and will always be empty after an SGSN restart. Sponsored-by: On-Waves ehf
-rw-r--r--openbsc/src/gprs/sgsn_vty.c143
-rw-r--r--openbsc/tests/vty_test_runner.py16
2 files changed, 159 insertions, 0 deletions
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index 5fb230f4c..36711c282 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -21,6 +21,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <time.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
@@ -373,6 +374,143 @@ DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
return CMD_SUCCESS;
}
+/* Subscriber */
+#include <openbsc/gsm_subscriber.h>
+
+static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, int pending)
+{
+ char expire_time[200];
+
+ vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
+ subscr->authorized, VTY_NEWLINE);
+ if (strlen(subscr->name))
+ vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE);
+ if (strlen(subscr->extension))
+ vty_out(vty, " Extension: %s%s", subscr->extension,
+ VTY_NEWLINE);
+ vty_out(vty, " LAC: %d/0x%x%s",
+ subscr->lac, subscr->lac, VTY_NEWLINE);
+ vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
+ if (subscr->tmsi != GSM_RESERVED_TMSI)
+ vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
+ VTY_NEWLINE);
+
+ if (strlen(subscr->equipment.imei) > 0)
+ vty_out(vty, " IMEI: %s%s", subscr->equipment.imei, VTY_NEWLINE);
+
+ /* print the expiration time of a subscriber */
+ if (subscr->expire_lu) {
+ strftime(expire_time, sizeof(expire_time),
+ "%a, %d %b %Y %T %z", localtime(&subscr->expire_lu));
+ expire_time[sizeof(expire_time) - 1] = '\0';
+ vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
+ }
+
+ if (subscr->flags)
+ vty_out(vty, " Flags: %s%s%s%s",
+ subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
+ "FIRST_CONTACT " : "",
+ subscr->flags & GPRS_SUBSCRIBER_CANCELLED ?
+ "CANCELLED " : "",
+ subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING ?
+ "UPDATE_PENDING " : "",
+ VTY_NEWLINE);
+
+ vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
+}
+
+DEFUN(show_subscr_cache,
+ show_subscr_cache_cmd,
+ "show subscriber cache",
+ SHOW_STR "Show information about subscribers\n"
+ "Display contents of subscriber cache\n")
+{
+ struct gsm_subscriber *subscr;
+
+ llist_for_each_entry(subscr, &active_subscribers, entry) {
+ vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
+ subscr_dump_full_vty(vty, subscr, 0);
+ }
+
+ return CMD_SUCCESS;
+}
+
+#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
+#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
+ "Use the IMSI to select the subscriber\n" \
+ "The IMSI\n"
+
+DEFUN(update_subscr_insert, update_subscr_insert_cmd,
+ UPDATE_SUBSCR_STR "insert authorized (0|1)",
+ UPDATE_SUBSCR_HELP
+ "Insert data into the subscriber record\n"
+ "Authorize the subscriber to attach\n"
+ "New option value\n")
+{
+ const char *imsi = argv[0];
+ const char *option = "authorized";
+ const char *value = argv[1];
+
+ struct gsm_subscriber *subscr;
+
+ subscr = gprs_subscr_get_or_create(imsi);
+ if (!subscr) {
+ vty_out(vty, "%% unable get subscriber record for %s\n", imsi);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(option, "authorized"))
+ subscr->authorized = atoi(value);
+
+ gprs_subscr_update(subscr);
+
+ subscr_put(subscr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
+ UPDATE_SUBSCR_STR "cancel",
+ UPDATE_SUBSCR_HELP
+ "Cancel (remove) subscriber record\n")
+{
+ const char *imsi = argv[0];
+
+ struct gsm_subscriber *subscr;
+
+ subscr = gprs_subscr_get_by_imsi(imsi);
+ if (!subscr) {
+ vty_out(vty, "%% no subscriber record for %s\n", imsi);
+ return CMD_WARNING;
+ }
+
+ gprs_subscr_put_and_cancel(subscr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(update_subscr_commit, update_subscr_commit_cmd,
+ UPDATE_SUBSCR_STR "commit",
+ UPDATE_SUBSCR_HELP
+ "Apply the changes made by the insert commands\n")
+{
+ const char *imsi = argv[0];
+
+ struct gsm_subscriber *subscr;
+
+ subscr = gprs_subscr_get_by_imsi(imsi);
+ if (!subscr) {
+ vty_out(vty, "%% unable to get subscriber record for %s\n", imsi);
+ return CMD_WARNING;
+ }
+
+ gprs_subscr_update(subscr);
+
+ subscr_put(subscr);
+
+ return CMD_SUCCESS;
+}
+
int sgsn_vty_init(void)
{
install_element_ve(&show_sgsn_cmd);
@@ -380,6 +518,11 @@ int sgsn_vty_init(void)
install_element_ve(&show_mmctx_imsi_cmd);
install_element_ve(&show_mmctx_all_cmd);
install_element_ve(&show_pdpctx_all_cmd);
+ install_element_ve(&show_subscr_cache_cmd);
+
+ install_element(ENABLE_NODE, &update_subscr_insert_cmd);
+ install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
+ install_element(ENABLE_NODE, &update_subscr_commit_cmd);
install_element(CONFIG_NODE, &cfg_sgsn_cmd);
install_node(&sgsn_node, config_write_sgsn);
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index 64437a19c..a3cb9e580 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -756,6 +756,22 @@ class TestVTYSGSN(TestVTYGenericBSC):
res = self.vty.command("show running-config")
self.assert_(res.find('auth-policy remote') > 0)
+ def testVtySubscriber(self):
+ self.vty.enable()
+ res = self.vty.command('show subscriber cache')
+ self.assert_(res.find('1234567890') < 0)
+ self.assertTrue(self.vty.verify('update-subscriber imsi 1234567890 insert authorized 1', ['']))
+ res = self.vty.command('show subscriber cache')
+ self.assert_(res.find('1234567890') >= 0)
+ self.assert_(res.find('Authorized: 1') >= 0)
+ self.assertTrue(self.vty.verify('update-subscriber imsi 1234567890 insert authorized 0', ['']))
+ res = self.vty.command('show subscriber cache')
+ self.assert_(res.find('Authorized: 0') >= 0)
+ self.assertTrue(self.vty.verify('update-subscriber imsi 1234567890 commit', ['']))
+ self.assertTrue(self.vty.verify('update-subscriber imsi 1234567890 cancel', ['']))
+ res = self.vty.command('show subscriber cache')
+ self.assert_(res.find('1234567890') < 0)
+
def add_nat_test(suite, workdir):
if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc_nat/osmo-bsc_nat")):
print("Skipping the NAT test")