<br><br><div class="gmail_quote">On Sun, Apr 3, 2011 at 1:57 AM, Mark Smith <span dir="ltr">&lt;<a href="mailto:radvd@02a76c927861ca7413a122f2a73a0d37.nosense.org">radvd@02a76c927861ca7413a122f2a73a0d37.nosense.org</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Hi,<br>
<br>
This is an updated version of the DecrementLifetimes option I posted<br>
for comments a few weeks ago. I think it is ready to commit. Here is<br>
the manual page text -<br>
<br>
       DecrementLifetimes on|off<br>
<br>
              This  option  causes  radvd  to decrement the values of<br>
              the pre‐ ferred and valid lifetimes for the prefix over<br>
              time.  The  life‐ times  are  decremented  by the number<br>
              of seconds since the last RA. If radvd receives a SIGUSR1<br>
              signal, it will reset the values of  the preferred and<br>
              valid lifetimes back to the initial values used by radvd<br>
              when it started. If radvd never receives a SIGUSR1<br>
              signal,  it  will  continue to decrement the lifetimes<br>
              until the preferred lifetime reaches zero. After a final<br>
              RA  with  a  zero value  preferred lifetime, radvd will<br>
              cease to announce the pre‐ fix. If a SIGUSR1 signal then<br>
              causes the lifetimes to be  reset, the prefix will then<br>
              re-appear in the RAs.<br>
<br>
              This  option is intended to be used in conjunction with a<br>
              DHCPv6 client that is using the Identity Association for<br>
              Prefix Delega‐ tion  (IA_PD) option to acquire a prefix<br>
              for use by a Requesting Router. In this scenario, the<br>
              prefix(es) from within  the  delegated  prefix that are<br>
              announced by radvd should age in parallel with and at the<br>
              same rate as the delegated prefix, and expire at<br>
              approximately  the  same  time,  if  the delegated<br>
              prefix&#39;s life isn&#39;t extended by the DHCPv6 server.<br>
<br>
              See RFC3633, &quot;IPv6 Prefix Options for Dynamic Host<br>
              Configuration Protocol  (DHCP)  version 6&quot;, specifically<br>
              the Requesting Router sections.<br>
<br>
The updates were -<br>
<br>
o  some routine renaming<br>
o  use time_t for timeval seconds calculations<br>
o  call gettimeofday() per RA, not per prefix<br>
o  manual page text<br>
<br>
It should apply cleanly to cvs revision 1.116. Attached and shown below.<br>
<br>
Thanks,<br>
Mark.<br>
<br>
<br>
diff --git a/defaults.h b/defaults.h<br>
index 059cbd5..66c5b55 100644<br>
--- a/defaults.h<br>
+++ b/defaults.h<br>
@@ -57,6 +57,7 @@<br>
 #define DFLT_AdvPreferredLifetime      14400 /* seconds */<br>
 #define DFLT_AdvAutonomousFlag         1<br>
 #define DFLT_DeprecatePrefixFlag       0<br>
+#define DFLT_DecrementLifetimesFlag    0<br>
<br>
 /* Each route has an associated: */<br>
 #define DFLT_AdvRouteLifetime(iface)   (3 * (iface)-&gt;MaxRtrAdvInterval)<br>
diff --git a/gram.y b/gram.y<br>
index 3c648fe..52ce610 100644<br>
--- a/gram.y<br>
+++ b/gram.y<br>
@@ -96,6 +96,7 @@ static struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr<br>
 %token         T_AdvValidLifetime<br>
 %token         T_AdvPreferredLifetime<br>
 %token         T_DeprecatePrefix<br>
+%token         T_DecrementLifetimes<br>
<br>
 %token         T_AdvRouterAddr<br>
 %token         T_AdvHomeAgentFlag<br>
