[IPV6]: Check interface bindings on IPv6 raw socket reception
authorAndrew McDonald <andrew@mcdonald.org.uk>
Wed, 10 Aug 2005 02:44:42 +0000 (19:44 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 29 Aug 2005 22:37:06 +0000 (15:37 -0700)
Take account of whether a socket is bound to a particular device when
selecting an IPv6 raw socket to receive a packet. Also perform this
check when receiving IPv6 packets with router alert options.

Signed-off-by: Andrew McDonald <andrew@mcdonald.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/rawv6.h
net/ipv6/icmp.c
net/ipv6/ip6_output.c
net/ipv6/raw.c

index 23fd9a6a221a2094546fe66c7a17b619a906d0c3..887009aa1f8872e20e2dc393950e48947fb53a8b 100644 (file)
@@ -10,7 +10,8 @@ extern rwlock_t raw_v6_lock;
 extern void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr);
 
 extern struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
-                                   struct in6_addr *loc_addr, struct in6_addr *rmt_addr);
+                                   struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
+                                   int dif);
 
 extern int                     rawv6_rcv(struct sock *sk,
                                          struct sk_buff *skb);
index ff3ec9822e36bb5e8c0100014c20bd8e3b14af50..ee9f1d36346c647c5aadd5e4137561790ded9590 100644 (file)
@@ -551,7 +551,8 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
 
        read_lock(&raw_v6_lock);
        if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) {
-               while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
+               while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr,
+                                           skb->dev->ifindex))) {
                        rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
                        sk = sk_next(sk);
                }
index a7fcbcc835761e31ab46c2d3944c66b9aa02839f..00f85148b85f3a780fd3ff3ac2a3025fa920a4d9 100644 (file)
@@ -277,7 +277,9 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel)
        read_lock(&ip6_ra_lock);
        for (ra = ip6_ra_chain; ra; ra = ra->next) {
                struct sock *sk = ra->sk;
-               if (sk && ra->sel == sel) {
+               if (sk && ra->sel == sel &&
+                   (!sk->sk_bound_dev_if ||
+                    sk->sk_bound_dev_if == skb->dev->ifindex)) {
                        if (last) {
                                struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2)
index 1d4d75b34d321c19ec892013c9f3b73bdfa3d9fe..9db0de81f0741c88b8f5818f2aad1cb3356c9755 100644 (file)
@@ -81,7 +81,8 @@ static void raw_v6_unhash(struct sock *sk)
 
 /* Grumble... icmp and ip_input want to get at this... */
 struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
-                            struct in6_addr *loc_addr, struct in6_addr *rmt_addr)
+                            struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
+                            int dif)
 {
        struct hlist_node *node;
        int is_multicast = ipv6_addr_is_multicast(loc_addr);
@@ -94,6 +95,9 @@ struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
                            !ipv6_addr_equal(&np->daddr, rmt_addr))
                                continue;
 
+                       if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
+                               continue;
+
                        if (!ipv6_addr_any(&np->rcv_saddr)) {
                                if (ipv6_addr_equal(&np->rcv_saddr, loc_addr))
                                        goto found;
@@ -160,7 +164,7 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
        if (sk == NULL)
                goto out;
 
-       sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr);
+       sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, skb->dev->ifindex);
 
        while (sk) {
                if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) {
@@ -170,7 +174,8 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
                        if (clone)
                                rawv6_rcv(sk, clone);
                }
-               sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr);
+               sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr,
+                                    skb->dev->ifindex);
        }
 out:
        read_unlock(&raw_v6_lock);