diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/exthdrs.c | 16 | ||||
| -rw-r--r-- | net/ipv6/ip6_input.c | 3 | ||||
| -rw-r--r-- | net/ipv6/xfrm6_policy.c | 8 |
3 files changed, 20 insertions, 7 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 2a1e7e45b890..a18d4256372c 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
| @@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { | |||
| 485 | { -1, } | 485 | { -1, } |
| 486 | }; | 486 | }; |
| 487 | 487 | ||
| 488 | int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) | 488 | int ipv6_parse_hopopts(struct sk_buff *skb) |
| 489 | { | 489 | { |
| 490 | struct inet6_skb_parm *opt = IP6CB(skb); | 490 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 491 | 491 | ||
| 492 | /* | ||
| 493 | * skb->nh.raw is equal to skb->data, and | ||
| 494 | * skb->h.raw - skb->nh.raw is always equal to | ||
| 495 | * sizeof(struct ipv6hdr) by definition of | ||
| 496 | * hop-by-hop options. | ||
| 497 | */ | ||
| 498 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) || | ||
| 499 | !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) { | ||
| 500 | kfree_skb(skb); | ||
| 501 | return -1; | ||
| 502 | } | ||
| 503 | |||
| 492 | opt->hop = sizeof(struct ipv6hdr); | 504 | opt->hop = sizeof(struct ipv6hdr); |
| 493 | if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { | 505 | if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { |
| 494 | skb->h.raw += (skb->h.raw[1]+1)<<3; | 506 | skb->h.raw += (skb->h.raw[1]+1)<<3; |
| 495 | opt->nhoff = sizeof(struct ipv6hdr); | 507 | opt->nhoff = sizeof(struct ipv6hdr); |
| 496 | return sizeof(struct ipv6hdr); | 508 | return 1; |
| 497 | } | 509 | } |
| 498 | return -1; | 510 | return -1; |
| 499 | } | 511 | } |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 29f73592e68e..aceee252503d 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -114,11 +114,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | if (hdr->nexthdr == NEXTHDR_HOP) { | 116 | if (hdr->nexthdr == NEXTHDR_HOP) { |
| 117 | if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) { | 117 | if (ipv6_parse_hopopts(skb) < 0) { |
| 118 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 118 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); |
| 119 | return 0; | 119 | return 0; |
| 120 | } | 120 | } |
| 121 | hdr = skb->nh.ipv6h; | ||
| 122 | } | 121 | } |
| 123 | 122 | ||
| 124 | return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); | 123 | return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 91cce8b2d7a5..88c840f1beb6 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -191,16 +191,18 @@ error: | |||
| 191 | static inline void | 191 | static inline void |
| 192 | _decode_session6(struct sk_buff *skb, struct flowi *fl) | 192 | _decode_session6(struct sk_buff *skb, struct flowi *fl) |
| 193 | { | 193 | { |
| 194 | u16 offset = sizeof(struct ipv6hdr); | 194 | u16 offset = skb->h.raw - skb->nh.raw; |
| 195 | struct ipv6hdr *hdr = skb->nh.ipv6h; | 195 | struct ipv6hdr *hdr = skb->nh.ipv6h; |
| 196 | struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 196 | struct ipv6_opt_hdr *exthdr; |
| 197 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | 197 | u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff]; |
| 198 | 198 | ||
| 199 | memset(fl, 0, sizeof(struct flowi)); | 199 | memset(fl, 0, sizeof(struct flowi)); |
| 200 | ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); | 200 | ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); |
| 201 | ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); | 201 | ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); |
| 202 | 202 | ||
| 203 | while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { | 203 | while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { |
| 204 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | ||
| 205 | |||
| 204 | switch (nexthdr) { | 206 | switch (nexthdr) { |
| 205 | case NEXTHDR_ROUTING: | 207 | case NEXTHDR_ROUTING: |
| 206 | case NEXTHDR_HOP: | 208 | case NEXTHDR_HOP: |
