aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-03-31 13:02:22 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-03-31 13:15:19 +0200
commit82cb311c4fb184a12676fd2090fcdc09cb3e399a (patch)
treefdbb9cd84d129b0e6ecb2d631c6a900d77d8a3fd /openbsc
parent2980442e33028eca3917900dd5fa60c3c5a2c713 (diff)
nat: First go at handling MGCP inside the nat
Listen on the MGCP gateway port and let our protocol stack handle everything for now. We will need to have some more control over things though.
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/bsc_nat.h2
-rw-r--r--openbsc/src/nat/bsc_mgcp_utils.c109
-rw-r--r--openbsc/src/nat/bsc_nat.c6
3 files changed, 117 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index a5d3b1c79..6f79106fd 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -142,6 +142,7 @@ struct bsc_nat {
/* MGCP config */
struct mgcp_config *mgcp_cfg;
+ struct write_queue mgcp_queue;
};
/* create and init the structures */
@@ -180,5 +181,6 @@ int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned in
int bsc_mgcp_assign(struct sccp_connections *, struct msgb *msg);
void bsc_mgcp_clear(struct sccp_connections *);
void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
+int bsc_mgcp_init(struct bsc_nat *nat);
#endif
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
index 38f1abfab..e19010597 100644
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -29,6 +29,9 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <errno.h>
+#include <unistd.h>
+
int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
{
struct tlv_parsed tp;
@@ -74,3 +77,109 @@ void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
for (i = 1; i < nat->mgcp_cfg->number_endpoints; ++i)
mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
}
+
+static int mgcp_do_read(struct bsc_fd *fd)
+{
+ struct bsc_nat *nat;
+ struct msgb *msg, *resp;
+ int rc;
+
+ msg = msgb_alloc(4096, "MGCP GW Read");
+ if (!msg) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to create buffer.\n");
+ return -1;
+ }
+
+
+ rc = read(fd->fd, msg->data, msg->data_len);
+ if (rc <= 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to read errno: %d\n", errno);
+ msgb_free(msg);
+ return -1;
+ }
+
+ nat = fd->data;
+ msg->l2h = msgb_put(msg, rc);
+ resp = mgcp_handle_message(nat->mgcp_cfg, msg);
+ msgb_free(msg);
+
+ /* we do have a direct answer... e.g. AUEP */
+ if (resp) {
+ if (write_queue_enqueue(&nat->mgcp_queue, resp) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to enqueue msg.\n");
+ msgb_free(resp);
+ }
+ }
+
+ return 0;
+}
+
+static int mgcp_do_write(struct bsc_fd *bfd, struct msgb *msg)
+{
+ int rc;
+
+ rc = write(bfd->fd, msg->data, msg->len);
+
+ if (rc != msg->len) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to write msg to MGCP CallAgent.\n");
+ return -1;
+ }
+
+ return rc;
+}
+
+int bsc_mgcp_init(struct bsc_nat *nat)
+{
+ int on;
+ struct sockaddr_in addr;
+
+ if (!nat->mgcp_cfg->call_agent_addr) {
+ LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\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);
+ return -1;
+ }
+
+ on = 1;
+ setsockopt(nat->mgcp_queue.bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(nat->mgcp_cfg->source_port);
+ inet_aton(nat->mgcp_cfg->source_addr, &addr.sin_addr);
+
+ if (bind(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to bind. errno: %d\n", errno);
+ close(nat->mgcp_queue.bfd.fd);
+ nat->mgcp_queue.bfd.fd = -1;
+ return -1;
+ }
+
+ addr.sin_port = htons(2727);
+ inet_aton(nat->mgcp_cfg->call_agent_addr, &addr.sin_addr);
+ if (connect(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n",
+ nat->mgcp_cfg->call_agent_addr, errno);
+ close(nat->mgcp_queue.bfd.fd);
+ nat->mgcp_queue.bfd.fd = -1;
+ return -1;
+ }
+
+ write_queue_init(&nat->mgcp_queue, 10);
+ nat->mgcp_queue.bfd.when = BSC_FD_READ;
+ nat->mgcp_queue.bfd.data = nat;
+ nat->mgcp_queue.read_cb = mgcp_do_read;
+ nat->mgcp_queue.write_cb = mgcp_do_write;
+
+ if (bsc_register_fd(&nat->mgcp_queue.bfd) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to register MGCP fd.\n");
+ close(nat->mgcp_queue.bfd.fd);
+ nat->mgcp_queue.bfd.fd = -1;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index b2fc2c7c9..f505bd5ad 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -754,6 +754,12 @@ int main(int argc, char** argv)
/* seed the PRNG */
srand(time(NULL));
+ /*
+ * Setup the MGCP code..
+ */
+ if (bsc_mgcp_init(nat) != 0)
+ return -4;
+
/* connect to the MSC */
msc_con = bsc_msc_create(msc_address, 5000);
if (!msc_con) {