Skip to content

Add support for RFC6603 Prefix Exclude Option#374

Open
mmmspatz wants to merge 1 commit intoopenwrt:masterfrom
mmmspatz:mspatz/pd_exclude
Open

Add support for RFC6603 Prefix Exclude Option#374
mmmspatz wants to merge 1 commit intoopenwrt:masterfrom
mmmspatz:mspatz/pd_exclude

Conversation

@mmmspatz
Copy link

If option dhcpv6_pd_exclude is set in a dhcp config section (in addition to dhcpv6_pd), consider delegating prefixes that include the on-link prefix, and send RFC6603 DHCPV6_OPT_PD_EXCLUDE for the on-link prefix.

For example, if the interface's longest prefix is 2001:0db8::/32, we might delegate that entire /32 and send a DHCPV6_OPT_PD_EXCLUDE option for 2001:0db8::/64. More commonly, we might delegate a smaller prefix that includes the on-link prefix, like 2001:0db8::/56.

For this behavior to be triggered, all of the following must be true:

  1. option dhcpv6_pd_exclude ='1' must be set in the config
  2. A client must send an DHCPV6_OPT_ORO option with the DHCPV6_OPT_PD_EXCLUDE option code
  3. An overlapping prefix must not have already been assigned. For example, if 2001:0db8:0:10::/60 has been assigned to client A, we can't assign 2001:0db8::/56 to client B. We'll instead end up assigning 2001:0db8:0:100::/56 just as before.

My implementation makes the assumption that the on-link prefix is the first /64 in the interface's larger prefix. I note that assign_pd() already made that assumption: The first subnet id it considered was 0000:0001, now it may optionally consider 0000:0000. I believe it is correct to say that odhcpd relies on netifd assigning the first /64 as the on-link prefix when it is delegating a prefix to an interface. If a user gave an interface address 2001:0db8:dead:beef::/32 and also created an unreachable route to that prefix, odhcpd would misbehave.

@mmmspatz
Copy link
Author

Note that odhcp6c currently has bad bugs in its handling of DHCPV6_OPT_PD_EXCLUDE, see openwrt/odhcp6c#151

@systemcrash
Copy link
Contributor

I know about those bugs.... I've spent a few midnight hours chasing them. Thanks for this interesting PR!

You know about max prefix length parameter, right?

I'll take a closer look over the coming days since PX requires attention up to 128 bits, according to the spec.

@mmmspatz
Copy link
Author

I know about dhcpv6_pd_min_len, and it is still respected. I should have mentioned: in order for an interface's full prefix to be re-delegated, dhcpv6_pd_min_len has to allow it.

There's no compliance issue with only supporting 32 bits of prefix id, since as the server we only have to emit a valid option, not consume it. And in this PR, I I've hard coded exclusion of a /64 with prefix id 0000:0000.

src/dhcpv6-ia.c Outdated
uint8_t excl_subnet_id_nbytes = ((excl_subnet_id_nbits - 1) / 8) + 1;
o_pd_exl_len = sizeof(o_pd_exl) + excl_subnet_id_nbytes;

/* Work around a bug in odhcp6c that ignores DHCPV6_OPT_PD_EXCLUDE with valid option length of 2. */
Copy link
Author

@mmmspatz mmmspatz Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workaround allows the current master branch of odhcp6c (with its bugs) to correctly parse the exclude option. It only works because the subnet id bits are all 0, so it doesn't matter that they get jumbled up.

A standards compliant parser shouldn't care about the extra trailing byte.

@mmmspatz mmmspatz force-pushed the mspatz/pd_exclude branch 2 times, most recently from 8ad322e to d082db1 Compare January 21, 2026 20:09
@systemcrash
Copy link
Contributor

ping @Noltari and @Alphix :)

If option dhcpv6_pd_exclude is set in a dhcp config section (in addition
to option dhcpv6_pd), consider delegating prefixes that include on-link
prefixes.

This allows an entire delegated prefix to be re-delegated to a
downstream router under certain circumstances.

Signed-off-by: Mark H. Spatz <mark.h.spatz@gmail.com>
@systemcrash
Copy link
Contributor

OK - this is looking decent. What do captures reveal? The spec does not rule out an exclusion all the way up to 128, but it seems you're halting at 64 bits. The cross boundary maths there can get a bit difficult to follow.

How do captures (tcpdump ish) look for this?

@mmmspatz
Copy link
Author

mmmspatz commented Feb 6, 2026

I think you're confusing this with my other PR on odhcp6c.
That one's about fixing the currently-completely-wrong handling of option 67 in the client.
I think that one's more important to get merged.

This PR is about sending option 67 from the server to exclude the first /64 (ie. subnet id 0) from the delegated prefix. Since it always excludes a /64 with subnet id 0, the IPv6 subnet ID field in the option is trivial to calculate: it's just ((64 - delegated_len - 1) / 8) + 1 null bytes. So the nonsensical case of delegated_len = 0 is indeed supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants