Page MenuHomeFreeBSD

D54636.id.diff
No OneTemporary

D54636.id.diff

diff --git a/usr.sbin/rtadvctl/rtadvctl.c b/usr.sbin/rtadvctl/rtadvctl.c
--- a/usr.sbin/rtadvctl/rtadvctl.c
+++ b/usr.sbin/rtadvctl/rtadvctl.c
@@ -89,6 +89,7 @@
static int action_show_rtinfo(struct rtinfo *);
static int action_show_rdnss(void *);
static int action_show_dnssl(void *);
+static void action_show_pref64(void *);
static int csock_client_open(struct sockinfo *);
static size_t dname_labeldec(char *, size_t, const char *);
@@ -414,6 +415,7 @@
char argv_ifi_ra_timer[IFNAMSIZ + sizeof(":ifi_ra_timer=")];
char argv_rdnss[IFNAMSIZ + sizeof(":rdnss=")];
char argv_dnssl[IFNAMSIZ + sizeof(":dnssl=")];
+ char argv_pref64[IFNAMSIZ + sizeof(":pref64=")];
char ssbuf[SSBUFLEN];
struct timespec now, ts0, ts;
@@ -691,6 +693,21 @@
action_show_dnssl(cp.cp_val);
}
+ /* PREF64 information */
+ sprintf(argv_pref64, "%s:pref64=", ifi->ifi_ifname);
+ action_argv = argv_pref64;
+
+ error = action_propget(action_argv, &cp);
+ if (error)
+ continue;
+
+ len = *((uint16_t *)cp.cp_val);
+
+ if (len > 0) {
+ printf("\tPREF64:\n");
+ action_show_pref64(cp.cp_val);
+ }
+
if (vflag < LOG_NOTICE)
continue;
@@ -896,6 +913,35 @@
return (0);
}
+static void
+action_show_pref64(void *msg)
+{
+ struct pref64 *prf64;
+ uint16_t *prf64_cnt;
+ char ntopbuf[INET6_ADDRSTRLEN];
+ char ssbuf[SSBUFLEN];
+ char *p;
+ int i;
+ uint16_t prf64len;
+
+ p = msg;
+ prf64_cnt = (uint16_t *)p;
+ p += sizeof(*prf64_cnt);
+
+ for (i = 0; i < *prf64_cnt; i++) {
+ prf64 = (struct pref64 *)p;
+
+ /* RFC 8781 Section 4: Map PLC values to prefix lengths */
+ prf64len = (prf64->p64_plc == 0) ? 96 : 72 - (8 * prf64->p64_plc);
+ printf("\t %s/%d (ltime: %s)\n",
+ inet_ntop(AF_INET6, &prf64->p64_prefix,
+ ntopbuf, sizeof(ntopbuf)),
+ prf64len, sec2str(prf64->p64_sl, ssbuf));
+
+ p += sizeof(*prf64);
+ }
+}
+
/* Decode domain name label encoding in RFC 1035 Section 3.1 */
static size_t
dname_labeldec(char *dst, size_t dlen, const char *src)
diff --git a/usr.sbin/rtadvd/config.h b/usr.sbin/rtadvd/config.h
--- a/usr.sbin/rtadvd/config.h
+++ b/usr.sbin/rtadvd/config.h
@@ -52,3 +52,4 @@
#define MAXROUTE 100
#define MAXRDNSSENT 100
#define MAXDNSSLENT 100
+#define MAXPREF64 100
diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c
--- a/usr.sbin/rtadvd/config.c
+++ b/usr.sbin/rtadvd/config.c
@@ -291,6 +291,7 @@
struct rdnss *rdn;
struct rdnss_addr *rdna;
struct dnssl *dns;
+ struct pref64 *prf64;
struct rtinfo *rti;
syslog(LOG_DEBUG, "<%s>: enter", __func__);
@@ -325,6 +326,10 @@
TAILQ_REMOVE(&rai->rai_route, rti, rti_next);
free(rti);
}
+ while ((prf64 = TAILQ_FIRST(&rai->rai_pref64)) != NULL) {
+ TAILQ_REMOVE(&rai->rai_pref64, prf64, p64_next);
+ free(prf64);
+ }
free(rai);
syslog(LOG_DEBUG, "<%s>: leave", __func__);
@@ -369,6 +374,7 @@
TAILQ_INIT(&rai->rai_route);
TAILQ_INIT(&rai->rai_rdnss);
TAILQ_INIT(&rai->rai_dnssl);
+ TAILQ_INIT(&rai->rai_pref64);
TAILQ_INIT(&rai->rai_soliciter);
rai->rai_ifinfo = ifi;
@@ -916,52 +922,62 @@
/*
* handle pref64
*/
- rai->rai_pref64.p64_enabled = false;
+ for (i = -1; i < MAXPREF64 ; i++) {
+ struct pref64 *prf64;
+
+ makeentry(entbuf, sizeof(entbuf), i, "pref64");
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL)
+ continue;
+ ELM_MALLOC(prf64, exit(1));
- if ((addr = (char *)agetstr("pref64", &bp))) {
- if (inet_pton(AF_INET6, addr, &rai->rai_pref64.p64_prefix) != 1) {
+ if (inet_pton(AF_INET6, addr, &prf64->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;
- }
+ goto getconfig_free_prf64;
+ }
- /* 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;
+ makeentry(entbuf, sizeof(entbuf), i, "pref64len");
+ MAYHAVE(val64, entbuf, 96);
+ switch (val64) {
+ case 96:
+ prf64->p64_plc = 0;
+ break;
+ case 64:
+ prf64->p64_plc = 1;
+ break;
+ case 56:
+ prf64->p64_plc = 2;
+ break;
+ case 48:
+ prf64->p64_plc = 3;
+ break;
+ case 40:
+ prf64->p64_plc = 4;
+ break;
+ case 32:
+ prf64->p64_plc = 5;
+ break;
+ default:
+ syslog(LOG_ERR, "prefix length %" PRIi64
+ "on %s is invalid; disabling PREF64",
+ val64, ifi->ifi_ifname);
+ goto getconfig_free_prf64;
}
+
+ makeentry(entbuf, sizeof(entbuf), i, "pref64lifetime");
+ MAYHAVE(val64, entbuf, (rai->rai_lifetime * 3));
+ /* This logic is from RFC 8781 section 4.1. */
+ if (val64 > 65528)
+ val64 = 65528;
+ val64 = (val64 + 7) / 8;
+ prf64->p64_sl = (uint16_t)val64;
+
+ /* link into chain */
+ TAILQ_INSERT_TAIL(&rai->rai_pref64, prf64, p64_next);
+ continue;
+getconfig_free_prf64:
+ free(prf64);
}
/* construct the sending packet */
@@ -1386,6 +1402,7 @@
struct rdnss *rdn;
struct nd_opt_dnssl *ndopt_dnssl;
struct dnssl *dns;
+ struct pref64 *prf64;
struct nd_opt_pref64 *ndopt_pref64;
size_t len;
struct prefix *pfx;
@@ -1408,8 +1425,6 @@
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) +
@@ -1436,6 +1451,9 @@
packlen += len;
}
+ TAILQ_FOREACH(prf64, &rai->rai_pref64, p64_next)
+ packlen += sizeof(struct nd_opt_pref64);
+
/* allocate memory for the packet */
if ((buf = malloc(packlen)) == NULL) {
syslog(LOG_ERR,
@@ -1490,19 +1508,6 @@
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;
@@ -1616,4 +1621,17 @@
syslog(LOG_DEBUG, "<%s>: nd_opt_dnssl_len = %d", __func__,
ndopt_dnssl->nd_opt_dnssl_len);
}
+
+ TAILQ_FOREACH(prf64, &rai->rai_pref64, p64_next) {
+ 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(prf64->p64_sl << 3)) |
+ htons((prf64->p64_plc & 0x7));
+ memcpy(&ndopt_pref64->nd_opt_prefix[0],
+ &prf64->p64_prefix,
+ sizeof(ndopt_pref64->nd_opt_prefix));
+ buf += sizeof(struct nd_opt_pref64);
+ }
}
diff --git a/usr.sbin/rtadvd/control_server.c b/usr.sbin/rtadvd/control_server.c
--- a/usr.sbin/rtadvd/control_server.c
+++ b/usr.sbin/rtadvd/control_server.c
@@ -80,6 +80,7 @@
static int cm_getprop_pfx(struct ctrl_msg_pl *);
static int cm_getprop_rdnss(struct ctrl_msg_pl *);
static int cm_getprop_dnssl(struct ctrl_msg_pl *);
+static int cm_getprop_pref64(struct ctrl_msg_pl *);
static int cm_getprop_rti(struct ctrl_msg_pl *);
static int cm_setprop_reload(struct ctrl_msg_pl *);
@@ -101,6 +102,7 @@
DEF_PL_HANDLER(pfx),
DEF_PL_HANDLER(rdnss),
DEF_PL_HANDLER(dnssl),
+ DEF_PL_HANDLER(pref64),
};
static int
@@ -516,6 +518,60 @@
return (0);
}
+static int
+cm_getprop_pref64(struct ctrl_msg_pl *cp)
+{
+ struct ifinfo *ifi;
+ struct rainfo *rai;
+ struct pref64 *prf64;
+ char *p;
+ size_t len;
+ uint16_t *prf64_cnt;
+
+ syslog(LOG_DEBUG, "<%s> enter", __func__);
+
+ len = 0;
+ TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
+ if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
+ break;
+ }
+ if (ifi == NULL) {
+ syslog(LOG_ERR, "<%s> %s not found", __func__,
+ cp->cp_ifname);
+ return (1);
+ }
+ if (ifi->ifi_rainfo == NULL) {
+ syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
+ cp->cp_ifname);
+ return (1);
+ }
+ rai = ifi->ifi_rainfo;
+
+ len = sizeof(*prf64_cnt);
+ TAILQ_FOREACH(prf64, &rai->rai_pref64, p64_next)
+ len += sizeof(*prf64);
+
+ syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
+
+ p = malloc(len);
+ if (p == NULL)
+ exit(1);
+ memset(p, 0, len);
+ cp->cp_val = p;
+
+ prf64_cnt = (uint16_t *)cp->cp_val;
+ p += sizeof(*prf64_cnt);
+ TAILQ_FOREACH(prf64, &rai->rai_pref64, p64_next) {
+ (*prf64_cnt)++;
+ memcpy(p, prf64, sizeof(*prf64));
+ p += sizeof(*prf64);
+ }
+ cp->cp_val_len = p - cp->cp_val;
+
+ return (0);
+}
+
+
int
cm_getprop(struct ctrl_msg_pl *cp)
{
diff --git a/usr.sbin/rtadvd/rtadvd.h b/usr.sbin/rtadvd/rtadvd.h
--- a/usr.sbin/rtadvd/rtadvd.h
+++ b/usr.sbin/rtadvd/rtadvd.h
@@ -152,7 +152,6 @@
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;
@@ -227,7 +226,7 @@
/* actual RA packet data and its length */
size_t rai_ra_datalen;
char *rai_ra_data;
- struct pref64 rai_pref64; /* PREF64 option */
+ TAILQ_HEAD(, pref64) rai_pref64; /* PREF64 option */
/* info about soliciter */
TAILQ_HEAD(, soliciter) rai_soliciter; /* recent solication source */
diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c
--- a/usr.sbin/rtadvd/rtadvd.c
+++ b/usr.sbin/rtadvd/rtadvd.c
@@ -137,6 +137,7 @@
#define NDOPT_FLAG_MTU (1 << 4)
#define NDOPT_FLAG_RDNSS (1 << 5)
#define NDOPT_FLAG_DNSSL (1 << 6)
+#define NDOPT_FLAG_PREF64 (1 << 7)
static uint32_t ndopt_flags[] = {
[ND_OPT_SOURCE_LINKADDR] = NDOPT_FLAG_SRCLINKADDR,
@@ -146,6 +147,7 @@
[ND_OPT_MTU] = NDOPT_FLAG_MTU,
[ND_OPT_RDNSS] = NDOPT_FLAG_RDNSS,
[ND_OPT_DNSSL] = NDOPT_FLAG_DNSSL,
+ [ND_OPT_PREF64] = NDOPT_FLAG_PREF64,
};
static void rtadvd_shutdown(void);
@@ -1083,7 +1085,7 @@
error = nd6_options((struct nd_opt_hdr *)(nra + 1),
len - sizeof(struct nd_router_advert), &ndopts,
NDOPT_FLAG_SRCLINKADDR | NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU |
- NDOPT_FLAG_RDNSS | NDOPT_FLAG_DNSSL);
+ NDOPT_FLAG_RDNSS | NDOPT_FLAG_DNSSL | NDOPT_FLAG_PREF64);
if (error) {
syslog(LOG_INFO,
"<%s> ND option check failed for an RA from %s on %s",
@@ -1428,7 +1430,8 @@
if (hdr->nd_opt_type > ND_OPT_MTU &&
hdr->nd_opt_type != ND_OPT_RDNSS &&
- hdr->nd_opt_type != ND_OPT_DNSSL) {
+ hdr->nd_opt_type != ND_OPT_DNSSL &&
+ hdr->nd_opt_type != ND_OPT_PREF64) {
syslog(LOG_INFO, "<%s> unknown ND option(type %d)",
__func__, hdr->nd_opt_type);
continue;
@@ -1473,6 +1476,7 @@
case ND_OPT_REDIRECTED_HEADER:
case ND_OPT_RDNSS:
case ND_OPT_DNSSL:
+ case ND_OPT_PREF64:
break; /* we don't care about these options */
case ND_OPT_SOURCE_LINKADDR:
case ND_OPT_MTU:
diff --git a/usr.sbin/rtadvd/rtadvd.conf.5 b/usr.sbin/rtadvd/rtadvd.conf.5
--- a/usr.sbin/rtadvd/rtadvd.conf.5
+++ b/usr.sbin/rtadvd/rtadvd.conf.5
@@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 4, 2011
+.Dd January 14, 2026
.Dt RTADVD.CONF 5
.Os
.Sh NAME
@@ -435,6 +435,21 @@
.Bl -tag -width indent
.It Cm \&pref64
(str) The prefix to advertise in the PREF64 option.
+Multiple PREF64 prefixes can be specified by seperating entries using
+.Cm pref64 ,
+.Cm pref640 ,
+.Cm pref641 ,
+.Cm pref642 ...
+options with corresponding
+.Cm pref64len ,
+.Cm pref64len0 ,
+.Cm pref64len1 ,
+.Cm pref64len2 ...
+entries.
+This is also true for the
+.Cm pref64lifetime
+option.
+Note that the maximum number of servers depends on the receiver side.
.It Cm \&pref64len
(num) The length of the PREF64 prefix.
This must be 96, 64, 56, 48, 40, or 32.
@@ -484,13 +499,15 @@
.Pp
The following example configures the
.Li wlan0
-interface and adds two DNS servers and a DNS domain search options
+interface and adds two DNS servers, a DNS domain search,
+and a PREF64 prefix,
using the default option lifetime values.
.Bd -literal -offset indent
wlan0:\\
:addr="2001:db8:ffff:1000::":prefixlen#64:\\
:rdnss="2001:db8:ffff::10,2001:db8:ffff::2:43":\\
- :dnssl="example.com":
+ :dnssl="example.com":\\
+ :pref64="64:ff9b::":
.Ed
.Pp
The following example presents the default values in an explicit manner.

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 24, 11:04 AM (14 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27896220
Default Alt Text
D54636.id.diff (12 KB)

Event Timeline