Commit 6dd2de9c authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6] fix algorithm for updating lifetime

This patch, depends on "IPV6: remove unused variable,"
fixes algorithm for updating lifetime according to RFC2462.
 - We should not delete an address even if prefix is 
   advertised with valid lifetime == 0.
 - support the "2 hours" rule.
parent 511db023
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#define MAX_RTR_SOLICITATIONS 3 #define MAX_RTR_SOLICITATIONS 3
#define RTR_SOLICITATION_INTERVAL (4*HZ) #define RTR_SOLICITATION_INTERVAL (4*HZ)
#define MIN_VALID_LIFETIME (2*3600) /* 2 hours */
#define TEMP_VALID_LIFETIME (7*86400) #define TEMP_VALID_LIFETIME (7*86400)
#define TEMP_PREFERRED_LIFETIME (86400) #define TEMP_PREFERRED_LIFETIME (86400)
#define REGEN_MAX_RETRY (5) #define REGEN_MAX_RETRY (5)
......
...@@ -1380,7 +1380,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1380,7 +1380,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
if (pinfo->autoconf && in6_dev->cnf.autoconf) { if (pinfo->autoconf && in6_dev->cnf.autoconf) {
struct inet6_ifaddr * ifp; struct inet6_ifaddr * ifp;
struct in6_addr addr; struct in6_addr addr;
int create = 0; int create = 0, update_lft = 0;
if (pinfo->prefix_len == 64) { if (pinfo->prefix_len == 64) {
memcpy(&addr, &pinfo->prefix, 8); memcpy(&addr, &pinfo->prefix, 8);
...@@ -1414,25 +1414,45 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1414,25 +1414,45 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
return; return;
} }
create = 1; update_lft = create = 1;
addrconf_dad_start(ifp); addrconf_dad_start(ifp);
} }
if (ifp && valid_lft == 0) {
ipv6_del_addr(ifp);
ifp = NULL;
}
if (ifp) { if (ifp) {
int flags; int flags;
unsigned long now;
#ifdef CONFIG_IPV6_PRIVACY #ifdef CONFIG_IPV6_PRIVACY
struct inet6_ifaddr *ift; struct inet6_ifaddr *ift;
#endif #endif
u32 stored_lft;
/* update lifetime (RFC2462 5.5.3 e) */
spin_lock(&ifp->lock); spin_lock(&ifp->lock);
now = jiffies;
if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
else
stored_lft = 0;
if (!update_lft && stored_lft) {
if (valid_lft > MIN_VALID_LIFETIME ||
valid_lft > stored_lft)
update_lft = 1;
else if (stored_lft <= MIN_VALID_LIFETIME) {
/* valid_lft <= stored_lft is always true */
/* XXX: IPsec */
update_lft = 0;
} else {
valid_lft = MIN_VALID_LIFETIME;
if (valid_lft < prefered_lft)
prefered_lft = valid_lft;
update_lft = 1;
}
}
if (update_lft) {
ifp->valid_lft = valid_lft; ifp->valid_lft = valid_lft;
ifp->prefered_lft = prefered_lft; ifp->prefered_lft = prefered_lft;
ifp->tstamp = jiffies; ifp->tstamp = now;
flags = ifp->flags; flags = ifp->flags;
ifp->flags &= ~IFA_F_DEPRECATED; ifp->flags &= ~IFA_F_DEPRECATED;
spin_unlock(&ifp->lock); spin_unlock(&ifp->lock);
...@@ -1440,6 +1460,8 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1440,6 +1460,8 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
if (!(flags&IFA_F_TENTATIVE)) if (!(flags&IFA_F_TENTATIVE))
ipv6_ifa_notify((flags&IFA_F_DEPRECATED) ? ipv6_ifa_notify((flags&IFA_F_DEPRECATED) ?
0 : RTM_NEWADDR, ifp); 0 : RTM_NEWADDR, ifp);
} else
spin_unlock(&ifp->lock);
#ifdef CONFIG_IPV6_PRIVACY #ifdef CONFIG_IPV6_PRIVACY
read_lock_bh(&in6_dev->lock); read_lock_bh(&in6_dev->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment