Andrei G has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/43574?usp=email )
Change subject: core/socket: init_osa: pass family-correct len ......................................................................
core/socket: init_osa: pass family-correct len
osmo_sock_init_osa() hands bind() and connect() sizeof(struct osmo_sockaddr), the 128 byte union, whatever the address family. Linux accepts a namelen longer than the family needs and reads only the family-appropriate part. Darwin returns EINVAL because the kernel enforces the exact length (16 for IPv4, 28 for IPv6). The BSDs behave like Darwin.
Use osmo_sockaddr_size(), which the header already provides and which the sendto() callers already use. It returns sizeof(struct sockaddr_in) or sizeof(struct sockaddr_in6) by family. Linux behaviour is unchanged.
Consequence on Darwin without this fix: gprs_ns2_ip_bind() cannot bind its NS-VC UDP socket ("unable to bind socket: 0.0.0.0:23001: Invalid argument"), so osmo-pcu exits with "No NSVC available to connect to the SGSN" right after the INFO_IND from osmo-bts. osmo-sgsn and osmo-gbproxy reach the same call.
Change-Id: I37cb08a6e1809d51c97e666f980d4c68f8b56933 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/74/43574/1
diff --git a/src/core/socket.c b/src/core/socket.c index 3a2d7b7..e392710 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -598,7 +598,9 @@ } }
- if (bind(sfd, &local->u.sa, sizeof(struct osmo_sockaddr)) == -1) { + /* Pass the length of the address family in use, not of the union: + * Darwin and the BSDs reject a longer namelen with EINVAL. */ + if (bind(sfd, &local->u.sa, osmo_sockaddr_size(local)) == -1) { int err = errno; _SOCKADDR_TO_STR(sastr, local); LOGP(DLGLOBAL, LOGL_ERROR, "unable to bind socket: " OSMO_SOCKADDR_STR_FMT ": %s\n", @@ -621,7 +623,7 @@ } }
- rc = connect(sfd, &remote->u.sa, sizeof(struct osmo_sockaddr)); + rc = connect(sfd, &remote->u.sa, osmo_sockaddr_size(remote)); if (rc != 0 && errno != EINPROGRESS) { int err = errno; _SOCKADDR_TO_STR(sastr, remote);