From 16a6f70834fecfd946ce36583ac738e591a30b10 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 29 Mar 2010 17:18:42 +0200 Subject: [PATCH] nat: Keep track of both sides of the connection On a CC message we will need to remeber where the source local reference of the network belonged so we can properly identify the connection when receiving UDT messages. --- openbsc/include/openbsc/bsc_nat.h | 2 ++ openbsc/src/nat/bsc_nat.c | 4 ++++ openbsc/src/nat/bsc_sccp.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 2f2b8c962..5f730fe6b 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -102,6 +102,7 @@ struct sccp_connections { struct sccp_source_reference real_ref; struct sccp_source_reference patched_ref; + struct sccp_source_reference remote_ref; }; /** @@ -154,6 +155,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat); * SCCP patching and handling */ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed); +int update_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed); void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed); struct bsc_connection *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *); struct bsc_connection *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *); diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c index 65fc10b4e..cafca8352 100644 --- a/openbsc/src/nat/bsc_nat.c +++ b/openbsc/src/nat/bsc_nat.c @@ -191,7 +191,11 @@ static int forward_sccp_to_bts(struct msgb *msg) case SCCP_MSG_TYPE_RLSD: case SCCP_MSG_TYPE_CREF: case SCCP_MSG_TYPE_DT1: + bsc = patch_sccp_src_ref_to_bsc(msg, parsed, nat); + break; case SCCP_MSG_TYPE_CC: + if (update_sccp_src_ref(bsc, msg, parsed) != 0) + goto exit; bsc = patch_sccp_src_ref_to_bsc(msg, parsed, nat); break; case SCCP_MSG_TYPE_RLC: diff --git a/openbsc/src/nat/bsc_sccp.c b/openbsc/src/nat/bsc_sccp.c index 226e2e0d8..e29dc9b84 100644 --- a/openbsc/src/nat/bsc_sccp.c +++ b/openbsc/src/nat/bsc_sccp.c @@ -103,6 +103,34 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc return 0; } +int update_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed) +{ + struct sccp_connections *conn; + + if (!parsed->dest_local_ref || !parsed->src_local_ref) { + LOGP(DNAT, LOGL_ERROR, "CC MSG should contain both local and dest address.\n"); + return -1; + } + + llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) { + if (conn->bsc != bsc) + continue; + + if (memcmp(parsed->dest_local_ref, + &conn->patched_ref, sizeof(conn->patched_ref)) != 0) + continue; + + conn->remote_ref = *parsed->src_local_ref; + LOGP(DNAT, LOGL_DEBUG, "Updating 0x%x to remote 0x%x on 0x%p\n", + sccp_src_ref_to_int(&conn->patched_ref), + sccp_src_ref_to_int(&conn->remote_ref), bsc); + return 0; + } + + LOGP(DNAT, LOGL_ERROR, "Referenced connection not found on BSC: 0x%p\n", bsc); + return -1; +} + void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed) { struct sccp_connections *conn;