ipv6: use newly introduced __ipv6_addr_needs_scope_id and ipv6_iface_scope_id
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Fri, 8 Mar 2013 02:07:19 +0000 (02:07 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Mar 2013 17:29:22 +0000 (12:29 -0500)
This patch requires multicast interface-scoped addresses to supply a
sin6_scope_id. Because the sin6_scope_id is now also correctly used
in case of interface-scoped multicast traffic this enables one to use
interface scoped addresses over interfaces which are not targeted by the
default multicast route (the route has to be put there manually, though).

getsockname() and getpeername() now return the correct sin6_scope_id in
case of interface-local mc addresses.

v2:
a) rebased ontop of patch 1/4 (now uses ipv6_addr_props)

v3:
a) reverted changes for ipv6_addr_props

v4:
a) unchanged

Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>dave
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/af_inet6.c
net/ipv6/datagram.c
net/ipv6/icmp.c
net/ipv6/inet6_connection_sock.c
net/ipv6/raw.c
net/ipv6/udp.c

index 6b793bfc0e10b4fc42a5d7887e613d00e545ee70..f56277f159030a272eb3baf3e0e4823f2761b8ed 100644 (file)
@@ -323,7 +323,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                        struct net_device *dev = NULL;
 
                        rcu_read_lock();
-                       if (addr_type & IPV6_ADDR_LINKLOCAL) {
+                       if (__ipv6_addr_needs_scope_id(addr_type)) {
                                if (addr_len >= sizeof(struct sockaddr_in6) &&
                                    addr->sin6_scope_id) {
                                        /* Override any existing binding, if another one
@@ -471,8 +471,8 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
 
                sin->sin6_port = inet->inet_sport;
        }
-       if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-               sin->sin6_scope_id = sk->sk_bound_dev_if;
+       sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr,
+                                                sk->sk_bound_dev_if);
        *uaddr_len = sizeof(*sin);
        return 0;
 }
index f5a54782a3408422ab4aa5da733bdbffb8755905..b55e70add93ccee04419a6ad650ea33463e04cba 100644 (file)
@@ -124,7 +124,7 @@ ipv4_connected:
                goto out;
        }
 
-       if (addr_type&IPV6_ADDR_LINKLOCAL) {
+       if (__ipv6_addr_needs_scope_id(addr_type)) {
                if (addr_len >= sizeof(struct sockaddr_in6) &&
                    usin->sin6_scope_id) {
                        if (sk->sk_bound_dev_if &&
@@ -355,18 +355,19 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
                sin->sin6_family = AF_INET6;
                sin->sin6_flowinfo = 0;
                sin->sin6_port = serr->port;
-               sin->sin6_scope_id = 0;
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        const struct ipv6hdr *ip6h = container_of((struct in6_addr *)(nh + serr->addr_offset),
                                                                  struct ipv6hdr, daddr);
                        sin->sin6_addr = ip6h->daddr;
                        if (np->sndflow)
                                sin->sin6_flowinfo = ip6_flowinfo(ip6h);
-                       if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-                               sin->sin6_scope_id = IP6CB(skb)->iif;
+                       sin->sin6_scope_id =
+                               ipv6_iface_scope_id(&sin->sin6_addr,
+                                                   IP6CB(skb)->iif);
                } else {
                        ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset),
                                               &sin->sin6_addr);
+                       sin->sin6_scope_id = 0;
                }
        }
 
@@ -376,18 +377,19 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
        if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
                sin->sin6_family = AF_INET6;
                sin->sin6_flowinfo = 0;
-               sin->sin6_scope_id = 0;
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        sin->sin6_addr = ipv6_hdr(skb)->saddr;
                        if (np->rxopt.all)
                                ip6_datagram_recv_ctl(sk, msg, skb);
-                       if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-                               sin->sin6_scope_id = IP6CB(skb)->iif;
+                       sin->sin6_scope_id =
+                               ipv6_iface_scope_id(&sin->sin6_addr,
+                                                   IP6CB(skb)->iif);
                } else {
                        struct inet_sock *inet = inet_sk(sk);
 
                        ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
                                               &sin->sin6_addr);
+                       sin->sin6_scope_id = 0;
                        if (inet->cmsg_flags)
                                ip_cmsg_recv(msg, skb);
                }
index fff5bdd8b6800d56679957a62e201e84fd846d09..71b900c3f4ffc5a7634deef14716ba30187c2b36 100644 (file)
@@ -434,7 +434,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
         *      Source addr check
         */
 
-       if (addr_type & IPV6_ADDR_LINKLOCAL)
+       if (__ipv6_addr_needs_scope_id(addr_type))
                iif = skb->dev->ifindex;
 
        /*
index 5f25510f584ef8ce6462e3b2fd667dc2dc553471..e4311cbc8b4ecbf70ea1fb2e2f2415342be382cc 100644 (file)
@@ -173,10 +173,8 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
        sin6->sin6_port = inet_sk(sk)->inet_dport;
        /* We do not store received flowlabel for TCP */
        sin6->sin6_flowinfo = 0;
-       sin6->sin6_scope_id = 0;
-       if (sk->sk_bound_dev_if &&
-           ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-               sin6->sin6_scope_id = sk->sk_bound_dev_if;
+       sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,
+                                                 sk->sk_bound_dev_if);
 }
 
 EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
index 330b5e7b7df6f705f1bcf2c66880b1e3de374df3..eedff8ccded507cc977bd073dbbf334b2624033b 100644 (file)
@@ -263,7 +263,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (addr_type != IPV6_ADDR_ANY) {
                struct net_device *dev = NULL;
 
-               if (addr_type & IPV6_ADDR_LINKLOCAL) {
+               if (__ipv6_addr_needs_scope_id(addr_type)) {
                        if (addr_len >= sizeof(struct sockaddr_in6) &&
                            addr->sin6_scope_id) {
                                /* Override any existing binding, if another
@@ -498,9 +498,8 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
                sin6->sin6_port = 0;
                sin6->sin6_addr = ipv6_hdr(skb)->saddr;
                sin6->sin6_flowinfo = 0;
-               sin6->sin6_scope_id = 0;
-               if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-                       sin6->sin6_scope_id = IP6CB(skb)->iif;
+               sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,
+                                                         IP6CB(skb)->iif);
        }
 
        sock_recv_ts_and_drops(msg, sk, skb);
@@ -802,7 +801,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 
                if (addr_len >= sizeof(struct sockaddr_in6) &&
                    sin6->sin6_scope_id &&
-                   ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
+                   __ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr)))
                        fl6.flowi6_oif = sin6->sin6_scope_id;
        } else {
                if (sk->sk_state != TCP_ESTABLISHED)
index 599e1ba6d1ceaa6766d53eda020a69a0aa234e5b..3ed57eced37605d0437d785741542875179fd0c2 100644 (file)
@@ -450,15 +450,16 @@ try_again:
                sin6->sin6_family = AF_INET6;
                sin6->sin6_port = udp_hdr(skb)->source;
                sin6->sin6_flowinfo = 0;
-               sin6->sin6_scope_id = 0;
 
-               if (is_udp4)
+               if (is_udp4) {
                        ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
                                               &sin6->sin6_addr);
-               else {
+                       sin6->sin6_scope_id = 0;
+               } else {
                        sin6->sin6_addr = ipv6_hdr(skb)->saddr;
-                       if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-                               sin6->sin6_scope_id = IP6CB(skb)->iif;
+                       sin6->sin6_scope_id =
+                               ipv6_iface_scope_id(&sin6->sin6_addr,
+                                                   IP6CB(skb)->iif);
                }
 
        }
@@ -1118,7 +1119,7 @@ do_udp_sendmsg:
 
                if (addr_len >= sizeof(struct sockaddr_in6) &&
                    sin6->sin6_scope_id &&
-                   ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
+                   __ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr)))
                        fl6.flowi6_oif = sin6->sin6_scope_id;
        } else {
                if (sk->sk_state != TCP_ESTABLISHED)