[radvd-devel-l] DecrementLifetimes option

Mark Smith radvd at 02a76c927861ca7413a122f2a73a0d37.nosense.org
Sun Apr 3 04:57:46 EDT 2011


Hi,

This is an updated version of the DecrementLifetimes option I posted
for comments a few weeks ago. I think it is ready to commit. Here is
the manual page text -

       DecrementLifetimes on|off

              This  option  causes  radvd  to decrement the values of
              the pre‐ ferred and valid lifetimes for the prefix over
              time.  The  life‐ times  are  decremented  by the number
              of seconds since the last RA. If radvd receives a SIGUSR1
              signal, it will reset the values of  the preferred and
              valid lifetimes back to the initial values used by radvd
              when it started. If radvd never receives a SIGUSR1
              signal,  it  will  continue to decrement the lifetimes
              until the preferred lifetime reaches zero. After a final
              RA  with  a  zero value  preferred lifetime, radvd will
              cease to announce the pre‐ fix. If a SIGUSR1 signal then
              causes the lifetimes to be  reset, the prefix will then
              re-appear in the RAs.

              This  option is intended to be used in conjunction with a
              DHCPv6 client that is using the Identity Association for
              Prefix Delega‐ tion  (IA_PD) option to acquire a prefix
              for use by a Requesting Router. In this scenario, the
              prefix(es) from within  the  delegated  prefix that are
              announced by radvd should age in parallel with and at the
              same rate as the delegated prefix, and expire at
              approximately  the  same  time,  if  the delegated
              prefix's life isn't extended by the DHCPv6 server.

              See RFC3633, "IPv6 Prefix Options for Dynamic Host
              Configuration Protocol  (DHCP)  version 6", specifically
              the Requesting Router sections.

The updates were -

o  some routine renaming
o  use time_t for timeval seconds calculations
o  call gettimeofday() per RA, not per prefix
o  manual page text

It should apply cleanly to cvs revision 1.116. Attached and shown below.

Thanks,
Mark.


diff --git a/defaults.h b/defaults.h
index 059cbd5..66c5b55 100644
--- a/defaults.h
+++ b/defaults.h
@@ -57,6 +57,7 @@
 #define DFLT_AdvPreferredLifetime	14400 /* seconds */
 #define DFLT_AdvAutonomousFlag		1
 #define DFLT_DeprecatePrefixFlag	0
+#define DFLT_DecrementLifetimesFlag	0
 
 /* Each route has an associated: */
 #define DFLT_AdvRouteLifetime(iface)	(3 * (iface)->MaxRtrAdvInterval)
diff --git a/gram.y b/gram.y
index 3c648fe..52ce610 100644
--- a/gram.y
+++ b/gram.y
@@ -96,6 +96,7 @@ static struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr
 %token		T_AdvValidLifetime
 %token		T_AdvPreferredLifetime
 %token		T_DeprecatePrefix
+%token		T_DecrementLifetimes
 
 %token		T_AdvRouterAddr
 %token		T_AdvHomeAgentFlag
@@ -605,11 +606,13 @@ prefixparms	: T_AdvOnLink SWITCH ';'
 					struct AdvPrefix *p = prefix;
 					do {
 						p->AdvValidLifetime = $2;
+						p->curr_validlft = $2;
 						p = p->next;
 					} while (p && p->AutoSelected);
 				}
 				else
 					prefix->AdvValidLifetime = $2;
+					prefix->curr_validlft = $2;
 			}
 		}
 		| T_AdvPreferredLifetime number_or_infinity ';'
@@ -619,17 +622,23 @@ prefixparms	: T_AdvOnLink SWITCH ';'
 					struct AdvPrefix *p = prefix;
 					do {
 						p->AdvPreferredLifetime = $2;
+						p->curr_preferredlft = $2;
 						p = p->next;
 					} while (p && p->AutoSelected);
 				}
 				else
 					prefix->AdvPreferredLifetime = $2;
