Import NetBSD rtadvd(8)

Change-Id: I22626843d85c78f0fadefd58d61d7a85d285b2b8
This commit is contained in:
David van Moolenbroek 2017-02-19 14:27:23 +00:00
parent 5de448e315
commit 8f957290eb
26 changed files with 6247 additions and 2 deletions

View File

@ -160,6 +160,7 @@
./etc/rc.d/npf minix-base
./etc/rc.d/pwcheck minix-base
./etc/rc.d/root minix-base
./etc/rc.d/rtadvd minix-base
./etc/rc.d/sysctl minix-base
./etc/rc.d/sysdb minix-base
./etc/rc.d/syslogd minix-base
@ -1133,6 +1134,7 @@
./usr/sbin/rdate minix-base
./usr/sbin/rndc-confgen minix-base
./usr/sbin/rndc minix-base
./usr/sbin/rtadvd minix-base use_inet6
./usr/sbin/service minix-base
./usr/sbin/services_mkdb minix-base
./usr/sbin/syslogd minix-base
@ -1258,6 +1260,8 @@
./usr/share/examples/openssl/CA.pl minix-base crypto
./usr/share/examples/openssl/CA.sh minix-base crypto
./usr/share/examples/openssl/openssl.cnf minix-base crypto
./usr/share/examples/rtadvd minix-base
./usr/share/examples/rtadvd/rtadvd.conf minix-base use_inet6
./usr/share/examples/tmux minix-base
./usr/share/examples/tmux/screen-keys.conf minix-base
./usr/share/i18n minix-base nls
@ -3938,6 +3942,10 @@
./var/chroot/named/var/run/lwresd minix-base
./var/chroot/named/var/run/named minix-base
./var/chroot/named/var/tmp minix-base
./var/chroot/rtadvd minix-base
./var/chroot/rtadvd/etc minix-base
./var/chroot/rtadvd/var minix-base
./var/chroot/rtadvd/var/run minix-base
./var/chroot/tcpdump minix-base
./var/db minix-base
./var/db/obsolete minix-base

View File

@ -660,6 +660,7 @@
./usr/libdata/debug/usr/sbin/rdate.debug minix-debug debug
./usr/libdata/debug/usr/sbin/rndc-confgen.debug minix-debug debug
./usr/libdata/debug/usr/sbin/rndc.debug minix-debug debug
./usr/libdata/debug/usr/sbin/rtadvd.debug minix-debug use_inet6,debug
./usr/libdata/debug/usr/sbin/services_mkdb.debug minix-debug debug
./usr/libdata/debug/usr/sbin/syslogd.debug minix-debug debug
./usr/libdata/debug/usr/sbin/tcpdump.debug minix-debug debug

View File

@ -3390,6 +3390,7 @@
./usr/man/man5/resolver.5 minix-man
./usr/man/man5/rhosts.5 minix-man obsolete
./usr/man/man5/rndc.conf.5 minix-man
./usr/man/man5/rtadvd.conf.5 minix-man use_inet6
./usr/man/man5/serv.access.5 minix-man obsolete
./usr/man/man5/statvfs.5 minix-man
./usr/man/man5/syslog.conf.5 minix-man
@ -3564,6 +3565,7 @@
./usr/man/man8/rotate.8 minix-man
./usr/man/man8/route.8 minix-man
./usr/man/man8/rshd.8 minix-man
./usr/man/man8/rtadvd.8 minix-man use_inet6
./usr/man/man8/screendump.8 minix-man
./usr/man/man8/serial-ip.8 minix-man obsolete
./usr/man/man8/service.8 minix-man

View File

@ -205,6 +205,7 @@
./usr/share/examples/lua
./usr/share/examples/lutok
./usr/share/examples/openssl
./usr/share/examples/rtadvd
./usr/share/examples/tmux
./usr/share/games
./usr/share/games/fortune
@ -714,6 +715,10 @@
./var/chroot/named/var/run/lwresd mode=0775 gname=named
./var/chroot/named/var/run/named mode=0775 gname=named
./var/chroot/named/var/tmp mode=01775 gname=named
./var/chroot/rtadvd type=dir mode=0755
./var/chroot/rtadvd/etc type=dir mode=0755
./var/chroot/rtadvd/var type=dir mode=0755
./var/chroot/rtadvd/var/run type=dir mode=0775 gname=_rtadvd
./var/chroot/tcpdump mode=0755
./var/db
./var/db/obsolete

View File

@ -45,7 +45,7 @@ CONFIGFILES=\
pwcheck \
\
\
root \
root rtadvd \
\
\
sysctl sysdb syslogd \

60
etc/rc.d/rtadvd Executable file
View File

@ -0,0 +1,60 @@
#!/bin/sh
#
# $NetBSD: rtadvd,v 1.8 2013/07/09 09:34:58 roy Exp $
#
# PROVIDE: rtadvd
# REQUIRE: DAEMON
# BEFORE: LOGIN
$_rc_subr_loaded . /etc/rc.subr
name=rtadvd
rcvar=$name
command="/usr/sbin/$name"
pidfile="/var/run/$name.pid"
extra_commands=reload
start_precmd=rtadvd_prestart
reload_precmd=rtadvd_prereload
rtadvd_prereload()
{
local chdir="$(getent passwd _rtadvd | cut -d: -f6)"
local conf=/etc/rtadvd.conf myflags o confdir
[ -z "$chdir" -o "$chdir" = / ] && return 0
if [ -n "$flags" ]; then
myflags=$flags
else
eval myflags=\$${name}_flags
fi
set -- ${myflags}
while getopts c:dDfM:Rs o; do
case "$1" in
-c) conf="$OPTARG";;
esac
shift
done
confdir=$(dirname "$conf")
echo "$name: copying $conf to $chdir$conf"
cp "$conf" "$chdir$conf"
# Provide a link to the chrooted dump file
ln -snf "$chdir/var/run/$name.dump" /var/run
}
rtadvd_prestart()
{
if [ "$ip6mode" != router ]; then
warn \
"${name} cannot be used on IPv6 host, only on an IPv6 router."
return 1
fi
rtadvd_prereload
}
load_rc_config $name
run_rc_command "$1"

View File

@ -55,7 +55,7 @@ SUBDIR+= mdsetimage
SUBDIR+= ndp
.endif
.if (${USE_INET6} != "no")
SUBDIR+= traceroute6
SUBDIR+= rtadvd traceroute6
.endif
.if !defined(__MINIX)

26
usr.sbin/rtadvd/Makefile Normal file
View File

@ -0,0 +1,26 @@
# $NetBSD: Makefile,v 1.17 2012/08/10 12:10:30 joerg Exp $
WARNS?= 4
.include <bsd.own.mk>
USE_FORT?= yes # network server
PROG= rtadvd
SRCS= rtadvd.c rrenum.c advcap.c if.c config.c timer.c dump.c
CPPFLAGS+=-DINET6
MAN= rtadvd.8 rtadvd.conf.5
LDADD+= -lutil
DPADD+= ${LIBUTIL}
.if ${MKSHARE} != "no"
FILESDIR= /usr/share/examples/rtadvd
FILES= rtadvd.conf
.endif
.include <bsd.prog.mk>
.if defined(HAVE_GCC) || defined(HAVE_LLVM)
COPTS.dump.c=-fno-strict-aliasing
.endif

444
usr.sbin/rtadvd/advcap.c Normal file
View File

