Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142774993
D54636.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D54636.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D54636: rtadvd: add multi pref64 support
Attached
Detach File
Event Timeline
Log In to Comment