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.c142
1 files changed, 88 insertions, 54 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e591e09e5e4e..147588f4c7c0 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -731,8 +731,13 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
731 onlink = -1; 731 onlink = -1;
732 732
733 spin_lock(&ifa->lock); 733 spin_lock(&ifa->lock);
734 lifetime = min_t(unsigned long, 734
735 ifa->valid_lft, 0x7fffffffUL/HZ); 735 lifetime = addrconf_timeout_fixup(ifa->valid_lft, HZ);
736 /*
737 * Note: Because this address is
738 * not permanent, lifetime <
739 * LONG_MAX / HZ here.
740 */
736 if (time_before(expires, 741 if (time_before(expires,
737 ifa->tstamp + lifetime * HZ)) 742 ifa->tstamp + lifetime * HZ))
738 expires = ifa->tstamp + lifetime * HZ; 743 expires = ifa->tstamp + lifetime * HZ;
@@ -1722,7 +1727,6 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
1722 __u32 valid_lft; 1727 __u32 valid_lft;
1723 __u32 prefered_lft; 1728 __u32 prefered_lft;
1724 int addr_type; 1729 int addr_type;
1725 unsigned long rt_expires;
1726 struct inet6_dev *in6_dev; 1730 struct inet6_dev *in6_dev;
1727 1731
1728 pinfo = (struct prefix_info *) opt; 1732 pinfo = (struct prefix_info *) opt;
@@ -1764,41 +1768,49 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
1764 * 2) Configure prefixes with the auto flag set 1768 * 2) Configure prefixes with the auto flag set
1765 */ 1769 */
1766 1770
1767 /* Avoid arithmetic overflow. Really, we could
1768 save rt_expires in seconds, likely valid_lft,
1769 but it would require division in fib gc, that it
1770 not good.
1771 */
1772 if (valid_lft >= 0x7FFFFFFF/HZ)
1773 rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ);
1774 else
1775 rt_expires = valid_lft * HZ;
1776
1777 /*
1778 * We convert this (in jiffies) to clock_t later.
1779 * Avoid arithmetic overflow there as well.
1780 * Overflow can happen only if HZ < USER_HZ.
1781 */
1782 if (HZ < USER_HZ && rt_expires > 0x7FFFFFFF / USER_HZ)
1783 rt_expires = 0x7FFFFFFF / USER_HZ;
1784
1785 if (pinfo->onlink) { 1771 if (pinfo->onlink) {
1786 struct rt6_info *rt; 1772 struct rt6_info *rt;
1773 unsigned long rt_expires;
1774
1775 /* Avoid arithmetic overflow. Really, we could
1776 * save rt_expires in seconds, likely valid_lft,
1777 * but it would require division in fib gc, that it
1778 * not good.
1779 */
1780 if (HZ > USER_HZ)
1781 rt_expires = addrconf_timeout_fixup(valid_lft, HZ);
1782 else
1783 rt_expires = addrconf_timeout_fixup(valid_lft, USER_HZ);
1784
1785 if (addrconf_finite_timeout(rt_expires))
1786 rt_expires *= HZ;
1787
1787 rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, 1788 rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
1788 dev->ifindex, 1); 1789 dev->ifindex, 1);
1789 1790
1790 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { 1791 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
1791 if (rt->rt6i_flags&RTF_EXPIRES) { 1792 /* Autoconf prefix route */
1792 if (valid_lft == 0) { 1793 if (valid_lft == 0) {
1793 ip6_del_rt(rt); 1794 ip6_del_rt(rt);
1794 rt = NULL; 1795 rt = NULL;
1795 } else { 1796 } else if (addrconf_finite_timeout(rt_expires)) {
1796 rt->rt6i_expires = jiffies + rt_expires; 1797 /* not infinity */
1797 } 1798 rt->rt6i_expires = jiffies + rt_expires;
1799 rt->rt6i_flags |= RTF_EXPIRES;
1800 } else {
1801 rt->rt6i_flags &= ~RTF_EXPIRES;
1802 rt->rt6i_expires = 0;
1798 } 1803 }
1799 } else if (valid_lft) { 1804 } else if (valid_lft) {
1805 clock_t expires = 0;
1806 int flags = RTF_ADDRCONF | RTF_PREFIX_RT;
1807 if (addrconf_finite_timeout(rt_expires)) {
1808 /* not infinity */
1809 flags |= RTF_EXPIRES;
1810 expires = jiffies_to_clock_t(rt_expires);
1811 }
1800 addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, 1812 addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
1801 dev, jiffies_to_clock_t(rt_expires), RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT); 1813 dev, expires, flags);
1802 } 1814 }
1803 if (rt) 1815 if (rt)
1804 dst_release(&rt->u.dst); 1816 dst_release(&rt->u.dst);
@@ -2014,17 +2026,22 @@ err_exit:
2014 * Manual configuration of address on an interface 2026 * Manual configuration of address on an interface
2015 */ 2027 */
2016static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, 2028static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
2017 int plen, __u8 ifa_flags, __u32 prefered_lft, 2029 unsigned int plen, __u8 ifa_flags, __u32 prefered_lft,
2018 __u32 valid_lft) 2030 __u32 valid_lft)
2019{ 2031{
2020 struct inet6_ifaddr *ifp; 2032 struct inet6_ifaddr *ifp;
2021 struct inet6_dev *idev; 2033 struct inet6_dev *idev;
2022 struct net_device *dev; 2034 struct net_device *dev;
2023 int scope; 2035 int scope;
2024 u32 flags = RTF_EXPIRES; 2036 u32 flags;
2037 clock_t expires;
2038 unsigned long timeout;
2025 2039
2026 ASSERT_RTNL(); 2040 ASSERT_RTNL();
2027 2041
2042 if (plen > 128)
2043 return -EINVAL;
2044
2028 /* check the lifetime */ 2045 /* check the lifetime */
2029 if (!valid_lft || prefered_lft > valid_lft) 2046 if (!valid_lft || prefered_lft > valid_lft)
2030 return -EINVAL; 2047 return -EINVAL;
@@ -2038,17 +2055,23 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
2038 2055
2039 scope = ipv6_addr_scope(pfx); 2056 scope = ipv6_addr_scope(pfx);
2040 2057
2041 if (valid_lft == INFINITY_LIFE_TIME) { 2058 timeout = addrconf_timeout_fixup(valid_lft, HZ);
2042 ifa_flags |= IFA_F_PERMANENT; 2059 if (addrconf_finite_timeout(timeout)) {
2060 expires = jiffies_to_clock_t(timeout * HZ);
2061 valid_lft = timeout;
2062 flags = RTF_EXPIRES;
2063 } else {
2064 expires = 0;
2043 flags = 0; 2065 flags = 0;
2044 } else if (valid_lft >= 0x7FFFFFFF/HZ) 2066 ifa_flags |= IFA_F_PERMANENT;
2045 valid_lft = 0x7FFFFFFF/HZ; 2067 }
2046 2068
2047 if (prefered_lft == 0) 2069 timeout = addrconf_timeout_fixup(prefered_lft, HZ);
2048 ifa_flags |= IFA_F_DEPRECATED; 2070 if (addrconf_finite_timeout(timeout)) {
2049 else if ((prefered_lft >= 0x7FFFFFFF/HZ) && 2071 if (timeout == 0)
2050 (prefered_lft != INFINITY_LIFE_TIME)) 2072 ifa_flags |= IFA_F_DEPRECATED;
2051 prefered_lft = 0x7FFFFFFF/HZ; 2073 prefered_lft = timeout;
2074 }
2052 2075
2053 ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); 2076 ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags);
2054 2077
@@ -2060,7 +2083,7 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
2060 spin_unlock_bh(&ifp->lock); 2083 spin_unlock_bh(&ifp->lock);
2061 2084
2062 addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 2085 addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
2063 jiffies_to_clock_t(valid_lft * HZ), flags); 2086 expires, flags);
2064 /* 2087 /*
2065 * Note that section 3.1 of RFC 4429 indicates 2088 * Note that section 3.1 of RFC 4429 indicates
2066 * that the Optimistic flag should not be set for 2089 * that the Optimistic flag should not be set for
@@ -2076,12 +2099,15 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
2076} 2099}
2077 2100
2078static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, 2101static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx,
2079 int plen) 2102 unsigned int plen)
2080{ 2103{
2081 struct inet6_ifaddr *ifp; 2104 struct inet6_ifaddr *ifp;
2082 struct inet6_dev *idev; 2105 struct inet6_dev *idev;
2083 struct net_device *dev; 2106 struct net_device *dev;
2084 2107
2108 if (plen > 128)
2109 return -EINVAL;
2110
2085 dev = __dev_get_by_index(net, ifindex); 2111 dev = __dev_get_by_index(net, ifindex);
2086 if (!dev) 2112 if (!dev)
2087 return -ENODEV; 2113 return -ENODEV;
@@ -3148,22 +3174,30 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
3148static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, 3174static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
3149 u32 prefered_lft, u32 valid_lft) 3175 u32 prefered_lft, u32 valid_lft)
3150{ 3176{
3151 u32 flags = RTF_EXPIRES; 3177 u32 flags;
3178 clock_t expires;
3179 unsigned long timeout;
3152 3180
3153 if (!valid_lft || (prefered_lft > valid_lft)) 3181 if (!valid_lft || (prefered_lft > valid_lft))
3154 return -EINVAL; 3182 return -EINVAL;
3155 3183
3156 if (valid_lft == INFINITY_LIFE_TIME) { 3184 timeout = addrconf_timeout_fixup(valid_lft, HZ);
3157 ifa_flags |= IFA_F_PERMANENT; 3185 if (addrconf_finite_timeout(timeout)) {
3186 expires = jiffies_to_clock_t(timeout * HZ);
3187 valid_lft = timeout;
3188 flags = RTF_EXPIRES;
3189 } else {
3190 expires = 0;
3158 flags = 0; 3191 flags = 0;
3159 } else if (valid_lft >= 0x7FFFFFFF/HZ) 3192 ifa_flags |= IFA_F_PERMANENT;
3160 valid_lft = 0x7FFFFFFF/HZ; 3193 }
3161 3194
3162 if (prefered_lft == 0) 3195 timeout = addrconf_timeout_fixup(prefered_lft, HZ);
3163 ifa_flags |= IFA_F_DEPRECATED; 3196 if (addrconf_finite_timeout(timeout)) {
3164 else if ((prefered_lft >= 0x7FFFFFFF/HZ) && 3197 if (timeout == 0)
3165 (prefered_lft != INFINITY_LIFE_TIME)) 3198 ifa_flags |= IFA_F_DEPRECATED;
3166 prefered_lft = 0x7FFFFFFF/HZ; 3199 prefered_lft = timeout;
3200 }
3167 3201
3168 spin_lock_bh(&ifp->lock); 3202 spin_lock_bh(&ifp->lock);
3169 ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags; 3203 ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;
@@ -3176,7 +3210,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
3176 ipv6_ifa_notify(0, ifp); 3210 ipv6_ifa_notify(0, ifp);
3177 3211
3178 addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev, 3212 addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
3179 jiffies_to_clock_t(valid_lft * HZ), flags); 3213 expires, flags);
3180 addrconf_verify(0); 3214 addrconf_verify(0);
3181 3215
3182 return 0; 3216 return 0;
@@ -4242,7 +4276,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev)
4242 neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6, 4276 neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6,
4243 NET_IPV6_NEIGH, "ipv6", 4277 NET_IPV6_NEIGH, "ipv6",
4244 &ndisc_ifinfo_sysctl_change, 4278 &ndisc_ifinfo_sysctl_change,
4245 NULL); 4279 ndisc_ifinfo_sysctl_strategy);
4246 __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, 4280 __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
4247 idev->dev->ifindex, idev, &idev->cnf); 4281 idev->dev->ifindex, idev, &idev->cnf);
4248} 4282}