summaryrefslogtreecommitdiffstats
path: root/usr.sbin/rtadvd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/rtadvd')
-rw-r--r--usr.sbin/rtadvd/Makefile2
-rw-r--r--usr.sbin/rtadvd/config.c232
-rw-r--r--usr.sbin/rtadvd/config.h2
-rw-r--r--usr.sbin/rtadvd/dump.c64
-rw-r--r--usr.sbin/rtadvd/if.c1
-rw-r--r--usr.sbin/rtadvd/rrenum.c1
-rw-r--r--usr.sbin/rtadvd/rtadvd.c69
-rw-r--r--usr.sbin/rtadvd/rtadvd.conf3
-rw-r--r--usr.sbin/rtadvd/rtadvd.conf.585
-rw-r--r--usr.sbin/rtadvd/rtadvd.h42
10 files changed, 482 insertions, 19 deletions
diff --git a/usr.sbin/rtadvd/Makefile b/usr.sbin/rtadvd/Makefile
index 9dbfc99..29c26fe 100644
--- a/usr.sbin/rtadvd/Makefile
+++ b/usr.sbin/rtadvd/Makefile
@@ -21,7 +21,7 @@ SRCS= rtadvd.c rrenum.c advcap.c if.c config.c timer.c dump.c
DPADD= ${LIBUTIL}
LDADD= -lutil
-CFLAGS+= -DHAVE_ARC4RANDOM -DHAVE_POLL_H -DROUTEINFO
+CFLAGS+= -DHAVE_ARC4RANDOM -DHAVE_POLL_H -DROUTEINFO -DRDNSS
WARNS?= 1
diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c
index 5eadcc5..086a23c 100644
--- a/usr.sbin/rtadvd/config.c
+++ b/usr.sbin/rtadvd/config.c
@@ -53,6 +53,7 @@
#include <stdio.h>
#include <syslog.h>
#include <errno.h>
+#include <netdb.h>
#include <string.h>
#include <search.h>
#include <stdlib.h>
@@ -65,6 +66,11 @@
#include "if.h"
#include "config.h"
+/* label of tcapcode + number + domain name + zero octet */
+static char entbuf[10 + 3 + NI_MAXHOST + 1];
+static char oentbuf[10 + 3 + NI_MAXHOST + 1];
+static char abuf[DNAME_LABELENC_MAXLEN];
+
static time_t prefix_timo = (60 * 120); /* 2 hours.
* XXX: should be configurable. */
extern struct rainfo *ralist;
@@ -72,6 +78,32 @@ extern struct rainfo *ralist;
static struct rtadvd_timer *prefix_timeout(void *);
static void makeentry(char *, size_t, int, char *);
static int getinet6sysctl(int);
+static size_t dname_labelenc(char *, const char *);
+
+/* Encode domain name label encoding in RFC 1035 Section 3.1 */
+static size_t
+dname_labelenc(char *dst, const char *src)
+{
+ char *dst_origin;
+ size_t len;
+
+ dst_origin = dst;
+ len = strlen(src);
+
+ /* Length fields per 63 octets + '\0' (<= DNAME_LABELENC_MAXLEN) */
+ memset(dst, 0, len + len / 64 + 1 + 1);
+
+ syslog(LOG_DEBUG, "<%s> labelenc = %s", __func__, src);
+ while ((len = strlen(src)) != 0) {
+ /* Put a length field with 63 octet limitation first. */
+ *dst++ = len = MIN(63, len + 1);
+ memcpy(dst, src, len);
+ dst += len;
+ src += len;
+ }
+ syslog(LOG_DEBUG, "<%s> labellen = %d", __func__, dst - dst_origin);
+ return (dst - dst_origin);
+}
void
getconfig(intface)
@@ -123,6 +155,10 @@ getconfig(intface)
#ifdef ROUTEINFO
tmp->route.next = tmp->route.prev = &tmp->route;
#endif
+#ifdef RDNSS
+ TAILQ_INIT(&tmp->rdnss);
+ TAILQ_INIT(&tmp->dnssl);
+#endif
/* check if we are allowed to forward packets (if not determined) */
if (forwarding < 0) {
@@ -276,7 +312,6 @@ getconfig(intface)
tmp->pfxs = 0;
for (i = -1; i < MAXPREFIX; i++) {
struct prefix *pfx;
- char entbuf[256];
makeentry(entbuf, sizeof(entbuf), i, "addr");
addr = (char *)agetstr(entbuf, &bp);
@@ -442,7 +477,6 @@ getconfig(intface)
tmp->routes = 0;
for (i = -1; i < MAXROUTE; i++) {
struct rtinfo *rti;
- char entbuf[256], oentbuf[256];
makeentry(entbuf, sizeof(entbuf), i, "rtprefix");
addr = (char *)agetstr(entbuf, &bp);
@@ -585,6 +619,118 @@ getconfig(intface)
}
#endif
+#ifdef RDNSS
+ /* DNS server and DNS search list information */
+ for (i = -1; i < MAXRDNSSENT ; i++) {
+ struct rdnss *rdn;
+ struct rdnss_addr *rdna;
+ char *ap;
+ int c;
+
+ makeentry(entbuf, sizeof(entbuf), i, "rdnss");
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL)
+ break;
+ rdn = malloc(sizeof(*rdn));
+ if (rdn == NULL) {
+ syslog(LOG_ERR,
+ "<%s> can't get allocate buffer for rdnss entry",
+ __func__);
+ exit(1);
+ }
+ memset(rdn, 0, sizeof(*rdn));
+ TAILQ_INIT(&rdn->rd_list);
+
+ for (ap = addr; ap - addr < strlen(addr); ap += c+1) {
+ c = strcspn(ap, ",");
+ strncpy(abuf, ap, c);
+ abuf[c] = '\0';
+ rdna = malloc(sizeof(*rdna));
+ if (rdna == NULL) {
+ syslog(LOG_ERR,
+ "<%s> can't get allocate buffer for "
+ "rdnss_addr entry",
+ __func__);
+ exit(1);
+ }
+ memset(rdna, 0, sizeof(*rdna));
+ if (inet_pton(AF_INET6, abuf, &rdna->ra_dns) != 1) {
+ syslog(LOG_ERR, "<%s> inet_pton failed for %s",
+ __func__, abuf);
+ exit(1);
+ }
+ TAILQ_INSERT_TAIL(&rdn->rd_list, rdna, ra_next);
+ }
+
+ makeentry(entbuf, sizeof(entbuf), i, "rdnssltime");
+ MAYHAVE(val, entbuf, (tmp->maxinterval * 3 / 2));
+ if (val < tmp->maxinterval || val > tmp->maxinterval * 2) {
+ syslog(LOG_ERR, "%s (%ld) on %s is invalid "
+ "(must be between %d and %d)",
+ entbuf, val, intface, tmp->maxinterval,
+ tmp->maxinterval * 2);
+ exit(1);
+ }
+ rdn->rd_ltime = val;
+
+ /* link into chain */
+ insque(rdn, &tmp->rdnss);
+ }
+
+ for (i = -1; i < MAXDNSSLENT ; i++) {
+ struct dnssl *dns;
+ struct dnssl_addr *dnsa;
+ char *ap;
+ int c;
+ char *p, *q;
+
+ makeentry(entbuf, sizeof(entbuf), i, "dnssl");
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL)
+ break;
+ dns = malloc(sizeof(*dns));
+ if (dns == NULL) {
+ syslog(LOG_ERR,
+ "<%s> can't get allocate buffer for dnssl entry",
+ __func__);
+ exit(1);
+ }
+ memset(dns, 0, sizeof(*dns));
+ TAILQ_INIT(&dns->dn_list);
+
+ for (ap = addr; ap - addr < strlen(addr); ap += c+1) {
+ c = strcspn(ap, ",");
+ strncpy(abuf, ap, c);
+ abuf[c] = '\0';
+ dnsa = malloc(sizeof(struct dnssl_addr));
+ if (dnsa == NULL) {
+ syslog(LOG_ERR,
+ "<%s> can't get allocate buffer for "
+ "dnssl_addr entry", __func__);
+ exit(1);
+ }
+ memset(dnsa, 0, sizeof(*dnsa));
+ dnsa->da_len = dname_labelenc(dnsa->da_dom, abuf);
+ syslog(LOG_DEBUG, "<%s>: dnsa->da_len = %d", __func__,
+ dnsa->da_len);
+ TAILQ_INSERT_TAIL(&dns->dn_list, dnsa, da_next);
+ }
+
+ makeentry(entbuf, sizeof(entbuf), i, "dnsslltime");
+ MAYHAVE(val, entbuf, (tmp->maxinterval * 3 / 2));
+ if (val < tmp->maxinterval || val > tmp->maxinterval * 2) {
+ syslog(LOG_ERR, "%s (%ld) on %s is invalid "
+ "(must be between %d and %d)",
+ entbuf, val, intface, tmp->maxinterval,
+ tmp->maxinterval * 2);
+ exit(1);
+ }
+ dns->dn_ltime = val;
+
+ /* link into chain */
+ insque(dns, &tmp->dnssl);
+ }
+#endif
/* okey */
tmp->next = ralist;
ralist = tmp;
@@ -913,6 +1059,13 @@ make_packet(struct rainfo *rainfo)
struct nd_opt_route_info *ndopt_rti;
struct rtinfo *rti;
#endif
+#ifdef RDNSS
+ struct nd_opt_rdnss *ndopt_rdnss;
+ struct rdnss *rdn;
+ struct nd_opt_dnssl *ndopt_dnssl;
+ struct dnssl *dns;
+ size_t len;
+#endif
struct prefix *pfx;
/* calculate total length */
@@ -936,6 +1089,29 @@ make_packet(struct rainfo *rainfo)
packlen += sizeof(struct nd_opt_route_info) +
((rti->prefixlen + 0x3f) >> 6) * 8;
#endif
+#ifdef RDNSS
+ TAILQ_FOREACH(rdn, &rainfo->rdnss, rd_next) {
+ struct rdnss_addr *rdna;
+
+ packlen += sizeof(struct nd_opt_rdnss);
+ TAILQ_FOREACH(rdna, &rdn->rd_list, ra_next)
+ packlen += sizeof(rdna->ra_dns);
+ }
+ TAILQ_FOREACH(dns, &rainfo->dnssl, dn_next) {
+ struct dnssl_addr *dnsa;
+
+ packlen += sizeof(struct nd_opt_dnssl);
+ len = 0;
+ TAILQ_FOREACH(dnsa, &dns->dn_list, da_next)
+ len += dnsa->da_len;
+
+ /* A zero octet and 8 octet boundary */
+ len++;
+ len += 8 - (len % 8);
+
+ packlen += len;
+ }
+#endif
/* allocate memory for the packet */
if ((buf = malloc(packlen)) == NULL) {
@@ -944,6 +1120,7 @@ make_packet(struct rainfo *rainfo)
__func__);
exit(1);
}
+ memset(buf, 0, packlen);
if (rainfo->ra_data) {
/* free the previous packet */
free(rainfo->ra_data);
@@ -1056,6 +1233,57 @@ make_packet(struct rainfo *rainfo)
}
#endif
+#ifdef RDNSS
+ TAILQ_FOREACH(rdn, &rainfo->rdnss, rd_next) {
+ struct rdnss_addr *rdna;
+
+ ndopt_rdnss = (struct nd_opt_rdnss *)buf;
+ ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS;
+ ndopt_rdnss->nd_opt_rdnss_len = 0;
+ ndopt_rdnss->nd_opt_rdnss_reserved = 0;
+ ndopt_rdnss->nd_opt_rdnss_lifetime = htonl(rdn->rd_ltime);
+ buf += sizeof(struct nd_opt_rdnss);
+
+ TAILQ_FOREACH(rdna, &rdn->rd_list, ra_next) {
+ memcpy(buf, &rdna->ra_dns, sizeof(rdna->ra_dns));
+ buf += sizeof(rdna->ra_dns);
+ }
+ /* Length field should be in 8 octets */
+ ndopt_rdnss->nd_opt_rdnss_len = (buf - (char *)ndopt_rdnss) / 8;
+
+ syslog(LOG_DEBUG, "<%s>: nd_opt_dnss_len = %d", __func__,
+ ndopt_rdnss->nd_opt_rdnss_len);
+ }
+ TAILQ_FOREACH(dns, &rainfo->dnssl, dn_next) {
+ struct dnssl_addr *dnsa;
+ size_t len = 0;
+
+ ndopt_dnssl = (struct nd_opt_dnssl *)buf;
+ ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL;
+ ndopt_dnssl->nd_opt_dnssl_len = 0;
+ ndopt_dnssl->nd_opt_dnssl_reserved = 0;
+ ndopt_dnssl->nd_opt_dnssl_lifetime = htonl(dns->dn_ltime);
+ buf += sizeof(*ndopt_dnssl);
+
+ TAILQ_FOREACH(dnsa, &dns->dn_list, da_next) {
+ memcpy(buf, dnsa->da_dom, dnsa->da_len);
+ buf += dnsa->da_len;
+ }
+
+ /* A zero octet after encoded DNS server list. */
+ *buf++ = '\0';
+
+ /* Padding to next 8 octets boundary */
+ len = buf - (char *)ndopt_dnssl;
+ len += 8 - (len % 8);
+
+ /* Length field must be in 8 octets */
+ ndopt_dnssl->nd_opt_dnssl_len = len / 8;
+
+ syslog(LOG_DEBUG, "<%s>: nd_opt_dnssl_len = %d", __func__,
+ ndopt_dnssl->nd_opt_dnssl_len);
+ }
+#endif
return;
}
diff --git a/usr.sbin/rtadvd/config.h b/usr.sbin/rtadvd/config.h
index 2d02b8a..3fa14f9 100644
--- a/usr.sbin/rtadvd/config.h
+++ b/usr.sbin/rtadvd/config.h
@@ -45,3 +45,5 @@ extern void get_prefix(struct rainfo *);
*/
#define MAXPREFIX 100
#define MAXROUTE 100
+#define MAXRDNSSENT 100
+#define MAXDNSSLENT 100
diff --git a/usr.sbin/rtadvd/dump.c b/usr.sbin/rtadvd/dump.c
index d37f5db..a94a62e 100644
--- a/usr.sbin/rtadvd/dump.c
+++ b/usr.sbin/rtadvd/dump.c
@@ -45,6 +45,7 @@
#include <arpa/inet.h>
+#include <netdb.h>
#include <time.h>
#include <stdio.h>
#include <stdarg.h>
@@ -63,6 +64,7 @@ extern struct rainfo *ralist;
static char *ether_str(struct sockaddr_dl *);
static void if_dump(void);
+static size_t dname_labeldec(char *, const char *);
static char *rtpref_str[] = {
"medium", /* 00 */
@@ -96,6 +98,10 @@ if_dump()
#ifdef ROUTEINFO
struct rtinfo *rti;
#endif
+#ifdef RDNSS
+ struct rdnss *rdn;
+ struct dnssl *dns;
+#endif
char prefixbuf[INET6_ADDRSTRLEN];
int first;
struct timeval now;
@@ -230,6 +236,44 @@ if_dump()
fprintf(fp, ")\n");
}
#endif
+#ifdef RDNSS
+ TAILQ_FOREACH(rdn, &rai->rdnss, rd_next) {
+ struct rdnss_addr *rdna;
+
+ if (rdn == TAILQ_FIRST(&rai->rdnss))
+ fprintf(fp, " Recursive DNS servers:\n"
+ " Lifetime\tServers\n");
+
+ fprintf(fp, " % 8u\t", rdn->rd_ltime);
+ TAILQ_FOREACH(rdna, &rdn->rd_list, ra_next) {
+ inet_ntop(AF_INET6, &rdna->ra_dns,
+ prefixbuf, sizeof(prefixbuf));
+
+ if (rdna != TAILQ_FIRST(&rdn->rd_list))
+ fprintf(fp, " \t");
+ fprintf(fp, "%s\n", prefixbuf);
+ }
+ fprintf(fp, "\n");
+ }
+
+ TAILQ_FOREACH(dns, &rai->dnssl, dn_next) {
+ struct dnssl_addr *dnsa;
+ char buf[NI_MAXHOST + 1];
+
+ if (dns == TAILQ_FIRST(&rai->dnssl))
+ fprintf(fp, " DNS search list:\n"
+ " Lifetime\tDomains\n");
+
+ fprintf(fp, " % 8u\t", dns->dn_ltime);
+ TAILQ_FOREACH(dnsa, &dns->dn_list, da_next) {
+ dname_labeldec(buf, dnsa->da_dom);
+ if (dnsa != TAILQ_FIRST(&dns->dn_list))
+ fprintf(fp, " \t");
+ fprintf(fp, "%s(%d)\n", buf, dnsa->da_len);
+ }
+ fprintf(fp, "\n");
+ }
+#endif
}
}
@@ -250,3 +294,23 @@ rtadvd_dump_file(dumpfile)
fclose(fp);
}
+
+/* Decode domain name label encoding in RFC 1035 Section 3.1 */
+static size_t
+dname_labeldec(char *dst, const char *src)
+{
+ size_t len;
+ const char *src_origin;
+
+ src_origin = src;
+ while (*src && (len = (uint8_t)(*src++) & 0x3f) != 0) {
+ syslog(LOG_DEBUG, "<%s> labellen = %d", __func__, len);
+ memcpy(dst, src, len);
+ src += len;
+ dst += len;
+ if (*(dst - 1) == '\0')
+ break;
+ }
+
+ return (src - src_origin);
+}
diff --git a/usr.sbin/rtadvd/if.c b/usr.sbin/rtadvd/if.c
index d8ed088..6cd8dd8 100644
--- a/usr.sbin/rtadvd/if.c
+++ b/usr.sbin/rtadvd/if.c
@@ -44,6 +44,7 @@
#include <netinet/icmp6.h>
#include <unistd.h>
#include <errno.h>
+#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
diff --git a/usr.sbin/rtadvd/rrenum.c b/usr.sbin/rtadvd/rrenum.c
index aafa0f9..b2ea902 100644
--- a/usr.sbin/rtadvd/rrenum.c
+++ b/usr.sbin/rtadvd/rrenum.c
@@ -45,6 +45,7 @@
#include <arpa/inet.h>
#include <errno.h>
+#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c
index 02e3dc7..3652e20 100644
--- a/usr.sbin/rtadvd/rtadvd.c
+++ b/usr.sbin/rtadvd/rtadvd.c
@@ -37,6 +37,7 @@
#include <sys/queue.h>
#include <net/if.h>
+#include <net/if_media.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
@@ -52,6 +53,7 @@
#include <err.h>
#include <errno.h>
#include <libutil.h>
+#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
@@ -115,15 +117,26 @@ union nd_opts {
#define nd_opts_mtu nd_opt_each.mtu
#define nd_opts_list nd_opt_each.list
-#define NDOPT_FLAG_SRCLINKADDR 0x1
-#define NDOPT_FLAG_TGTLINKADDR 0x2
-#define NDOPT_FLAG_PREFIXINFO 0x4
-#define NDOPT_FLAG_RDHDR 0x8
-#define NDOPT_FLAG_MTU 0x10
+#define NDOPT_FLAG_SRCLINKADDR (1 << 0)
+#define NDOPT_FLAG_TGTLINKADDR (1 << 1)
+#define NDOPT_FLAG_PREFIXINFO (1 << 2)
+#define NDOPT_FLAG_RDHDR (1 << 3)
+#define NDOPT_FLAG_MTU (1 << 4)
+#ifdef RDNSS
+#define NDOPT_FLAG_RDNSS (1 << 5)
+#define NDOPT_FLAG_DNSSL (1 << 6)
+#endif
u_int32_t ndopt_flags[] = {
- 0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR,
- NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU,
+ [ND_OPT_SOURCE_LINKADDR] = NDOPT_FLAG_SRCLINKADDR,
+ [ND_OPT_TARGET_LINKADDR] = NDOPT_FLAG_TGTLINKADDR,
+ [ND_OPT_PREFIX_INFORMATION] = NDOPT_FLAG_PREFIXINFO,
+ [ND_OPT_REDIRECTED_HEADER] = NDOPT_FLAG_RDHDR,
+ [ND_OPT_MTU] = NDOPT_FLAG_MTU,
+#ifdef RDNSS
+ [ND_OPT_RDNSS] = NDOPT_FLAG_RDNSS,
+ [ND_OPT_DNSSL] = NDOPT_FLAG_DNSSL,
+#endif
};
int main(int, char *[]);
@@ -376,6 +389,10 @@ static void
die()
{
struct rainfo *ra;
+#ifdef RDNSS
+ struct rdnss *rdn;
+ struct dnssl *dns;
+#endif
int i;
const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS;
@@ -386,6 +403,12 @@ die()
for (ra = ralist; ra; ra = ra->next) {
ra->lifetime = 0;
+#ifdef RDNSS
+ TAILQ_FOREACH(rdn, &ra->rdnss, rd_next)
+ rdn->rd_ltime = 0;
+ TAILQ_FOREACH(dns, &ra->dnssl, dn_next)
+ dns->dn_ltime = 0;
+#endif
make_packet(ra);
}
for (i = 0; i < retrans; i++) {
@@ -961,7 +984,11 @@ ra_input(int len, struct nd_router_advert *ra,
if (nd6_options((struct nd_opt_hdr *)(ra + 1),
len - sizeof(struct nd_router_advert),
&ndopts, NDOPT_FLAG_SRCLINKADDR |
- NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
+ NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU
+#ifdef RDNSS
+ | NDOPT_FLAG_RDNSS | NDOPT_FLAG_DNSSL
+#endif
+ )) {
syslog(LOG_INFO,
"<%s> ND option check failed for an RA from %s on %s",
__func__,
@@ -1300,7 +1327,12 @@ nd6_options(struct nd_opt_hdr *hdr, int limit,
goto bad;
}
- if (hdr->nd_opt_type > ND_OPT_MTU) {
+ if (hdr->nd_opt_type > ND_OPT_MTU
+#ifdef RDNSS
+ && hdr->nd_opt_type != ND_OPT_RDNSS &&
+ hdr->nd_opt_type != ND_OPT_DNSSL
+#endif
+ ) {
syslog(LOG_INFO, "<%s> unknown ND option(type %d)",
__func__, hdr->nd_opt_type);
continue;
@@ -1317,9 +1349,18 @@ nd6_options(struct nd_opt_hdr *hdr, int limit,
* options.
*/
if ((hdr->nd_opt_type == ND_OPT_MTU &&
- (optlen != sizeof(struct nd_opt_mtu))) ||
- ((hdr->nd_opt_type == ND_OPT_PREFIX_INFORMATION &&
- optlen != sizeof(struct nd_opt_prefix_info)))) {
+ optlen != sizeof(struct nd_opt_mtu)) ||
+#ifdef RDNSS
+ (hdr->nd_opt_type == ND_OPT_RDNSS &&
+ (optlen < 24 ||
+ (optlen - sizeof(struct nd_opt_rdnss)) % 16 != 0)) ||
+ (hdr->nd_opt_type == ND_OPT_DNSSL &&
+ (optlen < 16 ||
+ (optlen - sizeof(struct nd_opt_dnssl)) % 8 != 0)) ||
+#endif
+ (hdr->nd_opt_type == ND_OPT_PREFIX_INFORMATION &&
+ optlen != sizeof(struct nd_opt_prefix_info))
+ ) {
syslog(LOG_INFO, "<%s> invalid option length",
__func__);
continue;
@@ -1328,6 +1369,10 @@ nd6_options(struct nd_opt_hdr *hdr, int limit,
switch (hdr->nd_opt_type) {
case ND_OPT_TARGET_LINKADDR:
case ND_OPT_REDIRECTED_HEADER:
+#ifdef RDNSS
+ case ND_OPT_RDNSS:
+ case ND_OPT_DNSSL:
+#endif
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 b/usr.sbin/rtadvd/rtadvd.conf
index 33ab7f3..6213c4e 100644
--- a/usr.sbin/rtadvd/rtadvd.conf
+++ b/usr.sbin/rtadvd/rtadvd.conf
@@ -18,4 +18,5 @@
# this part by hand, and then invoke rtadvd with the -s option.
#ef0:\
-# :addr="3ffe:501:ffff:1000::":prefixlen#64:
+# :addr="2001:db8:ffff:1000::":prefixlen#64:\
+# :rddns="2001:db8:ffff:1000::1":dnssl="foo.com":
diff --git a/usr.sbin/rtadvd/rtadvd.conf.5 b/usr.sbin/rtadvd/rtadvd.conf.5
index 81ffa70..f6003cd 100644
--- a/usr.sbin/rtadvd/rtadvd.conf.5
+++ b/usr.sbin/rtadvd/rtadvd.conf.5
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 17, 1998
+.Dd May 28, 2011
.Dt RTADVD.CONF 5
.Os
.Sh NAME
@@ -355,6 +355,65 @@ However, keywords that start with
.Dq Li rtr
have basically been obsoleted, and should not be used any more.
.Pp
+The following items are for ICMPv6 Recursive DNS Server Option and
+DNS Search List Option
+.Pq RFC 6106 ,
+which will be attached to router advertisement header.
+These items are optional.
+.Bl -tag -width indent
+.It Cm \&rdnss
+(str) The IPv6 address of one or more recursive DNS servers.
+The argument must be inside double quotes.
+Multiple DNS servers can be specified in a comma-separated string.
+If different lifetimes are needed for different servers,
+separate entries can be given by using
+.Cm rdnss ,
+.Cm rdnss0 ,
+.Cm rdnss1 ,
+.Cm rdnss2 ...
+options with corresponding
+.Cm rdnssltime ,
+.Cm rdnssltime0 ,
+.Cm rdnssltime1 ,
+.Cm rdnssltime2 ...
+entries.
+Note that the maximum number of servers depends on the receiver side.
+See also
+.Xr resolver 5
+manual page for resolver implementation in
+.Fx .
+.It Cm \&rdnssltime
+The lifetime of the
+.Cm rdnss
+DNS server entries. The default value is 3/2 of the interval
+time.
+.It Cm \&dnssl
+(str) One or more domain names in a comma-separated string.
+These domain names will be used when making DNS queries on a
+non-fully-qualified domain name. If different lifetimes are needed for
+different domains, separate entries can be given by using
+.Cm dnssl ,
+.Cm dnssl0 ,
+.Cm dnssl1 ,
+.Cm dnssl2 ...
+options with corresponding
+.Cm dnsslltime ,
+.Cm dnsslltime0 ,
+.Cm dnsslltime1 ,
+.Cm dnsslltime2 ...
+entries.
+Note that the maximum number of names depends on the receiver side.
+See also
+.Xr resolver 5
+manual page for resolver implementation in
+.Fx .
+.It Cm \&dnsslltime
+The lifetime of the
+.Cm dnssl
+DNS search list entries. The default value is 3/2 of the interval
+time.
+.El
+.Pp
You can also refer one line from another by using
.Cm tc
capability.
@@ -388,7 +447,18 @@ option to
.Xr rtadvd 8 .
.Bd -literal -offset
ef0:\\
- :addr="3ffe:501:ffff:1000::":prefixlen#64:
+ :addr="2001:db8:ffff:1000::":prefixlen#64:
+.Ed
+.Pp
+The following example configures the
+.Li wlan0
+interface and adds two DNS servers and a DNS domain search options
+using the default option lifetime values.
+.Bd -literal -offset
+wlan0:\\
+ :addr="2001:db8:ffff:1000::":prefixlen#64:\\
+ :rdnss="2001:db8:ffff::10,2001:db8:ffff::2:43:\\
+ :dnssl="foo.com":
.Ed
.Pp
The following example presents the default values in an explicit manner.
@@ -399,10 +469,11 @@ default:\\
:chlim#64:raflags#0:rltime#1800:rtime#0:retrans#0:\\
:pinfoflags="la":vltime#2592000:pltime#604800:mtu#0:
ef0:\\
- :addr="3ffe:501:ffff:1000::":prefixlen#64:tc=default:
+ :addr="2001:db8:ffff:1000::":prefixlen#64:tc=default:
.Ed
.Sh SEE ALSO
.Xr termcap 5 ,
+.Xr resolver 5 ,
.Xr rtadvd 8 ,
.Xr rtsol 8
.Rs
@@ -417,6 +488,14 @@ ef0:\\
.%T Default Router Preferences and More-Specific Routes
.%R draft-ietf-ipngwg-router-selection-xx.txt
.Re
+.Rs
+.%A J. Jeong
+.%A S. Park
+.%A L. Beloeil
+.%A S. Madanapalli
+.%T IPv6 Router Advertisement Options for DNS Configuration
+.%R RFC 6106
+.Re
.Sh HISTORY
The
.Xr rtadvd 8
diff --git a/usr.sbin/rtadvd/rtadvd.h b/usr.sbin/rtadvd/rtadvd.h
index 828fec6..e346a1a 100644
--- a/usr.sbin/rtadvd/rtadvd.h
+++ b/usr.sbin/rtadvd/rtadvd.h
@@ -94,6 +94,44 @@ struct rtinfo {
};
#endif
+#ifdef RDNSS
+struct rdnss_addr {
+ TAILQ_ENTRY(rdnss_addr) ra_next;
+
+ struct in6_addr ra_dns; /* DNS server entry */
+};
+struct rdnss {
+ TAILQ_ENTRY(rdnss) rd_next;
+
+ TAILQ_HEAD(, rdnss_addr) rd_list; /* list of DNS servers */
+ int rd_cnt; /* number of DNS servers */
+ u_int32_t rd_ltime; /* number of seconds valid */
+};
+
+/*
+ * 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
+ * the tail and adding 8 octet boundary padding.
+ */
+#define _DNAME_LABELENC_MAXLEN \
+ (NI_MAXHOST + (NI_MAXHOST / 64 + 1) + 1)
+#define DNAME_LABELENC_MAXLEN \
+ (_DNAME_LABELENC_MAXLEN + 8 - _DNAME_LABELENC_MAXLEN % 8)
+
+struct dnssl_addr {
+ TAILQ_ENTRY(dnssl_addr) da_next;
+
+ int da_len; /* length of entry */
+ char da_dom[DNAME_LABELENC_MAXLEN]; /* search domain name entry */
+};
+struct dnssl {
+ TAILQ_ENTRY(dnssl) dn_next;
+
+ TAILQ_HEAD(, dnssl_addr) dn_list; /* list of search domains */
+ u_int32_t dn_ltime; /* number of seconds valid */
+};
+#endif
+
struct soliciter {
struct soliciter *next;
struct sockaddr_in6 addr;
@@ -130,6 +168,10 @@ struct rainfo {
u_int hoplimit; /* AdvCurHopLimit */
struct prefix prefix; /* AdvPrefixList(link head) */
int pfxs; /* number of prefixes */
+#ifdef RDNSS
+ TAILQ_HEAD(, rdnss) rdnss; /* DNS server list */
+ TAILQ_HEAD(, dnssl) dnssl; /* search domain list */
+#endif
long clockskew; /* used for consisitency check of lifetimes */
#ifdef ROUTEINFO
OpenPOWER on IntegriCloud