@ -0,0 +1,444 @@
/* $NetBSD: advcap.c,v 1.15 2015/06/05 15:41:59 roy Exp $ */
/* $KAME: advcap.c,v 1.11 2003/05/19 09:46:50 keiichi Exp $ */
/*
* Copyright (c) 1983 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* remcap - routines for dealing with the remote host data base
*
* derived from termcap
*/
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <syslog.h>
#include <errno.h>
#include <string.h>
#include "pathnames.h"
#ifndef __UNCONST
#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
#endif
#ifndef BUFSIZ
#define BUFSIZ 1024
#endif
#define MAXHOP 32 /* max number of tc= indirections */
#define tgetent agetent
#define tnchktc anchktc
#define tnamatch anamatch
#define tgetnum agetnum
#define tgetflag agetflag
#define tgetstr agetstr
#if 0
#define V_TERMCAP "REMOTE"
#define V_TERM "HOST"
#endif
char *RM;
/*
* termcap - routines for dealing with the terminal capability data base
*
* BUG: Should use a "last" pointer in tbuf, so that searching
* for capabilities alphabetically would not be a n**2/2
* process when large numbers of capabilities are given.
* Note: If we add a last pointer now we will screw up the
* tc capability. We really should compile termcap.
*
* Essentially all the work here is scanning and decoding escapes
* in string capabilities. We don't use stdio because the editor
* doesn't, and because living w/o it is not hard.
*/
static char *tbuf;
static int hopcount; /* detect infinite loops in termcap, init 0 */
static char *remotefile;
extern char *conffile;
int tgetent(char *, char *);
int getent(char *, char *, char *);
int tnchktc(void);
int tnamatch(char *);
static char *tskip(char *);
int64_t tgetnum(char *);
int tgetflag(char *);
char *tgetstr(char *, char **);
static char *tdecode(char *, char **);
/*
* Get an entry for terminal name in buffer bp,
* from the termcap file. Parse is very rudimentary;
* we just notice escaped newlines.
*/
int
tgetent(char *bp, char *name)
{
char *cp;
remotefile = cp = conffile ? conffile : __UNCONST(_PATH_RTADVDCONF);
return (getent(bp, name, cp));
}
int
getent(char *bp, char *name, char *cp)
{
int c;
int i = 0, cnt = 0;
char ibuf[BUFSIZ];
int tf;
tbuf = bp;
tf = 0;
/*
* TERMCAP can have one of two things in it. It can be the
* name of a file to use instead of /etc/termcap. In this
* case it better start with a "/". Or it can be an entry to
* use so we don't have to read the file. In this case it
* has to already have the newlines crunched out.
*/
if (cp && *cp) {
tf = open(RM = cp, O_RDONLY);
}
if (tf < 0) {
syslog(LOG_INFO, "<%s> open: %m", __func__);
return (-2);
}
for (;;) {
cp = bp;
for (;;) {
if (i == cnt) {
cnt = read(tf, ibuf, BUFSIZ);
if (cnt <= 0) {
close(tf);
return (0);
}
i = 0;
}
c = ibuf[i++];
if (c == '\n') {
if (cp > bp && cp[-1] == '\\') {
cp--;
continue;
}
break;
}
if (cp >= bp + BUFSIZ) {
write(2,"Remcap entry too long\n", 23);
break;
} else
*cp++ = c;
}
*cp = 0;
/*
* The real work for the match.
*/
if (tnamatch(name)) {
close(tf);
return (tnchktc());
}
}
}
/*
* tnchktc: check the last entry, see if it's tc=xxx. If so,
* recursively find xxx and append that entry (minus the names)
* to take the place of the tc=xxx entry. This allows termcap
* entries to say "like an HP2621 but doesn't turn on the labels".
* Note that this works because of the left to right scan.
*/
int
tnchktc(void)
{
char *p, *q;
char tcname[16]; /* name of similar terminal */
char tcbuf[BUFSIZ];
char *holdtbuf = tbuf;
int l;
p = tbuf + strlen(tbuf) - 2; /* before the last colon */
while (*--p != ':')
if (p < tbuf) {
write(2, "Bad remcap entry\n", 18);
return (0);
}
p++;
/* p now points to beginning of last field */
if (p[0] != 't' || p[1] != 'c')
return (1);
strlcpy(tcname, p + 3, sizeof tcname);
q = tcname;
while (*q && *q != ':')
q++;
*q = 0;
if (++hopcount > MAXHOP) {
write(2, "Infinite tc= loop\n", 18);
return (0);
}
if (getent(tcbuf, tcname, remotefile) != 1) {
return (0);
}
for (q = tcbuf; *q++ != ':'; )
;
l = p - holdtbuf + strlen(q);
if (l > BUFSIZ) {
write(2, "Remcap entry too long\n", 23);
q[BUFSIZ - (p-holdtbuf)] = 0;
}
strcpy(p, q);
tbuf = holdtbuf;
return (1);
}
/*
* Tnamatch deals with name matching. The first field of the termcap
* entry is a sequence of names separated by |'s, so we compare
* against each such name. The normal : terminator after the last
* name (before the first field) stops us.
*/
int
tnamatch(char *np)
{
char *Np, *Bp;
Bp = tbuf;
if (*Bp == '#')
return (0);
for (;;) {
for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
continue;
if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
return (1);
while (*Bp && *Bp != ':' && *Bp != '|')
Bp++;
if (*Bp == 0 || *Bp == ':')
return (0);
Bp++;
}
}
/*
* Skip to the next field. Notice that this is very dumb, not
* knowing about \: escapes or any such. If necessary, :'s can be put
* into the termcap file in octal.
*/
static char *
tskip(char *bp)
{
int dquote;
dquote = 0;
while (*bp) {
switch (*bp) {
case ':':
if (!dquote)
goto breakbreak;
else
bp++;
break;
case '\\':
bp++;
if (isdigit((unsigned char)*bp)) {
while (isdigit((unsigned char)*bp++))
;
} else
bp++;
case '"':
dquote = (dquote ? 0 : 1);
bp++;
break;
default:
bp++;
break;
}
}
breakbreak:
if (*bp == ':')
bp++;
return (bp);
}
/*
* Return the (numeric) option id.
* Numeric options look like
* li#80
* i.e. the option string is separated from the numeric value by
* a # character. If the option is not found we return -1.
* Note that we handle octal numbers beginning with 0.
*/
int64_t
tgetnum(char *id)
{
int64_t i;
int base;
char *bp = tbuf;
for (;;) {
bp = tskip(bp);
if (*bp == 0)
return (-1);
if (strncmp(bp, id, strlen(id)) != 0)
continue;
bp += strlen(id);
if (*bp == '@')
return (-1);
if (*bp != '#')
continue;
bp++;
base = 10;
if (*bp == '0')
base = 8;
i = 0;
while (isdigit((unsigned char)*bp))
i *= base, i += *bp++ - '0';
return (i);
}
}
/*
* Handle a flag option.
* Flag options are given "naked", i.e. followed by a : or the end
* of the buffer. Return 1 if we find the option, or 0 if it is
* not given.
*/
int
tgetflag(char *id)
{
char *bp = tbuf;
for (;;) {
bp = tskip(bp);
if (!*bp)
return (0);
if (strncmp(bp, id, strlen(id)) == 0) {
bp += strlen(id);
if (!*bp || *bp == ':')
return (1);
else if (*bp == '@')
return (0);
}
}
}
/*
* Get a string valued option.
* These are given as
* cl=^Z
* Much decoding is done on the strings, and the strings are
* placed in area, which is a ref parameter which is updated.
* No checking on area overflow.
*/
char *
tgetstr(char *id, char **area)
{
char *bp = tbuf;
for (;;) {
bp = tskip(bp);
if (!*bp)
return (0);
if (strncmp(bp, id, strlen(id)) != 0)
continue;
bp += strlen(id);
if (*bp == '@')
return (0);
if (*bp != '=')
continue;
bp++;
return (tdecode(bp, area));
}
}
/*
* Tdecode does the grung work to decode the
* string capability escapes.
*/
static char *
tdecode(char *str, char **area)
{
char *cp;
int c;
const char *dps = "E\033^^\\\\::n\nr\rt\tb\bf\f\"\"", *dp;
int i;
char term;
term = ':';
cp = *area;
again:
if (*str == '"') {
term = '"';
str++;
}
while ((c = *str++) && c != term) {
switch (c) {
case '^':
c = *str++ & 037;
break;
case '\\':
dp = dps;
c = *str++;
nextc:
if (*dp++ == c) {
c = *dp++;
break;
}
dp++;
if (*dp)
goto nextc;
if (isdigit((unsigned char)c)) {
c -= '0', i = 2;
do
c <<= 3, c |= *str++ - '0';
while (--i && isdigit((unsigned char)*str));
}
break;
}
*cp++ = c;
}
if (c == term && term != ':') {
term = ':';
goto again;
}
*cp++ = 0;
str = *area;
*area = cp;
return (str);
}

46
usr.sbin/rtadvd/advcap.h Normal file
View File

@ -0,0 +1,46 @@
/* $NetBSD: advcap.h,v 1.7 2011/12/10 19:14:29 roy Exp $ */
/* $KAME: advcap.h,v 1.5 2003/06/09 05:40:54 t-momose Exp $ */
/*
* Copyright (C) 1994,1995 by Andrey A. Chernov, Moscow, Russia.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* Based on Id: termcap.h,v 1.8 1996/09/10 12:42:10 peter Exp */
#ifndef _ADVCAP_H_
#define _ADVCAP_H_
#include <sys/cdefs.h>
__BEGIN_DECLS
extern int agetent(char *, const char *);
extern int agetflag(const char *);
extern int64_t agetnum(const char *);
extern char *agetstr(const char *, char **);
__END_DECLS
#endif /* _ADVCAP_H_ */

1324
usr.sbin/rtadvd/config.c Normal file

File diff suppressed because it is too large Load Diff

49
usr.sbin/rtadvd/config.h Normal file
View File

@ -0,0 +1,49 @@
/* $NetBSD: config.h,v 1.9 2012/12/13 15:36:36 roy Exp $ */
/* $KAME: config.h,v 1.9 2003/08/06 04:19:40 ono Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
extern void free_rainfo(struct rainfo *);
extern void getconfig(const char *, int);
extern void delete_prefix(struct prefix *);
extern void invalidate_prefix(struct prefix *);
extern void update_prefix(struct prefix *);
extern void make_prefix(struct rainfo *, int, struct in6_addr *, int);
extern void make_packet(struct rainfo *);
extern void get_prefix(struct rainfo *);
/*
* it is highly unlikely to have 100 information options,
* so it should be okay to limit it
*/
#define MAXPREFIX 100
#define MAXROUTE 100
#define MAXRDNSS 100
#define MAXDNSSL 100

