aboutsummaryrefslogtreecommitdiffstats
path: root/src/socket.c
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2020-08-28 14:32:02 +0200
committerlaforge <laforge@osmocom.org>2020-08-30 16:08:35 +0000
commit4f463c5ccce7527c6a3fd98c7f4a32c68638888a (patch)
tree92a9271c48a39ec322491a840dcf7ae5424b9950 /src/socket.c
parent776c5b16ea63eb80349379fffb39e52ee6b2024d (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.c17
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;