aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c104
-rw-r--r--net/ipv6/fib6_rules.c11
-rw-r--r--net/ipv6/route.c11
-rw-r--r--net/ipv6/tcp_ipv6.c7
-rw-r--r--net/ipv6/udp.c28
-rw-r--r--net/ipv6/xfrm6_policy.c3
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)
2615static int addrconf_ifdown(struct net_device *dev, int how) 2617static 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)
2739static void addrconf_rs_timer(unsigned long data) 2761static 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
2774out: 2797out:
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 }
594drop:
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
119static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) 119static 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