+					prefix->curr_preferredlft = $2;
 			}
 		}
 		| T_DeprecatePrefix SWITCH ';'
 		{
 			prefix->DeprecatePrefixFlag = $2;
 		}
+		| T_DecrementLifetimes SWITCH ';'
+		{
+			prefix->DecrementLifetimesFlag = $2;
+		}
 		| T_Base6Interface name ';'
 		{
 			if (prefix) {
diff --git a/interface.c b/interface.c
index 54265ec..4c37748 100644
--- a/interface.c
+++ b/interface.c
@@ -58,8 +58,12 @@ prefix_init_defaults(struct AdvPrefix *prefix)
 	prefix->AdvValidLifetime = DFLT_AdvValidLifetime;
 	prefix->AdvPreferredLifetime = DFLT_AdvPreferredLifetime;
 	prefix->DeprecatePrefixFlag = DFLT_DeprecatePrefixFlag;
+	prefix->DecrementLifetimesFlag = DFLT_DecrementLifetimesFlag;
 	prefix->if6to4[0] = 0;
 	prefix->enabled = 1;
+
+	prefix->curr_validlft = prefix->AdvValidLifetime;
+	prefix->curr_preferredlft = prefix->AdvPreferredLifetime;
 }
 
 void
diff --git a/process.c b/process.c
index 570911f..3cbebce 100644
--- a/process.c
+++ b/process.c
@@ -333,7 +333,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
 				{
 					print_addr(&prefix->Prefix, prefix_str);
 
-					if (valid != prefix->AdvValidLifetime)
+					if (!prefix->DecrementLifetimesFlag && valid != prefix->AdvValidLifetime)
 					{
 						flog(LOG_WARNING, "our AdvValidLifetime on"
 						 " %s for %s doesn't agree with %s",
@@ -342,7 +342,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
 						 addr_str
 						 );
 					}
-					if (preferred != prefix->AdvPreferredLifetime)
+					if (!prefix->DecrementLifetimesFlag && preferred != prefix->AdvPreferredLifetime)
 					{
 						flog(LOG_WARNING, "our AdvPreferredLifetime on"
 						 " %s for %s doesn't agree with %s",
diff --git a/radvd.c b/radvd.c
index 09a6fbe..fe88d79 100644
--- a/radvd.c
+++ b/radvd.c
@@ -78,10 +78,12 @@ int sock = -1;
 volatile int sighup_received = 0;
 volatile int sigterm_received = 0;
 volatile int sigint_received = 0;
+volatile int sigusr1_received = 0;
 
 void sighup_handler(int sig);
 void sigterm_handler(int sig);
 void sigint_handler(int sig);
+void sigusr1_handler(int sig);
 void timer_handler(void *data);
 void config_interface(void);
 void kickoff_adverts(void);
@@ -339,6 +341,7 @@ main(int argc, char *argv[])
 	signal(SIGHUP, sighup_handler);
 	signal(SIGTERM, sigterm_handler);
 	signal(SIGINT, sigint_handler);
+	signal(SIGUSR1, sigusr1_handler);
 
 	snprintf(pidstr, sizeof(pidstr), "%ld\n", (long)getpid());
 
@@ -446,6 +449,13 @@ void main_loop(void)
 			reload_config();
 			sighup_received = 0;
 		}
+
+		if (sigusr1_received)
+		{
+			reset_prefix_lifetimes();
+			sigusr1_received = 0;
+		}
+
 	}
 }
 
@@ -502,6 +512,9 @@ kickoff_adverts(void)
 	{
 		double next;
 
+
+		gettimeofday(&iface->last_ra_time, NULL);
+
 		if( iface->UnicastOnly )
 			continue;
 
@@ -667,6 +680,45 @@ sigint_handler(int sig)
 	}
 }
 
