diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
| -rw-r--r-- | net/ipv6/addrconf.c | 27 | 
1 files changed, 20 insertions, 7 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3eee17790a82..f927c199a93c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2589,7 +2589,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,  				 __u32 valid_lft, u32 prefered_lft)  {  	struct inet6_ifaddr *ifp = ipv6_get_ifaddr(net, addr, dev, 1); -	int create = 0; +	int create = 0, update_lft = 0;  	if (!ifp && valid_lft) {  		int max_addresses = in6_dev->cnf.max_addresses; @@ -2633,19 +2633,32 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,  		unsigned long now;  		u32 stored_lft; -		/* Update lifetime (RFC4862 5.5.3 e) -		 * We deviate from RFC4862 by honoring all Valid Lifetimes to -		 * improve the reaction of SLAAC to renumbering events -		 * (draft-gont-6man-slaac-renum-06, Section 4.2) -		 */ +		/* update lifetime (RFC2462 5.5.3 e) */  		spin_lock_bh(&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 (!create && stored_lft) { +			const u32 minimum_lft = min_t(u32, +				stored_lft, MIN_VALID_LIFETIME); +			valid_lft = max(valid_lft, minimum_lft); + +			/* RFC4862 Section 5.5.3e: +			 * "Note that the preferred lifetime of the +			 *  corresponding address is always reset to +			 *  the Preferred Lifetime in the received +			 *  Prefix Information option, regardless of +			 *  whether the valid lifetime is also reset or +			 *  ignored." +			 * +			 * So we should always update prefered_lft here. +			 */ +			update_lft = 1; +		} + +		if (update_lft) {  			ifp->valid_lft = valid_lft;  			ifp->prefered_lft = prefered_lft;  			ifp->tstamp = now;  |