@@ -605,11 +606,13 @@ prefixparms       : T_AdvOnLink SWITCH &#39;;&#39;<br>
                                        struct AdvPrefix *p = prefix;<br>
                                        do {<br>
                                                p-&gt;AdvValidLifetime = $2;<br>
+                                               p-&gt;curr_validlft = $2;<br>
                                                p = p-&gt;next;<br>
                                        } while (p &amp;&amp; p-&gt;AutoSelected);<br>
                                }<br>
                                else<br>
                                        prefix-&gt;AdvValidLifetime = $2;<br>
+                                       prefix-&gt;curr_validlft = $2;<br>
                        }<br>
                }<br>
                | T_AdvPreferredLifetime number_or_infinity &#39;;&#39;<br>
@@ -619,17 +622,23 @@ prefixparms       : T_AdvOnLink SWITCH &#39;;&#39;<br>
                                        struct AdvPrefix *p = prefix;<br>
                                        do {<br>
                                                p-&gt;AdvPreferredLifetime = $2;<br>
+                                               p-&gt;curr_preferredlft = $2;<br>
                                                p = p-&gt;next;<br>
                                        } while (p &amp;&amp; p-&gt;AutoSelected);<br>
                                }<br>
                                else<br>
                                        prefix-&gt;AdvPreferredLifetime = $2;<br>
+                                       prefix-&gt;curr_preferredlft = $2;<br>
                        }<br>
                }<br>
                | T_DeprecatePrefix SWITCH &#39;;&#39;<br>
                {<br>
                        prefix-&gt;DeprecatePrefixFlag = $2;<br>
                }<br>
+               | T_DecrementLifetimes SWITCH &#39;;&#39;<br>
+               {<br>
+                       prefix-&gt;DecrementLifetimesFlag = $2;<br>
+               }<br>
                | T_Base6Interface name &#39;;&#39;<br>
                {<br>
                        if (prefix) {<br>
diff --git a/interface.c b/interface.c<br>
index 54265ec..4c37748 100644<br>
--- a/interface.c<br>
+++ b/interface.c<br>
@@ -58,8 +58,12 @@ prefix_init_defaults(struct AdvPrefix *prefix)<br>
        prefix-&gt;AdvValidLifetime = DFLT_AdvValidLifetime;<br>
        prefix-&gt;AdvPreferredLifetime = DFLT_AdvPreferredLifetime;<br>
        prefix-&gt;DeprecatePrefixFlag = DFLT_DeprecatePrefixFlag;<br>
+       prefix-&gt;DecrementLifetimesFlag = DFLT_DecrementLifetimesFlag;<br>
        prefix-&gt;if6to4[0] = 0;<br>
        prefix-&gt;enabled = 1;<br>
+<br>
+       prefix-&gt;curr_validlft = prefix-&gt;AdvValidLifetime;<br>
+       prefix-&gt;curr_preferredlft = prefix-&gt;AdvPreferredLifetime;<br>
 }<br>
<br>
 void<br>
diff --git a/process.c b/process.c<br>
index 570911f..3cbebce 100644<br>
--- a/process.c<br>
+++ b/process.c<br>
@@ -333,7 +333,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,<br>
                                {<br>
                                        print_addr(&amp;prefix-&gt;Prefix, prefix_str);<br>
<br>
-                                       if (valid != prefix-&gt;AdvValidLifetime)<br>
+                                       if (!prefix-&gt;DecrementLifetimesFlag &amp;&amp; valid != prefix-&gt;AdvValidLifetime)<br>
                                        {<br>
                                                flog(LOG_WARNING, &quot;our AdvValidLifetime on&quot;<br>
                                                 &quot; %s for %s doesn&#39;t agree with %s&quot;,<br>
@@ -342,7 +342,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,<br>
                                                 addr_str<br>
                                                 );<br>
                                        }<br>
-                                       if (preferred != prefix-&gt;AdvPreferredLifetime)<br>
+                                       if (!prefix-&gt;DecrementLifetimesFlag &amp;&amp; preferred != prefix-&gt;AdvPreferredLifetime)<br>
                                        {<br>
                                                flog(LOG_WARNING, &quot;our AdvPreferredLifetime on&quot;<br>
                                                 &quot; %s for %s doesn&#39;t agree with %s&quot;,<br>
diff --git a/radvd.c b/radvd.c<br>
index 09a6fbe..fe88d79 100644<br>
--- a/radvd.c<br>
+++ b/radvd.c<br>
@@ -78,10 +78,12 @@ int sock = -1;<br>
 volatile int sighup_received = 0;<br>
 volatile int sigterm_received = 0;<br>
 volatile int sigint_received = 0;<br>
+volatile int sigusr1_received = 0;<br>
<br>
 void sighup_handler(int sig);<br>
 void sigterm_handler(int sig);<br>
 void sigint_handler(int sig);<br>
+void sigusr1_handler(int sig);<br>
 void timer_handler(void *data);<br>
 void config_interface(void);<br>
 void kickoff_adverts(void);<br>
@@ -339,6 +341,7 @@ main(int argc, char *argv[])<br>
        signal(SIGHUP, sighup_handler);<br>
        signal(SIGTERM, sigterm_handler);<br>
        signal(SIGINT, sigint_handler);<br>
+       signal(SIGUSR1, sigusr1_handler);<br>
<br>
        snprintf(pidstr, sizeof(pidstr), &quot;%ld\n&quot;, (long)getpid());<br>
<br>
@@ -446,6 +449,13 @@ void main_loop(void)<br>
                        reload_config();<br>
                        sighup_received = 0;<br>
                }<br>
+<br>
+               if (sigusr1_received)<br>
+               {<br>
+                       reset_prefix_lifetimes();<br>
+                       sigusr1_received = 0;<br>
+               }<br>
+<br>
        }<br>
 }<br>
<br>
@@ -502,6 +512,9 @@ kickoff_adverts(void)<br>
        {<br>
                double next;<br>
<br>
+<br>
+               gettimeofday(&amp;iface-&gt;last_ra_time, NULL);<br>
+<br>
                if( iface-&gt;UnicastOnly )<br>
                        continue;<br>
<br>
@@ -667,6 +680,45 @@ sigint_handler(int sig)<br>
        }<br>
 }<br>
