diff options
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r-- | net/ipv6/ndisc.c | 84 |
1 files changed, 61 insertions, 23 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 886c5be14906..b79b00042310 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -449,6 +449,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
449 | ifp = ipv6_get_ifaddr(solicited_addr, dev, 1); | 449 | ifp = ipv6_get_ifaddr(solicited_addr, dev, 1); |
450 | if (ifp) { | 450 | if (ifp) { |
451 | src_addr = solicited_addr; | 451 | src_addr = solicited_addr; |
452 | if (ifp->flags & IFA_F_OPTIMISTIC) | ||
453 | override = 0; | ||
452 | in6_ifa_put(ifp); | 454 | in6_ifa_put(ifp); |
453 | } else { | 455 | } else { |
454 | if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) | 456 | if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) |
@@ -544,7 +546,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | |||
544 | int send_llinfo; | 546 | int send_llinfo; |
545 | 547 | ||
546 | if (saddr == NULL) { | 548 | if (saddr == NULL) { |
547 | if (ipv6_get_lladdr(dev, &addr_buf)) | 549 | if (ipv6_get_lladdr(dev, &addr_buf, |
550 | (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC))) | ||
548 | return; | 551 | return; |
549 | saddr = &addr_buf; | 552 | saddr = &addr_buf; |
550 | } | 553 | } |
@@ -624,9 +627,33 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
624 | struct sk_buff *skb; | 627 | struct sk_buff *skb; |
625 | struct icmp6hdr *hdr; | 628 | struct icmp6hdr *hdr; |
626 | __u8 * opt; | 629 | __u8 * opt; |
630 | struct inet6_ifaddr *ifp; | ||
631 | int send_sllao = dev->addr_len; | ||
627 | int len; | 632 | int len; |
628 | int err; | 633 | int err; |
629 | 634 | ||
635 | |||
636 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
637 | /* | ||
638 | * According to section 2.2 of RFC 4429, we must not | ||
639 | * send router solicitations with a sllao from | ||
640 | * optimistic addresses, but we may send the solicitation | ||
641 | * if we don't include the sllao. So here we check | ||
642 | * if our address is optimistic, and if so, we | ||
643 | * supress the inclusion of the sllao. | ||
644 | */ | ||
645 | if (send_sllao) { | ||
646 | ifp = ipv6_get_ifaddr(saddr, dev, 1); | ||
647 | if (ifp) { | ||
648 | if (ifp->flags & IFA_F_OPTIMISTIC) { | ||
649 | send_sllao=0; | ||
650 | in6_ifa_put(ifp); | ||
651 | } | ||
652 | } else { | ||
653 | send_sllao = 0; | ||
654 | } | ||
655 | } | ||
656 | #endif | ||
630 | ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr, | 657 | ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr, |
631 | dev->ifindex); | 658 | dev->ifindex); |
632 | 659 | ||
@@ -639,7 +666,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
639 | return; | 666 | return; |
640 | 667 | ||
641 | len = sizeof(struct icmp6hdr); | 668 | len = sizeof(struct icmp6hdr); |
642 | if (dev->addr_len) | 669 | if (send_sllao) |
643 | len += ndisc_opt_addr_space(dev); | 670 | len += ndisc_opt_addr_space(dev); |
644 | 671 | ||
645 | skb = sock_alloc_send_skb(sk, | 672 | skb = sock_alloc_send_skb(sk, |
@@ -666,7 +693,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
666 | 693 | ||
667 | opt = (u8*) (hdr + 1); | 694 | opt = (u8*) (hdr + 1); |
668 | 695 | ||
669 | if (dev->addr_len) | 696 | if (send_sllao) |
670 | ndisc_fill_addr_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, | 697 | ndisc_fill_addr_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, |
671 | dev->addr_len, dev->type); | 698 | dev->addr_len, dev->type); |
672 | 699 | ||
@@ -798,28 +825,39 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
798 | inc = ipv6_addr_is_multicast(daddr); | 825 | inc = ipv6_addr_is_multicast(daddr); |
799 | 826 | ||
800 | if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) { | 827 | if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) { |
801 | if (ifp->flags & IFA_F_TENTATIVE) { | 828 | |
802 | /* Address is tentative. If the source | 829 | if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { |
803 | is unspecified address, it is someone | 830 | if (dad) { |
804 | does DAD, otherwise we ignore solicitations | 831 | if (dev->type == ARPHRD_IEEE802_TR) { |
805 | until DAD timer expires. | 832 | unsigned char *sadr = skb->mac.raw; |
806 | */ | 833 | if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 && |
807 | if (!dad) | 834 | sadr[9] == dev->dev_addr[1] && |
835 | sadr[10] == dev->dev_addr[2] && | ||
836 | sadr[11] == dev->dev_addr[3] && | ||
837 | sadr[12] == dev->dev_addr[4] && | ||
838 | sadr[13] == dev->dev_addr[5]) { | ||
839 | /* looped-back to us */ | ||
840 | goto out; | ||
841 | } | ||
842 | } | ||
843 | |||
844 | /* | ||
845 | * We are colliding with another node | ||
846 | * who is doing DAD | ||
847 | * so fail our DAD process | ||
848 | */ | ||
849 | addrconf_dad_failure(ifp); | ||
808 | goto out; | 850 | goto out; |
809 | if (dev->type == ARPHRD_IEEE802_TR) { | 851 | } else { |
810 | unsigned char *sadr = skb->mac.raw; | 852 | /* |
811 | if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 && | 853 | * This is not a dad solicitation. |
812 | sadr[9] == dev->dev_addr[1] && | 854 | * If we are an optimistic node, |
813 | sadr[10] == dev->dev_addr[2] && | 855 | * we should respond. |
814 | sadr[11] == dev->dev_addr[3] && | 856 | * Otherwise, we should ignore it. |
815 | sadr[12] == dev->dev_addr[4] && | 857 | */ |
816 | sadr[13] == dev->dev_addr[5]) { | 858 | if (!(ifp->flags & IFA_F_OPTIMISTIC)) |
817 | /* looped-back to us */ | ||
818 | goto out; | 859 | goto out; |
819 | } | ||
820 | } | 860 | } |
821 | addrconf_dad_failure(ifp); | ||
822 | return; | ||
823 | } | 861 | } |
824 | 862 | ||
825 | idev = ifp->idev; | 863 | idev = ifp->idev; |
@@ -1408,7 +1446,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1408 | 1446 | ||
1409 | dev = skb->dev; | 1447 | dev = skb->dev; |
1410 | 1448 | ||
1411 | if (ipv6_get_lladdr(dev, &saddr_buf)) { | 1449 | if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { |
1412 | ND_PRINTK2(KERN_WARNING | 1450 | ND_PRINTK2(KERN_WARNING |
1413 | "ICMPv6 Redirect: no link-local address on %s\n", | 1451 | "ICMPv6 Redirect: no link-local address on %s\n", |
1414 | dev->name); | 1452 | dev->name); |