From 4247cead2b77b2ad8ae2a6c1b48a450309185bb3 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 4 Apr 2015 18:42:46 +0200 Subject: filter: Move the gsm 04.08 filter to a common place For customer requirements we want to be able to do filtering on the BSC as well. The same messages need to be scanned and the same access-lists will be looked at. In the future we might even split traffic based on the IMSI. Begin with moving the code to a new top level directory and then renaming and removing the nat dependency. --- openbsc/src/libfilter/Makefile.am | 9 + openbsc/src/libfilter/bsc_msg_filter.c | 443 +++++++++++++++++++++++++++++++++ 2 files changed, 452 insertions(+) create mode 100644 openbsc/src/libfilter/Makefile.am create mode 100644 openbsc/src/libfilter/bsc_msg_filter.c (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/Makefile.am b/openbsc/src/libfilter/Makefile.am new file mode 100644 index 000000000..e24ec5f73 --- /dev/null +++ b/openbsc/src/libfilter/Makefile.am @@ -0,0 +1,9 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) +AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) \ + $(LIBOSMOVTY_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) + +noinst_LIBRARIES = libfilter.a + +libfilter_a_SOURCES = \ + bsc_msg_filter.c + diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c new file mode 100644 index 000000000..64f6d7347 --- /dev/null +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -0,0 +1,443 @@ +/* + * Access filtering + */ +/* + * (C) 2010-2012 by Holger Hans Peter Freyther + * (C) 2010-2012 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +int bsc_nat_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu) +{ + struct bsc_nat_barr_entry *n; + n = rb_entry(root->rb_node, struct bsc_nat_barr_entry, node); + + while (n) { + int rc = strcmp(imsi, n->imsi); + if (rc == 0) { + *cm = n->cm_reject_cause; + *lu = n->lu_reject_cause; + return 1; + } + + n = rb_entry( + (rc < 0) ? n->node.rb_left : n->node.rb_right, + struct bsc_nat_barr_entry, node); + }; + + return 0; +} + +static int insert_barr_node(struct bsc_nat_barr_entry *entry, struct rb_root *root) +{ + struct rb_node **new = &root->rb_node, *parent = NULL; + + while (*new) { + int rc; + struct bsc_nat_barr_entry *this; + this = rb_entry(*new, struct bsc_nat_barr_entry, node); + parent = *new; + + rc = strcmp(entry->imsi, this->imsi); + if (rc < 0) + new = &((*new)->rb_left); + else if (rc > 0) + new = &((*new)->rb_right); + else { + LOGP(DNAT, LOGL_ERROR, + "Duplicate entry for IMSI(%s)\n", entry->imsi); + talloc_free(entry); + return -1; + } + } + + rb_link_node(&entry->node, parent, new); + rb_insert_color(&entry->node, root); + return 0; +} + +int bsc_nat_barr_adapt(void *ctx, struct rb_root *root, + const struct osmo_config_list *list) +{ + struct osmo_config_entry *cfg_entry; + int err = 0; + + /* free the old data */ + while (!RB_EMPTY_ROOT(root)) { + struct rb_node *node = rb_first(root); + rb_erase(node, root); + talloc_free(node); + } + + if (!list) + return 0; + + /* now adapt the new list */ + llist_for_each_entry(cfg_entry, &list->entry, list) { + struct bsc_nat_barr_entry *entry; + entry = talloc_zero(ctx, struct bsc_nat_barr_entry); + if (!entry) { + LOGP(DNAT, LOGL_ERROR, + "Allocation of the barr entry failed.\n"); + continue; + } + + entry->imsi = talloc_strdup(entry, cfg_entry->mcc); + entry->cm_reject_cause = atoi(cfg_entry->mnc); + entry->lu_reject_cause = atoi(cfg_entry->option); + err |= insert_barr_node(entry, root); + } + + return err; +} + + +static int lst_check_deny(struct bsc_nat_acc_lst *lst, const char *mi_string, + int *cm_cause, int *lu_cause) +{ + struct bsc_nat_acc_lst_entry *entry; + + llist_for_each_entry(entry, &lst->fltr_list, list) { + if (!entry->imsi_deny) + continue; + if (regexec(&entry->imsi_deny_re, mi_string, 0, NULL, 0) == 0) { + *cm_cause = entry->cm_reject_cause; + *lu_cause = entry->lu_reject_cause; + return 0; + } + } + + return 1; +} + +/* apply white/black list */ +static int auth_imsi(struct bsc_connection *bsc, const char *imsi, + struct bsc_nat_reject_cause *cause) +{ + /* + * Now apply blacklist/whitelist of the BSC and the NAT. + * 1.) Check the global IMSI barr list + * 2.) Allow directly if the IMSI is allowed at the BSC + * 3.) Reject if the IMSI is not allowed at the BSC + * 4.) Reject if the IMSI not allowed at the global level. + * 5.) Allow directly if the IMSI is allowed at the global level + */ + int cm, lu; + struct bsc_nat_acc_lst *nat_lst = NULL; + struct bsc_nat_acc_lst *bsc_lst = NULL; + + /* 1. global check for barred imsis */ + if (bsc_nat_barr_find(&bsc->nat->imsi_black_list, imsi, &cm, &lu)) { + cause->cm_reject_cause = cm; + cause->lu_reject_cause = lu; + LOGP(DNAT, LOGL_DEBUG, + "Blocking subscriber IMSI %s with CM: %d LU: %d\n", + imsi, cm, lu); + return -4; + } + + + bsc_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->cfg->acc_lst_name); + nat_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->nat->acc_lst_name); + + + if (bsc_lst) { + /* 2. BSC allow */ + if (bsc_nat_lst_check_allow(bsc_lst, imsi) == 0) + return 1; + + /* 3. BSC deny */ + if (lst_check_deny(bsc_lst, imsi, &cm, &lu) == 0) { + LOGP(DNAT, LOGL_ERROR, + "Filtering %s by imsi_deny on bsc nr: %d.\n", imsi, bsc->cfg->nr); + rate_ctr_inc(&bsc_lst->stats->ctr[ACC_LIST_BSC_FILTER]); + cause->cm_reject_cause = cm; + cause->lu_reject_cause = lu; + return -2; + } + + } + + /* 4. NAT deny */ + if (nat_lst) { + if (lst_check_deny(nat_lst, imsi, &cm, &lu) == 0) { + LOGP(DNAT, LOGL_ERROR, + "Filtering %s by nat imsi_deny on bsc nr: %d.\n", imsi, bsc->cfg->nr); + rate_ctr_inc(&nat_lst->stats->ctr[ACC_LIST_NAT_FILTER]); + cause->cm_reject_cause = cm; + cause->lu_reject_cause = lu; + return -3; + } + } + + return 1; +} + +static int _cr_check_loc_upd(struct bsc_connection *bsc, + uint8_t *data, unsigned int length, + char **imsi) +{ + uint8_t mi_type; + struct gsm48_loc_upd_req *lu; + char mi_string[GSM48_MI_SIZE]; + + if (length < sizeof(*lu)) { + LOGP(DNAT, LOGL_ERROR, + "LU does not fit. Length is %d \n", length); + return -1; + } + + lu = (struct gsm48_loc_upd_req *) data; + mi_type = lu->mi[0] & GSM_MI_TYPE_MASK; + + /* + * We can only deal with the IMSI. This will fail for a phone that + * will send the TMSI of a previous network to us. + */ + if (mi_type != GSM_MI_TYPE_IMSI) + return 0; + + gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len); + *imsi = talloc_strdup(bsc, mi_string); + return 1; +} + +static int _cr_check_cm_serv_req(struct bsc_connection *bsc, + uint8_t *data, unsigned int length, + int *con_type, char **imsi) +{ + static const uint32_t classmark_offset = + offsetof(struct gsm48_service_request, classmark); + + char mi_string[GSM48_MI_SIZE]; + uint8_t mi_type; + int rc; + struct gsm48_service_request *req; + + /* unfortunately in Phase1 the classmark2 length is variable */ + + if (length < sizeof(*req)) { + LOGP(DNAT, LOGL_ERROR, + "CM Serv Req does not fit. Length is %d\n", length); + return -1; + } + + req = (struct gsm48_service_request *) data; + if (req->cm_service_type == 0x8) + *con_type = NAT_CON_TYPE_SSA; + rc = gsm48_extract_mi((uint8_t *) &req->classmark, + length - classmark_offset, mi_string, &mi_type); + if (rc < 0) { + LOGP(DNAT, LOGL_ERROR, "Failed to parse the classmark2/mi. error: %d\n", rc); + return -1; + } + + /* we have to let the TMSI or such pass */ + if (mi_type != GSM_MI_TYPE_IMSI) + return 0; + + *imsi = talloc_strdup(bsc, mi_string); + return 1; +} + +static int _cr_check_pag_resp(struct bsc_connection *bsc, + uint8_t *data, unsigned int length, char **imsi) +{ + struct gsm48_pag_resp *resp; + char mi_string[GSM48_MI_SIZE]; + uint8_t mi_type; + + if (length < sizeof(*resp)) { + LOGP(DNAT, LOGL_ERROR, "PAG RESP does not fit. Length was %d.\n", length); + return -1; + } + + resp = (struct gsm48_pag_resp *) data; + if (gsm48_paging_extract_mi(resp, length, mi_string, &mi_type) < 0) { + LOGP(DNAT, LOGL_ERROR, "Failed to extract the MI.\n"); + return -1; + } + + /* we need to let it pass for now */ + if (mi_type != GSM_MI_TYPE_IMSI) + return 0; + + *imsi = talloc_strdup(bsc, mi_string); + return 1; +} + +static int _dt_check_id_resp(struct bsc_connection *bsc, + uint8_t *data, unsigned int length, + struct nat_sccp_connection *con, + struct bsc_nat_reject_cause *cause) +{ + char mi_string[GSM48_MI_SIZE]; + uint8_t mi_type; + + if (length < 2) { + LOGP(DNAT, LOGL_ERROR, "mi does not fit.\n"); + return -1; + } + + if (data[0] < length - 1) { + LOGP(DNAT, LOGL_ERROR, "mi length too big.\n"); + return -2; + } + + mi_type = data[1] & GSM_MI_TYPE_MASK; + gsm48_mi_to_string(mi_string, sizeof(mi_string), &data[1], data[0]); + + if (mi_type != GSM_MI_TYPE_IMSI) + return 0; + + con->imsi_checked = 1; + con->imsi = talloc_strdup(con, mi_string); + return auth_imsi(bsc, mi_string, cause); +} + + +/* Filter out CR data... */ +int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, + struct bsc_nat_parsed *parsed, int *con_type, + char **imsi, struct bsc_nat_reject_cause *cause) +{ + struct tlv_parsed tp; + struct gsm48_hdr *hdr48; + int hdr48_len; + int len, ret = 0; + uint8_t msg_type, proto; + + *con_type = NAT_CON_TYPE_NONE; + cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; + cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; + *imsi = NULL; + + if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) { + LOGP(DNAT, LOGL_ERROR, + "Rejecting CR message due wrong GSM Type %d\n", parsed->gsm_type); + return -1; + } + + /* the parsed has had some basic l3 length check */ + len = msg->l3h[1]; + if (msgb_l3len(msg) - 3 < len) { + LOGP(DNAT, LOGL_ERROR, + "The CR Data has not enough space...\n"); + return -1; + } + + msg->l4h = &msg->l3h[3]; + len -= 1; + + tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h, len, 0, 0); + + if (!TLVP_PRESENT(&tp, GSM0808_IE_LAYER_3_INFORMATION)) { + LOGP(DNAT, LOGL_ERROR, "CR Data does not contain layer3 information.\n"); + return -1; + } + + hdr48_len = TLVP_LEN(&tp, GSM0808_IE_LAYER_3_INFORMATION); + + if (hdr48_len < sizeof(*hdr48)) { + LOGP(DNAT, LOGL_ERROR, "GSM48 header does not fit.\n"); + return -1; + } + + hdr48 = (struct gsm48_hdr *) TLVP_VAL(&tp, GSM0808_IE_LAYER_3_INFORMATION); + + proto = hdr48->proto_discr & 0x0f; + msg_type = hdr48->msg_type & 0xbf; + if (proto == GSM48_PDISC_MM && + msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) { + *con_type = NAT_CON_TYPE_LU; + ret = _cr_check_loc_upd(bsc, &hdr48->data[0], + hdr48_len - sizeof(*hdr48), imsi); + } else if (proto == GSM48_PDISC_MM && + msg_type == GSM48_MT_MM_CM_SERV_REQ) { + *con_type = NAT_CON_TYPE_CM_SERV_REQ; + ret = _cr_check_cm_serv_req(bsc, &hdr48->data[0], + hdr48_len - sizeof(*hdr48), + con_type, imsi); + } else if (proto == GSM48_PDISC_RR && + msg_type == GSM48_MT_RR_PAG_RESP) { + *con_type = NAT_CON_TYPE_PAG_RESP; + ret = _cr_check_pag_resp(bsc, &hdr48->data[0], + hdr48_len - sizeof(*hdr48), imsi); + } else { + /* We only want to filter the above, let other things pass */ + *con_type = NAT_CON_TYPE_OTHER; + return 0; + } + + /* check if we are done */ + if (ret != 1) + return ret; + + /* the memory allocation failed */ + if (!*imsi) + return -1; + + /* now check the imsi */ + return auth_imsi(bsc, *imsi, cause); +} + +int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg, + struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, + struct bsc_nat_reject_cause *cause) +{ + uint32_t len; + uint8_t msg_type, proto; + struct gsm48_hdr *hdr48; + + cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; + cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; + + if (con->imsi_checked) + return 0; + + /* only care about DTAP messages */ + if (parsed->bssap != BSSAP_MSG_DTAP) + return 0; + + hdr48 = bsc_unpack_dtap(parsed, msg, &len); + if (!hdr48) + return -1; + + proto = hdr48->proto_discr & 0x0f; + msg_type = hdr48->msg_type & 0xbf; + if (proto != GSM48_PDISC_MM || msg_type != GSM48_MT_MM_ID_RESP) + return 0; + + return _dt_check_id_resp(bsc, &hdr48->data[0], + len - sizeof(*hdr48), con, cause); +} -- cgit v1.2.3 From 973dbaeebdbdbd8fed417cdfd169644093389d05 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 4 Apr 2015 20:47:03 +0200 Subject: filter: Move the method definition to the filter module Move the filter methods to the filter module. This is still only usable for the NAT and the _dt/_cr filter routines need to move back to the bsc_nat in the long run. --- openbsc/src/libfilter/bsc_msg_filter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 64f6d7347..8f2e1cabf 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -2,7 +2,7 @@ * Access filtering */ /* - * (C) 2010-2012 by Holger Hans Peter Freyther + * (C) 2010-2015 by Holger Hans Peter Freyther * (C) 2010-2012 by On-Waves * All Rights Reserved * @@ -21,6 +21,8 @@ * */ +#include + #include #include #include @@ -28,7 +30,6 @@ #include #include -#include #include #include -- cgit v1.2.3 From 4579bb1ed7464d66343d84846314ec66e6f8cccd Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 4 Apr 2015 21:55:08 +0200 Subject: filter: Move the access list management around --- openbsc/src/libfilter/Makefile.am | 3 +- openbsc/src/libfilter/bsc_msg_acc.c | 116 ++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 openbsc/src/libfilter/bsc_msg_acc.c (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/Makefile.am b/openbsc/src/libfilter/Makefile.am index e24ec5f73..d79afb2cb 100644 --- a/openbsc/src/libfilter/Makefile.am +++ b/openbsc/src/libfilter/Makefile.am @@ -5,5 +5,6 @@ AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) \ noinst_LIBRARIES = libfilter.a libfilter_a_SOURCES = \ - bsc_msg_filter.c + bsc_msg_filter.c \ + bsc_msg_acc.c diff --git a/openbsc/src/libfilter/bsc_msg_acc.c b/openbsc/src/libfilter/bsc_msg_acc.c new file mode 100644 index 000000000..947a7b2ed --- /dev/null +++ b/openbsc/src/libfilter/bsc_msg_acc.c @@ -0,0 +1,116 @@ +/* + * (C) 2010-2015 by Holger Hans Peter Freyther + * (C) 2010-2011 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include + +#include + +#include + +static const struct rate_ctr_desc acc_list_ctr_description[] = { + [ACC_LIST_BSC_FILTER] = { "access-list.bsc-filter", "Rejected by rule for BSC"}, + [ACC_LIST_NAT_FILTER] = { "access-list.nat-filter", "Rejected by rule for NAT"}, +}; + +static const struct rate_ctr_group_desc bsc_cfg_acc_list_desc = { + .group_name_prefix = "nat.filter", + .group_description = "NAT Access-List Statistics", + .num_ctr = ARRAY_SIZE(acc_list_ctr_description), + .ctr_desc = acc_list_ctr_description, +}; + + +int bsc_nat_lst_check_allow(struct bsc_nat_acc_lst *lst, const char *mi_string) +{ + struct bsc_nat_acc_lst_entry *entry; + + llist_for_each_entry(entry, &lst->fltr_list, list) { + if (!entry->imsi_allow) + continue; + if (regexec(&entry->imsi_allow_re, mi_string, 0, NULL, 0) == 0) + return 0; + } + + return 1; +} + +struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct bsc_nat *nat, const char *name) +{ + struct bsc_nat_acc_lst *lst; + + if (!name) + return NULL; + + llist_for_each_entry(lst, &nat->access_lists, list) + if (strcmp(lst->name, name) == 0) + return lst; + + return NULL; +} + +struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(struct bsc_nat *nat, const char *name) +{ + struct bsc_nat_acc_lst *lst; + + lst = bsc_nat_acc_lst_find(nat, name); + if (lst) + return lst; + + lst = talloc_zero(nat, struct bsc_nat_acc_lst); + if (!lst) { + LOGP(DNAT, LOGL_ERROR, "Failed to allocate access list"); + return NULL; + } + + /* TODO: get the index right */ + lst->stats = rate_ctr_group_alloc(lst, &bsc_cfg_acc_list_desc, 0); + if (!lst->stats) { + talloc_free(lst); + return NULL; + } + + INIT_LLIST_HEAD(&lst->fltr_list); + lst->name = talloc_strdup(lst, name); + llist_add_tail(&lst->list, &nat->access_lists); + return lst; +} + +void bsc_nat_acc_lst_delete(struct bsc_nat_acc_lst *lst) +{ + llist_del(&lst->list); + rate_ctr_group_free(lst->stats); + talloc_free(lst); +} + +struct bsc_nat_acc_lst_entry *bsc_nat_acc_lst_entry_create(struct bsc_nat_acc_lst *lst) +{ + struct bsc_nat_acc_lst_entry *entry; + + entry = talloc_zero(lst, struct bsc_nat_acc_lst_entry); + if (!entry) + return NULL; + + entry->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; + entry->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; + llist_add_tail(&entry->list, &lst->fltr_list); + return entry; +} + -- cgit v1.2.3 From d04d009f473d89a426c16dd24e5a4c692caf0017 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 4 Apr 2015 22:14:34 +0200 Subject: filter: Move VTY code into the filter module --- openbsc/src/libfilter/Makefile.am | 3 +- openbsc/src/libfilter/bsc_msg_vty.c | 141 ++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 openbsc/src/libfilter/bsc_msg_vty.c (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/Makefile.am b/openbsc/src/libfilter/Makefile.am index d79afb2cb..4dbc59041 100644 --- a/openbsc/src/libfilter/Makefile.am +++ b/openbsc/src/libfilter/Makefile.am @@ -6,5 +6,6 @@ noinst_LIBRARIES = libfilter.a libfilter_a_SOURCES = \ bsc_msg_filter.c \ - bsc_msg_acc.c + bsc_msg_acc.c \ + bsc_msg_vty.c diff --git a/openbsc/src/libfilter/bsc_msg_vty.c b/openbsc/src/libfilter/bsc_msg_vty.c new file mode 100644 index 000000000..070a03da6 --- /dev/null +++ b/openbsc/src/libfilter/bsc_msg_vty.c @@ -0,0 +1,141 @@ +/* (C) 2010-2015 by Holger Hans Peter Freyther + * (C) 2010-2013 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include + +#include + +static struct bsc_nat *_nat; + +DEFUN(cfg_lst_no, + cfg_lst_no_cmd, + "no access-list NAME", + NO_STR "Remove an access-list by name\n" + "The access-list to remove\n") +{ + struct bsc_nat_acc_lst *acc; + acc = bsc_nat_acc_lst_find(_nat, argv[0]); + if (!acc) + return CMD_WARNING; + + bsc_nat_acc_lst_delete(acc); + return CMD_SUCCESS; +} + +DEFUN(show_acc_lst, + show_acc_lst_cmd, + "show access-list NAME", + SHOW_STR "IMSI access list\n" "Name of the access list\n") +{ + struct bsc_nat_acc_lst *acc; + acc = bsc_nat_acc_lst_find(_nat, argv[0]); + if (!acc) + return CMD_WARNING; + + vty_out(vty, "access-list %s%s", acc->name, VTY_NEWLINE); + vty_out_rate_ctr_group(vty, " ", acc->stats); + + return CMD_SUCCESS; +} + +DEFUN(cfg_lst_imsi_allow, + cfg_lst_imsi_allow_cmd, + "access-list NAME imsi-allow [REGEXP]", + "Access list commands\n" + "Name of the access list\n" + "Add allowed IMSI to the list\n" + "Regexp for IMSIs\n") +{ + struct bsc_nat_acc_lst *acc; + struct bsc_nat_acc_lst_entry *entry; + + acc = bsc_nat_acc_lst_get(_nat, argv[0]); + if (!acc) + return CMD_WARNING; + + entry = bsc_nat_acc_lst_entry_create(acc); + if (!entry) + return CMD_WARNING; + + if (gsm_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, argc - 1, &argv[1]) != 0) + return CMD_WARNING; + return CMD_SUCCESS; +} + +DEFUN(cfg_lst_imsi_deny, + cfg_lst_imsi_deny_cmd, + "access-list NAME imsi-deny [REGEXP] (<0-256>) (<0-256>)", + "Access list commands\n" + "Name of the access list\n" + "Add denied IMSI to the list\n" + "Regexp for IMSIs\n" + "CM Service Reject reason\n" + "LU Reject reason\n") +{ + struct bsc_nat_acc_lst *acc; + struct bsc_nat_acc_lst_entry *entry; + + acc = bsc_nat_acc_lst_get(_nat, argv[0]); + if (!acc) + return CMD_WARNING; + + entry = bsc_nat_acc_lst_entry_create(acc); + if (!entry) + return CMD_WARNING; + + if (gsm_parse_reg(acc, &entry->imsi_deny_re, &entry->imsi_deny, argc - 1, &argv[1]) != 0) + return CMD_WARNING; + if (argc >= 3) + entry->cm_reject_cause = atoi(argv[2]); + if (argc >= 4) + entry->lu_reject_cause = atoi(argv[3]); + return CMD_SUCCESS; +} + +void bsc_nat_acc_lst_write(struct vty *vty, struct bsc_nat_acc_lst *lst) +{ + struct bsc_nat_acc_lst_entry *entry; + + llist_for_each_entry(entry, &lst->fltr_list, list) { + if (entry->imsi_allow) + vty_out(vty, " access-list %s imsi-allow %s%s", + lst->name, entry->imsi_allow, VTY_NEWLINE); + if (entry->imsi_deny) + vty_out(vty, " access-list %s imsi-deny %s %d %d%s", + lst->name, entry->imsi_deny, + entry->cm_reject_cause, entry->lu_reject_cause, + VTY_NEWLINE); + } +} + + +void bsc_nat_lst_vty_init(struct bsc_nat *nat, int node) +{ + _nat = nat; + + install_element_ve(&show_acc_lst_cmd); + + /* access-list */ + install_element(node, &cfg_lst_imsi_allow_cmd); + install_element(node, &cfg_lst_imsi_deny_cmd); + install_element(node, &cfg_lst_no_cmd); +} -- cgit v1.2.3 From d7e04b9956bb7d579697604fff6ba67fc6b9e52d Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 4 Apr 2015 22:28:32 +0200 Subject: filter: Cease out "struct bsc_nat" from the API This means we need to require a talloc context and simply operate on the list. I had considered creating a structure to hold the list head but I didn't find any other members so omitted it for now. --- openbsc/src/libfilter/bsc_msg_acc.c | 12 ++++++------ openbsc/src/libfilter/bsc_msg_filter.c | 4 ++-- openbsc/src/libfilter/bsc_msg_vty.c | 19 +++++++++---------- 3 files changed, 17 insertions(+), 18 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_acc.c b/openbsc/src/libfilter/bsc_msg_acc.c index 947a7b2ed..cc6c44405 100644 --- a/openbsc/src/libfilter/bsc_msg_acc.c +++ b/openbsc/src/libfilter/bsc_msg_acc.c @@ -52,29 +52,29 @@ int bsc_nat_lst_check_allow(struct bsc_nat_acc_lst *lst, const char *mi_string) return 1; } -struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct bsc_nat *nat, const char *name) +struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct llist_head *head, const char *name) { struct bsc_nat_acc_lst *lst; if (!name) return NULL; - llist_for_each_entry(lst, &nat->access_lists, list) + llist_for_each_entry(lst, head, list) if (strcmp(lst->name, name) == 0) return lst; return NULL; } -struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(struct bsc_nat *nat, const char *name) +struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(void *ctx, struct llist_head *head, const char *name) { struct bsc_nat_acc_lst *lst; - lst = bsc_nat_acc_lst_find(nat, name); + lst = bsc_nat_acc_lst_find(head, name); if (lst) return lst; - lst = talloc_zero(nat, struct bsc_nat_acc_lst); + lst = talloc_zero(ctx, struct bsc_nat_acc_lst); if (!lst) { LOGP(DNAT, LOGL_ERROR, "Failed to allocate access list"); return NULL; @@ -89,7 +89,7 @@ struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(struct bsc_nat *nat, const char *nam INIT_LLIST_HEAD(&lst->fltr_list); lst->name = talloc_strdup(lst, name); - llist_add_tail(&lst->list, &nat->access_lists); + llist_add_tail(&lst->list, head); return lst; } diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 8f2e1cabf..1f7a14e63 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -168,8 +168,8 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, } - bsc_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->cfg->acc_lst_name); - nat_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->nat->acc_lst_name); + bsc_lst = bsc_nat_acc_lst_find(&bsc->nat->access_lists, bsc->cfg->acc_lst_name); + nat_lst = bsc_nat_acc_lst_find(&bsc->nat->access_lists, bsc->nat->acc_lst_name); if (bsc_lst) { diff --git a/openbsc/src/libfilter/bsc_msg_vty.c b/openbsc/src/libfilter/bsc_msg_vty.c index 070a03da6..79cf03db1 100644 --- a/openbsc/src/libfilter/bsc_msg_vty.c +++ b/openbsc/src/libfilter/bsc_msg_vty.c @@ -18,13 +18,13 @@ */ #include -#include #include #include #include -static struct bsc_nat *_nat; +static struct llist_head *_acc_lst; +static void *_ctx; DEFUN(cfg_lst_no, cfg_lst_no_cmd, @@ -33,7 +33,7 @@ DEFUN(cfg_lst_no, "The access-list to remove\n") { struct bsc_nat_acc_lst *acc; - acc = bsc_nat_acc_lst_find(_nat, argv[0]); + acc = bsc_nat_acc_lst_find(_acc_lst, argv[0]); if (!acc) return CMD_WARNING; @@ -47,7 +47,7 @@ DEFUN(show_acc_lst, SHOW_STR "IMSI access list\n" "Name of the access list\n") { struct bsc_nat_acc_lst *acc; - acc = bsc_nat_acc_lst_find(_nat, argv[0]); + acc = bsc_nat_acc_lst_find(_acc_lst, argv[0]); if (!acc) return CMD_WARNING; @@ -68,7 +68,7 @@ DEFUN(cfg_lst_imsi_allow, struct bsc_nat_acc_lst *acc; struct bsc_nat_acc_lst_entry *entry; - acc = bsc_nat_acc_lst_get(_nat, argv[0]); + acc = bsc_nat_acc_lst_get(_ctx, _acc_lst, argv[0]); if (!acc) return CMD_WARNING; @@ -94,7 +94,7 @@ DEFUN(cfg_lst_imsi_deny, struct bsc_nat_acc_lst *acc; struct bsc_nat_acc_lst_entry *entry; - acc = bsc_nat_acc_lst_get(_nat, argv[0]); + acc = bsc_nat_acc_lst_get(_ctx, _acc_lst, argv[0]); if (!acc) return CMD_WARNING; @@ -127,11 +127,10 @@ void bsc_nat_acc_lst_write(struct vty *vty, struct bsc_nat_acc_lst *lst) } } - -void bsc_nat_lst_vty_init(struct bsc_nat *nat, int node) +void bsc_nat_lst_vty_init(void *ctx, struct llist_head *lst, int node) { - _nat = nat; - + _ctx = ctx; + _acc_lst = lst; install_element_ve(&show_acc_lst_cmd); /* access-list */ -- cgit v1.2.3 From a1e6bd6768e61828823da3ba774e55b6f89559fc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 4 Apr 2015 22:40:12 +0200 Subject: filter: Remove nat from bsc_nat_acc_lst and replace with msg --- openbsc/src/libfilter/bsc_msg_acc.c | 24 ++++++++++++------------ openbsc/src/libfilter/bsc_msg_filter.c | 14 +++++++------- openbsc/src/libfilter/bsc_msg_vty.c | 32 ++++++++++++++++---------------- 3 files changed, 35 insertions(+), 35 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_acc.c b/openbsc/src/libfilter/bsc_msg_acc.c index cc6c44405..d2f45b36f 100644 --- a/openbsc/src/libfilter/bsc_msg_acc.c +++ b/openbsc/src/libfilter/bsc_msg_acc.c @@ -38,9 +38,9 @@ static const struct rate_ctr_group_desc bsc_cfg_acc_list_desc = { }; -int bsc_nat_lst_check_allow(struct bsc_nat_acc_lst *lst, const char *mi_string) +int bsc_msg_acc_lst_check_allow(struct bsc_msg_acc_lst *lst, const char *mi_string) { - struct bsc_nat_acc_lst_entry *entry; + struct bsc_msg_acc_lst_entry *entry; llist_for_each_entry(entry, &lst->fltr_list, list) { if (!entry->imsi_allow) @@ -52,9 +52,9 @@ int bsc_nat_lst_check_allow(struct bsc_nat_acc_lst *lst, const char *mi_string) return 1; } -struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct llist_head *head, const char *name) +struct bsc_msg_acc_lst *bsc_msg_acc_lst_find(struct llist_head *head, const char *name) { - struct bsc_nat_acc_lst *lst; + struct bsc_msg_acc_lst *lst; if (!name) return NULL; @@ -66,15 +66,15 @@ struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct llist_head *head, const char return NULL; } -struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(void *ctx, struct llist_head *head, const char *name) +struct bsc_msg_acc_lst *bsc_msg_acc_lst_get(void *ctx, struct llist_head *head, const char *name) { - struct bsc_nat_acc_lst *lst; + struct bsc_msg_acc_lst *lst; - lst = bsc_nat_acc_lst_find(head, name); + lst = bsc_msg_acc_lst_find(head, name); if (lst) return lst; - lst = talloc_zero(ctx, struct bsc_nat_acc_lst); + lst = talloc_zero(ctx, struct bsc_msg_acc_lst); if (!lst) { LOGP(DNAT, LOGL_ERROR, "Failed to allocate access list"); return NULL; @@ -93,18 +93,18 @@ struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(void *ctx, struct llist_head *head, return lst; } -void bsc_nat_acc_lst_delete(struct bsc_nat_acc_lst *lst) +void bsc_msg_acc_lst_delete(struct bsc_msg_acc_lst *lst) { llist_del(&lst->list); rate_ctr_group_free(lst->stats); talloc_free(lst); } -struct bsc_nat_acc_lst_entry *bsc_nat_acc_lst_entry_create(struct bsc_nat_acc_lst *lst) +struct bsc_msg_acc_lst_entry *bsc_msg_acc_lst_entry_create(struct bsc_msg_acc_lst *lst) { - struct bsc_nat_acc_lst_entry *entry; + struct bsc_msg_acc_lst_entry *entry; - entry = talloc_zero(lst, struct bsc_nat_acc_lst_entry); + entry = talloc_zero(lst, struct bsc_msg_acc_lst_entry); if (!entry) return NULL; diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 1f7a14e63..19367a013 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -123,10 +123,10 @@ int bsc_nat_barr_adapt(void *ctx, struct rb_root *root, } -static int lst_check_deny(struct bsc_nat_acc_lst *lst, const char *mi_string, +static int lst_check_deny(struct bsc_msg_acc_lst *lst, const char *mi_string, int *cm_cause, int *lu_cause) { - struct bsc_nat_acc_lst_entry *entry; + struct bsc_msg_acc_lst_entry *entry; llist_for_each_entry(entry, &lst->fltr_list, list) { if (!entry->imsi_deny) @@ -154,8 +154,8 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, * 5.) Allow directly if the IMSI is allowed at the global level */ int cm, lu; - struct bsc_nat_acc_lst *nat_lst = NULL; - struct bsc_nat_acc_lst *bsc_lst = NULL; + struct bsc_msg_acc_lst *nat_lst = NULL; + struct bsc_msg_acc_lst *bsc_lst = NULL; /* 1. global check for barred imsis */ if (bsc_nat_barr_find(&bsc->nat->imsi_black_list, imsi, &cm, &lu)) { @@ -168,13 +168,13 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, } - bsc_lst = bsc_nat_acc_lst_find(&bsc->nat->access_lists, bsc->cfg->acc_lst_name); - nat_lst = bsc_nat_acc_lst_find(&bsc->nat->access_lists, bsc->nat->acc_lst_name); + bsc_lst = bsc_msg_acc_lst_find(&bsc->nat->access_lists, bsc->cfg->acc_lst_name); + nat_lst = bsc_msg_acc_lst_find(&bsc->nat->access_lists, bsc->nat->acc_lst_name); if (bsc_lst) { /* 2. BSC allow */ - if (bsc_nat_lst_check_allow(bsc_lst, imsi) == 0) + if (bsc_msg_acc_lst_check_allow(bsc_lst, imsi) == 0) return 1; /* 3. BSC deny */ diff --git a/openbsc/src/libfilter/bsc_msg_vty.c b/openbsc/src/libfilter/bsc_msg_vty.c index 79cf03db1..c342fdca0 100644 --- a/openbsc/src/libfilter/bsc_msg_vty.c +++ b/openbsc/src/libfilter/bsc_msg_vty.c @@ -32,12 +32,12 @@ DEFUN(cfg_lst_no, NO_STR "Remove an access-list by name\n" "The access-list to remove\n") { - struct bsc_nat_acc_lst *acc; - acc = bsc_nat_acc_lst_find(_acc_lst, argv[0]); + struct bsc_msg_acc_lst *acc; + acc = bsc_msg_acc_lst_find(_acc_lst, argv[0]); if (!acc) return CMD_WARNING; - bsc_nat_acc_lst_delete(acc); + bsc_msg_acc_lst_delete(acc); return CMD_SUCCESS; } @@ -46,8 +46,8 @@ DEFUN(show_acc_lst, "show access-list NAME", SHOW_STR "IMSI access list\n" "Name of the access list\n") { - struct bsc_nat_acc_lst *acc; - acc = bsc_nat_acc_lst_find(_acc_lst, argv[0]); + struct bsc_msg_acc_lst *acc; + acc = bsc_msg_acc_lst_find(_acc_lst, argv[0]); if (!acc) return CMD_WARNING; @@ -65,14 +65,14 @@ DEFUN(cfg_lst_imsi_allow, "Add allowed IMSI to the list\n" "Regexp for IMSIs\n") { - struct bsc_nat_acc_lst *acc; - struct bsc_nat_acc_lst_entry *entry; + struct bsc_msg_acc_lst *acc; + struct bsc_msg_acc_lst_entry *entry; - acc = bsc_nat_acc_lst_get(_ctx, _acc_lst, argv[0]); + acc = bsc_msg_acc_lst_get(_ctx, _acc_lst, argv[0]); if (!acc) return CMD_WARNING; - entry = bsc_nat_acc_lst_entry_create(acc); + entry = bsc_msg_acc_lst_entry_create(acc); if (!entry) return CMD_WARNING; @@ -91,14 +91,14 @@ DEFUN(cfg_lst_imsi_deny, "CM Service Reject reason\n" "LU Reject reason\n") { - struct bsc_nat_acc_lst *acc; - struct bsc_nat_acc_lst_entry *entry; + struct bsc_msg_acc_lst *acc; + struct bsc_msg_acc_lst_entry *entry; - acc = bsc_nat_acc_lst_get(_ctx, _acc_lst, argv[0]); + acc = bsc_msg_acc_lst_get(_ctx, _acc_lst, argv[0]); if (!acc) return CMD_WARNING; - entry = bsc_nat_acc_lst_entry_create(acc); + entry = bsc_msg_acc_lst_entry_create(acc); if (!entry) return CMD_WARNING; @@ -111,9 +111,9 @@ DEFUN(cfg_lst_imsi_deny, return CMD_SUCCESS; } -void bsc_nat_acc_lst_write(struct vty *vty, struct bsc_nat_acc_lst *lst) +void bsc_msg_acc_lst_write(struct vty *vty, struct bsc_msg_acc_lst *lst) { - struct bsc_nat_acc_lst_entry *entry; + struct bsc_msg_acc_lst_entry *entry; llist_for_each_entry(entry, &lst->fltr_list, list) { if (entry->imsi_allow) @@ -127,7 +127,7 @@ void bsc_nat_acc_lst_write(struct vty *vty, struct bsc_nat_acc_lst *lst) } } -void bsc_nat_lst_vty_init(void *ctx, struct llist_head *lst, int node) +void bsc_msg_lst_vty_init(void *ctx, struct llist_head *lst, int node) { _ctx = ctx; _acc_lst = lst; -- cgit v1.2.3 From 14b2cd9f321974e211f3291a6ccc2d1aaaf948d1 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 16:50:34 +0200 Subject: filter: Rename BSC to LOCAL and NAT to GLOBAL --- openbsc/src/libfilter/bsc_msg_acc.c | 4 ++-- openbsc/src/libfilter/bsc_msg_filter.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_acc.c b/openbsc/src/libfilter/bsc_msg_acc.c index d2f45b36f..6258b3577 100644 --- a/openbsc/src/libfilter/bsc_msg_acc.c +++ b/openbsc/src/libfilter/bsc_msg_acc.c @@ -26,8 +26,8 @@ #include static const struct rate_ctr_desc acc_list_ctr_description[] = { - [ACC_LIST_BSC_FILTER] = { "access-list.bsc-filter", "Rejected by rule for BSC"}, - [ACC_LIST_NAT_FILTER] = { "access-list.nat-filter", "Rejected by rule for NAT"}, + [ACC_LIST_LOCAL_FILTER] = { "access-list.local-filter", "Rejected by rule for local"}, + [ACC_LIST_GLOBAL_FILTER]= { "access-list.global-filter", "Rejected by rule for global"}, }; static const struct rate_ctr_group_desc bsc_cfg_acc_list_desc = { diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 19367a013..e72ec0a37 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -181,7 +181,7 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, if (lst_check_deny(bsc_lst, imsi, &cm, &lu) == 0) { LOGP(DNAT, LOGL_ERROR, "Filtering %s by imsi_deny on bsc nr: %d.\n", imsi, bsc->cfg->nr); - rate_ctr_inc(&bsc_lst->stats->ctr[ACC_LIST_BSC_FILTER]); + rate_ctr_inc(&bsc_lst->stats->ctr[ACC_LIST_LOCAL_FILTER]); cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; return -2; @@ -194,7 +194,7 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, if (lst_check_deny(nat_lst, imsi, &cm, &lu) == 0) { LOGP(DNAT, LOGL_ERROR, "Filtering %s by nat imsi_deny on bsc nr: %d.\n", imsi, bsc->cfg->nr); - rate_ctr_inc(&nat_lst->stats->ctr[ACC_LIST_NAT_FILTER]); + rate_ctr_inc(&nat_lst->stats->ctr[ACC_LIST_GLOBAL_FILTER]); cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; return -3; -- cgit v1.2.3 From c36a6d5705830a6fd6e41e684dc031db35165e04 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 16:55:28 +0200 Subject: filter: More renaming and remove of "NAT" from it --- openbsc/src/libfilter/bsc_msg_filter.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index e72ec0a37..5f8bff004 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -38,10 +38,10 @@ #include -int bsc_nat_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu) +int bsc_filter_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu) { - struct bsc_nat_barr_entry *n; - n = rb_entry(root->rb_node, struct bsc_nat_barr_entry, node); + struct bsc_filter_barr_entry *n; + n = rb_entry(root->rb_node, struct bsc_filter_barr_entry, node); while (n) { int rc = strcmp(imsi, n->imsi); @@ -53,20 +53,20 @@ int bsc_nat_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu) n = rb_entry( (rc < 0) ? n->node.rb_left : n->node.rb_right, - struct bsc_nat_barr_entry, node); + struct bsc_filter_barr_entry, node); }; return 0; } -static int insert_barr_node(struct bsc_nat_barr_entry *entry, struct rb_root *root) +static int insert_barr_node(struct bsc_filter_barr_entry *entry, struct rb_root *root) { struct rb_node **new = &root->rb_node, *parent = NULL; while (*new) { int rc; - struct bsc_nat_barr_entry *this; - this = rb_entry(*new, struct bsc_nat_barr_entry, node); + struct bsc_filter_barr_entry *this; + this = rb_entry(*new, struct bsc_filter_barr_entry, node); parent = *new; rc = strcmp(entry->imsi, this->imsi); @@ -87,7 +87,7 @@ static int insert_barr_node(struct bsc_nat_barr_entry *entry, struct rb_root *ro return 0; } -int bsc_nat_barr_adapt(void *ctx, struct rb_root *root, +int bsc_filter_barr_adapt(void *ctx, struct rb_root *root, const struct osmo_config_list *list) { struct osmo_config_entry *cfg_entry; @@ -105,8 +105,8 @@ int bsc_nat_barr_adapt(void *ctx, struct rb_root *root, /* now adapt the new list */ llist_for_each_entry(cfg_entry, &list->entry, list) { - struct bsc_nat_barr_entry *entry; - entry = talloc_zero(ctx, struct bsc_nat_barr_entry); + struct bsc_filter_barr_entry *entry; + entry = talloc_zero(ctx, struct bsc_filter_barr_entry); if (!entry) { LOGP(DNAT, LOGL_ERROR, "Allocation of the barr entry failed.\n"); @@ -143,7 +143,7 @@ static int lst_check_deny(struct bsc_msg_acc_lst *lst, const char *mi_string, /* apply white/black list */ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, - struct bsc_nat_reject_cause *cause) + struct bsc_filter_reject_cause *cause) { /* * Now apply blacklist/whitelist of the BSC and the NAT. @@ -158,7 +158,7 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, struct bsc_msg_acc_lst *bsc_lst = NULL; /* 1. global check for barred imsis */ - if (bsc_nat_barr_find(&bsc->nat->imsi_black_list, imsi, &cm, &lu)) { + if (bsc_filter_barr_find(&bsc->nat->imsi_black_list, imsi, &cm, &lu)) { cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; LOGP(DNAT, LOGL_DEBUG, @@ -300,7 +300,7 @@ static int _cr_check_pag_resp(struct bsc_connection *bsc, static int _dt_check_id_resp(struct bsc_connection *bsc, uint8_t *data, unsigned int length, struct nat_sccp_connection *con, - struct bsc_nat_reject_cause *cause) + struct bsc_filter_reject_cause *cause) { char mi_string[GSM48_MI_SIZE]; uint8_t mi_type; @@ -330,7 +330,7 @@ static int _dt_check_id_resp(struct bsc_connection *bsc, /* Filter out CR data... */ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed, int *con_type, - char **imsi, struct bsc_nat_reject_cause *cause) + char **imsi, struct bsc_filter_reject_cause *cause) { struct tlv_parsed tp; struct gsm48_hdr *hdr48; @@ -414,7 +414,7 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg, struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, - struct bsc_nat_reject_cause *cause) + struct bsc_filter_reject_cause *cause) { uint32_t len; uint8_t msg_type, proto; -- cgit v1.2.3 From 4ba947bf4b80b553a3411ec1fd29c45430bd6c40 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 18:07:45 +0200 Subject: filter: Separate SCCP/BSSAP extraction and gsm48 code For the BSC we will have the gsm48_hdr and don't need to find data within SCCP. For legacy reasons we need to initialize con_type, imsi, reject causes early on and need to do the same in the filter method. --- openbsc/src/libfilter/bsc_msg_filter.c | 58 ++++------------------------------ 1 file changed, 7 insertions(+), 51 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 5f8bff004..a1271a095 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -328,14 +328,12 @@ static int _dt_check_id_resp(struct bsc_connection *bsc, /* Filter out CR data... */ -int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, - struct bsc_nat_parsed *parsed, int *con_type, +int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, + struct bsc_connection *bsc, + int *con_type, char **imsi, struct bsc_filter_reject_cause *cause) { - struct tlv_parsed tp; - struct gsm48_hdr *hdr48; - int hdr48_len; - int len, ret = 0; + int ret = 0; uint8_t msg_type, proto; *con_type = NAT_CON_TYPE_NONE; @@ -343,39 +341,6 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; *imsi = NULL; - if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) { - LOGP(DNAT, LOGL_ERROR, - "Rejecting CR message due wrong GSM Type %d\n", parsed->gsm_type); - return -1; - } - - /* the parsed has had some basic l3 length check */ - len = msg->l3h[1]; - if (msgb_l3len(msg) - 3 < len) { - LOGP(DNAT, LOGL_ERROR, - "The CR Data has not enough space...\n"); - return -1; - } - - msg->l4h = &msg->l3h[3]; - len -= 1; - - tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h, len, 0, 0); - - if (!TLVP_PRESENT(&tp, GSM0808_IE_LAYER_3_INFORMATION)) { - LOGP(DNAT, LOGL_ERROR, "CR Data does not contain layer3 information.\n"); - return -1; - } - - hdr48_len = TLVP_LEN(&tp, GSM0808_IE_LAYER_3_INFORMATION); - - if (hdr48_len < sizeof(*hdr48)) { - LOGP(DNAT, LOGL_ERROR, "GSM48 header does not fit.\n"); - return -1; - } - - hdr48 = (struct gsm48_hdr *) TLVP_VAL(&tp, GSM0808_IE_LAYER_3_INFORMATION); - proto = hdr48->proto_discr & 0x0f; msg_type = hdr48->msg_type & 0xbf; if (proto == GSM48_PDISC_MM && @@ -412,13 +377,12 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, return auth_imsi(bsc, *imsi, cause); } -int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg, - struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, +int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, + struct bsc_connection *bsc, + struct nat_sccp_connection *con, struct bsc_filter_reject_cause *cause) { - uint32_t len; uint8_t msg_type, proto; - struct gsm48_hdr *hdr48; cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; @@ -426,14 +390,6 @@ int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg, if (con->imsi_checked) return 0; - /* only care about DTAP messages */ - if (parsed->bssap != BSSAP_MSG_DTAP) - return 0; - - hdr48 = bsc_unpack_dtap(parsed, msg, &len); - if (!hdr48) - return -1; - proto = hdr48->proto_discr & 0x0f; msg_type = hdr48->msg_type & 0xbf; if (proto != GSM48_PDISC_MM || msg_type != GSM48_MT_MM_ID_RESP) -- cgit v1.2.3 From a0478814bc1c56a9e5648ffecd7c11671804e6ff Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 18:42:45 +0200 Subject: filter: Remove NAT knowledge from auth_imsi Push back the parameters we need to pass. auth_imsi doesn't know anything about the nat now. --- openbsc/src/libfilter/bsc_msg_filter.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index a1271a095..486ed9368 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -142,7 +142,10 @@ static int lst_check_deny(struct bsc_msg_acc_lst *lst, const char *mi_string, } /* apply white/black list */ -static int auth_imsi(struct bsc_connection *bsc, const char *imsi, +static int auth_imsi(struct rb_root *black_list, + struct llist_head *access_lists, + const char *local_lst_name, const char *global_lst_name, + int bsc_nr, const char *imsi, struct bsc_filter_reject_cause *cause) { /* @@ -158,7 +161,7 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, struct bsc_msg_acc_lst *bsc_lst = NULL; /* 1. global check for barred imsis */ - if (bsc_filter_barr_find(&bsc->nat->imsi_black_list, imsi, &cm, &lu)) { + if (bsc_filter_barr_find(black_list, imsi, &cm, &lu)) { cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; LOGP(DNAT, LOGL_DEBUG, @@ -168,8 +171,8 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, } - bsc_lst = bsc_msg_acc_lst_find(&bsc->nat->access_lists, bsc->cfg->acc_lst_name); - nat_lst = bsc_msg_acc_lst_find(&bsc->nat->access_lists, bsc->nat->acc_lst_name); + bsc_lst = bsc_msg_acc_lst_find(access_lists, local_lst_name); + nat_lst = bsc_msg_acc_lst_find(access_lists, global_lst_name); if (bsc_lst) { @@ -180,7 +183,7 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, /* 3. BSC deny */ if (lst_check_deny(bsc_lst, imsi, &cm, &lu) == 0) { LOGP(DNAT, LOGL_ERROR, - "Filtering %s by imsi_deny on bsc nr: %d.\n", imsi, bsc->cfg->nr); + "Filtering %s by imsi_deny on config nr: %d.\n", imsi, bsc_nr); rate_ctr_inc(&bsc_lst->stats->ctr[ACC_LIST_LOCAL_FILTER]); cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; @@ -193,7 +196,7 @@ static int auth_imsi(struct bsc_connection *bsc, const char *imsi, if (nat_lst) { if (lst_check_deny(nat_lst, imsi, &cm, &lu) == 0) { LOGP(DNAT, LOGL_ERROR, - "Filtering %s by nat imsi_deny on bsc nr: %d.\n", imsi, bsc->cfg->nr); + "Filtering %s global imsi_deny on bsc nr: %d.\n", imsi, bsc_nr); rate_ctr_inc(&nat_lst->stats->ctr[ACC_LIST_GLOBAL_FILTER]); cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; @@ -323,7 +326,10 @@ static int _dt_check_id_resp(struct bsc_connection *bsc, con->imsi_checked = 1; con->imsi = talloc_strdup(con, mi_string); - return auth_imsi(bsc, mi_string, cause); + return auth_imsi(&bsc->nat->imsi_black_list, + &bsc->nat->access_lists, + bsc->cfg->acc_lst_name, bsc->nat->acc_lst_name, + bsc->cfg->nr, mi_string, cause); } @@ -374,7 +380,10 @@ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, return -1; /* now check the imsi */ - return auth_imsi(bsc, *imsi, cause); + return auth_imsi(&bsc->nat->imsi_black_list, + &bsc->nat->access_lists, + bsc->cfg->acc_lst_name, bsc->nat->acc_lst_name, + bsc->cfg->nr, *imsi, cause); } int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, -- cgit v1.2.3 From 71857d72426c75e4bb71c3843a9eeeff53eca37d Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 18:48:27 +0200 Subject: filter: Put all the parameters in a struct to avoid order issues With the "local" and "global" list name we might pick the wrong argument. Avoid it by passing them as a struct. --- openbsc/src/libfilter/bsc_msg_filter.c | 50 +++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 486ed9368..a24e9de8b 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -38,6 +38,14 @@ #include +struct filter_request { + struct rb_root *black_list; + struct llist_head *access_lists; + const char *local_lst_name; + const char *global_lst_name; + int bsc_nr; +}; + int bsc_filter_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu) { struct bsc_filter_barr_entry *n; @@ -142,10 +150,8 @@ static int lst_check_deny(struct bsc_msg_acc_lst *lst, const char *mi_string, } /* apply white/black list */ -static int auth_imsi(struct rb_root *black_list, - struct llist_head *access_lists, - const char *local_lst_name, const char *global_lst_name, - int bsc_nr, const char *imsi, +static int auth_imsi(struct filter_request *req, + const char *imsi, struct bsc_filter_reject_cause *cause) { /* @@ -161,7 +167,7 @@ static int auth_imsi(struct rb_root *black_list, struct bsc_msg_acc_lst *bsc_lst = NULL; /* 1. global check for barred imsis */ - if (bsc_filter_barr_find(black_list, imsi, &cm, &lu)) { + if (bsc_filter_barr_find(req->black_list, imsi, &cm, &lu)) { cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; LOGP(DNAT, LOGL_DEBUG, @@ -171,8 +177,8 @@ static int auth_imsi(struct rb_root *black_list, } - bsc_lst = bsc_msg_acc_lst_find(access_lists, local_lst_name); - nat_lst = bsc_msg_acc_lst_find(access_lists, global_lst_name); + bsc_lst = bsc_msg_acc_lst_find(req->access_lists, req->local_lst_name); + nat_lst = bsc_msg_acc_lst_find(req->access_lists, req->global_lst_name); if (bsc_lst) { @@ -183,7 +189,7 @@ static int auth_imsi(struct rb_root *black_list, /* 3. BSC deny */ if (lst_check_deny(bsc_lst, imsi, &cm, &lu) == 0) { LOGP(DNAT, LOGL_ERROR, - "Filtering %s by imsi_deny on config nr: %d.\n", imsi, bsc_nr); + "Filtering %s by imsi_deny on config nr: %d.\n", imsi, req->bsc_nr); rate_ctr_inc(&bsc_lst->stats->ctr[ACC_LIST_LOCAL_FILTER]); cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; @@ -196,7 +202,7 @@ static int auth_imsi(struct rb_root *black_list, if (nat_lst) { if (lst_check_deny(nat_lst, imsi, &cm, &lu) == 0) { LOGP(DNAT, LOGL_ERROR, - "Filtering %s global imsi_deny on bsc nr: %d.\n", imsi, bsc_nr); + "Filtering %s global imsi_deny on bsc nr: %d.\n", imsi, req->bsc_nr); rate_ctr_inc(&nat_lst->stats->ctr[ACC_LIST_GLOBAL_FILTER]); cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; @@ -300,7 +306,7 @@ static int _cr_check_pag_resp(struct bsc_connection *bsc, return 1; } -static int _dt_check_id_resp(struct bsc_connection *bsc, +static int _dt_check_id_resp(struct filter_request *req, uint8_t *data, unsigned int length, struct nat_sccp_connection *con, struct bsc_filter_reject_cause *cause) @@ -326,10 +332,7 @@ static int _dt_check_id_resp(struct bsc_connection *bsc, con->imsi_checked = 1; con->imsi = talloc_strdup(con, mi_string); - return auth_imsi(&bsc->nat->imsi_black_list, - &bsc->nat->access_lists, - bsc->cfg->acc_lst_name, bsc->nat->acc_lst_name, - bsc->cfg->nr, mi_string, cause); + return auth_imsi(req, mi_string, cause); } @@ -339,6 +342,7 @@ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, int *con_type, char **imsi, struct bsc_filter_reject_cause *cause) { + struct filter_request req; int ret = 0; uint8_t msg_type, proto; @@ -380,10 +384,12 @@ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, return -1; /* now check the imsi */ - return auth_imsi(&bsc->nat->imsi_black_list, - &bsc->nat->access_lists, - bsc->cfg->acc_lst_name, bsc->nat->acc_lst_name, - bsc->cfg->nr, *imsi, cause); + req.black_list = &bsc->nat->imsi_black_list; + req.access_lists = &bsc->nat->access_lists; + req.local_lst_name = bsc->cfg->acc_lst_name; + req.global_lst_name = bsc->nat->acc_lst_name; + req.bsc_nr = bsc->cfg->nr; + return auth_imsi(&req, *imsi, cause); } int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, @@ -391,6 +397,7 @@ int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, struct nat_sccp_connection *con, struct bsc_filter_reject_cause *cause) { + struct filter_request req; uint8_t msg_type, proto; cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; @@ -404,6 +411,11 @@ int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, if (proto != GSM48_PDISC_MM || msg_type != GSM48_MT_MM_ID_RESP) return 0; - return _dt_check_id_resp(bsc, &hdr48->data[0], + req.black_list = &bsc->nat->imsi_black_list; + req.access_lists = &bsc->nat->access_lists; + req.local_lst_name = bsc->cfg->acc_lst_name; + req.global_lst_name = bsc->nat->acc_lst_name; + req.bsc_nr = bsc->cfg->nr; + return _dt_check_id_resp(&req, &hdr48->data[0], len - sizeof(*hdr48), con, cause); } -- cgit v1.2.3 From 81dbfe412c8196df443f38bf4fbea4f9897607ef Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 18:58:55 +0200 Subject: filter: Remove the bsc_connection from the internal functions --- openbsc/src/libfilter/bsc_msg_filter.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index a24e9de8b..b836f432d 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -213,7 +213,7 @@ static int auth_imsi(struct filter_request *req, return 1; } -static int _cr_check_loc_upd(struct bsc_connection *bsc, +static int _cr_check_loc_upd(void *ctx, uint8_t *data, unsigned int length, char **imsi) { @@ -238,11 +238,11 @@ static int _cr_check_loc_upd(struct bsc_connection *bsc, return 0; gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len); - *imsi = talloc_strdup(bsc, mi_string); + *imsi = talloc_strdup(ctx, mi_string); return 1; } -static int _cr_check_cm_serv_req(struct bsc_connection *bsc, +static int _cr_check_cm_serv_req(void *ctx, uint8_t *data, unsigned int length, int *con_type, char **imsi) { @@ -276,11 +276,11 @@ static int _cr_check_cm_serv_req(struct bsc_connection *bsc, if (mi_type != GSM_MI_TYPE_IMSI) return 0; - *imsi = talloc_strdup(bsc, mi_string); + *imsi = talloc_strdup(ctx, mi_string); return 1; } -static int _cr_check_pag_resp(struct bsc_connection *bsc, +static int _cr_check_pag_resp(void *ctx, uint8_t *data, unsigned int length, char **imsi) { struct gsm48_pag_resp *resp; @@ -302,7 +302,7 @@ static int _cr_check_pag_resp(struct bsc_connection *bsc, if (mi_type != GSM_MI_TYPE_IMSI) return 0; - *imsi = talloc_strdup(bsc, mi_string); + *imsi = talloc_strdup(ctx, mi_string); return 1; } -- cgit v1.2.3 From c09f8a3b7fb94ccef41e33c32bfe2bff1ffe0e44 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 19:13:27 +0200 Subject: filter: Remove nat_sccp_connection from public API --- openbsc/src/libfilter/bsc_msg_filter.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index b836f432d..52c71b99c 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -306,9 +306,9 @@ static int _cr_check_pag_resp(void *ctx, return 1; } -static int _dt_check_id_resp(struct filter_request *req, +static int _dt_check_id_resp(void *ctx, struct filter_request *req, uint8_t *data, unsigned int length, - struct nat_sccp_connection *con, + struct bsc_filter_state *state, struct bsc_filter_reject_cause *cause) { char mi_string[GSM48_MI_SIZE]; @@ -330,8 +330,8 @@ static int _dt_check_id_resp(struct filter_request *req, if (mi_type != GSM_MI_TYPE_IMSI) return 0; - con->imsi_checked = 1; - con->imsi = talloc_strdup(con, mi_string); + state->imsi_checked = 1; + state->imsi = talloc_strdup(ctx, mi_string); return auth_imsi(req, mi_string, cause); } @@ -394,7 +394,7 @@ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, struct bsc_connection *bsc, - struct nat_sccp_connection *con, + struct bsc_filter_state *state, struct bsc_filter_reject_cause *cause) { struct filter_request req; @@ -403,7 +403,7 @@ int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; - if (con->imsi_checked) + if (state->imsi_checked) return 0; proto = hdr48->proto_discr & 0x0f; @@ -416,6 +416,6 @@ int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, req.local_lst_name = bsc->cfg->acc_lst_name; req.global_lst_name = bsc->nat->acc_lst_name; req.bsc_nr = bsc->cfg->nr; - return _dt_check_id_resp(&req, &hdr48->data[0], - len - sizeof(*hdr48), con, cause); + return _dt_check_id_resp(bsc, &req, &hdr48->data[0], + len - sizeof(*hdr48), state, cause); } -- cgit v1.2.3 From 4e8176d0c9c9a98f32cb4541b4f986de0011d4b9 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 19:20:09 +0200 Subject: filter: Remove bsc_connection from the filter API Remove the last occurence of NAT datastructures in the filtering module and add the ctx to the filter request structure. --- openbsc/src/libfilter/bsc_msg_filter.c | 40 +++++++++------------------------- 1 file changed, 10 insertions(+), 30 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 52c71b99c..159f6ccec 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -38,14 +38,6 @@ #include -struct filter_request { - struct rb_root *black_list; - struct llist_head *access_lists; - const char *local_lst_name; - const char *global_lst_name; - int bsc_nr; -}; - int bsc_filter_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu) { struct bsc_filter_barr_entry *n; @@ -150,7 +142,7 @@ static int lst_check_deny(struct bsc_msg_acc_lst *lst, const char *mi_string, } /* apply white/black list */ -static int auth_imsi(struct filter_request *req, +static int auth_imsi(struct bsc_filter_request *req, const char *imsi, struct bsc_filter_reject_cause *cause) { @@ -306,7 +298,7 @@ static int _cr_check_pag_resp(void *ctx, return 1; } -static int _dt_check_id_resp(void *ctx, struct filter_request *req, +static int _dt_check_id_resp(struct bsc_filter_request *req, uint8_t *data, unsigned int length, struct bsc_filter_state *state, struct bsc_filter_reject_cause *cause) @@ -331,18 +323,17 @@ static int _dt_check_id_resp(void *ctx, struct filter_request *req, return 0; state->imsi_checked = 1; - state->imsi = talloc_strdup(ctx, mi_string); + state->imsi = talloc_strdup(req->ctx, mi_string); return auth_imsi(req, mi_string, cause); } /* Filter out CR data... */ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, - struct bsc_connection *bsc, + struct bsc_filter_request *req, int *con_type, char **imsi, struct bsc_filter_reject_cause *cause) { - struct filter_request req; int ret = 0; uint8_t msg_type, proto; @@ -356,18 +347,18 @@ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, if (proto == GSM48_PDISC_MM && msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) { *con_type = NAT_CON_TYPE_LU; - ret = _cr_check_loc_upd(bsc, &hdr48->data[0], + ret = _cr_check_loc_upd(req->ctx, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi); } else if (proto == GSM48_PDISC_MM && msg_type == GSM48_MT_MM_CM_SERV_REQ) { *con_type = NAT_CON_TYPE_CM_SERV_REQ; - ret = _cr_check_cm_serv_req(bsc, &hdr48->data[0], + ret = _cr_check_cm_serv_req(req->ctx, &hdr48->data[0], hdr48_len - sizeof(*hdr48), con_type, imsi); } else if (proto == GSM48_PDISC_RR && msg_type == GSM48_MT_RR_PAG_RESP) { *con_type = NAT_CON_TYPE_PAG_RESP; - ret = _cr_check_pag_resp(bsc, &hdr48->data[0], + ret = _cr_check_pag_resp(req->ctx, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi); } else { /* We only want to filter the above, let other things pass */ @@ -384,20 +375,14 @@ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, return -1; /* now check the imsi */ - req.black_list = &bsc->nat->imsi_black_list; - req.access_lists = &bsc->nat->access_lists; - req.local_lst_name = bsc->cfg->acc_lst_name; - req.global_lst_name = bsc->nat->acc_lst_name; - req.bsc_nr = bsc->cfg->nr; - return auth_imsi(&req, *imsi, cause); + return auth_imsi(req, *imsi, cause); } int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, - struct bsc_connection *bsc, + struct bsc_filter_request *req, struct bsc_filter_state *state, struct bsc_filter_reject_cause *cause) { - struct filter_request req; uint8_t msg_type, proto; cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; @@ -411,11 +396,6 @@ int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len, if (proto != GSM48_PDISC_MM || msg_type != GSM48_MT_MM_ID_RESP) return 0; - req.black_list = &bsc->nat->imsi_black_list; - req.access_lists = &bsc->nat->access_lists; - req.local_lst_name = bsc->cfg->acc_lst_name; - req.global_lst_name = bsc->nat->acc_lst_name; - req.bsc_nr = bsc->cfg->nr; - return _dt_check_id_resp(bsc, &req, &hdr48->data[0], + return _dt_check_id_resp(req, &hdr48->data[0], len - sizeof(*hdr48), state, cause); } -- cgit v1.2.3 From 06a88fa0ae1f86cef0a23a1462bfef950418ea36 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 19:34:12 +0200 Subject: filter: Move from DNAT to DFILTER category --- openbsc/src/libfilter/bsc_msg_filter.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 159f6ccec..c3d1bed9d 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -75,7 +75,7 @@ static int insert_barr_node(struct bsc_filter_barr_entry *entry, struct rb_root else if (rc > 0) new = &((*new)->rb_right); else { - LOGP(DNAT, LOGL_ERROR, + LOGP(DFILTER, LOGL_ERROR, "Duplicate entry for IMSI(%s)\n", entry->imsi); talloc_free(entry); return -1; @@ -108,7 +108,7 @@ int bsc_filter_barr_adapt(void *ctx, struct rb_root *root, struct bsc_filter_barr_entry *entry; entry = talloc_zero(ctx, struct bsc_filter_barr_entry); if (!entry) { - LOGP(DNAT, LOGL_ERROR, + LOGP(DFILTER, LOGL_ERROR, "Allocation of the barr entry failed.\n"); continue; } @@ -162,7 +162,7 @@ static int auth_imsi(struct bsc_filter_request *req, if (bsc_filter_barr_find(req->black_list, imsi, &cm, &lu)) { cause->cm_reject_cause = cm; cause->lu_reject_cause = lu; - LOGP(DNAT, LOGL_DEBUG, + LOGP(DFILTER, LOGL_DEBUG, "Blocking subscriber IMSI %s with CM: %d LU: %d\n", imsi, cm, lu); return -4; @@ -180,7 +180,7 @@ static int auth_imsi(struct bsc_filter_request *req, /* 3. BSC deny */ if (lst_check_deny(bsc_lst, imsi, &cm, &lu) == 0) { - LOGP(DNAT, LOGL_ERROR, + LOGP(DFILTER, LOGL_ERROR, "Filtering %s by imsi_deny on config nr: %d.\n", imsi, req->bsc_nr); rate_ctr_inc(&bsc_lst->stats->ctr[ACC_LIST_LOCAL_FILTER]); cause->cm_reject_cause = cm; @@ -193,7 +193,7 @@ static int auth_imsi(struct bsc_filter_request *req, /* 4. NAT deny */ if (nat_lst) { if (lst_check_deny(nat_lst, imsi, &cm, &lu) == 0) { - LOGP(DNAT, LOGL_ERROR, + LOGP(DFILTER, LOGL_ERROR, "Filtering %s global imsi_deny on bsc nr: %d.\n", imsi, req->bsc_nr); rate_ctr_inc(&nat_lst->stats->ctr[ACC_LIST_GLOBAL_FILTER]); cause->cm_reject_cause = cm; @@ -214,7 +214,7 @@ static int _cr_check_loc_upd(void *ctx, char mi_string[GSM48_MI_SIZE]; if (length < sizeof(*lu)) { - LOGP(DNAT, LOGL_ERROR, + LOGP(DFILTER, LOGL_ERROR, "LU does not fit. Length is %d \n", length); return -1; } @@ -249,7 +249,7 @@ static int _cr_check_cm_serv_req(void *ctx, /* unfortunately in Phase1 the classmark2 length is variable */ if (length < sizeof(*req)) { - LOGP(DNAT, LOGL_ERROR, + LOGP(DFILTER, LOGL_ERROR, "CM Serv Req does not fit. Length is %d\n", length); return -1; } @@ -260,7 +260,7 @@ static int _cr_check_cm_serv_req(void *ctx, rc = gsm48_extract_mi((uint8_t *) &req->classmark, length - classmark_offset, mi_string, &mi_type); if (rc < 0) { - LOGP(DNAT, LOGL_ERROR, "Failed to parse the classmark2/mi. error: %d\n", rc); + LOGP(DFILTER, LOGL_ERROR, "Failed to parse the classmark2/mi. error: %d\n", rc); return -1; } @@ -280,13 +280,13 @@ static int _cr_check_pag_resp(void *ctx, uint8_t mi_type; if (length < sizeof(*resp)) { - LOGP(DNAT, LOGL_ERROR, "PAG RESP does not fit. Length was %d.\n", length); + LOGP(DFILTER, LOGL_ERROR, "PAG RESP does not fit. Length was %d.\n", length); return -1; } resp = (struct gsm48_pag_resp *) data; if (gsm48_paging_extract_mi(resp, length, mi_string, &mi_type) < 0) { - LOGP(DNAT, LOGL_ERROR, "Failed to extract the MI.\n"); + LOGP(DFILTER, LOGL_ERROR, "Failed to extract the MI.\n"); return -1; } @@ -307,12 +307,12 @@ static int _dt_check_id_resp(struct bsc_filter_request *req, uint8_t mi_type; if (length < 2) { - LOGP(DNAT, LOGL_ERROR, "mi does not fit.\n"); + LOGP(DFILTER, LOGL_ERROR, "mi does not fit.\n"); return -1; } if (data[0] < length - 1) { - LOGP(DNAT, LOGL_ERROR, "mi length too big.\n"); + LOGP(DFILTER, LOGL_ERROR, "mi length too big.\n"); return -2; } -- cgit v1.2.3 From c652913674ecc30f8d234878a17baa623cbacf99 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 21:03:49 +0200 Subject: filter: Move the con_type into the filter_state --- openbsc/src/libfilter/bsc_msg_filter.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index c3d1bed9d..2bbfa078e 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -256,7 +256,7 @@ static int _cr_check_cm_serv_req(void *ctx, req = (struct gsm48_service_request *) data; if (req->cm_service_type == 0x8) - *con_type = NAT_CON_TYPE_SSA; + *con_type = FLT_CON_TYPE_SSA; rc = gsm48_extract_mi((uint8_t *) &req->classmark, length - classmark_offset, mi_string, &mi_type); if (rc < 0) { @@ -337,7 +337,7 @@ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, int ret = 0; uint8_t msg_type, proto; - *con_type = NAT_CON_TYPE_NONE; + *con_type = FLT_CON_TYPE_NONE; cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED; *imsi = NULL; @@ -346,23 +346,23 @@ int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len, msg_type = hdr48->msg_type & 0xbf; if (proto == GSM48_PDISC_MM && msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) { - *con_type = NAT_CON_TYPE_LU; + *con_type = FLT_CON_TYPE_LU; ret = _cr_check_loc_upd(req->ctx, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi); } else if (proto == GSM48_PDISC_MM && msg_type == GSM48_MT_MM_CM_SERV_REQ) { - *con_type = NAT_CON_TYPE_CM_SERV_REQ; + *con_type = FLT_CON_TYPE_CM_SERV_REQ; ret = _cr_check_cm_serv_req(req->ctx, &hdr48->data[0], hdr48_len - sizeof(*hdr48), con_type, imsi); } else if (proto == GSM48_PDISC_RR && msg_type == GSM48_MT_RR_PAG_RESP) { - *con_type = NAT_CON_TYPE_PAG_RESP; + *con_type = FLT_CON_TYPE_PAG_RESP; ret = _cr_check_pag_resp(req->ctx, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi); } else { /* We only want to filter the above, let other things pass */ - *con_type = NAT_CON_TYPE_OTHER; + *con_type = FLT_CON_TYPE_OTHER; return 0; } -- cgit v1.2.3 From ec0cb7c64d5d42e8d0d599b209a3eabacfceba60 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 5 Apr 2015 20:53:42 +0200 Subject: bsc: Add access list filtering to the BSC --- openbsc/src/libfilter/bsc_msg_filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc/src/libfilter') diff --git a/openbsc/src/libfilter/bsc_msg_filter.c b/openbsc/src/libfilter/bsc_msg_filter.c index 2bbfa078e..be518a478 100644 --- a/openbsc/src/libfilter/bsc_msg_filter.c +++ b/openbsc/src/libfilter/bsc_msg_filter.c @@ -159,7 +159,7 @@ static int auth_imsi(struct bsc_filter_request *req, 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, -- cgit v1.2.3