]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
DHCP: Implement IPv6-Only Preferred option, RFC 8925.
authorRoy Marples <roy@marples.name>
Mon, 26 Oct 2020 11:19:54 +0000 (11:19 +0000)
committerRoy Marples <roy@marples.name>
Mon, 26 Oct 2020 11:19:54 +0000 (11:19 +0000)
Enable it like so in dhcpcd.conf:
option ipv6_only_preferred

src/dhcp.c
src/dhcp.h
src/dhcpcd-definitions.conf

index cbfb2bc8f8c8e9dc9606f1873b1b3cf436cdfb8a..2b7413851bd3d21ff6c74da1a73e1624b4f3b0d4 100644 (file)
@@ -2926,6 +2926,8 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
        unsigned int i;
        char *msg;
        bool bootp_copied;
+       uint32_t v6only_time = 0;
+       bool use_v6only = false;
 #ifdef AUTH
        const uint8_t *auth;
        size_t auth_len;
@@ -3143,6 +3145,23 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
                }
        }
 
+       if (has_option_mask(ifo->requestmask, DHO_IPV6_PREFERRED_ONLY)) {
+               if (get_option_uint32(ifp->ctx, &v6only_time, bootp, bootp_len,
+                   DHO_IPV6_PREFERRED_ONLY) == 0 &&
+                   (state->state == DHS_DISCOVER || state->state == DHS_REBOOT))
+               {
+                       char v6msg[128];
+
+                       use_v6only = true;
+                       if (v6only_time < MIN_V6ONLY_WAIT)
+                               v6only_time = MIN_V6ONLY_WAIT;
+                       snprintf(v6msg, sizeof(v6msg),
+                           "IPv6-Only Preferred received (%u seconds)",
+                           v6only_time);
+                       LOGDHCP(LOG_INFO, v6msg);
+               }
+       }
+
        /* DHCP Auto-Configure, RFC 2563 */
        if (type == DHCP_OFFER && bootp->yiaddr == 0) {
                LOGDHCP(LOG_WARNING, "no address given");
@@ -3177,12 +3196,22 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
                        }
                        eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
                        eloop_timeout_add_sec(ifp->ctx->eloop,
-                           DHCP_MAX, dhcp_discover, ifp);
+                           use_v6only ? v6only_time : DHCP_MAX,
+                           dhcp_discover, ifp);
                }
 #endif
                return;
        }
 
+       if (use_v6only) {
+               dhcp_drop(ifp, "EXPIRE");
+               dhcp_unlink(ifp->ctx, state->leasefile);
+               eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+               eloop_timeout_add_sec(ifp->ctx->eloop, v6only_time,
+                   dhcp_discover, ifp);
+               return;
+       }
+
        /* Ensure that the address offered is valid */
        if ((type == 0 || type == DHCP_OFFER || type == DHCP_ACK) &&
            (bootp->ciaddr == INADDR_ANY || bootp->ciaddr == INADDR_BROADCAST)
index 497e288813b5a9178e0cd2d022387b93da512c56..d0f569d59e8471f07b30870b7006e2cb665728c9 100644 (file)
@@ -116,6 +116,7 @@ enum DHO {
        DHO_RAPIDCOMMIT            = 80,  /* RFC 4039 */
        DHO_FQDN                   = 81,
        DHO_AUTHENTICATION         = 90,  /* RFC 3118 */
+       DHO_IPV6_PREFERRED_ONLY    = 108, /* RFC 8925 */
        DHO_AUTOCONFIGURE          = 116, /* RFC 2563 */
        DHO_DNSSEARCH              = 119, /* RFC 3397 */
        DHO_CSR                    = 121, /* RFC 3442 */
@@ -139,6 +140,8 @@ enum FQDN {
        FQDN_BOTH       = 0x31
 };
 
+#define        MIN_V6ONLY_WAIT         300 /* seconds, RFC 8925 */
+
 /* Sizes for BOOTP options */
 #define        BOOTP_CHADDR_LEN         16
 #define        BOOTP_SNAME_LEN          64
index d0b643144940c1d429f0a047970abe9faf07979f..388700913975b8e021e69e0dc61cf52aab6f048f 100644 (file)
@@ -172,6 +172,9 @@ define 101  string                  tzdb_timezone
 
 # Options 102-115 are unused, RFC3679
 
+# DHCP IPv6-Only Preferred, RFC8925
+define 108     uint32                  ipv6_only_preferred
+
 # DHCP Auto-Configuration, RFC2563
 define 116     byte                    auto_configure