aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/bsc_nat.h2
-rw-r--r--openbsc/src/nat/bsc_nat.c4
-rw-r--r--openbsc/src/nat/bsc_sccp.c28
3 files changed, 34 insertions, 0 deletions
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 71da5cd54..061396de8 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 809fe94c8..8ad0dc7e7 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;