aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
+}
+