diff options
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r-- | net/ipv6/raw.c | 20 |
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... */ |
83 | struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, | 84 | struct 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 | */ |
140 | void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | 145 | int 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 | } |
175 | out: | 183 | out: |
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 | } |