diff options
Diffstat (limited to 'openbsc/src/osmo-bsc/osmo_bsc_api.c')
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_api.c | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c index 18b9607a0..5a01d6b82 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,69 @@ static uint16_t get_ci_for_msc(struct osmo_msc_data *msc, struct gsm_bts *bts) return bts->cell_identity; } +static void bsc_maybe_lu_reject(struct gsm_subscriber_connection *conn, int con_type, int cause) +{ + struct msgb *msg; + + /* ignore cm service request or such */ + if (con_type != FLT_CON_TYPE_LU) + return; + + msg = gsm48_create_loc_upd_rej(cause); + if (!msg) { + LOGP(DMM, LOGL_ERROR, "Failed to create msg for LOCATION UPDATING REJECT.\n"); + return; + } + + msg->lchan = conn->lchan; + gsm0808_submit_dtap(conn, msg, 0, 0); +} + +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, + int *lu_cause) +{ + struct bsc_filter_request req; + struct bsc_filter_reject_cause cause; + struct gsm48_hdr *gh = msgb_l3(msg); + int rc; + + 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; + + rc = bsc_msg_filter_initial(gh, msgb_l3len(msg), &req, + con_type, imsi, &cause); + *lu_cause = cause.lu_reject_cause; + return rc; +} + +static int bsc_filter_data(struct gsm_subscriber_connection *conn, + struct msgb *msg, int *lu_cause) +{ + struct bsc_filter_request req; + struct gsm48_hdr *gh = msgb_l3(msg); + struct bsc_filter_reject_cause cause; + int rc; + + 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; + + rc = bsc_msg_filter_data(gh, msgb_l3len(msg), &req, + &conn->sccp_con->filter_state, + &cause); + *lu_cause = cause.lu_reject_cause; + return rc; +} static void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci) { @@ -172,6 +235,8 @@ static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg static int complete_layer3(struct gsm_subscriber_connection *conn, struct msgb *msg, struct osmo_msc_data *msc) { + int con_type, rc, lu_cause; + char *imsi = NULL; struct timeval tv; struct msgb *resp; uint16_t network_code; @@ -189,6 +254,14 @@ static int complete_layer3(struct gsm_subscriber_connection *conn, if (send_ping && osmo_timer_remaining(&msc->ping_timer, NULL, &tv) == -1) send_ping = 0; + /* Check the filter */ + rc = bsc_filter_initial(msc->network->bsc_data, msc, conn, msg, + &imsi, &con_type, &lu_cause); + if (rc < 0) { + bsc_maybe_lu_reject(conn, con_type, lu_cause); + return BSC_API_CONN_POL_REJECT; + } + /* allocate resource for a new connection */ ret = bsc_create_new_connection(conn, msc, send_ping); @@ -202,6 +275,10 @@ static int complete_layer3(struct gsm_subscriber_connection *conn, return BSC_API_CONN_POL_REJECT; } + if (imsi) + conn->sccp_con->filter_state.imsi = talloc_steal(conn, imsi); + conn->sccp_con->filter_state.con_type = con_type; + /* check return value, if failed check msg for and send USSD */ network_code = get_network_code_for_msc(conn->sccp_con->msc); @@ -210,6 +287,7 @@ static int complete_layer3(struct gsm_subscriber_connection *conn, ci = get_ci_for_msc(conn->sccp_con->msc, conn->bts); bsc_scan_bts_msg(conn, msg); + resp = gsm0808_create_layer3(msg, network_code, country_code, lac, ci); if (!resp) { LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n"); @@ -320,6 +398,7 @@ static int handle_cc_setup(struct gsm_subscriber_connection *conn, static void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg) { + int lu_cause; struct msgb *resp; return_when_not_connected(conn); @@ -332,8 +411,16 @@ static void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, st if (handle_cc_setup(conn, msg) >= 1) return; - bsc_scan_bts_msg(conn, msg); + /* Check the filter */ + if (bsc_filter_data(conn, msg, &lu_cause) < 0) { + bsc_maybe_lu_reject(conn, + conn->sccp_con->filter_state.con_type, + lu_cause); + bsc_clear_request(conn, 0); + return; + } + bsc_scan_bts_msg(conn, msg); resp = gsm0808_create_dtap(msg, link_id); queue_msg_or_return(resp); |