diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2020-08-28 14:32:02 +0200 |
---|---|---|
committer | laforge <laforge@osmocom.org> | 2020-08-30 16:08:35 +0000 |
commit | 4f463c5ccce7527c6a3fd98c7f4a32c68638888a (patch) | |
tree | 92a9271c48a39ec322491a840dcf7ae5424b9950 /src/socket.c | |
parent | 776c5b16ea63eb80349379fffb39e52ee6b2024d (diff) |
socket: Allow binding to :: (IPv6) and connecting to IPv4-only on the remote
sctp_bindx() fails if passed both "0.0.0.0" and "::", only "::" must
be passed instead, which covers both.
As a result, it is fine in this case and makes sense having only IPv6
formatted IPs in the local side (which actually also includes all IPv4
ones in th system) and IPv4-only addresses on the remote side.
Change-Id: I0b590113e5def20edcbcb098426b19cd504eabff
Diffstat (limited to 'src/socket.c')
-rw-r--r-- | src/socket.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/src/socket.c b/src/socket.c index 1afbe6ef..a5bbddf5 100644 --- a/src/socket.c +++ b/src/socket.c @@ -443,6 +443,22 @@ static void addrinfo_has_v4v6addr(const struct addrinfo **result, size_t result_ } } +/* Check whether there's an IPv6 with IN6ADDR_ANY_INIT ("::") */ +static bool addrinfo_has_in6addr_any(const struct addrinfo **result, size_t result_count) +{ + size_t host_idx; + struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + + for (host_idx = 0; host_idx < result_count; host_idx++) { + if (result[host_idx]->ai_family != AF_INET6) + continue; + if (memcmp(&((struct sockaddr_in6 *)result[host_idx]->ai_addr)->sin6_addr, + &in6addr_any, sizeof(in6addr_any)) == 0) + return true; + } + return false; +} + static int socket_helper_multiaddr(uint16_t family, uint16_t type, uint8_t proto, unsigned int flags) { int sfd, on = 1; @@ -577,6 +593,7 @@ int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto, } if (((flags & OSMO_SOCK_F_BIND) && (flags & OSMO_SOCK_F_CONNECT)) && + !addrinfo_has_in6addr_any((const struct addrinfo **)res_loc, local_hosts_cnt) && (loc_has_v4addr != rem_has_v4addr || loc_has_v6addr != rem_has_v6addr)) { LOGP(DLGLOBAL, LOGL_ERROR, "Invalid v4 vs v6 in local vs remote addresses\n"); rc = -EINVAL; |