Andrei G has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/43573?usp=email )
Change subject: core/socket: local_ip: connect to discard port ......................................................................
core/socket: local_ip: connect to discard port
osmo_sock_local_ip() finds the source address for a remote by connecting a dummy UDP socket to that remote and reading the local side back with getsockname(). It connects to port 0. Linux accepts that and returns the source address. Darwin rejects it with EADDRNOTAVAIL (errno 49), so the function returns -EINVAL for every remote. The BSDs behave like Darwin here.
Two consumers break on Darwin as a result. libosmo-mgcp-client cannot determine its local address at mgcp_client.c:1347 and fails to build any MGCP message carrying SDP ("Could not determine local IP-Address!"); the mgcp_client test then dereferences the message it did not get. In osmo-mgw, mgcp_network.c:137 uses the same call to pick the local RTP address when none is configured.
No packet is ever sent on the dummy socket, so the remote port has no effect on the answer: the socket is connected, read with getsockname() and closed. Use 9 (discard, IANA reserved), which every kernel accepts. Behaviour on Linux is unchanged.
Change-Id: I597874d5b2a81dd34c6a2b274fcf8d9bfc14c301 Signed-off-by: Andrei Gosman andrei.gosman@gmail.com --- M src/core/socket.c 1 file changed, 4 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/73/43573/1
diff --git a/src/core/socket.c b/src/core/socket.c index 3a2d7b7..cf737fe 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2466,8 +2466,10 @@
/* Connect a dummy socket to trick the kernel into determining the * ip-address of the interface that would be used if we would send - * out an actual packet */ - sfd = osmo_sock_init2(family, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, remote_ip, 0, OSMO_SOCK_F_CONNECT); + * out an actual packet. No packet is sent, so the remote port does + * not matter, but it must not be 0: Linux accepts a UDP connect() to + * port 0, while Darwin and the BSDs reject it with EADDRNOTAVAIL. */ + sfd = osmo_sock_init2(family, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, remote_ip, 9, OSMO_SOCK_F_CONNECT); if (sfd < 0) return -EINVAL;