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/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;
+}