osmux: Qualify the handle by IPv4 address _and_ port

For our usecase several different systems might be behind the
same firewall so we need to distinguish the remote by more than
the IPv4 address.
diff --git a/openbsc/src/libmgcp/osmux.c b/openbsc/src/libmgcp/osmux.c
index ad9c2ee..b713183 100644
--- a/openbsc/src/libmgcp/osmux.c
+++ b/openbsc/src/libmgcp/osmux.c
@@ -33,20 +33,22 @@
 struct osmux_handle {
 	struct llist_head head;
 	struct osmux_in_handle *in;
+	struct in_addr rem_addr;
+	int rem_port;
 };
 
 static void *osmux;
 
 static void osmux_deliver(struct msgb *batch_msg, void *data)
 {
-	struct in_addr *addr = data;
+	struct osmux_handle *handle = data;
 	struct sockaddr_in out = {
 		.sin_family = AF_INET,
-		.sin_port = htons(OSMUX_PORT),
+		.sin_port = handle->rem_port,
 	};
 	char buf[4096];
 
-	memcpy(&out.sin_addr, addr, sizeof(*addr));
+	memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr));
 
 	osmux_snprintf(buf, sizeof(buf), batch_msg);
 	LOGP(DMGCP, LOGL_DEBUG, "OSMUX delivering batch to addr=%s: %s\n",
@@ -57,16 +59,16 @@
 }
 
 static struct osmux_in_handle *
-osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr)
+osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
 {
 	struct osmux_handle *h;
 
 	/* Lookup for existing OSMUX handle for this destination address. */
 	llist_for_each_entry(h, &osmux_handle_list, head) {
-		if (memcmp(h->in->data, addr, sizeof(struct in_addr)) == 0) {
+		if (memcmp(&h->rem_addr, addr, sizeof(struct in_addr)) == 0 && h->rem_port == rem_port) {
 			LOGP(DMGCP, LOGL_DEBUG, "using existing OSMUX handle "
-						"for addr=%s\n",
-				inet_ntoa(*addr));
+						"for addr=%s:%d\n",
+				inet_ntoa(*addr), ntohs(rem_port));
 			goto out;
 		}
 	}
@@ -75,6 +77,8 @@
 	h = talloc_zero(osmux, struct osmux_handle);
 	if (!h)
 		return NULL;
+	h->rem_addr = *addr;
+	h->rem_port = rem_port;
 
 	h->in = talloc_zero(osmux, struct osmux_in_handle);
 	if (!h->in) {
@@ -86,19 +90,19 @@
 	h->in->batch_factor = cfg->osmux_batch;
 	h->in->deliver = osmux_deliver;
 	osmux_xfrm_input_init(h->in);
-	h->in->data = addr;
+	h->in->data = h;
 
 	llist_add(&h->head, &osmux_handle_list);
 
-	LOGP(DMGCP, LOGL_DEBUG, "created new OSMUX handle for addr=%s\n",
-		inet_ntoa(*addr));
+	LOGP(DMGCP, LOGL_DEBUG, "created new OSMUX handle for addr=%s:%d\n",
+		inet_ntoa(*addr), ntohs(rem_port));
 out:
 	return h->in;
 }
 
 int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp)
 {
-	int ret;
+	int ret, port;
 	struct msgb *msg;
 	struct in_addr *addr;
 	struct osmux_in_handle *in;
@@ -113,9 +117,11 @@
 	switch(type) {
 	case MGCP_DEST_NET:
 		addr = &endp->net_end.addr;
+		port = htons(OSMUX_PORT);
 		break;
 	case MGCP_DEST_BTS:
 		addr = &endp->bts_end.addr;
+		port = endp->bts_end.rtp_port;
 		break;
 	default:
 		/* Should not ever happen */
@@ -125,7 +131,7 @@
 	}
 
 	/* Lookup for osmux input handle that munches this RTP frame */
-	in = osmux_handle_lookup(endp->cfg, addr);
+	in = osmux_handle_lookup(endp->cfg, addr, port);
 	if (!in) {
 		LOGP(DMGCP, LOGL_ERROR, "No osmux handle, aborting\n");
 		msgb_free(msg);
@@ -336,6 +342,13 @@
 			goto out;
 		}
 
+		if (endp->bts_end.rtp_port == 0) {
+			endp->bts_end.rtp_port = addr.sin_port;
+			LOGP(DMGCP, LOGL_NOTICE, "0x%x found BTS on endpoint %s:%d\n",
+				ENDPOINT_NUMBER(endp),
+				inet_ntoa(addr.sin_addr), htons(addr.sin_port));
+		}
+
 		LOGP(DMGCP, LOGL_DEBUG,
 		     "sending extracted RTP from OSMUX to MSC via endpoint=%u "
 		     "(allocated=%d)\n", ENDPOINT_NUMBER(endp), endp->allocated);