@@ -278,6 +278,21 @@ static int addr6_resolve_remote(struct sockaddr_in6 *src_in,
fl.nl_u.ip6_u.daddr = dst_in->sin6_addr;
fl.nl_u.ip6_u.saddr = src_in->sin6_addr;
+ if (ipv6_addr_type(&src_in->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
+ if (!src_in->sin6_scope_id)
+ return -EINVAL;
+ fl.oif = src_in->sin6_scope_id;
+ }
+ if (ipv6_addr_type(&dst_in->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
+ if (dst_in->sin6_scope_id) {
+ if (fl.oif && fl.oif != dst_in->sin6_scope_id)
+ return -EINVAL;
+ fl.oif = dst_in->sin6_scope_id;
+ }
+ if (!fl.oif)
+ return -EINVAL;
+ }
+
dst = ip6_route_output(&init_net, NULL, &fl);
if (!dst)
return ret;
@@ -390,14 +405,16 @@ static int addr_resolve_local(struct sockaddr *src_in,
case AF_INET6:
{
struct in6_addr *a;
+ int found = 0;
for_each_netdev(&init_net, dev)
if (ipv6_chk_addr(&init_net,
&((struct sockaddr_in6 *) dst_in)->sin6_addr,
- dev, 1))
+ dev, 1)) {
+ found = 1;
break;
-
- if (!dev)
+ }
+ if (!found)
return -EADDRNOTAVAIL;
a = &((struct sockaddr_in6 *) src_in)->sin6_addr;
@@ -406,6 +423,8 @@ static int addr_resolve_local(struct sockaddr *src_in,
src_in->sa_family = dst_in->sa_family;
((struct sockaddr_in6 *) src_in)->sin6_addr =
((struct sockaddr_in6 *) dst_in)->sin6_addr;
+ ((struct sockaddr_in6 *) src_in)->sin6_scope_id =
+ ((struct sockaddr_in6 *) dst_in)->sin6_scope_id;
ret = rdma_copy_addr(addr, dev, dev->dev_addr);
} else if (ipv6_addr_loopback(a)) {
ret = rdma_translate_ip(dst_in, addr);