aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 1d4d75b34d32..7a5863298f3f 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -49,6 +49,7 @@
49#include <net/transp_v6.h> 49#include <net/transp_v6.h>
50#include <net/udp.h> 50#include <net/udp.h>
51#include <net/inet_common.h> 51#include <net/inet_common.h>
52#include <net/tcp_states.h>
52 53
53#include <net/rawv6.h> 54#include <net/rawv6.h>
54#include <net/xfrm.h> 55#include <net/xfrm.h>
@@ -81,7 +82,8 @@ static void raw_v6_unhash(struct sock *sk)
81 82
82/* Grumble... icmp and ip_input want to get at this... */ 83/* Grumble... icmp and ip_input want to get at this... */
83struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, 84struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
84 struct in6_addr *loc_addr, struct in6_addr *rmt_addr) 85 struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
86 int dif)
85{ 87{
86 struct hlist_node *node; 88 struct hlist_node *node;
87 int is_multicast = ipv6_addr_is_multicast(loc_addr); 89 int is_multicast = ipv6_addr_is_multicast(loc_addr);
@@ -94,6 +96,9 @@ struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
94 !ipv6_addr_equal(&np->daddr, rmt_addr)) 96 !ipv6_addr_equal(&np->daddr, rmt_addr))
95 continue; 97 continue;
96 98
99 if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
100 continue;
101
97 if (!ipv6_addr_any(&np->rcv_saddr)) { 102 if (!ipv6_addr_any(&np->rcv_saddr)) {
98 if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) 103 if (ipv6_addr_equal(&np->rcv_saddr, loc_addr))
99 goto found; 104 goto found;
@@ -137,11 +142,12 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
137 * 142 *
138 * Caller owns SKB so we must make clones. 143 * Caller owns SKB so we must make clones.
139 */ 144 */
140void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) 145int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
141{ 146{
142 struct in6_addr *saddr; 147 struct in6_addr *saddr;
143 struct in6_addr *daddr; 148 struct in6_addr *daddr;
144 struct sock *sk; 149 struct sock *sk;
150 int delivered = 0;
145 __u8 hash; 151 __u8 hash;
146 152
147 saddr = &skb->nh.ipv6h->saddr; 153 saddr = &skb->nh.ipv6h->saddr;
@@ -160,9 +166,10 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
160 if (sk == NULL) 166 if (sk == NULL)
161 goto out; 167 goto out;
162 168
163 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr); 169 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, skb->dev->ifindex);
164 170
165 while (sk) { 171 while (sk) {
172 delivered = 1;
166 if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) { 173 if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) {
167 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); 174 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
168 175
@@ -170,10 +177,12 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
170 if (clone) 177 if (clone)
171 rawv6_rcv(sk, clone); 178 rawv6_rcv(sk, clone);
172 } 179 }
173 sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr); 180 sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr,
181 skb->dev->ifindex);
174 } 182 }
175out: 183out:
176 read_unlock(&raw_v6_lock); 184 read_unlock(&raw_v6_lock);
185 return delivered;
177} 186}
178 187
179/* This cleans up af_inet6 a bit. -DaveM */ 188/* This cleans up af_inet6 a bit. -DaveM */
@@ -334,8 +343,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
334 if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, 343 if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
335 &skb->nh.ipv6h->daddr, 344 &skb->nh.ipv6h->daddr,
336 skb->len, inet->num, skb->csum)) { 345 skb->len, inet->num, skb->csum)) {
337 LIMIT_NETDEBUG( 346 LIMIT_NETDEBUG(KERN_DEBUG "raw v6 hw csum failure.\n");
338 printk(KERN_DEBUG "raw v6 hw csum failure.\n"));
339 skb->ip_summed = CHECKSUM_NONE; 347 skb->ip_summed = CHECKSUM_NONE;
340 } 348 }
341 } 349 }