+
+void reset_prefix_lifetimes(void)
+{
+	struct Interface *iface;
+	struct AdvPrefix *prefix;
+
+
+	flog(LOG_INFO, "Resetting prefix lifetimes\n");
+	
+	for (iface = IfaceList; iface; iface = iface->next) 
+	{
+		for (prefix = iface->AdvPrefixList; prefix;
+							prefix = prefix->next) 
+		{
+			if (prefix->DecrementLifetimesFlag)
+			{
+				prefix->curr_validlft =
+						prefix->AdvValidLifetime;
+				prefix->curr_preferredlft =
+						prefix->AdvPreferredLifetime;
+			}
+		}
+		
+	}
+
+}
+
+void sigusr1_handler(int sig)
+{
+
+	/* Linux has "one-shot" signals, reinstall the signal handler */
+	signal(SIGUSR1, sigusr1_handler);
+
+	dlog(LOG_DEBUG, 4, "sigusr1_handler called");
+
+	sigusr1_received = 1;
+
+}
+
 int
 drop_root_privileges(const char *username)
 {
diff --git a/radvd.conf.5.man b/radvd.conf.5.man
index a8f1e7b..182ff65 100644
--- a/radvd.conf.5.man
+++ b/radvd.conf.5.man
@@ -432,6 +432,17 @@ See RFC4862, section 5.5.3., "Router Advertisement Processing", part (e).
 Default: off
 
 .TP
+.BR DecrementLifetimes " " on | off
+
+This option causes radvd to decrement the values of the preferred and valid lifetimes for the prefix over time. The lifetimes are decremented by the number of seconds since the last RA. If radvd receives a SIGUSR1 signal, it will reset the values of the preferred and valid lifetimes back to the initial values used by radvd when it started. If radvd never receives a SIGUSR1 signal, it will continue to decrement the lifetimes until the preferred lifetime reaches zero. After a final RA with a zero value preferred lifetime, radvd will cease to announce the prefix. If a SIGUSR1 signal then causes the lifetimes to be reset, the prefix will then re-appear in the RAs.
+
+This option is intended to be used in conjunction with a DHCPv6 client that is using the Identity Association for Prefix Delegation (IA_PD) option to acquire a prefix from a Delegating Router for use by a Requesting Router. In this scenario, the prefix(es) from within the delegated prefix that are announced by radvd would age in parallel with and at the same rate as the delegated prefix, and expire at approximately the same time, if the delegated prefix's life isn't extended.
+
+See RFC3633, "IPv6 Prefix Options for Dynamic Host Configuration Protocol (DHCP) version 6".
+
+Default: off
+
+.TP
 .BR "Base6Interface " name 
 
 If this options is specified, this prefix will be combined with the
diff --git a/radvd.h b/radvd.h
index 8ea9460..a154ff5 100644
--- a/radvd.h
+++ b/radvd.h
@@ -49,6 +49,8 @@ struct Interface {
 
 	int			cease_adv;
 
+	struct timeval		last_ra_time;
+
 	int			IgnoreIfMissing;
 	int			AdvSendAdvert;
 	double			MaxRtrAdvInterval;
@@ -103,6 +105,10 @@ struct AdvPrefix {
 	uint32_t		AdvValidLifetime;
 	uint32_t		AdvPreferredLifetime;
 	int			DeprecatePrefixFlag;
+	int			DecrementLifetimesFlag;
+
+	uint32_t		curr_validlft;
+	uint32_t		curr_preferredlft;
 
 	/* Mobile IPv6 extensions */
 	int             	AdvRouterAddr;
@@ -180,6 +186,7 @@ int yylex(void);
 /* radvd.c */
 int check_ip6_forwarding(void);
 void reload_config(void);
+void reset_prefix_lifetimes(void);
 
 /* timer.c */
 struct timeval next_timeval(double next);
diff --git a/scanner.l b/scanner.l
index 21f5b5b..142bba9 100644
--- a/scanner.l
+++ b/scanner.l
@@ -70,6 +70,7 @@ AdvAutonomous		{ return T_AdvAutonomous; }
 AdvValidLifetime	{ return T_AdvValidLifetime; }
 AdvPreferredLifetime	{ return T_AdvPreferredLifetime; }
 DeprecatePrefix		{ return T_DeprecatePrefix; }
+DecrementLifetimes	{ return T_DecrementLifetimes; }
 
 AdvRouterAddr		{ return T_AdvRouterAddr; }
 AdvHomeAgentFlag	{ return T_AdvHomeAgentFlag; }
diff --git a/send.c b/send.c
index 6d45403..a5dda18 100644
--- a/send.c
+++ b/send.c
@@ -77,6 +77,29 @@ send_ra_inc_len(size_t *len, int add)
 	}
 }
 
+static time_t time_diff_secs(const struct timeval *time_x,
+			     const struct timeval *time_y)
+{
+	time_t secs_diff;
+
+	secs_diff = time_x->tv_sec - time_y->tv_sec;
+	if ((time_x->tv_usec - time_y->tv_usec) >= 500000)
+		secs_diff++;
+
+	return secs_diff;
+	
+}
+
+static void decrement_lifetime(const time_t secs, uint32_t *lifetime)
+{
+
+	if (*lifetime > secs) {
+		*lifetime -= secs;	
+	} else {
+		*lifetime = 0;
+	}
+}
+
 int
 send_ra(struct Interface *iface, struct in6_addr *dest)
 {
@@ -92,6 +115,8 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 	struct AdvRoute *route;
 	struct AdvRDNSS *rdnss;
 	struct AdvDNSSL *dnssl;
+	struct timeval time_now;
+	time_t secs_since_last_ra;
 
 	unsigned char buff[MSG_SIZE_SEND];
 	size_t len = 0;
@@ -134,6 +159,14 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 		gettimeofday(&iface->last_multicast, NULL);
 	}
 
+	gettimeofday(&time_now, NULL);
+	secs_since_last_ra = time_diff_secs(&time_now, &iface->last_ra_time);
+	if (secs_since_last_ra < 0) {
+		secs_since_last_ra = 0;
+		flog(LOG_WARNING, "gettimeofday() went backwards!");
+	}
+	iface->last_ra_time = time_now;
+
 	memset((void *)&addr, 0, sizeof(addr));
 	addr.sin6_family = AF_INET6;
 	addr.sin6_port = htons(IPPROTO_ICMPV6);
@@ -177,7 +210,7 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 
 	while(prefix)
 	{
-		if( prefix->enabled )
+		if( prefix->enabled && prefix->curr_preferredlft > 0 )
 		{
 			struct nd_opt_prefix_info *pinfo;
 
@@ -200,9 +233,16 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 				pinfo->nd_opt_pi_valid_time	= htonl(MIN_AdvValidLifetime);
 				pinfo->nd_opt_pi_preferred_time = 0;
 			} else {
+				if (prefix->DecrementLifetimesFlag) {
+					decrement_lifetime(secs_since_last_ra,
+								&prefix->curr_validlft);
+					
+					decrement_lifetime(secs_since_last_ra,
+								&prefix->curr_preferredlft);
+				}
+				pinfo->nd_opt_pi_valid_time	= htonl(prefix->curr_validlft);
+				pinfo->nd_opt_pi_preferred_time = htonl(prefix->curr_preferredlft);
 
-				pinfo->nd_opt_pi_valid_time	= htonl(prefix->AdvValidLifetime);
-				pinfo->nd_opt_pi_preferred_time = htonl(prefix->AdvPreferredLifetime);
 			}
 			pinfo->nd_opt_pi_reserved2	= 0;
 




-------------- next part --------------
A non-text attachment was scrubbed...
Name: DecrementLifetimes.patch
Type: text/x-patch
Size: 10289 bytes
Desc: not available
URL: <http://lists.litech.org/pipermail/radvd-devel-l/attachments/20110403/40f51b9c/attachment.bin>


More information about the radvd-devel-l mailing list