nat: Make it possible to send MGCP messages through the IPA multiplex

Instead of handling MGCP through the UDP socket, read and write messages
through the ipa connection to the MSC.
diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
index 1436ebd..480a8f6 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
@@ -62,7 +62,7 @@
 #include <errno.h>
 #include <unistd.h>
 
-static void mgcp_queue_for_call_agent(struct bsc_nat *nat, struct msgb *output)
+static void send_direct(struct bsc_nat *nat, struct msgb *output)
 {
 	if (osmo_wqueue_enqueue(&nat->mgcp_cfg->gw_fd, output) != 0) {
 		LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
@@ -70,6 +70,14 @@
 	}
 }
 
+static void mgcp_queue_for_call_agent(struct bsc_nat *nat, struct msgb *output)
+{
+	if (nat->mgcp_ipa)
+		bsc_nat_send_mgcp_to_msc(nat, output);
+	else
+		send_direct(nat, output);
+}
+
 int bsc_mgcp_nr_multiplexes(int max_endpoints)
 {
 	int div = max_endpoints / 32;
@@ -656,6 +664,38 @@
 	return output;
 }
 
+/*
+ * This comes from the MSC and we will now parse it. The caller needs
+ * to free the msgb.
+ */
+void bsc_nat_handle_mgcp(struct bsc_nat *nat, struct msgb *msg)
+{
+	struct msgb *resp;
+
+	if (!nat->mgcp_ipa) {
+		LOGP(DMGCP, LOGL_ERROR, "MGCP message not allowed on IPA.\n");
+		return;
+	}
+
+	if (msgb_l2len(msg) > sizeof(nat->mgcp_msg) - 1) {
+		LOGP(DMGCP, LOGL_ERROR, "MGCP msg too big for handling.\n");
+		return;
+	}
+
+	memcpy(nat->mgcp_msg, msg->l2h, msgb_l2len(msg));
+	nat->mgcp_length = msgb_l2len(msg);
+	nat->mgcp_msg[nat->mgcp_length] = '\0';
+
+	/* now handle the message */
+	resp = mgcp_handle_message(nat->mgcp_cfg, msg);
+
+	/* we do have a direct answer... e.g. AUEP */
+	if (resp)
+		mgcp_queue_for_call_agent(nat, resp);
+
+	return;
+}
+
 static int mgcp_do_read(struct osmo_fd *fd)
 {
 	struct bsc_nat *nat;
@@ -705,21 +745,10 @@
 	return rc;
 }
 
-int bsc_mgcp_nat_init(struct bsc_nat *nat)
+static int init_mgcp_socket(struct bsc_nat *nat, struct mgcp_config *cfg)
 {
-	int on;
 	struct sockaddr_in addr;
-	struct mgcp_config *cfg = nat->mgcp_cfg;
-
-	if (!cfg->call_agent_addr) {
-		LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
-		return -1;
-	}
-
-	if (cfg->bts_ip) {
-		LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
-		return -1;
-	}
+	int on;
 
 	cfg->gw_fd.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
 	if (cfg->gw_fd.bfd.fd < 0) {
@@ -765,6 +794,31 @@
 		return -1;
 	}
 
+	return 0;
+}
+
+int bsc_mgcp_nat_init(struct bsc_nat *nat)
+{
+	struct mgcp_config *cfg = nat->mgcp_cfg;
+
+	if (!cfg->call_agent_addr) {
+		LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
+		return -1;
+	}
+
+	if (cfg->bts_ip) {
+		LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
+		return -1;
+	}
+
+	/* initialize the MGCP socket */
+	if (!nat->mgcp_ipa) {
+		int rc =  init_mgcp_socket(nat, cfg);
+		if (rc != 0)
+			return rc;
+	}
+
+
 	/* some more MGCP config handling */
 	cfg->data = nat;
 	cfg->policy_cb = bsc_mgcp_policy_cb;