aboutsummaryrefslogtreecommitdiffstats
path: root/src/common/rsl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/rsl.c')
-rw-r--r--src/common/rsl.c60
1 files changed, 49 insertions, 11 deletions
diff --git a/src/common/rsl.c b/src/common/rsl.c
index cab8a56d..5f2dd901 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <errno.h>
+#include <netdb.h>
#include <sys/types.h>
#include <arpa/inet.h>
@@ -1198,6 +1199,27 @@ static int tx_ipac_XXcx_nack(struct gsm_lchan *lchan, uint8_t cause,
return abis_rsl_sendmsg(msg);
}
+static char *get_rsl_local_ip(struct gsm_bts_trx *trx)
+{
+ struct sockaddr_storage ss;
+ socklen_t sa_len = sizeof(ss);
+ static char hostbuf[256];
+ int rc;
+
+ rc = getsockname(trx->rsl_link->bfd.fd, (struct sockaddr *) &ss,
+ &sa_len);
+ if (rc < 0)
+ return NULL;
+
+ rc = getnameinfo((struct sockaddr *)&ss, sa_len,
+ hostbuf, sizeof(hostbuf), NULL, 0,
+ NI_NUMERICHOST);
+ if (rc < 0)
+ return NULL;
+
+ return hostbuf;
+}
+
static int rsl_rx_ipac_XXcx(struct msgb *msg)
{
struct abis_rsl_dchan_hdr *dch = msgb_l2(msg);
@@ -1207,7 +1229,7 @@ static int rsl_rx_ipac_XXcx(struct msgb *msg)
const uint8_t *payload_type, *speech_mode, *payload_type2;
const uint32_t *connect_ip;
const uint16_t *connect_port;
- int rc, inc_ip_port = 0;
+ int rc, inc_ip_port = 0, port;
char *name;
if (dch->c.msg_type == RSL_MT_IPAC_CRCX)
@@ -1239,6 +1261,7 @@ static int rsl_rx_ipac_XXcx(struct msgb *msg)
}
if (dch->c.msg_type == RSL_MT_IPAC_CRCX) {
+ char *ipstr = NULL;
if (lchan->abis_ip.rtp_socket) {
LOGP(DRSL, LOGL_ERROR, "%s Rx RSL IPAC CRCX, "
"but we already have socket!\n",
@@ -1263,8 +1286,22 @@ static int rsl_rx_ipac_XXcx(struct msgb *msg)
lchan->abis_ip.rtp_socket->priv = lchan;
lchan->abis_ip.rtp_socket->rx_cb = &bts_model_rtp_rx_cb;
+ if (connect_ip && connect_port) {
+ /* if CRCX specifies a remote IP, we can bind()
+ * here to 0.0.0.0 and wait for the connect()
+ * below, after which the kernel will have
+ * selected the local IP address. */
+ ipstr = "0.0.0.0";
+ } else {
+ /* if CRCX does not specify a remote IP, we will
+ * not do any connect() below, and thus the
+ * local socket will remain bound to 0.0.0.0 -
+ * which however we cannot legitimately report
+ * back to the BSC in the CRCX_ACK */
+ ipstr = get_rsl_local_ip(lchan->ts->trx);
+ }
rc = osmo_rtp_socket_bind(lchan->abis_ip.rtp_socket,
- "0.0.0.0", -1);
+ ipstr, -1);
if (rc < 0) {
LOGP(DRSL, LOGL_ERROR,
"%s IPAC Failed to bind RTP/RTCP sockets\n",
@@ -1289,7 +1326,6 @@ static int rsl_rx_ipac_XXcx(struct msgb *msg)
if (connect_ip && connect_port) {
struct in_addr ia;
- int port;
/* Special rule: If connect_ip == 0.0.0.0, use RSL IP
* address */
@@ -1315,17 +1351,19 @@ static int rsl_rx_ipac_XXcx(struct msgb *msg)
lchan->abis_ip.connect_ip = ntohl(ia.s_addr);
lchan->abis_ip.connect_port = ntohs(*connect_port);
- rc = osmo_rtp_get_bound_ip_port(lchan->abis_ip.rtp_socket,
- &lchan->abis_ip.bound_ip,
- &port);
- if (rc < 0)
- LOGP(DRSL, LOGL_ERROR, "%s IPAC cannot obtain "
- "locally bound IP/port: %d\n",
- gsm_lchan_name(lchan), rc);
- lchan->abis_ip.bound_port = port;
} else {
/* FIXME: discard all codec frames */
}
+
+ rc = osmo_rtp_get_bound_ip_port(lchan->abis_ip.rtp_socket,
+ &lchan->abis_ip.bound_ip,
+ &port);
+ if (rc < 0)
+ LOGP(DRSL, LOGL_ERROR, "%s IPAC cannot obtain "
+ "locally bound IP/port: %d\n",
+ gsm_lchan_name(lchan), rc);
+ lchan->abis_ip.bound_port = port;
+
/* Everything has succeeded, we can store new values in lchan */
if (payload_type) {
lchan->abis_ip.rtp_payload = *payload_type;