<br>
+<br>
+void reset_prefix_lifetimes(void)<br>
+{<br>
+       struct Interface *iface;<br>
+       struct AdvPrefix *prefix;<br>
+<br>
+<br>
+       flog(LOG_INFO, &quot;Resetting prefix lifetimes\n&quot;);<br>
+<br>
+       for (iface = IfaceList; iface; iface = iface-&gt;next)<br>
+       {<br>
+               for (prefix = iface-&gt;AdvPrefixList; prefix;<br>
+                                                       prefix = prefix-&gt;next)<br>
+               {<br>
+                       if (prefix-&gt;DecrementLifetimesFlag)<br>
+                       {<br>
+                               prefix-&gt;curr_validlft =<br>
+                                               prefix-&gt;AdvValidLifetime;<br>
+                               prefix-&gt;curr_preferredlft =<br>
+                                               prefix-&gt;AdvPreferredLifetime;<br>
+                       }<br>
+               }<br>
+<br>
+       }<br>
+<br>
+}<br>
+<br>
+void sigusr1_handler(int sig)<br>
+{<br>
+<br>
+       /* Linux has &quot;one-shot&quot; signals, reinstall the signal handler */<br>
+       signal(SIGUSR1, sigusr1_handler);<br>
+<br>
+       dlog(LOG_DEBUG, 4, &quot;sigusr1_handler called&quot;);<br>
+<br>
+       sigusr1_received = 1;<br>
+<br>
+}<br>
+<br>
 int<br>
 drop_root_privileges(const char *username)<br>
 {<br>
diff --git a/radvd.conf.5.man b/radvd.conf.5.man<br>
index a8f1e7b..182ff65 100644<br>
--- a/radvd.conf.5.man<br>
+++ b/radvd.conf.5.man<br>
@@ -432,6 +432,17 @@ See RFC4862, section 5.5.3., &quot;Router Advertisement Processing&quot;, part (e).<br>
 Default: off<br>
<br>
 .TP<br>
+.BR DecrementLifetimes &quot; &quot; on | off<br>
+<br>
+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.<br>

+<br>
+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&#39;s life isn&#39;t extended.<br>

+<br>
+See RFC3633, &quot;IPv6 Prefix Options for Dynamic Host Configuration Protocol (DHCP) version 6&quot;.<br>
+<br>
+Default: off<br>
+<br>
+.TP<br>
 .BR &quot;Base6Interface &quot; name<br>
<br>
 If this options is specified, this prefix will be combined with the<br>
diff --git a/radvd.h b/radvd.h<br>
index 8ea9460..a154ff5 100644<br>
--- a/radvd.h<br>
+++ b/radvd.h<br>
@@ -49,6 +49,8 @@ struct Interface {<br>
<br>
        int                     cease_adv;<br>
<br>
+       struct timeval          last_ra_time;<br>
+<br>
        int                     IgnoreIfMissing;<br>
        int                     AdvSendAdvert;<br>
        double                  MaxRtrAdvInterval;<br>
@@ -103,6 +105,10 @@ struct AdvPrefix {<br>
        uint32_t                AdvValidLifetime;<br>
        uint32_t                AdvPreferredLifetime;<br>
        int                     DeprecatePrefixFlag;<br>
+       int                     DecrementLifetimesFlag;<br>
+<br>
+       uint32_t                curr_validlft;<br>
+       uint32_t                curr_preferredlft;<br>
<br>
        /* Mobile IPv6 extensions */<br>
        int                     AdvRouterAddr;<br>
@@ -180,6 +186,7 @@ int yylex(void);<br>
 /* radvd.c */<br>
 int check_ip6_forwarding(void);<br>
 void reload_config(void);<br>
+void reset_prefix_lifetimes(void);<br>
<br>
 /* timer.c */<br>
 struct timeval next_timeval(double next);<br>
diff --git a/scanner.l b/scanner.l<br>
index 21f5b5b..142bba9 100644<br>
--- a/scanner.l<br>
+++ b/scanner.l<br>
@@ -70,6 +70,7 @@ AdvAutonomous         { return T_AdvAutonomous; }<br>
 AdvValidLifetime       { return T_AdvValidLifetime; }<br>
 AdvPreferredLifetime   { return T_AdvPreferredLifetime; }<br>
 DeprecatePrefix                { return T_DeprecatePrefix; }<br>
+DecrementLifetimes     { return T_DecrementLifetimes; }<br>
<br>
 AdvRouterAddr          { return T_AdvRouterAddr; }<br>
 AdvHomeAgentFlag       { return T_AdvHomeAgentFlag; }<br>
diff --git a/send.c b/send.c<br>
index 6d45403..a5dda18 100644<br>
--- a/send.c<br>
+++ b/send.c<br>
@@ -77,6 +77,29 @@ send_ra_inc_len(size_t *len, int add)<br>
        }<br>
 }<br>
<br>
+static time_t time_diff_secs(const struct timeval *time_x,<br>
+                            const struct timeval *time_y)<br>
+{<br>
+       time_t secs_diff;<br>
+<br>
+       secs_diff = time_x-&gt;tv_sec - time_y-&gt;tv_sec;<br>
+       if ((time_x-&gt;tv_usec - time_y-&gt;tv_usec) &gt;= 500000)<br>
+               secs_diff++;<br>
+<br>
+       return secs_diff;<br>
+<br>
+}<br>
+<br>
+static void decrement_lifetime(const time_t secs, uint32_t *lifetime)<br>
+{<br>
+<br>
+       if (*lifetime &gt; secs) {<br>
+               *lifetime -= secs;<br>
+       } else {<br>
+               *lifetime = 0;<br>
+       }<br>
+}<br>
+<br>
 int<br>
 send_ra(struct Interface *iface, struct in6_addr *dest)<br>
 {<br>
@@ -92,6 +115,8 @@ send_ra(struct Interface *iface, struct in6_addr *dest)<br>
        struct AdvRoute *route;<br>
        struct AdvRDNSS *rdnss;<br>
        struct AdvDNSSL *dnssl;<br>
+       struct timeval time_now;<br>
+       time_t secs_since_last_ra;<br>
<br>
        unsigned char buff[MSG_SIZE_SEND];<br>
        size_t len = 0;<br>
@@ -134,6 +159,14 @@ send_ra(struct Interface *iface, struct in6_addr *dest)<br>
                gettimeofday(&amp;iface-&gt;last_multicast, NULL);<br>
        }<br>
<br>
+       gettimeofday(&amp;time_now, NULL);<br>
+       secs_since_last_ra = time_diff_secs(&amp;time_now, &amp;iface-&gt;last_ra_time);<br>
+       if (secs_since_last_ra &lt; 0) {<br>
+               secs_since_last_ra = 0;<br>
+               flog(LOG_WARNING, &quot;gettimeofday() went backwards!&quot;);<br>
+       }<br>
+       iface-&gt;last_ra_time = time_now;<br>
+<br>
        memset((void *)&amp;addr, 0, sizeof(addr));<br>
        addr.sin6_family = AF_INET6;<br>
        addr.sin6_port = htons(IPPROTO_ICMPV6);<br>
@@ -177,7 +210,7 @@ send_ra(struct Interface *iface, struct in6_addr *dest)<br>
<br>
        while(prefix)<br>
        {<br>
-               if( prefix-&gt;enabled )<br>
+               if( prefix-&gt;enabled &amp;&amp; prefix-&gt;curr_preferredlft &gt; 0 )<br>
                {<br>
                        struct nd_opt_prefix_info *pinfo;<br>
<br>
@@ -200,9 +233,16 @@ send_ra(struct Interface *iface, struct in6_addr *dest)<br>
                                pinfo-&gt;nd_opt_pi_valid_time     = htonl(MIN_AdvValidLifetime);<br>
                                pinfo-&gt;nd_opt_pi_preferred_time = 0;<br>
                        } else {<br>
+                               if (prefix-&gt;DecrementLifetimesFlag) {<br>
+                                       decrement_lifetime(secs_since_last_ra,<br>
+                                                               &amp;prefix-&gt;curr_validlft);<br>
+<br>
+                                       decrement_lifetime(secs_since_last_ra,<br>
+                                                               &amp;prefix-&gt;curr_preferredlft);<br>
+                               }<br>
+                               pinfo-&gt;nd_opt_pi_valid_time     = htonl(prefix-&gt;curr_validlft);<br>
+                               pinfo-&gt;nd_opt_pi_preferred_time = htonl(prefix-&gt;curr_preferredlft);<br>
<br>
-                               pinfo-&gt;nd_opt_pi_valid_time     = htonl(prefix-&gt;AdvValidLifetime);<br>
-                               pinfo-&gt;nd_opt_pi_preferred_time = htonl(prefix-&gt;AdvPreferredLifetime);<br>
                        }<br>
                        pinfo-&gt;nd_opt_pi_reserved2      = 0;<br>
<br>
<br>
<br>
<br>
<br>
<br>--<br>
radvd-devel-l mailing list  :  <a href="mailto:radvd-devel-l@litech.org">radvd-devel-l@litech.org</a><br>
<a href="http://lists.litech.org/listinfo/radvd-devel-l" target="_blank">http://lists.litech.org/listinfo/radvd-devel-l</a><br></blockquote></div><br><br><br>Hi Mark,<br><br>It looks like everything is working.  I applied the patch.  If you would like to submit another patch with a some logging, I&#39;ll apply it too.  I&#39;d like to see in the logs, with dlog(LOG_DEBUG, 4,... ), the updated current and valid lifetimes with the prefix text and with dlog(LOG_DEBUG, 3,... ), when the prefix times out.<br>
<br>Check CVS to make sure you patch applied correctly.<br><br>Thanks,<br>Reuben<br>