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...
This commit is contained in:
Holger Hans Peter Freyther 2010-03-29 17:41:01 +02:00
parent 3bdaa69fb2
commit d21b4d7f98
1 changed files with 43 additions and 11 deletions

View File

@ -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;
}
}