280
usr.sbin/rtadvd/dump.c Normal file
View File

@ -0,0 +1,280 @@
/* $NetBSD: dump.c,v 1.12 2015/06/05 14:09:20 roy Exp $ */
/* $KAME: dump.c,v 1.34 2004/06/14 05:35:59 itojun Exp $ */
/*
* Copyright (C) 2000 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <net/if.h>
#include <net/if_dl.h>
#ifdef __FreeBSD__
#include <net/if_var.h>
#endif
#include <netinet/in.h>
/* XXX: the following two are non-standard include files */
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <syslog.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include "rtadvd.h"
#include "timer.h"
#include "if.h"
#include "dump.h"
static FILE *fp;
static char *ether_str(struct sockaddr_dl *);
static void if_dump(void);
static const char *rtpref_str[] = {
"medium", /* 00 */
"high", /* 01 */
"rsv", /* 10 */
"low" /* 11 */
};
static char *
ether_str(struct sockaddr_dl *sdl)
{
static char hbuf[NI_MAXHOST];
if (sdl->sdl_alen) {
if (getnameinfo((struct sockaddr *)sdl, sdl->sdl_len,
hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
snprintf(hbuf, sizeof(hbuf), "<invalid>");
} else
snprintf(hbuf, sizeof(hbuf), "NONE");
return(hbuf);
}
static void
if_dump(void)
{
struct rainfo *rai;
struct prefix *pfx;
struct rtinfo *rti;
struct rdnss *rdns;
struct rdnss_addr *rdnsa;
struct dnssl *dnsl;
struct dnssl_domain *dnsd;
char *p, len;
char prefixbuf[INET6_ADDRSTRLEN];
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); /* XXX: unused in most cases */
TAILQ_FOREACH(rai, &ralist, next) {
fprintf(fp, "%s:\n", rai->ifname);
fprintf(fp, " Status: %s\n",
(rai->ifflags & IFF_UP) ? "UP" : "DOWN");
/* control information */
if (rai->lastsent.tv_sec) {
/* note that ctime() appends CR by itself */
fprintf(fp, " Last RA sent: %s",
ctime((time_t *)&rai->lastsent.tv_sec));
}
if (rai->timer) {
fprintf(fp, " Next RA will be sent: %s",
ctime((time_t *)&rai->timer->tm.tv_sec));
}
else
fprintf(fp, " RA timer is stopped");
fprintf(fp, " waits: %d, initcount: %d\n",
rai->waiting, rai->initcounter);
/* statistics */
fprintf(fp, " statistics: RA(out/in/inconsistent): "
"%llu/%llu/%llu, ",
(unsigned long long)rai->raoutput,
(unsigned long long)rai->rainput,
(unsigned long long)rai->rainconsistent);
fprintf(fp, "RS(input): %llu\n",
(unsigned long long)rai->rsinput);
/* interface information */
if (rai->advlinkopt)
fprintf(fp, " Link-layer address: %s\n",
ether_str(rai->sdl));
fprintf(fp, " MTU: %d\n", rai->phymtu);
/* Router configuration variables */
fprintf(fp, " DefaultLifetime: %d, MaxAdvInterval: %d, "
"MinAdvInterval: %d\n", rai->lifetime, rai->maxinterval,
rai->mininterval);
fprintf(fp, " Flags: %s%s%s, ",
rai->managedflg ? "M" : "", rai->otherflg ? "O" : "",
"");
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);
if (rai->clockskew)
fprintf(fp, " Clock skew: %dsec\n",
rai->clockskew);
TAILQ_FOREACH(pfx, &rai->prefix, next) {
if (pfx == TAILQ_FIRST(&rai->prefix))
fprintf(fp, " Prefixes:\n");
fprintf(fp, " %s/%d(",
inet_ntop(AF_INET6, &pfx->prefix, prefixbuf,
sizeof(prefixbuf)), pfx->prefixlen);
switch (pfx->origin) {
case PREFIX_FROM_KERNEL:
fprintf(fp, "KERNEL, ");
break;
case PREFIX_FROM_CONFIG:
fprintf(fp, "CONFIG, ");
break;
case PREFIX_FROM_DYNAMIC:
fprintf(fp, "DYNAMIC, ");
break;
}
if (pfx->validlifetime == ND6_INFINITE_LIFETIME)
fprintf(fp, "vltime: infinity");
else
fprintf(fp, "vltime: %ld",
(long)pfx->validlifetime);
if (pfx->vltimeexpire != 0)
fprintf(fp, "(decr,expire %lld), ", (long 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");
else
fprintf(fp, "pltime: %ld",
(long)pfx->preflifetime);
if (pfx->pltimeexpire != 0)
fprintf(fp, "(decr,expire %lld), ", (long 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" : "",
"");
if (pfx->timer) {
struct timespec *rest;
rest = rtadvd_timer_rest(pfx->timer);
if (rest) { /* XXX: what if not? */
fprintf(fp, ", expire in: %ld",
(long)rest->tv_sec);
}
}
fprintf(fp, ")\n");
}
TAILQ_FOREACH(rti, &rai->route, next) {
if (rti == TAILQ_FIRST(&rai->route))
fprintf(fp, " Route Information:\n");
fprintf(fp, " %s/%d (",
inet_ntop(AF_INET6, &rti->prefix,
prefixbuf, sizeof(prefixbuf)),
rti->prefixlen);
fprintf(fp, "preference: %s, ",
rtpref_str[0xff & (rti->rtpref >> 3)]);
if (rti->ltime == ND6_INFINITE_LIFETIME)
fprintf(fp, "lifetime: infinity");
else
fprintf(fp, "lifetime: %ld", (long)rti->ltime);
fprintf(fp, ")\n");
}
TAILQ_FOREACH(rdns, &rai->rdnss, next) {
fprintf(fp, " Recursive DNS Servers:\n");
if (rdns->lifetime == ND6_INFINITE_LIFETIME)
fprintf(fp, " lifetime: infinity\n");
else
fprintf(fp, " lifetime: %ld\n",
(long)rdns->lifetime);
TAILQ_FOREACH(rdnsa, &rdns->list, next)
fprintf(fp, " %s\n",
inet_ntop(AF_INET6, &rdnsa->addr,
prefixbuf, sizeof(prefixbuf)));
}
TAILQ_FOREACH(dnsl, &rai->dnssl, next) {
fprintf(fp, " DNS Search List:\n");
if (dnsl->lifetime == ND6_INFINITE_LIFETIME)
fprintf(fp, " lifetime: infinity\n");
else
fprintf(fp, " lifetime: %ld\n",
(long)dnsl->lifetime);
TAILQ_FOREACH(dnsd, &dnsl->list, next) {
fprintf(fp, " ");
for (p = dnsd->domain, len = *p++;
len != 0;
len = *p++)
{
if (p != dnsd->domain)
fputc('.', fp);
while(len-- != 0)
fputc(*p++, fp);
}
fputc('\n', fp);
}
}
}
}
void
rtadvd_dump_file(const char *dumpfile)
{
syslog(LOG_DEBUG, "<%s> dump current status to %s", __func__,
dumpfile);
if ((fp = fopen(dumpfile, "w")) == NULL) {
syslog(LOG_WARNING, "<%s> open a dump file(%s): %m",
__func__, dumpfile);
return;
}
if_dump();
fclose(fp);
}

33
usr.sbin/rtadvd/dump.h Normal file
View File

@ -0,0 +1,33 @@
/* $NetBSD: dump.h,v 1.2 2011/12/10 19:14:29 roy Exp $ */
/* $KAME: dump.h,v 1.1 2000/05/23 11:31:26 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
extern void rtadvd_dump_file(const char *);

418
usr.sbin/rtadvd/if.c Normal file
View File

@ -0,0 +1,418 @@
/* $NetBSD: if.c,v 1.23 2015/06/05 15:41:59 roy Exp $ */
/* $KAME: if.c,v 1.36 2004/11/30 22:32:01 suz Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_types.h>
#include <ifaddrs.h>
#ifdef __FreeBSD__
#include <net/ethernet.h>
#else
#include <net/if_ether.h>
#endif
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include "rtadvd.h"
#include "if.h"
#ifndef RT_ROUNDUP
#define RT_ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
#endif
static void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{
int i;
for (i = 0; i < RTAX_MAX; i++) {
if (addrs & (1 << i)) {
rti_info[i] = sa;
RT_ADVANCE(sa, sa);
}
else
rti_info[i] = NULL;
}
}
struct sockaddr_dl *
if_nametosdl(const char *name)
{
struct ifaddrs *ifap, *ifa;
struct sockaddr_dl *sdl;
if (getifaddrs(&ifap) != 0)
return (NULL);
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (strcmp(ifa->ifa_name, name) != 0)
continue;
if (ifa->ifa_addr->sa_family != AF_LINK)
continue;
sdl = malloc(ifa->ifa_addr->sa_len);
if (!sdl)
continue; /*XXX*/
memcpy(sdl, ifa->ifa_addr, ifa->ifa_addr->sa_len);
freeifaddrs(ifap);
return (sdl);
}
freeifaddrs(ifap);
return (NULL);
}
int
if_getmtu(const char *name)
{
struct ifreq ifr;
int s, mtu;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
return 0;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET6;
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
else
mtu = 0;
close(s);
return mtu;
}
/* give interface index and its old flags, then new flags returned */
int
if_getflags(int ifindex, int oifflags)
{
struct ifreq ifr;
int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
syslog(LOG_ERR, "<%s> socket: %m", __func__);
return (oifflags & ~IFF_UP);
}
memset(&ifr, 0, sizeof(ifr));
if_indextoname(ifindex, ifr.ifr_name);
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
syslog(LOG_ERR, "<%s> ioctl:SIOCGIFFLAGS: failed for %s",
__func__, ifr.ifr_name);
close(s);
return (oifflags & ~IFF_UP);
}
close(s);
return (ifr.ifr_flags);
}
#define ROUNDUP8(a) (1 + (((a) - 1) | 7))
int
lladdropt_length(struct sockaddr_dl *sdl)
{
switch (sdl->sdl_type) {
case IFT_ETHER:
case IFT_FDDI:
return(ROUNDUP8(ETHER_ADDR_LEN + 2));
default:
return(0);
}
}
void
lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt)
{
char *addr;
ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */
switch (sdl->sdl_type) {
case IFT_ETHER:
case IFT_FDDI:
ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
addr = (char *)(ndopt + 1);
memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
break;
default:
syslog(LOG_ERR, "<%s> unsupported link type(%d)",
__func__, sdl->sdl_type);
exit(1);
}
return;
}
#define FILTER_MATCH(type, filter) ((0x1 << type) & filter)
#define SIN6(s) ((struct sockaddr_in6 *)(s))
#define SDL(s) ((struct sockaddr_dl *)(s))
char *
get_next_msg(char *buf, char *lim, int ifindex, size_t *lenp, int filter)
{
struct rt_msghdr *rtm;
struct ifa_msghdr *ifam;
struct sockaddr *sa, *dst, *gw, *ifa, *rti_info[RTAX_MAX];
*lenp = 0;
for (rtm = (struct rt_msghdr *)buf;
rtm < (struct rt_msghdr *)lim;
rtm = (struct rt_msghdr *)(((char *)rtm) + rtm->rtm_msglen)) {
/* just for safety */
if (!rtm->rtm_msglen) {
syslog(LOG_WARNING, "<%s> rtm_msglen is 0 "
"(buf=%p lim=%p rtm=%p)", __func__,
buf, lim, rtm);
break;
}
if (FILTER_MATCH(rtm->rtm_type, filter) == 0) {
continue;
}
switch (rtm->rtm_type) {
case RTM_GET:
case RTM_ADD:
case RTM_DELETE:
/* address related checks */
sa = (struct sockaddr *)(rtm + 1);
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
if ((dst = rti_info[RTAX_DST]) == NULL ||
dst->sa_family != AF_INET6)
continue;
if (IN6_IS_ADDR_LINKLOCAL(&SIN6(dst)->sin6_addr) ||
IN6_IS_ADDR_MULTICAST(&SIN6(dst)->sin6_addr))
continue;
if ((gw = rti_info[RTAX_GATEWAY]) == NULL ||
gw->sa_family != AF_LINK)
continue;
if (ifindex && SDL(gw)->sdl_index != ifindex)
continue;
if (rti_info[RTAX_NETMASK] == NULL)
continue;
/* found */
*lenp = rtm->rtm_msglen;
return (char *)rtm;
/* NOTREACHED */
case RTM_NEWADDR:
case RTM_DELADDR:
ifam = (struct ifa_msghdr *)rtm;
/* address related checks */
sa = (struct sockaddr *)(ifam + 1);
get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
if ((ifa = rti_info[RTAX_IFA]) == NULL ||
(ifa->sa_family != AF_INET &&
ifa->sa_family != AF_INET6))
continue;
if (ifa->sa_family == AF_INET6 &&
(IN6_IS_ADDR_LINKLOCAL(&SIN6(ifa)->sin6_addr) ||
IN6_IS_ADDR_MULTICAST(&SIN6(ifa)->sin6_addr)))
continue;
if (ifindex && ifam->ifam_index != ifindex)
continue;
/* found */
*lenp = ifam->ifam_msglen;
return (char *)rtm;
/* NOTREACHED */
#ifdef RTM_IFANNOUNCE
case RTM_IFANNOUNCE:
#endif
case RTM_IFINFO:
/* found */
*lenp = rtm->rtm_msglen;
return (char *)rtm;
/* NOTREACHED */
}
}
return (char *)rtm;
}
#undef FILTER_MATCH
struct in6_addr *
get_addr(char *buf)
{
struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
struct sockaddr *sa, *rti_info[RTAX_MAX];
sa = (struct sockaddr *)(rtm + 1);
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
return(&SIN6(rti_info[RTAX_DST])->sin6_addr);
}
int
get_rtm_ifindex(char *buf)
{
struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
struct sockaddr *sa, *rti_info[RTAX_MAX];
sa = (struct sockaddr *)(rtm + 1);
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
return(((struct sockaddr_dl *)rti_info[RTAX_GATEWAY])->sdl_index);
}
int
get_ifm_ifindex(char *buf)
{
struct if_msghdr *ifm = (struct if_msghdr *)buf;
return ((int)ifm->ifm_index);
}
int
get_ifam_ifindex(char *buf)
{
struct ifa_msghdr *ifam = (struct ifa_msghdr *)buf;
return ((int)ifam->ifam_index);
}
int
get_ifm_flags(char *buf)
{
struct if_msghdr *ifm = (struct if_msghdr *)buf;
return (ifm->ifm_flags);
}
#ifdef RTM_IFANNOUNCE
int
get_ifan_ifindex(char *buf)
{
struct if_announcemsghdr *ifan = (struct if_announcemsghdr *)buf;
return ((int)ifan->ifan_index);
}
int
get_ifan_what(char *buf)
{
struct if_announcemsghdr *ifan = (struct if_announcemsghdr *)buf;
return ((int)ifan->ifan_what);
}
#endif
int
get_prefixlen(char *buf)
{
struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
struct sockaddr *sa, *rti_info[RTAX_MAX];
unsigned char *p, *lim;
sa = (struct sockaddr *)(rtm + 1);
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
sa = rti_info[RTAX_NETMASK];
p = (unsigned char *)(&SIN6(sa)->sin6_addr);
lim = (unsigned char *)sa + sa->sa_len;
return prefixlen(p, lim);
}
int
prefixlen(const unsigned char *p, const unsigned char *lim)
{
int masklen;
for (masklen = 0; p < lim; p++) {
switch (*p) {
case 0xff:
masklen += 8;
break;
case 0xfe:
masklen += 7;
break;
case 0xfc:
masklen += 6;
break;
case 0xf8:
masklen += 5;
break;
case 0xf0:
masklen += 4;
break;
case 0xe0:
masklen += 3;
break;
case 0xc0:
masklen += 2;
break;
case 0x80:
masklen += 1;
break;
case 0x00:
break;
default:
return(-1);
}
}
return(masklen);
}
int
rtmsg_type(char *buf)
{
struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
return(rtm->rtm_type);
}
int
rtmsg_len(char *buf)
{
struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
return(rtm->rtm_msglen);
}

