<br><br><div class="gmail_quote">On Thu, Mar 24, 2011 at 9:36 PM, Mark Smith <span dir="ltr"><<a href="mailto:radvd@02a76c927861ca7413a122f2a73a0d37.nosense.org">radvd@02a76c927861ca7413a122f2a73a0d37.nosense.org</a>></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 "T1" 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's<br>
configuration file, and then continue to decrease them for each<br>
RA. If the delegated prefix either doesn'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'm interested in comments on the following patch. If people are happy<br>
with the approach, I'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)->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 ';'<br>
struct AdvPrefix *p = prefix;<br>
do {<br>
p->AdvValidLifetime = $2;<br>
+ p->curr_validlft = $2;<br>
p = p->next;<br>
} while (p && p->AutoSelected);<br>
}<br>
else<br>
prefix->AdvValidLifetime = $2;<br>
+ prefix->curr_validlft = $2;<br>
}<br>
}<br>
| T_AdvPreferredLifetime number_or_infinity ';'<br>
@@ -618,17 +621,23 @@ prefixparms : T_AdvOnLink SWITCH ';'<br>
struct AdvPrefix *p = prefix;<br>
do {<br>
p->AdvPreferredLifetime = $2;<br>
+ p->curr_preferredlft = $2;<br>
p = p->next;<br>
} while (p && p->AutoSelected);<br>
}<br>
else<br>
prefix->AdvPreferredLifetime = $2;<br>
+ prefix->curr_preferredlft = $2;<br>
}<br>
}<br>
| T_DeprecatePrefix SWITCH ';'<br>
{<br>
prefix->DeprecatePrefixFlag = $2;<br>
}<br>
+ | T_DecrementLifetimes SWITCH ';'<br>
+ {<br>
+ prefix->DecrementLifetimesFlag = $2;<br>
+ }<br>
| T_Base6Interface name ';'<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->AdvValidLifetime = DFLT_AdvValidLifetime;<br>
prefix->AdvPreferredLifetime = DFLT_AdvPreferredLifetime;<br>
prefix->DeprecatePrefixFlag = DFLT_DeprecatePrefixFlag;<br>
+ prefix->DecrementLifetimesFlag = DFLT_DecrementLifetimesFlag;<br>
prefix->if6to4[0] = 0;<br>
prefix->enabled = 1;<br>
+<br>
+ prefix->curr_validlft = prefix->AdvValidLifetime;<br>
+ prefix->curr_preferredlft = prefix->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(&prefix->Prefix, prefix_str);<br>
<br>
- if (valid != prefix->AdvValidLifetime)<br>
+ if (!prefix->DecrementLifetimesFlag && valid != prefix->AdvValidLifetime)<br>
{<br>
flog(LOG_WARNING, "our AdvValidLifetime on"<br>
" %s for %s doesn't agree with %s",<br>
@@ -342,7 +342,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,<br>
addr_str<br>
);<br>
}<br>
- if (preferred != prefix->AdvPreferredLifetime)<br>
+ if (!prefix->DecrementLifetimesFlag && preferred != prefix->AdvPreferredLifetime)<br>
{<br>
flog(LOG_WARNING, "our AdvPreferredLifetime on"<br>
" %s for %s doesn't agree with %s",<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), "%ld\n", (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(&iface->last_ra_time, NULL);<br>
+<br>
if( iface->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, "Resetting prefix lifetimes\n");<br>
+<br>
+ for (iface = IfaceList; iface; iface = iface->next)<br>
+ {<br>
+ for (prefix = iface->AdvPrefixList; prefix;<br>
+ prefix = prefix->next)<br>
+ {<br>
+ if (prefix->DecrementLifetimesFlag)<br>
+ {<br>
+ prefix->curr_validlft =<br>
+ prefix->AdvValidLifetime;<br>
+ prefix->curr_preferredlft =<br>
+ prefix->AdvPreferredLifetime;<br>
+ }<br>
+ }<br>
+<br>
+ }<br>
+<br>
+}<br>
+<br>
+void sigusr1_handler(int sig)<br>
+{<br>
+<br>
+ /* Linux has "one-shot" signals, reinstall the signal handler */<br>
+ signal(SIGUSR1, sigusr1_handler);<br>
+<br>
+ dlog(LOG_DEBUG, 4, "sigusr1_handler called");<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 > 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(&iface->last_multicast, NULL);<br>
}<br>
<br>
+ gettimeofday(&time_now, NULL);<br>
+ secs_since_last_ra = time_now.tv_sec - iface->last_ra_time.tv_sec;<br>
+ if (secs_since_last_ra < 0) {<br>
+ secs_since_last_ra = 0;<br>
+ flog(LOG_WARNING, "gettimeofday() went backwards!");<br>
+ }<br>
+ iface->last_ra_time = time_now;<br>
+<br>
memset((void *)&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->enabled )<br>
+ if( prefix->enabled && prefix->curr_preferredlft > 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->nd_opt_pi_valid_time = htonl(MIN_AdvValidLifetime);<br>
pinfo->nd_opt_pi_preferred_time = 0;<br>
} else {<br>
+ if (prefix->DecrementLifetimesFlag) {<br>
+ decrement_lifetime(secs_since_last_ra,<br>
+ &prefix->curr_validlft);<br>
+<br>
+ decrement_lifetime(secs_since_last_ra,<br>
+ &prefix->curr_preferredlft);<br>
+ }<br>
+ pinfo->nd_opt_pi_valid_time = htonl(prefix->curr_validlft);<br>
+ pinfo->nd_opt_pi_preferred_time = htonl(prefix->curr_preferredlft);<br>
<br>
- pinfo->nd_opt_pi_valid_time = htonl(prefix->AdvValidLifetime);<br>
- pinfo->nd_opt_pi_preferred_time = htonl(prefix->AdvPreferredLifetime);<br>
}<br>
pinfo->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'm not too enthusiastic about this patch for a few reasons. I don't like the idea of an advert being dependent on time. Although it'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's working. If there's no objections to committing this, I'll commit it in a few weeks.<br><br>Thanks,<br>Reuben<br>