aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-04-08 11:28:12 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-04-08 11:28:12 +0200
commit59f2470650ae7fefed3d7313aebe17acc8a59494 (patch)
tree6dd748279795cb3e5b7f100a18583b24f2c244a2
parent339dfdb62470e4b98e1c91e9303ce85cf2c2f480 (diff)
nat: Handle unknown RLSD by send a RLC back to the network.
-rw-r--r--openbsc/src/nat/bsc_nat.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index 0fe9ce9c4..8897cc39f 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -153,6 +153,32 @@ static void nat_send_rlsd(struct sccp_connections *conn)
}
}
+static void nat_send_rlc(struct sccp_source_reference *src,
+ struct sccp_source_reference *dst)
+{
+ struct sccp_connection_release_complete *rlc;
+ struct msgb *msg;
+
+ msg = msgb_alloc_headroom(4096, 128, "rlc");
+ if (!msg) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n");
+ return;
+ }
+
+ msg->l2h = msgb_put(msg, sizeof(*rlc));
+ rlc = (struct sccp_connection_release_complete *) msg->l2h;
+ rlc->type = SCCP_MSG_TYPE_RLC;
+ rlc->destination_local_reference = *dst;
+ rlc->source_local_reference = *src;
+
+ ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
+
+ if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
+ LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
+ msgb_free(msg);
+ }
+}
+
static void send_mgcp_reset(struct bsc_connection *bsc)
{
static const u_int8_t mgcp_reset[] = {
@@ -254,7 +280,11 @@ static int forward_sccp_to_bts(struct msgb *msg)
goto exit;
}
- if (!con)
+ if (!con && parsed->sccp_type == SCCP_MSG_TYPE_RLSD) {
+ LOGP(DNAT, LOGL_NOTICE, "Sending fake RLC on RLSD message to network.\n");
+ /* Exchange src/dest for the reply */
+ nat_send_rlc(parsed->dest_local_ref, parsed->src_local_ref);
+ } else if (!con)
LOGP(DNAT, LOGL_ERROR, "Unknown connection for msg type: 0x%x.\n", parsed->sccp_type);
}