54
usr.sbin/rtadvd/if.h Normal file
View File

@ -0,0 +1,54 @@
/* $NetBSD: if.h,v 1.10 2012/12/13 15:36:36 roy Exp $ */
/* $KAME: if.h,v 1.12 2003/09/21 07:17:03 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define RTADV_TYPE2BITMASK(type) (0x1 << type)
struct nd_opt_hdr;
struct sockaddr_dl *if_nametosdl(const char *);
int if_getmtu(const char *);
int if_getflags(int, int);
int lladdropt_length(struct sockaddr_dl *);
void lladdropt_fill(struct sockaddr_dl *, struct nd_opt_hdr *);
char *get_next_msg(char *, char *, int, size_t *, int);
struct in6_addr *get_addr(char *);
int get_rtm_ifindex(char *);
int get_ifm_ifindex(char *);
int get_ifam_ifindex(char *);
int get_ifm_flags(char *);
#ifdef RTM_IFANNOUNCE
int get_ifan_ifindex(char *);
int get_ifan_what(char *);
#endif
int get_prefixlen(char *);
int prefixlen(const unsigned char *, const unsigned char *);
int rtmsg_type(char *);
int rtmsg_len(char *);

View File

@ -0,0 +1,4 @@
/* $NetBSD: pathnames.h,v 1.3 2000/05/23 11:37:59 itojun Exp $ */
/* $KAME: pathnames.h,v 1.2 2000/05/16 13:34:13 itojun Exp $ */
#define _PATH_RTADVDCONF "/etc/rtadvd.conf"

488
usr.sbin/rtadvd/rrenum.c Normal file
View File

