feat: Implement --pref64 (RFC 8781)#10
feat: Implement --pref64 (RFC 8781)#10DasSkelett wants to merge 2 commits intofreifunk-gluon:mainfrom
Conversation
jluebbe
left a comment
There was a problem hiding this comment.
I only checked that the default behavior is unchanged, which seems to be the case.
benzea
left a comment
There was a problem hiding this comment.
I guess there is no point in permitting the option to be passed multiple times?
| [OPT_PREFERRED_LIFETIME] = {"preferred-lifetime", required_argument, 0, 0}, | ||
| [OPT_MAX_ROUTER_ADV_INTERVAL] = {"max-router-adv-interval", required_argument, 0, 0}, | ||
| [OPT_MIN_ROUTER_ADV_INTERVAL] = {"min-router-adv-interval", required_argument, 0, 0}, | ||
| [OPT_PREF64] = {"pref64", required_argument, 0, 0}, |
There was a problem hiding this comment.
Other options seem to be pretty verbose. Maybe this should be --nat64-prefix?
There was a problem hiding this comment.
The "concept" is generally called pref64 in e.g. RFC6146 and RFC8781, but --nat64-prefix might give a better hint for people who aren't immediately familiar with it,so fine with me
There was a problem hiding this comment.
I'd stick with pref64 as OpenWRT also calls it pref64:
https://git.openwrt.org/?p=project/odhcpd.git;a=commitdiff;h=c6bff6f1c0fbb37a21a7f54e393615bad22a72d9
Also some nice slides about it:
https://www.ripe.net/participate/forms/uploads/fobi_plugins/file/see-13-presentations/SEE13-IPv6-mostly_on_OpenWRT_41ec5ce8-afc0-4721-9285-12b1891a7af4.pdf
There was a problem hiding this comment.
I'd stick with pref64 as OpenWRT also calls it pref64:
https://git.openwrt.org/?p=project/odhcpd.git;a=commitdiff;h=c6bff6f1c0fbb37a21a7f54e393615bad22a72d9
Also some nice slides about it:
https://www.ripe.net/participate/forms/uploads/fobi_plugins/file/see-13-presentations/SEE13-IPv6-mostly_on_OpenWRT_41ec5ce8-afc0-4721-9285-12b1891a7af4.pdf
There was a problem hiding this comment.
Sure, fine with me if that is what people are expecting.
How would I restrict this? I believe this is missing for all the other options as well, right? |
Ah, no, it is all good. I meant the other way around, actually add multiple entries into the frame if the option is passed multiple times. |
This adds support for the PREF64 Router Advertisement option (RFC 8781).
To include the option in the RA, a prefix needs to be set using the new `--pref64` argument, e.g. `--pref64 64:ff9b::/96`.
Clients can use this prefix for IPv6 address synthesis aka local DNS64, or 464XLAT.
Clients usually require DHCPv4 option 108 ("IPv6-only preferred") to be set to actually enable the 464XLAT CLAT system.
| memcpy(G.pref64_prefix, buf.s6_addr, 12); | ||
| G.pref64_enabled = true; | ||
|
|
||
| return; |
| fprintf(stderr, "uradvd: error: invalid PREF64 length %s (only prefixes of length 32, 40, 48, 56, 64 or 96 are supported).\n", slash+1); | ||
| exit(1); | ||
| } | ||
| preflen = (uint8_t)pl; |
There was a problem hiding this comment.
The preflen variable is not needed, pl can be used instead.
|
|
||
| *slash = 0; | ||
| char *endptr; | ||
| ulong pl = strtoul(slash+1, &endptr, 0); |
There was a problem hiding this comment.
Might be nice to assign slash+1 to a new const char* variable, as it appears a lot.
| pref64.nd_opt_pref64_len = 2; | ||
| uint16_t scld_lifetime = (3u * G.max_rtr_adv_interval) / 8u; // RFC8781 Section 4.1 | ||
| if (scld_lifetime > 8191) { /* 0x1FFF, max 13 bit value */ | ||
| scld_lifetime = 8191; |
There was a problem hiding this comment.
Might make sense to add a comment that this check can't be hit, as max_rtr_adv_interval can't be larger than 1800.
As the limit is specifically about the width of the field, I'd prefer writing this as scld_lifetime > 0x1FFF.
Hi! This implements the PREF64 option as defined in RFC 8781.
The background is that we want to do an IPv6-mostly Parker-based setup at FFMUC, i.e. DNS64 + NAT64 + 464XLAT on clients and on nodes as fallback for clients that don't support CLAT on their own.
PREF64 helps clients to discover the NAT64 prefix for CLAT, especially useful in compination with the DHCP option 108 ("IPv6-only preferred") from RFC 8925
The implementation should be relatively straightforward, adding the new
--pref64option, to be used e.g. likeuradvd --pref64 64:ff9b::/96 -i eth0 -p 2001:db8::/64.The most "confusing" part I believe is the combined
nd_opt_pref64_scaled_lifetime_and_plc("scaled lifetime" plus "prefix length code"), as per the standard they are of length 13 bit and 3 bit respectively, which is quite annoying to handle given there's no arbitrary-sized integer <C23. to my knowledge In the end it's only one bitwise operation combining the two values into a common 16 bit int, though.Note that I don't usually write any code in C, so please pay extra attention to things like safe string & memory handling during review, which I might or might not have gotten right. (I tried my best and followed existing code whenever possible)
I was not able to test this with an actual client yet unfortunately, but at least Wireshark is able to parse the option correctly.Successfully tested with:
After reconnecting to the WiFi, Android started doing its own DNS64 + CLAT using the prefix from the PREF64 option.
I have also cherry-picked theiovlenchange from #4 to base this option on the new mechanism - maybe you want to merge #4 first so I can rebase on top afterwards.Now waiting for #11