aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ndisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r--net/ipv6/ndisc.c435
1 files changed, 183 insertions, 252 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 121f31c283f8..d8b36451bada 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -319,6 +319,8 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d
319 return -EINVAL; 319 return -EINVAL;
320} 320}
321 321
322EXPORT_SYMBOL(ndisc_mc_map);
323
322static u32 ndisc_hash(const void *pkey, const struct net_device *dev) 324static u32 ndisc_hash(const void *pkey, const struct net_device *dev)
323{ 325{
324 const u32 *p32 = pkey; 326 const u32 *p32 = pkey;
@@ -425,36 +427,23 @@ static inline void ndisc_flow_init(struct flowi *fl, u8 type,
425 security_sk_classify_flow(ndisc_socket->sk, fl); 427 security_sk_classify_flow(ndisc_socket->sk, fl);
426} 428}
427 429
428static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, 430static void __ndisc_send(struct net_device *dev,
429 struct in6_addr *daddr, struct in6_addr *solicited_addr, 431 struct neighbour *neigh,
430 int router, int solicited, int override, int inc_opt) 432 struct in6_addr *daddr, struct in6_addr *saddr,
433 struct icmp6hdr *icmp6h, struct in6_addr *target,
434 int llinfo, int icmp6_mib_outnd)
431{ 435{
432 struct in6_addr tmpaddr;
433 struct inet6_ifaddr *ifp;
434 struct inet6_dev *idev;
435 struct flowi fl; 436 struct flowi fl;
436 struct dst_entry* dst; 437 struct dst_entry *dst;
437 struct sock *sk = ndisc_socket->sk; 438 struct sock *sk = ndisc_socket->sk;
438 struct in6_addr *src_addr;
439 struct nd_msg *msg;
440 int len;
441 struct sk_buff *skb; 439 struct sk_buff *skb;
440 struct icmp6hdr *hdr;
441 struct inet6_dev *idev;
442 int len;
442 int err; 443 int err;
444 u8 *opt;
443 445
444 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); 446 ndisc_flow_init(&fl, icmp6h->icmp6_type, saddr, daddr,
445
446 /* for anycast or proxy, solicited_addr != src_addr */
447 ifp = ipv6_get_ifaddr(solicited_addr, dev, 1);
448 if (ifp) {
449 src_addr = solicited_addr;
450 in6_ifa_put(ifp);
451 } else {
452 if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
453 return;
454 src_addr = &tmpaddr;
455 }
456
457 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr,
458 dev->ifindex); 447 dev->ifindex);
459 448
460 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); 449 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
@@ -465,60 +454,57 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
465 if (err < 0) 454 if (err < 0)
466 return; 455 return;
467 456
468 if (inc_opt) { 457 if (!dev->addr_len)
469 if (dev->addr_len) 458 llinfo = 0;
470 len += ndisc_opt_addr_space(dev); 459
471 else 460 len = sizeof(struct icmp6hdr) + (target ? sizeof(*target) : 0);
472 inc_opt = 0; 461 if (llinfo)
473 } 462 len += ndisc_opt_addr_space(dev);
474 463
475 skb = sock_alloc_send_skb(sk, 464 skb = sock_alloc_send_skb(sk,
476 (MAX_HEADER + sizeof(struct ipv6hdr) + 465 (MAX_HEADER + sizeof(struct ipv6hdr) +
477 len + LL_RESERVED_SPACE(dev)), 466 len + LL_RESERVED_SPACE(dev)),
478 1, &err); 467 1, &err);
479 468 if (!skb) {
480 if (skb == NULL) {
481 ND_PRINTK0(KERN_ERR 469 ND_PRINTK0(KERN_ERR
482 "ICMPv6 NA: %s() failed to allocate an skb.\n", 470 "ICMPv6 ND: %s() failed to allocate an skb.\n",
483 __FUNCTION__); 471 __FUNCTION__);
484 dst_release(dst); 472 dst_release(dst);
485 return; 473 return;
486 } 474 }
487 475
488 skb_reserve(skb, LL_RESERVED_SPACE(dev)); 476 skb_reserve(skb, LL_RESERVED_SPACE(dev));
489 ip6_nd_hdr(sk, skb, dev, src_addr, daddr, IPPROTO_ICMPV6, len); 477 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
490
491 msg = (struct nd_msg *)skb_put(skb, len);
492 skb->h.raw = (unsigned char*)msg;
493 478
494 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; 479 skb->transport_header = skb->tail;
495 msg->icmph.icmp6_code = 0; 480 skb_put(skb, len);
496 msg->icmph.icmp6_cksum = 0;
497 481
498 msg->icmph.icmp6_unused = 0; 482 hdr = (struct icmp6hdr *)skb_transport_header(skb);
499 msg->icmph.icmp6_router = router; 483 memcpy(hdr, icmp6h, sizeof(*hdr));
500 msg->icmph.icmp6_solicited = solicited;
501 msg->icmph.icmp6_override = override;
502 484
503 /* Set the target address. */ 485 opt = skb_transport_header(skb) + sizeof(struct icmp6hdr);
504 ipv6_addr_copy(&msg->target, solicited_addr); 486 if (target) {
487 ipv6_addr_copy((struct in6_addr *)opt, target);
488 opt += sizeof(*target);
489 }
505 490
506 if (inc_opt) 491 if (llinfo)
507 ndisc_fill_addr_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr, 492 ndisc_fill_addr_option(opt, llinfo, dev->dev_addr,
508 dev->addr_len, dev->type); 493 dev->addr_len, dev->type);
509 494
510 /* checksum */ 495 hdr->icmp6_cksum = csum_ipv6_magic(saddr, daddr, len,
511 msg->icmph.icmp6_cksum = csum_ipv6_magic(src_addr, daddr, len, 496 IPPROTO_ICMPV6,
512 IPPROTO_ICMPV6, 497 csum_partial((__u8 *) hdr,
513 csum_partial((__u8 *) msg, 498 len, 0));
514 len, 0));
515 499
516 skb->dst = dst; 500 skb->dst = dst;
501
517 idev = in6_dev_get(dst->dev); 502 idev = in6_dev_get(dst->dev);
518 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); 503 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
504
519 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); 505 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
520 if (!err) { 506 if (!err) {
521 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); 507 ICMP6_INC_STATS(idev, icmp6_mib_outnd);
522 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); 508 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
523 } 509 }
524 510
@@ -526,165 +512,95 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
526 in6_dev_put(idev); 512 in6_dev_put(idev);
527} 513}
528 514
515static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
516 struct in6_addr *daddr, struct in6_addr *solicited_addr,
517 int router, int solicited, int override, int inc_opt)
518{
519 struct in6_addr tmpaddr;
520 struct inet6_ifaddr *ifp;
521 struct in6_addr *src_addr;
522 struct icmp6hdr icmp6h = {
523 .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
524 };
525
526 /* for anycast or proxy, solicited_addr != src_addr */
527 ifp = ipv6_get_ifaddr(solicited_addr, dev, 1);
528 if (ifp) {
529 src_addr = solicited_addr;
530 if (ifp->flags & IFA_F_OPTIMISTIC)
531 override = 0;
532 in6_ifa_put(ifp);
533 } else {
534 if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
535 return;
536 src_addr = &tmpaddr;
537 }
538
539 icmp6h.icmp6_router = router;
540 icmp6h.icmp6_solicited = solicited;
541 icmp6h.icmp6_override = override;
542
543 __ndisc_send(dev, neigh, daddr, src_addr,
544 &icmp6h, solicited_addr,
545 inc_opt ? ND_OPT_TARGET_LL_ADDR : 0,
546 ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS);
547}
548
529void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, 549void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
530 struct in6_addr *solicit, 550 struct in6_addr *solicit,
531 struct in6_addr *daddr, struct in6_addr *saddr) 551 struct in6_addr *daddr, struct in6_addr *saddr)
532{ 552{
533 struct flowi fl;
534 struct dst_entry* dst;
535 struct inet6_dev *idev;
536 struct sock *sk = ndisc_socket->sk;
537 struct sk_buff *skb;
538 struct nd_msg *msg;
539 struct in6_addr addr_buf; 553 struct in6_addr addr_buf;
540 int len; 554 struct icmp6hdr icmp6h = {
541 int err; 555 .icmp6_type = NDISC_NEIGHBOUR_SOLICITATION,
542 int send_llinfo; 556 };
543 557
544 if (saddr == NULL) { 558 if (saddr == NULL) {
545 if (ipv6_get_lladdr(dev, &addr_buf)) 559 if (ipv6_get_lladdr(dev, &addr_buf,
560 (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)))
546 return; 561 return;
547 saddr = &addr_buf; 562 saddr = &addr_buf;
548 } 563 }
549 564
550 ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr, 565 __ndisc_send(dev, neigh, daddr, saddr,
551 dev->ifindex); 566 &icmp6h, solicit,
552 567 !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0,
553 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); 568 ICMP6_MIB_OUTNEIGHBORSOLICITS);
554 if (!dst)
555 return;
556
557 err = xfrm_lookup(&dst, &fl, NULL, 0);
558 if (err < 0)
559 return;
560
561 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
562 send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
563 if (send_llinfo)
564 len += ndisc_opt_addr_space(dev);
565
566 skb = sock_alloc_send_skb(sk,
567 (MAX_HEADER + sizeof(struct ipv6hdr) +
568 len + LL_RESERVED_SPACE(dev)),
569 1, &err);
570 if (skb == NULL) {
571 ND_PRINTK0(KERN_ERR
572 "ICMPv6 NA: %s() failed to allocate an skb.\n",
573 __FUNCTION__);
574 dst_release(dst);
575 return;
576 }
577
578 skb_reserve(skb, LL_RESERVED_SPACE(dev));
579 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
580
581 msg = (struct nd_msg *)skb_put(skb, len);
582 skb->h.raw = (unsigned char*)msg;
583 msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
584 msg->icmph.icmp6_code = 0;
585 msg->icmph.icmp6_cksum = 0;
586 msg->icmph.icmp6_unused = 0;
587
588 /* Set the target address. */
589 ipv6_addr_copy(&msg->target, solicit);
590
591 if (send_llinfo)
592 ndisc_fill_addr_option(msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr,
593 dev->addr_len, dev->type);
594
595 /* checksum */
596 msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr,
597 daddr, len,
598 IPPROTO_ICMPV6,
599 csum_partial((__u8 *) msg,
600 len, 0));
601 /* send it! */
602 skb->dst = dst;
603 idev = in6_dev_get(dst->dev);
604 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
605 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
606 if (!err) {
607 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS);
608 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
609 }
610
611 if (likely(idev != NULL))
612 in6_dev_put(idev);
613} 569}
614 570
615void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, 571void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
616 struct in6_addr *daddr) 572 struct in6_addr *daddr)
617{ 573{
618 struct flowi fl; 574 struct icmp6hdr icmp6h = {
619 struct dst_entry* dst; 575 .icmp6_type = NDISC_ROUTER_SOLICITATION,
620 struct inet6_dev *idev; 576 };
621 struct sock *sk = ndisc_socket->sk; 577 int send_sllao = dev->addr_len;
622 struct sk_buff *skb;
623 struct icmp6hdr *hdr;
624 __u8 * opt;
625 int len;
626 int err;
627
628 ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr,
629 dev->ifindex);
630
631 dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output);
632 if (!dst)
633 return;
634
635 err = xfrm_lookup(&dst, &fl, NULL, 0);
636 if (err < 0)
637 return;
638
639 len = sizeof(struct icmp6hdr);
640 if (dev->addr_len)
641 len += ndisc_opt_addr_space(dev);
642
643 skb = sock_alloc_send_skb(sk,
644 (MAX_HEADER + sizeof(struct ipv6hdr) +
645 len + LL_RESERVED_SPACE(dev)),
646 1, &err);
647 if (skb == NULL) {
648 ND_PRINTK0(KERN_ERR
649 "ICMPv6 RS: %s() failed to allocate an skb.\n",
650 __FUNCTION__);
651 dst_release(dst);
652 return;
653 }
654
655 skb_reserve(skb, LL_RESERVED_SPACE(dev));
656 ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
657
658 hdr = (struct icmp6hdr *)skb_put(skb, len);
659 skb->h.raw = (unsigned char*)hdr;
660 hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
661 hdr->icmp6_code = 0;
662 hdr->icmp6_cksum = 0;
663 hdr->icmp6_unused = 0;
664
665 opt = (u8*) (hdr + 1);
666
667 if (dev->addr_len)
668 ndisc_fill_addr_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr,
669 dev->addr_len, dev->type);
670
671 /* checksum */
672 hdr->icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr, daddr, len,
673 IPPROTO_ICMPV6,
674 csum_partial((__u8 *) hdr, len, 0));
675 578
676 /* send it! */ 579#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
677 skb->dst = dst; 580 /*
678 idev = in6_dev_get(dst->dev); 581 * According to section 2.2 of RFC 4429, we must not
679 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); 582 * send router solicitations with a sllao from
680 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); 583 * optimistic addresses, but we may send the solicitation
681 if (!err) { 584 * if we don't include the sllao. So here we check
682 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS); 585 * if our address is optimistic, and if so, we
683 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); 586 * supress the inclusion of the sllao.
587 */
588 if (send_sllao) {
589 struct inet6_ifaddr *ifp = ipv6_get_ifaddr(saddr, dev, 1);
590 if (ifp) {
591 if (ifp->flags & IFA_F_OPTIMISTIC) {
592 send_sllao = 0;
593 }
594 in6_ifa_put(ifp);
595 } else {
596 send_sllao = 0;
597 }
684 } 598 }
685 599#endif
686 if (likely(idev != NULL)) 600 __ndisc_send(dev, NULL, daddr, saddr,
687 in6_dev_put(idev); 601 &icmp6h, NULL,
602 send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0,
603 ICMP6_MIB_OUTROUTERSOLICITS);
688} 604}
689 605
690 606
@@ -708,8 +624,8 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
708 struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; 624 struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
709 int probes = atomic_read(&neigh->probes); 625 int probes = atomic_read(&neigh->probes);
710 626
711 if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 1)) 627 if (skb && ipv6_chk_addr(&ipv6_hdr(skb)->saddr, dev, 1))
712 saddr = &skb->nh.ipv6h->saddr; 628 saddr = &ipv6_hdr(skb)->saddr;
713 629
714 if ((probes -= neigh->parms->ucast_probes) < 0) { 630 if ((probes -= neigh->parms->ucast_probes) < 0) {
715 if (!(neigh->nud_state & NUD_VALID)) { 631 if (!(neigh->nud_state & NUD_VALID)) {
@@ -732,11 +648,12 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
732 648
733static void ndisc_recv_ns(struct sk_buff *skb) 649static void ndisc_recv_ns(struct sk_buff *skb)
734{ 650{
735 struct nd_msg *msg = (struct nd_msg *)skb->h.raw; 651 struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
736 struct in6_addr *saddr = &skb->nh.ipv6h->saddr; 652 struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
737 struct in6_addr *daddr = &skb->nh.ipv6h->daddr; 653 struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
738 u8 *lladdr = NULL; 654 u8 *lladdr = NULL;
739 u32 ndoptlen = skb->tail - msg->opt; 655 u32 ndoptlen = skb->tail - (skb->transport_header +
656 offsetof(struct nd_msg, opt));
740 struct ndisc_options ndopts; 657 struct ndisc_options ndopts;
741 struct net_device *dev = skb->dev; 658 struct net_device *dev = skb->dev;
742 struct inet6_ifaddr *ifp; 659 struct inet6_ifaddr *ifp;
@@ -796,28 +713,40 @@ static void ndisc_recv_ns(struct sk_buff *skb)
796 inc = ipv6_addr_is_multicast(daddr); 713 inc = ipv6_addr_is_multicast(daddr);
797 714
798 if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) { 715 if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) {
799 if (ifp->flags & IFA_F_TENTATIVE) { 716
800 /* Address is tentative. If the source 717 if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
801 is unspecified address, it is someone 718 if (dad) {
802 does DAD, otherwise we ignore solicitations 719 if (dev->type == ARPHRD_IEEE802_TR) {
803 until DAD timer expires. 720 const unsigned char *sadr;
804 */ 721 sadr = skb_mac_header(skb);
805 if (!dad) 722 if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 &&
723 sadr[9] == dev->dev_addr[1] &&
724 sadr[10] == dev->dev_addr[2] &&
725 sadr[11] == dev->dev_addr[3] &&
726 sadr[12] == dev->dev_addr[4] &&
727 sadr[13] == dev->dev_addr[5]) {
728 /* looped-back to us */
729 goto out;
730 }
731 }
732
733 /*
734 * We are colliding with another node
735 * who is doing DAD
736 * so fail our DAD process
737 */
738 addrconf_dad_failure(ifp);
806 goto out; 739 goto out;
807 if (dev->type == ARPHRD_IEEE802_TR) { 740 } else {
808 unsigned char *sadr = skb->mac.raw; 741 /*
809 if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 && 742 * This is not a dad solicitation.
810 sadr[9] == dev->dev_addr[1] && 743 * If we are an optimistic node,
811 sadr[10] == dev->dev_addr[2] && 744 * we should respond.
812 sadr[11] == dev->dev_addr[3] && 745 * Otherwise, we should ignore it.
813 sadr[12] == dev->dev_addr[4] && 746 */
814 sadr[13] == dev->dev_addr[5]) { 747 if (!(ifp->flags & IFA_F_OPTIMISTIC))
815 /* looped-back to us */
816 goto out; 748 goto out;
817 }
818 } 749 }
819 addrconf_dad_failure(ifp);
820 return;
821 } 750 }
822 751
823 idev = ifp->idev; 752 idev = ifp->idev;
@@ -898,11 +827,12 @@ out:
898 827
899static void ndisc_recv_na(struct sk_buff *skb) 828static void ndisc_recv_na(struct sk_buff *skb)
900{ 829{
901 struct nd_msg *msg = (struct nd_msg *)skb->h.raw; 830 struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
902 struct in6_addr *saddr = &skb->nh.ipv6h->saddr; 831 struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
903 struct in6_addr *daddr = &skb->nh.ipv6h->daddr; 832 struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
904 u8 *lladdr = NULL; 833 u8 *lladdr = NULL;
905 u32 ndoptlen = skb->tail - msg->opt; 834 u32 ndoptlen = skb->tail - (skb->transport_header +
835 offsetof(struct nd_msg, opt));
906 struct ndisc_options ndopts; 836 struct ndisc_options ndopts;
907 struct net_device *dev = skb->dev; 837 struct net_device *dev = skb->dev;
908 struct inet6_ifaddr *ifp; 838 struct inet6_ifaddr *ifp;
@@ -1000,11 +930,11 @@ out:
1000 930
1001static void ndisc_recv_rs(struct sk_buff *skb) 931static void ndisc_recv_rs(struct sk_buff *skb)
1002{ 932{
1003 struct rs_msg *rs_msg = (struct rs_msg *) skb->h.raw; 933 struct rs_msg *rs_msg = (struct rs_msg *)skb_transport_header(skb);
1004 unsigned long ndoptlen = skb->len - sizeof(*rs_msg); 934 unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
1005 struct neighbour *neigh; 935 struct neighbour *neigh;
1006 struct inet6_dev *idev; 936 struct inet6_dev *idev;
1007 struct in6_addr *saddr = &skb->nh.ipv6h->saddr; 937 struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
1008 struct ndisc_options ndopts; 938 struct ndisc_options ndopts;
1009 u8 *lladdr = NULL; 939 u8 *lladdr = NULL;
1010 940
@@ -1057,7 +987,7 @@ out:
1057 987
1058static void ndisc_router_discovery(struct sk_buff *skb) 988static void ndisc_router_discovery(struct sk_buff *skb)
1059{ 989{
1060 struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw; 990 struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb);
1061 struct neighbour *neigh = NULL; 991 struct neighbour *neigh = NULL;
1062 struct inet6_dev *in6_dev; 992 struct inet6_dev *in6_dev;
1063 struct rt6_info *rt = NULL; 993 struct rt6_info *rt = NULL;
@@ -1068,9 +998,9 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1068 998
1069 __u8 * opt = (__u8 *)(ra_msg + 1); 999 __u8 * opt = (__u8 *)(ra_msg + 1);
1070 1000
1071 optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg); 1001 optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg);
1072 1002
1073 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) { 1003 if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
1074 ND_PRINTK2(KERN_WARNING 1004 ND_PRINTK2(KERN_WARNING
1075 "ICMPv6 RA: source address is not link-local.\n"); 1005 "ICMPv6 RA: source address is not link-local.\n");
1076 return; 1006 return;
@@ -1136,7 +1066,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1136 pref = ICMPV6_ROUTER_PREF_MEDIUM; 1066 pref = ICMPV6_ROUTER_PREF_MEDIUM;
1137#endif 1067#endif
1138 1068
1139 rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); 1069 rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
1140 1070
1141 if (rt) 1071 if (rt)
1142 neigh = rt->rt6i_nexthop; 1072 neigh = rt->rt6i_nexthop;
@@ -1151,7 +1081,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1151 ND_PRINTK3(KERN_DEBUG 1081 ND_PRINTK3(KERN_DEBUG
1152 "ICMPv6 RA: adding default router.\n"); 1082 "ICMPv6 RA: adding default router.\n");
1153 1083
1154 rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev, pref); 1084 rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref);
1155 if (rt == NULL) { 1085 if (rt == NULL) {
1156 ND_PRINTK0(KERN_ERR 1086 ND_PRINTK0(KERN_ERR
1157 "ICMPv6 RA: %s() failed to add default route.\n", 1087 "ICMPv6 RA: %s() failed to add default route.\n",
@@ -1223,7 +1153,7 @@ skip_defrtr:
1223 */ 1153 */
1224 1154
1225 if (!neigh) 1155 if (!neigh)
1226 neigh = __neigh_lookup(&nd_tbl, &skb->nh.ipv6h->saddr, 1156 neigh = __neigh_lookup(&nd_tbl, &ipv6_hdr(skb)->saddr,
1227 skb->dev, 1); 1157 skb->dev, 1);
1228 if (neigh) { 1158 if (neigh) {
1229 u8 *lladdr = NULL; 1159 u8 *lladdr = NULL;
@@ -1252,7 +1182,7 @@ skip_defrtr:
1252 if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) 1182 if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
1253 continue; 1183 continue;
1254 rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, 1184 rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
1255 &skb->nh.ipv6h->saddr); 1185 &ipv6_hdr(skb)->saddr);
1256 } 1186 }
1257 } 1187 }
1258#endif 1188#endif
@@ -1311,13 +1241,13 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
1311 int optlen; 1241 int optlen;
1312 u8 *lladdr = NULL; 1242 u8 *lladdr = NULL;
1313 1243
1314 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) { 1244 if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
1315 ND_PRINTK2(KERN_WARNING 1245 ND_PRINTK2(KERN_WARNING
1316 "ICMPv6 Redirect: source address is not link-local.\n"); 1246 "ICMPv6 Redirect: source address is not link-local.\n");
1317 return; 1247 return;
1318 } 1248 }
1319 1249
1320 optlen = skb->tail - skb->h.raw; 1250 optlen = skb->tail - skb->transport_header;
1321 optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); 1251 optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
1322 1252
1323 if (optlen < 0) { 1253 if (optlen < 0) {
@@ -1326,7 +1256,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
1326 return; 1256 return;
1327 } 1257 }
1328 1258
1329 icmph = (struct icmp6hdr *) skb->h.raw; 1259 icmph = icmp6_hdr(skb);
1330 target = (struct in6_addr *) (icmph + 1); 1260 target = (struct in6_addr *) (icmph + 1);
1331 dest = target + 1; 1261 dest = target + 1;
1332 1262
@@ -1376,8 +1306,8 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
1376 1306
1377 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1); 1307 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
1378 if (neigh) { 1308 if (neigh) {
1379 rt6_redirect(dest, &skb->nh.ipv6h->daddr, 1309 rt6_redirect(dest, &ipv6_hdr(skb)->daddr,
1380 &skb->nh.ipv6h->saddr, neigh, lladdr, 1310 &ipv6_hdr(skb)->saddr, neigh, lladdr,
1381 on_link); 1311 on_link);
1382 neigh_release(neigh); 1312 neigh_release(neigh);
1383 } 1313 }
@@ -1406,21 +1336,21 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1406 1336
1407 dev = skb->dev; 1337 dev = skb->dev;
1408 1338
1409 if (ipv6_get_lladdr(dev, &saddr_buf)) { 1339 if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) {
1410 ND_PRINTK2(KERN_WARNING 1340 ND_PRINTK2(KERN_WARNING
1411 "ICMPv6 Redirect: no link-local address on %s\n", 1341 "ICMPv6 Redirect: no link-local address on %s\n",
1412 dev->name); 1342 dev->name);
1413 return; 1343 return;
1414 } 1344 }
1415 1345
1416 if (!ipv6_addr_equal(&skb->nh.ipv6h->daddr, target) && 1346 if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) &&
1417 !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { 1347 !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
1418 ND_PRINTK2(KERN_WARNING 1348 ND_PRINTK2(KERN_WARNING
1419 "ICMPv6 Redirect: target address is not link-local.\n"); 1349 "ICMPv6 Redirect: target address is not link-local.\n");
1420 return; 1350 return;
1421 } 1351 }
1422 1352
1423 ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr, 1353 ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &ipv6_hdr(skb)->saddr,
1424 dev->ifindex); 1354 dev->ifindex);
1425 1355
1426 dst = ip6_route_output(NULL, &fl); 1356 dst = ip6_route_output(NULL, &fl);
@@ -1475,11 +1405,12 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1475 hlen = 0; 1405 hlen = 0;
1476 1406
1477 skb_reserve(buff, LL_RESERVED_SPACE(dev)); 1407 skb_reserve(buff, LL_RESERVED_SPACE(dev));
1478 ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr, 1408 ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr,
1479 IPPROTO_ICMPV6, len); 1409 IPPROTO_ICMPV6, len);
1480 1410
1481 icmph = (struct icmp6hdr *)skb_put(buff, len); 1411 skb_set_transport_header(buff, skb_tail_pointer(buff) - buff->data);
1482 buff->h.raw = (unsigned char*)icmph; 1412 skb_put(buff, len);
1413 icmph = icmp6_hdr(buff);
1483 1414
1484 memset(icmph, 0, sizeof(struct icmp6hdr)); 1415 memset(icmph, 0, sizeof(struct icmp6hdr));
1485 icmph->icmp6_type = NDISC_REDIRECT; 1416 icmph->icmp6_type = NDISC_REDIRECT;
@@ -1491,7 +1422,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1491 addrp = (struct in6_addr *)(icmph + 1); 1422 addrp = (struct in6_addr *)(icmph + 1);
1492 ipv6_addr_copy(addrp, target); 1423 ipv6_addr_copy(addrp, target);
1493 addrp++; 1424 addrp++;
1494 ipv6_addr_copy(addrp, &skb->nh.ipv6h->daddr); 1425 ipv6_addr_copy(addrp, &ipv6_hdr(skb)->daddr);
1495 1426
1496 opt = (u8*) (addrp + 1); 1427 opt = (u8*) (addrp + 1);
1497 1428
@@ -1512,9 +1443,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1512 *(opt++) = (rd_len >> 3); 1443 *(opt++) = (rd_len >> 3);
1513 opt += 6; 1444 opt += 6;
1514 1445
1515 memcpy(opt, skb->nh.ipv6h, rd_len - 8); 1446 memcpy(opt, ipv6_hdr(skb), rd_len - 8);
1516 1447
1517 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &skb->nh.ipv6h->saddr, 1448 icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr,
1518 len, IPPROTO_ICMPV6, 1449 len, IPPROTO_ICMPV6,
1519 csum_partial((u8 *) icmph, len, 0)); 1450 csum_partial((u8 *) icmph, len, 0));
1520 1451
@@ -1544,14 +1475,14 @@ int ndisc_rcv(struct sk_buff *skb)
1544 if (!pskb_may_pull(skb, skb->len)) 1475 if (!pskb_may_pull(skb, skb->len))
1545 return 0; 1476 return 0;
1546 1477
1547 msg = (struct nd_msg *) skb->h.raw; 1478 msg = (struct nd_msg *)skb_transport_header(skb);
1548 1479
1549 __skb_push(skb, skb->data-skb->h.raw); 1480 __skb_push(skb, skb->data - skb_transport_header(skb));
1550 1481
1551 if (skb->nh.ipv6h->hop_limit != 255) { 1482 if (ipv6_hdr(skb)->hop_limit != 255) {
1552 ND_PRINTK2(KERN_WARNING 1483 ND_PRINTK2(KERN_WARNING
1553 "ICMPv6 NDISC: invalid hop-limit: %d\n", 1484 "ICMPv6 NDISC: invalid hop-limit: %d\n",
1554 skb->nh.ipv6h->hop_limit); 1485 ipv6_hdr(skb)->hop_limit);
1555 return 0; 1486 return 0;
1556 } 1487 }
1557 1488
@@ -1584,7 +1515,7 @@ int ndisc_rcv(struct sk_buff *skb)
1584 case NDISC_REDIRECT: 1515 case NDISC_REDIRECT:
1585 ndisc_redirect_rcv(skb); 1516 ndisc_redirect_rcv(skb);
1586 break; 1517 break;
1587 }; 1518 }
1588 1519
1589 return 0; 1520 return 0;
1590} 1521}