aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c102
1 files changed, 41 insertions, 61 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 79181819a24..d7c56f8a5b4 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -127,8 +127,8 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
127#endif 127#endif
128 128
129#ifdef CONFIG_IPV6_PRIVACY 129#ifdef CONFIG_IPV6_PRIVACY
130static int __ipv6_regen_rndid(struct inet6_dev *idev); 130static void __ipv6_regen_rndid(struct inet6_dev *idev);
131static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); 131static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
132static void ipv6_regen_rndid(unsigned long data); 132static void ipv6_regen_rndid(unsigned long data);
133#endif 133#endif
134 134
@@ -494,8 +494,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
494 struct net_device *dev; 494 struct net_device *dev;
495 struct inet6_dev *idev; 495 struct inet6_dev *idev;
496 496
497 rcu_read_lock(); 497 for_each_netdev(net, dev) {
498 for_each_netdev_rcu(net, dev) {
499 idev = __in6_dev_get(dev); 498 idev = __in6_dev_get(dev);
500 if (idev) { 499 if (idev) {
501 int changed = (!idev->cnf.forwarding) ^ (!newf); 500 int changed = (!idev->cnf.forwarding) ^ (!newf);
@@ -504,7 +503,6 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
504 dev_forward_change(idev); 503 dev_forward_change(idev);
505 } 504 }
506 } 505 }
507 rcu_read_unlock();
508} 506}
509 507
510static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) 508static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
@@ -790,10 +788,16 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
790 struct in6_addr prefix; 788 struct in6_addr prefix;
791 struct rt6_info *rt; 789 struct rt6_info *rt;
792 struct net *net = dev_net(ifp->idev->dev); 790 struct net *net = dev_net(ifp->idev->dev);
791 struct flowi6 fl6 = {};
792
793 ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); 793 ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
794 rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); 794 fl6.flowi6_oif = ifp->idev->dev->ifindex;
795 fl6.daddr = prefix;
796 rt = (struct rt6_info *)ip6_route_lookup(net, &fl6,
797 RT6_LOOKUP_F_IFACE);
795 798
796 if (rt && addrconf_is_prefix_route(rt)) { 799 if (rt != net->ipv6.ip6_null_entry &&
800 addrconf_is_prefix_route(rt)) {
797 if (onlink == 0) { 801 if (onlink == 0) {
798 ip6_del_rt(rt); 802 ip6_del_rt(rt);
799 rt = NULL; 803 rt = NULL;
@@ -854,16 +858,7 @@ retry:
854 } 858 }
855 in6_ifa_hold(ifp); 859 in6_ifa_hold(ifp);
856 memcpy(addr.s6_addr, ifp->addr.s6_addr, 8); 860 memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
857 if (__ipv6_try_regen_rndid(idev, tmpaddr) < 0) { 861 __ipv6_try_regen_rndid(idev, tmpaddr);
858 spin_unlock_bh(&ifp->lock);
859 write_unlock(&idev->lock);
860 pr_warn("%s: regeneration of randomized interface id failed\n",
861 __func__);
862 in6_ifa_put(ifp);
863 in6_dev_put(idev);
864 ret = -1;
865 goto out;
866 }
867 memcpy(&addr.s6_addr[8], idev->rndid, 8); 862 memcpy(&addr.s6_addr[8], idev->rndid, 8);
868 age = (now - ifp->tstamp) / HZ; 863 age = (now - ifp->tstamp) / HZ;
869 tmp_valid_lft = min_t(__u32, 864 tmp_valid_lft = min_t(__u32,
@@ -1081,8 +1076,10 @@ static int ipv6_get_saddr_eval(struct net *net,
1081 break; 1076 break;
1082 case IPV6_SADDR_RULE_PREFIX: 1077 case IPV6_SADDR_RULE_PREFIX:
1083 /* Rule 8: Use longest matching prefix */ 1078 /* Rule 8: Use longest matching prefix */
1084 score->matchlen = ret = ipv6_addr_diff(&score->ifa->addr, 1079 ret = ipv6_addr_diff(&score->ifa->addr, dst->addr);
1085 dst->addr); 1080 if (ret > score->ifa->prefix_len)
1081 ret = score->ifa->prefix_len;
1082 score->matchlen = ret;
1086 break; 1083 break;
1087 default: 1084 default:
1088 ret = 0; 1085 ret = 0;
@@ -1095,7 +1092,7 @@ out:
1095 return ret; 1092 return ret;
1096} 1093}
1097 1094
1098int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, 1095int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
1099 const struct in6_addr *daddr, unsigned int prefs, 1096 const struct in6_addr *daddr, unsigned int prefs,
1100 struct in6_addr *saddr) 1097 struct in6_addr *saddr)
1101{ 1098{
@@ -1602,7 +1599,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
1602 1599
1603#ifdef CONFIG_IPV6_PRIVACY 1600#ifdef CONFIG_IPV6_PRIVACY
1604/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */ 1601/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
1605static int __ipv6_regen_rndid(struct inet6_dev *idev) 1602static void __ipv6_regen_rndid(struct inet6_dev *idev)
1606{ 1603{
1607regen: 1604regen:
1608 get_random_bytes(idev->rndid, sizeof(idev->rndid)); 1605 get_random_bytes(idev->rndid, sizeof(idev->rndid));
@@ -1629,8 +1626,6 @@ regen:
1629 if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00) 1626 if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00)
1630 goto regen; 1627 goto regen;
1631 } 1628 }
1632
1633 return 0;
1634} 1629}
1635 1630
1636static void ipv6_regen_rndid(unsigned long data) 1631static void ipv6_regen_rndid(unsigned long data)
@@ -1644,8 +1639,7 @@ static void ipv6_regen_rndid(unsigned long data)
1644 if (idev->dead) 1639 if (idev->dead)
1645 goto out; 1640 goto out;
1646 1641
1647 if (__ipv6_regen_rndid(idev) < 0) 1642 __ipv6_regen_rndid(idev);
1648 goto out;
1649 1643
1650 expires = jiffies + 1644 expires = jiffies +
1651 idev->cnf.temp_prefered_lft * HZ - 1645 idev->cnf.temp_prefered_lft * HZ -
@@ -1666,13 +1660,10 @@ out:
1666 in6_dev_put(idev); 1660 in6_dev_put(idev);
1667} 1661}
1668 1662
1669static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) 1663static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
1670{ 1664{
1671 int ret = 0;
1672
1673 if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0) 1665 if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
1674 ret = __ipv6_regen_rndid(idev); 1666 __ipv6_regen_rndid(idev);
1675 return ret;
1676} 1667}
1677#endif 1668#endif
1678 1669
@@ -1723,7 +1714,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
1723 if (table == NULL) 1714 if (table == NULL)
1724 return NULL; 1715 return NULL;
1725 1716
1726 write_lock_bh(&table->tb6_lock); 1717 read_lock_bh(&table->tb6_lock);
1727 fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0); 1718 fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0);
1728 if (!fn) 1719 if (!fn)
1729 goto out; 1720 goto out;
@@ -1738,7 +1729,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
1738 break; 1729 break;
1739 } 1730 }
1740out: 1731out:
1741 write_unlock_bh(&table->tb6_lock); 1732 read_unlock_bh(&table->tb6_lock);
1742 return rt; 1733 return rt;
1743} 1734}
1744 1735
@@ -1778,14 +1769,6 @@ static void sit_route_add(struct net_device *dev)
1778} 1769}
1779#endif 1770#endif
1780 1771
1781static void addrconf_add_lroute(struct net_device *dev)
1782{
1783 struct in6_addr addr;
1784
1785 ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
1786 addrconf_prefix_route(&addr, 64, dev, 0, 0);
1787}
1788
1789static struct inet6_dev *addrconf_add_dev(struct net_device *dev) 1772static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
1790{ 1773{
1791 struct inet6_dev *idev; 1774 struct inet6_dev *idev;
@@ -1803,8 +1786,6 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
1803 if (!(dev->flags & IFF_LOOPBACK)) 1786 if (!(dev->flags & IFF_LOOPBACK))
1804 addrconf_add_mroute(dev); 1787 addrconf_add_mroute(dev);
1805 1788
1806 /* Add link local route */
1807 addrconf_add_lroute(dev);
1808 return idev; 1789 return idev;
1809} 1790}
1810 1791
@@ -2483,10 +2464,9 @@ static void addrconf_sit_config(struct net_device *dev)
2483 2464
2484 sit_add_v4_addrs(idev); 2465 sit_add_v4_addrs(idev);
2485 2466
2486 if (dev->flags&IFF_POINTOPOINT) { 2467 if (dev->flags&IFF_POINTOPOINT)
2487 addrconf_add_mroute(dev); 2468 addrconf_add_mroute(dev);
2488 addrconf_add_lroute(dev); 2469 else
2489 } else
2490 sit_route_add(dev); 2470 sit_route_add(dev);
2491} 2471}
2492#endif 2472#endif
@@ -3551,12 +3531,12 @@ static inline int inet6_ifaddr_msgsize(void)
3551} 3531}
3552 3532
3553static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, 3533static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
3554 u32 pid, u32 seq, int event, unsigned int flags) 3534 u32 portid, u32 seq, int event, unsigned int flags)
3555{ 3535{
3556 struct nlmsghdr *nlh; 3536 struct nlmsghdr *nlh;
3557 u32 preferred, valid; 3537 u32 preferred, valid;
3558 3538
3559 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); 3539 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
3560 if (nlh == NULL) 3540 if (nlh == NULL)
3561 return -EMSGSIZE; 3541 return -EMSGSIZE;
3562 3542
@@ -3594,7 +3574,7 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
3594} 3574}
3595 3575
3596static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, 3576static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3597 u32 pid, u32 seq, int event, u16 flags) 3577 u32 portid, u32 seq, int event, u16 flags)
3598{ 3578{
3599 struct nlmsghdr *nlh; 3579 struct nlmsghdr *nlh;
3600 u8 scope = RT_SCOPE_UNIVERSE; 3580 u8 scope = RT_SCOPE_UNIVERSE;
@@ -3603,7 +3583,7 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3603 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE) 3583 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
3604 scope = RT_SCOPE_SITE; 3584 scope = RT_SCOPE_SITE;
3605 3585
3606 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); 3586 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
3607 if (nlh == NULL) 3587 if (nlh == NULL)
3608 return -EMSGSIZE; 3588 return -EMSGSIZE;
3609 3589
@@ -3619,7 +3599,7 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3619} 3599}
3620 3600
3621static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, 3601static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
3622 u32 pid, u32 seq, int event, unsigned int flags) 3602 u32 portid, u32 seq, int event, unsigned int flags)
3623{ 3603{
3624 struct nlmsghdr *nlh; 3604 struct nlmsghdr *nlh;
3625 u8 scope = RT_SCOPE_UNIVERSE; 3605 u8 scope = RT_SCOPE_UNIVERSE;
@@ -3628,7 +3608,7 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
3628 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE) 3608 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
3629 scope = RT_SCOPE_SITE; 3609 scope = RT_SCOPE_SITE;
3630 3610
3631 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); 3611 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
3632 if (nlh == NULL) 3612 if (nlh == NULL)
3633 return -EMSGSIZE; 3613 return -EMSGSIZE;
3634 3614
@@ -3669,7 +3649,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3669 if (++ip_idx < s_ip_idx) 3649 if (++ip_idx < s_ip_idx)
3670 continue; 3650 continue;
3671 err = inet6_fill_ifaddr(skb, ifa, 3651 err = inet6_fill_ifaddr(skb, ifa,
3672 NETLINK_CB(cb->skb).pid, 3652 NETLINK_CB(cb->skb).portid,
3673 cb->nlh->nlmsg_seq, 3653 cb->nlh->nlmsg_seq,
3674 RTM_NEWADDR, 3654 RTM_NEWADDR,
3675 NLM_F_MULTI); 3655 NLM_F_MULTI);
@@ -3685,7 +3665,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3685 if (ip_idx < s_ip_idx) 3665 if (ip_idx < s_ip_idx)
3686 continue; 3666 continue;
3687 err = inet6_fill_ifmcaddr(skb, ifmca, 3667 err = inet6_fill_ifmcaddr(skb, ifmca,
3688 NETLINK_CB(cb->skb).pid, 3668 NETLINK_CB(cb->skb).portid,
3689 cb->nlh->nlmsg_seq, 3669 cb->nlh->nlmsg_seq,
3690 RTM_GETMULTICAST, 3670 RTM_GETMULTICAST,
3691 NLM_F_MULTI); 3671 NLM_F_MULTI);
@@ -3700,7 +3680,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3700 if (ip_idx < s_ip_idx) 3680 if (ip_idx < s_ip_idx)
3701 continue; 3681 continue;
3702 err = inet6_fill_ifacaddr(skb, ifaca, 3682 err = inet6_fill_ifacaddr(skb, ifaca,
3703 NETLINK_CB(cb->skb).pid, 3683 NETLINK_CB(cb->skb).portid,
3704 cb->nlh->nlmsg_seq, 3684 cb->nlh->nlmsg_seq,
3705 RTM_GETANYCAST, 3685 RTM_GETANYCAST,
3706 NLM_F_MULTI); 3686 NLM_F_MULTI);
@@ -3822,7 +3802,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
3822 goto errout_ifa; 3802 goto errout_ifa;
3823 } 3803 }
3824 3804
3825 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, 3805 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).portid,
3826 nlh->nlmsg_seq, RTM_NEWADDR, 0); 3806 nlh->nlmsg_seq, RTM_NEWADDR, 0);
3827 if (err < 0) { 3807 if (err < 0) {
3828 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */ 3808 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
@@ -3830,7 +3810,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
3830 kfree_skb(skb); 3810 kfree_skb(skb);
3831 goto errout_ifa; 3811 goto errout_ifa;
3832 } 3812 }
3833 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); 3813 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
3834errout_ifa: 3814errout_ifa:
3835 in6_ifa_put(ifa); 3815 in6_ifa_put(ifa);
3836errout: 3816errout:
@@ -4032,14 +4012,14 @@ static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
4032} 4012}
4033 4013
4034static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 4014static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
4035 u32 pid, u32 seq, int event, unsigned int flags) 4015 u32 portid, u32 seq, int event, unsigned int flags)
4036{ 4016{
4037 struct net_device *dev = idev->dev; 4017 struct net_device *dev = idev->dev;
4038 struct ifinfomsg *hdr; 4018 struct ifinfomsg *hdr;
4039 struct nlmsghdr *nlh; 4019 struct nlmsghdr *nlh;
4040 void *protoinfo; 4020 void *protoinfo;
4041 4021
4042 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); 4022 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*hdr), flags);
4043 if (nlh == NULL) 4023 if (nlh == NULL)
4044 return -EMSGSIZE; 4024 return -EMSGSIZE;
4045 4025
@@ -4097,7 +4077,7 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
4097 if (!idev) 4077 if (!idev)
4098 goto cont; 4078 goto cont;
4099 if (inet6_fill_ifinfo(skb, idev, 4079 if (inet6_fill_ifinfo(skb, idev,
4100 NETLINK_CB(cb->skb).pid, 4080 NETLINK_CB(cb->skb).portid,
4101 cb->nlh->nlmsg_seq, 4081 cb->nlh->nlmsg_seq,
4102 RTM_NEWLINK, NLM_F_MULTI) <= 0) 4082 RTM_NEWLINK, NLM_F_MULTI) <= 0)
4103 goto out; 4083 goto out;
@@ -4145,14 +4125,14 @@ static inline size_t inet6_prefix_nlmsg_size(void)
4145} 4125}
4146 4126
4147static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, 4127static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
4148 struct prefix_info *pinfo, u32 pid, u32 seq, 4128 struct prefix_info *pinfo, u32 portid, u32 seq,
4149 int event, unsigned int flags) 4129 int event, unsigned int flags)
4150{ 4130{
4151 struct prefixmsg *pmsg; 4131 struct prefixmsg *pmsg;
4152 struct nlmsghdr *nlh; 4132 struct nlmsghdr *nlh;
4153 struct prefix_cacheinfo ci; 4133 struct prefix_cacheinfo ci;
4154 4134
4155 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags); 4135 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*pmsg), flags);
4156 if (nlh == NULL) 4136 if (nlh == NULL)
4157 return -EMSGSIZE; 4137 return -EMSGSIZE;
4158 4138