summaryrefslogtreecommitdiffstats
path: root/usr.sbin/rtadvd
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit832f8d224926758a9ae0b23a6b45353e44fbc87a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /usr.sbin/rtadvd
parent2693854b01a52b0395a91322aa3edf926bddff38 (diff)
downloadFreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip
FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks
Diffstat (limited to 'usr.sbin/rtadvd')
-rw-r--r--usr.sbin/rtadvd/advcap.c8
-rw-r--r--usr.sbin/rtadvd/advcap.h4
-rw-r--r--usr.sbin/rtadvd/config.c396
-rw-r--r--usr.sbin/rtadvd/config.h2
-rw-r--r--usr.sbin/rtadvd/dump.c42
-rw-r--r--usr.sbin/rtadvd/dump.h2
-rw-r--r--usr.sbin/rtadvd/if.c15
-rw-r--r--usr.sbin/rtadvd/if.h37
-rw-r--r--usr.sbin/rtadvd/pathnames.h2
-rw-r--r--usr.sbin/rtadvd/rrenum.c96
-rw-r--r--usr.sbin/rtadvd/rrenum.h7
-rw-r--r--usr.sbin/rtadvd/rtadvd.845
-rw-r--r--usr.sbin/rtadvd/rtadvd.c209
-rw-r--r--usr.sbin/rtadvd/rtadvd.conf.5104
-rw-r--r--usr.sbin/rtadvd/rtadvd.h25
-rw-r--r--usr.sbin/rtadvd/timer.c2
-rw-r--r--usr.sbin/rtadvd/timer.h2
17 files changed, 799 insertions, 199 deletions
diff --git a/usr.sbin/rtadvd/advcap.c b/usr.sbin/rtadvd/advcap.c
index 55a43ce..5cba1f5 100644
--- a/usr.sbin/rtadvd/advcap.c
+++ b/usr.sbin/rtadvd/advcap.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: advcap.c,v 1.3 2000/05/16 13:34:13 itojun Exp $ */
+/* $KAME: advcap.c,v 1.5 2001/02/01 09:12:08 jinmei Exp $ */
/*
* Copyright (c) 1983 The Regents of the University of California.
@@ -96,7 +96,7 @@ int getent __P((char *, char *, char *));
int tnchktc __P((void));
int tnamatch __P((char *));
static char *tskip __P((char *));
-int tgetnum __P((char *));
+long long tgetnum __P((char *));
int tgetflag __P((char *));
char *tgetstr __P((char *, char **));
static char *tdecode __P((char *, char **));
@@ -307,11 +307,11 @@ breakbreak:
* a # character. If the option is not found we return -1.
* Note that we handle octal numbers beginning with 0.
*/
-int
+long long
tgetnum(id)
char *id;
{
- register long int i;
+ register long long i;
register int base;
register char *bp = tbuf;
diff --git a/usr.sbin/rtadvd/advcap.h b/usr.sbin/rtadvd/advcap.h
index dc3f428..7b3715a 100644
--- a/usr.sbin/rtadvd/advcap.h
+++ b/usr.sbin/rtadvd/advcap.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME$ */
+/* $KAME: advcap.h,v 1.3 2001/02/01 09:12:08 jinmei Exp $ */
/*
* Copyright (C) 1994,1995 by Andrey A. Chernov, Moscow, Russia.
@@ -38,7 +38,7 @@ __BEGIN_DECLS
extern int agetent __P((char *, const char *));
extern int agetflag __P((const char *));
-extern int agetnum __P((const char *));
+extern long long agetnum __P((const char *));
extern char *agetstr __P((const char *, char **));
__END_DECLS
diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c
index ec294f1..01cfb4c 100644
--- a/usr.sbin/rtadvd/config.c
+++ b/usr.sbin/rtadvd/config.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: config.c,v 1.11 2000/05/16 13:34:13 itojun Exp $ */
+/* $KAME: config.c,v 1.37 2001/05/25 07:34:00 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
@@ -34,6 +34,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
@@ -62,6 +63,7 @@
#include <search.h>
#endif
#include <unistd.h>
+#include <ifaddrs.h>
#include "rtadvd.h"
#include "advcap.h"
@@ -71,6 +73,7 @@
static void makeentry __P((char *, int, char *, int));
static void get_prefix __P((struct rainfo *));
+static int getinet6sysctl __P((int));
extern struct rainfo *ralist;
@@ -82,9 +85,11 @@ getconfig(intface)
char tbuf[BUFSIZ];
struct rainfo *tmp;
long val;
+ long long val64;
char buf[BUFSIZ];
char *bp = buf;
char *addr;
+ static int forwarding = -1;
#define MUSTHAVE(var, cap) \
do { \
@@ -114,6 +119,13 @@ getconfig(intface)
tmp = (struct rainfo *)malloc(sizeof(*ralist));
memset(tmp, 0, sizeof(*tmp));
tmp->prefix.next = tmp->prefix.prev = &tmp->prefix;
+ tmp->route.next = tmp->route.prev = &tmp->route;
+
+ /* check if we are allowed to forward packets (if not determined) */
+ if (forwarding < 0) {
+ if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0)
+ exit(1);
+ }
/* get interface information */
if (agetflag("nolladdr"))
@@ -164,12 +176,22 @@ getconfig(intface)
tmp->hoplimit = val & 0xff;
MAYHAVE(val, "raflags", 0);
- tmp->managedflg= val & ND_RA_FLAG_MANAGED;
+ tmp->managedflg = val & ND_RA_FLAG_MANAGED;
tmp->otherflg = val & ND_RA_FLAG_OTHER;
#ifdef MIP6
if (mobileip6)
tmp->haflg = val & ND_RA_FLAG_HA;
#endif
+#ifndef ND_RA_FLAG_RTPREF_MASK
+#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
+#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */
+#endif
+ tmp->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+ if (tmp->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+ syslog(LOG_ERR, "<%s> invalid router preference on %s",
+ __FUNCTION__, intface);
+ exit(1);
+ }
MAYHAVE(val, "rltime", tmp->maxinterval * 3);
if (val && (val < tmp->maxinterval || val > MAXROUTERLIFETIME)) {
@@ -180,6 +202,21 @@ getconfig(intface)
tmp->maxinterval, MAXROUTERLIFETIME);
exit(1);
}
+ /*
+ * Basically, hosts MUST NOT send Router Advertisement messages at any
+ * time (RFC 2461, Section 6.2.3). However, it would sometimes be
+ * useful to allow hosts to advertise some parameters such as prefix
+ * information and link MTU. Thus, we allow hosts to invoke rtadvd
+ * only when router lifetime (on every advertising interface) is
+ * explicitly set zero. (see also the above section)
+ */
+ if (val && forwarding == 0) {
+ syslog(LOG_WARNING,
+ "<%s> non zero router lifetime is specified for %s, "
+ "which must not be allowed for hosts.",
+ __FUNCTION__, intface);
+ exit(1);
+ }
tmp->lifetime = val & 0xffff;
MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME);
@@ -191,20 +228,23 @@ getconfig(intface)
}
tmp->reachabletime = (u_int32_t)val;
- MAYHAVE(val, "retrans", DEF_ADVRETRANSTIMER);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> retrans time out of range", __FUNCTION__);
exit(1);
}
- tmp->retranstimer = (u_int32_t)val;
+ tmp->retranstimer = (u_int32_t)val64;
-#ifdef MIP6
- if (!mobileip6)
+#ifndef MIP6
+ if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) {
+ syslog(LOG_ERR,
+ "<%s> mobile-ip6 configuration not supported",
+ __FUNCTION__);
+ exit(1);
+ }
#else
- if (1)
-#endif
- {
+ if (!mobileip6) {
if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) {
syslog(LOG_ERR,
"<%s> mobile-ip6 configuration without "
@@ -212,9 +252,7 @@ getconfig(intface)
__FUNCTION__);
exit(1);
}
- }
-#ifdef MIP6
- else {
+ } else {
tmp->hapref = 0;
if ((val = agetnum("hapref")) >= 0)
tmp->hapref = (int16_t)val;
@@ -233,6 +271,15 @@ getconfig(intface)
#endif
/* prefix information */
+
+ /*
+ * This is an implementation specific parameter to consinder
+ * link propagation delays and poorly synchronized clocks when
+ * checking consistency of advertised lifetimes.
+ */
+ MAYHAVE(val, "clockskew", 0);
+ tmp->clockskew = val;
+
if ((pfxs = agetnum("addrs")) < 0) {
/* auto configure prefix information */
if (agetstr("addr", &bp) || agetstr("addr1", &bp)) {
@@ -281,7 +328,7 @@ getconfig(intface)
{
MAYHAVE(val, entbuf,
(ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO|
- ND_OPT_PI_FLAG_RTADDR));
+ ND_OPT_PI_FLAG_ROUTER));
} else
#endif
{
@@ -291,29 +338,44 @@ getconfig(intface)
pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK;
pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO;
#ifdef MIP6
- if (mobileip6)
- pfx->routeraddr = val & ND_OPT_PI_FLAG_RTADDR;
+ pfx->routeraddr = val & ND_OPT_PI_FLAG_ROUTER;
#endif
makeentry(entbuf, i, "vltime", added);
- MAYHAVE(val, entbuf, DEF_ADVVALIDLIFETIME);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> vltime out of range",
__FUNCTION__);
exit(1);
}
- pfx->validlifetime = (u_int32_t)val;
+ pfx->validlifetime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "vltimedecr", added);
+ if (agetflag(entbuf)) {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ pfx->vltimeexpire =
+ now.tv_sec + pfx->validlifetime;
+ }
makeentry(entbuf, i, "pltime", added);
- MAYHAVE(val, entbuf, DEF_ADVPREFERREDLIFETIME);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> pltime out of range",
__FUNCTION__);
exit(1);
}
- pfx->preflifetime = (u_int32_t)val;
+ pfx->preflifetime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "pltimedecr", added);
+ if (agetflag(entbuf)) {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ pfx->pltimeexpire =
+ now.tv_sec + pfx->preflifetime;
+ }
makeentry(entbuf, i, "addr", added);
addr = (char *)agetstr(entbuf, &bp);
@@ -368,6 +430,106 @@ getconfig(intface)
exit(1);
}
+ /* route information */
+
+ MAYHAVE(val, "routes", 0);
+ if (val < 0 || val > 0xffffffff) {
+ syslog(LOG_ERR,
+ "<%s> number of route information improper", __FUNCTION__);
+ exit(1);
+ }
+ tmp->routes = val;
+ for (i = 0; i < tmp->routes; i++) {
+ struct rtinfo *rti;
+ char entbuf[256];
+ int added = (tmp->routes > 1) ? 1 : 0;
+
+ /* allocate memory to store prefix information */
+ if ((rti = malloc(sizeof(struct rtinfo))) == NULL) {
+ syslog(LOG_ERR,
+ "<%s> can't allocate enough memory",
+ __FUNCTION__);
+ exit(1);
+ }
+ memset(rti, 0, sizeof(*rti));
+
+ /* link into chain */
+ insque(rti, &tmp->route);
+
+ makeentry(entbuf, i, "rtrplen", added);
+ MAYHAVE(val, entbuf, 64);
+ if (val < 0 || val > 128) {
+ syslog(LOG_ERR,
+ "<%s> prefixlen out of range",
+ __FUNCTION__);
+ exit(1);
+ }
+ rti->prefixlen = (int)val;
+
+ makeentry(entbuf, i, "rtrflags", added);
+ MAYHAVE(val, entbuf, 0);
+ rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+ if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+ syslog(LOG_ERR, "<%s> invalid router preference",
+ __FUNCTION__);
+ exit(1);
+ }
+
+ makeentry(entbuf, i, "rtrltime", added);
+ /*
+ * XXX: since default value of route lifetime is not defined in
+ * draft-draves-route-selection-01.txt, I took the default
+ * value of valid lifetime of prefix as its default.
+ * It need be much considered.
+ */
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
+ syslog(LOG_ERR,
+ "<%s> rtrltime out of range",
+ __FUNCTION__);
+ exit(1);
+ }
+ rti->ltime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "rtrprefix", added);
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL) {
+ syslog(LOG_ERR,
+ "<%s> need %s as an route for "
+ "interface %s",
+ __FUNCTION__, entbuf, intface);
+ exit(1);
+ }
+ if (inet_pton(AF_INET6, addr, &rti->prefix) != 1) {
+ syslog(LOG_ERR,
+ "<%s> inet_pton failed for %s",
+ __FUNCTION__, addr);
+ exit(1);
+ }
+#if 0
+ /*
+ * XXX: currently there's no restriction in route information
+ * prefix according to draft-draves-route-selection-01.txt,
+ * however I think the similar restriction be necessary.
+ */
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (IN6_IS_ADDR_MULTICAST(&rti->prefix)) {
+ syslog(LOG_ERR,
+ "<%s> multicast route (%s) must "
+ "not be advertised (IF=%s)",
+ __FUNCTION__, addr, intface);
+ exit(1);
+ }
+ if (IN6_IS_ADDR_LINKLOCAL(&rti->prefix)) {
+ syslog(LOG_NOTICE,
+ "<%s> link-local route (%s) must "
+ "not be advertised on %s",
+ __FUNCTION__, addr, intface);
+ exit(1);
+ }
+#endif
+ }
+
/* okey */
tmp->next = ralist;
ralist = tmp;
@@ -385,33 +547,26 @@ getconfig(intface)
static void
get_prefix(struct rainfo *rai)
{
- size_t len;
- u_char *buf, *lim, *next;
+ struct ifaddrs *ifap, *ifa;
+ struct prefix *pp;
+ struct in6_addr *a;
+ u_char *p, *ep, *m, *lim;
u_char ntopbuf[INET6_ADDRSTRLEN];
- if ((len = rtbuf_len()) < 0) {
+ if (getifaddrs(&ifap) < 0) {
syslog(LOG_ERR,
- "<%s> can't get buffer length for routing info",
+ "<%s> can't get interface addresses",
__FUNCTION__);
exit(1);
}
- if ((buf = malloc(len)) == NULL) {
- syslog(LOG_ERR,
- "<%s> can't allocate buffer", __FUNCTION__);
- exit(1);
- }
- if (get_rtinfo(buf, &len) < 0) {
- syslog(LOG_ERR,
- "<%s> can't get routing inforamtion", __FUNCTION__);
- exit(1);
- }
-
- lim = buf + len;
- next = get_next_msg(buf, lim, rai->ifindex, &len,
- RTADV_TYPE2BITMASK(RTM_GET));
- while (next < lim) {
- struct prefix *pp;
- struct in6_addr *a;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (strcmp(ifa->ifa_name, rai->ifname) != 0)
+ continue;
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+ if (IN6_IS_ADDR_LINKLOCAL(a))
+ continue;
/* allocate memory to store prefix info. */
if ((pp = malloc(sizeof(*pp))) == NULL) {
@@ -422,21 +577,35 @@ get_prefix(struct rainfo *rai)
}
memset(pp, 0, sizeof(*pp));
- /* set prefix and its length */
- a = get_addr(next);
- memcpy(&pp->prefix, a, sizeof(*a));
- if ((pp->prefixlen = get_prefixlen(next)) < 0) {
+ /* set prefix length */
+ m = (u_char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
+ lim = (u_char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len;
+ pp->prefixlen = prefixlen(m, lim);
+ if (pp->prefixlen < 0 || pp->prefixlen > 128) {
syslog(LOG_ERR,
"<%s> failed to get prefixlen "
- "or prefixl is invalid",
+ "or prefix is invalid",
__FUNCTION__);
exit(1);
}
+
+ /* set prefix, sweep bits outside of prefixlen */
+ memcpy(&pp->prefix, a, sizeof(*a));
+ p = (u_char *)&pp->prefix;
+ ep = (u_char *)(&pp->prefix + 1);
+ while (m < lim)
+ *p++ &= *m++;
+ while (p < ep)
+ *p++ = 0x00;
+
+ if (!inet_ntop(AF_INET6, &pp->prefix, ntopbuf,
+ sizeof(ntopbuf))) {
+ syslog(LOG_ERR, "<%s> inet_ntop failed", __FUNCTION__);
+ exit(1);
+ }
syslog(LOG_DEBUG,
"<%s> add %s/%d to prefix list on %s",
- __FUNCTION__,
- inet_ntop(AF_INET6, a, ntopbuf, INET6_ADDRSTRLEN),
- pp->prefixlen, rai->ifname);
+ __FUNCTION__, ntopbuf, pp->prefixlen, rai->ifname);
/* set other fields with protocol defaults */
pp->validlifetime = DEF_ADVVALIDLIFETIME;
@@ -450,14 +619,9 @@ get_prefix(struct rainfo *rai)
/* counter increment */
rai->pfxs++;
-
- /* forward pointer and get next prefix(if any) */
- next += len;
- next = get_next_msg(next, lim, rai->ifindex,
- &len, RTADV_TYPE2BITMASK(RTM_GET));
}
- free(buf);
+ freeifaddrs(ifap);
}
static void
@@ -493,6 +657,7 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
__FUNCTION__);
return; /* XXX: error or exit? */
}
+ memset(prefix, 0, sizeof(*prefix));
prefix->prefix = ipr->ipr_prefix.sin6_addr;
prefix->prefixlen = ipr->ipr_plen;
prefix->validlifetime = ipr->ipr_vltime;
@@ -510,7 +675,7 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
/* free the previous packet */
free(rai->ra_data);
- rai->ra_data = 0;
+ rai->ra_data = NULL;
/* reconstruct the packet */
rai->pfxs++;
@@ -617,10 +782,12 @@ make_packet(struct rainfo *rainfo)
struct nd_opt_prefix_info *ndopt_pi;
struct nd_opt_mtu *ndopt_mtu;
#ifdef MIP6
- struct nd_opt_advint *ndopt_advint;
- struct nd_opt_hai *ndopt_hai;
+ struct nd_opt_advinterval *ndopt_advint;
+ struct nd_opt_homeagent_info *ndopt_hai;
#endif
+ struct nd_opt_route_info *ndopt_rti;
struct prefix *pfx;
+ struct rtinfo *rti;
/* calculate total length */
packlen = sizeof(struct nd_router_advert);
@@ -641,9 +808,14 @@ make_packet(struct rainfo *rainfo)
packlen += sizeof(struct nd_opt_mtu);
#ifdef MIP6
if (mobileip6 && rainfo->maxinterval)
- packlen += sizeof(struct nd_opt_advint);
+ packlen += sizeof(struct nd_opt_advinterval);
if (mobileip6 && rainfo->hatime)
- packlen += sizeof(struct nd_opt_hai);
+ packlen += sizeof(struct nd_opt_homeagent_info);
+#endif
+#ifdef ND_OPT_ROUTE_INFO
+ for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next)
+ packlen += sizeof(struct nd_opt_route_info) +
+ ((rti->prefixlen + 0x3f) >> 6) * 8;
#endif
/* allocate memory for the packet */
@@ -653,6 +825,11 @@ make_packet(struct rainfo *rainfo)
__FUNCTION__);
exit(1);
}
+ if (rainfo->ra_data) {
+ /* free the previous packet */
+ free(rainfo->ra_data);
+ rainfo->ra_data = NULL;
+ }
rainfo->ra_data = buf;
/* XXX: what if packlen > 576? */
rainfo->ra_datalen = packlen;
@@ -665,7 +842,12 @@ make_packet(struct rainfo *rainfo)
ra->nd_ra_code = 0;
ra->nd_ra_cksum = 0;
ra->nd_ra_curhoplimit = (u_int8_t)(0xff & rainfo->hoplimit);
- ra->nd_ra_flags_reserved = 0;
+ ra->nd_ra_flags_reserved = 0; /* just in case */
+ /*
+ * XXX: the router preference field, which is a 2-bit field, should be
+ * initialized before other fields.
+ */
+ ra->nd_ra_flags_reserved = 0xff & rainfo->rtpref;
ra->nd_ra_flags_reserved |=
rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0;
ra->nd_ra_flags_reserved |=
@@ -689,36 +871,39 @@ make_packet(struct rainfo *rainfo)
ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
ndopt_mtu->nd_opt_mtu_len = 1;
ndopt_mtu->nd_opt_mtu_reserved = 0;
- ndopt_mtu->nd_opt_mtu_mtu = ntohl(rainfo->linkmtu);
+ ndopt_mtu->nd_opt_mtu_mtu = htonl(rainfo->linkmtu);
buf += sizeof(struct nd_opt_mtu);
}
#ifdef MIP6
if (mobileip6 && rainfo->maxinterval) {
- ndopt_advint = (struct nd_opt_advint *)buf;
- ndopt_advint->nd_opt_int_type = ND_OPT_ADV_INTERVAL;
- ndopt_advint->nd_opt_int_len = 1;
- ndopt_advint->nd_opt_int_reserved = 0;
- ndopt_advint->nd_opt_int_interval = ntohl(rainfo->maxinterval *
+ ndopt_advint = (struct nd_opt_advinterval *)buf;
+ ndopt_advint->nd_opt_adv_type = ND_OPT_ADVINTERVAL;
+ ndopt_advint->nd_opt_adv_len = 1;
+ ndopt_advint->nd_opt_adv_reserved = 0;
+ ndopt_advint->nd_opt_adv_interval = htonl(rainfo->maxinterval *
1000);
- buf += sizeof(struct nd_opt_advint);
+ buf += sizeof(struct nd_opt_advinterval);
}
#endif
#ifdef MIP6
if (rainfo->hatime) {
- ndopt_hai = (struct nd_opt_hai *)buf;
- ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
+ ndopt_hai = (struct nd_opt_homeagent_info *)buf;
+ ndopt_hai->nd_opt_hai_type = ND_OPT_HOMEAGENT_INFO;
ndopt_hai->nd_opt_hai_len = 1;
ndopt_hai->nd_opt_hai_reserved = 0;
- ndopt_hai->nd_opt_hai_pref = ntohs(rainfo->hapref);
- ndopt_hai->nd_opt_hai_lifetime = ntohs(rainfo->hatime);
- buf += sizeof(struct nd_opt_hai);
+ ndopt_hai->nd_opt_hai_preference = htons(rainfo->hapref);
+ ndopt_hai->nd_opt_hai_lifetime = htons(rainfo->hatime);
+ buf += sizeof(struct nd_opt_homeagent_info);
}
#endif
for (pfx = rainfo->prefix.next;
pfx != &rainfo->prefix; pfx = pfx->next) {
+ u_int32_t vltime, pltime;
+ struct timeval now;
+
ndopt_pi = (struct nd_opt_prefix_info *)buf;
ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
ndopt_pi->nd_opt_pi_len = 4;
@@ -733,16 +918,69 @@ make_packet(struct rainfo *rainfo)
#ifdef MIP6
if (pfx->routeraddr)
ndopt_pi->nd_opt_pi_flags_reserved |=
- ND_OPT_PI_FLAG_RTADDR;
+ ND_OPT_PI_FLAG_ROUTER;
#endif
- ndopt_pi->nd_opt_pi_valid_time = ntohl(pfx->validlifetime);
- ndopt_pi->nd_opt_pi_preferred_time =
- ntohl(pfx->preflifetime);
+ if (pfx->vltimeexpire || pfx->pltimeexpire)
+ gettimeofday(&now, NULL);
+ if (pfx->vltimeexpire == 0)
+ vltime = pfx->validlifetime;
+ else
+ vltime = (pfx->vltimeexpire > now.tv_sec) ?
+ pfx->vltimeexpire - now.tv_sec : 0;
+ if (pfx->pltimeexpire == 0)
+ pltime = pfx->preflifetime;
+ else
+ pltime = (pfx->pltimeexpire > now.tv_sec) ?
+ pfx->pltimeexpire - now.tv_sec : 0;
+ if (vltime < pltime) {
+ /*
+ * this can happen if vltime is decrement but pltime
+ * is not.
+ */
+ pltime = vltime;
+ }
+ ndopt_pi->nd_opt_pi_valid_time = htonl(vltime);
+ ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime);
ndopt_pi->nd_opt_pi_reserved2 = 0;
ndopt_pi->nd_opt_pi_prefix = pfx->prefix;
buf += sizeof(struct nd_opt_prefix_info);
}
+#ifdef ND_OPT_ROUTE_INFO
+ for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next) {
+ u_int8_t psize = (rti->prefixlen + 0x3f) >> 6;
+
+ ndopt_rti = (struct nd_opt_route_info *)buf;
+ ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO;
+ ndopt_rti->nd_opt_rti_len = 1 + psize;
+ ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen;
+ ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref;
+ ndopt_rti->nd_opt_rti_lifetime = rti->ltime;
+ memcpy(ndopt_rti + 1, &rti->prefix, psize * 8);
+ buf += sizeof(struct nd_opt_route_info) + psize * 8;
+ }
+#endif
+
return;
}
+
+static int
+getinet6sysctl(int code)
+{
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
+ int value;
+ size_t size;
+
+ mib[3] = code;
+ size = sizeof(value);
+ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0)
+ < 0) {
+ syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s",
+ __FUNCTION__, code,
+ strerror(errno));
+ return(-1);
+ }
+ else
+ return(value);
+}
diff --git a/usr.sbin/rtadvd/config.h b/usr.sbin/rtadvd/config.h
index f08a702..9000461 100644
--- a/usr.sbin/rtadvd/config.h
+++ b/usr.sbin/rtadvd/config.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME$ */
+/* $KAME: config.h,v 1.3 2000/05/16 13:34:13 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
diff --git a/usr.sbin/rtadvd/dump.c b/usr.sbin/rtadvd/dump.c
index 4b2801d..4e4be1a 100644
--- a/usr.sbin/rtadvd/dump.c
+++ b/usr.sbin/rtadvd/dump.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: dump.c,v 1.10 2000/05/23 11:31:25 itojun Exp $ */
+/* $KAME: dump.c,v 1.16 2001/03/21 17:41:13 jinmei Exp $ */
/*
* Copyright (C) 2000 WIDE Project.
@@ -31,6 +31,7 @@
*/
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/queue.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
@@ -71,6 +72,13 @@ static void if_dump __P((void));
#define LONGLONG "%llu"
#endif
+static char *rtpref_str[] = {
+ "medium", /* 00 */
+ "high", /* 01 */
+ "rsv", /* 10 */
+ "low" /* 11 */
+};
+
static char *
ether_str(sdl)
struct sockaddr_dl *sdl;
@@ -97,7 +105,9 @@ if_dump()
struct prefix *pfx;
char prefixbuf[INET6_ADDRSTRLEN];
int first;
+ struct timeval now;
+ gettimeofday(&now, NULL); /* XXX: unused in most cases */
for (rai = ralist; rai; rai = rai->next) {
fprintf(fp, "%s:\n", rai->ifname);
@@ -141,12 +151,15 @@ if_dump()
" DefaultLifetime: %d, MaxAdvInterval: %d, "
"MinAdvInterval: %d\n",
rai->lifetime, rai->maxinterval, rai->mininterval);
- fprintf(fp, " Flags: %s%s%s MTU: %d\n",
+ fprintf(fp, " Flags: %s%s%s, ",
rai->managedflg ? "M" : "", rai->otherflg ? "O" : "",
#ifdef MIP6
rai->haflg ? "H" :
#endif
- "", rai->linkmtu);
+ "");
+ fprintf(fp, "Preference: %s, ",
+ rtpref_str[(rai->rtpref >> 3) & 0xff]);
+ fprintf(fp, "MTU: %d\n", rai->linkmtu);
fprintf(fp, " ReachableTime: %d, RetransTimer: %d, "
"CurHopLimit: %d\n", rai->reachabletime,
rai->retranstimer, rai->hoplimit);
@@ -155,6 +168,9 @@ if_dump()
rai->hapref, rai->hatime);
#endif
+ if (rai->clockskew)
+ fprintf(fp, " Clock skew: %ldsec\n",
+ rai->clockskew);
for (first = 1, pfx = rai->prefix.next; pfx != &rai->prefix;
pfx = pfx->next) {
if (first) {
@@ -177,15 +193,27 @@ if_dump()
break;
}
if (pfx->validlifetime == ND6_INFINITE_LIFETIME)
- fprintf(fp, "vltime: infinity, ");
+ fprintf(fp, "vltime: infinity");
else
- fprintf(fp, "vltime: %ld, ",
+ fprintf(fp, "vltime: %ld",
(long)pfx->validlifetime);
+ if (pfx->vltimeexpire != 0)
+ fprintf(fp, "(decr,expire %ld), ", (long)
+ pfx->vltimeexpire > now.tv_sec ?
+ pfx->vltimeexpire - now.tv_sec : 0);
+ else
+ fprintf(fp, ", ");
if (pfx->preflifetime == ND6_INFINITE_LIFETIME)
- fprintf(fp, "pltime: infinity, ");
+ fprintf(fp, "pltime: infinity");
else
- fprintf(fp, "pltime: %ld, ",
+ fprintf(fp, "pltime: %ld",
(long)pfx->preflifetime);
+ if (pfx->pltimeexpire != 0)
+ fprintf(fp, "(decr,expire %ld), ", (long)
+ pfx->pltimeexpire > now.tv_sec ?
+ pfx->pltimeexpire - now.tv_sec : 0);
+ else
+ fprintf(fp, ", ");
fprintf(fp, "flags: %s%s%s",
pfx->onlinkflg ? "L" : "",
pfx->autoconfflg ? "A" : "",
diff --git a/usr.sbin/rtadvd/dump.h b/usr.sbin/rtadvd/dump.h
index 03dff70..cc3b472 100644
--- a/usr.sbin/rtadvd/dump.h
+++ b/usr.sbin/rtadvd/dump.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME$ */
+/* $KAME: dump.h,v 1.1 2000/05/23 11:31:26 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
diff --git a/usr.sbin/rtadvd/if.c b/usr.sbin/rtadvd/if.c
index b77f472..c6aa2e6 100644
--- a/usr.sbin/rtadvd/if.c
+++ b/usr.sbin/rtadvd/if.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: if.c,v 1.14 2000/10/25 04:28:34 jinmei Exp $ */
+/* $KAME: if.c,v 1.17 2001/01/21 15:27:30 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -259,17 +259,6 @@ rtbuf_len()
return(len);
}
-int
-get_rtinfo(char *buf, size_t *len)
-{
- int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET6, NET_RT_DUMP, 0};
-
- if (sysctl(mib, 6, buf, len, NULL, 0) < 0)
- return(-1);
-
- return(0);
-}
-
#define FILTER_MATCH(type, filter) ((0x1 << type) & filter)
#define SIN6(s) ((struct sockaddr_in6 *)(s))
#define SDL(s) ((struct sockaddr_dl *)(s))
@@ -357,7 +346,7 @@ get_next_msg(char *buf, char *lim, int ifindex, size_t *lenp, int filter)
return (char *)rtm;
}
-#undef FILTER_MATCH(type, filter)
+#undef FILTER_MATCH
struct in6_addr *
get_addr(char *buf)
diff --git a/usr.sbin/rtadvd/if.h b/usr.sbin/rtadvd/if.h
index f91e8d4..23f9a98 100644
--- a/usr.sbin/rtadvd/if.h
+++ b/usr.sbin/rtadvd/if.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: if.h,v 1.2 2000/05/16 13:34:13 itojun Exp $ */
+/* $KAME: if.h,v 1.6 2001/01/21 15:37:14 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -37,23 +37,22 @@ extern size_t ifblock_size;
extern char *ifblock;
struct nd_opt_hdr;
-struct sockaddr_dl *if_nametosdl __P((char *name));
-int if_getmtu __P((char *name));
-int if_getflags __P((int ifindex, int oifflags));
-int lladdropt_length __P((struct sockaddr_dl *sdl));
-void lladdropt_fill __P((struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt));
+struct sockaddr_dl *if_nametosdl __P((char *));
+int if_getmtu __P((char *));
+int if_getflags __P((int, int));
+int lladdropt_length __P((struct sockaddr_dl *));
+void lladdropt_fill __P((struct sockaddr_dl *, struct nd_opt_hdr *));
int rtbuf_len __P((void));
-int get_rtinfo __P((char *buf, size_t *len));
-char *get_next_msg __P((char *buf, char *lim, int ifindex, size_t *lenp,
- int filter));
-struct in6_addr *get_addr __P((char *buf));
-int get_rtm_ifindex __P((char *buf));
-int get_ifm_ifindex __P((char *buf));
-int get_ifam_ifindex __P((char *buf));
-int get_ifm_flags __P((char *buf));
-int get_prefixlen __P((char *buf));
-int rtmsg_type __P((char *buf));
-int ifmsg_type __P((char *buf));
-int rtmsg_len __P((char *buf));
-int ifmsg_len __P((char *buf));
+char *get_next_msg __P((char *, char *, int, size_t *, int));
+struct in6_addr *get_addr __P((char *));
+int get_rtm_ifindex __P((char *));
+int get_ifm_ifindex __P((char *));
+int get_ifam_ifindex __P((char *));
+int get_ifm_flags __P((char *));
+int get_prefixlen __P((char *));
+int prefixlen __P((u_char *, u_char *));
+int rtmsg_type __P((char *));
+int ifmsg_type __P((char *));
+int rtmsg_len __P((char *));
+int ifmsg_len __P((char *));
void init_iflist __P((void));
diff --git a/usr.sbin/rtadvd/pathnames.h b/usr.sbin/rtadvd/pathnames.h
index 9c68cc4..3afee55 100644
--- a/usr.sbin/rtadvd/pathnames.h
+++ b/usr.sbin/rtadvd/pathnames.h
@@ -1,4 +1,4 @@
+/* $KAME: pathnames.h,v 1.2 2000/05/16 13:34:13 itojun Exp $ */
/* $FreeBSD$ */
-/* $KAME$ */
#define _PATH_RTADVDCONF "/etc/rtadvd.conf"
diff --git a/usr.sbin/rtadvd/rrenum.c b/usr.sbin/rtadvd/rrenum.c
index a0edf9f..a5fbe20 100644
--- a/usr.sbin/rtadvd/rrenum.c
+++ b/usr.sbin/rtadvd/rrenum.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: rrenum.c,v 1.3 2000/05/16 13:34:14 itojun Exp $ */
+/* $KAME: rrenum.c,v 1.10 2001/01/21 15:32:16 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -50,6 +50,7 @@
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
+#include "rtadvd.h"
#include "rrenum.h"
#include "if.h"
@@ -138,13 +139,17 @@ rr_pco_check(int len, struct rr_pco_match *rpm)
}
static void
-do_use_prefix(int len, struct rr_pco_match *rpm, struct in6_rrenumreq *irr) {
+do_use_prefix(int len, struct rr_pco_match *rpm,
+ struct in6_rrenumreq *irr, int ifindex)
+{
struct rr_pco_use *rpu, *rpulim;
+ struct rainfo *rai;
+ struct prefix *pp;
rpu = (struct rr_pco_use *)(rpm + 1);
rpulim = (struct rr_pco_use *)((char *)rpm + len);
- if (rpu == rpulim) {
+ if (rpu == rpulim) { /* no use prefix */
if (rpm->rpm_code == RPM_PCO_ADD)
return;
@@ -176,16 +181,16 @@ do_use_prefix(int len, struct rr_pco_match *rpm, struct in6_rrenumreq *irr) {
(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK);
irr->irr_raf_mask_auto =
(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_AUTO);
- irr->irr_vltime = rpu->rpu_vltime;
- irr->irr_pltime = rpu->rpu_pltime;
+ irr->irr_vltime = ntohl(rpu->rpu_vltime);
+ irr->irr_pltime = ntohl(rpu->rpu_pltime);
irr->irr_raf_onlink =
- (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK);
+ (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK) == 0 ? 0 : 1;
irr->irr_raf_auto =
- (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO);
+ (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO) == 0 ? 0 : 1;
irr->irr_rrf_decrvalid =
- (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME);
+ (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME) == 0 ? 0 : 1;
irr->irr_rrf_decrprefd =
- (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME);
+ (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME) == 0 ? 0 : 1;
irr->irr_useprefix.sin6_len = sizeof(irr->irr_useprefix);
irr->irr_useprefix.sin6_family = AF_INET6;
irr->irr_useprefix.sin6_addr = rpu->rpu_prefix;
@@ -194,6 +199,40 @@ do_use_prefix(int len, struct rr_pco_match *rpm, struct in6_rrenumreq *irr) {
errno != EADDRNOTAVAIL)
syslog(LOG_ERR, "<%s> ioctl: %s", __FUNCTION__,
strerror(errno));
+
+ /* very adhoc: should be rewritten */
+ if (rpm->rpm_code == RPM_PCO_CHANGE &&
+ IN6_ARE_ADDR_EQUAL(&rpm->rpm_prefix, &rpu->rpu_prefix) &&
+ rpm->rpm_matchlen == rpu->rpu_uselen &&
+ rpu->rpu_uselen == rpu->rpu_keeplen) {
+ if ((rai = if_indextorainfo(ifindex)) == NULL)
+ continue; /* non-advertising IF */
+
+ for (pp = rai->prefix.next; pp != &rai->prefix;
+ pp = pp->next) {
+ struct timeval now;
+
+ if (prefix_match(&pp->prefix, pp->prefixlen,
+ &rpm->rpm_prefix,
+ rpm->rpm_matchlen)) {
+ /* change parameters */
+ pp->validlifetime = ntohl(rpu->rpu_vltime);
+ pp->preflifetime = ntohl(rpu->rpu_pltime);
+ if (irr->irr_rrf_decrvalid) {
+ gettimeofday(&now, 0);
+ pp->vltimeexpire =
+ now.tv_sec + pp->validlifetime;
+ } else
+ pp->vltimeexpire = 0;
+ if (irr->irr_rrf_decrprefd) {
+ gettimeofday(&now, 0);
+ pp->pltimeexpire =
+ now.tv_sec + pp->preflifetime;
+ } else
+ pp->pltimeexpire = 0;
+ }
+ }
+ }
}
}
@@ -234,7 +273,7 @@ do_pco(struct icmp6_router_renum *rr, int len, struct rr_pco_match *rpm)
(iflist[ifindex]->ifm_flags & IFF_UP) == 0)
continue;
/* TODO: interface scope check */
- do_use_prefix(len, rpm, &irr);
+ do_use_prefix(len, rpm, &irr, ifindex);
}
if (errno == ENXIO)
return 0;
@@ -392,9 +431,40 @@ rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi,
inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- rr_rcvifindex = pi->ipi6_ifindex;
+ /* packet validation based on Section 4.1 of RFC2894 */
+ if (len < sizeof(struct icmp6_router_renum)) {
+ syslog(LOG_NOTICE,
+ "<%s>: RR short message (size %d) from %s to %s on %s",
+ __FUNCTION__, len,
+ inet_ntop(AF_INET6, &from->sin6_addr,
+ ntopbuf[0], INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
+ return;
+ }
- /* TODO: some consistency check. */
+ /*
+ * If the IPv6 destination address is neither an All Routers multicast
+ * address [AARCH] nor one of the receiving router's unicast addresses,
+ * the message MUST be discarded and SHOULD be logged to network
+ * management.
+ * We rely on the kernel input routine for unicast addresses, and thus
+ * check multicast destinations only.
+ */
+ if (IN6_IS_ADDR_MULTICAST(&pi->ipi6_addr) &&
+ !IN6_ARE_ADDR_EQUAL(&in6a_site_allrouters, &pi->ipi6_addr)) {
+ syslog(LOG_NOTICE,
+ "<%s>: RR message with invalid destination (%s) "
+ "from %s on %s",
+ __FUNCTION__,
+ inet_ntop(AF_INET6, &dst, ntopbuf[0], INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &from->sin6_addr,
+ ntopbuf[1], INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
+ return;
+ }
+
+ rr_rcvifindex = pi->ipi6_ifindex;
switch (rr->rr_code) {
case ICMP6_ROUTER_RENUMBERING_COMMAND:
diff --git a/usr.sbin/rtadvd/rrenum.h b/usr.sbin/rtadvd/rrenum.h
index 3ab1e7d..ce94015 100644
--- a/usr.sbin/rtadvd/rrenum.h
+++ b/usr.sbin/rtadvd/rrenum.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME$ */
+/* $KAME: rrenum.h,v 1.3 2001/01/21 15:37:14 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
@@ -30,6 +30,5 @@
* SUCH DAMAGE.
*/
-void rr_input __P((int len, struct icmp6_router_renum *rr,
- struct in6_pktinfo *pi, struct sockaddr_in6 *from,
- struct in6_addr *dst));
+void rr_input __P((int, struct icmp6_router_renum *, struct in6_pktinfo *,
+ struct sockaddr_in6 *, struct in6_addr *));
diff --git a/usr.sbin/rtadvd/rtadvd.8 b/usr.sbin/rtadvd/rtadvd.8
index 3ddc77d..dcdcdab 100644
--- a/usr.sbin/rtadvd/rtadvd.8
+++ b/usr.sbin/rtadvd/rtadvd.8
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.\" $KAME: rtadvd.8,v 1.9 2000/05/27 13:37:01 jinmei Exp $
+.\" $KAME: rtadvd.8,v 1.17 2001/02/04 05:34:38 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -36,8 +36,8 @@
.Nd router advertisement daemon
.Sh SYNOPSIS
.Nm
+.Op Fl dDfMRs
.Op Fl c Ar configfile
-.Op Fl dDfRs
.Ar interface ...
.Sh DESCRIPTION
.Nm
@@ -77,6 +77,15 @@ Moreover, if the status of an advertising interface changes,
will start or stop sending router advertisements according
to the latest status.
.Pp
+Basically, hosts MUST NOT send Router Advertisement messages at any
+time (RFC 2461, Section 6.2.3).
+However, it would sometimes be useful to allow hosts to advertise some
+parameters such as prefix information and link MTU.
+Thus,
+.Nm
+can be invoked if router lifetime is explicitly set zero on every
+advertising interface.
+.Pp
The command line options are:
.Bl -tag -width indent
.\"
@@ -93,6 +102,15 @@ Print debugging information.
Even more debugging information is printed.
.It Fl f
Foreground mode (useful when debugging).
+.It Fl M
+Specify an interface to join the all-routers site-local multicast group.
+By default,
+.Nm
+tries to join the first advertising interface appeared in the command
+line.
+This option has meaning only with the
+.Fl R
+option, which enables routing renumbering protocol support.
.\".It Fl m
.\"Enables mobile IPv6 support.
.\"This changes the content of router advertisement option, as well as
@@ -100,6 +118,12 @@ Foreground mode (useful when debugging).
.It Fl R
Accept router renumbering requests.
If you enable it, certain IPsec setup is suggested for security reasons.
+On KAME-based systems,
+.Xr rrenumd 8
+generates router renumbering request packets.
+This option is currently disabled, and is ignored by
+.Nm
+with a warning message.
.It Fl s
Do not add or delete prefixes dynamically.
Only statically configured prefixes, if any, will be advertised.
@@ -138,17 +162,20 @@ in which
dumps its internal state.
.El
.Sh SEE ALSO
-.Xr daemon 3 ,
.Xr rtadvd.conf 5 ,
-.Xr rtsol 8
+.Xr rtsol 8 ,
+.Xr rrenumd 8
.Sh HISTORY
The
.Nm
command first appeared in WIDE Hydrangea IPv6 protocol stack kit.
.Sh CAVEAT
-Router advertisements should only be performed downstream.
-Erroneous upstream advertisements will cause
+There used to be some text that recommended users not to let
+.Nm
+advertise Router Advertisement messages on an upstream link to avoid
+undesirable
.Xr icmp6 4
-redirect packet storms in the subnet, as (per the specification) the
-advertising router is assumed to become the default router for
-end hosts in the subnet.
+redirect messages.
+However, based on the later discussion in the IETF ipng working group,
+all routers should rather advertise the messages regardless of
+the network topology, in order to ensure reachability.
diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c
index 000e612..e9931df 100644
--- a/usr.sbin/rtadvd/rtadvd.c
+++ b/usr.sbin/rtadvd/rtadvd.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: rtadvd.c,v 1.30 2000/06/22 20:16:12 itojun Exp $ */
+/* $KAME: rtadvd.c,v 1.50 2001/02/04 06:15:15 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -34,6 +34,7 @@
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/time.h>
+#include <sys/queue.h>
#include <net/if.h>
#include <net/route.h>
@@ -68,14 +69,18 @@ static size_t rcvcmsgbuflen;
static u_char *sndcmsgbuf = NULL;
static size_t sndcmsgbuflen;
static int do_dump;
+static int do_die;
struct msghdr sndmhdr;
struct iovec rcviov[2];
struct iovec sndiov[2];
struct sockaddr_in6 from;
struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6};
+struct in6_addr in6a_site_allrouters;
static char *dumpfilename = "/var/run/rtadvd.dump"; /* XXX: should be configurable */
static char *pidfilename = "/var/run/rtadvd.pid"; /* should be configurable */
-int sock, rtsock;
+static char *mcastif;
+int sock;
+int rtsock = -1;
#ifdef MIP6
int mobileip6 = 0;
#endif
@@ -120,7 +125,8 @@ u_int32_t ndopt_flags[] = {
};
int main __P((int, char *[]));
-static void die __P((int));
+static void set_die __P((int));
+static void die __P((void));
static void sock_open __P((void));
static void rtsock_open __P((void));
static void rtadvd_input __P((void));
@@ -133,7 +139,6 @@ static int prefix_check __P((struct nd_opt_prefix_info *, struct rainfo *,
static int nd6_options __P((struct nd_opt_hdr *, int,
union nd_opts *, u_int32_t));
static void free_ndopts __P((union nd_opts *));
-static struct rainfo *if_indextorainfo __P((int));
static void ra_output __P((struct rainfo *));
static void rtmsg_input __P((void));
static void rtadvd_set_dump_file __P((void));
@@ -157,9 +162,9 @@ main(argc, argv)
/* get command line options and arguments */
#ifdef MIP6
-#define OPTIONS "c:dDfmRs"
+#define OPTIONS "c:dDfM:mRs"
#else
-#define OPTIONS "c:dDfRs"
+#define OPTIONS "c:dDfM:Rs"
#endif
while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
#undef OPTIONS
@@ -176,13 +181,19 @@ main(argc, argv)
case 'f':
fflag = 1;
break;
+ case 'M':
+ mcastif = optarg;
+ break;
#ifdef MIP6
case 'm':
mobileip6 = 1;
break;
#endif
case 'R':
- accept_rr = 1;
+ fprintf(stderr, "rtadvd: "
+ "the -R option is currently ignored.\n");
+ /* accept_rr = 1; */
+ /* run anyway... */
break;
case 's':
sflag = 1;
@@ -194,9 +205,9 @@ main(argc, argv)
if (argc == 0) {
fprintf(stderr,
#ifdef MIP6
- "usage: rtadvd [-dDfmRs] [-c conffile] "
+ "usage: rtadvd [-dDfMmRs] [-c conffile] "
#else
- "usage: rtadvd [-dDfRs] [-c conffile] "
+ "usage: rtadvd [-dDfMRs] [-c conffile] "
#endif
"interfaces...\n");
exit(1);
@@ -243,12 +254,15 @@ main(argc, argv)
FD_ZERO(&fdset);
FD_SET(sock, &fdset);
maxfd = sock;
- rtsock_open();
- FD_SET(rtsock, &fdset);
- if (rtsock > sock)
+ if (sflag == 0) {
+ rtsock_open();
+ FD_SET(rtsock, &fdset);
+ if (rtsock > sock)
maxfd = rtsock;
+ } else
+ rtsock = -1;
- signal(SIGTERM, (void *)die);
+ signal(SIGTERM, (void *)set_die);
signal(SIGUSR1, (void *)rtadvd_set_dump_file);
while (1) {
@@ -259,6 +273,11 @@ main(argc, argv)
rtadvd_dump_file(dumpfilename);
}
+ if (do_die) {
+ die();
+ /*NOTREACHED*/
+ }
+
/* timer expiration check and reset the timer */
timeout = rtadvd_check_timer();
@@ -285,7 +304,7 @@ main(argc, argv)
}
if (i == 0) /* timeout */
continue;
- if (sflag == 0 && FD_ISSET(rtsock, &select_fd))
+ if (rtsock != -1 && FD_ISSET(rtsock, &select_fd))
rtmsg_input();
if (FD_ISSET(sock, &select_fd))
rtadvd_input();
@@ -300,9 +319,15 @@ rtadvd_set_dump_file()
}
static void
-die(sig)
+set_die(sig)
int sig;
{
+ do_die = 1;
+}
+
+static void
+die()
+{
struct rainfo *ra;
int i;
const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS;
@@ -331,13 +356,13 @@ rtmsg_input()
int n, type, ifindex = 0, plen;
size_t len;
char msg[2048], *next, *lim;
- u_char ifname[16];
+ u_char ifname[IF_NAMESIZE];
struct prefix *prefix;
struct rainfo *rai;
struct in6_addr *addr;
char addrbuf[INET6_ADDRSTRLEN];
- n = read(rtsock, msg, 2048);
+ n = read(rtsock, msg, sizeof(msg));
if (dflag > 1) {
syslog(LOG_DEBUG,
"<%s> received a routing message "
@@ -876,8 +901,8 @@ ra_input(int len, struct nd_router_advert *ra,
memset(&ndopts, 0, sizeof(ndopts));
if (nd6_options((struct nd_opt_hdr *)(ra + 1),
len - sizeof(struct nd_router_advert),
- &ndopts,
- NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
+ &ndopts, NDOPT_FLAG_SRCLINKADDR |
+ NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
syslog(LOG_ERR,
"<%s> ND option check failed for an RA from %s on %s",
__FUNCTION__,
@@ -905,7 +930,7 @@ ra_input(int len, struct nd_router_advert *ra,
/* Cur Hop Limit value */
if (ra->nd_ra_curhoplimit && rai->hoplimit &&
ra->nd_ra_curhoplimit != rai->hoplimit) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> CurHopLimit inconsistent on %s:"
" %d from %s, %d from us",
__FUNCTION__,
@@ -919,7 +944,7 @@ ra_input(int len, struct nd_router_advert *ra,
/* M flag */
if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) !=
rai->managedflg) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> M flag inconsistent on %s:"
" %s from %s, %s from us",
__FUNCTION__,
@@ -933,7 +958,7 @@ ra_input(int len, struct nd_router_advert *ra,
/* O flag */
if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) !=
rai->otherflg) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> O flag inconsistent on %s:"
" %s from %s, %s from us",
__FUNCTION__,
@@ -948,7 +973,7 @@ ra_input(int len, struct nd_router_advert *ra,
reachabletime = ntohl(ra->nd_ra_reachable);
if (reachabletime && rai->reachabletime &&
reachabletime != rai->reachabletime) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> ReachableTime inconsistent on %s:"
" %d from %s, %d from us",
__FUNCTION__,
@@ -963,7 +988,7 @@ ra_input(int len, struct nd_router_advert *ra,
retranstimer = ntohl(ra->nd_ra_retransmit);
if (retranstimer && rai->retranstimer &&
retranstimer != rai->retranstimer) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> RetranceTimer inconsistent on %s:"
" %d from %s, %d from us",
__FUNCTION__,
@@ -978,7 +1003,7 @@ ra_input(int len, struct nd_router_advert *ra,
if (ndopts.nd_opts_mtu) {
mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
if (mtu && rai->linkmtu && mtu != rai->linkmtu) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> MTU option value inconsistent on %s:"
" %d from %s, %d from us",
__FUNCTION__,
@@ -992,7 +1017,7 @@ ra_input(int len, struct nd_router_advert *ra,
/* Preferred and Valid Lifetimes for prefixes */
{
struct nd_optlist *optp = ndopts.nd_opts_list;
-
+
if (ndopts.nd_opts_pi) {
if (prefix_check(ndopts.nd_opts_pi, rai, from))
inconsistent++;
@@ -1005,10 +1030,8 @@ ra_input(int len, struct nd_router_advert *ra,
}
}
- if (inconsistent) {
- printf("RA input %d inconsistents\n", inconsistent);
+ if (inconsistent)
rai->rainconsistent++;
- }
done:
free_ndopts(&ndopts);
@@ -1024,6 +1047,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
struct prefix *pp;
int inconsistent = 0;
u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
+ struct timeval now;
#if 0 /* impossible */
if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION)
@@ -1061,8 +1085,36 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
}
preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time);
- if (preferred_time != pp->preflifetime) {
- syslog(LOG_WARNING,
+ if (pp->pltimeexpire) {
+ /*
+ * The lifetime is decremented in real time, so we should
+ * compare the expiration time.
+ * (RFC 2461 Section 6.2.7.)
+ * XXX: can we really expect that all routers on the link
+ * have synchronized clocks?
+ */
+ gettimeofday(&now, NULL);
+ preferred_time += now.tv_sec;
+
+ if (rai->clockskew &&
+ abs(preferred_time - pp->pltimeexpire) > rai->clockskew) {
+ syslog(LOG_INFO,
+ "<%s> prefeerred lifetime for %s/%d"
+ " (decr. in real time) inconsistent on %s:"
+ " %d from %s, %ld from us",
+ __FUNCTION__,
+ inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
+ prefixbuf, INET6_ADDRSTRLEN),
+ pinfo->nd_opt_pi_prefix_len,
+ rai->ifname, preferred_time,
+ inet_ntop(AF_INET6, &from->sin6_addr,
+ ntopbuf, INET6_ADDRSTRLEN),
+ pp->pltimeexpire);
+ inconsistent++;
+ }
+ }
+ else if (preferred_time != pp->preflifetime) {
+ syslog(LOG_INFO,
"<%s> prefeerred lifetime for %s/%d"
" inconsistent on %s:"
" %d from %s, %d from us",
@@ -1074,12 +1126,32 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
inet_ntop(AF_INET6, &from->sin6_addr,
ntopbuf, INET6_ADDRSTRLEN),
pp->preflifetime);
- inconsistent++;
}
valid_time = ntohl(pinfo->nd_opt_pi_valid_time);
- if (valid_time != pp->validlifetime) {
- syslog(LOG_WARNING,
+ if (pp->vltimeexpire) {
+ gettimeofday(&now, NULL);
+ valid_time += now.tv_sec;
+
+ if (rai->clockskew &&
+ abs(valid_time - pp->vltimeexpire) > rai->clockskew) {
+ syslog(LOG_INFO,
+ "<%s> valid lifetime for %s/%d"
+ " (decr. in real time) inconsistent on %s:"
+ " %d from %s, %ld from us",
+ __FUNCTION__,
+ inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
+ prefixbuf, INET6_ADDRSTRLEN),
+ pinfo->nd_opt_pi_prefix_len,
+ rai->ifname, preferred_time,
+ inet_ntop(AF_INET6, &from->sin6_addr,
+ ntopbuf, INET6_ADDRSTRLEN),
+ pp->vltimeexpire);
+ inconsistent++;
+ }
+ }
+ else if (valid_time != pp->validlifetime) {
+ syslog(LOG_INFO,
"<%s> valid lifetime for %s/%d"
" inconsistent on %s:"
" %d from %s, %d from us",
@@ -1118,6 +1190,26 @@ find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen)
return(NULL);
}
+/* check if p0/plen0 matches p1/plen1; return 1 if matches, otherwise 0. */
+int
+prefix_match(struct in6_addr *p0, int plen0,
+ struct in6_addr *p1, int plen1)
+{
+ int bytelen, bitlen;
+
+ if (plen0 < plen1)
+ return(0);
+ bytelen = plen1 / 8;
+ bitlen = plen1 % 8;
+ if (memcmp((void *)p0, (void *)p1, bytelen))
+ return(0);
+ if (p0->s6_addr[bytelen] >> (8 - bitlen) ==
+ p1->s6_addr[bytelen] >> (8 - bitlen))
+ return(1);
+
+ return(0);
+}
+
static int
nd6_options(struct nd_opt_hdr *hdr, int limit,
union nd_opts *ndopts, u_int32_t optflags)
@@ -1276,7 +1368,7 @@ sock_open()
__FUNCTION__, strerror(errno));
exit(1);
}
-#endif
+#endif
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
@@ -1293,7 +1385,8 @@ sock_open()
/*
* join all routers multicast address on each advertising interface.
*/
- if (inet_pton(AF_INET6, ALLROUTERS, &mreq.ipv6mr_multiaddr.s6_addr)
+ if (inet_pton(AF_INET6, ALLROUTERS_LINK,
+ &mreq.ipv6mr_multiaddr.s6_addr)
!= 1) {
syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
__FUNCTION__);
@@ -1301,15 +1394,47 @@ sock_open()
}
while(ra) {
mreq.ipv6mr_interface = ra->ifindex;
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- &mreq,
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
sizeof(mreq)) < 0) {
- syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP on %s: %s",
+ syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s",
__FUNCTION__, ra->ifname, strerror(errno));
exit(1);
}
ra = ra->next;
}
+
+ /*
+ * When attending router renumbering, join all-routers site-local
+ * multicast group.
+ */
+ if (accept_rr) {
+ if (inet_pton(AF_INET6, ALLROUTERS_SITE,
+ &in6a_site_allrouters) != 1) {
+ syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
+ __FUNCTION__);
+ exit(1);
+ }
+ mreq.ipv6mr_multiaddr = in6a_site_allrouters;
+ if (mcastif) {
+ if ((mreq.ipv6mr_interface = if_nametoindex(mcastif))
+ == 0) {
+ syslog(LOG_ERR,
+ "<%s> invalid interface: %s",
+ __FUNCTION__, mcastif);
+ exit(1);
+ }
+ } else
+ mreq.ipv6mr_interface = ralist->ifindex;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ &mreq, sizeof(mreq)) < 0) {
+ syslog(LOG_ERR,
+ "<%s> IPV6_JOIN_GROUP(site) on %s: %s",
+ __FUNCTION__,
+ mcastif ? mcastif : ralist->ifname,
+ strerror(errno));
+ exit(1);
+ }
+ }
/* initialize msghdr for receiving packets */
rcviov[0].iov_base = (caddr_t)answer;
@@ -1342,7 +1467,7 @@ rtsock_open()
}
}
-static struct rainfo *
+struct rainfo *
if_indextorainfo(int index)
{
struct rainfo *rai = ralist;
@@ -1370,6 +1495,8 @@ struct rainfo *rainfo;
return;
}
+ make_packet(rainfo); /* XXX: inefficient */
+
sndmhdr.msg_name = (caddr_t)&sin6_allnodes;
sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data;
sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen;
@@ -1474,7 +1601,7 @@ ra_timer_update(void *data, struct timeval *tm)
* Whenever a multicast advertisement is sent from an interface,
* the timer is reset to a uniformly-distributed random value
* between the interface's configured MinRtrAdvInterval and
- * MaxRtrAdvInterval(discovery-v2-02 6.2.4).
+ * MaxRtrAdvInterval (RFC2461 6.2.4).
*/
interval = rai->mininterval;
interval += random() % (rai->maxinterval - rai->mininterval);
diff --git a/usr.sbin/rtadvd/rtadvd.conf.5 b/usr.sbin/rtadvd/rtadvd.conf.5
index b6d4f5c..9b9faaa 100644
--- a/usr.sbin/rtadvd/rtadvd.conf.5
+++ b/usr.sbin/rtadvd/rtadvd.conf.5
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.\" $KAME: rtadvd.conf.5,v 1.32 2001/01/19 05:32:05 jinmei Exp $
+.\" $KAME: rtadvd.conf.5,v 1.35 2001/05/25 07:40:22 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -117,6 +117,16 @@ and Bit 6
.Li 0x40
.Pc
means Other stateful configuration flag bit.
+Bit 4
+.Po
+.Li 0x10
+.Pc
+and Bit 3
+.Po
+.Li 0x08
+.Pc
+are used to encode router preference.
+0x01 means high, 0x00 means medium, and 0x11 means low.
The default value is 0.
.It Cm \&rltime
(num) Router lifetime field
@@ -145,6 +155,17 @@ These items can be omitted, then
will automatically get appropriate prefixes from the kernel's routing table,
and advertise the prefixes with the default parameters.
.Bl -tag -width indent
+.It Cm \&clockskew
+(num) Time skew to adjust link propagation delays and clock skews
+betwen routers on the link
+.Pq unit: seconds .
+This value is used in consistency check for locally-configured and
+advertised prefix lifetimes, and has its meaning when the local router
+configures a prefix on the link with a lifetime that decrements in
+real time.
+If the value is 0, it means the consistency check will be skipped
+for such prefixes.
+The default value is 0.
.It Cm \&addrs
(num) Number of prefixes.
Its default is 0, so it must explicitly be set to positve values
@@ -193,10 +214,16 @@ is more than 0.
(num) Valid lifetime field
.Pq unit: seconds .
The default value is 2592000 (30 days).
+.It Cm \&vltimedecr
+(bool) This item means the advertised valid lifetime will decrements
+in real time, which is disabled by default.
.It Cm \&pltime
(num) Preferred lifetime field
.Pq unit: seconds .
The default value is 604800 (7 days).
+.It Cm \&pltimedecr
+(bool) This item means the advertised preferred lifetime will decrements
+in real time, which is disabled by default.
.El
.Pp
The following item is for ICMPv6 MTU option,
@@ -237,6 +264,75 @@ will not attach source link-layer address option to
router advertisement packets.
.El
.Pp
+The following item controls ICMPV6 home agent information option,
+which was defined with mobile IPv6 support.
+It will be attached to router advertisement header just like other options do.
+.Bl -tag -width indent
+.It Cm \&hapref
+(num) Specifies home agent preference.
+If set to non-zero,
+.Cm \&hatime
+must be present as well.
+.It Cm \&hatime
+(num) Specifies home agent lifetime.
+.El
+.Pp
+When mobile IPv6 support is turned on for
+.Xr rtadvd 8 ,
+advertisement interval option will be attached to router advertisement
+packet, by configuring
+.Cm \&maxinterval
+explicitly.
+.Pp
+The following items are for ICMPv6 route information option,
+which will be attached to router advertisement header.
+These items are optional.
+.Bl -tag -width indent
+.It Cm \&routes
+(num) Number of routes.
+Its default is 0, so it must explicitly be set to positve values
+if you want to specify any route information option.
+If its value is 0, no route information is sent.
+If its value is more than 1, you must specify the index of the routes
+for each item below.
+Indices vary from 0 to N-1, where N is the
+value of
+.Cm routes.
+Each index shall follow the name of each item, e.g.,
+.Dq rtrplen2 .
+.It Cm \&rtrplen
+(num) Prefix length field in route information option.
+The default value is 64.
+.It Cm \&rtrflags
+(num) Flags field in route information option.
+Bit 4
+.Po
+.Li 0x10
+.Pc
+and
+and Bit 3
+.Po
+.Li 0x08
+.Pc
+are used to encode router preference for the route.
+The default value is 0x00, i.e. medium router preference.
+.It Cm \&rtrprefix
+(str) The prefix filled into the Prefix field of route information option.
+Since
+.Dq \&:
+is used for
+.Xr termcap 5
+file format as well as IPv6 numeric address, the field MUST be quoted by
+doublequote character.
+This field cannot be
+omitted if the value of
+.Cm addrs
+is more than 0.
+.It Cm \&rtrltime
+(num) route lifetime field in route information option.
+.Pq unit: seconds .
+The default value is 2592000 (30 days). (not specified in draft-draves-router-selection-01.txt now)
+.El
You can also refer one line from another by using
.Cm tc
capability.
@@ -293,6 +389,12 @@ Thomas Narten, Erik Nordmark and W. A. Simpson,
Neighbor Discovery for IP version 6 (IPv6)
.Dc ,
RFC 2461
+.Pp
+Richard Draves,
+.Do
+Default Router Preferences and More-Specific Routes
+.Dc ,
+draft-ietf-ipngwg-router-selection-01.txt
.Sh HISTORY
The
.Xr rtadvd 8
diff --git a/usr.sbin/rtadvd/rtadvd.h b/usr.sbin/rtadvd/rtadvd.h
index 3ffc7e6..c05dcf4 100644
--- a/usr.sbin/rtadvd/rtadvd.h
+++ b/usr.sbin/rtadvd/rtadvd.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: rtadvd.h,v 1.8 2000/05/16 13:34:14 itojun Exp $ */
+/* $KAME: rtadvd.h,v 1.16 2001/04/10 15:08:31 suz Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
@@ -31,7 +31,8 @@
*/
#define ALLNODES "ff02::1"
-#define ALLROUTERS "ff02::2"
+#define ALLROUTERS_LINK "ff02::2"
+#define ALLROUTERS_SITE "ff05::2"
#define ANY "::"
#define RTSOLLEN 8
@@ -74,7 +75,9 @@ struct prefix {
struct prefix *prev; /* previous link */
u_int32_t validlifetime; /* AdvValidLifetime */
+ long vltimeexpire; /* expiration of vltime; decrement case only */
u_int32_t preflifetime; /* AdvPreferredLifetime */
+ long pltimeexpire; /* expiration of pltime; decrement case only */
u_int onlinkflg; /* bool: AdvOnLinkFlag */
u_int autoconfflg; /* bool: AdvAutonomousFlag */
#ifdef MIP6
@@ -85,6 +88,16 @@ struct prefix {
struct in6_addr prefix;
};
+struct rtinfo {
+ struct rtinfo *prev; /* previous link */
+ struct rtinfo *next; /* forward link */
+
+ u_int32_t ltime; /* route lifetime */
+ u_int rtpref; /* router preference */
+ int prefixlen;
+ struct in6_addr prefix;
+};
+
struct soliciter {
struct soliciter *next;
struct sockaddr_in6 addr;
@@ -116,17 +129,21 @@ struct rainfo {
#ifdef MIP6
int haflg; /* HAFlag */
#endif
+ int rtpref; /* router preference */
u_int32_t linkmtu; /* AdvLinkMTU */
u_int32_t reachabletime; /* AdvReachableTime */
u_int32_t retranstimer; /* AdvRetransTimer */
u_int hoplimit; /* AdvCurHopLimit */
struct prefix prefix; /* AdvPrefixList(link head) */
int pfxs; /* number of prefixes */
+ long clockskew; /* used for consisitency check of lifetimes */
#ifdef MIP6
u_short hapref; /* Home Agent Preference */
u_short hatime; /* Home Agent Lifetime */
#endif
+ struct rtinfo route; /* route information option (link head) */
+ int routes; /* number of route information options */
/* actual RA packet data and its length */
size_t ra_datalen;
@@ -145,6 +162,10 @@ struct rainfo {
void ra_timeout __P((void *));
void ra_timer_update __P((void *, struct timeval *));
+int prefix_match __P((struct in6_addr *, int, struct in6_addr *, int));
+struct rainfo *if_indextorainfo __P((int));
+
+extern struct in6_addr in6a_site_allrouters;
#ifdef MIP6
extern int mobileip6;
#endif
diff --git a/usr.sbin/rtadvd/timer.c b/usr.sbin/rtadvd/timer.c
index 7ccfb7e..439cbb2 100644
--- a/usr.sbin/rtadvd/timer.c
+++ b/usr.sbin/rtadvd/timer.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: timer.c,v 1.3 2000/05/22 22:23:07 itojun Exp $ */
+/* $KAME: timer.c,v 1.4 2000/05/27 11:30:43 jinmei Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
diff --git a/usr.sbin/rtadvd/timer.h b/usr.sbin/rtadvd/timer.h
index c5f8b85..3baf0d0 100644
--- a/usr.sbin/rtadvd/timer.h
+++ b/usr.sbin/rtadvd/timer.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: timer.h,v 1.2 2000/05/16 13:34:14 itojun Exp $ */
+/* $KAME: timer.h,v 1.3 2000/05/27 11:30:43 jinmei Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
OpenPOWER on IntegriCloud