<br><br><div class="gmail_quote">On Thu, Mar 24, 2011 at 9:36 PM, 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 option is a bit more complicated than the last ones. It provides<br>
an option to have radvd decrease the preferred and valid lifetime<br>
values of specified prefixes over time. This would be used in<br>
conjunction with prefixes supplied by DHCPv6 based Prefix Delegation<br>
(DHCPv6-PD). The sequence of events would be as follows -<br>
<br>
1. Initial DHCPv6-PD transaction takes place over a e.g. WAN interface<br>
of the router, and a delegated prefix e.g. a /56 is acquired, with e.g.<br>
a preferred lifetime of 14400 seconds and a valid lifetime of 86400<br>
seconds.<br>
<br>
2. A /64 is taken from within the delegated prefix, for use on the LAN<br>
interface of the router.<br>
<br>
3. A radvd configuration is built with to announce this prefix, with<br>
preferred and valid lifetimes of 14400 and 86400 seconds respectively,<br>
and a prefix DecreaseLifetimes option.<br>
<br>
4. For each RA, either solicited or unsolicited, the preferred and<br>
valid lifetimes are decreased by the number of seconds since the last<br>
RA.<br>
<br>
5. At time &quot;T1&quot; the DHCPv6-PD client will attempt to renew the<br>
delegated prefix. If the delegated prefix is renewed successfully, with<br>
the same preferred and valid lifetimes, the DHCPv6-PD client sends a<br>
USR1 signal to radvd. This causes radvd to reset the announced preferred<br>
and valid lifetimes back to the lifetime values specified in it&#39;s<br>
configuration file, and then continue to decrease them for each<br>
RA. If the delegated prefix either doesn&#39;t renew successfully, or has<br>
different preferred and valid lifetimes, then the DHCPv6-PD client will<br>
have to stop radvd, generate a new configuration for it and start it<br>
again.<br>
<br>
6. If radvd never receives the USR1 signal, it will continue to<br>
decrease the lifetimes until the preferred lifetime reaches 0.<br>
After an announcement of the prefix with a 0 preferred lifetime, radvd<br>
then stops announcing that prefix. If it subsequently receives a USR1<br>
signal, it will then start announcing the prefix again, with the<br>
lifetimes starting back at the specified initial values.<br>
<br>
I&#39;m interested in comments on the following patch. If people are happy<br>
with the approach, I&#39;ll finish it off by e.g. adding manual page<br>
entries.<br>
<br>
Attached and shown below, it should apply to cvs revision 1.115.<br>
<br>
<br>
Thanks,<br>
Mark.<br>
<br>
<br>
diff --git a/defaults.h b/defaults.h<br>
index e09a659..d17cb6f 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 4c74cc8..eb7fb0d 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>
@@ -604,11 +605,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>
@@ -618,17 +621,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 0e6f672..4ffdbf1 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.h b/radvd.h<br>
index 16638fa..78e92b1 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>
@@ -179,6 +185,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 77106cf..a413b30 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 5ff5b5b..6dd9a25 100644<br>
--- a/send.c<br>
+++ b/send.c<br>
@@ -77,6 +77,16 @@ send_ra_inc_len(size_t *len, int add)<br>
        }<br>
 }<br>
<br>
+static void decrement_lifetime(const long int 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 +102,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>
+       long int secs_since_last_ra;<br>
<br>
        unsigned char buff[MSG_SIZE_SEND];<br>
        size_t len = 0;<br>
@@ -134,6 +146,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_now.tv_sec - iface-&gt;last_ra_time.tv_sec;<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 +197,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 +220,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>--<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>Hi Mark,<br><br>I&#39;m not too enthusiastic about this patch for a few reasons.  I don&#39;t like the idea of an advert being dependent on time.  Although it&#39;s subtle, it makes debugging and/or reproducing a bug more difficult.  However, this is called for in section 6.2.1 of RFC 2461 under AdvPreferredLifetime and AdvValidLifetime.<br>
<br>As such, please continue to test this for a while.  Make sure it&#39;s working.  If there&#39;s no objections to committing this, I&#39;ll commit it in a few weeks.<br><br>Thanks,<br>Reuben<br>