diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-03-29 17:41:01 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-03-29 17:43:32 +0200 |
commit | d21b4d7f9867bfc00c86e5cf26bc5a056a03ef24 (patch) | |
tree | 6dad9fdad7e00ebe867bb22a26a30a682cae6311 /openbsc | |
parent | 3bdaa69fb2c449cd217c0c7bd6d6866d9f1091a1 (diff) |
nat: Fix the lookup of connections to and from the BSC
When sending a message to the MSC in the case of DT1
messages we only have the address of the MSC, so we
need to go with that, otherwise (e.g. in case of a CR, RLC)
we do have the source address and need to patch it.
When forwarding a message to the BSC we do receive
a msg that should contain the patched address, we need
to unpatch it...
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/src/nat/bsc_sccp.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/openbsc/src/nat/bsc_sccp.c b/openbsc/src/nat/bsc_sccp.c index 8ad0dc7e7..eed80305c 100644 --- a/openbsc/src/nat/bsc_sccp.c +++ b/openbsc/src/nat/bsc_sccp.c @@ -29,6 +29,11 @@ #include <string.h> +static int equal(struct sccp_source_reference *ref1, struct sccp_source_reference *ref2) +{ + return memcmp(ref1, ref2, sizeof(*ref1)) == 0; +} + /* * SCCP patching below */ @@ -155,34 +160,61 @@ void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bs LOGP(DNAT, LOGL_ERROR, "Unknown connection.\n"); } +/* + * We have a message from the MSC to the BSC. The MSC is using + * an address that was assigned by the MUX, we need to update the + * dest reference to the real network. + */ struct bsc_connection *patch_sccp_src_ref_to_bsc(struct msgb *msg, struct bsc_nat_parsed *parsed, struct bsc_nat *nat) { struct sccp_connections *conn; + + if (!parsed->dest_local_ref) { + LOGP(DNAT, LOGL_ERROR, "MSG should contain dest_local_ref.\n"); + return NULL; + } + + llist_for_each_entry(conn, &nat->sccp_connections, list_entry) { - if (memcmp(parsed->dest_local_ref, - &conn->real_ref, sizeof(*parsed->dest_local_ref)) == 0) { - memcpy(parsed->dest_local_ref, - &conn->patched_ref, sizeof(*parsed->dest_local_ref)); - return conn->bsc; - } + if (!equal(parsed->dest_local_ref, &conn->patched_ref)) + continue; + + /* Change the dest address to the real one */ + *parsed->dest_local_ref = conn->real_ref; + return conn->bsc; } return NULL; } +/* + * These are message to the MSC. We will need to find the BSC + * Connection by either the SRC or the DST local reference. + * + * In case of a CR we need to work by the SRC local reference + * in all other cases we need to work by the destination local + * reference.. + */ struct bsc_connection *patch_sccp_src_ref_to_msc(struct msgb *msg, struct bsc_nat_parsed *parsed, struct bsc_nat *nat) { struct sccp_connections *conn; + llist_for_each_entry(conn, &nat->sccp_connections, list_entry) { - if (memcmp(parsed->src_local_ref, - &conn->real_ref, sizeof(*parsed->src_local_ref)) == 0) { - memcpy(parsed->src_local_ref, - &conn->patched_ref, sizeof(*parsed->src_local_ref)); - return conn->bsc; + if (parsed->src_local_ref) { + if (equal(parsed->src_local_ref, &conn->real_ref)) { + *parsed->src_local_ref = conn->patched_ref; + return conn->bsc; + } + } else if (parsed->dest_local_ref) { + if (equal(parsed->dest_local_ref, &conn->remote_ref)) + return conn->bsc; + } else { + LOGP(DNAT, LOGL_ERROR, "Header has neither loc/dst ref.\n"); + return NULL; } } |