aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/nat
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-06-08 10:53:39 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-06-15 20:24:21 +0800
commitd77c8171aa22585a46cc9fdff4734a2b6b4f35f1 (patch)
tree2d227ec3d33ad4ef0e67e564cb3ff2453c235c4c /openbsc/src/nat
parent29c67039fe449e9e44f6422fcf122d4263aa56b6 (diff)
nat: Allow to specify multiple entries in the access-list...
Inside the access-list we have a list of entries that have either one allow or one deny rule... we do not allow to remove a single rule but one has to remove the whole list, in that case talloc will handle cleaning all entries. Right now the matching is O(n*m) as we traverse the list (multiple times) and run the regexp multiple times. One way to make it faster would be to concat all regexps into one.
Diffstat (limited to 'openbsc/src/nat')
-rw-r--r--openbsc/src/nat/bsc_nat_utils.c57
-rw-r--r--openbsc/src/nat/bsc_nat_vty.c35
2 files changed, 75 insertions, 17 deletions
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index 663d8bc18..5bb8fb9ac 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -195,6 +195,34 @@ int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int proto)
return 0;
}
+static int 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;
+}
+
+static int lst_check_deny(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_deny)
+ continue;
+ if (regexec(&entry->imsi_deny_re, mi_string, 0, NULL, 0) == 0)
+ return 0;
+ }
+
+ return 1;
+}
+
/* apply white/black list */
static int auth_imsi(struct bsc_connection *bsc, const char *mi_string)
{
@@ -212,24 +240,22 @@ static int auth_imsi(struct bsc_connection *bsc, const char *mi_string)
nat_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->nat->acc_lst_name);
- /* 1. BSC deny */
- if (bsc_lst && bsc_lst->imsi_deny) {
- if (regexec(&bsc_lst->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
+ if (bsc_lst) {
+ /* 1. BSC deny */
+ if (lst_check_deny(bsc_lst, mi_string) == 0) {
LOGP(DNAT, LOGL_ERROR,
"Filtering %s by imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
return -2;
}
- }
- /* 2. BSC allow */
- if (bsc_lst && bsc_lst->imsi_allow) {
- if (regexec(&bsc_lst->imsi_allow_re, mi_string, 0, NULL, 0) == 0)
+ /* 2. BSC allow */
+ if (lst_check_allow(bsc_lst, mi_string) == 0)
return 0;
}
/* 3. NAT deny */
- if (nat_lst && nat_lst->imsi_deny) {
- if (regexec(&nat_lst->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
+ if (nat_lst) {
+ if (lst_check_deny(nat_lst, mi_string) == 0) {
LOGP(DNAT, LOGL_ERROR,
"Filtering %s by nat imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
return -3;
@@ -440,6 +466,7 @@ struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(struct bsc_nat *nat, const char *nam
return NULL;
}
+ INIT_LLIST_HEAD(&lst->fltr_list);
lst->name = talloc_strdup(lst, name);
llist_add(&lst->list, &nat->access_lists);
return lst;
@@ -449,4 +476,16 @@ void bsc_nat_acc_lst_delete(struct bsc_nat_acc_lst *lst)
{
llist_del(&lst->list);
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;
+
+ llist_add(&entry->list, &lst->fltr_list);
+ return entry;
} \ No newline at end of file
diff --git a/openbsc/src/nat/bsc_nat_vty.c b/openbsc/src/nat/bsc_nat_vty.c
index fdd7886e5..22375a87a 100644
--- a/openbsc/src/nat/bsc_nat_vty.c
+++ b/openbsc/src/nat/bsc_nat_vty.c
@@ -49,6 +49,20 @@ static struct cmd_node bsc_node = {
1,
};
+static void write_acc_lst(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%s",
+ lst->name, entry->imsi_deny, VTY_NEWLINE);
+ }
+}
+
static int config_write_nat(struct vty *vty)
{
struct bsc_nat_acc_lst *lst;
@@ -66,12 +80,7 @@ static int config_write_nat(struct vty *vty)
vty_out(vty, " access-list-name %s%s", _nat->acc_lst_name, VTY_NEWLINE);
llist_for_each_entry(lst, &_nat->access_lists, list) {
- if (lst->imsi_allow)
- vty_out(vty, " access-list %s imsi-allow %s%s",
- lst->name, lst->imsi_allow, VTY_NEWLINE);
- if (lst->imsi_deny)
- vty_out(vty, " access-list %s imsi-deny %s%s",
- lst->name, lst->imsi_deny, VTY_NEWLINE);
+ write_acc_lst(vty, lst);
}
return CMD_SUCCESS;
@@ -387,12 +396,17 @@ DEFUN(cfg_lst_imsi_allow,
"The regexp of allowed 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;
- bsc_parse_reg(acc, &acc->imsi_allow_re, &acc->imsi_allow, argc - 1, &argv[1]);
+ entry = bsc_nat_acc_lst_entry_create(acc);
+ if (!entry)
+ return CMD_WARNING;
+
+ bsc_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, argc - 1, &argv[1]);
return CMD_SUCCESS;
}
@@ -404,12 +418,17 @@ DEFUN(cfg_lst_imsi_deny,
"The regexp of to be denied 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;
- bsc_parse_reg(acc, &acc->imsi_deny_re, &acc->imsi_deny, argc - 1, &argv[1]);
+ entry = bsc_nat_acc_lst_entry_create(acc);
+ if (!entry)
+ return CMD_WARNING;
+
+ bsc_parse_reg(acc, &entry->imsi_deny_re, &entry->imsi_deny, argc - 1, &argv[1]);
return CMD_SUCCESS;
}