summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/rtadvd/config.c184
-rw-r--r--usr.sbin/rtadvd/dump.c30
-rw-r--r--usr.sbin/rtadvd/if.c61
-rw-r--r--usr.sbin/rtadvd/if.h5
-rw-r--r--usr.sbin/rtadvd/rrenum.c98
-rw-r--r--usr.sbin/rtadvd/rtadvd.859
-rw-r--r--usr.sbin/rtadvd/rtadvd.c194
-rw-r--r--usr.sbin/rtadvd/rtadvd.conf2
-rw-r--r--usr.sbin/rtadvd/rtadvd.conf.592
-rw-r--r--usr.sbin/rtadvd/rtadvd.h14
10 files changed, 606 insertions, 133 deletions
diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c
index 6e34165f64b..51c69fb2dd3 100644
--- a/usr.sbin/rtadvd/config.c
+++ b/usr.sbin/rtadvd/config.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: config.c,v 1.7 2000/07/06 10:14:46 itojun Exp $ */
-/* $KAME: config.c,v 1.12 2000/05/22 22:23:07 itojun Exp $ */
+/* $OpenBSD: config.c,v 1.8 2001/01/15 11:06:24 itojun Exp $ */
+/* $KAME: config.c,v 1.26 2000/12/25 12:19:27 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;
@@ -85,6 +88,7 @@ getconfig(intface)
char buf[BUFSIZ];
char *bp = buf;
char *addr;
+ static int forwarding = -1;
#define MUSTHAVE(var, cap) \
do { \
@@ -115,6 +119,12 @@ getconfig(intface)
memset(tmp, 0, sizeof(*tmp));
tmp->prefix.next = tmp->prefix.prev = &tmp->prefix;
+ /* 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"))
tmp->advlinkopt = 0;
@@ -180,6 +190,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);
@@ -233,6 +258,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)) {
@@ -303,6 +337,14 @@ getconfig(intface)
}
pfx->validlifetime = (u_int32_t)val;
+ 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) {
@@ -313,6 +355,14 @@ getconfig(intface)
}
pfx->preflifetime = (u_int32_t)val;
+ 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);
if (addr == NULL) {
@@ -383,6 +433,7 @@ getconfig(intface)
static void
get_prefix(struct rainfo *rai)
{
+#if 0
size_t len;
u_char *buf, *lim, *next;
u_char ntopbuf[INET6_ADDRSTRLEN];
@@ -426,14 +477,14 @@ get_prefix(struct rainfo *rai)
if ((pp->prefixlen = get_prefixlen(next)) < 0) {
syslog(LOG_ERR,
"<%s> failed to get prefixlen "
- "or prefixl is invalid",
+ "or prefix is invalid",
__FUNCTION__);
exit(1);
}
syslog(LOG_DEBUG,
"<%s> add %s/%d to prefix list on %s",
__FUNCTION__,
- inet_ntop(AF_INET6, a, ntopbuf, INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, a, ntopbuf, sizeof(ntopbuf)),
pp->prefixlen, rai->ifname);
/* set other fields with protocol defaults */
@@ -456,6 +507,83 @@ get_prefix(struct rainfo *rai)
}
free(buf);
+#else
+ struct ifaddrs *ifap, *ifa;
+ struct prefix *pp;
+ struct in6_addr *a;
+ u_char *p, *ep, *m, *lim;
+ u_char ntopbuf[INET6_ADDRSTRLEN];
+
+ if (getifaddrs(&ifap) < 0) {
+ syslog(LOG_ERR,
+ "<%s> can't get interface addresses",
+ __FUNCTION__);
+ exit(1);
+ }
+ 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) {
+ syslog(LOG_ERR,
+ "<%s> can't get allocate buffer for prefix",
+ __FUNCTION__);
+ exit(1);
+ }
+ memset(pp, 0, sizeof(*pp));
+
+ /* 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 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__, ntopbuf, pp->prefixlen, rai->ifname);
+
+ /* set other fields with protocol defaults */
+ pp->validlifetime = DEF_ADVVALIDLIFETIME;
+ pp->preflifetime = DEF_ADVPREFERREDLIFETIME;
+ pp->onlinkflg = 1;
+ pp->autoconfflg = 1;
+ pp->origin = PREFIX_FROM_KERNEL;
+
+ /* link into chain */
+ insque(pp, &rai->prefix);
+
+ /* counter increment */
+ rai->pfxs++;
+ }
+
+ freeifaddrs(ifap);
+#endif
}
static void
@@ -491,6 +619,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;
@@ -717,6 +846,9 @@ make_packet(struct rainfo *rainfo)
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,9 +865,27 @@ make_packet(struct rainfo *rainfo)
ndopt_pi->nd_opt_pi_flags_reserved |=
ND_OPT_PI_FLAG_RTADDR;
#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 = ntohl(vltime);
+ ndopt_pi->nd_opt_pi_preferred_time = ntohl(pltime);
ndopt_pi->nd_opt_pi_reserved2 = 0;
ndopt_pi->nd_opt_pi_prefix = pfx->prefix;
@@ -744,3 +894,23 @@ make_packet(struct rainfo *rainfo)
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/dump.c b/usr.sbin/rtadvd/dump.c
index 893c4389068..38698653b43 100644
--- a/usr.sbin/rtadvd/dump.c
+++ b/usr.sbin/rtadvd/dump.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: dump.c,v 1.2 2000/07/06 10:14:46 itojun Exp $ */
-/* $KAME: dump.c,v 1.11 2000/05/27 11:30:43 jinmei Exp $ */
+/* $OpenBSD: dump.c,v 1.3 2001/01/15 11:06:25 itojun Exp $ */
+/* $KAME: dump.c,v 1.15 2000/11/11 06:57:22 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
@@ -97,7 +98,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);
@@ -155,6 +158,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 +183,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/if.c b/usr.sbin/rtadvd/if.c
index 849c4b7e8d4..f7238d63d3c 100644
--- a/usr.sbin/rtadvd/if.c
+++ b/usr.sbin/rtadvd/if.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if.c,v 1.6 2000/09/01 01:24:04 itojun Exp $ */
-/* $KAME: if.c,v 1.12 2000/08/31 16:35:29 itojun Exp $ */
+/* $OpenBSD: if.c,v 1.7 2001/01/15 11:06:25 itojun Exp $ */
+/* $KAME: if.c,v 1.15 2000/10/25 04:30:44 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -147,42 +147,44 @@ if_nametosdl(char *name)
int
if_getmtu(char *name)
{
-#ifdef SIOCGIFMTU
- struct ifreq ifr;
- int s;
-
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
- return(0);
-
- ifr.ifr_addr.sa_family = AF_INET6;
- strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) {
- close(s);
- return(0);
- }
-
- close(s);
-
- return(ifr.ifr_mtu);
-#else
struct ifaddrs *ifap, *ifa;
struct if_data *ifd;
+ u_long mtu = 0;
if (getifaddrs(&ifap) < 0)
return(0);
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (strcmp(ifa->ifa_name, name) == 0) {
ifd = ifa->ifa_data;
- freeifaddrs(ifap);
if (ifd)
- return ifd->ifi_mtu;
- else
- return 0;
+ mtu = ifd->ifi_mtu;
+ break;
}
}
freeifaddrs(ifap);
- return 0;
+
+#ifdef SIOCGIFMTU /* XXX: this ifdef may not be necessary */
+ if (mtu == 0) {
+ struct ifreq ifr;
+ int s;
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
+ return(0);
+
+ ifr.ifr_addr.sa_family = AF_INET6;
+ strncpy(ifr.ifr_name, name,
+ sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) {
+ close(s);
+ return(0);
+ }
+ close(s);
+
+ mtu = ifr.ifr_mtu;
+ }
#endif
+
+ return(mtu);
}
/* give interface index and its old flags, then new flags returned */
@@ -410,7 +412,6 @@ get_prefixlen(char *buf)
{
struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
struct sockaddr *sa, *rti_info[RTAX_MAX];
- int masklen;
u_char *p, *lim;
sa = (struct sockaddr *)(rtm + 1);
@@ -419,6 +420,14 @@ get_prefixlen(char *buf)
p = (u_char *)(&SIN6(sa)->sin6_addr);
lim = (u_char *)sa + sa->sa_len;
+ return prefixlen(p, lim);
+}
+
+int
+prefixlen(u_char *p, u_char *lim)
+{
+ int masklen;
+
for (masklen = 0; p < lim; p++) {
switch (*p) {
case 0xff:
diff --git a/usr.sbin/rtadvd/if.h b/usr.sbin/rtadvd/if.h
index 77093d05939..07642c0deee 100644
--- a/usr.sbin/rtadvd/if.h
+++ b/usr.sbin/rtadvd/if.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: if.h,v 1.4 2000/07/06 10:14:47 itojun Exp $ */
-/* $KAME: if.h,v 1.3 2000/05/27 11:47:09 itojun Exp $ */
+/* $OpenBSD: if.h,v 1.5 2001/01/15 11:06:26 itojun Exp $ */
+/* $KAME: if.h,v 1.4 2000/09/06 20:06:30 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -52,6 +52,7 @@ 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 prefixlen __P((u_char *, u_char *));
int rtmsg_type __P((char *buf));
int ifmsg_type __P((char *buf));
int rtmsg_len __P((char *buf));
diff --git a/usr.sbin/rtadvd/rrenum.c b/usr.sbin/rtadvd/rrenum.c
index dd5fde63576..0d371cc7f00 100644
--- a/usr.sbin/rtadvd/rrenum.c
+++ b/usr.sbin/rtadvd/rrenum.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rrenum.c,v 1.5 2000/07/06 10:14:47 itojun Exp $ */
-/* $KAME: rrenum.c,v 1.4 2000/07/03 02:51:08 itojun Exp $ */
+/* $OpenBSD: rrenum.c,v 1.6 2001/01/15 11:06:27 itojun Exp $ */
+/* $KAME: rrenum.c,v 1.8 2000/11/11 16:37:07 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/rtadvd.8 b/usr.sbin/rtadvd/rtadvd.8
index 13cb1d4463d..58e40c21f06 100644
--- a/usr.sbin/rtadvd/rtadvd.8
+++ b/usr.sbin/rtadvd/rtadvd.8
@@ -1,5 +1,5 @@
-.\" $OpenBSD: rtadvd.8,v 1.12 2000/07/06 10:14:47 itojun Exp $
-.\" $KAME: rtadvd.8,v 1.9 2000/05/27 13:37:01 jinmei Exp $
+.\" $OpenBSD: rtadvd.8,v 1.13 2001/01/15 11:06:28 itojun Exp $
+.\" $KAME: rtadvd.8,v 1.15 2000/12/22 08:54:29 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -41,18 +41,18 @@
.Ar interface ...
.Sh DESCRIPTION
.Nm
-advertises router advertisement packet to the specified
+sends router advertisement packets to the specified
.Ar interfaces .
.Pp
The program will daemonize itself on invocation.
-It will then periodically send router advertisement packets, as well
+It will then send router advertisement packets periodically, as well
as in response to router solicitation messages sent by end hosts.
.Pp
Router advertisements can be configured on a per-interface basis, as
described in
.Xr rtadvd.conf 5 .
.Pp
-In the event of no configuration file entry for an interface,
+If there is no configuration file entry for an interface,
or if the configuration file does not exist altogether,
.Nm
sets all the parameters to their default values.
@@ -70,13 +70,22 @@ specified by the configuration file,
adds/deletes the corresponding prefix to/from its advertising list,
respectively.
The
-.Ic Fl s
-may be used to disable this behavior.
+.Fl s
+option may be used to disable this behavior.
Moreover, if the status of an advertising interface changes,
.Nm
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 auto routing renumbering.
.\".It Fl m
.\"Enables mobile IPv6 support.
.\"This changes the content of router advertisement option, as well as
@@ -109,7 +127,7 @@ Upon receipt of signal
.Dv SIGUSR1 ,
.Nm
will dump the current internal state into
-.Pa /var/run/rtadvd.dump.
+.Pa /var/run/rtadvd.dump .
.Pp
Use
.Dv SIGTERM
@@ -120,18 +138,20 @@ In this case,
.Nm
will transmit router advertisement with router lifetime 0
to all the interfaces
-.Pq according to RFC2461 6.2.5 .
+.Pq in accordance with RFC2461 6.2.5 .
.Sh RETURN VALUES
-The program exits with 0 on success, and non-zero on failures.
+The
+.Nm
+program exits 0 on success, and >0 on failures.
.Sh FILES
-.Bl -tag -width /etc/rtadvd.conf -compact
+.Bl -tag -width Pa -compact
.It Pa /etc/rtadvd.conf
The default configuration file.
.It Pa /var/run/rtadvd.pid
-contains pid of the currently running
+contains the pid of the currently running
.Nm rtadvd .
.It Pa /var/run/rtadvd.dump
-on which
+in which
.Nm
dumps its internal state.
.El
@@ -144,9 +164,12 @@ 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 c0d1e46a5fb..a67aae688b3 100644
--- a/usr.sbin/rtadvd/rtadvd.c
+++ b/usr.sbin/rtadvd/rtadvd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rtadvd.c,v 1.7 2000/07/06 10:14:48 itojun Exp $ */
-/* $KAME: rtadvd.c,v 1.31 2000/06/23 06:34:51 itojun Exp $ */
+/* $OpenBSD: rtadvd.c,v 1.8 2001/01/15 11:06:28 itojun Exp $ */
+/* $KAME: rtadvd.c,v 1.47 2001/01/15 05:50:25 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,13 +69,16 @@ 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 */
+static char *mcastif;
int sock, rtsock;
#ifdef MIP6
int mobileip6 = 0;
@@ -120,7 +124,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 +138,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 +161,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,6 +180,9 @@ main(argc, argv)
case 'f':
fflag = 1;
break;
+ case 'M':
+ mcastif = optarg;
+ break;
#ifdef MIP6
case 'm':
mobileip6 = 1;
@@ -194,9 +201,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);
@@ -246,9 +253,9 @@ main(argc, argv)
rtsock_open();
FD_SET(rtsock, &fdset);
if (rtsock > sock)
- maxfd = rtsock;
+ maxfd = rtsock;
- signal(SIGTERM, (void *)die);
+ signal(SIGTERM, (void *)set_die);
signal(SIGUSR1, (void *)rtadvd_set_dump_file);
while (1) {
@@ -259,6 +266,11 @@ main(argc, argv)
rtadvd_dump_file(dumpfilename);
}
+ if (do_die) {
+ die();
+ /*NOTREACHED*/
+ }
+
/* timer expiration check and reset the timer */
timeout = rtadvd_check_timer();
@@ -300,9 +312,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 +349,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 +894,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 +923,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 +937,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 +951,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 +966,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 +981,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 +996,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 +1010,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 +1023,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 +1040,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 +1078,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 +1119,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 +1183,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 +1361,7 @@ sock_open()
__FUNCTION__, strerror(errno));
exit(1);
}
-#endif
+#endif
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
@@ -1293,7 +1378,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 +1387,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 +1460,7 @@ rtsock_open()
}
}
-static struct rainfo *
+struct rainfo *
if_indextorainfo(int index)
{
struct rainfo *rai = ralist;
@@ -1370,6 +1488,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 +1594,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 b/usr.sbin/rtadvd/rtadvd.conf
index 418b665871f..bb8a496758a 100644
--- a/usr.sbin/rtadvd/rtadvd.conf
+++ b/usr.sbin/rtadvd/rtadvd.conf
@@ -18,7 +18,7 @@
# per-interface definitions.
# Mainly IPv6 prefixes are configured in this part. However, rtadvd
# automatically learns appropriate prefixes from the kernel's routing
-# table and advertises the prefixes, so you don't have to configure
+# table, and advertises the prefixes, so you don't have to configure
# this part, either.
# If you don't want the automatic advertisement, invoke rtadvd with
# the -s option and configure this part by hand.
diff --git a/usr.sbin/rtadvd/rtadvd.conf.5 b/usr.sbin/rtadvd/rtadvd.conf.5
index 9db54596a8f..533defa7e7f 100644
--- a/usr.sbin/rtadvd/rtadvd.conf.5
+++ b/usr.sbin/rtadvd/rtadvd.conf.5
@@ -1,5 +1,5 @@
-.\" $OpenBSD: rtadvd.conf.5,v 1.11 2000/12/15 14:31:18 aaron Exp $
-.\" $KAME: rtadvd.conf.5,v 1.6 2000/05/26 10:54:58 jinmei Exp $
+.\" $OpenBSD: rtadvd.conf.5,v 1.12 2001/01/15 11:06:30 itojun Exp $
+.\" $KAME: rtadvd.conf.5,v 1.19 2001/01/15 11:02:26 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -37,6 +37,15 @@
.Sh DESCRIPTION
This file describes how the router advertisement packets must be constructed
for each of the interfaces.
+As described in
+.Xr rtadvd 8 ,
+you do not have to set this configuration file up at all,
+unless you need some special configurations.
+You may even omit to create this file.
+In such cases, the
+.Nm rtadvd
+daemon will automatically configure itself using default values
+specified in the specification.
.Pp
It obeys the famous
.Xr termcap 5
@@ -49,7 +58,7 @@ Lines may be concatenated by the
.Sq \e
character.
The comment marker is the
-.Sq \#
+.Sq \&#
character.
.Pp
.Sh CAPABILITIES
@@ -64,6 +73,9 @@ Note that almost all items have default values.
If you omit an item, the default value of the item will be used.
.Pp
There are two items which control the interval of sending router advertisements.
+These items can be omitted, then
+.Nm rtadvd
+will use the default values.
.Bl -tag -width indent
.It Cm \&maxinterval
(num) The maximum time allowed between sending unsolicited
@@ -85,6 +97,9 @@ the value of
.Pp
The following items are for ICMPv6 router advertisement message
header.
+These items can be omitted, then
+.Nm rtadvd
+will use the default values.
.Bl -tag -width indent
.It Cm \&chlim
(num) The value for Cur Hop Limit field.
@@ -106,6 +121,11 @@ The default value is 0.
(num) Router lifetime field
.Pq unit: seconds .
Its value must be no greater than 3600000.
+When
+.Nm rtadvd
+runs on a host, this value must explicitly set 0 on all the
+advertising interfaces as described in
+.Xr rtadvd 8 .
The default value is 1800.
.It Cm \&rtime
(num) Reachable time field
@@ -119,7 +139,20 @@ The default value is 0, which means unspecified by this router.
.Pp
The following items are for ICMPv6 prefix information option,
which will be attached to router advertisement header.
+These items can be omitted, then
+.Nm rtadvd
+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
@@ -162,20 +195,29 @@ 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
-.Ic addrs
+.Cm addrs
is more than 0.
.It Cm \&vltime
(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 items are for ICMPv6 MTU option,
+The following item is for ICMPv6 MTU option,
which will be attached to router advertisement header.
+This item can be omitted, then
+.Nm rtadvd
+will use the default value.
.Bl -tag -width indent
.It Cm \&mtu
(num or str) MTU (maximum transmission unit) field.
@@ -189,6 +231,9 @@ will be set to the interface MTU automatically.
.Pp
The following item controls ICMPv6 source link-layer address option,
which will be attached to router advertisement header.
+As noted above, you can just omit the item, then
+.Nm rtadvd
+will use the default value.
.Bl -tag -width indent
.It Cm \&nolladdr
(bool) By default
@@ -217,21 +262,30 @@ for details on the capability.
#
# common definitions.
#
-default:\\
- :raflags#0:rltime#3600:\\
- :pinfoflags#64:vltime#360000:pltime#360000:mtu#1500:
-ether:\\
- :mtu#1280:tc=default:
-
-#
-# interfaces.
+# Note: All of the following parameters have default values defined
+# in specifications, and hence you usually do not have to set them
+# by hand unless you need special non-default values.
#
-ef0:\\
- :addrs#1:\\
- :addr="3ffe:501:4819:1000::":tc=ether:
-ef1:\\
- :addrs#2:addr0="3ffe:501:4819:2000::":\\
- :addr1="3ffe:501:4819:3000::":tc=ether:
+# You even do not need to create the configuration file. rtadvd
+# would usually work well without a configuration file.
+# See also: rtadvd(8)
+
+#default:\\
+# :chlim#64:raflags#0:rltime#1800:rtime#30000:retrans#1000:\\
+# :pinfoflags#192:vltime#3600000:pltime#3600000:mtu#1500:
+#ether:\\
+# :mtu#1500:tc=default:
+
+# per-interface definitions.
+# Mainly IPv6 prefixes are configured in this part. However, rtadvd
+# automatically learns appropriate prefixes from the kernel's routing
+# table, and advertises the prefixes, so you don't have to configure
+# this part, either.
+# If you don't want the automatic advertisement, invoke rtadvd with
+# the -s option and configure this part by hand.
+
+#ef0:\\
+# :addrs#1:addr="3ffe:501:4819:1000::":prefixlen#64:tc=ether:
.Ed
.Sh SEE ALSO
diff --git a/usr.sbin/rtadvd/rtadvd.h b/usr.sbin/rtadvd/rtadvd.h
index ce16f907302..456fd5257d7 100644
--- a/usr.sbin/rtadvd/rtadvd.h
+++ b/usr.sbin/rtadvd/rtadvd.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: rtadvd.h,v 1.5 2000/07/06 10:14:48 itojun Exp $ */
-/* $KAME: rtadvd.h,v 1.9 2000/06/22 20:16:13 itojun Exp $ */
+/* $OpenBSD: rtadvd.h,v 1.6 2001/01/15 11:06:30 itojun Exp $ */
+/* $KAME: rtadvd.h,v 1.14 2000/11/11 06:57:22 jinmei 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
@@ -122,6 +125,7 @@ struct rainfo {
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 */
@@ -145,6 +149,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