diff --git a/usr.sbin/rtadvd/Makefile b/usr.sbin/rtadvd/Makefile index 561883e943d8..d1ca23ba8641 100644 --- a/usr.sbin/rtadvd/Makefile +++ b/usr.sbin/rtadvd/Makefile @@ -18,7 +18,7 @@ PROG= rtadvd MAN= rtadvd.conf.5 rtadvd.8 SRCS= rtadvd.c rrenum.c advcap.c if.c config.c timer.c dump.c -CFLAGS+= -DINET6 -DHAVE_ARC4RANDOM -DHAVE_POLL_H +CFLAGS+= -DINET6 -DHAVE_ARC4RANDOM -DHAVE_POLL_H -DROUTEINFO DPADD= ${LIBCOMPAT} LDADD= -lcompat diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c index bb6ba9d43930..27bedd7e5f2a 100644 --- a/usr.sbin/rtadvd/config.c +++ b/usr.sbin/rtadvd/config.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: config.c,v 1.37 2001/05/25 07:34:00 itojun Exp $ */ +/* $KAME: config.c,v 1.84 2003/08/05 12:34:23 itojun Exp $ */ /* * Copyright (C) 1998 WIDE Project. @@ -68,22 +68,21 @@ static time_t prefix_timo = (60 * 120); /* 2 hours. extern struct rainfo *ralist; static struct rtadvd_timer *prefix_timeout __P((void *)); -static void makeentry __P((char *, size_t, int, char *, int)); -static void get_prefix __P((struct rainfo *)); +static void makeentry __P((char *, size_t, int, char *)); static int getinet6sysctl __P((int)); void getconfig(intface) char *intface; { - int stat, pfxs, i; + int stat, i; char tbuf[BUFSIZ]; struct rainfo *tmp; long val; int64_t val64; char buf[BUFSIZ]; char *bp = buf; - char *addr; + char *addr, *flagstr; static int forwarding = -1; #define MUSTHAVE(var, cap) \ @@ -119,7 +118,9 @@ getconfig(intface) } memset(tmp, 0, sizeof(*tmp)); tmp->prefix.next = tmp->prefix.prev = &tmp->prefix; +#ifdef ROUTEINFO tmp->route.next = tmp->route.prev = &tmp->route; +#endif /* check if we are allowed to forward packets (if not determined) */ if (forwarding < 0) { @@ -156,17 +157,18 @@ getconfig(intface) MAYHAVE(val, "maxinterval", DEF_MAXRTRADVINTERVAL); if (val < MIN_MAXINTERVAL || val > MAX_MAXINTERVAL) { syslog(LOG_ERR, - "<%s> maxinterval must be between %e and %u", - __func__, MIN_MAXINTERVAL, MAX_MAXINTERVAL); + "<%s> maxinterval (%ld) on %s is invalid " + "(must be between %u and %u)", __func__, val, + intface, MIN_MAXINTERVAL, MAX_MAXINTERVAL); exit(1); } tmp->maxinterval = (u_int)val; MAYHAVE(val, "mininterval", tmp->maxinterval/3); if (val < MIN_MININTERVAL || val > (tmp->maxinterval * 3) / 4) { syslog(LOG_ERR, - "<%s> mininterval must be between %e and %d", - __func__, - MIN_MININTERVAL, + "<%s> mininterval (%ld) on %s is invalid " + "(must be between %d and %d)", + __func__, val, intface, MIN_MININTERVAL, (tmp->maxinterval * 3) / 4); exit(1); } @@ -175,7 +177,25 @@ getconfig(intface) MAYHAVE(val, "chlim", DEF_ADVCURHOPLIMIT); tmp->hoplimit = val & 0xff; - MAYHAVE(val, "raflags", 0); + if ((flagstr = (char *)agetstr("raflags", &bp))) { + val = 0; + if (strchr(flagstr, 'm')) + val |= ND_RA_FLAG_MANAGED; + if (strchr(flagstr, 'o')) + val |= ND_RA_FLAG_OTHER; + if (strchr(flagstr, 'h')) + val |= ND_RA_FLAG_RTPREF_HIGH; + if (strchr(flagstr, 'l')) { + if ((val & ND_RA_FLAG_RTPREF_HIGH)) { + syslog(LOG_ERR, "<%s> the \'h\' and \'l\'" + " router flags are exclusive", __func__); + exit(1); + } + val |= ND_RA_FLAG_RTPREF_LOW; + } + } else { + MAYHAVE(val, "raflags", 0); + } tmp->managedflg = val & ND_RA_FLAG_MANAGED; tmp->otherflg = val & ND_RA_FLAG_OTHER; #ifndef ND_RA_FLAG_RTPREF_MASK @@ -184,18 +204,19 @@ getconfig(intface) #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", - __func__, intface); + syslog(LOG_ERR, "<%s> invalid router preference (%02x) on %s", + __func__, tmp->rtpref, intface); exit(1); } MAYHAVE(val, "rltime", tmp->maxinterval * 3); if (val && (val < tmp->maxinterval || val > MAXROUTERLIFETIME)) { syslog(LOG_ERR, - "<%s> router lifetime on %s must be 0 or" - " between %d and %d", - __func__, intface, - tmp->maxinterval, MAXROUTERLIFETIME); + "<%s> router lifetime (%ld) on %s is invalid " + "(must be 0 or between %d and %d)", + __func__, val, intface, + tmp->maxinterval, + MAXROUTERLIFETIME); exit(1); } /* @@ -207,37 +228,39 @@ getconfig(intface) * explicitly set zero. (see also the above section) */ if (val && forwarding == 0) { - syslog(LOG_WARNING, + syslog(LOG_ERR, "<%s> non zero router lifetime is specified for %s, " - "which must not be allowed for hosts.", + "which must not be allowed for hosts. you must " + "change router lifetime or enable IPv6 forwarding.", __func__, intface); exit(1); } tmp->lifetime = val & 0xffff; MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME); - if (val > MAXREACHABLETIME) { + if (val < 0 || val > MAXREACHABLETIME) { syslog(LOG_ERR, - "<%s> reachable time must be no greater than %d", - __func__, MAXREACHABLETIME); + "<%s> reachable time (%ld) on %s is invalid " + "(must be no greater than %d)", + __func__, val, intface, MAXREACHABLETIME); exit(1); } tmp->reachabletime = (u_int32_t)val; MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER); if (val64 < 0 || val64 > 0xffffffff) { - syslog(LOG_ERR, "<%s> retrans time out of range", __func__); + syslog(LOG_ERR, "<%s> retrans time (%lld) on %s out of range", + __func__, (long long)val64, intface); exit(1); } tmp->retranstimer = (u_int32_t)val64; - if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) { + if (agetnum("hapref") != -1 || agetnum("hatime") != -1) { syslog(LOG_ERR, "<%s> mobile-ip6 configuration not supported", __func__); exit(1); } - /* prefix information */ /* @@ -248,132 +271,122 @@ getconfig(intface) MAYHAVE(val, "clockskew", 0); tmp->clockskew = val; - if ((pfxs = agetnum("addrs")) < 0) { - /* auto configure prefix information */ - if (agetstr("addr", &bp) || agetstr("addr1", &bp)) { + tmp->pfxs = 0; + for (i = -1; i < MAXPREFIX; i++) { + struct prefix *pfx; + char entbuf[256]; + + makeentry(entbuf, sizeof(entbuf), i, "addr"); + addr = (char *)agetstr(entbuf, &bp); + if (addr == NULL) + continue; + + /* allocate memory to store prefix information */ + if ((pfx = malloc(sizeof(struct prefix))) == NULL) { syslog(LOG_ERR, - "<%s> conflicting prefix configuration for %s: " - "automatic and manual config at the same time", - __func__, intface); + "<%s> can't allocate enough memory", + __func__); exit(1); } - get_prefix(tmp); - } - else { - tmp->pfxs = pfxs; - for (i = 0; i < pfxs; i++) { - struct prefix *pfx; - char entbuf[256]; - int added = (pfxs > 1) ? 1 : 0; + memset(pfx, 0, sizeof(*pfx)); - /* allocate memory to store prefix information */ - if ((pfx = malloc(sizeof(struct prefix))) == NULL) { - syslog(LOG_ERR, - "<%s> can't allocate enough memory", - __func__); - exit(1); - } - memset(pfx, 0, sizeof(*pfx)); + /* link into chain */ + insque(pfx, &tmp->prefix); + tmp->pfxs++; + pfx->rainfo = tmp; - /* link into chain */ - insque(pfx, &tmp->prefix); - pfx->rainfo = tmp; + pfx->origin = PREFIX_FROM_CONFIG; - pfx->origin = PREFIX_FROM_CONFIG; + if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1) { + syslog(LOG_ERR, + "<%s> inet_pton failed for %s", + __func__, addr); + exit(1); + } + if (IN6_IS_ADDR_MULTICAST(&pfx->prefix)) { + syslog(LOG_ERR, + "<%s> multicast prefix (%s) must " + "not be advertised on %s", + __func__, addr, intface); + exit(1); + } + if (IN6_IS_ADDR_LINKLOCAL(&pfx->prefix)) + syslog(LOG_NOTICE, + "<%s> link-local prefix (%s) will be" + " advertised on %s", + __func__, addr, intface); - makeentry(entbuf, sizeof(entbuf), i, "prefixlen", - added); - MAYHAVE(val, entbuf, 64); - if (val < 0 || val > 128) { - syslog(LOG_ERR, - "<%s> prefixlen out of range", - __func__); - exit(1); - } - pfx->prefixlen = (int)val; + makeentry(entbuf, sizeof(entbuf), i, "prefixlen"); + MAYHAVE(val, entbuf, 64); + if (val < 0 || val > 128) { + syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s " + "on %s out of range", + __func__, val, addr, intface); + exit(1); + } + pfx->prefixlen = (int)val; - makeentry(entbuf, sizeof(entbuf), i, "pinfoflags", - added); - { - MAYHAVE(val, entbuf, - (ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO)); - } - pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK; - pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO; + makeentry(entbuf, sizeof(entbuf), i, "pinfoflags"); + if ((flagstr = (char *)agetstr(entbuf, &bp))) { + val = 0; + if (strchr(flagstr, 'l')) + val |= ND_OPT_PI_FLAG_ONLINK; + if (strchr(flagstr, 'a')) + val |= ND_OPT_PI_FLAG_AUTO; + } else { + MAYHAVE(val, entbuf, + (ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO)); + } + pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK; + pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO; - makeentry(entbuf, sizeof(entbuf), i, "vltime", added); - MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME); - if (val64 < 0 || val64 > 0xffffffff) { - syslog(LOG_ERR, - "<%s> vltime out of range", - __func__); - exit(1); - } - pfx->validlifetime = (u_int32_t)val64; + makeentry(entbuf, sizeof(entbuf), i, "vltime"); + MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME); + if (val64 < 0 || val64 > 0xffffffff) { + syslog(LOG_ERR, "<%s> vltime (%lld) for " + "%s/%d on %s is out of range", + __func__, (long long)val64, + addr, pfx->prefixlen, intface); + exit(1); + } + pfx->validlifetime = (u_int32_t)val64; - makeentry(entbuf, sizeof(entbuf), i, "vltimedecr", - added); - if (agetflag(entbuf)) { - struct timeval now; - gettimeofday(&now, 0); - pfx->vltimeexpire = - now.tv_sec + pfx->validlifetime; - } + makeentry(entbuf, sizeof(entbuf), i, "vltimedecr"); + if (agetflag(entbuf)) { + struct timeval now; + gettimeofday(&now, 0); + pfx->vltimeexpire = + now.tv_sec + pfx->validlifetime; + } - makeentry(entbuf, sizeof(entbuf), i, "pltime", added); - MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME); - if (val64 < 0 || val64 > 0xffffffff) { - syslog(LOG_ERR, - "<%s> pltime out of range", - __func__); - exit(1); - } - pfx->preflifetime = (u_int32_t)val64; + makeentry(entbuf, sizeof(entbuf), i, "pltime"); + MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME); + if (val64 < 0 || val64 > 0xffffffff) { + syslog(LOG_ERR, + "<%s> pltime (%lld) for %s/%d on %s " + "is out of range", + __func__, (long long)val64, + addr, pfx->prefixlen, intface); + exit(1); + } + pfx->preflifetime = (u_int32_t)val64; - makeentry(entbuf, sizeof(entbuf), i, "pltimedecr", - added); - if (agetflag(entbuf)) { - struct timeval now; - gettimeofday(&now, 0); - pfx->pltimeexpire = - now.tv_sec + pfx->preflifetime; - } - - makeentry(entbuf, sizeof(entbuf), i, "addr", added); - addr = (char *)agetstr(entbuf, &bp); - if (addr == NULL) { - syslog(LOG_ERR, - "<%s> need %s as a prefix for " - "interface %s", - __func__, entbuf, intface); - exit(1); - } - if (inet_pton(AF_INET6, addr, - &pfx->prefix) != 1) { - syslog(LOG_ERR, - "<%s> inet_pton failed for %s", - __func__, addr); - exit(1); - } - if (IN6_IS_ADDR_MULTICAST(&pfx->prefix)) { - syslog(LOG_ERR, - "<%s> multicast prefix(%s) must " - "not be advertised (IF=%s)", - __func__, addr, intface); - exit(1); - } - if (IN6_IS_ADDR_LINKLOCAL(&pfx->prefix)) - syslog(LOG_NOTICE, - "<%s> link-local prefix(%s) will be" - " advertised on %s", - __func__, addr, intface); + makeentry(entbuf, sizeof(entbuf), i, "pltimedecr"); + if (agetflag(entbuf)) { + struct timeval now; + gettimeofday(&now, 0); + pfx->pltimeexpire = + now.tv_sec + pfx->preflifetime; } } + if (tmp->pfxs == 0) + get_prefix(tmp); MAYHAVE(val, "mtu", 0); if (val < 0 || val > 0xffffffff) { syslog(LOG_ERR, - "<%s> mtu out of range", __func__); + "<%s> mtu (%ld) on %s out of range", + __func__, val, intface); exit(1); } tmp->linkmtu = (u_int32_t)val; @@ -386,25 +399,32 @@ getconfig(intface) } else if (tmp->linkmtu < IPV6_MMTU || tmp->linkmtu > tmp->phymtu) { syslog(LOG_ERR, - "<%s> advertised link mtu must be between" - " least MTU and physical link MTU", - __func__); + "<%s> advertised link mtu (%lu) on %s is invalid (must " + "be between least MTU (%d) and physical link MTU (%d)", + __func__, (unsigned long)tmp->linkmtu, intface, + IPV6_MMTU, tmp->phymtu); exit(1); } /* route information */ - - MAYHAVE(val, "routes", 0); - if (val < 0 || val > 0xffffffff) { - syslog(LOG_ERR, - "<%s> number of route information improper", __func__); - exit(1); - } - tmp->routes = val; - for (i = 0; i < tmp->routes; i++) { +#ifdef ROUTEINFO + tmp->routes = 0; + for (i = -1; i < MAXROUTE; i++) { struct rtinfo *rti; - char entbuf[256]; - int added = (tmp->routes > 1) ? 1 : 0; + char entbuf[256], oentbuf[256]; + + makeentry(entbuf, sizeof(entbuf), i, "rtprefix"); + addr = (char *)agetstr(entbuf, &bp); + if (addr == NULL) { + makeentry(oentbuf, sizeof(oentbuf), i, "rtrprefix"); + addr = (char *)agetstr(oentbuf, &bp); + if (addr) { + fprintf(stderr, "%s was obsoleted. Use %s.\n", + oentbuf, entbuf); + } + } + if (addr == NULL) + continue; /* allocate memory to store prefix information */ if ((rti = malloc(sizeof(struct rtinfo))) == NULL) { @@ -417,80 +437,122 @@ getconfig(intface) /* link into chain */ insque(rti, &tmp->route); + tmp->routes++; - makeentry(entbuf, sizeof(entbuf), i, "rtrplen", added); - MAYHAVE(val, entbuf, 64); - if (val < 0 || val > 128) { - syslog(LOG_ERR, - "<%s> prefixlen out of range", - __func__); - exit(1); - } - rti->prefixlen = (int)val; - - makeentry(entbuf, sizeof(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 route preference", - __func__); - exit(1); - } - - makeentry(entbuf, sizeof(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", - __func__); - exit(1); - } - rti->ltime = (u_int32_t)val64; - - makeentry(entbuf, sizeof(entbuf), i, "rtrprefix", added); - addr = (char *)agetstr(entbuf, &bp); - if (addr == NULL) { - syslog(LOG_ERR, - "<%s> need %s as a route for " - "interface %s", - __func__, entbuf, intface); - exit(1); - } if (inet_pton(AF_INET6, addr, &rti->prefix) != 1) { - syslog(LOG_ERR, - "<%s> inet_pton failed for %s", + syslog(LOG_ERR, "<%s> inet_pton failed for %s", __func__, 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. + * prefix according to + * draft-ietf-ipngwg-router-selection-00.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)", + "not be advertised on %s", __func__, 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", + "<%s> link-local route (%s) will " + "be advertised on %s", __func__, addr, intface); exit(1); } #endif + + makeentry(entbuf, sizeof(entbuf), i, "rtplen"); + /* XXX: 256 is a magic number for compatibility check. */ + MAYHAVE(val, entbuf, 256); + if (val == 256) { + makeentry(oentbuf, sizeof(oentbuf), i, "rtrplen"); + MAYHAVE(val, oentbuf, 256); + if (val != 256) { + fprintf(stderr, "%s was obsoleted. Use %s.\n", + oentbuf, entbuf); + } else + val = 64; + } + if (val < 0 || val > 128) { + syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s on %s " + "out of range", + __func__, val, addr, intface); + exit(1); + } + rti->prefixlen = (int)val; + + makeentry(entbuf, sizeof(entbuf), i, "rtflags"); + if ((flagstr = (char *)agetstr(entbuf, &bp))) { + val = 0; + if (strchr(flagstr, 'h')) + val |= ND_RA_FLAG_RTPREF_HIGH; + if (strchr(flagstr, 'l')) { + if ((val & ND_RA_FLAG_RTPREF_HIGH)) { + syslog(LOG_ERR, + "<%s> the \'h\' and \'l\' route" + " preferences are exclusive", + __func__); + exit(1); + } + val |= ND_RA_FLAG_RTPREF_LOW; + } + } else + MAYHAVE(val, entbuf, 256); /* XXX */ + if (val == 256) { + makeentry(oentbuf, sizeof(oentbuf), i, "rtrflags"); + MAYHAVE(val, oentbuf, 256); + if (val != 256) { + fprintf(stderr, "%s was obsoleted. Use %s.\n", + oentbuf, entbuf); + } else + val = 0; + } + rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK; + if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV) { + syslog(LOG_ERR, "<%s> invalid route preference (%02x) " + "for %s/%d on %s", + __func__, rti->rtpref, addr, + rti->prefixlen, intface); + exit(1); + } + + /* + * Since the spec does not a default value, we should make + * this entry mandatory. However, FreeBSD 4.4 has shipped + * with this field being optional, we use the router lifetime + * as an ad-hoc default value with a warning message. + */ + makeentry(entbuf, sizeof(entbuf), i, "rtltime"); + MAYHAVE(val64, entbuf, -1); + if (val64 == -1) { + makeentry(oentbuf, sizeof(oentbuf), i, "rtrltime"); + MAYHAVE(val64, oentbuf, -1); + if (val64 != -1) { + fprintf(stderr, "%s was obsoleted. Use %s.\n", + oentbuf, entbuf); + } else { + fprintf(stderr, "%s should be specified " + "for interface %s.\n", + entbuf, intface); + val64 = tmp->lifetime; + } + } + if (val64 < 0 || val64 > 0xffffffff) { + syslog(LOG_ERR, "<%s> route lifetime (%lld) for " + "%s/%d on %s out of range", __func__, + (long long)val64, addr, rti->prefixlen, intface); + exit(1); + } + rti->ltime = (u_int32_t)val64; } +#endif /* okey */ tmp->next = ralist; @@ -506,7 +568,7 @@ getconfig(intface) rtadvd_set_timer(&tmp->timer->tm, tmp->timer); } -static void +void get_prefix(struct rainfo *rai) { struct ifaddrs *ifap, *ifa; @@ -536,12 +598,14 @@ get_prefix(struct rainfo *rai) m = (u_char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; lim = (u_char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len; plen = prefixlen(m, lim); - if (plen < 0 || plen > 128) { + if (plen <= 0 || plen > 128) { syslog(LOG_ERR, "<%s> failed to get prefixlen " "or prefix is invalid", __func__); exit(1); } + if (plen == 128) /* XXX */ + continue; if (find_prefix(rai, a, plen)) { /* ignore a duplicated prefix. */ continue; @@ -580,10 +644,10 @@ get_prefix(struct rainfo *rai) pp->onlinkflg = 1; pp->autoconfflg = 1; pp->origin = PREFIX_FROM_KERNEL; + pp->rainfo = rai; /* link into chain */ insque(pp, &rai->prefix); - pp->rainfo = rai; /* counter increment */ rai->pfxs++; @@ -593,29 +657,24 @@ get_prefix(struct rainfo *rai) } static void -makeentry(buf, len, id, string, add) +makeentry(buf, len, id, string) char *buf; size_t len; int id; char *string; - int add; { - char *ep = buf + len; - strlcpy(buf, string, len); - if (add) { - char *cp; - - cp = (char *)index(buf, '\0'); - snprintf(cp, ep - cp, "%d", id); - } + if (id < 0) + strlcpy(buf, string, len); + else + snprintf(buf, len, "%s%d", string, id); } /* * Add a prefix to the list of specified interface and reconstruct * the outgoing packet. * The prefix must not be in the list. - * XXX: other parameter of the prefix(e.g. lifetime) shoule be + * XXX: other parameters of the prefix (e.g. lifetime) shoule be * able to be specified. */ static void @@ -653,13 +712,6 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr) /* reconstruct the packet */ rai->pfxs++; make_packet(rai); - - /* - * reset the timer so that the new prefix will be advertised quickly. - */ - rai->initcounter = 0; - ra_timer_update((void *)rai, &rai->timer->tm); - rtadvd_set_timer(&rai->timer->tm, rai->timer); } /* @@ -826,9 +878,11 @@ make_packet(struct rainfo *rainfo) struct nd_router_advert *ra; struct nd_opt_prefix_info *ndopt_pi; struct nd_opt_mtu *ndopt_mtu; +#ifdef ROUTEINFO struct nd_opt_route_info *ndopt_rti; - struct prefix *pfx; struct rtinfo *rti; +#endif + struct prefix *pfx; /* calculate total length */ packlen = sizeof(struct nd_router_advert); @@ -846,7 +900,7 @@ make_packet(struct rainfo *rainfo) packlen += sizeof(struct nd_opt_prefix_info) * rainfo->pfxs; if (rainfo->linkmtu) packlen += sizeof(struct nd_opt_mtu); -#ifdef ND_OPT_ROUTE_INFO +#ifdef ROUTEINFO for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next) packlen += sizeof(struct nd_opt_route_info) + ((rti->prefixlen + 0x3f) >> 6) * 8; @@ -956,7 +1010,7 @@ make_packet(struct rainfo *rainfo) buf += sizeof(struct nd_opt_prefix_info); } -#ifdef ND_OPT_ROUTE_INFO +#ifdef ROUTEINFO for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next) { u_int8_t psize = (rti->prefixlen + 0x3f) >> 6; diff --git a/usr.sbin/rtadvd/config.h b/usr.sbin/rtadvd/config.h index 0bb137b1f313..aeb1c2c9d457 100644 --- a/usr.sbin/rtadvd/config.h +++ b/usr.sbin/rtadvd/config.h @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: config.h,v 1.3 2000/05/16 13:34:13 itojun Exp $ */ +/* $KAME: config.h,v 1.8 2003/06/17 08:26:22 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -36,3 +36,12 @@ extern void invalidate_prefix __P((struct prefix *)); extern void update_prefix __P((struct prefix *)); extern void make_prefix __P((struct rainfo *, int, struct in6_addr *, int)); extern void make_packet __P((struct rainfo *)); +extern void get_prefix __P((struct rainfo *)); + + +/* + * it is highly unlikely to have 100 prefix information options, + * so it should be okay to limit it + */ +#define MAXPREFIX 100 +#define MAXROUTE 100 diff --git a/usr.sbin/rtadvd/dump.c b/usr.sbin/rtadvd/dump.c index ab9defa0863d..7b9a2748d6ca 100644 --- a/usr.sbin/rtadvd/dump.c +++ b/usr.sbin/rtadvd/dump.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: dump.c,v 1.16 2001/03/21 17:41:13 jinmei Exp $ */ +/* $KAME: dump.c,v 1.32 2003/05/19 09:46:50 keiichi Exp $ */ /* * Copyright (C) 2000 WIDE Project. @@ -93,7 +93,9 @@ if_dump() { struct rainfo *rai; struct prefix *pfx; +#ifdef ROUTEINFO struct rtinfo *rti; +#endif char prefixbuf[INET6_ADDRSTRLEN]; int first; struct timeval now; @@ -208,6 +210,7 @@ if_dump() } fprintf(fp, ")\n"); } +#ifdef ROUTEINFO for (first = 1, rti = rai->route.next; rti != &rai->route; rti = rti->next) { if (first) { @@ -226,6 +229,7 @@ if_dump() fprintf(fp, "lifetime: %ld", (long)rti->ltime); fprintf(fp, ")\n"); } +#endif } } diff --git a/usr.sbin/rtadvd/rtadvd.8 b/usr.sbin/rtadvd/rtadvd.8 index 4edb19fa3c37..6fa41d692598 100644 --- a/usr.sbin/rtadvd/rtadvd.8 +++ b/usr.sbin/rtadvd/rtadvd.8 @@ -1,5 +1,5 @@ .\" $FreeBSD$ -.\" $KAME: rtadvd.8,v 1.17 2001/02/04 05:34:38 jinmei Exp $ +.\" $KAME: rtadvd.8,v 1.24 2002/05/31 16:16:08 jinmei Exp $ .\" .\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. .\" All rights reserved. @@ -40,9 +40,8 @@ .Op Fl c Ar configfile .Ar interface ... .Sh DESCRIPTION -The .Nm -utility sends router advertisement packets to the specified +sends router advertisement packets to the specified .Ar interfaces . .Pp The program will daemonize itself on invocation. @@ -62,9 +61,8 @@ In particular, reads all the interface routes from the routing table and advertises them as on-link prefixes. .Pp -The .Nm -utility also watches the routing table. +also watches the routing table. If an interface direct route is added on an advertising interface and no static prefixes are specified by the configuration file, @@ -126,25 +124,19 @@ Print debugging information. Even more debugging information is printed. .It Fl f Foreground mode (useful when debugging). +Log messages will be dumped to stderr when this option is specified. .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 +tries to join the first advertising interface appearing on 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 -.\"permitted configuration directives. .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. @@ -168,9 +160,11 @@ In this case, .Nm will transmit router advertisement with router lifetime 0 to all the interfaces -(in accordance with RFC2461 6.2.5). -.Sh DIAGNOSTICS -.Ex -std +.Pq in accordance with RFC2461 6.2.5 . +.Sh RETURN VALUES +The +.Nm +program exits 0 on success, and >0 on failures. .Sh FILES .Bl -tag -width Pa -compact .It Pa /etc/rtadvd.conf @@ -179,19 +173,18 @@ The default configuration file. contains the pid of the currently running .Nm . .It Pa /var/run/rtadvd.dump -in which +The file in which .Nm dumps its internal state. .El .Sh SEE ALSO .Xr rtadvd.conf 5 , -.Xr rrenumd 8 , .Xr rtsol 8 .Sh HISTORY The .Nm -utility first appeared in WIDE Hydrangea IPv6 protocol stack kit. -.Sh CAVEAT +command first appeared in the WIDE Hydrangea IPv6 protocol stack kit. +.Sh BUGS There used to be some text that recommended users not to let .Nm advertise Router Advertisement messages on an upstream link to avoid diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c index f33a9518dcef..8a5092e825f6 100644 --- a/usr.sbin/rtadvd/rtadvd.c +++ b/usr.sbin/rtadvd/rtadvd.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: rtadvd.c,v 1.50 2001/02/04 06:15:15 itojun Exp $ */ +/* $KAME: rtadvd.c,v 1.82 2003/08/05 12:34:23 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -96,7 +96,7 @@ struct nd_optlist { struct nd_opt_hdr *opt; }; union nd_opts { - struct nd_opt_hdr *nd_opt_array[7]; + struct nd_opt_hdr *nd_opt_array[9]; struct { struct nd_opt_hdr *zero; struct nd_opt_hdr *src_lladdr; @@ -122,7 +122,7 @@ union nd_opts { u_int32_t ndopt_flags[] = { 0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR, - NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU + NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU, }; int main __P((int, char *[])); @@ -143,6 +143,7 @@ static void free_ndopts __P((union nd_opts *)); static void ra_output __P((struct rainfo *)); static void rtmsg_input __P((void)); static void rtadvd_set_dump_file __P((int)); +static void set_short_delay __P((struct rainfo *)); int main(argc, argv) @@ -243,8 +244,8 @@ main(argc, argv) pid = getpid(); if ((pidfp = fopen(pidfilename, "w")) == NULL) { syslog(LOG_ERR, - "<%s> failed to open a log file(%s), run anyway.", - __func__, pidfilename); + "<%s> failed to open the pid log file, run anyway.", + __func__); } else { fprintf(pidfp, "%d\n", pid); fclose(pidfp); @@ -398,6 +399,7 @@ rtmsg_input() struct rainfo *rai; struct in6_addr *addr; char addrbuf[INET6_ADDRSTRLEN]; + int prefixchange = 0; n = read(rtsock, msg, sizeof(msg)); if (dflag > 1) { @@ -496,6 +498,7 @@ rtmsg_input() * make it available again. */ update_prefix(prefix); + prefixchange = 1; } else if (dflag > 1) { syslog(LOG_DEBUG, "<%s> new prefix(%s/%d) " @@ -509,6 +512,7 @@ rtmsg_input() break; } make_prefix(rai, ifindex, addr, plen); + prefixchange = 1; break; case RTM_DELETE: /* init ifflags because it may have changed */ @@ -544,6 +548,7 @@ rtmsg_input() break; } invalidate_prefix(prefix); + prefixchange = 1; break; case RTM_NEWADDR: case RTM_DELADDR: @@ -584,6 +589,14 @@ rtmsg_input() ra_timer_update, rai, rai); ra_timer_update((void *)rai, &rai->timer->tm); rtadvd_set_timer(&rai->timer->tm, rai->timer); + } else if (prefixchange && + (iflist[ifindex]->ifm_flags & IFF_UP)) { + /* + * An advertised prefix has been added or invalidated. + * Will notice the change in a short delay. + */ + rai->initcounter = 0; + set_short_delay(rai); } } @@ -784,6 +797,7 @@ rs_input(int len, struct nd_router_solicit *rs, u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; union nd_opts ndopts; struct rainfo *ra; + struct soliciter *sol; syslog(LOG_DEBUG, "<%s> RS received from %s on %s", @@ -841,73 +855,77 @@ rs_input(int len, struct nd_router_solicit *rs, * Decide whether to send RA according to the rate-limit * consideration. */ - { - long delay; /* must not be greater than 1000000 */ - struct timeval interval, now, min_delay, tm_tmp, *rest; - struct soliciter *sol; - /* - * record sockaddr waiting for RA, if possible - */ - sol = (struct soliciter *)malloc(sizeof(*sol)); - if (sol) { - sol->addr = *from; - /*XXX RFC2553 need clarification on flowinfo */ - sol->addr.sin6_flowinfo = 0; - sol->next = ra->soliciter; - ra->soliciter = sol->next; - } - - /* - * If there is already a waiting RS packet, don't - * update the timer. - */ - if (ra->waiting++) - goto done; - - /* - * Compute a random delay. If the computed value - * corresponds to a time later than the time the next - * multicast RA is scheduled to be sent, ignore the random - * delay and send the advertisement at the - * already-scheduled time. RFC-2461 6.2.6 - */ - delay = random() % MAX_RA_DELAY_TIME; - interval.tv_sec = 0; - interval.tv_usec = delay; - rest = rtadvd_timer_rest(ra->timer); - if (TIMEVAL_LT(*rest, interval)) { - syslog(LOG_DEBUG, - "<%s> random delay is larger than " - "the rest of normal timer", - __func__); - interval = *rest; - } - - /* - * If we sent a multicast Router Advertisement within - * the last MIN_DELAY_BETWEEN_RAS seconds, schedule - * the advertisement to be sent at a time corresponding to - * MIN_DELAY_BETWEEN_RAS plus the random value after the - * previous advertisement was sent. - */ - gettimeofday(&now, NULL); - TIMEVAL_SUB(&now, &ra->lastsent, &tm_tmp); - min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS; - min_delay.tv_usec = 0; - if (TIMEVAL_LT(tm_tmp, min_delay)) { - TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay); - TIMEVAL_ADD(&min_delay, &interval, &interval); - } - rtadvd_set_timer(&interval, ra->timer); - goto done; + /* record sockaddr waiting for RA, if possible */ + sol = (struct soliciter *)malloc(sizeof(*sol)); + if (sol) { + sol->addr = *from; + /* XXX RFC2553 need clarification on flowinfo */ + sol->addr.sin6_flowinfo = 0; + sol->next = ra->soliciter; + ra->soliciter = sol; } + /* + * If there is already a waiting RS packet, don't + * update the timer. + */ + if (ra->waiting++) + goto done; + + set_short_delay(ra); + done: free_ndopts(&ndopts); return; } +static void +set_short_delay(rai) + struct rainfo *rai; +{ + long delay; /* must not be greater than 1000000 */ + struct timeval interval, now, min_delay, tm_tmp, *rest; + + /* + * Compute a random delay. If the computed value + * corresponds to a time later than the time the next + * multicast RA is scheduled to be sent, ignore the random + * delay and send the advertisement at the + * already-scheduled time. RFC-2461 6.2.6 + */ +#ifdef HAVE_ARC4RANDOM + delay = arc4random() % MAX_RA_DELAY_TIME; +#else + delay = random() % MAX_RA_DELAY_TIME; +#endif + interval.tv_sec = 0; + interval.tv_usec = delay; + rest = rtadvd_timer_rest(rai->timer); + if (TIMEVAL_LT(*rest, interval)) { + syslog(LOG_DEBUG, "<%s> random delay is larger than " + "the rest of the current timer", __func__); + interval = *rest; + } + + /* + * If we sent a multicast Router Advertisement within + * the last MIN_DELAY_BETWEEN_RAS seconds, schedule + * the advertisement to be sent at a time corresponding to + * MIN_DELAY_BETWEEN_RAS plus the random value after the + * previous advertisement was sent. + */ + gettimeofday(&now, NULL); + TIMEVAL_SUB(&now, &rai->lastsent, &tm_tmp); + min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS; + min_delay.tv_usec = 0; + if (TIMEVAL_LT(tm_tmp, min_delay)) { + TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay); + TIMEVAL_ADD(&min_delay, &interval, &interval); + } + rtadvd_set_timer(&interval, rai->timer); +} + static void ra_input(int len, struct nd_router_advert *ra, struct in6_pktinfo *pi, struct sockaddr_in6 *from) @@ -1125,7 +1143,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo, gettimeofday(&now, NULL); preferred_time += now.tv_sec; - if (rai->clockskew && + if (!pp->timer && rai->clockskew && abs(preferred_time - pp->pltimeexpire) > rai->clockskew) { syslog(LOG_INFO, "<%s> preferred lifetime for %s/%d" @@ -1141,7 +1159,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo, pp->pltimeexpire); inconsistent++; } - } else if (preferred_time != pp->preflifetime) { + } else if (!pp->timer && preferred_time != pp->preflifetime) { syslog(LOG_INFO, "<%s> preferred lifetime for %s/%d" " inconsistent on %s:" @@ -1161,7 +1179,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo, gettimeofday(&now, NULL); valid_time += now.tv_sec; - if (rai->clockskew && + if (!pp->timer && rai->clockskew && abs(valid_time - pp->vltimeexpire) > rai->clockskew) { syslog(LOG_INFO, "<%s> valid lifetime for %s/%d" @@ -1177,7 +1195,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo, pp->vltimeexpire); inconsistent++; } - } else if (valid_time != pp->validlifetime) { + } else if (!pp->timer && valid_time != pp->validlifetime) { syslog(LOG_INFO, "<%s> valid lifetime for %s/%d" " inconsistent on %s:" @@ -1201,17 +1219,21 @@ find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen) { struct prefix *pp; int bytelen, bitlen; + u_char bitmask; for (pp = rai->prefix.next; pp != &rai->prefix; pp = pp->next) { if (plen != pp->prefixlen) continue; bytelen = plen / 8; bitlen = plen % 8; + bitmask = 0xff << (8 - bitlen); if (memcmp((void *)prefix, (void *)&pp->prefix, bytelen)) continue; - if (prefix->s6_addr[bytelen] >> (8 - bitlen) == - pp->prefix.s6_addr[bytelen] >> (8 - bitlen)) + if (bitlen == 0 || + ((prefix->s6_addr[bytelen] & bitmask) == + (pp->prefix.s6_addr[bytelen] & bitmask))) { return(pp); + } } return(NULL); @@ -1223,16 +1245,20 @@ prefix_match(struct in6_addr *p0, int plen0, struct in6_addr *p1, int plen1) { int bytelen, bitlen; + u_char bitmask; if (plen0 < plen1) return(0); bytelen = plen1 / 8; bitlen = plen1 % 8; + bitmask = 0xff << (8 - bitlen); if (memcmp((void *)p0, (void *)p1, bytelen)) return(0); - if (p0->s6_addr[bytelen] >> (8 - bitlen) == - p1->s6_addr[bytelen] >> (8 - bitlen)) + if (bitlen == 0 || + ((p0->s6_addr[bytelen] & bitmask) == + (p1->s6_addr[bytelen] & bitmask))) { return(1); + } return(0); } @@ -1577,6 +1603,10 @@ struct rainfo *rainfo; strerror(errno)); } } + /* update counter */ + if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS) + rainfo->initcounter++; + rainfo->raoutput++; /* * unicast advertisements @@ -1591,11 +1621,6 @@ struct rainfo *rainfo; } rainfo->soliciter = NULL; - /* update counter */ - if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS) - rainfo->initcounter++; - rainfo->raoutput++; - /* update timestamp */ gettimeofday(&rainfo->lastsent, NULL); diff --git a/usr.sbin/rtadvd/rtadvd.conf b/usr.sbin/rtadvd/rtadvd.conf index e202a6c860d1..33ab7f3e46bc 100644 --- a/usr.sbin/rtadvd/rtadvd.conf +++ b/usr.sbin/rtadvd/rtadvd.conf @@ -1,5 +1,5 @@ # $FreeBSD$ -# $KAME: rtadvd.conf,v 1.12 2001/01/21 14:56:38 itojun Exp $ +# $KAME: rtadvd.conf,v 1.13 2003/06/25 03:45:21 itojun Exp $ # # Note: All of the following parameters have default values defined # in specifications, and hence you usually do not have to set them @@ -18,4 +18,4 @@ # this part by hand, and then invoke rtadvd with the -s option. #ef0:\ -# :addrs#1:addr="3ffe:501:ffff:1000::":prefixlen#64: +# :addr="3ffe:501:ffff:1000::":prefixlen#64: diff --git a/usr.sbin/rtadvd/rtadvd.conf.5 b/usr.sbin/rtadvd/rtadvd.conf.5 index 3124e6f3b05a..90f747090aac 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.35 2001/05/25 07:40:22 jinmei Exp $ +.\" $KAME: rtadvd.conf.5,v 1.49 2003/07/24 21:51:26 jinmei Exp $ .\" .\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. .\" All rights reserved. @@ -80,14 +80,14 @@ will use the default values. .It Cm \&maxinterval (num) The maximum time allowed between sending unsolicited multicast router advertisements -(unit: seconds). +.Pq unit: seconds . The default value is 600. Its value must be no less than 4 seconds and no greater than 1800 seconds. .It Cm \&mininterval (num) The minimum time allowed between sending unsolicited multicast router advertisements -(unit: seconds). +.Pq unit: seconds . The default value is the one third of value of .Cm maxinterval . Its value must be no less than 3 seconds and no greater than .75 * @@ -105,27 +105,52 @@ will use the default values. (num) The value for Cur Hop Limit field. The default value is 64. .It Cm \&raflags -(num) Flags field in router advertisement message header. +(str or num) A 8-bit flags field in router advertisement message header. +This field can be specified either as a case-sensitive string or as an +integer. +A sting consists of characters each of which corresponds to a +particular flag bit(s). +An integer should be the logical OR of all enabled bits. Bit 7 -.Pq Li 0x80 +.Po +.Li 'm' or 0x80 +.Pc means Managed address configuration flag bit, and Bit 6 -.Pq Li 0x40 +.Po +.Li 'o' or 0x40 +.Pc means Other stateful configuration flag bit. Bit 4 -.Pq Li 0x10 +.Po +.Li 0x10 +.Pc and Bit 3 -.Pq Li 0x08 +.Po +.Li 0x08 +.Pc are used to encode router preference. -Bits 01 means high, 00 means medium, and 11 means low. +Bits 01 +.Po +or 'h' +.Pc +means high, 00 means medium, and 11 +.Po +or 'l' +.Pc +means low. Bits 10 is reserved, and must not be specified. -The default value of the entire flag is 0, +There is no character to specify the medium preference explicitly. +The default value of the entire flag is 0 +.Po +or a null string, +.Pc which means no additional configuration methods, and the medium router preference. .It Cm \&rltime (num) Router lifetime field -(unit: seconds). -Its value must be either zero or between +.Pq unit: seconds . +The value must be either zero or between the value of .Cm maxinterval and 9000. @@ -137,11 +162,11 @@ advertising interfaces as described in The default value is 1800. .It Cm \&rtime (num) Reachable time field -(unit: milliseconds). +.Pq unit: milliseconds . The default value is 0, which means unspecified by this router. .It Cm \&retrans (num) Retrans Timer field -(unit: milliseconds). +.Pq unit: milliseconds . The default value is 0, which means unspecified by this router. .El .Pp @@ -151,11 +176,16 @@ 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. +Keywords other than +.Cm clockskew +can be augmented with a number, like +.Dq Li prefix2 , +to specify multiple prefixes. .Bl -tag -width indent .It Cm \&clockskew (num) Time skew to adjust link propagation delays and clock skews between routers on the link -(unit: seconds). +.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 @@ -163,34 +193,27 @@ 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 positive values -if you want to specify any prefix information option. -If its value is 0, -.Xr rtadvd 8 -looks up the system routing table and -advertise the prefixes corresponding to interface routes -on the interface. -If its value is more than 1, you must specify the index of the prefix -for each item below. -Indices vary from 0 to N-1, where N is the -value of -.Cm addrs . -Each index shall follow the name of each item, e.g., -.Dq prefixlen2 . .It Cm \&prefixlen (num) Prefix length field. The default value is 64. .It Cm \&pinfoflags -(num) Flags field in prefix information option. +(str or num) A 8-bit flags field in prefix information option. +This field can be specified either as a case-sensitive string or as an +integer. +A sting consists of characters each of which corresponds to a +particular flag bit(s). +An integer should be the logical OR of all enabled bits. Bit 7 -.Pq Li 0x80 +.Po +.Li 'l' or 0x80 +.Pc means On-link flag bit, and Bit 6 -.Pq Li 0x40 +.Po +.Li 'a' or 0x40 +.Pc means Autonomous address-configuration flag bit. -The default value is 0xc0, i.e., both bits are set. +The default value is "la" or 0xc0, i.e., both bits are set. .It Cm \&addr (str) The address filled into Prefix field. Since @@ -199,20 +222,16 @@ 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 \&vltime (num) Valid lifetime field -(unit: seconds). +.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 -(unit: seconds). +.Pq unit: seconds . The default value is 604800 (7 days). .It Cm \&pltimedecr (bool) This item means the advertised preferred lifetime will decrements @@ -243,9 +262,11 @@ will use the default value. .Bl -tag -width indent .It Cm \&nolladdr (bool) By default -(if +.Po +if .Cm \&nolladdr -is not specified), +is not specified +.Pc , .Xr rtadvd 8 will try to get link-layer address for the interface from the kernel, and attach that in source link-layer address option. @@ -255,7 +276,7 @@ will not attach source link-layer address option to router advertisement packets. .El .Pp -The following item controls ICMPV6 home agent information option, +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 @@ -278,32 +299,11 @@ explicitly. The following items are for ICMPv6 route information option, which will be attached to router advertisement header. These items are optional. +Each items can be augmented with number, like +.Dq Li rtplen2 , +to specify multiple routes. .Bl -tag -width indent -.It Cm \&routes -(num) Number of routes. -Its default is 0, so it must explicitly be set to positive 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 -.Pq Li 0x10 -and -and Bit 3 -.Pq Li 0x08 -are used to encode router preference for the route. -The default value is 0x00, i.e. medium router preference. -.It Cm \&rtrprefix +.It Cm \&rtprefix (str) The prefix filled into the Prefix field of route information option. Since .Dq \&: @@ -311,15 +311,49 @@ 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 +.It Cm \&rtplen +(num) Prefix length field in route information option. +The default value is 64. +.It Cm \&rtflags +(str or num) A 8-bit flags field in route information option. +Currently only the preference values are defined. +The notation is same as that of the raflags field. +Bit 4 +.Po +.Li 0x10 +.Pc +and +and Bit 3 +.Po +.Li 0x08 +.Pc +are used to encode the route preference for the route. +The default value is 0x00, i.e. medium preference. +.It Cm \&rtltime (num) route lifetime field in route information option. -(unit: seconds). -The default value is 2592000 (30 days). (not specified in draft-draves-router-selection-01.txt now) +.Pq unit: seconds . +Since the specification does not define the default value of this +item, the value for this item should be specified by hand. +However, +.Nm rtadvd +allows this item to be unspecified, and uses the router lifetime +as the default value in such a case, just for compatibility with an +old version of the program. .El +.Pp +In the above list, each keyword beginning with +.Dq Li rt +could be replaced with the one beginning with +.Dq Li rtr +for backward compatibility reason. +For example, +.Cm rtrplen +is accepted instead of +.Cm rtplen . +However, keywords that start with +.Dq Li rtr +have basically been obsoleted, and should not be used any more. +.Pp You can also refer one line from another by using .Cm tc capability. @@ -353,7 +387,7 @@ option to .Xr rtadvd 8 . .Bd -literal -offset ef0:\\ - :addrs#1:addr="3ffe:501:ffff:1000::":prefixlen#64: + :addr="3ffe:501:ffff:1000::":prefixlen#64: .Ed .Pp The following example presents the default values in an explicit manner. @@ -362,9 +396,9 @@ YOU DO NOT NEED TO HAVE IT AT ALL. .Bd -literal -offset default:\\ :chlim#64:raflags#0:rltime#1800:rtime#0:retrans#0:\\ - :pinfoflags#192:vltime#2592000:pltime#604800:mtu#0: + :pinfoflags="la":vltime#2592000:pltime#604800:mtu#0: ef0:\\ - :addrs#1:addr="3ffe:501:ffff:1000::":prefixlen#64:tc=default: + :addr="3ffe:501:ffff:1000::":prefixlen#64:tc=default: .Ed .Sh SEE ALSO .Xr termcap 5 , @@ -381,7 +415,7 @@ Richard Draves, .Do Default Router Preferences and More-Specific Routes .Dc , -draft-ietf-ipngwg-router-selection-01.txt +draft-ietf-ipngwg-router-selection-xx.txt .Sh HISTORY The .Xr rtadvd 8 diff --git a/usr.sbin/rtadvd/rtadvd.h b/usr.sbin/rtadvd/rtadvd.h index a25e861617f6..b1c505dd75aa 100644 --- a/usr.sbin/rtadvd/rtadvd.h +++ b/usr.sbin/rtadvd/rtadvd.h @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: rtadvd.h,v 1.16 2001/04/10 15:08:31 suz Exp $ */ +/* $KAME: rtadvd.h,v 1.26 2003/08/05 12:34:23 itojun Exp $ */ /* * Copyright (C) 1998 WIDE Project. @@ -45,9 +45,8 @@ #define DEF_ADVVALIDLIFETIME 2592000 #define DEF_ADVPREFERREDLIFETIME 604800 -/*XXX int-to-double comparison for INTERVAL items */ #define MAXROUTERLIFETIME 9000 -#define MIN_MAXINTERVAL 4.0 +#define MIN_MAXINTERVAL 4 #define MAX_MAXINTERVAL 1800 #define MIN_MININTERVAL 3 #define MAXREACHABLETIME 3600000 @@ -83,6 +82,7 @@ struct prefix { struct in6_addr prefix; }; +#ifdef ROUTEINFO struct rtinfo { struct rtinfo *prev; /* previous link */ struct rtinfo *next; /* forward link */ @@ -92,6 +92,7 @@ struct rtinfo { int prefixlen; struct in6_addr prefix; }; +#endif struct soliciter { struct soliciter *next; @@ -131,8 +132,10 @@ struct rainfo { int pfxs; /* number of prefixes */ long clockskew; /* used for consisitency check of lifetimes */ +#ifdef ROUTEINFO struct rtinfo route; /* route information option (link head) */ int routes; /* number of route information options */ +#endif /* actual RA packet data and its length */ size_t ra_datalen;