diff options
Diffstat (limited to 'usr.sbin/rtadvd')
-rw-r--r-- | usr.sbin/rtadvd/Makefile | 2 | ||||
-rw-r--r-- | usr.sbin/rtadvd/config.c | 232 | ||||
-rw-r--r-- | usr.sbin/rtadvd/config.h | 2 | ||||
-rw-r--r-- | usr.sbin/rtadvd/dump.c | 64 | ||||
-rw-r--r-- | usr.sbin/rtadvd/if.c | 1 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rrenum.c | 1 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rtadvd.c | 69 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rtadvd.conf | 3 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rtadvd.conf.5 | 85 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rtadvd.h | 42 |
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 |