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.
This commit is contained in:
parent
d192c9395b
commit
e9c7e27b5c
|
@ -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;
|
||||
|
|
|
@ -93,7 +93,8 @@ 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,
|
||||
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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0172,0049
|
||||
+49,0
|
||||
|
|
|
|
@ -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")
|
||||
|
||||
|
|
Loading…
Reference in New Issue