The RFC defines the P flag for use within PIOs, and defines its meaning
as "purely a positive indicator, telling nodes that DHCPv6 PD is
available and the network prefers that nodes use it".
The RFC abstract lays out:
The (P) flag is used to indicate that the network prefers that clients
use the deployment model in RFC 9663 instead of using individual
addresses in the on-link prefix assigned using SLAAC, or DHCPv6 address
assignment.
Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/301
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
| dhcpv6_assignall |bool | 1 | Assign all viable DHCPv6 addresses in statefull mode; if disabled only the DHCPv6 address having the longest preferred lifetime is assigned |
| dhcpv6_hostidlength |integer| 12 | Host ID length of dynamically created leases, allowed values: 12 - 64 (bits). |
| dhcpv6_na |bool | 1 | DHCPv6 stateful addressing hands out IA_NA - Internet Address - Network Address |
-| dhcpv6_pd |bool | 1 | DHCPv6 stateful addressing hands out IA_PD - Internet Address - Prefix Delegation |
+| dhcpv6_pd |bool | 1 | DHCPv6 stateful addressing hands out IA_PD - Internet Address - Prefix Delegation (PD) |
+| dhcpv6_pd_preferred |bool | 0 | Set the DHCPv6-PD Preferred (P) flag in outgoing ICMPv6 RA message PIOs (RFC9762); requires `dhcpv6` and `dhcpv6_pd`. |
| dhcpv6_pd_min_len |integer| - | Minimum prefix length to delegate with IA_PD (value is adjusted if needed to be greater than the interface prefix length). Range [1,62] |
| router |list |`<local address>`| Routers to announce, accepts IPv4 only |
| dns |list |`<local address>`| DNS servers to announce, accepts IPv4 and IPv6 |
IFACE_ATTR_DHCPV4_FORCERECONF,
IFACE_ATTR_DHCPV6_RAW,
IFACE_ATTR_DHCPV6_ASSIGNALL,
+ IFACE_ATTR_DHCPV6_PD_PREFERRED,
IFACE_ATTR_DHCPV6_PD,
IFACE_ATTR_DHCPV6_PD_MIN_LEN,
IFACE_ATTR_DHCPV6_NA,
[IFACE_ATTR_DHCPV4_FORCERECONF] = { .name = "dhcpv4_forcereconf", .type = BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_DHCPV6_RAW] = { .name = "dhcpv6_raw", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_DHCPV6_ASSIGNALL] = { .name ="dhcpv6_assignall", .type = BLOBMSG_TYPE_BOOL },
+ [IFACE_ATTR_DHCPV6_PD_PREFERRED] = { .name = "dhcpv6_pd_preferred", .type = BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_DHCPV6_PD] = { .name = "dhcpv6_pd", .type = BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_DHCPV6_PD_MIN_LEN] = { .name = "dhcpv6_pd_min_len", .type = BLOBMSG_TYPE_INT32 },
[IFACE_ATTR_DHCPV6_NA] = { .name = "dhcpv6_na", .type = BLOBMSG_TYPE_BOOL },
iface->dhcpv4_end.s_addr = htonl(START_DEFAULT + LIMIT_DEFAULT - 1);
iface->dhcpv6_assignall = true;
iface->dhcpv6_pd = true;
+ iface->dhcpv6_pd_preferred = false;
iface->dhcpv6_pd_min_len = 0;
iface->dhcpv6_na = true;
iface->dhcpv6_hostid_len = HOSTID_LEN_DEFAULT;
if ((c = tb[IFACE_ATTR_DHCPV6_ASSIGNALL]))
iface->dhcpv6_assignall = blobmsg_get_bool(c);
+ if ((c = tb[IFACE_ATTR_DHCPV6_PD_PREFERRED]))
+ iface->dhcpv6_pd_preferred = blobmsg_get_bool(c);
+
if ((c = tb[IFACE_ATTR_DHCPV6_PD]))
iface->dhcpv6_pd = blobmsg_get_bool(c);
size_t dhcpv6_raw_len;
bool dhcpv6_assignall;
bool dhcpv6_pd;
+ bool dhcpv6_pd_preferred;
bool dhcpv6_na;
uint32_t dhcpv6_hostid_len;
uint32_t dhcpv6_pd_min_len; // minimum delegated prefix length
adv.h.nd_ra_flags_reserved |= ND_RA_PREF_LOW;
else if (iface->route_preference > 0)
adv.h.nd_ra_flags_reserved |= ND_RA_PREF_HIGH;
+
+ if (iface->dhcpv6 != MODE_DISABLED && iface->dhcpv6_pd && iface->dhcpv6_pd_preferred) {
+ /* RFC9762 § 5
+ * If the network desires to delegate prefixes to devices that support
+ * DHCPv6 prefix delegation but do not support the P flag, it SHOULD
+ * also set the M or O bits in the RA to 1
+ */
+ adv.h.nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
+ }
adv.h.nd_ra_reachable = htonl(iface->ra_reachabletime);
adv.h.nd_ra_retransmit = htonl(iface->ra_retranstime);
p->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
p->nd_opt_pi_len = 4;
p->nd_opt_pi_prefix_len = (addr->prefix < 64) ? 64 : addr->prefix;
+ /* RFC9762 DHCPv6-PD Preferred Flag § 6:
+ * Routers SHOULD set the P flag to zero by default...
+ */
p->nd_opt_pi_flags_reserved = 0;
if (!iface->ra_not_onlink)
p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
if (iface->ra_slaac && addr->prefix <= 64)
p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
+ if (iface->dhcpv6 != MODE_DISABLED && iface->dhcpv6_pd && iface->dhcpv6_pd_preferred)
+ /* RFC9762 DHCPv6-PD Preferred Flag
+ * We can run both SLAAC and DHCPv6-PD.
+ * §6:
+ * "Routers MUST allow the P flag to be configured separately from the A flag.
+ * ...en/disabling the P flag MUST NOT trigger automatic changes in the A flag
+ * value set by the router."
+ */
+ p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_PD_PREFERRED;
if (iface->ra_advrouter)
// RFC6275, §7.2
p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
#define ND_RA_FLAG_PROXY 0x4
#define ND_RA_PREF_HIGH (1 << 3)
#define ND_RA_PREF_LOW (3 << 3)
+
+/* RFC9762 DHCPv6 PD Availability - Preferred Flag
+ * use this until it is defined in netinet/icmp6.h
+ */
+#define ND_OPT_PI_FLAG_PD_PREFERRED 0x10