[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