nat: Introduce a global IMSI barr list using red-black trees
diff --git a/openbsc/tests/bsc-nat/Makefile.am b/openbsc/tests/bsc-nat/Makefile.am
index bd3d33f..e284851 100644
--- a/openbsc/tests/bsc-nat/Makefile.am
+++ b/openbsc/tests/bsc-nat/Makefile.am
@@ -2,7 +2,7 @@
 AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS)
 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
 
-EXTRA_DIST = bsc_nat_test.ok bsc_data.c
+EXTRA_DIST = bsc_nat_test.ok bsc_data.c barr.cfg barr_dup.cfg
 
 noinst_PROGRAMS = bsc_nat_test
 
diff --git a/openbsc/tests/bsc-nat/barr.cfg b/openbsc/tests/bsc-nat/barr.cfg
new file mode 100644
index 0000000..a9a4a2b
--- /dev/null
+++ b/openbsc/tests/bsc-nat/barr.cfg
@@ -0,0 +1,12 @@
+12123124:3:2:
+12123123:3:1:
+12123128:3:6:
+12123125:3:3:
+12123127:3:5:
+12123126:3:4:
+12123120:3:4:
+12123119:3:4:
+12123118:3:4:
+12123117:3:4:
+12123116:3:4:
+12123115:3:4:
diff --git a/openbsc/tests/bsc-nat/barr_dup.cfg b/openbsc/tests/bsc-nat/barr_dup.cfg
new file mode 100644
index 0000000..ea94631
--- /dev/null
+++ b/openbsc/tests/bsc-nat/barr_dup.cfg
@@ -0,0 +1,2 @@
+12123124:3:2:
+12123124:3:2:
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index 59d92bd..66b4ff5 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -1153,6 +1153,72 @@
 	msgb_free(out);
 }
 
+static void test_barr_list_parsing(void)
+{
+	int rc;
+	int cm, lu;
+	struct rb_node *node;
+	struct rb_root root = RB_ROOT;
+	struct osmo_config_list *lst = osmo_config_list_parse(NULL, "barr.cfg");
+	if (lst == NULL)
+		abort();
+
+	rc = bsc_nat_barr_adapt(NULL, &root, lst);
+	if (rc != 0)
+		abort();
+	talloc_free(lst);
+
+
+	for (node = rb_first(&root); node; node = rb_next(node)) {
+		struct bsc_nat_barr_entry *entry;
+		entry = rb_entry(node, struct bsc_nat_barr_entry, node);
+		printf("IMSI: %s CM: %d LU: %d\n", entry->imsi,
+			entry->cm_reject_cause, entry->lu_reject_cause);
+	}
+
+	/* do the look up now.. */
+	rc = bsc_nat_barr_find(&root, "12123119", &cm, &lu);
+	if (!rc) {
+		printf("Failed to find the IMSI.\n");
+		abort();
+	}
+
+	if (cm != 3 || lu != 4) {
+		printf("Found CM(%d) and LU(%d)\n", cm, lu);
+		abort();
+	}
+
+	/* empty and check that it is empty */
+	bsc_nat_barr_adapt(NULL, &root, NULL);
+	if (!RB_EMPTY_ROOT(&root)) {
+		printf("Failed to empty the list.\n");
+		abort();
+	}
+
+	/* check that dup results in an error */
+	lst = osmo_config_list_parse(NULL, "barr_dup.cfg");
+	if (lst == NULL) {
+		printf("Failed to parse list with dups\n");
+		abort();
+	}
+
+	rc = bsc_nat_barr_adapt(NULL, &root, lst);
+	if (rc != -1) {
+		printf("It should have failed due dup\n");
+		abort();
+	}
+	talloc_free(lst);
+
+	/* dump for reference */
+	for (node = rb_first(&root); node; node = rb_next(node)) {
+		struct bsc_nat_barr_entry *entry;
+		entry = rb_entry(node, struct bsc_nat_barr_entry, node);
+		printf("IMSI: %s CM: %d LU: %d\n", entry->imsi,
+			entry->cm_reject_cause, entry->lu_reject_cause);
+
+	}
+}
+
 int main(int argc, char **argv)
 {
 	sccp_set_log_area(DSCCP);
@@ -1171,6 +1237,7 @@
 	test_sms_smsc_rewrite();
 	test_sms_number_rewrite();
 	test_mgcp_allocations();
+	test_barr_list_parsing();
 
 	printf("Testing execution completed.\n");
 	return 0;
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.ok b/openbsc/tests/bsc-nat/bsc_nat_test.ok
index db37ffa..cbedc85 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.ok
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.ok
@@ -22,4 +22,17 @@
 Attempting to only rewrite the HDR
 Attempting to change nothing.
 Testing SMS TP-DA rewriting.
+IMSI: 12123115 CM: 3 LU: 4
+IMSI: 12123116 CM: 3 LU: 4
+IMSI: 12123117 CM: 3 LU: 4
+IMSI: 12123118 CM: 3 LU: 4
+IMSI: 12123119 CM: 3 LU: 4
+IMSI: 12123120 CM: 3 LU: 4
+IMSI: 12123123 CM: 3 LU: 1
+IMSI: 12123124 CM: 3 LU: 2
+IMSI: 12123125 CM: 3 LU: 3
+IMSI: 12123126 CM: 3 LU: 4
+IMSI: 12123127 CM: 3 LU: 5
+IMSI: 12123128 CM: 3 LU: 6
+IMSI: 12123124 CM: 3 LU: 2
 Testing execution completed.