From: Roy Marples Date: Mon, 26 Oct 2020 11:19:54 +0000 (+0000) Subject: DHCP: Implement IPv6-Only Preferred option, RFC 8925. X-Git-Tag: v9.3.2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25e2eec83b600968f01f7fdb3ebfc3c82fc8c742;p=thirdparty%2Fdhcpcd.git DHCP: Implement IPv6-Only Preferred option, RFC 8925. Enable it like so in dhcpcd.conf: option ipv6_only_preferred --- diff --git a/src/dhcp.c b/src/dhcp.c index cbfb2bc8..2b741385 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -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) diff --git a/src/dhcp.h b/src/dhcp.h index 497e2888..d0f569d5 100644 --- a/src/dhcp.h +++ b/src/dhcp.h @@ -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 diff --git a/src/dhcpcd-definitions.conf b/src/dhcpcd-definitions.conf index d0b64314..38870091 100644 --- a/src/dhcpcd-definitions.conf +++ b/src/dhcpcd-definitions.conf @@ -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