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.
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index a5d3b1c..6f79106 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -142,6 +142,7 @@
 
 	/* MGCP config */
 	struct mgcp_config *mgcp_cfg;
+	struct write_queue mgcp_queue;
 };
 
 /* create and init the structures */
@@ -180,5 +181,6 @@
 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 38f1abf..e190105 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 @@
 	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 f69a994..d75c01d 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -755,6 +755,12 @@
 	/* 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) {