mgcp: Allow to bind to different ports for net/bts ports

When using multiple interfaces on a system one can now configure
which will be served for the BTS ports and which will be served
for the network. The direct usage of source_addr is now only to
initialize the MGCP receiving port itself.
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index 9befa7c..aebcda3 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -117,6 +117,9 @@
 struct mgcp_port_range {
 	int mode;
 
+	/* addr or NULL to fall-back to default */
+	char *bind_addr;
+
 	/* pre-allocated from a base? */
 	int base_port;
 
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index f97292d..1f83659 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -327,10 +327,14 @@
  */
 static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
 {
+	if (endp->cfg->bts_ports.bind_addr)
+		return endp->cfg->bts_ports.bind_addr;
 	return endp->cfg->source_addr;
 }
 
 static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
 {
+	if (endp->cfg->net_ports.bind_addr)
+		return endp->cfg->net_ports.bind_addr;
 	return endp->cfg->source_addr;
 }
diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c
index 8f6b10a..a620a20 100644
--- a/openbsc/src/libmgcp/mgcp_vty.c
+++ b/openbsc/src/libmgcp/mgcp_vty.c
@@ -78,12 +78,16 @@
 	else
 		vty_out(vty, "  rtp bts-range %u %u%s",
 			g_cfg->bts_ports.range_start, g_cfg->bts_ports.range_end, VTY_NEWLINE);
+	if (g_cfg->bts_ports.bind_addr)
+		vty_out(vty, "  rtp bts-bind-ip %s%s", g_cfg->bts_ports.bind_addr, VTY_NEWLINE);
 
 	if (g_cfg->net_ports.mode == PORT_ALLOC_STATIC)
 		vty_out(vty, "  rtp net-base %u%s", g_cfg->net_ports.base_port, VTY_NEWLINE);
 	else
 		vty_out(vty, "  rtp net-range %u %u%s",
 			g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
+	if (g_cfg->net_ports.bind_addr)
+		vty_out(vty, "  rtp net-bind-ip %s%s", g_cfg->net_ports.bind_addr, VTY_NEWLINE);
 
 	vty_out(vty, "  rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
 	if (g_cfg->trunk.keepalive_interval == MGCP_KEEPALIVE_ONCE)
@@ -378,6 +382,44 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_mgcp_rtp_bts_bind_ip,
+      cfg_mgcp_rtp_bts_bind_ip_cmd,
+      "rtp bts-bind-ip A.B.C.D",
+      RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n")
+{
+	bsc_replace_string(g_cfg, &g_cfg->bts_ports.bind_addr, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_no_bts_bind_ip,
+      cfg_mgcp_rtp_no_bts_bind_ip_cmd,
+      "no rtp bts-bind-ip",
+      NO_STR RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n")
+{
+	talloc_free(g_cfg->bts_ports.bind_addr);
+	g_cfg->bts_ports.bind_addr = NULL;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_net_bind_ip,
+      cfg_mgcp_rtp_net_bind_ip_cmd,
+      "rtp net-bind-ip A.B.C.D",
+      RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
+{
+	bsc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_no_net_bind_ip,
+      cfg_mgcp_rtp_no_net_bind_ip_cmd,
+      "no rtp net-bind-ip",
+      NO_STR RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
+{
+	talloc_free(g_cfg->net_ports.bind_addr);
+	g_cfg->net_ports.bind_addr = NULL;
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_mgcp_rtp_ip_dscp,
       cfg_mgcp_rtp_ip_dscp_cmd,
       "rtp ip-dscp <0-255>",
@@ -1282,7 +1324,11 @@
 	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
 	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
 	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_range_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_bind_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bts_bind_ip_cmd);
 	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
 	install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_range_cmd);
 	install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_base_cmd);
 	install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index 72471d8..8db0825 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -92,6 +92,28 @@
 
         # TODO: test it for the trunk!
 
+    def testBindAddr(self):
+        self.vty.enable()
+
+	self.vty.command("configure terminal")
+	self.vty.command("mgcp")
+
+        # enable.. disable bts-bind-ip
+        self.vty.command("rtp bts-bind-ip 254.253.252.250")
+        res = self.vty.command("show running-config")
+        self.assert_(res.find('rtp bts-bind-ip 254.253.252.250') > 0)
+        self.vty.command("no rtp bts-bind-ip")
+        res = self.vty.command("show running-config")
+        self.assertEquals(res.find('  rtp bts-bind-ip'), -1)
+
+        # enable.. disable net-bind-ip
+        self.vty.command("rtp net-bind-ip 254.253.252.250")
+        res = self.vty.command("show running-config")
+        self.assert_(res.find('rtp net-bind-ip 254.253.252.250') > 0)
+        self.vty.command("no rtp net-bind-ip")
+        res = self.vty.command("show running-config")
+        self.assertEquals(res.find('  rtp net-bind-ip'), -1)
+
 
 class TestVTYGenericBSC(TestVTYBase):