dhcpv6: add a minimum valid lifetime for IA_PD updates
authorAlin Nastac <alin.nastac@gmail.com>
Fri, 29 Oct 2021 08:44:10 +0000 (10:44 +0200)
committerHans Dedecker <dedeckeh@gmail.com>
Sat, 6 Nov 2021 19:31:23 +0000 (20:31 +0100)
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 <alin.nastac@gmail.com>
src/dhcpv6.c
src/odhcp6c.c
src/odhcp6c.h

index 51b99924991e1ea46f06142a1f9e20bf3c65ff9e..d9df23977067a8ff37fb3280d25177a42f33301d 100644 (file)
@@ -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",
index 227aef68a6b0d8e0d7d9141078f9e74f30b508d6..808aee8ad29198adf4b4e1d23ccb6187ad2a9723 100644 (file)
@@ -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 <seconds>    Maximum timeout for DHCPv6-SOLICIT (120)\n"
        "       -m <seconds>    Minimum time between accepting RA updates (3)\n"
+       "       -D <seconds>    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"
index 14d001760bbcbece1c61d04ade19ff24115dc1a2..6345f2f5d2702e4b5ef40f3d1455f208b248f46e 100644 (file)
@@ -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);