mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-21 07:15:49 +00:00
rtadvd(8): support PREF64 (RFC 8781)
PREF64 allows a router to advertise the network's NAT64 prefix, allowing clients to auto-configure CLAT. This makes it possible to deploy IPv6-only or IPv6-mostly client access networks without the need for DNS64. Reviewed by: imp, glebius (prior suggetions done) Pull Request: https://github.com/freebsd/freebsd-src/pull/1206
This commit is contained in:
parent
1e8eb413f6
commit
77f06c476c
@ -912,6 +912,58 @@ getconfig(struct ifinfo *ifi)
|
||||
}
|
||||
free(dns);
|
||||
}
|
||||
|
||||
/*
|
||||
* handle pref64
|
||||
*/
|
||||
rai->rai_pref64.p64_enabled = false;
|
||||
|
||||
if ((addr = (char *)agetstr("pref64", &bp))) {
|
||||
if (inet_pton(AF_INET6, addr, &rai->rai_pref64.p64_prefix) != 1) {
|
||||
syslog(LOG_ERR, "<%s> inet_pton failed for %s",
|
||||
__func__, addr);
|
||||
} else {
|
||||
rai->rai_pref64.p64_enabled = true;
|
||||
|
||||
switch (val64 = agetnum("pref64len")) {
|
||||
case -1:
|
||||
case 96:
|
||||
rai->rai_pref64.p64_plc = 0;
|
||||
break;
|
||||
case 64:
|
||||
rai->rai_pref64.p64_plc = 1;
|
||||
break;
|
||||
case 56:
|
||||
rai->rai_pref64.p64_plc = 2;
|
||||
break;
|
||||
case 48:
|
||||
rai->rai_pref64.p64_plc = 3;
|
||||
break;
|
||||
case 40:
|
||||
rai->rai_pref64.p64_plc = 4;
|
||||
break;
|
||||
case 32:
|
||||
rai->rai_pref64.p64_plc = 5;
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "prefix length %" PRIi64
|
||||
"on %s is invalid; disabling PREF64",
|
||||
val64, ifi->ifi_ifname);
|
||||
rai->rai_pref64.p64_enabled = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* This logic is from RFC 8781 section 4.1. */
|
||||
val64 = agetnum("pref64lifetime");
|
||||
if (val64 == -1)
|
||||
val64 = rai->rai_lifetime * 3;
|
||||
if (val64 > 65528)
|
||||
val64 = 65528;
|
||||
val64 = (val64 + 7) / 8;
|
||||
rai->rai_pref64.p64_sl = (uint16_t) (uint64_t) val64;
|
||||
}
|
||||
}
|
||||
|
||||
/* construct the sending packet */
|
||||
make_packet(rai);
|
||||
|
||||
@ -1334,6 +1386,7 @@ make_packet(struct rainfo *rai)
|
||||
struct rdnss *rdn;
|
||||
struct nd_opt_dnssl *ndopt_dnssl;
|
||||
struct dnssl *dns;
|
||||
struct nd_opt_pref64 *ndopt_pref64;
|
||||
size_t len;
|
||||
struct prefix *pfx;
|
||||
struct ifinfo *ifi;
|
||||
@ -1355,6 +1408,8 @@ make_packet(struct rainfo *rai)
|
||||
packlen += sizeof(struct nd_opt_prefix_info) * rai->rai_pfxs;
|
||||
if (rai->rai_linkmtu)
|
||||
packlen += sizeof(struct nd_opt_mtu);
|
||||
if (rai->rai_pref64.p64_enabled)
|
||||
packlen += sizeof(struct nd_opt_pref64);
|
||||
|
||||
TAILQ_FOREACH(rti, &rai->rai_route, rti_next)
|
||||
packlen += sizeof(struct nd_opt_route_info) +
|
||||
@ -1435,6 +1490,19 @@ make_packet(struct rainfo *rai)
|
||||
buf += sizeof(struct nd_opt_mtu);
|
||||
}
|
||||
|
||||
if (rai->rai_pref64.p64_enabled) {
|
||||
ndopt_pref64 = (struct nd_opt_pref64 *)buf;
|
||||
ndopt_pref64->nd_opt_pref64_type = ND_OPT_PREF64;
|
||||
ndopt_pref64->nd_opt_pref64_len = 2;
|
||||
ndopt_pref64->nd_opt_pref64_sl_plc =
|
||||
(htons(rai->rai_pref64.p64_sl << 3)) |
|
||||
htons((rai->rai_pref64.p64_plc & 0x7));
|
||||
memcpy(&ndopt_pref64->nd_opt_prefix[0],
|
||||
&rai->rai_pref64.p64_prefix,
|
||||
sizeof(ndopt_pref64->nd_opt_prefix));
|
||||
buf += sizeof(struct nd_opt_pref64);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) {
|
||||
uint32_t vltime, pltime;
|
||||
struct timespec now;
|
||||
|
@ -428,6 +428,24 @@ DNS search list entries.
|
||||
The default value is 3/2 of the interval time.
|
||||
.El
|
||||
.Pp
|
||||
The following items are for PREF64 discovery
|
||||
.Pq RFC 8781 ,
|
||||
which will advertise the network's NAT64 prefix to clients.
|
||||
These items are optional.
|
||||
.Bl -tag -width indent
|
||||
.It Cm \&pref64
|
||||
(str) The prefix to advertise in the PREF64 option.
|
||||
.It Cm \&pref64len
|
||||
(num) The length of the PREF64 prefix.
|
||||
This must be 96, 64, 56, 48, 40, or 32.
|
||||
If not specified, the default is 96.
|
||||
.It Cm \&pref64lifetime
|
||||
(num) The prefix lifetime to advertise in the PREF64 option.
|
||||
This should be at least as long as the RA lifetime, but cannot be greater
|
||||
than 65528.
|
||||
If not specified, the default is the RA lifetime, or 65528, whichever is lower.
|
||||
.El
|
||||
.Pp
|
||||
You can also refer one line from another by using
|
||||
.Cm tc
|
||||
capability.
|
||||
|
@ -32,6 +32,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define ELM_MALLOC(p,error_action) \
|
||||
do { \
|
||||
p = malloc(sizeof(*p)); \
|
||||
@ -148,6 +150,14 @@ struct rdnss {
|
||||
uint32_t rd_ltime; /* number of seconds valid */
|
||||
};
|
||||
|
||||
struct pref64 {
|
||||
TAILQ_ENTRY(pref64) p64_next;
|
||||
bool p64_enabled;
|
||||
uint16_t p64_plc; /* prefix length code */
|
||||
uint16_t p64_sl; /* scaled lifetime */
|
||||
struct in6_addr p64_prefix;
|
||||
};
|
||||
|
||||
/*
|
||||
* The maximum length of a domain name in a DNS search list is calculated
|
||||
* by a domain name + length fields per 63 octets + a zero octet at
|
||||
@ -217,6 +227,7 @@ struct rainfo {
|
||||
/* actual RA packet data and its length */
|
||||
size_t rai_ra_datalen;
|
||||
char *rai_ra_data;
|
||||
struct pref64 rai_pref64; /* PREF64 option */
|
||||
|
||||
/* info about soliciter */
|
||||
TAILQ_HEAD(, soliciter) rai_soliciter; /* recent solication source */
|
||||
|
Loading…
Reference in New Issue
Block a user