diff options
author | David S. Miller <davem@davemloft.net> | 2011-12-03 22:53:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-03 22:53:31 -0500 |
commit | 78a8a36fe0b2cee5a0a7360107815cbcad5b4003 (patch) | |
tree | 1abf45fa898ed4e31a131328b0e182f29a72300a /net/ipv6 | |
parent | 04a6f4417bfd17c3860e8fb37387cb78265ffe44 (diff) | |
parent | ccb1352e76cff0524e7ccb2074826a092dd13016 (diff) |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/exthdrs_core.c | 11 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 7 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 3 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_REJECT.c | 3 |
5 files changed, 20 insertions, 7 deletions
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 37f548b7f6dc..72957f4a7c6c 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c | |||
@@ -57,6 +57,9 @@ int ipv6_ext_hdr(u8 nexthdr) | |||
57 | * it returns NULL. | 57 | * it returns NULL. |
58 | * - First fragment header is skipped, not-first ones | 58 | * - First fragment header is skipped, not-first ones |
59 | * are considered as unparsable. | 59 | * are considered as unparsable. |
60 | * - Reports the offset field of the final fragment header so it is | ||
61 | * possible to tell whether this is a first fragment, later fragment, | ||
62 | * or not fragmented. | ||
60 | * - ESP is unparsable for now and considered like | 63 | * - ESP is unparsable for now and considered like |
61 | * normal payload protocol. | 64 | * normal payload protocol. |
62 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. | 65 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. |
@@ -64,10 +67,13 @@ int ipv6_ext_hdr(u8 nexthdr) | |||
64 | * --ANK (980726) | 67 | * --ANK (980726) |
65 | */ | 68 | */ |
66 | 69 | ||
67 | int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) | 70 | int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, |
71 | __be16 *frag_offp) | ||
68 | { | 72 | { |
69 | u8 nexthdr = *nexthdrp; | 73 | u8 nexthdr = *nexthdrp; |
70 | 74 | ||
75 | *frag_offp = 0; | ||
76 | |||
71 | while (ipv6_ext_hdr(nexthdr)) { | 77 | while (ipv6_ext_hdr(nexthdr)) { |
72 | struct ipv6_opt_hdr _hdr, *hp; | 78 | struct ipv6_opt_hdr _hdr, *hp; |
73 | int hdrlen; | 79 | int hdrlen; |
@@ -87,7 +93,8 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) | |||
87 | if (fp == NULL) | 93 | if (fp == NULL) |
88 | return -1; | 94 | return -1; |
89 | 95 | ||
90 | if (ntohs(*fp) & ~0x7) | 96 | *frag_offp = *fp; |
97 | if (ntohs(*frag_offp) & ~0x7) | ||
91 | break; | 98 | break; |
92 | hdrlen = 8; | 99 | hdrlen = 8; |
93 | } else if (nexthdr == NEXTHDR_AUTH) | 100 | } else if (nexthdr == NEXTHDR_AUTH) |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 9e2bdccf9143..01d46bff63c3 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -135,11 +135,12 @@ static int is_ineligible(struct sk_buff *skb) | |||
135 | int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; | 135 | int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; |
136 | int len = skb->len - ptr; | 136 | int len = skb->len - ptr; |
137 | __u8 nexthdr = ipv6_hdr(skb)->nexthdr; | 137 | __u8 nexthdr = ipv6_hdr(skb)->nexthdr; |
138 | __be16 frag_off; | ||
138 | 139 | ||
139 | if (len < 0) | 140 | if (len < 0) |
140 | return 1; | 141 | return 1; |
141 | 142 | ||
142 | ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr); | 143 | ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, &frag_off); |
143 | if (ptr < 0) | 144 | if (ptr < 0) |
144 | return 0; | 145 | return 0; |
145 | if (nexthdr == IPPROTO_ICMPV6) { | 146 | if (nexthdr == IPPROTO_ICMPV6) { |
@@ -596,6 +597,7 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
596 | int inner_offset; | 597 | int inner_offset; |
597 | int hash; | 598 | int hash; |
598 | u8 nexthdr; | 599 | u8 nexthdr; |
600 | __be16 frag_off; | ||
599 | 601 | ||
600 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 602 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
601 | return; | 603 | return; |
@@ -603,7 +605,8 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
603 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; | 605 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; |
604 | if (ipv6_ext_hdr(nexthdr)) { | 606 | if (ipv6_ext_hdr(nexthdr)) { |
605 | /* now skip over extension headers */ | 607 | /* now skip over extension headers */ |
606 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); | 608 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), |
609 | &nexthdr, &frag_off); | ||
607 | if (inner_offset<0) | 610 | if (inner_offset<0) |
608 | return; | 611 | return; |
609 | } else { | 612 | } else { |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index a46c64eb0a66..1ca5d45a12e8 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -280,6 +280,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
280 | u8 *ptr = skb_network_header(skb) + opt->ra; | 280 | u8 *ptr = skb_network_header(skb) + opt->ra; |
281 | struct icmp6hdr *icmp6; | 281 | struct icmp6hdr *icmp6; |
282 | u8 nexthdr = hdr->nexthdr; | 282 | u8 nexthdr = hdr->nexthdr; |
283 | __be16 frag_off; | ||
283 | int offset; | 284 | int offset; |
284 | 285 | ||
285 | /* Check if the value of Router Alert | 286 | /* Check if the value of Router Alert |
@@ -293,7 +294,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
293 | goto out; | 294 | goto out; |
294 | } | 295 | } |
295 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), | 296 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), |
296 | &nexthdr); | 297 | &nexthdr, &frag_off); |
297 | if (offset < 0) | 298 | if (offset < 0) |
298 | goto out; | 299 | goto out; |
299 | 300 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index a24e15557843..3221bc675654 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -329,10 +329,11 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) | |||
329 | { | 329 | { |
330 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 330 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
331 | u8 nexthdr = hdr->nexthdr; | 331 | u8 nexthdr = hdr->nexthdr; |
332 | __be16 frag_off; | ||
332 | int offset; | 333 | int offset; |
333 | 334 | ||
334 | if (ipv6_ext_hdr(nexthdr)) { | 335 | if (ipv6_ext_hdr(nexthdr)) { |
335 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr); | 336 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr, &frag_off); |
336 | if (offset < 0) | 337 | if (offset < 0) |
337 | return 0; | 338 | return 0; |
338 | } else | 339 | } else |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index b5a2aa58a03a..aad2fa41cf46 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -49,6 +49,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
49 | const __u8 tclass = DEFAULT_TOS_VALUE; | 49 | const __u8 tclass = DEFAULT_TOS_VALUE; |
50 | struct dst_entry *dst = NULL; | 50 | struct dst_entry *dst = NULL; |
51 | u8 proto; | 51 | u8 proto; |
52 | __be16 frag_off; | ||
52 | struct flowi6 fl6; | 53 | struct flowi6 fl6; |
53 | 54 | ||
54 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | 55 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || |
@@ -58,7 +59,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
58 | } | 59 | } |
59 | 60 | ||
60 | proto = oip6h->nexthdr; | 61 | proto = oip6h->nexthdr; |
61 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); | 62 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off); |
62 | 63 | ||
63 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | 64 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { |
64 | pr_debug("Cannot get TCP header.\n"); | 65 | pr_debug("Cannot get TCP header.\n"); |