nat: Add config option to filter/handle certain imsi'es.
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index df64723..4ad5495 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -33,6 +33,8 @@
 #include <osmocore/write_queue.h>
 #include <osmocore/statistics.h>
 
+#include <regex.h>
+
 #define DIR_BSC 1
 #define DIR_MSC 2
 
@@ -138,6 +140,13 @@
 	unsigned int lac;
 	int nr;
 
+	/* imsi white and blacklist */
+	char *imsi_allow;
+	regex_t imsi_allow_re;
+	char *imsi_deny;
+	regex_t imsi_deny_re;
+
+	/* backpointer */
 	struct bsc_nat *nat;
 
 	struct bsc_config_stats stats;
@@ -199,6 +208,12 @@
 
 	struct bsc_endpoint *bsc_endpoints;
 
+	/* filter */
+	char *imsi_allow;
+	regex_t imsi_allow_re;
+	char *imsi_deny;
+	regex_t imsi_deny_re;
+
 	/* statistics */
 	struct bsc_nat_statistics stats;
 };
diff --git a/openbsc/src/nat/bsc_nat_vty.c b/openbsc/src/nat/bsc_nat_vty.c
index 6ed1e72..4571d5b 100644
--- a/openbsc/src/nat/bsc_nat_vty.c
+++ b/openbsc/src/nat/bsc_nat_vty.c
@@ -51,6 +51,10 @@
 static int config_write_nat(struct vty *vty)
 {
 	vty_out(vty, "nat%s", VTY_NEWLINE);
+	if (_nat->imsi_allow)
+		vty_out(vty, " imsi allow %s%s", _nat->imsi_allow, VTY_NEWLINE);
+	if (_nat->imsi_deny)
+		vty_out(vty, " insi deny %s%s", _nat->imsi_deny, VTY_NEWLINE);
 	return CMD_SUCCESS;
 }
 
@@ -59,6 +63,10 @@
 	vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
 	vty_out(vty, "  token %s%s", bsc->token, VTY_NEWLINE);
 	vty_out(vty, "  lac %u%s", bsc->lac, VTY_NEWLINE);
+	if (bsc->imsi_allow)
+		vty_out(vty, "   imsi allow %s%s", bsc->imsi_allow, VTY_NEWLINE);
+	if (bsc->imsi_deny)
+		vty_out(vty, "   imsi deny %s%s", bsc->imsi_deny, VTY_NEWLINE);
 }
 
 static int config_write_bsc(struct vty *vty)
@@ -114,6 +122,10 @@
 	llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
 		vty_out(vty, "BSC token: '%s' lac: %u nr: %u%s",
 			conf->token, conf->lac, conf->nr, VTY_NEWLINE);
+		vty_out(vty, " imsi_allow: '%s' imsi_deny: '%s'%s",
+			conf->imsi_allow ? conf->imsi_allow: "any",
+			conf->imsi_deny  ? conf->imsi_deny : "none",
+			VTY_NEWLINE);
 	}
 
 	return CMD_SUCCESS;
@@ -157,6 +169,40 @@
 	return CMD_SUCCESS;
 }
 
+static void parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv)
+{
+	if (*imsi) {
+		talloc_free(*imsi);
+		*imsi = NULL;
+	}
+	regfree(reg);
+
+	if (argc > 0) {
+		*imsi = talloc_strdup(ctx, argv[0]);
+		regcomp(reg, argv[0], 0);
+	}
+}
+
+DEFUN(cfg_nat_imsi_allow,
+      cfg_nat_imsi_allow_cmd,
+      "imsi allow [REGEXP]",
+      "Allow matching IMSIs to talk to the MSC. "
+      "The defualt is to allow everyone.")
+{
+	parse_reg(_nat, &_nat->imsi_allow_re, &_nat->imsi_allow, argc, argv);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_imsi_deny,
+      cfg_nat_imsi_deny_cmd,
+      "imsi deny [REGEXP]",
+      "Deny matching IMSIs to talk to the MSC. "
+      "The defualt is to not deny.")
+{
+	parse_reg(_nat, &_nat->imsi_deny_re, &_nat->imsi_deny, argc, argv);
+	return CMD_SUCCESS;
+}
+
 /* per BSC configuration */
 DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure\n")
 {
@@ -225,6 +271,30 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_bsc_imsi_allow,
+      cfg_bsc_imsi_allow_cmd,
+      "imsi allow [REGEXP]",
+      "Allow IMSIs with the following network to talk to the MSC."
+      "The default is to allow everyone)")
+{
+	struct bsc_config *conf = vty->index;
+
+	parse_reg(conf, &conf->imsi_allow_re, &conf->imsi_allow, argc, argv);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_imsi_deny,
+      cfg_bsc_imsi_deny_cmd,
+      "imsi deny [REGEXP]",
+      "Deny IMSIs with the following network to talk to the MSC."
+      "The default is to not deny anyone.)")
+{
+	struct bsc_config *conf = vty->index;
+
+	parse_reg(conf, &conf->imsi_deny_re, &conf->imsi_deny, argc, argv);
+	return CMD_SUCCESS;
+}
+
 int bsc_nat_vty_init(struct bsc_nat *nat)
 {
 	_nat = nat;
@@ -244,6 +314,8 @@
 	install_element(CONFIG_NODE, &cfg_nat_cmd);
 	install_node(&nat_node, config_write_nat);
 	install_default(NAT_NODE);
+	install_element(NAT_NODE, &cfg_nat_imsi_allow_cmd);
+	install_element(NAT_NODE, &cfg_nat_imsi_deny_cmd);
 
 	/* BSC subgroups */
 	install_element(NAT_NODE, &cfg_bsc_cmd);
@@ -251,6 +323,8 @@
 	install_default(BSC_NODE);
 	install_element(BSC_NODE, &cfg_bsc_token_cmd);
 	install_element(BSC_NODE, &cfg_bsc_lac_cmd);
+	install_element(BSC_NODE, &cfg_bsc_imsi_allow_cmd);
+	install_element(BSC_NODE, &cfg_bsc_imsi_deny_cmd);
 
 	mgcp_vty_init();