@ -0,0 +1,488 @@
/* $NetBSD: rrenum.c,v 1.18 2015/06/05 15:41:59 roy Exp $ */
/* $KAME: rrenum.c,v 1.14 2004/06/14 05:36:00 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* 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>
#include <sys/sysctl.h>
#include <net/if.h>
#ifdef __FreeBSD__
#include <net/if_var.h>
#endif
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include "rtadvd.h"
#include "rrenum.h"
#include "if.h"
#define RR_ISSET_SEGNUM(segnum_bits, segnum) \
((((segnum_bits)[(segnum) >> 5]) & (1 << ((segnum) & 31))) != 0)
#define RR_SET_SEGNUM(segnum_bits, segnum) \
(((segnum_bits)[(segnum) >> 5]) |= (1 << ((segnum) & 31)))
struct rr_operation {
u_long rro_seqnum;
u_long rro_segnum_bits[8];
};
static struct rr_operation rro;
static int rr_rcvifindex;
static int rrcmd2pco[RPM_PCO_MAX] = {
0,
SIOCAIFPREFIX_IN6,
SIOCCIFPREFIX_IN6,
SIOCSGIFPREFIX_IN6
};
static int s = -1;
/*
* Check validity of a Prefix Control Operation(PCO).
* Return 0 on success, 1 on failure.
*/
static int
rr_pco_check(int len, struct rr_pco_match *rpm)
{
struct rr_pco_use *rpu, *rpulim;
int checklen;
/* rpm->rpm_len must be (4N * 3) as router-renum-05.txt */
if ((rpm->rpm_len - 3) < 0 || /* must be at least 3 */
(rpm->rpm_len - 3) & 0x3) { /* must be multiple of 4 */
syslog(LOG_WARNING, "<%s> rpm_len %d is not 4N * 3",
__func__, rpm->rpm_len);
return 1;
}
/* rpm->rpm_code must be valid value */
switch (rpm->rpm_code) {
case RPM_PCO_ADD:
case RPM_PCO_CHANGE:
case RPM_PCO_SETGLOBAL:
break;
default:
syslog(LOG_WARNING, "<%s> unknown rpm_code %d", __func__,
rpm->rpm_code);
return 1;
}
/* rpm->rpm_matchlen must be 0 to 128 inclusive */
if (rpm->rpm_matchlen > 128) {
syslog(LOG_WARNING, "<%s> rpm_matchlen %d is over 128",
__func__, rpm->rpm_matchlen);
return 1;
}
/*
* rpu->rpu_uselen, rpu->rpu_keeplen, and sum of them must be
* between 0 and 128 inclusive
*/
for (rpu = (struct rr_pco_use *)(rpm + 1),
rpulim = (struct rr_pco_use *)((char *)rpm + len);
rpu < rpulim;
rpu += 1) {
checklen = rpu->rpu_uselen;
checklen += rpu->rpu_keeplen;
/*
* omit these check, because either of rpu_uselen
* and rpu_keeplen is unsigned char
* (128 > rpu_uselen > 0)
* (128 > rpu_keeplen > 0)
* (rpu_uselen + rpu_keeplen > 0)
*/
if (checklen > 128) {
syslog(LOG_WARNING, "<%s> sum of rpu_uselen %d and"
" rpu_keeplen %d is %d(over 128)",
__func__, rpu->rpu_uselen,
rpu->rpu_keeplen,
rpu->rpu_uselen + rpu->rpu_keeplen);
return 1;
}
}
return 0;
}
static void
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) { /* no use prefix */
if (rpm->rpm_code == RPM_PCO_ADD)
return;
irr->irr_u_uselen = 0;
irr->irr_u_keeplen = 0;
irr->irr_raf_mask_onlink = 0;
irr->irr_raf_mask_auto = 0;
irr->irr_vltime = 0;
irr->irr_pltime = 0;
memset(&irr->irr_flags, 0, sizeof(irr->irr_flags));
irr->irr_useprefix.sin6_len = 0; /* let it mean, no addition */
irr->irr_useprefix.sin6_family = 0;
irr->irr_useprefix.sin6_addr = in6addr_any;
if (ioctl(s, rrcmd2pco[rpm->rpm_code], irr) < 0 &&
errno != EADDRNOTAVAIL)
syslog(LOG_ERR, "<%s> ioctl: %m", __func__);
return;
}
for (rpu = (struct rr_pco_use *)(rpm + 1),
rpulim = (struct rr_pco_use *)((char *)rpm + len);
rpu < rpulim;
rpu += 1) {
/* init in6_rrenumreq fields */
irr->irr_u_uselen = rpu->rpu_uselen;
irr->irr_u_keeplen = rpu->rpu_keeplen;
irr->irr_raf_mask_onlink =
!!(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK);
irr->irr_raf_mask_auto =
!!(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_AUTO);
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) == 0 ? 0 : 1;
irr->irr_raf_auto =
(rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO) == 0 ? 0 : 1;
irr->irr_rrf_decrvalid =
(rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME) == 0 ? 0 : 1;
irr->irr_rrf_decrprefd =
(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;
if (ioctl(s, rrcmd2pco[rpm->rpm_code], irr) < 0 &&
errno != EADDRNOTAVAIL)
syslog(LOG_ERR, "<%s> ioctl: %m", __func__);
/* 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 */
TAILQ_FOREACH(pp, &rai->prefix, next) {
struct timespec 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) {
clock_gettime(CLOCK_MONOTONIC,
&now);
pp->vltimeexpire =
now.tv_sec + pp->validlifetime;
} else
pp->vltimeexpire = 0;
if (irr->irr_rrf_decrprefd) {
clock_gettime(CLOCK_MONOTONIC,
&now);
pp->pltimeexpire =
now.tv_sec + pp->preflifetime;
} else
pp->pltimeexpire = 0;
}
}
}
}
}
/*
* process a Prefix Control Operation(PCO).
* return 0 on success, 1 on failure
*/
static int
do_pco(struct icmp6_router_renum *rr, int len, struct rr_pco_match *rpm)
{
int ifindex = 0;
struct in6_rrenumreq irr;
struct rainfo *rai;
if ((rr_pco_check(len, rpm) != 0))
return 1;
if (s == -1 && (s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
syslog(LOG_ERR, "<%s> socket: %m", __func__);
exit(1);
}
memset(&irr, 0, sizeof(irr));
irr.irr_origin = PR_ORIG_RR;
irr.irr_m_len = rpm->rpm_matchlen;
irr.irr_m_minlen = rpm->rpm_minlen;
irr.irr_m_maxlen = rpm->rpm_maxlen;
irr.irr_matchprefix.sin6_len = sizeof(irr.irr_matchprefix);
irr.irr_matchprefix.sin6_family = AF_INET6;
irr.irr_matchprefix.sin6_addr = rpm->rpm_prefix;
/*
* if ICMP6_RR_FLAGS_FORCEAPPLY(A flag) is 0 and IFF_UP is off,
* the interface is not applied
*/
if (rr->rr_flags & ICMP6_RR_FLAGS_FORCEAPPLY) {
while (if_indextoname(++ifindex, irr.irr_name)) {
rai = if_indextorainfo(ifindex);
if (rai && (rai->ifflags & IFF_UP)) {
/* TODO: interface scope check */
do_use_prefix(len, rpm, &irr, ifindex);
}
}
}
if (errno == ENXIO)
return 0;
else if (errno) {
syslog(LOG_ERR, "<%s> if_indextoname: %m", __func__);
return 1;
}
return 0;
}
/*
* call do_pco() for each Prefix Control Operations(PCOs) in a received
* Router Renumbering Command packet.
* return 0 on success, 1 on failure
*/
static int
do_rr(size_t len, struct icmp6_router_renum *rr)
{
struct rr_pco_match *rpm;
char *cp, *lim;
lim = (char *)rr + len;
cp = (char *)(rr + 1);
len -= sizeof(struct icmp6_router_renum);
while (cp < lim) {
size_t rpmlen;
rpm = (struct rr_pco_match *)cp;
if (len < sizeof(struct rr_pco_match)) {
tooshort:
syslog(LOG_ERR, "<%s> pkt too short. left len = %zd. "
"garbage at end of pkt?", __func__, len);
return 1;
}
rpmlen = rpm->rpm_len << 3;
if (len < rpmlen)
goto tooshort;
if (do_pco(rr, rpmlen, rpm)) {
syslog(LOG_WARNING, "<%s> invalid PCO", __func__);
goto next;
}
next:
cp += rpmlen;
len -= rpmlen;
}
return 0;
}
/*
* check validity of a router renumbering command packet
* return 0 on success, 1 on failure
*/
static int
rr_command_check(size_t len, struct icmp6_router_renum *rr,
struct in6_addr *from, struct in6_addr *dst)
{
char ntopbuf[INET6_ADDRSTRLEN];
/* omit rr minimal length check. hope kernel have done it. */
/* rr_command length check */
if (len < (sizeof(struct icmp6_router_renum) +
sizeof(struct rr_pco_match))) {
syslog(LOG_ERR, "<%s> rr_command len %zd is too short",
__func__, len);
return 1;
}
/* destination check. only for multicast. omit unicast check. */
if (IN6_IS_ADDR_MULTICAST(dst) && !IN6_IS_ADDR_MC_LINKLOCAL(dst) &&
!IN6_IS_ADDR_MC_SITELOCAL(dst)) {
syslog(LOG_ERR, "<%s> dst mcast addr %s is illegal",
__func__,
inet_ntop(AF_INET6, dst, ntopbuf, INET6_ADDRSTRLEN));
return 1;
}
/* seqnum and segnum check */
if (rro.rro_seqnum > rr->rr_seqnum) {
syslog(LOG_WARNING,
"<%s> rcvd old seqnum %d from %s",
__func__, (uint32_t)ntohl(rr->rr_seqnum),
inet_ntop(AF_INET6, from, ntopbuf, INET6_ADDRSTRLEN));
return 1;
}
if (rro.rro_seqnum == rr->rr_seqnum &&
(rr->rr_flags & ICMP6_RR_FLAGS_TEST) == 0 &&
RR_ISSET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum)) {
if ((rr->rr_flags & ICMP6_RR_FLAGS_REQRESULT) != 0)
syslog(LOG_WARNING,
"<%s> rcvd duped segnum %d from %s",
__func__, rr->rr_segnum,
inet_ntop(AF_INET6, from, ntopbuf,
INET6_ADDRSTRLEN));
return 0;
}
/* update seqnum */
if (rro.rro_seqnum != rr->rr_seqnum) {
/* then must be "<" */
/* init rro_segnum_bits */
memset(rro.rro_segnum_bits, 0,
sizeof(rro.rro_segnum_bits));
}
rro.rro_seqnum = rr->rr_seqnum;
return 0;
}
static void
rr_command_input(int len, struct icmp6_router_renum *rr,
struct in6_addr *from, struct in6_addr *dst)
{
/* rr_command validity check */
if (rr_command_check(len, rr, from, dst))
goto failed;
if ((rr->rr_flags & (ICMP6_RR_FLAGS_TEST|ICMP6_RR_FLAGS_REQRESULT)) ==
ICMP6_RR_FLAGS_TEST)
return;
/* do router renumbering */
if (do_rr(len, rr)) {
goto failed;
}
/* update segnum */
RR_SET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum);
return;
failed:
syslog(LOG_ERR, "<%s> received RR was invalid", __func__);
return;
}
void
rr_input(size_t len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi,
struct sockaddr_in6 *from, struct in6_addr *dst)
{
char ntopbuf[2][INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
syslog(LOG_DEBUG,
"<%s> RR received from %s to %s on %s",
__func__,
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));
/* packet validation based on Section 4.1 of RFC2894 */
if (len < sizeof(struct icmp6_router_renum)) {
syslog(LOG_NOTICE,
"<%s>: RR short message (size %zd) from %s to %s on %s",
__func__, 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;
}
/*
* 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(&sin6_sitelocal_allrouters.sin6_addr,
&pi->ipi6_addr))
{
syslog(LOG_NOTICE,
"<%s>: RR message with invalid destination (%s) "
"from %s on %s",
__func__,
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:
rr_command_input(len, rr, &from->sin6_addr, dst);
/* TODO: send reply msg */
break;
case ICMP6_ROUTER_RENUMBERING_RESULT:
/* RESULT will be processed by rrenumd */
break;
case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET:
/* TODO: sequence number reset */
break;
default:
syslog(LOG_ERR, "<%s> received unknown code %d",
__func__, rr->rr_code);
break;
}
return;
}

