From 5207bb19fdf2419f8984bb748973c0acc19b5ded Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 15 Oct 2022 13:26:15 +0000 Subject: [PATCH] Implement RFC 8781 PREF64 router advertisement option. With this clients can learn the presence and used prefix for Network Address and Protocol Translation between IPv6 and IPv4 (NAT64). Apparently there is support in mobile devices as well as in macOS. This option, together with the the dhcp "IPv6-only preferred" option (108) enables the Customer-side transLATor (CLAT) on macOS so IPv4 literals can be used in IPv6-only networks. Input & OK kn --- usr.sbin/rad/engine.c | 17 +++++- usr.sbin/rad/frontend.c | 71 +++++++++++++++++++++++- usr.sbin/rad/parse.y | 117 ++++++++++++++++++++++++++++++++++++++- usr.sbin/rad/printconf.c | 10 +++- usr.sbin/rad/rad.8 | 12 +++- usr.sbin/rad/rad.c | 36 +++++++++++- usr.sbin/rad/rad.conf.5 | 23 +++++++- usr.sbin/rad/rad.h | 12 +++- 8 files changed, 286 insertions(+), 12 deletions(-) diff --git a/usr.sbin/rad/engine.c b/usr.sbin/rad/engine.c index dddff2d4579..ceb11d574e3 100644 --- a/usr.sbin/rad/engine.c +++ b/usr.sbin/rad/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.20 2022/03/23 15:26:08 florian Exp $ */ +/* $OpenBSD: engine.c,v 1.21 2022/10/15 13:26:15 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser @@ -269,6 +269,7 @@ engine_dispatch_main(int fd, short event, void *bula) struct ra_prefix_conf *ra_prefix_conf; struct ra_rdnss_conf *ra_rdnss_conf; struct ra_dnssl_conf *ra_dnssl_conf; + struct ra_pref64_conf *pref64; ssize_t n; int shut = 0; @@ -333,6 +334,7 @@ engine_dispatch_main(int fd, short event, void *bula) SIMPLEQ_INIT(&nconf->ra_iface_list); SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list); SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list); + SIMPLEQ_INIT(&nconf->ra_options.ra_pref64_list); ra_options = &nconf->ra_options; break; case IMSG_RECONF_RA_IFACE: @@ -349,6 +351,7 @@ engine_dispatch_main(int fd, short event, void *bula) SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list); SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list); SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list); + SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_pref64_list); SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list, ra_iface_conf, entry); ra_options = &ra_iface_conf->ra_options; @@ -405,6 +408,18 @@ engine_dispatch_main(int fd, short event, void *bula) SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list, ra_dnssl_conf, entry); break; + case IMSG_RECONF_RA_PREF64: + if(IMSG_DATA_SIZE(imsg) != sizeof(struct + ra_pref64_conf)) + fatalx("%s: IMSG_RECONF_RA_PREF64 wrong length: " + "%lu", __func__, IMSG_DATA_SIZE(imsg)); + if ((pref64 = malloc(sizeof(struct ra_pref64_conf))) == + NULL) + fatal(NULL); + memcpy(pref64, imsg.data, sizeof(struct ra_pref64_conf)); + SIMPLEQ_INSERT_TAIL(&ra_options->ra_pref64_list, pref64, + entry); + break; case IMSG_RECONF_END: if (nconf == NULL) fatalx("%s: IMSG_RECONF_END without " diff --git a/usr.sbin/rad/frontend.c b/usr.sbin/rad/frontend.c index 30bcde218c4..211a3883117 100644 --- a/usr.sbin/rad/frontend.c +++ b/usr.sbin/rad/frontend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.c,v 1.40 2022/01/17 18:04:35 naddy Exp $ */ +/* $OpenBSD: frontend.c,v 1.41 2022/10/15 13:26:15 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser @@ -113,6 +113,14 @@ struct ra_iface { uint8_t data[RA_MAX_SIZE]; }; +#define ND_OPT_PREF64 38 +struct nd_opt_pref64 { + u_int8_t nd_opt_pref64_type; + u_int8_t nd_opt_pref64_len; + u_int16_t nd_opt_pref64_sltime_plc; + u_int8_t nd_opt_pref64[12]; +}; + TAILQ_HEAD(, ra_iface) ra_interfaces; __dead void frontend_shutdown(void); @@ -300,6 +308,7 @@ frontend_dispatch_main(int fd, short event, void *bula) struct ra_prefix_conf *ra_prefix_conf; struct ra_rdnss_conf *ra_rdnss_conf; struct ra_dnssl_conf *ra_dnssl_conf; + struct ra_pref64_conf *pref64; int n, shut = 0, icmp6sock, rdomain; if (event & EV_READ) { @@ -361,6 +370,7 @@ frontend_dispatch_main(int fd, short event, void *bula) SIMPLEQ_INIT(&nconf->ra_iface_list); SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list); SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list); + SIMPLEQ_INIT(&nconf->ra_options.ra_pref64_list); ra_options = &nconf->ra_options; break; case IMSG_RECONF_RA_IFACE: @@ -377,6 +387,7 @@ frontend_dispatch_main(int fd, short event, void *bula) SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list); SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list); SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list); + SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_pref64_list); SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list, ra_iface_conf, entry); ra_options = &ra_iface_conf->ra_options; @@ -433,6 +444,18 @@ frontend_dispatch_main(int fd, short event, void *bula) SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list, ra_dnssl_conf, entry); break; + case IMSG_RECONF_RA_PREF64: + if (IMSG_DATA_SIZE(imsg) != sizeof(struct + ra_pref64_conf)) + fatalx("%s: IMSG_RECONF_RA_PREF64 wrong length: " + "%lu", __func__, IMSG_DATA_SIZE(imsg)); + if ((pref64 = malloc(sizeof(struct ra_pref64_conf))) == + NULL) + fatal(NULL); + memcpy(pref64, imsg.data, sizeof(struct ra_pref64_conf)); + SIMPLEQ_INSERT_TAIL(&ra_options->ra_pref64_list, pref64, + entry); + break; case IMSG_RECONF_END: if (nconf == NULL) fatalx("%s: IMSG_RECONF_END without " @@ -1084,8 +1107,10 @@ build_packet(struct ra_iface *ra_iface) struct ra_prefix_conf *ra_prefix_conf; struct nd_opt_rdnss *ndopt_rdnss; struct nd_opt_dnssl *ndopt_dnssl; + struct nd_opt_pref64 *ndopt_pref64; struct ra_rdnss_conf *ra_rdnss; struct ra_dnssl_conf *ra_dnssl; + struct ra_pref64_conf *pref64; size_t len, label_len; uint8_t *p, buf[RA_MAX_SIZE]; char *label_start, *label_end; @@ -1108,6 +1133,10 @@ build_packet(struct ra_iface *ra_iface) len += sizeof(*ndopt_dnssl) + ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7); + SIMPLEQ_FOREACH(pref64, &ra_iface_conf->ra_options.ra_pref64_list, + entry) + len += sizeof(struct nd_opt_pref64); + if (len > sizeof(ra_iface->data)) fatalx("%s: packet too big", __func__); /* XXX send multiple */ @@ -1207,6 +1236,46 @@ build_packet(struct ra_iface *ra_iface) *p++ = '\0'; } + SIMPLEQ_FOREACH(pref64, &ra_iface_conf->ra_options.ra_pref64_list, + entry) { + uint16_t sltime_plc; + + /* scaled lifetime in units of 8 seconds */ + sltime_plc = pref64->ltime / 8; + sltime_plc = sltime_plc << 3; + /* encode prefix lenght in lower 3 bits */ + switch (pref64->prefixlen) { + case 96: + sltime_plc |= 0; + break; + case 64: + sltime_plc |= 1; + break; + case 56: + sltime_plc |= 2; + break; + case 48: + sltime_plc |= 3; + break; + case 40: + sltime_plc |= 4; + break; + case 32: + sltime_plc |= 5; + break; + default: + fatalx("%s: invalid pref64 length: %d", __func__, + pref64->prefixlen); + } + ndopt_pref64 = (struct nd_opt_pref64 *)p; + ndopt_pref64->nd_opt_pref64_type = ND_OPT_PREF64; + ndopt_pref64->nd_opt_pref64_len = 2; + ndopt_pref64->nd_opt_pref64_sltime_plc = htons(sltime_plc); + memcpy(ndopt_pref64->nd_opt_pref64, &pref64->prefix, + sizeof(ndopt_pref64->nd_opt_pref64)); + p += sizeof(struct nd_opt_pref64); + } + if (len != ra_iface->datalen || memcmp(buf, ra_iface->data, len) != 0) { memcpy(ra_iface->data, buf, len); diff --git a/usr.sbin/rad/parse.y b/usr.sbin/rad/parse.y index 41b1f0da133..2d4812a2dd5 100644 --- a/usr.sbin/rad/parse.y +++ b/usr.sbin/rad/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.19 2021/10/15 15:01:28 naddy Exp $ */ +/* $OpenBSD: parse.y,v 1.20 2022/10/15 13:26:15 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser @@ -96,11 +96,15 @@ static int errors; static struct ra_iface_conf *ra_iface_conf; static struct ra_prefix_conf *ra_prefix_conf; +static struct ra_pref64_conf *ra_pref64_conf; struct ra_prefix_conf *conf_get_ra_prefix(struct in6_addr*, int); +struct ra_pref64_conf *conf_get_ra_pref64(struct in6_addr*, int); struct ra_iface_conf *conf_get_ra_iface(char *); void copy_dns_options(const struct ra_options_conf *, struct ra_options_conf *); +void copy_pref64_options(const struct ra_options_conf *, + struct ra_options_conf *); typedef struct { union { @@ -116,7 +120,7 @@ typedef struct { %token DEFAULT ROUTER HOP LIMIT MANAGED ADDRESS %token CONFIGURATION OTHER LIFETIME REACHABLE TIME RETRANS TIMER %token AUTO PREFIX VALID PREFERRED LIFETIME ONLINK AUTONOMOUS -%token ADDRESS_CONFIGURATION DNS NAMESERVER SEARCH MTU +%token ADDRESS_CONFIGURATION DNS NAMESERVER SEARCH MTU NAT64 %token STRING %token NUMBER @@ -215,6 +219,51 @@ ra_opt_block : DEFAULT ROUTER yesno { | MTU NUMBER { ra_options->mtu = $2; } + | NAT64 PREFIX STRING { + struct in6_addr addr; + int prefixlen; + char *p; + const char *errstr; + + memset(&addr, 0, sizeof(addr)); + p = strchr($3, '/'); + if (p != NULL) { + *p++ = '\0'; + prefixlen = strtonum(p, 0, 128, &errstr); + if (errstr != NULL) { + yyerror("error parsing prefix " + "\"%s/%s\"", $3, p); + free($3); + YYERROR; + } + } else + prefixlen = 96; + + switch (prefixlen) { + case 96: + case 64: + case 56: + case 48: + case 40: + case 32: + break; + default: + yyerror("invalid nat64 prefix length: %d", + prefixlen); + YYERROR; + break; + } + if(inet_pton(AF_INET6, $3, &addr) == 0) { + yyerror("error parsing prefix \"%s/%d\"", $3, + prefixlen); + free($3); + YYERROR; + } + mask_prefix(&addr, prefixlen); + ra_pref64_conf = conf_get_ra_pref64(&addr, prefixlen); + } ra_pref64_block { + ra_pref64_conf = NULL; + } | DNS dns_block ; @@ -312,6 +361,26 @@ ra_prefixoptsl : VALID LIFETIME NUMBER { ra_prefix_conf->aflag = $3; } ; + +ra_pref64_block : '{' optnl ra_pref64opts_l '}' + | '{' optnl '}' + | /* empty */ + ; + +ra_pref64opts_l : ra_pref64opts_l ra_pref64optsl nl + | ra_pref64optsl optnl + ; + +ra_pref64optsl : LIFETIME NUMBER { + if ($2 < 0 || $2 > 65528) { + yyerror("Invalid nat64 prefix lifetime: %lld", + $2); + YYERROR; + } + ra_pref64_conf->ltime = $2; + } + ; + dns_block : '{' optnl dnsopts_l '}' | '{' optnl '}' | /* empty */ @@ -446,6 +515,7 @@ lookup(char *s) {"managed", MANAGED}, {"mtu", MTU}, {"nameserver", NAMESERVER}, + {"nat64", NAT64}, {"no", NO}, {"on-link", ONLINK}, {"other", OTHER}, @@ -853,6 +923,12 @@ parse_config(char *filename) &iface->ra_options); } + if (!SIMPLEQ_EMPTY(&conf->ra_options.ra_pref64_list)) { + SIMPLEQ_FOREACH(iface, &conf->ra_iface_list, entry) + copy_pref64_options(&conf->ra_options, + &iface->ra_options); + } + return (conf); } @@ -884,6 +960,20 @@ copy_dns_options(const struct ra_options_conf *src, struct ra_options_conf *dst) } } +void +copy_pref64_options(const struct ra_options_conf *src, struct ra_options_conf + *dst) +{ + struct ra_pref64_conf *pref64, *npref64; + + SIMPLEQ_FOREACH(pref64, &src->ra_pref64_list, entry) { + if ((npref64 = calloc(1, sizeof(*npref64))) == NULL) + err(1, "%s", __func__); + memcpy(npref64, pref64, sizeof(*npref64)); + SIMPLEQ_INSERT_TAIL(&dst->ra_pref64_list, npref64, entry); + } +} + int symset(const char *nam, const char *val, int persist) { @@ -991,6 +1081,28 @@ conf_get_ra_prefix(struct in6_addr *addr, int prefixlen) return (prefix); } +struct ra_pref64_conf * +conf_get_ra_pref64(struct in6_addr *addr, int prefixlen) +{ + struct ra_pref64_conf *pref64; + + SIMPLEQ_FOREACH(pref64, &ra_options->ra_pref64_list, entry) { + if (pref64->prefixlen == prefixlen && memcmp(addr, + &pref64->prefix, sizeof(*addr)) == 0) + return (pref64); + } + + pref64 = calloc(1, sizeof(*pref64)); + if (pref64 == NULL) + err(1, "%s", __func__); + pref64->prefixlen = prefixlen; + pref64->ltime = ADV_DEFAULT_LIFETIME; + pref64->prefix = *addr; + SIMPLEQ_INSERT_TAIL(&ra_options->ra_pref64_list, pref64, entry); + + return (pref64); +} + struct ra_iface_conf * conf_get_ra_iface(char *name) { @@ -1017,6 +1129,7 @@ conf_get_ra_iface(char *name) iface->ra_options.rdnss_count = 0; SIMPLEQ_INIT(&iface->ra_options.ra_dnssl_list); iface->ra_options.dnssl_len = 0; + SIMPLEQ_INIT(&iface->ra_options.ra_pref64_list); SIMPLEQ_INSERT_TAIL(&conf->ra_iface_list, iface, entry); diff --git a/usr.sbin/rad/printconf.c b/usr.sbin/rad/printconf.c index 78099534812..f664e58de83 100644 --- a/usr.sbin/rad/printconf.c +++ b/usr.sbin/rad/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.6 2021/01/19 17:38:41 florian Exp $ */ +/* $OpenBSD: printconf.c,v 1.7 2022/10/15 13:26:15 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser @@ -48,6 +48,7 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options) { struct ra_rdnss_conf *ra_rdnss; struct ra_dnssl_conf *ra_dnssl; + struct ra_pref64_conf *pref64; char buf[INET6_ADDRSTRLEN]; printf("%sdefault router %s\n", indent, yesno(ra_options->dfr)); @@ -84,6 +85,13 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options) } printf("%s}\n", indent); } + SIMPLEQ_FOREACH(pref64, &ra_options->ra_pref64_list, entry) { + printf("%snat64 prefix %s/%d {\n", indent, inet_ntop(AF_INET6, + &pref64->prefix, buf, sizeof(buf)), pref64->prefixlen); + printf("%s\tlifetime %u\n", indent, pref64->ltime); + printf("%s}\n", indent); + } + } void diff --git a/usr.sbin/rad/rad.8 b/usr.sbin/rad/rad.8 index 8e023d9dbc6..bc728317c91 100644 --- a/usr.sbin/rad/rad.8 +++ b/usr.sbin/rad/rad.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: rad.8,v 1.6 2019/11/10 20:51:53 landry Exp $ +.\" $OpenBSD: rad.8,v 1.7 2022/10/15 13:26:15 florian Exp $ .\" .\" Copyright (c) 2018 Florian Obser .\" Copyright (c) 2016 Kenneth R Westerback @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: November 10 2019 $ +.Dd $Mdocdate: October 15 2022 $ .Dt RAD 8 .Os .Sh NAME @@ -132,6 +132,14 @@ socket used for communication with .%R RFC 8106 .%T IPv6 Router Advertisement Options for DNS Configuration .Re +.Pp +.Rs +.%A L. Colitti +.%A J. Linkova +.%D April 2020 +.%R RFC 8781 +.%T Discovering PREF64 in Router Advertisements +.Re .Sh HISTORY The .Nm diff --git a/usr.sbin/rad/rad.c b/usr.sbin/rad/rad.c index 3bb4851bdb3..713fb4a9dca 100644 --- a/usr.sbin/rad/rad.c +++ b/usr.sbin/rad/rad.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rad.c,v 1.27 2021/02/27 10:35:20 florian Exp $ */ +/* $OpenBSD: rad.c,v 1.28 2022/10/15 13:26:15 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser @@ -573,6 +573,7 @@ main_imsg_send_config(struct rad_conf *xconf) struct ra_prefix_conf *ra_prefix_conf; struct ra_rdnss_conf *ra_rdnss_conf; struct ra_dnssl_conf *ra_dnssl_conf; + struct ra_pref64_conf *pref64; /* Send fixed part of config to children. */ if (main_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) @@ -592,6 +593,14 @@ main_imsg_send_config(struct rad_conf *xconf) return (-1); } + /* send global pref64 list to children */ + SIMPLEQ_FOREACH(pref64, &xconf->ra_options.ra_pref64_list, + entry) { + if (main_sendboth(IMSG_RECONF_RA_PREF64, pref64, + sizeof(*pref64)) == -1) + return (-1); + } + /* Send the interface list to children. */ SIMPLEQ_FOREACH(ra_iface_conf, &xconf->ra_iface_list, entry) { if (main_sendboth(IMSG_RECONF_RA_IFACE, ra_iface_conf, @@ -621,6 +630,12 @@ main_imsg_send_config(struct rad_conf *xconf) sizeof(*ra_dnssl_conf)) == -1) return (-1); } + SIMPLEQ_FOREACH(pref64, + &ra_iface_conf->ra_options.ra_pref64_list, entry) { + if (main_sendboth(IMSG_RECONF_RA_PREF64, pref64, + sizeof(*pref64)) == -1) + return (-1); + } } /* Tell children the revised config is now complete. */ @@ -644,6 +659,7 @@ void free_ra_iface_conf(struct ra_iface_conf *ra_iface_conf) { struct ra_prefix_conf *prefix; + struct ra_pref64_conf *pref64; if (!ra_iface_conf) return; @@ -658,6 +674,13 @@ free_ra_iface_conf(struct ra_iface_conf *ra_iface_conf) free_dns_options(&ra_iface_conf->ra_options); + while ((pref64 = + SIMPLEQ_FIRST(&ra_iface_conf->ra_options.ra_pref64_list)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&ra_iface_conf->ra_options.ra_pref64_list, + entry); + free(pref64); + } + free(ra_iface_conf); } @@ -684,6 +707,7 @@ void merge_config(struct rad_conf *conf, struct rad_conf *xconf) { struct ra_iface_conf *ra_iface_conf; + struct ra_pref64_conf *pref64; /* Remove & discard existing interfaces. */ while ((ra_iface_conf = SIMPLEQ_FIRST(&conf->ra_iface_list)) != NULL) { @@ -692,9 +716,16 @@ merge_config(struct rad_conf *conf, struct rad_conf *xconf) } free_dns_options(&conf->ra_options); + while ((pref64 = SIMPLEQ_FIRST(&conf->ra_options.ra_pref64_list)) + != NULL) { + SIMPLEQ_REMOVE_HEAD(&conf->ra_options.ra_pref64_list, entry); + free(pref64); + } + conf->ra_options = xconf->ra_options; SIMPLEQ_INIT(&conf->ra_options.ra_rdnss_list); SIMPLEQ_INIT(&conf->ra_options.ra_dnssl_list); + SIMPLEQ_INIT(&conf->ra_options.ra_pref64_list); /* Add new interfaces. */ SIMPLEQ_CONCAT(&conf->ra_iface_list, &xconf->ra_iface_list); @@ -704,6 +735,8 @@ merge_config(struct rad_conf *conf, struct rad_conf *xconf) &xconf->ra_options.ra_rdnss_list); SIMPLEQ_CONCAT(&conf->ra_options.ra_dnssl_list, &xconf->ra_options.ra_dnssl_list); + SIMPLEQ_CONCAT(&conf->ra_options.ra_pref64_list, + &xconf->ra_options.ra_pref64_list); free(xconf); } @@ -729,6 +762,7 @@ config_new_empty(void) xconf->ra_options.rdns_lifetime = DEFAULT_RDNS_LIFETIME; SIMPLEQ_INIT(&xconf->ra_options.ra_rdnss_list); SIMPLEQ_INIT(&xconf->ra_options.ra_dnssl_list); + SIMPLEQ_INIT(&xconf->ra_options.ra_pref64_list); return (xconf); } diff --git a/usr.sbin/rad/rad.conf.5 b/usr.sbin/rad/rad.conf.5 index b3ecf8c11be..065fcd1d7db 100644 --- a/usr.sbin/rad/rad.conf.5 +++ b/usr.sbin/rad/rad.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: rad.conf.5,v 1.18 2022/09/23 19:24:08 florian Exp $ +.\" $OpenBSD: rad.conf.5,v 1.19 2022/10/15 13:26:15 florian Exp $ .\" .\" Copyright (c) 2018 Florian Obser .\" Copyright (c) 2005 Esben Norby @@ -18,7 +18,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: September 23 2022 $ +.Dd $Mdocdate: October 15 2022 $ .Dt RAD.CONF 5 .Os .Sh NAME @@ -96,6 +96,23 @@ The MTU option is used in Router Advertisement messages to ensure that all nodes on a link use the same MTU value in those cases where the link MTU is not well known. The default is 0, meaning unspecified by this router. +.It Ic nat64 prefix Ar prefix Oc Brq nat64 options +Add a PREF64 router advertisement option to communicate prefixes used +for Network Address and Protocol Translation from IPv6 to IPv4 (NAT64). +If +.Ar prefix +is specified without a prefix length, its default is 64. +.Pp +.Ic nat64 prefix +options are as follows: +.Bl -tag -width Ds +.It Ic lifetime Ar seconds +The number of seconds the nat64 prefix option is valid after receiving a router +advertisement message. +A value of zero indicates to not use the prefix anymore. +The maximum is 65528 seconds. +The default is 1800 seconds. +.El .It Ic other configuration Pq Ic yes Ns | Ns Ic no If set to yes, hosts should consult DHCPv6 for additional configuration like NTP servers or DNS name servers. @@ -128,7 +145,7 @@ This can be disabled with .Ic no auto prefix . If .Ar prefix -is specified without prefixlen, its default is 64. +is specified without a prefix length, its default is 64. .Pp .Ic prefix options are as follows: diff --git a/usr.sbin/rad/rad.h b/usr.sbin/rad/rad.h index 9b0fedd77fb..3af48dda5ad 100644 --- a/usr.sbin/rad/rad.h +++ b/usr.sbin/rad/rad.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rad.h,v 1.22 2022/03/23 15:26:08 florian Exp $ */ +/* $OpenBSD: rad.h,v 1.23 2022/10/15 13:26:15 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser @@ -55,6 +55,7 @@ enum imsg_type { IMSG_RECONF_RA_PREFIX, IMSG_RECONF_RA_RDNSS, IMSG_RECONF_RA_DNSSL, + IMSG_RECONF_RA_PREF64, IMSG_RECONF_END, IMSG_ICMP6SOCK, IMSG_OPEN_ICMP6SOCK, @@ -78,6 +79,14 @@ struct ra_dnssl_conf { char search[MAX_SEARCH]; }; +/* RFC 8781 Section 4 */ +struct ra_pref64_conf { + SIMPLEQ_ENTRY(ra_pref64_conf) entry; + struct in6_addr prefix; /* prefix */ + int prefixlen; /* prefix length */ + uint32_t ltime; /* lifetime */ +}; + /* RFC 4861 Sections 4.2 and 4.6.4 */ struct ra_options_conf { int dfr; /* is default router? */ @@ -93,6 +102,7 @@ struct ra_options_conf { int rdnss_count; SIMPLEQ_HEAD(, ra_dnssl_conf) ra_dnssl_list; int dnssl_len; + SIMPLEQ_HEAD(, ra_pref64_conf) ra_pref64_list; }; /* RFC 4861 Section 4.6.2 */ -- 2.20.1