- struct sockaddr_in locaddr = {};
-
- locaddr.sin_family = AF_INET;
- locaddr.sin_addr.s_addr = INADDR_ANY;
- if (interface >= 0) {
- struct sockaddr_in *sin = (void *)remaddr;
- __u32 ip;
-
- rc = choose_ipv4_src(&ip,
- interface,
- ntohl(sin->sin_addr.s_addr),
- ns);
- if (rc)
- goto failed;
- locaddr.sin_addr.s_addr = htonl(ip);
+ struct sockaddr_storage locaddr = {};
+ struct sockaddr_in *sin = (void *)&locaddr;
+ struct sockaddr_in6 *sin6 = (void *)&locaddr;
+
+ switch (family) {
+ case AF_INET:
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ if (interface >= 0 && remaddr) {
+ struct sockaddr_in *rem = (void *)remaddr;
+ __u32 ip;
+
+ rc = choose_ipv4_src(&ip,
+ interface,
+ ntohl(rem->sin_addr.s_addr),
+ ns);
+ if (rc)
+ goto failed;
+ sin->sin_addr.s_addr = htonl(ip);
+ }
+ sin->sin_port = htons(local_port);
+ break;
+ case AF_INET6:
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_addr = in6addr_any;
+ if (interface >= 0 && remaddr) {
+ struct sockaddr_in6 *rem = (void *)remaddr;
+
+ ipv6_dev_get_saddr(ns,
+ dev_get_by_index(ns,
+ interface),
+ &rem->sin6_addr, 0,
+ &sin6->sin6_addr);
+ }
+ sin6->sin6_port = htons(local_port);
+ break;