34
usr.sbin/rtadvd/rrenum.h Normal file
View File

@ -0,0 +1,34 @@
/* $NetBSD: rrenum.h,v 1.5 2011/12/10 19:14:29 roy Exp $ */
/* $KAME: rrenum.h,v 1.3 2001/01/21 15:37:14 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
void rr_input(size_t, struct icmp6_router_renum *, struct in6_pktinfo *,
struct sockaddr_in6 *, struct in6_addr *);

216
usr.sbin/rtadvd/rtadvd.8 Normal file
View File

@ -0,0 +1,216 @@
.\" $NetBSD: rtadvd.8,v 1.24 2012/12/13 21:49:38 wiz 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.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the project nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd December 13, 2006
.Dt RTADVD 8
.Os
.Sh NAME
.Nm rtadvd
.Nd router advertisement daemon
.Sh SYNOPSIS
.Nm
.Op Fl DdfRs
.Op Fl c Ar configfile
.Op Fl M Ar ifname
.Ar interface ...
.Sh DESCRIPTION
.Nm
sends router advertisement packets to the specified interfaces.
.Pp
The program will daemonize itself on invocation.
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
If there is no configuration file entry for an interface,
or if the configuration file does not exist at all,
.Nm
sets all the parameters to their default values.
In particular,
.Nm
reads all the interface routes from the routing table and advertises
them as on-link prefixes.
.Pp
.Nm
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,
.Nm
adds the corresponding prefix to its advertising list.
.Pp
Similarly, when an interface direct route is deleted,
.Nm
will start advertising the prefixes with zero valid and preferred
lifetimes to help the receiving hosts switch to a new prefix when
renumbering.
Note, however, that the zero valid lifetime cannot invalidate the
autoconfigured addresses at a receiving host immediately.
According to the specification, the host will retain the address
for a certain period, which will typically be two hours.
The zero lifetimes rather intend to make the address deprecated,
indicating that a new non-deprecated address should be used as the
source address of a new connection.
This behavior will last for two hours.
Then
.Nm
will completely remove the prefix from the advertising list,
and succeeding advertisements will not contain the prefix information.
.Pp
Moreover, if the status of an advertising interface changes,
.Nm
will start or stop sending router advertisements according
to the latest status.
.Pp
The
.Fl s
option may be used to disable this behavior;
.Nm
will not watch the routing table and the whole functionality described
above will be suppressed.
.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 to zero on every
advertising interface.
.Pp
The command line options are:
.Bl -tag -width indent
.\"
.It Fl c Ar configfile
Specify an alternate location,
.Ar configfile ,
for the configuration file.
By default,
.Pa /etc/rtadvd.conf
is used.
.It Fl D
Even more debugging information than that offered by the
.Fl d
option is printed.
.It Fl d
Print debugging information.
.It Fl f
Foreground mode (useful when debugging).
Log messages will be dumped to stderr when this option is specified.
.It Fl M Ar ifname
Specify an interface to join the all-routers site-local multicast group.
By default,
.Nm
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, an
.Xr ipsec 4
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.
.El
.Pp
Use
.Dv SIGHUP
to reload the configuration file
.Pa /etc/rtadvd.conf .
If an invalid parameter is found in the configuration file upon the reload, the
entry will be ignored and the old configuration will be used.
When parameters in an existing entry are updated,
.Nm
will send Router Advertisement messages with the old configuration but zero
router lifetime to the interface first, and then start to send a new message.
.Pp
Upon receipt of signal
.Dv SIGUSR1 ,
.Nm
will dump the current internal state into
.Pa /var/run/rtadvd.dump .
.Pp
Use
.Dv SIGTERM
to kill
.Nm
gracefully.
In this case,
.Nm
will transmit router advertisement with router lifetime 0
to all the interfaces
.Pq in accordance with RFC 2461 6.2.5 .
.Sh FILES
.Bl -tag -width /var/run/rtadvd.dumpXX -compact
.It Pa /etc/rtadvd.conf
The default configuration file.
.It Pa /var/run/rtadvd.pid
Contains the PID of the currently running
.Nm .
.It Pa /var/run/rtadvd.dump
The file in which
.Nm
dumps its internal state.
.El
.Sh EXIT STATUS
.Ex -std rtadvd
.Sh SEE ALSO
.Xr rtadvd.conf 5 ,
.Xr rtsol 8
.Sh HISTORY
The
.Nm
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
undesirable
.Xr icmp6 4
redirect messages.
However, based on 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.

1820
usr.sbin/rtadvd/rtadvd.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
# $NetBSD: rtadvd.conf,v 1.4 2009/11/01 15:17:59 jakllsch 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
# by hand unless you need special non-default values.
#
# You even do not need to create the configuration file. rtadvd
# would usually work well without a configuration file.
# See also: rtadvd(8)
# 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, (uncomment and) configure
# this part by hand, and then invoke rtadvd with the -s option.
#ef0:\
# :addr="2001:db8:ffff:1000::":prefixlen#64:

View File

@ -0,0 +1,497 @@
.\" $NetBSD: rtadvd.conf.5,v 1.18 2012/12/11 16:37:23 roy Exp $
.\" $KAME: rtadvd.conf.5,v 1.50 2005/01/14 05:30:59 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the project nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd December 11, 2012
.Dt RTADVD.CONF 5
.Os
.Sh NAME
.Nm rtadvd.conf
.Nd config file for router advertisement daemon
.Sh DESCRIPTION
This file describes how the router advertisement packets must be constructed
for each of the interfaces.
.Pp
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 the file as a whole.
In such cases, the
.Nm rtadvd
daemon will automatically configure itself using default values
specified in the specification.
.Pp
It obeys the famous
.Xr capfile 5
file format.
Each line in the file describes a network interface.
Fields are separated by a colon
.Pq Sq \&: ,
and each field contains one capability description.
Lines may be concatenated by the
.Sq \e
character.
The comment marker is the
.Sq \&#
character.
.Sh CAPABILITIES
Capabilities describe the value to be filled into ICMPv6 router
advertisement messages and to control
.Xr rtadvd 8
behavior.
Therefore, you are encouraged to read IETF neighbor discovery documents
if you would like to modify the sample configuration file.
.Pp
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
multicast router advertisements
.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
.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 *
the value of
.Cm maxinterval .
.El
.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.
The default value is 64.
.It Cm \&raflags
(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
.Po
.Li 'm' or 0x80
.Pc
means Managed address configuration flag bit,
and Bit 6
.Po
.Li 'o' or 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.
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.
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
.Pq unit: seconds .
The value must be either zero or between
the value of
.Cm maxinterval
and 9000.
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
.Pq unit: milliseconds .
The default value is 0, which means unspecified by this router.
.It Cm \&retrans
(num) Retrans Timer field
.Pq unit: milliseconds .
The default value is 0, which means unspecified by this router.
.El
.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, unless the
.Cm noifprefix
flag is specified.
Keywords other than
.Cm clockskew
and
.Cm noifprefix
can be augmented with a number, like
.Dq Li prefix2 ,
to specify multiple prefixes.
.Bl -tag -width indent
.It Cm \&noifprefix
(bool) Specified whether
.Nm rtadvd
should gather prefix information from the interface if no
.Cm addr
is specified.
If no
.Cm addr
is given, and
.Cm noifprefix
is set,
.Nm rtadvd
will send RA packets with no prefix information.
.It Cm \&clockskew
(num) Time skew to adjust link propagation delays and clock skews
between 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 \&prefixlen
(num) Prefix length field.
The default value is 64.
.It Cm \&pinfoflags
(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
.Po
.Li 'l' or 0x80
.Pc
means On-link flag bit,
and Bit 6
.Po
.Li 'a' or 0x40
.Pc
means Autonomous address-configuration flag bit.
The default value is "la" or 0xc0, i.e., both bits are set.
.It Cm \&addr
(str) The address filled into Prefix field.
Since
.Dq \&:
is used for
.Xr capfile 5
file format as well as IPv6 numeric address, the field MUST be quoted by
doublequote character.
.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 decrement
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 decrement
in real time, which is disabled by default.
.El
.Pp
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.
If 0 is specified, it means that the option will not be included.
The default value is 0.
If the special string
.Dq auto
is specified for this item, MTU option will be included and its value
will be set to the interface MTU automatically.
.El
.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
.Po
if
.Cm \&nolladdr
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.
If this capability exists,
.Xr rtadvd 8
will not attach source link-layer address option to
router advertisement packets.
.El
.Pp
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 \&rtprefix
(str) The prefix filled into the Prefix field of route information option.
Since
.Dq \&:
is used for
.Xr capfile 5
file format as well as IPv6 numeric address, the field MUST be quoted by
doublequote character.
.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 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.
.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
The following items are for ICMPv6 Recursive DNS Server Option and
DNS Search List Option
.Pq RFC 6106 ,
which will be attached to router advertisement header.
These items are optional.
.Bl -tag -width indent
.It Cm \&rdnss
(str) The IPv6 address of one or more recursive DNS servers.
The argument must be inside double quotes.
Multiple DNS servers can be specified in a comma-separated string.
If different lifetimes are needed for different servers,
separate entries can be given by using
.Cm rdnss ,
.Cm rdnss0 ,
.Cm rdnss1 ,
.Cm rdnss2 ...
options with corresponding
.Cm rdnssltime ,
.Cm rdnssltime0 ,
.Cm rdnssltime1 ,
.Cm rdnssltime2 ...
entries.
Note that the maximum number of servers depends on the receiver side.
See also the
.Xr resolv.conf 5
manual page for the resolver implementation.
.It Cm \&rdnssltime
The lifetime of the
.Cm rdnss
DNS server entries.
The default value is 3/2 of the interval time.
.It Cm \&dnssl
(str) One or more domain names in a comma-separated string.
These domain names will be used when making DNS queries on a
non-fully-qualified domain name.
If different lifetimes are needed for different domains, separate entries
can be given by using
.Cm dnssl ,
.Cm dnssl0 ,
.Cm dnssl1 ,
.Cm dnssl2 ...
options with corresponding
.Cm dnsslltime ,
.Cm dnsslltime0 ,
.Cm dnsslltime1 ,
.Cm dnsslltime2 ...
entries.
Note that the maximum number of names depends on the receiver side.
See also the
.Xr resolv.conf 5
manual page for the resolver implementation.
.It Cm \&dnsslltime
The lifetime of the
.Cm dnssl
DNS search list entries.
The default value is 3/2 of the interval time.
.El
.Pp
You can also refer one line from another by using
.Cm tc
capability.
See
.Xr capfile 5
for details on the capability.
.Sh EXAMPLES
As presented above, all of the advertised 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.
It can cause interoperability problem if you use an ill-configured
parameter.
.Pp
To override a configuration parameter, you can specify the parameter alone.
With the following configuration,
.Xr rtadvd 8
overrides the router lifetime parameter for the
.Li ne0
interface.
.Bd -literal
ne0:\\
:rltime#0:
.Ed
.Pp
The following example manually configures prefixes advertised from the
.Li ef0
interface.
The configuration must be used with the
.Fl s
option to
.Xr rtadvd 8 .
.Bd -literal
ef0:\\
:addr="2001:db8:ffff:1000::":prefixlen#64:
.Ed
.Pp
The following example configures the
.Li wlan0
interface and adds two DNS servers and a DNS domain search options
using the default option lifetime values.
.Bd -literal -offset
wlan0:\\
:addr="2001:db8:ffff:1000::":prefixlen#64:\\
:rdnss="2001:db8:ffff::10,2001:db8:ffff::2:43":\\
:dnssl="example.com":
.Ed
.Pp
The following example presents the default values in an explicit manner.
The configuration is provided just for reference purposes;
YOU DO NOT NEED TO HAVE IT AT ALL.
.Bd -literal
default:\\
:chlim#64:raflags#0:rltime#1800:rtime#0:retrans#0:\\
:pinfoflags="la":vltime#2592000:pltime#604800:mtu#0:
ef0:\\
:addr="2001:db8:ffff:1000::":prefixlen#64:tc=default:
.Ed
.Sh SEE ALSO
.Xr capfile 5 ,
.Xr rtadvd 8 ,
.Xr rtsol 8
.Pp
Thomas Narten, Erik Nordmark and W. A. Simpson,
.Do
Neighbor Discovery for IP version 6 (IPv6)
.Dc ,
RFC 2461
.Pp
Richard Draves,
.Do
Default Router Preferences and More-Specific Routes
.Dc ,
RFC 4191
.Pp
J. Jeong, S. Park, L. Beloeil, S. Madanapalli
.Do
IPv6 Router Advertisement Options for DNS Configuration
.Dc ,
RFC 6106
.Sh HISTORY
The
.Xr rtadvd 8
and the configuration file
.Nm
first appeared in WIDE Hydrangea IPv6 protocol stack kit.
.\" .Sh BUGS
.\" (to be written)

196
usr.sbin/rtadvd/rtadvd.h Normal file
View File

@ -0,0 +1,196 @@
/* $NetBSD: rtadvd.h,v 1.14 2015/06/05 14:09:20 roy Exp $ */
/* $KAME: rtadvd.h,v 1.30 2005/10/17 14:40:02 suz Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define RTADVD_USER "_rtadvd"
#define ALLNODES "ff02::1"
#define ALLROUTERS_LINK "ff02::2"
#define ALLROUTERS_SITE "ff05::2"
#define IN6ADDR_SITELOCAL_ALLROUTERS_INIT \
{{{ 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
//extern struct sockaddr_in6 sin6_linklocal_allnodes;
//extern struct sockaddr_in6 sin6_linklocal_allrouters;
extern struct sockaddr_in6 sin6_sitelocal_allrouters;
/* protocol constants and default values */
#define DEF_MAXRTRADVINTERVAL 600
#define DEF_ADVLINKMTU 0
#define DEF_ADVREACHABLETIME 0
#define DEF_ADVRETRANSTIMER 0
#define DEF_ADVCURHOPLIMIT 64
#define DEF_ADVVALIDLIFETIME 2592000
#define DEF_ADVPREFERREDLIFETIME 604800
#define MAXROUTERLIFETIME 9000
#define MIN_MAXINTERVAL 4
#define MAX_MAXINTERVAL 1800
#define MIN_MININTERVAL 3
#define MAXREACHABLETIME 3600000
#define MAX_INITIAL_RTR_ADVERT_INTERVAL 16
#define MAX_INITIAL_RTR_ADVERTISEMENTS 3
#define MAX_FINAL_RTR_ADVERTISEMENTS 3
#define MIN_DELAY_BETWEEN_RAS 3
#define MAX_RA_DELAY_TIME 500000000 /* nsec */
#define PREFIX_FROM_KERNEL 1
#define PREFIX_FROM_CONFIG 2
#define PREFIX_FROM_DYNAMIC 3
struct prefix {
TAILQ_ENTRY(prefix) next;
struct rainfo *rainfo; /* back pointer to the interface */
struct rtadvd_timer *timer; /* expiration timer. used when a prefix
* derived from the kernel is deleted.
*/
uint32_t validlifetime; /* AdvValidLifetime */
long vltimeexpire; /* expiration of vltime; decrement case only */
uint32_t preflifetime; /* AdvPreferredLifetime */
long pltimeexpire; /* expiration of pltime; decrement case only */
uint16_t onlinkflg; /* bool: AdvOnLinkFlag */
uint16_t autoconfflg; /* bool: AdvAutonomousFlag */
int prefixlen;
int origin; /* from kernel or config */
struct in6_addr prefix;
};
struct rtinfo {
TAILQ_ENTRY(rtinfo) next;
uint32_t ltime; /* route lifetime */
uint16_t rtpref; /* route preference */
int prefixlen;
struct in6_addr prefix;
};
struct rdnss_addr {
TAILQ_ENTRY(rdnss_addr) next;
struct in6_addr addr;
};
struct rdnss {
TAILQ_ENTRY(rdnss) next;
TAILQ_HEAD(, rdnss_addr) list;
uint32_t lifetime;
};
struct dnssl_domain {
TAILQ_ENTRY(dnssl_domain) next;
int len;
char domain[256];
};
struct dnssl {
TAILQ_ENTRY(dnssl) next;
TAILQ_HEAD(, dnssl_domain) list;
uint32_t lifetime;
};
struct soliciter {
TAILQ_ENTRY(soliciter) next;
struct sockaddr_in6 addr;
};
struct rainfo {
TAILQ_ENTRY(rainfo) next;
/* timer related parameters */
struct rtadvd_timer *timer;
int initcounter; /* counter for the first few advertisements */
struct timespec lastsent; /* timestamp when the latest RA was sent */
int waiting; /* number of RS waiting for RA */
struct rainfo *leaving; /* the config which is leaving */
struct rainfo *leaving_for; /* the new config to activate */
int leaving_adv; /* number of RA left to send */
/* interface information */
uint16_t ifindex;
int ifflags;
int advlinkopt; /* bool: whether include link-layer addr opt */
struct sockaddr_dl *sdl;
char ifname[16];
uint32_t phymtu; /* mtu of the physical interface */
/* Router configuration variables */
uint16_t lifetime; /* AdvDefaultLifetime */
uint16_t maxinterval; /* MaxRtrAdvInterval */
uint16_t mininterval; /* MinRtrAdvInterval */
int managedflg; /* AdvManagedFlag */
int otherflg; /* AdvOtherConfigFlag */
int rtpref; /* router preference */
uint32_t linkmtu; /* AdvLinkMTU */
uint32_t reachabletime; /* AdvReachableTime */
uint32_t retranstimer; /* AdvRetransTimer */
uint16_t hoplimit; /* AdvCurHopLimit */
TAILQ_HEAD(, prefix) prefix; /* AdvPrefixList(link head) */
int pfxs;
uint16_t clockskew;/* used for consisitency check of lifetimes */
TAILQ_HEAD(, rtinfo) route;
TAILQ_HEAD(, rdnss) rdnss; /* RDNSS list */
TAILQ_HEAD(, dnssl) dnssl; /* DNS Search List */
/* actual RA packet data and its length */
size_t ra_datalen;
char *ra_data;
/* statistics */
uint64_t raoutput; /* number of RAs sent */
uint64_t rainput; /* number of RAs received */
uint64_t rainconsistent; /* number of RAs inconsistent with ours */
uint64_t rsinput; /* number of RSs received */
/* info about soliciter */
TAILQ_HEAD(, soliciter) soliciter; /* recent solication source */
};
extern TAILQ_HEAD(ralist_head_t, rainfo) ralist;
struct rtadvd_timer *ra_timeout(void *);
void ra_timer_update(void *, struct timespec *);
void ra_timer_set_short_delay(struct rainfo *);
int prefix_match(struct in6_addr *, int, struct in6_addr *, int);
struct rainfo *if_indextorainfo(unsigned int);
struct prefix *find_prefix(struct rainfo *, struct in6_addr *, int);

