bsc: Add access list filtering to the BSC
diff --git a/openbsc/include/openbsc/osmo_bsc.h b/openbsc/include/openbsc/osmo_bsc.h
index 7df16cc..fd5303d 100644
--- a/openbsc/include/openbsc/osmo_bsc.h
+++ b/openbsc/include/openbsc/osmo_bsc.h
@@ -66,4 +66,6 @@
 
 void bsc_gen_location_state_trap(struct gsm_bts *bts);
 
+struct llist_head *bsc_access_lists(void);
+
 #endif
diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c
index 2bbfa07..be518a4 100644
--- a/openbsc/src/libfilter/bsc_msg_filter.c
+++ b/openbsc/src/libfilter/bsc_msg_filter.c
@@ -159,7 +159,7 @@
 	struct bsc_msg_acc_lst *bsc_lst = NULL;
 
 	/* 1. global check for barred imsis */
-	if (bsc_filter_barr_find(req->black_list, imsi, &cm, &lu)) {
+	if (req->black_list && bsc_filter_barr_find(req->black_list, imsi, &cm, &lu)) {
 		cause->cm_reject_cause = cm;
 		cause->lu_reject_cause = lu;
 		LOGP(DFILTER, LOGL_DEBUG,
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c
index a90ad16..17026af 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_api.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c
@@ -1,4 +1,4 @@
-/* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+/* (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
  * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
@@ -79,6 +79,45 @@
 	return bts->cell_identity;
 }
 
+static int bsc_filter_initial(struct osmo_bsc_data *bsc,
+				struct osmo_msc_data *msc,
+				struct gsm_subscriber_connection *conn,
+				struct msgb *msg, char **imsi)
+{
+	int con_type;
+	struct bsc_filter_request req;
+	struct bsc_filter_reject_cause cause;
+	struct gsm48_hdr *gh = msgb_l3(msg);
+
+	req.ctx = conn;
+	req.black_list = NULL;
+	req.access_lists = bsc_access_lists();
+	req.local_lst_name = msc->acc_lst_name;
+	req.global_lst_name = conn->bts->network->bsc_data->acc_lst_name;
+	req.bsc_nr = 0;
+
+	return bsc_msg_filter_initial(gh, msgb_l3len(msg), &req,
+				&con_type, imsi, &cause);
+}
+
+static int bsc_filter_data(struct gsm_subscriber_connection *conn,
+				struct msgb *msg)
+{
+	struct bsc_filter_request req;
+	struct gsm48_hdr *gh = msgb_l3(msg);
+	struct bsc_filter_reject_cause cause;
+
+	req.ctx = conn;
+	req.black_list = NULL;
+	req.access_lists = bsc_access_lists();
+	req.local_lst_name = conn->sccp_con->msc->acc_lst_name;
+	req.global_lst_name = conn->bts->network->bsc_data->acc_lst_name;
+	req.bsc_nr = 0;
+
+	return bsc_msg_filter_data(gh, msgb_l3len(msg), &req,
+				&conn->sccp_con->filter_state,
+				&cause);
+}
 
 static void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
 {
@@ -172,6 +211,7 @@
 static int complete_layer3(struct gsm_subscriber_connection *conn,
 			   struct msgb *msg, struct osmo_msc_data *msc)
 {
+	char *imsi = NULL;
 	struct timeval tv;
 	struct msgb *resp;
 	uint16_t network_code;
@@ -189,6 +229,10 @@
 	if (send_ping && osmo_timer_remaining(&msc->ping_timer, NULL, &tv) == -1)
 		send_ping = 0;
 
+	/* Check the filter */
+	if (bsc_filter_initial(msc->network->bsc_data, msc, conn, msg, &imsi) < 0)
+		return BSC_API_CONN_POL_REJECT;
+
 	/* allocate resource for a new connection */
 	ret = bsc_create_new_connection(conn, msc, send_ping);
 
@@ -202,6 +246,9 @@
 		return BSC_API_CONN_POL_REJECT;
 	}
 
+	if (imsi)
+		conn->sccp_con->filter_state.imsi = talloc_steal(conn, imsi);
+
 	/* check return value, if failed check msg for and send USSD */
 
 	network_code = get_network_code_for_msc(conn->sccp_con->msc);
@@ -333,8 +380,13 @@
 	if (handle_cc_setup(conn, msg) >= 1)
 		return;
 
-	bsc_scan_bts_msg(conn, msg);
+	/* Check the filter */
+	if (bsc_filter_data(conn, msg) < 0) {
+		bsc_clear_request(conn, 0);
+		return;
+	}
 
+	bsc_scan_bts_msg(conn, msg);
 
 	resp = gsm0808_create_dtap(msg, link_id);
 	queue_msg_or_return(resp);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_main.c b/openbsc/src/osmo-bsc/osmo_bsc_main.c
index 77c9bf9..ee86cb6 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_main.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_main.c
@@ -59,6 +59,12 @@
 static const char *rf_ctrl = NULL;
 extern const char *openbsc_copyright;
 static int daemonize = 0;
+static struct llist_head access_lists;
+
+struct llist_head *bsc_access_lists(void)
+{
+	return &access_lists;
+}
 
 static void print_usage()
 {
@@ -179,7 +185,6 @@
 
 int main(int argc, char **argv)
 {
-	struct llist_head access_lists;
 	struct osmo_msc_data *msc;
 	struct osmo_bsc_data *data;
 	int rc;