aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-04-01 08:21:33 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-04-01 08:21:33 +0200
commit9d519189aefc1a872e8388b8264f8cf9b70aca7b (patch)
treefc333ec6c8dc7553525743ae647fbd341491768b
parentf0fc618782dbcb9cfb915184dbe5f218f5346273 (diff)
nat: Handle CRCX/MDCX/DLCX at the nat
* Forward a rewritten msg to the BSS. We change the IP and port to point to the NAT instead of the core network. We also keep track of the BSC and the transacition id. * Handle the case where we have not found a SCCP connection and need to send a response ourselves.
-rw-r--r--openbsc/include/openbsc/bsc_nat.h15
-rw-r--r--openbsc/src/nat/bsc_mgcp_utils.c94
-rw-r--r--openbsc/src/nat/bsc_nat.c31
-rw-r--r--openbsc/src/nat/bsc_nat_utils.c38
4 files changed, 146 insertions, 32 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 068ef68fb..e41849652 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -127,6 +127,16 @@ struct bsc_config {
};
/**
+ * BSCs point of view of endpoints
+ */
+struct bsc_endpoint {
+ /* the pending transaction id */
+ char *transaction_id;
+ /* the bsc we are talking to */
+ struct bsc_connection *bsc;
+};
+
+/**
* the structure of the "nat" network
*/
struct bsc_nat {
@@ -143,6 +153,9 @@ struct bsc_nat {
/* MGCP config */
struct mgcp_config *mgcp_cfg;
struct write_queue mgcp_queue;
+ struct msgb *mgcp_msg;
+
+ struct bsc_endpoint *bsc_endpoints;
};
/* create and init the structures */
@@ -177,9 +190,11 @@ struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat
/**
* MGCP/Audio handling
*/
+int bsc_write_mgcp_msg(struct bsc_connection *bsc, struct msgb *msg);
int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length);
int bsc_mgcp_assign(struct sccp_connections *, struct msgb *msg);
void bsc_mgcp_clear(struct sccp_connections *);
+void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int);
void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
int bsc_mgcp_init(struct bsc_nat *nat);
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
index 3639a7b00..24f66a14f 100644
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -26,6 +26,8 @@
#include <openbsc/mgcp.h>
#include <openbsc/mgcp_internal.h>
+#include <osmocore/talloc.h>
+
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -70,12 +72,23 @@ void bsc_mgcp_clear(struct sccp_connections *con)
con->bsc_timeslot = -1;
}
+void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int i)
+{
+ if (nat->bsc_endpoints[i].transaction_id) {
+ talloc_free(nat->bsc_endpoints[i].transaction_id);
+ nat->bsc_endpoints[i].transaction_id = NULL;
+ }
+
+ nat->bsc_endpoints[i].bsc = NULL;
+ mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
+}
+
void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
{
int i;
for (i = 1; i < nat->mgcp_cfg->number_endpoints; ++i)
- mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
+ bsc_mgcp_free_endpoint(nat, i);
}
struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
@@ -95,6 +108,71 @@ struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
return NULL;
}
+int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const char *transaction_id)
+{
+ struct bsc_nat *nat;
+ struct bsc_endpoint *bsc_endp;
+ struct bsc_connection *bsc_con;
+ struct mgcp_endpoint *mgcp_endp;
+ struct msgb *bsc_msg;
+
+ nat = cfg->data;
+ bsc_endp = &nat->bsc_endpoints[endpoint];
+ mgcp_endp = &nat->mgcp_cfg->endpoints[endpoint];
+
+ bsc_con = bsc_mgcp_find_con(nat, endpoint);
+
+ if (!bsc_con) {
+ LOGP(DMGCP, LOGL_ERROR, "Did not find BSC for a new connection on 0x%x for %d\n", endpoint, state);
+
+ switch (state) {
+ case MGCP_ENDP_CRCX:
+ return MGCP_POLICY_REJECT;
+ break;
+ case MGCP_ENDP_DLCX:
+ return MGCP_POLICY_CONT;
+ break;
+ case MGCP_ENDP_MDCX:
+ return MGCP_POLICY_CONT;
+ break;
+ default:
+ LOGP(DMGCP, LOGL_FATAL, "Unhandled state: %d\n", state);
+ return MGCP_POLICY_CONT;
+ break;
+ }
+ }
+
+ if (bsc_endp->transaction_id) {
+ LOGP(DMGCP, LOGL_ERROR, "One transaction with id '%s' on 0x%x\n",
+ bsc_endp->transaction_id, endpoint);
+ talloc_free(bsc_endp->transaction_id);
+ }
+
+ bsc_endp->transaction_id = talloc_strdup(bsc_endp, transaction_id);
+ bsc_endp->bsc = bsc_con;
+
+ /* we need to update some bits */
+ if (state == MGCP_ENDP_CRCX) {
+ struct sockaddr_in sock;
+ socklen_t len = sizeof(sock);
+ if (getpeername(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &sock, &len) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Can not get the peername...\n");
+ } else {
+ mgcp_endp->bts = sock.sin_addr;
+ }
+ }
+
+ /* we need to generate a new and patched message */
+ bsc_msg = bsc_mgcp_rewrite(nat->mgcp_msg, nat->mgcp_cfg->source_addr, mgcp_endp->rtp_port);
+ if (!bsc_msg) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to patch the msg.\n");
+ return MGCP_POLICY_CONT;
+ }
+
+ bsc_write_mgcp_msg(bsc_con, bsc_msg);
+ return MGCP_POLICY_DEFER;
+}
+
/* we need to replace some strings... */
struct msgb *bsc_mgcp_rewrite(struct msgb *input, const char *ip, int port)
{
@@ -177,9 +255,11 @@ static int mgcp_do_read(struct bsc_fd *fd)
}
nat = fd->data;
+ nat->mgcp_msg = msg;
msg->l2h = msgb_put(msg, rc);
resp = mgcp_handle_message(nat->mgcp_cfg, msg);
msgb_free(msg);
+ nat->mgcp_msg = NULL;
/* we do have a direct answer... e.g. AUEP */
if (resp) {
@@ -216,6 +296,11 @@ int bsc_mgcp_init(struct bsc_nat *nat)
return -1;
}
+ if (nat->mgcp_cfg->bts_ip) {
+ LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
+ return -1;
+ }
+
nat->mgcp_queue.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
if (nat->mgcp_queue.bfd.fd < 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to create MGCP socket. errno: %d\n", errno);
@@ -259,5 +344,12 @@ int bsc_mgcp_init(struct bsc_nat *nat)
return -1;
}
+ /* some more MGCP config handling */
+ nat->mgcp_cfg->data = nat;
+ nat->mgcp_cfg->policy_cb = bsc_mgcp_policy_cb;
+ nat->bsc_endpoints = talloc_zero_array(nat,
+ struct bsc_endpoint,
+ nat->mgcp_cfg->number_endpoints + 1);
+
return 0;
}
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index f505bd5ad..a0115df69 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -175,37 +175,6 @@ static void bsc_write(struct bsc_connection *bsc, const u_int8_t *data, unsigned
}
}
-int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length)
-{
- struct msgb *msg;
-
- if (length > 4096 - 128) {
- LOGP(DINP, LOGL_ERROR, "Can not send message of that size.\n");
- return -1;
- }
-
- msg = msgb_alloc_headroom(4096, 128, "to-bsc");
- if (!msg) {
- LOGP(DINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
- return -1;
- }
-
- /* copy the data */
- msg->l3h = msgb_put(msg, length);
- memcpy(msg->l3h, data, length);
-
- /* prepend the header */
- ipaccess_prepend_header(msg, NAT_IPAC_PROTO_MGCP);
-
- if (write_queue_enqueue(&bsc->write_queue, msg) != 0) {
- LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
- msgb_free(msg);
- return -1;
- }
-
- return 0;
-}
-
static int forward_sccp_to_bts(struct msgb *msg)
{
struct sccp_connections *con;
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index dc6cfec5c..1c68e10fe 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -26,6 +26,7 @@
#include <openbsc/gsm_data.h>
#include <openbsc/bssap.h>
#include <openbsc/debug.h>
+#include <openbsc/ipaccess.h>
#include <osmocore/linuxlist.h>
#include <osmocore/talloc.h>
@@ -123,3 +124,40 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg)
return NULL;
}
+
+int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length)
+{
+ struct msgb *msg;
+
+ if (length > 4096 - 128) {
+ LOGP(DINP, LOGL_ERROR, "Can not send message of that size.\n");
+ return -1;
+ }
+
+ msg = msgb_alloc_headroom(4096, 128, "to-bsc");
+ if (!msg) {
+ LOGP(DINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
+ return -1;
+ }
+
+ /* copy the data */
+ msg->l3h = msgb_put(msg, length);
+ memcpy(msg->l3h, data, length);
+
+ return bsc_write_mgcp_msg(bsc, msg);
+}
+
+int bsc_write_mgcp_msg(struct bsc_connection *bsc, struct msgb *msg)
+{
+ /* prepend the header */
+ ipaccess_prepend_header(msg, NAT_IPAC_PROTO_MGCP);
+
+ if (write_queue_enqueue(&bsc->write_queue, msg) != 0) {
+ LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+ return 0;
+}
+