168
usr.sbin/rtadvd/timer.c Normal file
View File

@ -0,0 +1,168 @@
/* $NetBSD: timer.c,v 1.12 2015/06/05 14:09:20 roy Exp $ */
/* $KAME: timer.c,v 1.11 2005/04/14 06:22:35 suz Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/queue.h>
#include <sys/time.h>
#include <limits.h>
#include <unistd.h>
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
#include <search.h>
#include "timer.h"
struct rtadvd_timer_head_t ra_timer = TAILQ_HEAD_INITIALIZER(ra_timer);
static struct timespec tm_limit = { LONG_MAX, 1000000000L - 1 };
static struct timespec tm_max;
void
rtadvd_timer_init(void)
{
TAILQ_INIT(&ra_timer);
tm_max = tm_limit;
}
struct rtadvd_timer *
rtadvd_add_timer(struct rtadvd_timer *(*timeout) (void *),
void (*update) (void *, struct timespec *),
void *timeodata, void *updatedata)
{
struct rtadvd_timer *newtimer;
if ((newtimer = malloc(sizeof(*newtimer))) == NULL) {
syslog(LOG_ERR,
"<%s> can't allocate memory", __func__);
exit(1);
}
memset(newtimer, 0, sizeof(*newtimer));
if (timeout == NULL) {
syslog(LOG_ERR,
"<%s> timeout function unspecified", __func__);
exit(1);
}
newtimer->expire = timeout;
newtimer->update = update;
newtimer->expire_data = timeodata;
newtimer->update_data = updatedata;
newtimer->tm = tm_max;
/* link into chain */
TAILQ_INSERT_TAIL(&ra_timer, newtimer, next);
return(newtimer);
}
void
rtadvd_remove_timer(struct rtadvd_timer **timer)
{
if (*timer) {
TAILQ_REMOVE(&ra_timer, *timer, next);
free(*timer);
*timer = NULL;
}
}
void
rtadvd_set_timer(struct timespec *tm, struct rtadvd_timer *timer)
{
struct timespec now;
/* reset the timer */
clock_gettime(CLOCK_MONOTONIC, &now);
timespecadd(&now, tm, &timer->tm);
/* upate the next expiration time */
if (timespeccmp(&timer->tm, &tm_max, <))
tm_max = timer->tm;
}
/*
* Check expiration for each timer. If a timer expires,
* call the expire function for the timer and update the timer.
* Return the next interval for select() call.
*/
struct timespec *
rtadvd_check_timer(void)
{
static struct timespec returnval;
struct timespec now;
struct rtadvd_timer *tm, *tmn;
clock_gettime(CLOCK_MONOTONIC, &now);
tm_max = tm_limit;
TAILQ_FOREACH_SAFE(tm, &ra_timer, next, tmn) {
if (timespeccmp(&tm->tm, &now, <=)) {
if ((*tm->expire)(tm->expire_data) == NULL)
continue; /* the timer was removed */
if (tm->update)
(*tm->update)(tm->update_data, &tm->tm);
timespecadd(&tm->tm, &now, &tm->tm);
}
if (timespeccmp(&tm->tm, &tm_max, <))
tm_max = tm->tm;
}
if (timespeccmp(&tm_max, &tm_limit, ==))
return(NULL);
if (timespeccmp(&tm_max, &now, <)) {
/* this may occur when the interval is too small */
timespecclear(&returnval);
} else
timespecsub(&tm_max, &now, &returnval);
return(&returnval);
}
struct timespec *
rtadvd_timer_rest(struct rtadvd_timer *timer)
{
static struct timespec returnval;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
if (timespeccmp(&timer->tm, &now, <=)) {
syslog(LOG_DEBUG,
"<%s> a timer must be expired, but not yet",
__func__);
returnval.tv_sec = 0;
returnval.tv_nsec = 0;
}
else
timespecsub(&timer->tm, &now, &returnval);
return(&returnval);
}

51
usr.sbin/rtadvd/timer.h Normal file
View File

@ -0,0 +1,51 @@
/* $NetBSD: timer.h,v 1.8 2015/06/05 14:09:20 roy Exp $ */
/* $KAME: timer.h,v 1.5 2002/05/31 13:30:38 jinmei Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
extern TAILQ_HEAD(rtadvd_timer_head_t, rtadvd_timer) ra_timer;
struct rtadvd_timer {
TAILQ_ENTRY(rtadvd_timer) next;
struct rainfo *rai;
struct timespec tm;
struct rtadvd_timer *(*expire) (void *); /* expiration function */
void *expire_data;
void (*update)(void *, struct timespec *); /* update function */
void *update_data;
};
void rtadvd_timer_init(void);
struct rtadvd_timer *rtadvd_add_timer(struct rtadvd_timer *(*) (void *),
void (*) (void *, struct timespec *), void *, void *);
void rtadvd_set_timer(struct timespec *, struct rtadvd_timer *);
void rtadvd_remove_timer(struct rtadvd_timer **);
struct timespec * rtadvd_check_timer(void);
struct timespec * rtadvd_timer_rest(struct rtadvd_timer *);