From ca43ea3f436c76fab0b8e3f170725c1d91ebdc36 Mon Sep 17 00:00:00 2001 From: Alin Nastac Date: Fri, 29 Oct 2021 10:44:10 +0200 Subject: [PATCH] dhcpv6: add a minimum valid lifetime for IA_PD updates Prefix delegation is removed when valid lifetime is set to 0, which will result in current prefix assignments to be preserved in odhcpd as long as their previously configured valid lifetime allows it. When IA_PD valid lifetime is set to a small value iso 0, netifd will update old IA_PD assignments, thus allowing removal of the old prefixes from downstream interfaces. Signed-off-by: Alin Nastac --- src/dhcpv6.c | 8 ++++++-- src/odhcp6c.c | 12 ++++++++++-- src/odhcp6c.h | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index 51b9992..d9df239 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -114,6 +114,9 @@ static uint8_t reconf_key[16]; // client options static unsigned int client_options = 0; +// Minimum valid lifetime for IA_PD updates +static unsigned int pd_safe_valid = 0; + static uint32_t ntohl_unaligned(const uint8_t *data) { uint32_t buf; @@ -193,10 +196,11 @@ static char *dhcpv6_status_code_to_str(uint16_t code) return "Unknown"; } -int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout) +int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout, unsigned int ia_pd_safe_valid) { client_options = options; dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = sol_timeout; + pd_safe_valid = ia_pd_safe_valid; sock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); if (sock < 0) @@ -1413,7 +1417,7 @@ static unsigned int dhcpv6_parse_ia(void *opt, void *end) } if (ok) { - if (odhcp6c_update_entry(STATE_IA_PD, &entry, 0, 0)) + if (odhcp6c_update_entry(STATE_IA_PD, &entry, pd_safe_valid, 0)) updated_IAs++; syslog(LOG_INFO, "%s/%d preferred %d valid %d", diff --git a/src/odhcp6c.c b/src/odhcp6c.c index 227aef6..808aee8 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -178,6 +178,7 @@ int main(_unused int argc, char* const argv[]) struct odhcp6c_opt *opt; int ia_pd_iaid_index = 0; int sol_timeout = DHCPV6_SOL_MAX_RT; + unsigned int ia_pd_safe_valid = 5; int verbosity = 0; bool help = false, daemonize = false; int logopt = LOG_PID; @@ -186,7 +187,7 @@ int main(_unused int argc, char* const argv[]) unsigned int ra_options = RA_RDNSS_DEFAULT_LIFETIME; unsigned int ra_holdoff_interval = RA_MIN_ADV_INTERVAL; - while ((c = getopt(argc, argv, "S::N:V:P:FB:c:i:r:Ru:Ux:s:kt:m:Lhedp:fav")) != -1) { + while ((c = getopt(argc, argv, "S::N:V:P:FB:c:i:r:Ru:Ux:s:kt:m:D:Lhedp:fav")) != -1) { switch (c) { case 'S': allow_slaac_only = (optarg) ? atoi(optarg) : -1; @@ -348,6 +349,12 @@ int main(_unused int argc, char* const argv[]) ra_holdoff_interval = atoi(optarg); break; + case 'D': + ia_pd_safe_valid = atoi(optarg); + if (ia_pd_safe_valid > 60) + ia_pd_safe_valid = 60; + break; + case 'L': ra_options &= ~RA_RDNSS_DEFAULT_LIFETIME; break; @@ -412,7 +419,7 @@ int main(_unused int argc, char* const argv[]) signal(SIGUSR2, sighandler); if ((urandom_fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY)) < 0 || - init_dhcpv6(ifname, client_options, sol_timeout) || + init_dhcpv6(ifname, client_options, sol_timeout, ia_pd_safe_valid) || ra_init(ifname, &ifid, ra_options, ra_holdoff_interval) || script_init(script, ifname)) { syslog(LOG_ERR, "failed to initialize: %s", strerror(errno)); @@ -623,6 +630,7 @@ static int usage(void) " -k Don't send a RELEASE when stopping\n" " -t Maximum timeout for DHCPv6-SOLICIT (120)\n" " -m Minimum time between accepting RA updates (3)\n" + " -D Minimum valid lifetime for IA_PD updates (5)\n" " -L Ignore default lifetime for RDNSS records\n" " -U Ignore Server Unicast option\n" "\nInvocation options:\n" diff --git a/src/odhcp6c.h b/src/odhcp6c.h index 14d0017..6345f2f 100644 --- a/src/odhcp6c.h +++ b/src/odhcp6c.h @@ -393,7 +393,7 @@ struct odhcp6c_opt { const char *str; }; -int init_dhcpv6(const char *ifname, unsigned int client_options, int sol_timeout); +int init_dhcpv6(const char *ifname, unsigned int client_options, int sol_timeout, unsigned int ia_pd_safe_valid); int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd); int dhcpv6_request(enum dhcpv6_msg type); int dhcpv6_poll_reconfigure(void); -- 2.30.2