diff options
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r-- | net/ipv6/icmp.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index edfe98bf64c3..e9bcce9e7bdf 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #include <asm/system.h> | 68 | #include <asm/system.h> |
69 | 69 | ||
70 | DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly; | 70 | DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly; |
71 | EXPORT_SYMBOL(icmpv6_statistics); | ||
71 | 72 | ||
72 | /* | 73 | /* |
73 | * The ICMP socket(s). This is the most convenient way to flow control | 74 | * The ICMP socket(s). This is the most convenient way to flow control |
@@ -128,9 +129,9 @@ void icmpv6_param_prob(struct sk_buff *skb, int code, int pos) | |||
128 | 129 | ||
129 | static int is_ineligible(struct sk_buff *skb) | 130 | static int is_ineligible(struct sk_buff *skb) |
130 | { | 131 | { |
131 | int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data; | 132 | int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; |
132 | int len = skb->len - ptr; | 133 | int len = skb->len - ptr; |
133 | __u8 nexthdr = skb->nh.ipv6h->nexthdr; | 134 | __u8 nexthdr = ipv6_hdr(skb)->nexthdr; |
134 | 135 | ||
135 | if (len < 0) | 136 | if (len < 0) |
136 | return 1; | 137 | return 1; |
@@ -205,7 +206,7 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset) | |||
205 | { | 206 | { |
206 | u8 _optval, *op; | 207 | u8 _optval, *op; |
207 | 208 | ||
208 | offset += skb->nh.raw - skb->data; | 209 | offset += skb_network_offset(skb); |
209 | op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval); | 210 | op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval); |
210 | if (op == NULL) | 211 | if (op == NULL) |
211 | return 1; | 212 | return 1; |
@@ -221,7 +222,7 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct | |||
221 | if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) | 222 | if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) |
222 | goto out; | 223 | goto out; |
223 | 224 | ||
224 | icmp6h = (struct icmp6hdr*) skb->h.raw; | 225 | icmp6h = icmp6_hdr(skb); |
225 | memcpy(icmp6h, thdr, sizeof(struct icmp6hdr)); | 226 | memcpy(icmp6h, thdr, sizeof(struct icmp6hdr)); |
226 | icmp6h->icmp6_cksum = 0; | 227 | icmp6h->icmp6_cksum = 0; |
227 | 228 | ||
@@ -274,7 +275,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st | |||
274 | #ifdef CONFIG_IPV6_MIP6 | 275 | #ifdef CONFIG_IPV6_MIP6 |
275 | static void mip6_addr_swap(struct sk_buff *skb) | 276 | static void mip6_addr_swap(struct sk_buff *skb) |
276 | { | 277 | { |
277 | struct ipv6hdr *iph = skb->nh.ipv6h; | 278 | struct ipv6hdr *iph = ipv6_hdr(skb); |
278 | struct inet6_skb_parm *opt = IP6CB(skb); | 279 | struct inet6_skb_parm *opt = IP6CB(skb); |
279 | struct ipv6_destopt_hao *hao; | 280 | struct ipv6_destopt_hao *hao; |
280 | struct in6_addr tmp; | 281 | struct in6_addr tmp; |
@@ -283,7 +284,8 @@ static void mip6_addr_swap(struct sk_buff *skb) | |||
283 | if (opt->dsthao) { | 284 | if (opt->dsthao) { |
284 | off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); | 285 | off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); |
285 | if (likely(off >= 0)) { | 286 | if (likely(off >= 0)) { |
286 | hao = (struct ipv6_destopt_hao *)(skb->nh.raw + off); | 287 | hao = (struct ipv6_destopt_hao *) |
288 | (skb_network_header(skb) + off); | ||
287 | ipv6_addr_copy(&tmp, &iph->saddr); | 289 | ipv6_addr_copy(&tmp, &iph->saddr); |
288 | ipv6_addr_copy(&iph->saddr, &hao->addr); | 290 | ipv6_addr_copy(&iph->saddr, &hao->addr); |
289 | ipv6_addr_copy(&hao->addr, &tmp); | 291 | ipv6_addr_copy(&hao->addr, &tmp); |
@@ -301,7 +303,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
301 | struct net_device *dev) | 303 | struct net_device *dev) |
302 | { | 304 | { |
303 | struct inet6_dev *idev = NULL; | 305 | struct inet6_dev *idev = NULL; |
304 | struct ipv6hdr *hdr = skb->nh.ipv6h; | 306 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
305 | struct sock *sk; | 307 | struct sock *sk; |
306 | struct ipv6_pinfo *np; | 308 | struct ipv6_pinfo *np; |
307 | struct in6_addr *saddr = NULL; | 309 | struct in6_addr *saddr = NULL; |
@@ -315,7 +317,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
315 | int hlimit, tclass; | 317 | int hlimit, tclass; |
316 | int err = 0; | 318 | int err = 0; |
317 | 319 | ||
318 | if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail) | 320 | if ((u8 *)hdr < skb->head || |
321 | (skb->network_header + sizeof(*hdr)) > skb->tail) | ||
319 | return; | 322 | return; |
320 | 323 | ||
321 | /* | 324 | /* |
@@ -430,7 +433,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
430 | tclass = 0; | 433 | tclass = 0; |
431 | 434 | ||
432 | msg.skb = skb; | 435 | msg.skb = skb; |
433 | msg.offset = skb->nh.raw - skb->data; | 436 | msg.offset = skb_network_offset(skb); |
434 | msg.type = type; | 437 | msg.type = type; |
435 | 438 | ||
436 | len = skb->len - msg.offset; | 439 | len = skb->len - msg.offset; |
@@ -466,13 +469,15 @@ out: | |||
466 | icmpv6_xmit_unlock(); | 469 | icmpv6_xmit_unlock(); |
467 | } | 470 | } |
468 | 471 | ||
472 | EXPORT_SYMBOL(icmpv6_send); | ||
473 | |||
469 | static void icmpv6_echo_reply(struct sk_buff *skb) | 474 | static void icmpv6_echo_reply(struct sk_buff *skb) |
470 | { | 475 | { |
471 | struct sock *sk; | 476 | struct sock *sk; |
472 | struct inet6_dev *idev; | 477 | struct inet6_dev *idev; |
473 | struct ipv6_pinfo *np; | 478 | struct ipv6_pinfo *np; |
474 | struct in6_addr *saddr = NULL; | 479 | struct in6_addr *saddr = NULL; |
475 | struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw; | 480 | struct icmp6hdr *icmph = icmp6_hdr(skb); |
476 | struct icmp6hdr tmp_hdr; | 481 | struct icmp6hdr tmp_hdr; |
477 | struct flowi fl; | 482 | struct flowi fl; |
478 | struct icmpv6_msg msg; | 483 | struct icmpv6_msg msg; |
@@ -481,7 +486,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
481 | int hlimit; | 486 | int hlimit; |
482 | int tclass; | 487 | int tclass; |
483 | 488 | ||
484 | saddr = &skb->nh.ipv6h->daddr; | 489 | saddr = &ipv6_hdr(skb)->daddr; |
485 | 490 | ||
486 | if (!ipv6_unicast_destination(skb)) | 491 | if (!ipv6_unicast_destination(skb)) |
487 | saddr = NULL; | 492 | saddr = NULL; |
@@ -491,7 +496,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
491 | 496 | ||
492 | memset(&fl, 0, sizeof(fl)); | 497 | memset(&fl, 0, sizeof(fl)); |
493 | fl.proto = IPPROTO_ICMPV6; | 498 | fl.proto = IPPROTO_ICMPV6; |
494 | ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr); | 499 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); |
495 | if (saddr) | 500 | if (saddr) |
496 | ipv6_addr_copy(&fl.fl6_src, saddr); | 501 | ipv6_addr_copy(&fl.fl6_src, saddr); |
497 | fl.oif = skb->dev->ifindex; | 502 | fl.oif = skb->dev->ifindex; |
@@ -579,8 +584,8 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | |||
579 | if (!pskb_may_pull(skb, inner_offset+8)) | 584 | if (!pskb_may_pull(skb, inner_offset+8)) |
580 | return; | 585 | return; |
581 | 586 | ||
582 | saddr = &skb->nh.ipv6h->saddr; | 587 | saddr = &ipv6_hdr(skb)->saddr; |
583 | daddr = &skb->nh.ipv6h->daddr; | 588 | daddr = &ipv6_hdr(skb)->daddr; |
584 | 589 | ||
585 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. | 590 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. |
586 | Without this we will not able f.e. to make source routed | 591 | Without this we will not able f.e. to make source routed |
@@ -624,8 +629,8 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
624 | 629 | ||
625 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS); | 630 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS); |
626 | 631 | ||
627 | saddr = &skb->nh.ipv6h->saddr; | 632 | saddr = &ipv6_hdr(skb)->saddr; |
628 | daddr = &skb->nh.ipv6h->daddr; | 633 | daddr = &ipv6_hdr(skb)->daddr; |
629 | 634 | ||
630 | /* Perform checksum. */ | 635 | /* Perform checksum. */ |
631 | switch (skb->ip_summed) { | 636 | switch (skb->ip_summed) { |
@@ -647,7 +652,7 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
647 | if (!pskb_pull(skb, sizeof(struct icmp6hdr))) | 652 | if (!pskb_pull(skb, sizeof(struct icmp6hdr))) |
648 | goto discard_it; | 653 | goto discard_it; |
649 | 654 | ||
650 | hdr = (struct icmp6hdr *) skb->h.raw; | 655 | hdr = icmp6_hdr(skb); |
651 | 656 | ||
652 | type = hdr->icmp6_type; | 657 | type = hdr->icmp6_type; |
653 | 658 | ||
@@ -673,7 +678,7 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
673 | */ | 678 | */ |
674 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 679 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
675 | goto discard_it; | 680 | goto discard_it; |
676 | hdr = (struct icmp6hdr *) skb->h.raw; | 681 | hdr = icmp6_hdr(skb); |
677 | orig_hdr = (struct ipv6hdr *) (hdr + 1); | 682 | orig_hdr = (struct ipv6hdr *) (hdr + 1); |
678 | rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, | 683 | rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, |
679 | ntohl(hdr->icmp6_mtu)); | 684 | ntohl(hdr->icmp6_mtu)); |
@@ -727,7 +732,8 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
727 | */ | 732 | */ |
728 | 733 | ||
729 | icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); | 734 | icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); |
730 | }; | 735 | } |
736 | |||
731 | kfree_skb(skb); | 737 | kfree_skb(skb); |
732 | return 0; | 738 | return 0; |
733 | 739 | ||
@@ -860,11 +866,13 @@ int icmpv6_err_convert(int type, int code, int *err) | |||
860 | case ICMPV6_TIME_EXCEED: | 866 | case ICMPV6_TIME_EXCEED: |
861 | *err = EHOSTUNREACH; | 867 | *err = EHOSTUNREACH; |
862 | break; | 868 | break; |
863 | }; | 869 | } |
864 | 870 | ||
865 | return fatal; | 871 | return fatal; |
866 | } | 872 | } |
867 | 873 | ||
874 | EXPORT_SYMBOL(icmpv6_err_convert); | ||
875 | |||
868 | #ifdef CONFIG_SYSCTL | 876 | #ifdef CONFIG_SYSCTL |
869 | ctl_table ipv6_icmp_table[] = { | 877 | ctl_table ipv6_icmp_table[] = { |
870 | { | 878 | { |