aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-03-29 17:41:01 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-03-29 17:43:32 +0200
commitd21b4d7f9867bfc00c86e5cf26bc5a056a03ef24 (patch)
tree6dad9fdad7e00ebe867bb22a26a30a682cae6311 /openbsc
parent3bdaa69fb2c449cd217c0c7bd6d6866d9f1091a1 (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.c54
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;
}
}