diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 83 |
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 |
130 | static int __ipv6_regen_rndid(struct inet6_dev *idev); | 130 | static void __ipv6_regen_rndid(struct inet6_dev *idev); |
131 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); | 131 | static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); |
132 | static void ipv6_regen_rndid(unsigned long data); | 132 | static 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 | ||
1096 | int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | 1095 | int 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) */ |
1603 | static int __ipv6_regen_rndid(struct inet6_dev *idev) | 1602 | static void __ipv6_regen_rndid(struct inet6_dev *idev) |
1604 | { | 1603 | { |
1605 | regen: | 1604 | regen: |
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 | ||
1634 | static void ipv6_regen_rndid(unsigned long data) | 1631 | static 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 | ||
1667 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) | 1663 | static 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 | } |
1738 | out: | 1731 | out: |
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 | ||
3551 | static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | 3544 | static 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 | ||
3594 | static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, | 3587 | static 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 | ||
3619 | static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | 3612 | static 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); |
3832 | errout_ifa: | 3825 | errout_ifa: |
3833 | in6_ifa_put(ifa); | 3826 | in6_ifa_put(ifa); |
3834 | errout: | 3827 | errout: |
@@ -4030,14 +4023,14 @@ static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev) | |||
4030 | } | 4023 | } |
4031 | 4024 | ||
4032 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | 4025 | static 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 | ||
4145 | static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, | 4138 | static 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 | ||