summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-06-01 01:03:13 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-06-01 01:03:13 +0800
commitdf342ea82bdca152c7ebfab91857e4a508b37597 (patch)
tree2ca487ea80d4f5ca813c803bf0fcc606593602fd
parent049eb23b73c0827936888aa555c5eb9866f9ef27 (diff)
[nat] Introduce the concept of access-list
One can set one access-list to one BSC and one access-list to one NAT. The matching of IMSIs remains the same for now, also applying the white/blacklist. Access lists can not be deleted for now and no perf opt is done (e.g. one could cache the result of the last lookup in the bsc struct).
-rw-r--r--openbsc/include/openbsc/bsc_nat.h28
-rw-r--r--openbsc/src/nat/bsc_nat_utils.c53
-rw-r--r--openbsc/src/nat/bsc_nat_vty.c110
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c12
4 files changed, 152 insertions, 51 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index f39afafb7..5d28e4c9d 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -165,10 +165,7 @@ struct bsc_config {
char *description;
/* imsi white and blacklist */
- char *imsi_allow;
- regex_t imsi_allow_re;
- char *imsi_deny;
- regex_t imsi_deny_re;
+ char *acc_lst_name;
int forbid_paging;
@@ -207,6 +204,19 @@ struct bsc_nat_statistics {
} msc;
};
+struct bsc_nat_access_list {
+ struct llist_head list;
+
+ /* the name of the list */
+ const char *name;
+
+ /* the filter */
+ char *imsi_allow;
+ regex_t imsi_allow_re;
+ char *imsi_deny;
+ regex_t imsi_deny_re;
+};
+
/**
* the structure of the "nat" network
*/
@@ -217,6 +227,9 @@ struct bsc_nat {
/* active BSC connections that need patching */
struct llist_head bsc_connections;
+ /* access lists */
+ struct llist_head access_lists;
+
/* known BSC's */
struct llist_head bsc_configs;
int num_bsc;
@@ -243,8 +256,7 @@ struct bsc_nat {
struct bsc_endpoint *bsc_endpoints;
/* filter */
- char *imsi_deny;
- regex_t imsi_deny_re;
+ char *acc_lst_name;
/* statistics */
struct bsc_nat_statistics stats;
@@ -310,7 +322,9 @@ int bsc_mgcp_extract_ci(const char *resp);
int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
-/* regexp handling */
+/* IMSI allow/deny handling */
void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv);
+struct bsc_nat_access_list *bsc_nat_accs_list_find(struct bsc_nat *nat, const char *name);
+struct bsc_nat_access_list *bsc_nat_accs_list_get(struct bsc_nat *nat, const char *name);
#endif
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index 5890c07cb..eeb3198e1 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -46,6 +46,8 @@ struct bsc_nat *bsc_nat_alloc(void)
INIT_LLIST_HEAD(&nat->sccp_connections);
INIT_LLIST_HEAD(&nat->bsc_connections);
INIT_LLIST_HEAD(&nat->bsc_configs);
+ INIT_LLIST_HEAD(&nat->access_lists);
+
nat->stats.sccp.conn = counter_alloc("nat.sccp.conn");
nat->stats.sccp.calls = counter_alloc("nat.sccp.calls");
nat->stats.bsc.reconn = counter_alloc("nat.bsc.conn");
@@ -203,10 +205,16 @@ static int auth_imsi(struct bsc_connection *bsc, const char *mi_string)
* 3.) Reject if the IMSI not allowed at the global level.
* 4.) Allow directly if the IMSI is allowed at the global level
*/
+ struct bsc_nat_access_list *nat_lst = NULL;
+ struct bsc_nat_access_list *bsc_lst = NULL;
+
+ bsc_lst = bsc_nat_accs_list_find(bsc->nat, bsc->cfg->acc_lst_name);
+ nat_lst = bsc_nat_accs_list_find(bsc->nat, bsc->nat->acc_lst_name);
+
/* 1. BSC deny */
- if (bsc->cfg->imsi_deny) {
- if (regexec(&bsc->cfg->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
+ if (bsc_lst && bsc_lst->imsi_deny) {
+ if (regexec(&bsc_lst->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
LOGP(DNAT, LOGL_ERROR,
"Filtering %s by imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
return -2;
@@ -214,14 +222,14 @@ static int auth_imsi(struct bsc_connection *bsc, const char *mi_string)
}
/* 2. BSC allow */
- if (bsc->cfg->imsi_allow) {
- if (regexec(&bsc->cfg->imsi_allow_re, mi_string, 0, NULL, 0) == 0)
+ if (bsc_lst && bsc_lst->imsi_allow) {
+ if (regexec(&bsc_lst->imsi_allow_re, mi_string, 0, NULL, 0) == 0)
return 0;
}
/* 3. NAT deny */
- if (bsc->nat->imsi_deny) {
- if (regexec(&bsc->nat->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
+ if (nat_lst && nat_lst->imsi_deny) {
+ if (regexec(&nat_lst->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
LOGP(DNAT, LOGL_ERROR,
"Filtering %s by nat imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
return -3;
@@ -403,3 +411,36 @@ const char *bsc_con_type_to_string(int type)
{
return con_types[type];
}
+
+struct bsc_nat_access_list *bsc_nat_accs_list_find(struct bsc_nat *nat, const char *name)
+{
+ struct bsc_nat_access_list *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_access_list *bsc_nat_accs_list_get(struct bsc_nat *nat, const char *name)
+{
+ struct bsc_nat_access_list *lst;
+
+ lst = bsc_nat_accs_list_find(nat, name);
+ if (lst)
+ return lst;
+
+ lst = talloc_zero(nat, struct bsc_nat_access_list);
+ if (!lst) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to allocate access list");
+ return NULL;
+ }
+
+ lst->name = talloc_strdup(lst, name);
+ llist_add(&lst->list, &nat->access_lists);
+ return lst;
+}
diff --git a/openbsc/src/nat/bsc_nat_vty.c b/openbsc/src/nat/bsc_nat_vty.c
index cef47d1b3..e77a896a2 100644
--- a/openbsc/src/nat/bsc_nat_vty.c
+++ b/openbsc/src/nat/bsc_nat_vty.c
@@ -51,9 +51,9 @@ static struct cmd_node bsc_node = {
static int config_write_nat(struct vty *vty)
{
+ struct bsc_nat_access_list *lst;
+
vty_out(vty, "nat%s", VTY_NEWLINE);
- if (_nat->imsi_deny)
- vty_out(vty, " imsi deny %s%s", _nat->imsi_deny, VTY_NEWLINE);
vty_out(vty, " msc ip %s%s", _nat->msc_ip, VTY_NEWLINE);
vty_out(vty, " msc port %d%s", _nat->msc_port, VTY_NEWLINE);
vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE);
@@ -62,6 +62,18 @@ static int config_write_nat(struct vty *vty)
if (_nat->token)
vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE);
vty_out(vty, " ip-tos %d%s", _nat->bsc_ip_tos, VTY_NEWLINE);
+ if (_nat->acc_lst_name)
+ 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);
+ }
+
return CMD_SUCCESS;
}
@@ -70,13 +82,11 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
vty_out(vty, " location_area_code %u%s", bsc->lac, VTY_NEWLINE);
- if (bsc->imsi_allow)
- vty_out(vty, " imsi allow %s%s", bsc->imsi_allow, VTY_NEWLINE);
- if (bsc->imsi_deny)
- vty_out(vty, " imsi deny %s%s", bsc->imsi_deny, VTY_NEWLINE);
vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE);
if (bsc->description)
vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE);
+ if (bsc->acc_lst_name)
+ vty_out(vty, " access-list-name %s%s", bsc->acc_lst_name, VTY_NEWLINE);
}
static int config_write_bsc(struct vty *vty)
@@ -137,10 +147,9 @@ DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
vty_out(vty, "BSC token: '%s' lac: %u nr: %u%s",
conf->token, conf->lac, conf->nr, VTY_NEWLINE);
- vty_out(vty, " imsi_allow: '%s' imsi_deny: '%s'%s",
- conf->imsi_allow ? conf->imsi_allow: "any",
- conf->imsi_deny ? conf->imsi_deny : "none",
- VTY_NEWLINE);
+ if (conf->acc_lst_name)
+ vty_out(vty, " access-list: %s%s",
+ conf->acc_lst_name, VTY_NEWLINE);
vty_out(vty, " paging forbidden: %d%s",
conf->forbid_paging, VTY_NEWLINE);
if (conf->description)
@@ -233,16 +242,6 @@ DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configute the NAT")
return CMD_SUCCESS;
}
-DEFUN(cfg_nat_imsi_deny,
- cfg_nat_imsi_deny_cmd,
- "imsi deny [REGEXP]",
- "Deny matching IMSIs to talk to the MSC. "
- "The defualt is to not deny.")
-{
- bsc_parse_reg(_nat, &_nat->imsi_deny_re, &_nat->imsi_deny, argc, argv);
- return CMD_SUCCESS;
-}
-
DEFUN(cfg_nat_msc_ip,
cfg_nat_msc_ip_cmd,
"msc ip A.B.C.D",
@@ -306,6 +305,18 @@ DEFUN(cfg_nat_bsc_ip_tos, cfg_nat_bsc_ip_tos_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_nat_acc_lst_name,
+ cfg_nat_acc_lst_name_cmd,
+ "access-list-name NAME",
+ "Set the name of the access list to use.\n"
+ "The name of the to be used access list.")
+{
+ if (_nat->acc_lst_name)
+ talloc_free(_nat->acc_lst_name);
+ _nat->acc_lst_name = talloc_strdup(_nat, argv[0]);
+ return CMD_SUCCESS;
+}
+
/* per BSC configuration */
DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure")
{
@@ -368,27 +379,53 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
return CMD_SUCCESS;
}
-DEFUN(cfg_bsc_imsi_allow,
- cfg_bsc_imsi_allow_cmd,
- "imsi allow [REGEXP]",
- "Allow IMSIs with the following network to talk to the MSC."
- "The default is to allow everyone)")
+DEFUN(cfg_lst_imsi_allow,
+ cfg_lst_imsi_allow_cmd,
+ "access-list NAME imsi-allow [REGEXP]",
+ "Allow IMSIs matching the REGEXP\n"
+ "The name of the access-list\n"
+ "The regexp of allowed IMSIs\n")
{
+ struct bsc_nat_access_list *acc;
struct bsc_config *conf = vty->index;
- bsc_parse_reg(conf, &conf->imsi_allow_re, &conf->imsi_allow, argc, argv);
+ acc = bsc_nat_accs_list_get(conf->nat, argv[0]);
+ if (!acc)
+ return CMD_WARNING;
+
+ bsc_parse_reg(acc, &acc->imsi_allow_re, &acc->imsi_allow, argc, argv);
return CMD_SUCCESS;
}
-DEFUN(cfg_bsc_imsi_deny,
- cfg_bsc_imsi_deny_cmd,
- "imsi deny [REGEXP]",
- "Deny IMSIs with the following network to talk to the MSC."
- "The default is to not deny anyone.)")
+DEFUN(cfg_lst_imsi_deny,
+ cfg_lst_imsi_deny_cmd,
+ "access-list NAME imsi-deny [REGEXP]",
+ "Allow IMSIs matching the REGEXP\n"
+ "The name of the access-list\n"
+ "The regexp of to be denied IMSIs\n")
{
+ struct bsc_nat_access_list *acc;
struct bsc_config *conf = vty->index;
- bsc_parse_reg(conf, &conf->imsi_deny_re, &conf->imsi_deny, argc, argv);
+ acc = bsc_nat_accs_list_get(conf->nat, argv[0]);
+ if (!acc)
+ return CMD_WARNING;
+
+ bsc_parse_reg(acc, &acc->imsi_deny_re, &acc->imsi_deny, argc, argv);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_acc_lst_name,
+ cfg_bsc_acc_lst_name_cmd,
+ "access-list-name NAME",
+ "Set the name of the access list to use.\n"
+ "The name of the to be used access list.")
+{
+ struct bsc_config *conf = vty->index;
+
+ if (conf->acc_lst_name)
+ talloc_free(conf->acc_lst_name);
+ conf->acc_lst_name = talloc_strdup(conf, argv[0]);
return CMD_SUCCESS;
}
@@ -460,7 +497,6 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(CONFIG_NODE, &cfg_nat_cmd);
install_node(&nat_node, config_write_nat);
install_default(NAT_NODE);
- install_element(NAT_NODE, &cfg_nat_imsi_deny_cmd);
install_element(NAT_NODE, &cfg_nat_msc_ip_cmd);
install_element(NAT_NODE, &cfg_nat_msc_port_cmd);
install_element(NAT_NODE, &cfg_nat_auth_time_cmd);
@@ -468,6 +504,11 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(NAT_NODE, &cfg_nat_pong_time_cmd);
install_element(NAT_NODE, &cfg_nat_token_cmd);
install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd);
+ install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd);
+
+ /* access-list */
+ install_element(NAT_NODE, &cfg_lst_imsi_allow_cmd);
+ install_element(NAT_NODE, &cfg_lst_imsi_deny_cmd);
/* BSC subgroups */
install_element(NAT_NODE, &cfg_bsc_cmd);
@@ -475,10 +516,9 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_default(BSC_NODE);
install_element(BSC_NODE, &cfg_bsc_token_cmd);
install_element(BSC_NODE, &cfg_bsc_lac_cmd);
- install_element(BSC_NODE, &cfg_bsc_imsi_allow_cmd);
- install_element(BSC_NODE, &cfg_bsc_imsi_deny_cmd);
install_element(BSC_NODE, &cfg_bsc_paging_cmd);
install_element(BSC_NODE, &cfg_bsc_desc_cmd);
+ install_element(NAT_NODE, &cfg_bsc_acc_lst_name_cmd);
mgcp_vty_init();
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index 8f3f358fc..d01700f83 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -640,22 +640,28 @@ static void test_cr_filter()
int i, res, contype;
struct msgb *msg = msgb_alloc(4096, "test_cr_filter");
struct bsc_nat_parsed *parsed;
+ struct bsc_nat_access_list *nat_lst, *bsc_lst;
struct bsc_nat *nat = bsc_nat_alloc();
struct bsc_connection *bsc = bsc_connection_alloc(nat);
bsc->cfg = bsc_config_alloc(nat, "foo", 1234);
+ bsc->cfg->acc_lst_name = "bsc";
+ nat->acc_lst_name = "nat";
for (i = 0; i < ARRAY_SIZE(cr_filter); ++i) {
msgb_reset(msg);
copy_to_msg(msg, cr_filter[i].data, cr_filter[i].length);
- bsc_parse_reg(nat, &nat->imsi_deny_re, &nat->imsi_deny,
+ nat_lst = bsc_nat_accs_list_get(nat, "nat");
+ bsc_lst = bsc_nat_accs_list_get(nat, "bsc");
+
+ bsc_parse_reg(nat_lst, &nat_lst->imsi_deny_re, &nat_lst->imsi_deny,
cr_filter[i].nat_imsi_deny ? 1 : 0,
&cr_filter[i].nat_imsi_deny);
- bsc_parse_reg(bsc->cfg, &bsc->cfg->imsi_allow_re, &bsc->cfg->imsi_allow,
+ bsc_parse_reg(bsc_lst, &bsc_lst->imsi_allow_re, &bsc_lst->imsi_allow,
cr_filter[i].bsc_imsi_allow ? 1 : 0,
&cr_filter[i].bsc_imsi_allow);
- bsc_parse_reg(bsc->cfg, &bsc->cfg->imsi_deny_re, &bsc->cfg->imsi_deny,
+ bsc_parse_reg(bsc_lst, &bsc_lst->imsi_deny_re, &bsc_lst->imsi_deny,
cr_filter[i].bsc_imsi_deny ? 1 : 0,
&cr_filter[i].bsc_imsi_deny);