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.c83
1 files changed, 38 insertions, 45 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6bc85f7c31e3..480e68422efb 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
@@ -788,10 +788,16 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
788 struct in6_addr prefix; 788 struct in6_addr prefix;
789 struct rt6_info *rt; 789 struct rt6_info *rt;
790 struct net *net = dev_net(ifp->idev->dev); 790 struct net *net = dev_net(ifp->idev->dev);
791 struct flowi6 fl6 = {};
792
791 ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); 793 ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
792 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);
793 798
794 if (rt && addrconf_is_prefix_route(rt)) { 799 if (rt != net->ipv6.ip6_null_entry &&
800 addrconf_is_prefix_route(rt)) {
795 if (onlink == 0) { 801 if (onlink == 0) {
796 ip6_del_rt(rt); 802 ip6_del_rt(rt);
797 rt = NULL; 803 rt = NULL;
@@ -852,16 +858,7 @@ retry:
852 } 858 }
853 in6_ifa_hold(ifp); 859 in6_ifa_hold(ifp);
854 memcpy(addr.s6_addr, ifp->addr.s6_addr, 8); 860 memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
855 if (__ipv6_try_regen_rndid(idev, tmpaddr) < 0) { 861 __ipv6_try_regen_rndid(idev, tmpaddr);
856 spin_unlock_bh(&ifp->lock);
857 write_unlock(&idev->lock);
858 pr_warn("%s: regeneration of randomized interface id failed\n",
859 __func__);
860 in6_ifa_put(ifp);
861 in6_dev_put(idev);
862 ret = -1;
863 goto out;
864 }
865 memcpy(&addr.s6_addr[8], idev->rndid, 8); 862 memcpy(&addr.s6_addr[8], idev->rndid, 8);
866 age = (now - ifp->tstamp) / HZ; 863 age = (now - ifp->tstamp) / HZ;
867 tmp_valid_lft = min_t(__u32, 864 tmp_valid_lft = min_t(__u32,
@@ -1079,8 +1076,10 @@ static int ipv6_get_saddr_eval(struct net *net,
1079 break; 1076 break;
1080 case IPV6_SADDR_RULE_PREFIX: 1077 case IPV6_SADDR_RULE_PREFIX:
1081 /* Rule 8: Use longest matching prefix */ 1078 /* Rule 8: Use longest matching prefix */
1082 score->matchlen = ret = ipv6_addr_diff(&score->ifa->addr, 1079 ret = ipv6_addr_diff(&score->ifa->addr, dst->addr);
1083 dst->addr); 1080 if (ret > score->ifa->prefix_len)
1081 ret = score->ifa->prefix_len;
1082 score->matchlen = ret;
1084 break; 1083 break;
1085 default: 1084 default:
1086 ret = 0; 1085 ret = 0;
@@ -1093,7 +1092,7 @@ out:
1093 return ret; 1092 return ret;
1094} 1093}
1095 1094
1096int 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,
1097 const struct in6_addr *daddr, unsigned int prefs, 1096 const struct in6_addr *daddr, unsigned int prefs,
1098 struct in6_addr *saddr) 1097 struct in6_addr *saddr)
1099{ 1098{
@@ -1600,7 +1599,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
1600 1599
1601#ifdef CONFIG_IPV6_PRIVACY 1600#ifdef CONFIG_IPV6_PRIVACY
1602/* (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) */
1603static int __ipv6_regen_rndid(struct inet6_dev *idev) 1602static void __ipv6_regen_rndid(struct inet6_dev *idev)
1604{ 1603{
1605regen: 1604regen:
1606 get_random_bytes(idev->rndid, sizeof(idev->rndid)); 1605 get_random_bytes(idev->rndid, sizeof(idev->rndid));
@@ -1627,8 +1626,6 @@ regen:
1627 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)
1628 goto regen; 1627 goto regen;
1629 } 1628 }
1630
1631 return 0;
1632} 1629}
1633 1630
1634static void ipv6_regen_rndid(unsigned long data) 1631static void ipv6_regen_rndid(unsigned long data)
@@ -1642,8 +1639,7 @@ static void ipv6_regen_rndid(unsigned long data)
1642 if (idev->dead) 1639 if (idev->dead)
1643 goto out; 1640 goto out;
1644 1641
1645 if (__ipv6_regen_rndid(idev) < 0) 1642 __ipv6_regen_rndid(idev);
1646 goto out;
1647 1643
1648 expires = jiffies + 1644 expires = jiffies +
1649 idev->cnf.temp_prefered_lft * HZ - 1645 idev->cnf.temp_prefered_lft * HZ -
@@ -1664,13 +1660,10 @@ out:
1664 in6_dev_put(idev); 1660 in6_dev_put(idev);
1665} 1661}
1666 1662
1667static 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)
1668{ 1664{
1669 int ret = 0;
1670
1671 if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0) 1665 if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
1672 ret = __ipv6_regen_rndid(idev); 1666 __ipv6_regen_rndid(idev);
1673 return ret;
1674} 1667}
1675#endif 1668#endif
1676 1669
@@ -1721,7 +1714,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
1721 if (table == NULL) 1714 if (table == NULL)
1722 return NULL; 1715 return NULL;
1723 1716
1724 write_lock_bh(&table->tb6_lock); 1717 read_lock_bh(&table->tb6_lock);
1725 fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0); 1718 fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0);
1726 if (!fn) 1719 if (!fn)
1727 goto out; 1720 goto out;
@@ -1736,7 +1729,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
1736 break; 1729 break;
1737 } 1730 }
1738out: 1731out:
1739 write_unlock_bh(&table->tb6_lock); 1732 read_unlock_bh(&table->tb6_lock);
1740 return rt; 1733 return rt;
1741} 1734}
1742 1735
@@ -3549,12 +3542,12 @@ static inline int inet6_ifaddr_msgsize(void)
3549} 3542}
3550 3543
3551static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, 3544static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
3552 u32 pid, u32 seq, int event, unsigned int flags) 3545 u32 portid, u32 seq, int event, unsigned int flags)
3553{ 3546{
3554 struct nlmsghdr *nlh; 3547 struct nlmsghdr *nlh;
3555 u32 preferred, valid; 3548 u32 preferred, valid;
3556 3549
3557 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); 3550 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
3558 if (nlh == NULL) 3551 if (nlh == NULL)
3559 return -EMSGSIZE; 3552 return -EMSGSIZE;
3560 3553
@@ -3592,7 +3585,7 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
3592} 3585}
3593 3586
3594static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, 3587static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3595 u32 pid, u32 seq, int event, u16 flags) 3588 u32 portid, u32 seq, int event, u16 flags)
3596{ 3589{
3597 struct nlmsghdr *nlh; 3590 struct nlmsghdr *nlh;
3598 u8 scope = RT_SCOPE_UNIVERSE; 3591 u8 scope = RT_SCOPE_UNIVERSE;
@@ -3601,7 +3594,7 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3601 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE) 3594 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
3602 scope = RT_SCOPE_SITE; 3595 scope = RT_SCOPE_SITE;
3603 3596
3604 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); 3597 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
3605 if (nlh == NULL) 3598 if (nlh == NULL)
3606 return -EMSGSIZE; 3599 return -EMSGSIZE;
3607 3600
@@ -3617,7 +3610,7 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3617} 3610}
3618 3611
3619static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, 3612static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
3620 u32 pid, u32 seq, int event, unsigned int flags) 3613 u32 portid, u32 seq, int event, unsigned int flags)
3621{ 3614{
3622 struct nlmsghdr *nlh; 3615 struct nlmsghdr *nlh;
3623 u8 scope = RT_SCOPE_UNIVERSE; 3616 u8 scope = RT_SCOPE_UNIVERSE;
@@ -3626,7 +3619,7 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
3626 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE) 3619 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
3627 scope = RT_SCOPE_SITE; 3620 scope = RT_SCOPE_SITE;
3628 3621
3629 nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); 3622 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags);
3630 if (nlh == NULL) 3623 if (nlh == NULL)
3631 return -EMSGSIZE; 3624 return -EMSGSIZE;
3632 3625
@@ -3667,7 +3660,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3667 if (++ip_idx < s_ip_idx) 3660 if (++ip_idx < s_ip_idx)
3668 continue; 3661 continue;
3669 err = inet6_fill_ifaddr(skb, ifa, 3662 err = inet6_fill_ifaddr(skb, ifa,
3670 NETLINK_CB(cb->skb).pid, 3663 NETLINK_CB(cb->skb).portid,
3671 cb->nlh->nlmsg_seq, 3664 cb->nlh->nlmsg_seq,
3672 RTM_NEWADDR, 3665 RTM_NEWADDR,
3673 NLM_F_MULTI); 3666 NLM_F_MULTI);
@@ -3683,7 +3676,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3683 if (ip_idx < s_ip_idx) 3676 if (ip_idx < s_ip_idx)
3684 continue; 3677 continue;
3685 err = inet6_fill_ifmcaddr(skb, ifmca, 3678 err = inet6_fill_ifmcaddr(skb, ifmca,
3686 NETLINK_CB(cb->skb).pid, 3679 NETLINK_CB(cb->skb).portid,
3687 cb->nlh->nlmsg_seq, 3680 cb->nlh->nlmsg_seq,
3688 RTM_GETMULTICAST, 3681 RTM_GETMULTICAST,
3689 NLM_F_MULTI); 3682 NLM_F_MULTI);
@@ -3698,7 +3691,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3698 if (ip_idx < s_ip_idx) 3691 if (ip_idx < s_ip_idx)
3699 continue; 3692 continue;
3700 err = inet6_fill_ifacaddr(skb, ifaca, 3693 err = inet6_fill_ifacaddr(skb, ifaca,
3701 NETLINK_CB(cb->skb).pid, 3694 NETLINK_CB(cb->skb).portid,
3702 cb->nlh->nlmsg_seq, 3695 cb->nlh->nlmsg_seq,
3703 RTM_GETANYCAST, 3696 RTM_GETANYCAST,
3704 NLM_F_MULTI); 3697 NLM_F_MULTI);
@@ -3820,7 +3813,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
3820 goto errout_ifa; 3813 goto errout_ifa;
3821 } 3814 }
3822 3815
3823 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, 3816 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).portid,
3824 nlh->nlmsg_seq, RTM_NEWADDR, 0); 3817 nlh->nlmsg_seq, RTM_NEWADDR, 0);
3825 if (err < 0) { 3818 if (err < 0) {
3826 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */ 3819 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
@@ -3828,7 +3821,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
3828 kfree_skb(skb); 3821 kfree_skb(skb);
3829 goto errout_ifa; 3822 goto errout_ifa;
3830 } 3823 }
3831 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); 3824 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
3832errout_ifa: 3825errout_ifa:
3833 in6_ifa_put(ifa); 3826 in6_ifa_put(ifa);
3834errout: 3827errout:
@@ -4030,14 +4023,14 @@ static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
4030} 4023}
4031 4024
4032static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 4025static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
4033 u32 pid, u32 seq, int event, unsigned int flags) 4026 u32 portid, u32 seq, int event, unsigned int flags)
4034{ 4027{
4035 struct net_device *dev = idev->dev; 4028 struct net_device *dev = idev->dev;
4036 struct ifinfomsg *hdr; 4029 struct ifinfomsg *hdr;
4037 struct nlmsghdr *nlh; 4030 struct nlmsghdr *nlh;
4038 void *protoinfo; 4031 void *protoinfo;
4039 4032
4040 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); 4033 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*hdr), flags);
4041 if (nlh == NULL) 4034 if (nlh == NULL)
4042 return -EMSGSIZE; 4035 return -EMSGSIZE;
4043 4036
@@ -4095,7 +4088,7 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
4095 if (!idev) 4088 if (!idev)
4096 goto cont; 4089 goto cont;
4097 if (inet6_fill_ifinfo(skb, idev, 4090 if (inet6_fill_ifinfo(skb, idev,
4098 NETLINK_CB(cb->skb).pid, 4091 NETLINK_CB(cb->skb).portid,
4099 cb->nlh->nlmsg_seq, 4092 cb->nlh->nlmsg_seq,
4100 RTM_NEWLINK, NLM_F_MULTI) <= 0) 4093 RTM_NEWLINK, NLM_F_MULTI) <= 0)
4101 goto out; 4094 goto out;
@@ -4143,14 +4136,14 @@ static inline size_t inet6_prefix_nlmsg_size(void)
4143} 4136}
4144 4137
4145static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, 4138static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
4146 struct prefix_info *pinfo, u32 pid, u32 seq, 4139 struct prefix_info *pinfo, u32 portid, u32 seq,
4147 int event, unsigned int flags) 4140 int event, unsigned int flags)
4148{ 4141{
4149 struct prefixmsg *pmsg; 4142 struct prefixmsg *pmsg;
4150 struct nlmsghdr *nlh; 4143 struct nlmsghdr *nlh;
4151 struct prefix_cacheinfo ci; 4144 struct prefix_cacheinfo ci;
4152 4145
4153 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags); 4146 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*pmsg), flags);
4154 if (nlh == NULL) 4147 if (nlh == NULL)
4155 return -EMSGSIZE; 4148 return -EMSGSIZE;
4156 4149