diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 104 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 11 | ||||
-rw-r--r-- | net/ipv6/route.c | 11 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 7 | ||||
-rw-r--r-- | net/ipv6/udp.c | 28 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 3 |
6 files changed, 93 insertions, 71 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 88fd8c5877ee..3381b4317c27 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1380,6 +1380,8 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
1380 | if (dad_failed) | 1380 | if (dad_failed) |
1381 | ifp->flags |= IFA_F_DADFAILED; | 1381 | ifp->flags |= IFA_F_DADFAILED; |
1382 | spin_unlock_bh(&ifp->lock); | 1382 | spin_unlock_bh(&ifp->lock); |
1383 | if (dad_failed) | ||
1384 | ipv6_ifa_notify(0, ifp); | ||
1383 | in6_ifa_put(ifp); | 1385 | in6_ifa_put(ifp); |
1384 | #ifdef CONFIG_IPV6_PRIVACY | 1386 | #ifdef CONFIG_IPV6_PRIVACY |
1385 | } else if (ifp->flags&IFA_F_TEMPORARY) { | 1387 | } else if (ifp->flags&IFA_F_TEMPORARY) { |
@@ -2615,7 +2617,7 @@ static void addrconf_bonding_change(struct net_device *dev, unsigned long event) | |||
2615 | static int addrconf_ifdown(struct net_device *dev, int how) | 2617 | static int addrconf_ifdown(struct net_device *dev, int how) |
2616 | { | 2618 | { |
2617 | struct inet6_dev *idev; | 2619 | struct inet6_dev *idev; |
2618 | struct inet6_ifaddr *ifa, **bifa; | 2620 | struct inet6_ifaddr *ifa, *keep_list, **bifa; |
2619 | struct net *net = dev_net(dev); | 2621 | struct net *net = dev_net(dev); |
2620 | int i; | 2622 | int i; |
2621 | 2623 | ||
@@ -2649,11 +2651,11 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2649 | write_lock_bh(&addrconf_hash_lock); | 2651 | write_lock_bh(&addrconf_hash_lock); |
2650 | while ((ifa = *bifa) != NULL) { | 2652 | while ((ifa = *bifa) != NULL) { |
2651 | if (ifa->idev == idev && | 2653 | if (ifa->idev == idev && |
2652 | (how || !(ifa->flags&IFA_F_PERMANENT))) { | 2654 | (how || !(ifa->flags&IFA_F_PERMANENT) || |
2655 | ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
2653 | *bifa = ifa->lst_next; | 2656 | *bifa = ifa->lst_next; |
2654 | ifa->lst_next = NULL; | 2657 | ifa->lst_next = NULL; |
2655 | addrconf_del_timer(ifa); | 2658 | __in6_ifa_put(ifa); |
2656 | in6_ifa_put(ifa); | ||
2657 | continue; | 2659 | continue; |
2658 | } | 2660 | } |
2659 | bifa = &ifa->lst_next; | 2661 | bifa = &ifa->lst_next; |
@@ -2689,31 +2691,51 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2689 | write_lock_bh(&idev->lock); | 2691 | write_lock_bh(&idev->lock); |
2690 | } | 2692 | } |
2691 | #endif | 2693 | #endif |
2692 | bifa = &idev->addr_list; | 2694 | keep_list = NULL; |
2693 | while ((ifa = *bifa) != NULL) { | 2695 | bifa = &keep_list; |
2694 | if (how == 0 && (ifa->flags&IFA_F_PERMANENT)) { | 2696 | while ((ifa = idev->addr_list) != NULL) { |
2695 | /* Retain permanent address on admin down */ | 2697 | idev->addr_list = ifa->if_next; |
2698 | ifa->if_next = NULL; | ||
2699 | |||
2700 | addrconf_del_timer(ifa); | ||
2701 | |||
2702 | /* If just doing link down, and address is permanent | ||
2703 | and not link-local, then retain it. */ | ||
2704 | if (how == 0 && | ||
2705 | (ifa->flags&IFA_F_PERMANENT) && | ||
2706 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
2707 | |||
2708 | /* Move to holding list */ | ||
2709 | *bifa = ifa; | ||
2696 | bifa = &ifa->if_next; | 2710 | bifa = &ifa->if_next; |
2697 | 2711 | ||
2698 | /* Restart DAD if needed when link comes back up */ | 2712 | /* If not doing DAD on this address, just keep it. */ |
2699 | if ( !((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | 2713 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || |
2700 | idev->cnf.accept_dad <= 0 || | 2714 | idev->cnf.accept_dad <= 0 || |
2701 | (ifa->flags & IFA_F_NODAD))) | 2715 | (ifa->flags & IFA_F_NODAD)) |
2702 | ifa->flags |= IFA_F_TENTATIVE; | 2716 | continue; |
2703 | } else { | ||
2704 | *bifa = ifa->if_next; | ||
2705 | ifa->if_next = NULL; | ||
2706 | 2717 | ||
2718 | /* If it was tentative already, no need to notify */ | ||
2719 | if (ifa->flags & IFA_F_TENTATIVE) | ||
2720 | continue; | ||
2721 | |||
2722 | /* Flag it for later restoration when link comes up */ | ||
2723 | ifa->flags |= IFA_F_TENTATIVE; | ||
2724 | in6_ifa_hold(ifa); | ||
2725 | } else { | ||
2707 | ifa->dead = 1; | 2726 | ifa->dead = 1; |
2708 | write_unlock_bh(&idev->lock); | 2727 | } |
2728 | write_unlock_bh(&idev->lock); | ||
2709 | 2729 | ||
2710 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2730 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
2711 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 2731 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); |
2712 | in6_ifa_put(ifa); | 2732 | in6_ifa_put(ifa); |
2713 | 2733 | ||
2714 | write_lock_bh(&idev->lock); | 2734 | write_lock_bh(&idev->lock); |
2715 | } | ||
2716 | } | 2735 | } |
2736 | |||
2737 | idev->addr_list = keep_list; | ||
2738 | |||
2717 | write_unlock_bh(&idev->lock); | 2739 | write_unlock_bh(&idev->lock); |
2718 | 2740 | ||
2719 | /* Step 5: Discard multicast list */ | 2741 | /* Step 5: Discard multicast list */ |
@@ -2739,28 +2761,29 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2739 | static void addrconf_rs_timer(unsigned long data) | 2761 | static void addrconf_rs_timer(unsigned long data) |
2740 | { | 2762 | { |
2741 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 2763 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; |
2764 | struct inet6_dev *idev = ifp->idev; | ||
2742 | 2765 | ||
2743 | if (ifp->idev->cnf.forwarding) | 2766 | read_lock(&idev->lock); |
2767 | if (idev->dead || !(idev->if_flags & IF_READY)) | ||
2744 | goto out; | 2768 | goto out; |
2745 | 2769 | ||
2746 | if (ifp->idev->if_flags & IF_RA_RCVD) { | 2770 | if (idev->cnf.forwarding) |
2747 | /* | 2771 | goto out; |
2748 | * Announcement received after solicitation | 2772 | |
2749 | * was sent | 2773 | /* Announcement received after solicitation was sent */ |
2750 | */ | 2774 | if (idev->if_flags & IF_RA_RCVD) |
2751 | goto out; | 2775 | goto out; |
2752 | } | ||
2753 | 2776 | ||
2754 | spin_lock(&ifp->lock); | 2777 | spin_lock(&ifp->lock); |
2755 | if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { | 2778 | if (ifp->probes++ < idev->cnf.rtr_solicits) { |
2756 | /* The wait after the last probe can be shorter */ | 2779 | /* The wait after the last probe can be shorter */ |
2757 | addrconf_mod_timer(ifp, AC_RS, | 2780 | addrconf_mod_timer(ifp, AC_RS, |
2758 | (ifp->probes == ifp->idev->cnf.rtr_solicits) ? | 2781 | (ifp->probes == idev->cnf.rtr_solicits) ? |
2759 | ifp->idev->cnf.rtr_solicit_delay : | 2782 | idev->cnf.rtr_solicit_delay : |
2760 | ifp->idev->cnf.rtr_solicit_interval); | 2783 | idev->cnf.rtr_solicit_interval); |
2761 | spin_unlock(&ifp->lock); | 2784 | spin_unlock(&ifp->lock); |
2762 | 2785 | ||
2763 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); | 2786 | ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); |
2764 | } else { | 2787 | } else { |
2765 | spin_unlock(&ifp->lock); | 2788 | spin_unlock(&ifp->lock); |
2766 | /* | 2789 | /* |
@@ -2768,10 +2791,11 @@ static void addrconf_rs_timer(unsigned long data) | |||
2768 | * assumption any longer. | 2791 | * assumption any longer. |
2769 | */ | 2792 | */ |
2770 | printk(KERN_DEBUG "%s: no IPv6 routers present\n", | 2793 | printk(KERN_DEBUG "%s: no IPv6 routers present\n", |
2771 | ifp->idev->dev->name); | 2794 | idev->dev->name); |
2772 | } | 2795 | } |
2773 | 2796 | ||
2774 | out: | 2797 | out: |
2798 | read_unlock(&idev->lock); | ||
2775 | in6_ifa_put(ifp); | 2799 | in6_ifa_put(ifp); |
2776 | } | 2800 | } |
2777 | 2801 | ||
@@ -2850,9 +2874,9 @@ static void addrconf_dad_timer(unsigned long data) | |||
2850 | struct inet6_dev *idev = ifp->idev; | 2874 | struct inet6_dev *idev = ifp->idev; |
2851 | struct in6_addr mcaddr; | 2875 | struct in6_addr mcaddr; |
2852 | 2876 | ||
2853 | read_lock_bh(&idev->lock); | 2877 | read_lock(&idev->lock); |
2854 | if (idev->dead) { | 2878 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
2855 | read_unlock_bh(&idev->lock); | 2879 | read_unlock(&idev->lock); |
2856 | goto out; | 2880 | goto out; |
2857 | } | 2881 | } |
2858 | 2882 | ||
@@ -2864,7 +2888,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
2864 | 2888 | ||
2865 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 2889 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
2866 | spin_unlock(&ifp->lock); | 2890 | spin_unlock(&ifp->lock); |
2867 | read_unlock_bh(&idev->lock); | 2891 | read_unlock(&idev->lock); |
2868 | 2892 | ||
2869 | addrconf_dad_completed(ifp); | 2893 | addrconf_dad_completed(ifp); |
2870 | 2894 | ||
@@ -2874,7 +2898,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
2874 | ifp->probes--; | 2898 | ifp->probes--; |
2875 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); | 2899 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); |
2876 | spin_unlock(&ifp->lock); | 2900 | spin_unlock(&ifp->lock); |
2877 | read_unlock_bh(&idev->lock); | 2901 | read_unlock(&idev->lock); |
2878 | 2902 | ||
2879 | /* send a neighbour solicitation for our addr */ | 2903 | /* send a neighbour solicitation for our addr */ |
2880 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 2904 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 551882b9dfd6..5e463c43fcc2 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -84,18 +84,11 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
84 | if ((rule->flags & FIB_RULE_FIND_SADDR) && | 84 | if ((rule->flags & FIB_RULE_FIND_SADDR) && |
85 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { | 85 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { |
86 | struct in6_addr saddr; | 86 | struct in6_addr saddr; |
87 | unsigned int srcprefs = 0; | ||
88 | |||
89 | if (flags & RT6_LOOKUP_F_SRCPREF_TMP) | ||
90 | srcprefs |= IPV6_PREFER_SRC_TMP; | ||
91 | if (flags & RT6_LOOKUP_F_SRCPREF_PUBLIC) | ||
92 | srcprefs |= IPV6_PREFER_SRC_PUBLIC; | ||
93 | if (flags & RT6_LOOKUP_F_SRCPREF_COA) | ||
94 | srcprefs |= IPV6_PREFER_SRC_COA; | ||
95 | 87 | ||
96 | if (ipv6_dev_get_saddr(net, | 88 | if (ipv6_dev_get_saddr(net, |
97 | ip6_dst_idev(&rt->u.dst)->dev, | 89 | ip6_dst_idev(&rt->u.dst)->dev, |
98 | &flp->fl6_dst, srcprefs, | 90 | &flp->fl6_dst, |
91 | rt6_flags2srcprefs(flags), | ||
99 | &saddr)) | 92 | &saddr)) |
100 | goto again; | 93 | goto again; |
101 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, | 94 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b08879e97f22..52cd3eff31dc 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -819,15 +819,8 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | |||
819 | 819 | ||
820 | if (!ipv6_addr_any(&fl->fl6_src)) | 820 | if (!ipv6_addr_any(&fl->fl6_src)) |
821 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 821 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
822 | else if (sk) { | 822 | else if (sk) |
823 | unsigned int prefs = inet6_sk(sk)->srcprefs; | 823 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); |
824 | if (prefs & IPV6_PREFER_SRC_TMP) | ||
825 | flags |= RT6_LOOKUP_F_SRCPREF_TMP; | ||
826 | if (prefs & IPV6_PREFER_SRC_PUBLIC) | ||
827 | flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC; | ||
828 | if (prefs & IPV6_PREFER_SRC_COA) | ||
829 | flags |= RT6_LOOKUP_F_SRCPREF_COA; | ||
830 | } | ||
831 | 824 | ||
832 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); | 825 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); |
833 | } | 826 | } |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6963a6b6763e..9b6dbba80d31 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1740,8 +1740,11 @@ process: | |||
1740 | if (!tcp_prequeue(sk, skb)) | 1740 | if (!tcp_prequeue(sk, skb)) |
1741 | ret = tcp_v6_do_rcv(sk, skb); | 1741 | ret = tcp_v6_do_rcv(sk, skb); |
1742 | } | 1742 | } |
1743 | } else | 1743 | } else if (unlikely(sk_add_backlog(sk, skb))) { |
1744 | sk_add_backlog(sk, skb); | 1744 | bh_unlock_sock(sk); |
1745 | NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); | ||
1746 | goto discard_and_relse; | ||
1747 | } | ||
1745 | bh_unlock_sock(sk); | 1748 | bh_unlock_sock(sk); |
1746 | 1749 | ||
1747 | sock_put(sk); | 1750 | sock_put(sk); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 52b8347ae3b2..3c0c9c755c92 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -583,16 +583,20 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
583 | bh_lock_sock(sk); | 583 | bh_lock_sock(sk); |
584 | if (!sock_owned_by_user(sk)) | 584 | if (!sock_owned_by_user(sk)) |
585 | udpv6_queue_rcv_skb(sk, skb1); | 585 | udpv6_queue_rcv_skb(sk, skb1); |
586 | else | 586 | else if (sk_add_backlog(sk, skb1)) { |
587 | sk_add_backlog(sk, skb1); | 587 | kfree_skb(skb1); |
588 | bh_unlock_sock(sk); | ||
589 | goto drop; | ||
590 | } | ||
588 | bh_unlock_sock(sk); | 591 | bh_unlock_sock(sk); |
589 | } else { | 592 | continue; |
590 | atomic_inc(&sk->sk_drops); | ||
591 | UDP6_INC_STATS_BH(sock_net(sk), | ||
592 | UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); | ||
593 | UDP6_INC_STATS_BH(sock_net(sk), | ||
594 | UDP_MIB_INERRORS, IS_UDPLITE(sk)); | ||
595 | } | 593 | } |
594 | drop: | ||
595 | atomic_inc(&sk->sk_drops); | ||
596 | UDP6_INC_STATS_BH(sock_net(sk), | ||
597 | UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); | ||
598 | UDP6_INC_STATS_BH(sock_net(sk), | ||
599 | UDP_MIB_INERRORS, IS_UDPLITE(sk)); | ||
596 | } | 600 | } |
597 | } | 601 | } |
598 | /* | 602 | /* |
@@ -754,8 +758,12 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
754 | bh_lock_sock(sk); | 758 | bh_lock_sock(sk); |
755 | if (!sock_owned_by_user(sk)) | 759 | if (!sock_owned_by_user(sk)) |
756 | udpv6_queue_rcv_skb(sk, skb); | 760 | udpv6_queue_rcv_skb(sk, skb); |
757 | else | 761 | else if (sk_add_backlog(sk, skb)) { |
758 | sk_add_backlog(sk, skb); | 762 | atomic_inc(&sk->sk_drops); |
763 | bh_unlock_sock(sk); | ||
764 | sock_put(sk); | ||
765 | goto discard; | ||
766 | } | ||
759 | bh_unlock_sock(sk); | 767 | bh_unlock_sock(sk); |
760 | sock_put(sk); | 768 | sock_put(sk); |
761 | return 0; | 769 | return 0; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index dbdc696f5fc5..ae181651c75a 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -116,7 +116,8 @@ static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, | |||
116 | return 0; | 116 | return 0; |
117 | } | 117 | } |
118 | 118 | ||
119 | static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) | 119 | static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, |
120 | struct flowi *fl) | ||
120 | { | 121 | { |
121 | struct rt6_info *rt = (struct rt6_info*)xdst->route; | 122 | struct rt6_info *rt = (struct rt6_info*)xdst->route; |
122 | 123 | ||