From 67e423c2561a5a08ac7331de2ab264a270b238c9 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 25 Jun 2013 15:38:31 +0200 Subject: nat: Implement a post-routing for the NAT software * The post-routing is applied after the first re-writing. To do this the new number is copied back into the called data structure. * Add a testcase that goes from 0172 to 0049 and then back to 0049 using the post rule with a table lookup. --- openbsc/include/openbsc/bsc_nat.h | 2 + openbsc/src/osmo-bsc_nat/bsc_nat_rewrite.c | 60 +++++++++++++++++++---------- openbsc/src/osmo-bsc_nat/bsc_nat_utils.c | 1 + openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 27 +++++++++++++ openbsc/tests/bsc-nat/bsc_nat_test.c | 61 ++++++++++++++++++++++++++++++ openbsc/tests/bsc-nat/prefixes.csv | 1 + openbsc/tests/vty_test_runner.py | 8 ++++ 7 files changed, 141 insertions(+), 19 deletions(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index f93b596d4..6ebe04560 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -299,6 +299,8 @@ struct bsc_nat { /* number rewriting */ char *num_rewr_name; struct llist_head num_rewr; + char *num_rewr_post_name; + struct llist_head num_rewr_post; char *smsc_rewr_name; struct llist_head smsc_rewr; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_rewrite.c b/openbsc/src/osmo-bsc_nat/bsc_nat_rewrite.c index 5984d962d..3bc602e79 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_rewrite.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_rewrite.c @@ -93,8 +93,9 @@ static char *match_and_rewrite_number(void *ctx, const char *number, return new_number; } -static char *rewrite_isdn_number(struct bsc_nat *nat, void *ctx, const char *imsi, - struct gsm_mncc_number *called) +static char *rewrite_isdn_number(struct bsc_nat *nat, struct llist_head *rewr_list, + void *ctx, const char *imsi, + struct gsm_mncc_number *called) { char int_number[sizeof(called->number) + 2]; char *number = called->number; @@ -114,9 +115,22 @@ static char *rewrite_isdn_number(struct bsc_nat *nat, void *ctx, const char *ims } return match_and_rewrite_number(ctx, number, - imsi, &nat->num_rewr, nat->num_rewr_trie); + imsi, rewr_list, nat->num_rewr_trie); } +static void update_called_number(struct gsm_mncc_number *called, + const char *chosen_number) +{ + if (strncmp(chosen_number, "00", 2) == 0) { + called->type = 1; + strncpy(called->number, chosen_number + 2, sizeof(called->number)); + } else { + /* rewrite international to unknown */ + if (called->type == 1) + called->type = 0; + strncpy(called->number, chosen_number, sizeof(called->number)); + } +} /** * Rewrite non global numbers... according to rules based on the IMSI @@ -129,7 +143,7 @@ static struct msgb *rewrite_setup(struct bsc_nat *nat, struct msgb *msg, unsigned int payload_len; struct gsm_mncc_number called; struct msgb *out; - char *new_number = NULL; + char *new_number_pre = NULL, *new_number_post = NULL, *chosen_number; uint8_t *outptr; const uint8_t *msgptr; int sec_len; @@ -147,16 +161,30 @@ static struct msgb *rewrite_setup(struct bsc_nat *nat, struct msgb *msg, TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) - 1); /* check if it looks international and stop */ - new_number = rewrite_isdn_number(nat, msg, imsi, &called); + new_number_pre = rewrite_isdn_number(nat, &nat->num_rewr, msg, imsi, &called); - if (!new_number) { + if (!new_number_pre) { LOGP(DNAT, LOGL_DEBUG, "No IMSI match found, returning message.\n"); return NULL; } - if (strlen(new_number) > sizeof(called.number)) { + if (strlen(new_number_pre) > sizeof(called.number)) { LOGP(DNAT, LOGL_ERROR, "Number is too long for structure.\n"); - talloc_free(new_number); + talloc_free(new_number_pre); + return NULL; + } + update_called_number(&called, new_number_pre); + + /* another run through the re-write engine with other rules */ + new_number_post = rewrite_isdn_number(nat, &nat->num_rewr_post, msg, + imsi, &called); + chosen_number = new_number_post ? new_number_post : new_number_pre; + + + if (strlen(chosen_number) > sizeof(called.number)) { + LOGP(DNAT, LOGL_ERROR, "Number is too long for structure.\n"); + talloc_free(new_number_pre); + talloc_free(new_number_post); return NULL; } @@ -169,7 +197,8 @@ static struct msgb *rewrite_setup(struct bsc_nat *nat, struct msgb *msg, out = msgb_alloc_headroom(4096, 128, "changed-setup"); if (!out) { LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n"); - talloc_free(new_number); + talloc_free(new_number_pre); + talloc_free(new_number_post); return NULL; } @@ -183,15 +212,7 @@ static struct msgb *rewrite_setup(struct bsc_nat *nat, struct msgb *msg, memcpy(outptr, &hdr48->data[0], sec_len); /* create the new number */ - if (strncmp(new_number, "00", 2) == 0) { - called.type = 1; - strncpy(called.number, new_number + 2, sizeof(called.number)); - } else { - /* rewrite international to unknown */ - if (called.type == 1) - called.type = 0; - strncpy(called.number, new_number, sizeof(called.number)); - } + update_called_number(&called, chosen_number); gsm48_encode_called(out, &called); /* copy thre rest */ @@ -201,7 +222,8 @@ static struct msgb *rewrite_setup(struct bsc_nat *nat, struct msgb *msg, outptr = msgb_put(out, sec_len); memcpy(outptr, msgptr, sec_len); - talloc_free(new_number); + talloc_free(new_number_pre); + talloc_free(new_number_post); return out; } diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c index 45c224ce8..bc8c4c1f3 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c @@ -96,6 +96,7 @@ struct bsc_nat *bsc_nat_alloc(void) INIT_LLIST_HEAD(&nat->access_lists); INIT_LLIST_HEAD(&nat->dests); INIT_LLIST_HEAD(&nat->num_rewr); + INIT_LLIST_HEAD(&nat->num_rewr_post); INIT_LLIST_HEAD(&nat->smsc_rewr); INIT_LLIST_HEAD(&nat->tpdest_match); INIT_LLIST_HEAD(&nat->sms_clear_tp_srr); diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 5404bfbba..0cac79470 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -127,6 +127,10 @@ static int config_write_nat(struct vty *vty) if (_nat->num_rewr_name) vty_out(vty, " number-rewrite %s%s", _nat->num_rewr_name, VTY_NEWLINE); + if (_nat->num_rewr_post_name) + vty_out(vty, " number-rewrite-post %s%s", + _nat->num_rewr_post_name, VTY_NEWLINE); + if (_nat->smsc_rewr_name) vty_out(vty, " rewrite-smsc addr %s%s", _nat->smsc_rewr_name, VTY_NEWLINE); @@ -570,6 +574,27 @@ DEFUN(cfg_nat_no_number_rewrite, return CMD_SUCCESS; } +DEFUN(cfg_nat_number_rewrite_post, + cfg_nat_number_rewrite_post_cmd, + "number-rewrite-post FILENAME", + "Set the file with post-routing rewriting rules.\n" "Filename") +{ + return replace_rules(_nat, &_nat->num_rewr_post_name, + &_nat->num_rewr_post, argv[0]); +} + +DEFUN(cfg_nat_no_number_rewrite_post, + cfg_nat_no_number_rewrite_post_cmd, + "no number-rewrite-post", + NO_STR "Set the file with post-routing rewriting rules.\n") +{ + talloc_free(_nat->num_rewr_post_name); + _nat->num_rewr_post_name = NULL; + + bsc_nat_num_rewr_entry_adapt(NULL, &_nat->num_rewr_post, NULL); + return CMD_SUCCESS; +} + DEFUN(cfg_nat_smsc_addr, cfg_nat_smsc_addr_cmd, "rewrite-smsc addr FILENAME", @@ -1183,6 +1208,8 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* number rewriting */ install_element(NAT_NODE, &cfg_nat_number_rewrite_cmd); install_element(NAT_NODE, &cfg_nat_no_number_rewrite_cmd); + install_element(NAT_NODE, &cfg_nat_number_rewrite_post_cmd); + install_element(NAT_NODE, &cfg_nat_no_number_rewrite_post_cmd); install_element(NAT_NODE, &cfg_nat_smsc_addr_cmd); install_element(NAT_NODE, &cfg_nat_smsc_tpdest_cmd); install_element(NAT_NODE, &cfg_nat_sms_clear_tpsrr_cmd); diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index 2b3041398..5158f46cf 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -1096,6 +1096,66 @@ static void test_setup_rewrite_prefix(void) talloc_free(nat); } +static void test_setup_rewrite_post(void) +{ + struct msgb *msg = msgb_alloc(4096, "test_dt_filter"); + struct msgb *out; + struct bsc_nat_parsed *parsed; + const char *imsi = "27408000001234"; + + struct bsc_nat *nat = bsc_nat_alloc(); + + /* a fake list */ + struct osmo_config_list entries; + struct osmo_config_entry entry; + struct osmo_config_list entries_post; + struct osmo_config_entry entry_post; + + INIT_LLIST_HEAD(&entries.entry); + entry.mcc = "274"; + entry.mnc = "08"; + entry.option = "^0([1-9])"; + entry.text = "0049"; + llist_add_tail(&entry.list, &entries.entry); + bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries); + + /* attempt to undo the previous one */ + INIT_LLIST_HEAD(&entries_post.entry); + entry_post.mcc = "274"; + entry_post.mnc = "08"; + entry_post.option = "^\\+49([1-9])"; + entry_post.text = "prefix_lookup"; + llist_add_tail(&entry_post.list, &entries_post.entry); + bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr_post, &entries_post); + + nat->num_rewr_trie = nat_rewrite_parse(nat, "prefixes.csv"); + + msgb_reset(msg); + copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national)); + parsed = bsc_nat_parse(msg); + if (!parsed) { + printf("FAIL: Could not parse ID resp\n"); + abort(); + } + + out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi); + if (!out) { + printf("FAIL: A new message should be created.\n"); + abort(); + } + + if (msg == out) { + printf("FAIL: The message should have changed\n"); + abort(); + } + + verify_msg(out, cc_setup_national, ARRAY_SIZE(cc_setup_national)); + msgb_free(out); + + bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, NULL); + talloc_free(nat); +} + static void test_sms_smsc_rewrite() { struct msgb *msg = msgb_alloc(4096, "SMSC rewrite"), *out; @@ -1378,6 +1438,7 @@ int main(int argc, char **argv) test_dt_filter(); test_setup_rewrite(); test_setup_rewrite_prefix(); + test_setup_rewrite_post(); test_sms_smsc_rewrite(); test_sms_number_rewrite(); test_mgcp_allocations(); diff --git a/openbsc/tests/bsc-nat/prefixes.csv b/openbsc/tests/bsc-nat/prefixes.csv index 0b66ffe47..0c7660f10 100644 --- a/openbsc/tests/bsc-nat/prefixes.csv +++ b/openbsc/tests/bsc-nat/prefixes.csv @@ -1 +1,2 @@ 0172,0049 ++49,0 diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 91b4684d4..730b8ba67 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -103,6 +103,14 @@ class TestVTYNAT(TestVTYBase): res = self.vty.command("number-rewrite rewrite.cfg") res = self.vty.command("no number-rewrite") + def testRewritePostNoRewrite(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.verify("number-rewrite-post rewrite.cfg", ['']) + self.vty.verify("no number-rewrite-post", ['']) + + def testPrefixTreeLoading(self): cfg = os.path.join(confpath, "tests/bsc-nat-trie/prefixes.csv") -- cgit v1.2.3