@@ -188,7 +188,13 @@ int choose_ipv4_src(u32 *ret, int interface, u32 dst_ipaddr, struct net *ns)
family = AF_INET6;
if (remaddr)
family = remaddr->sa_family;
+retry:
rc = sock_create_kern(ns, family, SOCK_STREAM, 0, &sock);
+ if (rc == -EAFNOSUPPORT && family == AF_INET6 && !remaddr) {
+ family = AF_INET;
+ goto retry;
+ }
+
if (rc) {
CERROR("Can't create socket: %d\n", rc);
return ERR_PTR(rc);
@@ -204,11 +210,11 @@ int choose_ipv4_src(u32 *ret, int interface, u32 dst_ipaddr, struct net *ns)
if (interface >= 0 || local_port) {
struct sockaddr_storage locaddr = {};
- struct sockaddr_in *sin = (void *)&locaddr;
- struct sockaddr_in6 *sin6 = (void *)&locaddr;
switch (family) {
- case AF_INET:
+ case AF_INET: {
+ struct sockaddr_in *sin = (void *)&locaddr;
+
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
if (interface >= 0 && remaddr) {
@@ -225,7 +231,11 @@ int choose_ipv4_src(u32 *ret, int interface, u32 dst_ipaddr, struct net *ns)
}
sin->sin_port = htons(local_port);
break;
- case AF_INET6:
+ }
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (void *)&locaddr;
+
sin6->sin6_family = AF_INET6;
sin6->sin6_addr = in6addr_any;
if (interface >= 0 && remaddr) {
@@ -240,6 +250,8 @@ int choose_ipv4_src(u32 *ret, int interface, u32 dst_ipaddr, struct net *ns)
sin6->sin6_port = htons(local_port);
break;
}
+#endif /* IS_ENABLED(CONFIG_IPV6) */
+ }
rc = kernel_bind(sock, (struct sockaddr *)&locaddr,
sizeof(locaddr));