diff options
-rw-r--r-- | include/net/rawv6.h | 19 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 15 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 9 | ||||
-rw-r--r-- | net/ipv6/raw.c | 52 |
4 files changed, 51 insertions, 44 deletions
diff --git a/include/net/rawv6.h b/include/net/rawv6.h index a5819891d525..8a22599f26ba 100644 --- a/include/net/rawv6.h +++ b/include/net/rawv6.h | |||
@@ -5,26 +5,13 @@ | |||
5 | 5 | ||
6 | #include <net/protocol.h> | 6 | #include <net/protocol.h> |
7 | 7 | ||
8 | #define RAWV6_HTABLE_SIZE MAX_INET_PROTOS | 8 | void raw6_icmp_error(struct sk_buff *, int nexthdr, |
9 | extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE]; | 9 | int type, int code, int inner_offset, __be32); |
10 | extern rwlock_t raw_v6_lock; | 10 | int raw6_local_deliver(struct sk_buff *, int); |
11 | |||
12 | extern int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr); | ||
13 | |||
14 | extern struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, | ||
15 | struct in6_addr *loc_addr, struct in6_addr *rmt_addr, | ||
16 | int dif); | ||
17 | 11 | ||
18 | extern int rawv6_rcv(struct sock *sk, | 12 | extern int rawv6_rcv(struct sock *sk, |
19 | struct sk_buff *skb); | 13 | struct sk_buff *skb); |
20 | 14 | ||
21 | |||
22 | extern void rawv6_err(struct sock *sk, | ||
23 | struct sk_buff *skb, | ||
24 | struct inet6_skb_parm *opt, | ||
25 | int type, int code, | ||
26 | int offset, __be32 info); | ||
27 | |||
28 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 15 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
29 | int rawv6_mh_filter_register(int (*filter)(struct sock *sock, | 16 | int rawv6_mh_filter_register(int (*filter)(struct sock *sock, |
30 | struct sk_buff *skb)); | 17 | struct sk_buff *skb)); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f1240688dc58..93c96cfd5ee1 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -555,9 +555,7 @@ out: | |||
555 | 555 | ||
556 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | 556 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) |
557 | { | 557 | { |
558 | struct in6_addr *saddr, *daddr; | ||
559 | struct inet6_protocol *ipprot; | 558 | struct inet6_protocol *ipprot; |
560 | struct sock *sk; | ||
561 | int inner_offset; | 559 | int inner_offset; |
562 | int hash; | 560 | int hash; |
563 | u8 nexthdr; | 561 | u8 nexthdr; |
@@ -579,9 +577,6 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | |||
579 | if (!pskb_may_pull(skb, inner_offset+8)) | 577 | if (!pskb_may_pull(skb, inner_offset+8)) |
580 | return; | 578 | return; |
581 | 579 | ||
582 | saddr = &ipv6_hdr(skb)->saddr; | ||
583 | daddr = &ipv6_hdr(skb)->daddr; | ||
584 | |||
585 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. | 580 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. |
586 | Without this we will not able f.e. to make source routed | 581 | Without this we will not able f.e. to make source routed |
587 | pmtu discovery. | 582 | pmtu discovery. |
@@ -597,15 +592,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | |||
597 | ipprot->err_handler(skb, NULL, type, code, inner_offset, info); | 592 | ipprot->err_handler(skb, NULL, type, code, inner_offset, info); |
598 | rcu_read_unlock(); | 593 | rcu_read_unlock(); |
599 | 594 | ||
600 | read_lock(&raw_v6_lock); | 595 | raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); |
601 | if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) { | ||
602 | while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr, | ||
603 | IP6CB(skb)->iif))) { | ||
604 | rawv6_err(sk, skb, NULL, type, code, inner_offset, info); | ||
605 | sk = sk_next(sk); | ||
606 | } | ||
607 | } | ||
608 | read_unlock(&raw_v6_lock); | ||
609 | } | 596 | } |
610 | 597 | ||
611 | /* | 598 | /* |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 79610b4bad3e..178aebc0427a 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -153,9 +153,8 @@ out: | |||
153 | static int ip6_input_finish(struct sk_buff *skb) | 153 | static int ip6_input_finish(struct sk_buff *skb) |
154 | { | 154 | { |
155 | struct inet6_protocol *ipprot; | 155 | struct inet6_protocol *ipprot; |
156 | struct sock *raw_sk; | ||
157 | unsigned int nhoff; | 156 | unsigned int nhoff; |
158 | int nexthdr; | 157 | int nexthdr, raw; |
159 | u8 hash; | 158 | u8 hash; |
160 | struct inet6_dev *idev; | 159 | struct inet6_dev *idev; |
161 | 160 | ||
@@ -171,9 +170,7 @@ resubmit: | |||
171 | nhoff = IP6CB(skb)->nhoff; | 170 | nhoff = IP6CB(skb)->nhoff; |
172 | nexthdr = skb_network_header(skb)[nhoff]; | 171 | nexthdr = skb_network_header(skb)[nhoff]; |
173 | 172 | ||
174 | raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); | 173 | raw = raw6_local_deliver(skb, nexthdr); |
175 | if (raw_sk && !ipv6_raw_deliver(skb, nexthdr)) | ||
176 | raw_sk = NULL; | ||
177 | 174 | ||
178 | hash = nexthdr & (MAX_INET_PROTOS - 1); | 175 | hash = nexthdr & (MAX_INET_PROTOS - 1); |
179 | if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) { | 176 | if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) { |
@@ -206,7 +203,7 @@ resubmit: | |||
206 | else if (ret == 0) | 203 | else if (ret == 0) |
207 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); | 204 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); |
208 | } else { | 205 | } else { |
209 | if (!raw_sk) { | 206 | if (!raw) { |
210 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 207 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
211 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS); | 208 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS); |
212 | icmpv6_send(skb, ICMPV6_PARAMPROB, | 209 | icmpv6_send(skb, ICMPV6_PARAMPROB, |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ad622cc11bda..53f01b4982c7 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -60,8 +60,10 @@ | |||
60 | #include <linux/proc_fs.h> | 60 | #include <linux/proc_fs.h> |
61 | #include <linux/seq_file.h> | 61 | #include <linux/seq_file.h> |
62 | 62 | ||
63 | struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE]; | 63 | #define RAWV6_HTABLE_SIZE MAX_INET_PROTOS |
64 | DEFINE_RWLOCK(raw_v6_lock); | 64 | |
65 | static struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE]; | ||
66 | static DEFINE_RWLOCK(raw_v6_lock); | ||
65 | 67 | ||
66 | static void raw_v6_hash(struct sock *sk) | 68 | static void raw_v6_hash(struct sock *sk) |
67 | { | 69 | { |
@@ -83,10 +85,8 @@ static void raw_v6_unhash(struct sock *sk) | |||
83 | } | 85 | } |
84 | 86 | ||
85 | 87 | ||
86 | /* Grumble... icmp and ip_input want to get at this... */ | 88 | static struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, |
87 | struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, | 89 | struct in6_addr *loc_addr, struct in6_addr *rmt_addr, int dif) |
88 | struct in6_addr *loc_addr, struct in6_addr *rmt_addr, | ||
89 | int dif) | ||
90 | { | 90 | { |
91 | struct hlist_node *node; | 91 | struct hlist_node *node; |
92 | int is_multicast = ipv6_addr_is_multicast(loc_addr); | 92 | int is_multicast = ipv6_addr_is_multicast(loc_addr); |
@@ -167,7 +167,7 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister); | |||
167 | * | 167 | * |
168 | * Caller owns SKB so we must make clones. | 168 | * Caller owns SKB so we must make clones. |
169 | */ | 169 | */ |
170 | int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | 170 | static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) |
171 | { | 171 | { |
172 | struct in6_addr *saddr; | 172 | struct in6_addr *saddr; |
173 | struct in6_addr *daddr; | 173 | struct in6_addr *daddr; |
@@ -242,6 +242,17 @@ out: | |||
242 | return delivered; | 242 | return delivered; |
243 | } | 243 | } |
244 | 244 | ||
245 | int raw6_local_deliver(struct sk_buff *skb, int nexthdr) | ||
246 | { | ||
247 | struct sock *raw_sk; | ||
248 | |||
249 | raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); | ||
250 | if (raw_sk && !ipv6_raw_deliver(skb, nexthdr)) | ||
251 | raw_sk = NULL; | ||
252 | |||
253 | return raw_sk != NULL; | ||
254 | } | ||
255 | |||
245 | /* This cleans up af_inet6 a bit. -DaveM */ | 256 | /* This cleans up af_inet6 a bit. -DaveM */ |
246 | static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 257 | static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
247 | { | 258 | { |
@@ -316,7 +327,7 @@ out: | |||
316 | return err; | 327 | return err; |
317 | } | 328 | } |
318 | 329 | ||
319 | void rawv6_err(struct sock *sk, struct sk_buff *skb, | 330 | static void rawv6_err(struct sock *sk, struct sk_buff *skb, |
320 | struct inet6_skb_parm *opt, | 331 | struct inet6_skb_parm *opt, |
321 | int type, int code, int offset, __be32 info) | 332 | int type, int code, int offset, __be32 info) |
322 | { | 333 | { |
@@ -350,6 +361,31 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb, | |||
350 | } | 361 | } |
351 | } | 362 | } |
352 | 363 | ||
364 | void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | ||
365 | int type, int code, int inner_offset, __be32 info) | ||
366 | { | ||
367 | struct sock *sk; | ||
368 | int hash; | ||
369 | struct in6_addr *saddr, *daddr; | ||
370 | |||
371 | hash = nexthdr & (RAWV6_HTABLE_SIZE - 1); | ||
372 | |||
373 | read_lock(&raw_v6_lock); | ||
374 | sk = sk_head(&raw_v6_htable[hash]); | ||
375 | if (sk != NULL) { | ||
376 | saddr = &ipv6_hdr(skb)->saddr; | ||
377 | daddr = &ipv6_hdr(skb)->daddr; | ||
378 | |||
379 | while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr, | ||
380 | IP6CB(skb)->iif))) { | ||
381 | rawv6_err(sk, skb, NULL, type, code, | ||
382 | inner_offset, info); | ||
383 | sk = sk_next(sk); | ||
384 | } | ||
385 | } | ||
386 | read_unlock(&raw_v6_lock); | ||
387 | } | ||
388 | |||
353 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) | 389 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) |
354 | { | 390 | { |
355 | if ((raw6_sk(sk)->checksum || sk->sk_filter) && | 391 | if ((raw6_sk(sk)->checksum || sk->sk_filter) && |