summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit832f8d224926758a9ae0b23a6b45353e44fbc87a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /usr.sbin
parent2693854b01a52b0395a91322aa3edf926bddff38 (diff)
downloadFreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip
FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/faithd/Makefile2
-rw-r--r--usr.sbin/faithd/README50
-rw-r--r--usr.sbin/faithd/faithd.8151
-rw-r--r--usr.sbin/faithd/faithd.c191
-rw-r--r--usr.sbin/faithd/faithd.h11
-rw-r--r--usr.sbin/faithd/ftp.c5
-rw-r--r--usr.sbin/faithd/prefix.c360
-rw-r--r--usr.sbin/faithd/prefix.h52
-rw-r--r--usr.sbin/faithd/rsh.c2
-rw-r--r--usr.sbin/faithd/tcp.c9
-rw-r--r--usr.sbin/gifconfig/gifconfig.89
-rw-r--r--usr.sbin/gifconfig/gifconfig.c60
-rw-r--r--usr.sbin/ifmcstat/ifmcstat.840
-rw-r--r--usr.sbin/ifmcstat/ifmcstat.c6
-rw-r--r--usr.sbin/mld6query/mld6.c9
-rw-r--r--usr.sbin/mld6query/mld6query.84
-rw-r--r--usr.sbin/ndp/ndp.821
-rw-r--r--usr.sbin/ndp/ndp.c366
-rw-r--r--usr.sbin/prefix/Makefile5
-rw-r--r--usr.sbin/prefix/prefix.c590
-rw-r--r--usr.sbin/prefix/prefix.sh74
-rw-r--r--usr.sbin/rip6query/rip6query.83
-rw-r--r--usr.sbin/rip6query/rip6query.c8
-rw-r--r--usr.sbin/route6d/route6d.89
-rw-r--r--usr.sbin/route6d/route6d.c1002
-rw-r--r--usr.sbin/route6d/route6d.h4
-rw-r--r--usr.sbin/rrenumd/lexer.l13
-rw-r--r--usr.sbin/rrenumd/parser.y50
-rw-r--r--usr.sbin/rrenumd/rrenumd.826
-rw-r--r--usr.sbin/rrenumd/rrenumd.c64
-rw-r--r--usr.sbin/rrenumd/rrenumd.conf.5107
-rw-r--r--usr.sbin/rrenumd/rrenumd.h2
-rw-r--r--usr.sbin/rtadvd/advcap.c8
-rw-r--r--usr.sbin/rtadvd/advcap.h4
-rw-r--r--usr.sbin/rtadvd/config.c396
-rw-r--r--usr.sbin/rtadvd/config.h2
-rw-r--r--usr.sbin/rtadvd/dump.c42
-rw-r--r--usr.sbin/rtadvd/dump.h2
-rw-r--r--usr.sbin/rtadvd/if.c15
-rw-r--r--usr.sbin/rtadvd/if.h37
-rw-r--r--usr.sbin/rtadvd/pathnames.h2
-rw-r--r--usr.sbin/rtadvd/rrenum.c96
-rw-r--r--usr.sbin/rtadvd/rrenum.h7
-rw-r--r--usr.sbin/rtadvd/rtadvd.845
-rw-r--r--usr.sbin/rtadvd/rtadvd.c209
-rw-r--r--usr.sbin/rtadvd/rtadvd.conf.5104
-rw-r--r--usr.sbin/rtadvd/rtadvd.h25
-rw-r--r--usr.sbin/rtadvd/timer.c2
-rw-r--r--usr.sbin/rtadvd/timer.h2
-rw-r--r--usr.sbin/rtsold/Makefile4
-rw-r--r--usr.sbin/rtsold/dump.c2
-rw-r--r--usr.sbin/rtsold/if.c9
-rw-r--r--usr.sbin/rtsold/probe.c2
-rw-r--r--usr.sbin/rtsold/rtsock.c179
-rw-r--r--usr.sbin/rtsold/rtsol.c2
-rw-r--r--usr.sbin/rtsold/rtsold.842
-rw-r--r--usr.sbin/rtsold/rtsold.c33
-rw-r--r--usr.sbin/rtsold/rtsold.h6
-rw-r--r--usr.sbin/setkey/parse.y85
-rw-r--r--usr.sbin/setkey/scriptdump.pl4
-rw-r--r--usr.sbin/setkey/setkey.8161
-rw-r--r--usr.sbin/setkey/setkey.c78
-rw-r--r--usr.sbin/setkey/token.l36
-rw-r--r--usr.sbin/traceroute6/traceroute6.82
-rw-r--r--usr.sbin/traceroute6/traceroute6.c90
65 files changed, 3452 insertions, 1586 deletions
diff --git a/usr.sbin/faithd/Makefile b/usr.sbin/faithd/Makefile
index c63b097..42da8df 100644
--- a/usr.sbin/faithd/Makefile
+++ b/usr.sbin/faithd/Makefile
@@ -14,7 +14,7 @@
# $FreeBSD$
PROG= faithd
-SRCS= faithd.c tcp.c ftp.c rsh.c
+SRCS= faithd.c tcp.c ftp.c rsh.c prefix.c
MAN= faithd.8
#CFLAGS+= -DFAITH4
CFLAGS+= -Wall
diff --git a/usr.sbin/faithd/README b/usr.sbin/faithd/README
index 4808b4a..2ad0592 100644
--- a/usr.sbin/faithd/README
+++ b/usr.sbin/faithd/README
@@ -1,7 +1,7 @@
Configuring FAITH IPv6-to-IPv4 TCP relay
Kazu Yamamoto and Jun-ichiro itojun Hagino
-$KAME: README,v 1.4 2000/05/31 03:16:14 itojun Exp $
+$KAME: README,v 1.7 2001/04/25 11:25:19 itojun Exp $
$FreeBSD$
Introduction
@@ -27,13 +27,13 @@ invoked per each TCP services (TCP port number).
clients IPv6 node "src" |
You will have to allocate an IPv6 address prefix to map IPv4 addresses into.
-The following description uses 3ffe:0501:1234:ffff:: as example.
+The following description uses 3ffe:0501:ffff:0000:: as example.
Please use a prefix which belongs to your site.
FAITH will make it possible to make a IPv6 TCP connection From IPv6 node
"src", toward IPv4 node "dest", by specifying FAITH-mapped address
-3ffe:0501:1234:ffff::123.4.5.6
-(which is, 3ffe:0501:1234:ffff:0000:0000:7b04:0506).
-The address mapping can be performed by hand:-), by speical nameserver on
+3ffe:0501:ffff:0000::123.4.5.6
+(which is, 3ffe:0501:ffff:0000:0000:0000:7b04:0506).
+The address mapping can be performed by hand:-), by special nameserver on
the network, or by special resolver on the source node.
@@ -41,7 +41,7 @@ Setup
=====
The following example assumes:
-- You have assigned 3ffe:0501:1234:ffff:: as FAITH adderss prefix.
+- You have assigned 3ffe:0501:ffff:0000:: as FAITH adderss prefix.
- You are willing to provide IPv6-to IPv4 TCP relay for telnet.
<<On the translating router on which faithd runs>>
@@ -57,12 +57,12 @@ The following example assumes:
(3) Route packets toward FAITH prefix into "faith0" interface.
# ifconfig faith0 up
- # route add -inet6 3ffe:0501:1234:ffff:: -prefixlen 64 \
- fe80::xxxx:yyyy:zzzz:wwww%faith0
+ # route add -inet6 3ffe:0501:ffff:0000:: -prefixlen 64 ::1
+ # route change -inet6 3ffe:0501:ffff:0000:: -prefixlen 64 -ifp faith0
(4) Execute "faithd" by root as follows:
- # faithd telnet /usr/local/v6/libexec/telnetd telnetd
+ # faithd telnet /usr/libexec/telnetd telnetd
1st argument is a service name you are willing to provide TCP relay.
(it can be specified either by number "23" or by string "telnet")
@@ -73,11 +73,14 @@ The following example assumes:
More examples:
- # faithd login /usr/local/v6/libexec/rlogin rlogind
- # faithd shell /usr/local/v6/libexec/rshd rshd
- # faithd ftpd /usr/local/v6/libexec/ftpd ftpd -l
+ # faithd login /usr/libexec/rlogin rlogind
+ # faithd shell /usr/libexec/rshd rshd
+ # faithd ftpd /usr/libexec/ftpd ftpd -l
# faithd sshd
+If inetd(8) on your platform have special support for faithd, it is possible
+to setup faithd services via inetd(8). Consult manpage for details.
+
<<Routing>>
@@ -95,7 +98,7 @@ There are two ways to translate IPv4 address to IPv6 address:
(5.b) Add an entry into /etc/hosts so that you can resolve hostname into
faked IPv6 addrss. For example, add the following line for www.netbsd.org:
- 3ffe:0501:1234:ffff::140.160.140.252 www.netbsd.org
+ 3ffe:0501:ffff:0000::140.160.140.252 www.netbsd.org
<<On the translating router on which faithd runs.>>
@@ -107,18 +110,31 @@ in "/var/log/daemon".
daemon.* /var/log/daemon
+Access control
+==============
+
+Since faithd implements TCP relaying service, it is critical to implement
+proper access control to cope with malicious use. Bad guy may try to
+use your relay router to circumvent access controls, or may try to
+abuse your network (like sending SPAMs from IPv4 address that belong to you).
+Install IPv6 packet filter directives that would reject traffic from
+unwanted source. If you are using inetd-based setup, you may be able to
+use access control mechanisms in inetd.
+
+
Advanced configuration
======================
If you would like to restrict IPv4 destination for translation, you may
want to do the following:
- # route add -inet6 3ffe:0501:1234:ffff::123.0.0.0 -prefixlen 104 \
- -interface faith0
+ # route add -inet6 3ffe:0501:ffff:0000::123.0.0.0 -prefixlen 104 ::1
+ # route change -inet6 3ffe:0501:ffff:0000::123.0.0.0 -prefixlen 104 \
+ -ifp faith0
By this way, you can restrict IPv4 destination to 123.0.0.0/8.
-You may also want to reject packets toward 3ffe:0501:1234:ffff::/64 which
-is not in 3ffe:0501:1234:ffff::123.0.0.0/104. This will be left as excerside
+You may also want to reject packets toward 3ffe:0501:ffff:0000::/64 which
+is not in 3ffe:0501:ffff:0000::123.0.0.0/104. This will be left as excerside
for the reader.
By doing this, you will be able to provide your IPv4 web server to outside
diff --git a/usr.sbin/faithd/faithd.8 b/usr.sbin/faithd/faithd.8
index 6d552eb..ff0fa65 100644
--- a/usr.sbin/faithd/faithd.8
+++ b/usr.sbin/faithd/faithd.8
@@ -1,4 +1,4 @@
-.\" $KAME: faithd.8,v 1.12 2000/07/04 13:15:01 itojun Exp $
+.\" $KAME: faithd.8,v 1.30 2001/05/24 20:47:56 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -38,7 +38,9 @@
.Sh SYNOPSIS
.Nm
.Op Fl dp
-.Op Ar service Op Ar serverpath Op Ar serverargs
+.Op Fl f Ar configfile
+.Ar service
+.Op Ar serverpath Op Ar serverargs
.Sh DESCRIPTION
.Nm
provides IPv6-to-IPv4 TCP relay.
@@ -96,6 +98,24 @@ address prefix, by using
and
.Xr sysctl 8
commands.
+.Pp
+.Nm
+needs a special name-to-address translation logic, so that
+hostnames gets resolved into special
+.Tn IPv6
+address prefix.
+For small-scale installation, use
+.Xr hosts 5 .
+For large-scale installation, it is useful to have
+a DNS server with special address translation support.
+An implementation called
+.Nm totd
+is available
+at
+.Pa http://www.vermicelli.pasta.cs.uit.no/ipv6/software.html .
+Make sure you do not propagate translated DNS records to normal DNS cloud,
+it is highly harmful.
+.Pp
.Ss Daemon mode
When
.Nm
@@ -136,26 +156,14 @@ You can also specify
.Ar serverargs
for the arguments for the local daemon.
.Pp
-If
-.Ar service
-is not given,
-.Li telnet
-is assumed, and
-.Nm
-will relay TCP traffic on TCP port
-.Li telnet .
-With
-.Ar service ,
-.Nm
-will work as TCP relaying daemon for specified
-.Ar service
-as described above.
-.Pp
The following options are available:
.Bl -tag -width indent
.It Fl d
Debugging information will be generated using
.Xr syslog 3 .
+.It Fl f Ar configfile
+Specify a configuration file for access control.
+See below.
.It Fl p
Use privileged TCP port number as source port,
for IPv4 TCP connection toward final destination.
@@ -200,7 +208,7 @@ is invoked via
.Xr inetd 8 ,
.Nm
will handle connection passed from standard input.
-If it the connection endpoint is in the reserved IPv6 address prefix.
+If the connection endpoint is in the reserved IPv6 address prefix,
.Nm
will relay the connection.
Otherwise,
@@ -223,6 +231,52 @@ The operation mode requires special support for
.Nm
in
.Xr inetd 8 .
+.Ss Access control
+To prevent malicious accesses,
+.Nm
+implements a simple address-based access control.
+With
+.Pa /etc/faithd.conf
+.Po
+or
+.Ar configfile
+specified by
+.Fl f
+.Pc ,
+.Nm
+will avoid relaying unwanted traffic.
+The
+.Pa faithd.conf
+contains directives with the following format:
+.Bl -bullet
+.It
+.Xo
+.Ic Ar src/slen Li deny Ar dst/dlen
+.Xc
+.Pp
+If the source address of a query matches
+.Ar src/slen ,
+and the translated destination address matches
+.Ar dst/dlen ,
+deny the connection.
+.It
+.Xo
+.Ic Ar src/slen Li permit Ar dst/dlen
+.Xc
+.Pp
+If the source address of a query matches
+.Ar src/slen ,
+and the translated destination address matches
+.Ar dst/dlen ,
+permit the connection.
+.El
+.Pp
+The directives are evaluated in sequence,
+and the first matching entry will be effective.
+.Pp
+With inetd mode,
+traffic may be filtered by using access control functionality in
+.Xr inetd 8 .
.Sh EXAMPLES
Before invoking
.Nm ,
@@ -241,9 +295,8 @@ To translate
.Li telnet
service, and provide no local telnet service, invoke
.Nm
-as either of the following:
+as follows:
.Bd -literal -offset
-# faithd
# faithd telnet
.Ed
.Pp
@@ -258,7 +311,7 @@ use the following command line:
.Pp
If you would like to pass extra arguments to the local daemon:
.Bd -literal -offset
-# faithd ftpd /usr/local/v6/libexec/ftpd ftpd -l
+# faithd ftp /usr/local/v6/libexec/ftpd ftpd -l
.Ed
.Pp
Here are some other examples.
@@ -266,14 +319,15 @@ You may need
.Fl p
to translate rsh/rlogin services.
.Bd -literal -offset
-# faithd sshd
+# faithd ssh
# faithd login /usr/local/v6/libexec/rlogin rlogind
# faithd shell /usr/local/v6/libexec/rshd rshd
.Ed
.Pp
However, you should be careful when translating rlogin or rsh
-connections. See
-.Sx SECURITY NOTICE
+connections.
+See
+.Sx SECURITY CONSIDERATIONS
for more details.
.Ss inetd mode samples
Add the following lines into
@@ -282,7 +336,7 @@ Syntax may vary depending upon your operating system.
.Bd -literal -offset
telnet stream tcp6/faith nowait root /usr/sbin/faithd telnetd
ftp stream tcp6/faith nowait root /usr/sbin/faithd ftpd -l
-ssh stream tcp6/faith nowait root /usr/sbin/faithd /usr/pkg/bin/sshd -i
+ssh stream tcp6/faith nowait root /usr/sbin/faithd /usr/sbin/sshd -i
.Ed
.Pp
.Xr inetd 8
@@ -298,6 +352,20 @@ Otherwise,
.Nm
will invoke service-specific daemon like
.Xr telnetd 8 .
+.Ss Access control samples
+The following illustrates a simple
+.Pa faithd.conf
+setting.
+.Bd -literal -offset
+# permit anyone from 3ffe:501:ffff::/48 to use the translator,
+# to connect to the following IPv4 destinations:
+# - any location except 10.0.0.0/8 and 127.0.0.0/8.
+# Permit no other connections.
+#
+3ffe:501:ffff::/48 deny 10.0.0.0/8
+3ffe:501:ffff::/48 deny 127.0.0.0/8
+3ffe:501:ffff::/48 permit 0.0.0.0/0
+.Ed
.Sh RETURN VALUES
.Nm
exits with
@@ -316,20 +384,34 @@ on error.
.%A Kazu Yamamoto
.%T "An IPv6-to-IPv4 transport relay translator"
.%R internet draft
-.%N draft-ietf-ngtrans-tcpudp-relay-01.txt
+.%N draft-ietf-ngtrans-tcpudp-relay-04.txt
.%O work in progress material
.Re
-.Sh SECURITY NOTICE
+.\"
+.Sh HISTORY
+The
+.Nm
+command first appeared in WIDE Hydrangea IPv6 protocol stack kit.
+.\"
+.Pp
+IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack
+was initially integrated into
+.Fx 4.0
+.Sh SECURITY CONSIDERATIONS
It is very insecure to use
.Xr rhosts 5
and other IP-address based authentication, for connections relayed by
.Nm
.Pq and any other TCP relaying services .
.Pp
+Administrators are advised to limit accesses to
.Nm
-itself does not implement access controls, as
-it intends to implement transparent TCP relay services.
-Administrators are advised to filter packets based on IPv6 address.
+using
+.Pa faithd.conf ,
+or by using IPv6 packet filters.
+It is to protect
+.Nm
+service from malicious parties and avoid theft of service/bandwidth.
IPv6 destination address can be limited by
carefully configuring routing entries that points to
.Xr faith 4 ,
@@ -339,12 +421,3 @@ IPv6 source address needs to be filtered by using packet filters.
Documents listed in
.Sx SEE ALSO
have more discussions on this topic.
-.\"
-.Sh HISTORY
-The
-.Nm
-command first appeared in WIDE Hydrangea IPv6 protocol stack kit.
-.Pp
-IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack
-was initially integrated into
-.Fx 4.0
diff --git a/usr.sbin/faithd/faithd.c b/usr.sbin/faithd/faithd.c
index fddf402..2f02da1 100644
--- a/usr.sbin/faithd/faithd.c
+++ b/usr.sbin/faithd/faithd.c
@@ -1,4 +1,4 @@
-/* $KAME: faithd.c,v 1.20 2000/07/01 11:40:45 itojun Exp $ */
+/* $KAME: faithd.c,v 1.39 2001/04/25 11:20:42 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -47,6 +47,9 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
+#ifdef __FreeBSD__
+#include <libutil.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
@@ -83,6 +86,7 @@
#endif
#include "faithd.h"
+#include "prefix.h"
char *serverpath = NULL;
char *serverarg[MAXARGV + 1];
@@ -101,6 +105,7 @@ static int sockfd = 0;
int dflag = 0;
static int pflag = 0;
static int inetd = 0;
+static char *configfile = NULL;
int main __P((int, char **));
static int inetd_main __P((int, char **));
@@ -115,6 +120,8 @@ static int map4to6 __P((struct sockaddr_in *, struct sockaddr_in6 *));
static void sig_child __P((int));
static void sig_terminate __P((int));
static void start_daemon __P((void));
+static void exit_stderr __P((const char *, ...))
+ __attribute__((__format__(__printf__, 1, 2)));
#ifndef HAVE_GETIFADDRS
static unsigned int if_maxindex __P((void));
#endif
@@ -156,6 +163,11 @@ inetd_main(int argc, char **argv)
const int on = 1;
char sbuf[NI_MAXSERV], snum[NI_MAXSERV];
+ if (config_load(configfile) < 0 && configfile) {
+ exit_failure("could not load config file");
+ /*NOTREACHED*/
+ }
+
if (strrchr(argv[0], '/') == NULL)
snprintf(path, sizeof(path), "%s/%s", DEFAULT_DIR, argv[0]);
else
@@ -166,17 +178,21 @@ inetd_main(int argc, char **argv)
sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
if (sockfd < 0) {
- exit_error("socket(PF_ROUTE): %s", ERRSTR);
+ exit_failure("socket(PF_ROUTE): %s", ERRSTR);
/*NOTREACHED*/
}
#endif
melen = sizeof(me);
- if (getsockname(STDIN_FILENO, (struct sockaddr *)&me, &melen) < 0)
- exit_error("getsockname");
+ if (getsockname(STDIN_FILENO, (struct sockaddr *)&me, &melen) < 0) {
+ exit_failure("getsockname: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
fromlen = sizeof(from);
- if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0)
- exit_error("getpeername");
+ if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) {
+ exit_failure("getpeername: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0,
sbuf, sizeof(sbuf), NI_NUMERICHOST) == 0)
service = sbuf;
@@ -190,8 +206,10 @@ inetd_main(int argc, char **argv)
snprintf(procname, sizeof(procname), "accepting port %s", snum);
openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
- if (argc >= MAXARGV)
+ if (argc >= MAXARGV) {
exit_failure("too many arguments");
+ /*NOTREACHED*/
+ }
serverarg[0] = serverpath = path;
for (i = 1; i < argc; i++)
serverarg[i] = argv[i];
@@ -199,8 +217,10 @@ inetd_main(int argc, char **argv)
error = setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &on,
sizeof(on));
- if (error < 0)
- exit_error("setsockopt(SO_OOBINLINE): %s", ERRSTR);
+ if (error < 0) {
+ exit_failure("setsockopt(SO_OOBINLINE): %s", ERRSTR);
+ /*NOTREACHED*/
+ }
play_child(STDIN_FILENO, (struct sockaddr *)&from);
exit_failure("should not reach here");
@@ -218,11 +238,14 @@ daemon_main(int argc, char **argv)
char *ns;
#endif /* FAITH_NS */
- while ((c = getopt(argc, argv, "dp46")) != -1) {
+ while ((c = getopt(argc, argv, "df:p46")) != -1) {
switch (c) {
case 'd':
dflag++;
break;
+ case 'f':
+ configfile = optarg;
+ break;
case 'p':
pflag++;
break;
@@ -236,12 +259,17 @@ daemon_main(int argc, char **argv)
#endif
default:
usage();
- break;
+ /*NOTREACHED*/
}
}
argc -= optind;
argv += optind;
+ if (config_load(configfile) < 0 && configfile) {
+ exit_failure("could not load config file");
+ /*NOTREACHED*/
+ }
+
#ifdef FAITH_NS
if ((ns = getenv(FAITH_NS)) != NULL) {
struct sockaddr_storage ss;
@@ -266,15 +294,12 @@ daemon_main(int argc, char **argv)
switch (argc) {
case 0:
- serverpath = DEFAULT_PATH;
- serverarg[0] = DEFAULT_NAME;
- serverarg[1] = NULL;
- service = DEFAULT_PORT_NAME;
- break;
+ usage();
+ /*NOTREACHED*/
default:
serverargc = argc - NUMARG;
if (serverargc >= MAXARGV)
- exit_error("too many augments");
+ exit_stderr("too many arguments");
serverpath = malloc(strlen(argv[NUMPRG]) + 1);
strcpy(serverpath, argv[NUMPRG]);
@@ -300,17 +325,17 @@ daemon_main(int argc, char **argv)
hints.ai_protocol = 0;
error = getaddrinfo(NULL, service, &hints, &res);
if (error)
- exit_error("getaddrinfo: %s", gai_strerror(error));
+ exit_stderr("getaddrinfo: %s", gai_strerror(error));
s_wld = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s_wld == -1)
- exit_error("socket: %s", ERRSTR);
+ exit_stderr("socket: %s", ERRSTR);
#ifdef IPV6_FAITH
if (res->ai_family == AF_INET6) {
error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_FAITH, &on, sizeof(on));
if (error == -1)
- exit_error("setsockopt(IPV6_FAITH): %s", ERRSTR);
+ exit_stderr("setsockopt(IPV6_FAITH): %s", ERRSTR);
}
#endif
#ifdef FAITH4
@@ -318,31 +343,31 @@ daemon_main(int argc, char **argv)
if (res->ai_family == AF_INET) {
error = setsockopt(s_wld, IPPROTO_IP, IP_FAITH, &on, sizeof(on));
if (error == -1)
- exit_error("setsockopt(IP_FAITH): %s", ERRSTR);
+ exit_stderr("setsockopt(IP_FAITH): %s", ERRSTR);
}
#endif
#endif /* FAITH4 */
error = setsockopt(s_wld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (error == -1)
- exit_error("setsockopt(SO_REUSEADDR): %s", ERRSTR);
+ exit_stderr("setsockopt(SO_REUSEADDR): %s", ERRSTR);
error = setsockopt(s_wld, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
if (error == -1)
- exit_error("setsockopt(SO_OOBINLINE): %s", ERRSTR);
+ exit_stderr("setsockopt(SO_OOBINLINE): %s", ERRSTR);
error = bind(s_wld, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
if (error == -1)
- exit_error("bind: %s", ERRSTR);
+ exit_stderr("bind: %s", ERRSTR);
error = listen(s_wld, 5);
if (error == -1)
- exit_error("listen: %s", ERRSTR);
+ exit_stderr("listen: %s", ERRSTR);
#ifdef USE_ROUTE
sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
if (sockfd < 0) {
- exit_error("socket(PF_ROUTE): %s", ERRSTR);
+ exit_stderr("socket(PF_ROUTE): %s", ERRSTR);
/*NOTREACHED*/
}
#endif
@@ -359,7 +384,7 @@ daemon_main(int argc, char **argv)
syslog(LOG_INFO, "Staring faith daemon for %s port", service);
play_service(s_wld);
- /*NOTREACHED*/
+ /* NOTREACHED */
exit(1); /*pacify gcc*/
}
@@ -407,8 +432,10 @@ again:
len = sizeof(srcaddr);
s_src = accept(s_wld, (struct sockaddr *)&srcaddr,
&len);
- if (s_src == -1)
+ if (s_src == -1) {
exit_failure("socket: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
child_pid = fork();
@@ -419,6 +446,7 @@ again:
openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
play_child(s_src, (struct sockaddr *)&srcaddr);
exit_failure("should never reach here");
+ /*NOTREACHED*/
} else {
/* parent process */
close(s_src);
@@ -441,6 +469,7 @@ play_child(int s_src, struct sockaddr *srcaddr)
int s_dst, error, hport, nresvport, on = 1;
struct timeval tv;
struct sockaddr *sa4;
+ const struct config *conf;
tv.tv_sec = 1;
tv.tv_usec = 0;
@@ -450,8 +479,10 @@ play_child(int s_src, struct sockaddr *srcaddr)
syslog(LOG_INFO, "accepted a client from %s", src);
error = getsockname(s_src, (struct sockaddr *)&dstaddr6, &len);
- if (error == -1)
+ if (error == -1) {
exit_failure("getsockname: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
getnameinfo((struct sockaddr *)&dstaddr6, len,
dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST);
@@ -487,7 +518,8 @@ play_child(int s_src, struct sockaddr *srcaddr)
if (!map6to4((struct sockaddr_in6 *)&dstaddr6,
(struct sockaddr_in *)&dstaddr4)) {
close(s_src);
- exit_error("map6to4 failed");
+ exit_failure("map6to4 failed");
+ /*NOTREACHED*/
}
syslog(LOG_INFO, "translating from v6 to v4");
break;
@@ -496,20 +528,35 @@ play_child(int s_src, struct sockaddr *srcaddr)
if (!map4to6((struct sockaddr_in *)&dstaddr6,
(struct sockaddr_in6 *)&dstaddr4)) {
close(s_src);
- exit_error("map4to6 failed");
+ exit_failure("map4to6 failed");
+ /*NOTREACHED*/
}
syslog(LOG_INFO, "translating from v4 to v6");
break;
#endif
default:
close(s_src);
- exit_error("family not supported");
+ exit_failure("family not supported");
/*NOTREACHED*/
}
sa4 = (struct sockaddr *)&dstaddr4;
getnameinfo(sa4, sa4->sa_len,
dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST);
+
+ conf = config_match(srcaddr, sa4);
+ if (!conf || !conf->permit) {
+ close(s_src);
+ if (conf) {
+ exit_failure("translation to %s not permitted for %s",
+ dst4, prefix_string(&conf->match));
+ /*NOTREACHED*/
+ } else {
+ exit_failure("translation to %s not permitted", dst4);
+ /*NOTREACHED*/
+ }
+ }
+
syslog(LOG_INFO, "the translator is connecting to %s", dst4);
setproctitle("port %s, %s -> %s", service, src, dst4);
@@ -531,31 +578,55 @@ play_child(int s_src, struct sockaddr *srcaddr)
s_dst = socket(sa4->sa_family, SOCK_STREAM, 0);
break;
}
- if (s_dst == -1)
+ if (s_dst < 0) {
exit_failure("socket: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
+
+ if (conf->src.a.ss_family) {
+ if (bind(s_dst, (struct sockaddr *)&conf->src.a,
+ conf->src.a.ss_len) < 0) {
+ exit_failure("bind: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
+ }
error = setsockopt(s_dst, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
- if (error == -1)
- exit_error("setsockopt(SO_OOBINLINE): %s", ERRSTR);
+ if (error < 0) {
+ exit_failure("setsockopt(SO_OOBINLINE): %s", ERRSTR);
+ /*NOTREACHED*/
+ }
error = setsockopt(s_src, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
- if (error == -1)
- exit_error("setsockopt(SO_SNDTIMEO): %s", ERRSTR);
+ if (error < 0) {
+ exit_failure("setsockopt(SO_SNDTIMEO): %s", ERRSTR);
+ /*NOTREACHED*/
+ }
error = setsockopt(s_dst, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
- if (error == -1)
- exit_error("setsockopt(SO_SNDTIMEO): %s", ERRSTR);
+ if (error < 0) {
+ exit_failure("setsockopt(SO_SNDTIMEO): %s", ERRSTR);
+ /*NOTREACHED*/
+ }
error = connect(s_dst, sa4, sa4->sa_len);
- if (error == -1)
+ if (error < 0) {
exit_failure("connect: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
switch (hport) {
case FTP_PORT:
ftp_relay(s_src, s_dst);
break;
case RSH_PORT:
+ syslog(LOG_WARNING,
+ "WARINNG: it is insecure to relay rsh port");
rsh_relay(s_src, s_dst);
break;
+ case RLOGIN_PORT:
+ syslog(LOG_WARNING,
+ "WARINNG: it is insecure to relay rlogin port");
+ /*FALLTHROUGH*/
default:
tcp_relay(s_src, s_dst, service);
break;
@@ -581,8 +652,10 @@ faith_prefix(struct sockaddr *dst)
mib[2] = IPPROTO_IPV6;
mib[3] = IPV6CTL_FAITH_PREFIX;
size = sizeof(struct in6_addr);
- if (sysctl(mib, 4, &faith_prefix, &size, NULL, 0) < 0)
- exit_error("sysctl: %s", ERRSTR);
+ if (sysctl(mib, 4, &faith_prefix, &size, NULL, 0) < 0) {
+ exit_failure("sysctl: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
if (memcmp(dst, &faith_prefix,
sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) {
@@ -649,7 +722,7 @@ map6to4(struct sockaddr_in6 *dst6, struct sockaddr_in *dst4)
if (dst4->sin_addr.s_addr == INADDR_ANY
|| dst4->sin_addr.s_addr == INADDR_BROADCAST
- || IN_MULTICAST(dst4->sin_addr.s_addr))
+ || IN_MULTICAST(ntohl(dst4->sin_addr.s_addr)))
return 0;
return 1;
@@ -695,7 +768,7 @@ sig_child(int sig)
pid_t pid;
pid = wait3(&status, WNOHANG, (struct rusage *)0);
- if (pid && status)
+ if (pid && WEXITSTATUS(status))
syslog(LOG_WARNING, "child %d exit status 0x%x", pid, status);
}
@@ -709,18 +782,34 @@ sig_terminate(int sig)
static void
start_daemon(void)
{
- if (daemon(0, 0) == -1)
- exit_error("daemon: %s", ERRSTR);
+#ifdef SA_NOCLDWAIT
+ struct sigaction sa;
+#endif
- if (signal(SIGCHLD, sig_child) == SIG_ERR)
+ if (daemon(0, 0) == -1)
+ exit_stderr("daemon: %s", ERRSTR);
+
+#ifdef SA_NOCLDWAIT
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = sig_child;
+ sa.sa_flags = SA_NOCLDWAIT;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGCHLD, &sa, (struct sigaction *)0);
+#else
+ if (signal(SIGCHLD, sig_child) == SIG_ERR) {
exit_failure("signal CHLD: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
+#endif
- if (signal(SIGTERM, sig_terminate) == SIG_ERR)
+ if (signal(SIGTERM, sig_terminate) == SIG_ERR) {
exit_failure("signal TERM: %s", ERRSTR);
+ /*NOTREACHED*/
+ }
}
-void
-exit_error(const char *fmt, ...)
+static void
+exit_stderr(const char *fmt, ...)
{
va_list ap;
char buf[BUFSIZ];
@@ -977,7 +1066,7 @@ update_myaddrs()
static void
usage()
{
- fprintf(stderr, "usage: %s [-dp] [service [serverpath [serverargs]]]\n",
+ fprintf(stderr, "usage: %s [-dp] [-f conf] service [serverpath [serverargs]]\n",
faithdname);
exit(0);
}
diff --git a/usr.sbin/faithd/faithd.h b/usr.sbin/faithd/faithd.h
index b882aad..8a5021b 100644
--- a/usr.sbin/faithd/faithd.h
+++ b/usr.sbin/faithd/faithd.h
@@ -1,4 +1,4 @@
-/* $KAME: faithd.h,v 1.2 2000/05/31 03:06:07 itojun Exp $ */
+/* $KAME: faithd.h,v 1.6 2000/10/05 22:20:37 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -40,12 +40,13 @@ extern int ftp_active __P((int, int, int *, int *));
extern int ftp_passive __P((int, int, int *, int *));
extern void rsh_relay __P((int, int));
extern void rsh_dual_relay __P((int, int));
-extern void exit_error __P((const char *fmt, ...));
-extern void exit_success __P((const char *fmt, ...));
-extern void exit_failure __P((const char *fmt, ...));
+extern void exit_success __P((const char *, ...))
+ __attribute__((__format__(__printf__, 1, 2)));
+extern void exit_failure __P((const char *, ...))
+ __attribute__((__format__(__printf__, 1, 2)));
#define DEFAULT_PORT_NAME "telnet"
-#define DEFAULT_DIR "/usr/local/v6/libexec"
+#define DEFAULT_DIR "/usr/libexec"
#define DEFAULT_NAME "telnetd"
#define DEFAULT_PATH (DEFAULT_DIR "/" DEFAULT_NAME)
diff --git a/usr.sbin/faithd/ftp.c b/usr.sbin/faithd/ftp.c
index e4838eb..b0daa5a 100644
--- a/usr.sbin/faithd/ftp.c
+++ b/usr.sbin/faithd/ftp.c
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: ftp.c,v 1.10 2000/09/14 00:23:39 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -514,7 +514,7 @@ passivefail:
error = setsockopt(wport6, IPPROTO_IPV6, IPV6_FAITH,
&on, sizeof(on));
if (error == -1)
- exit_error("setsockopt(IPV6_FAITH): %s", ERRSTR);
+ exit_failure("setsockopt(IPV6_FAITH): %s", ERRSTR);
}
#endif
error = bind(wport6, (struct sockaddr *)sin6, sin6->sin6_len);
@@ -924,6 +924,7 @@ eprtparamfail:
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(hostp, portp, &hints, &res);
if (error) {
n = snprintf(sbuf, sizeof(sbuf),
diff --git a/usr.sbin/faithd/prefix.c b/usr.sbin/faithd/prefix.c
new file mode 100644
index 0000000..739ae56
--- /dev/null
+++ b/usr.sbin/faithd/prefix.c
@@ -0,0 +1,360 @@
+/* $KAME: prefix.c,v 1.8 2000/11/24 06:16:56 itojun Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * 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 <netinet/in.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(u_long)(&((type *)0)->member))
+#endif
+
+#include "faithd.h"
+#include "prefix.h"
+
+static int prefix_set __P((const char *, struct prefix *, int));
+static struct config *config_load1 __P((const char *));
+#if 0
+static void config_show1 __P((const struct config *));
+static void config_show __P((void));
+#endif
+
+struct config *config_list = NULL;
+#ifdef NI_WITHSCOPEID
+const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
+#else
+const int niflags = NI_NUMERICHOST;
+#endif
+
+static int
+prefix_set(s, prefix, slash)
+ const char *s;
+ struct prefix *prefix;
+ int slash;
+{
+ char *p, *q, *r;
+ struct addrinfo hints, *res = NULL;
+ int max;
+ char *a;
+
+ p = strdup(s);
+ q = strchr(p, '/');
+ if (q) {
+ if (!slash)
+ goto fail;
+ *q++ = '\0';
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(p, "0", &hints, &res))
+ goto fail;
+ if (res->ai_next || res->ai_addrlen > sizeof(prefix->a))
+ goto fail;
+ memcpy(&prefix->a, res->ai_addr, res->ai_addrlen);
+
+ switch (prefix->a.ss_family) {
+ case AF_INET:
+ max = 32;
+ a = (char *)&((struct sockaddr_in *)&prefix->a)->sin_addr;
+ break;
+ case AF_INET6:
+ max = 128;
+ a = (char *)&((struct sockaddr_in6 *)&prefix->a)->sin6_addr;
+ break;
+ default:
+ a = NULL;
+ max = -1;
+ break;
+ }
+
+ if (q) {
+ r = NULL;
+ prefix->l = (int)strtoul(q, &r, 10);
+ if (!*q || *r)
+ goto fail;
+ if (prefix->l < 0 || prefix->l > max)
+ goto fail;
+ } else
+ prefix->l = max;
+
+ if (p)
+ free(p);
+ if (res)
+ freeaddrinfo(res);
+ return 0;
+
+fail:
+ if (p)
+ free(p);
+ if (res)
+ freeaddrinfo(res);
+ return -1;
+}
+
+const char *
+prefix_string(prefix)
+ const struct prefix *prefix;
+{
+ static char buf[NI_MAXHOST + 20];
+ char hbuf[NI_MAXHOST];
+
+ if (getnameinfo((struct sockaddr *)&prefix->a, prefix->a.ss_len, hbuf,
+ sizeof(hbuf), NULL, 0, niflags))
+ return NULL;
+ snprintf(buf, sizeof(buf), "%s/%d", hbuf, prefix->l);
+ return buf;
+}
+
+int
+prefix_match(prefix, sa)
+ const struct prefix *prefix;
+ const struct sockaddr *sa;
+{
+ struct sockaddr_storage a, b;
+ char *pa, *pb;
+ int off, l;
+
+ if (prefix->a.ss_family != sa->sa_family ||
+ prefix->a.ss_len != sa->sa_len)
+ return 0;
+
+ if (prefix->a.ss_len > sizeof(a) || sa->sa_len > sizeof(b))
+ return 0;
+
+ switch (prefix->a.ss_family) {
+ case AF_INET:
+ off = offsetof(struct sockaddr_in, sin_addr);
+ break;
+ case AF_INET6:
+ off = offsetof(struct sockaddr_in6, sin6_addr);
+ break;
+ default:
+ if (memcmp(&prefix->a, sa, prefix->a.ss_len) != 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ memcpy(&a, &prefix->a, prefix->a.ss_len);
+ memcpy(&b, sa, sa->sa_len);
+ l = prefix->l / 8 + (prefix->l % 8 ? 1 : 0);
+
+ /* overrun check */
+ if (off + l > a.ss_len)
+ return 0;
+
+ pa = ((char *)&a) + off;
+ pb = ((char *)&b) + off;
+ if (prefix->l % 8) {
+ pa[prefix->l / 8] &= 0xff00 >> (prefix->l % 8);
+ pb[prefix->l / 8] &= 0xff00 >> (prefix->l % 8);
+ }
+ if (memcmp(pa, pb, l) != 0)
+ return 0;
+ else
+ return 1;
+}
+
+/*
+ * prefix/prefixlen permit/deny prefix/prefixlen [srcaddr]
+ * 3ffe::/16 permit 10.0.0.0/8 10.1.1.1
+ */
+static struct config *
+config_load1(line)
+ const char *line;
+{
+ struct config *conf;
+ char buf[BUFSIZ];
+ char *p;
+ char *token[4];
+ int i;
+
+ if (strlen(line) + 1 > sizeof(buf))
+ return NULL;
+ strlcpy(buf, line, sizeof(buf));
+
+ p = strchr(buf, '\n');
+ if (!p)
+ return NULL;
+ *p = '\0';
+ p = strchr(buf, '#');
+ if (p)
+ *p = '\0';
+ if (strlen(buf) == 0)
+ return NULL;
+
+ p = buf;
+ memset(token, 0, sizeof(token));
+ for (i = 0; i < sizeof(token) / sizeof(token[0]); i++) {
+ token[i] = strtok(p, "\t ");
+ p = NULL;
+ if (token[i] == NULL)
+ break;
+ }
+ /* extra tokens? */
+ if (strtok(p, "\t ") != NULL)
+ return NULL;
+ /* insufficient tokens */
+ switch (i) {
+ case 3:
+ case 4:
+ break;
+ default:
+ return NULL;
+ }
+
+ conf = (struct config *)malloc(sizeof(*conf));
+ if (conf == NULL)
+ return NULL;
+ memset(conf, 0, sizeof(*conf));
+
+ if (strcasecmp(token[1], "permit") == 0)
+ conf->permit = 1;
+ else if (strcasecmp(token[1], "deny") == 0)
+ conf->permit = 0;
+ else {
+ /* invalid keyword is considered as "deny" */
+ conf->permit = 0;
+ }
+
+ if (prefix_set(token[0], &conf->match, 1) < 0)
+ goto fail;
+ if (prefix_set(token[2], &conf->dest, 1) < 0)
+ goto fail;
+ if (token[3]) {
+ if (prefix_set(token[3], &conf->src, 0) < 0)
+ goto fail;
+ }
+
+ return conf;
+
+fail:
+ free(conf);
+ return NULL;
+}
+
+int
+config_load(configfile)
+ const char *configfile;
+{
+ FILE *fp;
+ char buf[BUFSIZ];
+ struct config *conf, *p;
+ struct config sentinel;
+
+ config_list = NULL;
+
+ if (!configfile)
+ configfile = _PATH_PREFIX_CONF;
+ fp = fopen(configfile, "r");
+ if (fp == NULL)
+ return -1;
+
+ p = &sentinel;
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ conf = config_load1(buf);
+ if (conf) {
+ p->next = conf;
+ p = p->next;
+ }
+ }
+ config_list = sentinel.next;
+
+ fclose(fp);
+ return 0;
+}
+
+#if 0
+static void
+config_show1(conf)
+ const struct config *conf;
+{
+ const char *p;
+
+ p = prefix_string(&conf->match);
+ printf("%s", p ? p : "?");
+
+ if (conf->permit)
+ printf(" permit");
+ else
+ printf(" deny");
+
+ p = prefix_string(&conf->dest);
+ printf(" %s", p ? p : "?");
+
+ printf("\n");
+}
+
+static void
+config_show()
+{
+ struct config *conf;
+
+ for (conf = config_list; conf; conf = conf->next)
+ config_show1(conf);
+}
+#endif
+
+const struct config *
+config_match(sa1, sa2)
+ struct sockaddr *sa1, *sa2;
+{
+ static struct config conf;
+ const struct config *p;
+
+ if (sa1->sa_len > sizeof(conf.match.a) ||
+ sa2->sa_len > sizeof(conf.dest.a))
+ return NULL;
+
+ memset(&conf, 0, sizeof(conf));
+ if (!config_list) {
+ conf.permit = 1;
+ memcpy(&conf.match.a, sa1, sa1->sa_len);
+ memcpy(&conf.dest.a, sa2, sa2->sa_len);
+ return &conf;
+ }
+
+ for (p = config_list; p; p = p->next)
+ if (prefix_match(&p->match, sa1) && prefix_match(&p->dest, sa2))
+ return p;
+
+ return NULL;
+}
diff --git a/usr.sbin/faithd/prefix.h b/usr.sbin/faithd/prefix.h
new file mode 100644
index 0000000..3ef56e3
--- /dev/null
+++ b/usr.sbin/faithd/prefix.h
@@ -0,0 +1,52 @@
+/* $KAME: prefix.h,v 1.3 2000/11/19 11:45:38 itojun Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * 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.
+ */
+
+struct prefix {
+ struct sockaddr_storage a;
+ int l;
+};
+
+struct config {
+ struct config *next;
+
+ int permit;
+ struct prefix match;
+ struct prefix dest;
+ struct prefix src; /* src to use for outgoing connection */
+};
+
+#define _PATH_PREFIX_CONF "/etc/faithd.conf"
+
+extern const char *prefix_string __P((const struct prefix *));
+extern int prefix_match __P((const struct prefix *, const struct sockaddr *));
+extern int config_load __P((const char *));
+extern const struct config *config_match __P((struct sockaddr *, struct sockaddr *));
diff --git a/usr.sbin/faithd/rsh.c b/usr.sbin/faithd/rsh.c
index 6d81147..4e11d76 100644
--- a/usr.sbin/faithd/rsh.c
+++ b/usr.sbin/faithd/rsh.c
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: rsh.c,v 1.5 2001/02/15 17:28:04 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
diff --git a/usr.sbin/faithd/tcp.c b/usr.sbin/faithd/tcp.c
index 004686f..c754dfc 100644
--- a/usr.sbin/faithd/tcp.c
+++ b/usr.sbin/faithd/tcp.c
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: tcp.c,v 1.5 2000/09/29 03:48:31 sakane Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -93,9 +93,9 @@ sig_child(int sig)
pid_t pid;
pid = wait3(&status, WNOHANG, (struct rusage *)0);
- if (pid && status)
+ if (pid && WEXITSTATUS(status))
syslog(LOG_WARNING, "child %d exit status 0x%x", pid, status);
- exit_failure("terminate connection due to child termination");
+ exit_success("terminate connection due to child termination");
}
static void
@@ -195,7 +195,8 @@ relay(int s_rcv, int s_snd, const char *service, int direction)
FD_ZERO(&exceptfds);
fcntl(s_snd, F_SETFD, O_NONBLOCK);
oreadfds = readfds; owritefds = writefds; oexceptfds = exceptfds;
- FD_SET(s_rcv, &readfds); FD_SET(s_rcv, &exceptfds);
+ FD_SET(s_rcv, &readfds);
+ FD_SET(s_rcv, &exceptfds);
oob_exists = 0;
maxfd = (s_rcv > s_snd) ? s_rcv : s_snd;
diff --git a/usr.sbin/gifconfig/gifconfig.8 b/usr.sbin/gifconfig/gifconfig.8
index c851624..26b4dd6 100644
--- a/usr.sbin/gifconfig/gifconfig.8
+++ b/usr.sbin/gifconfig/gifconfig.8
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.\" $KAME: gifconfig.8,v 1.5 2000/05/13 07:48:10 itojun Exp $
+.\" $KAME: gifconfig.8,v 1.6 2000/11/22 11:10:09 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -34,6 +34,7 @@
.Sh NAME
.Nm gifconfig
.Nd configure generic IP tunnel
+.\"
.Sh SYNOPSIS
.Nm
.Ar interface
@@ -60,7 +61,7 @@ specifies the address family for
.Ar physsrc
and
.Ar physdest .
-.Ar Af
+.Ar af
can be
.Li inet
or
@@ -81,7 +82,9 @@ If no outer addresses are specified, this usage has no effect.
takes the following optional argument:
.Bl -tag -width Ds
.It Fl a
-Display information associated all generic IP tunnel interfaces.
+Display information associated with all
+.Xr gif 4
+interfaces.
.El
.Pp
Please note that it is very easy to create infinite routing loop,
diff --git a/usr.sbin/gifconfig/gifconfig.c b/usr.sbin/gifconfig/gifconfig.c
index d93d741..ac876dc 100644
--- a/usr.sbin/gifconfig/gifconfig.c
+++ b/usr.sbin/gifconfig/gifconfig.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: gifconfig.c,v 1.12 2000/05/22 05:50:43 itojun Exp $ */
+/* $KAME: gifconfig.c,v 1.14 2001/01/01 04:04:56 jinmei Exp $ */
/*
* Copyright (c) 1983, 1993
@@ -111,7 +111,7 @@ void delifaddrs __P((char *, int));
#define NEXTARG 0xffffff
-struct cmd {
+static struct cmd {
char *c_name;
int c_parameter; /* NEXTARG means next argv */
void (*c_func) __P((char *, int));
@@ -565,10 +565,11 @@ phys_status(force)
char psrcaddr[256];
char pdstaddr[256];
char hostname[NI_MAXHOST];
- u_long srccmd, dstcmd;
int flags = NI_NUMERICHOST;
+ char *af;
+#ifndef SIOCGLIFPHYADDR
+ u_long srccmd, dstcmd;
struct ifreq *ifrp;
- char *ver = "";
#ifdef INET6
int s6;
#endif
@@ -596,20 +597,55 @@ phys_status(force)
#endif /* INET6 */
if (0 <= ioctl(s, srccmd, (caddr_t)ifrp)) {
- getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
- hostname, sizeof(hostname), 0, 0, flags);
#ifdef INET6
if (ifrp->ifr_addr.sa_family == AF_INET6)
- ver = "6";
+ af = "inet6";
+ else
+ af = "inet";
+#else
+ af = "inet";
#endif /* INET6 */
- sprintf(psrcaddr, "inet%s %s", ver, hostname);
+ if (getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
+ psrcaddr, sizeof(psrcaddr), 0, 0, flags) != 0)
+ psrcaddr[0] = '\0';
}
if (0 <= ioctl(s, dstcmd, (caddr_t)ifrp)) {
- getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
- hostname, sizeof(hostname), 0, 0, flags);
- sprintf(pdstaddr, "%s", hostname);
+ if (getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
+ pdstaddr, sizeof(pdstaddr), 0, 0, flags) != 0)
+ pdstaddr[0] = '\0';
+ }
+ printf("\tphysical address %s %s --> %s\n", af, psrcaddr, pdstaddr);
+#else
+ struct if_laddrreq iflr;
+
+ force = 0; /*fool gcc*/
+
+ psrcaddr[0] = pdstaddr[0] = '\0';
+
+ memset(&iflr, 0, sizeof(iflr));
+ memcpy(iflr.iflr_name, ifr.ifr_name, sizeof(iflr.iflr_name));
+
+ if (0 <= ioctl(s, SIOCGLIFPHYADDR, (caddr_t)&iflr)) {
+ switch (iflr.addr.ss_family) {
+ case AF_INET:
+ af = "inet";
+ break;
+#ifdef INET6
+ case AF_INET6:
+ af = "inet6";
+ break;
+#endif /* INET6 */
+ }
+ if (getnameinfo((struct sockaddr *)&iflr.addr, iflr.addr.ss_len,
+ psrcaddr, sizeof(psrcaddr), 0, 0, flags) != 0)
+ psrcaddr[0] = '\0';
+ if (getnameinfo((struct sockaddr *)&iflr.dstaddr,
+ iflr.dstaddr.ss_len, pdstaddr, sizeof(pdstaddr), 0, 0,
+ flags) != 0)
+ pdstaddr[0] = '\0';
}
- printf("\tphysical address %s --> %s\n", psrcaddr, pdstaddr);
+ printf("\tphysical address %s %s --> %s\n", af, psrcaddr, pdstaddr);
+#endif
}
void
diff --git a/usr.sbin/ifmcstat/ifmcstat.8 b/usr.sbin/ifmcstat/ifmcstat.8
index 816da4b..bcb5bdd 100644
--- a/usr.sbin/ifmcstat/ifmcstat.8
+++ b/usr.sbin/ifmcstat/ifmcstat.8
@@ -1,16 +1,31 @@
-.\" Copyright (c) 1996 WIDE Project. All rights reserved.
+.\" $KAME: ifmcstat.8,v 1.3 2000/10/15 11:43:57 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
-.\" modifications, are permitted provided that the above copyright notice
-.\" and this paragraph are duplicated in all such forms and that any
-.\" documentation, advertising materials, and other materials related to
-.\" such distribution and use acknowledge that the software was developed
-.\" by the WIDE Project, Japan. The name of the Project may not be used to
-.\" endorse or promote products derived from this software without
-.\" specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
-.\" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
-.\" LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-.\" A PARTICULAR PURPOSE.
+.\" 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.
.\"
.\" $FreeBSD$
.\"
@@ -29,6 +44,3 @@ The
command dumps multicast group information in the kernel.
.Pp
There are no command-line options.
-.\"
-.\" .Sh SEE ALSO
-.\" RFC2080 -- IPng for IPv6. G. Malkin, R. Minnear. January 1997.
diff --git a/usr.sbin/ifmcstat/ifmcstat.c b/usr.sbin/ifmcstat/ifmcstat.c
index e26db45..68cad62 100644
--- a/usr.sbin/ifmcstat/ifmcstat.c
+++ b/usr.sbin/ifmcstat/ifmcstat.c
@@ -39,6 +39,8 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/queue.h>
+
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_types.h>
@@ -234,6 +236,10 @@ if6_addrlist(ifap)
KREAD(ifap0, &ifa, struct ifaddr);
nam = strdup(ifname(ifa.ifa_ifp));
+ if (!nam) {
+ fprintf(stderr, "ifmcstat: not enough core\n");
+ exit(1);
+ }
LIST_FOREACH(mkp, &in6_mk, mk_entry) {
KREAD(mkp, &mk, struct multi6_kludge);
diff --git a/usr.sbin/mld6query/mld6.c b/usr.sbin/mld6query/mld6.c
index 473e0f4..9b0b30a 100644
--- a/usr.sbin/mld6query/mld6.c
+++ b/usr.sbin/mld6query/mld6.c
@@ -1,3 +1,6 @@
+/* $KAME: mld6.c,v 1.11 2001/05/13 15:45:07 suz Exp $ */
+/* $FreeBSD$ */
+
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
@@ -75,7 +78,7 @@ main(int argc, char *argv[])
int ch;
type = MLD6_LISTENER_QUERY;
- while ((ch = getopt(argc, argv, "d")) != EOF) {
+ while ((ch = getopt(argc, argv, "dr")) != -1) {
switch (ch) {
case 'd':
type = MLD6_LISTENER_DONE;
@@ -98,7 +101,7 @@ main(int argc, char *argv[])
ifindex = (u_short)if_nametoindex(argv[0]);
if (ifindex == 0)
usage();
- if (argc == 3 && inet_pton(AF_INET6, argv[1], &maddr) != 1)
+ if (argc == 2 && inet_pton(AF_INET6, argv[1], &maddr) != 1)
usage();
if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
@@ -188,7 +191,7 @@ make_msg(int index, struct in6_addr *addr, u_int type)
m.msg_control = (caddr_t)cmsgbuf;
m.msg_controllen = cmsglen;
/* specify the outgoing interface */
- cmsgp->cmsg_len = CMSG_SPACE(sizeof(struct in6_pktinfo));
+ cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmsgp->cmsg_level = IPPROTO_IPV6;
cmsgp->cmsg_type = IPV6_PKTINFO;
pi = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
diff --git a/usr.sbin/mld6query/mld6query.8 b/usr.sbin/mld6query/mld6query.8
index 470e18a..4b7bf9c 100644
--- a/usr.sbin/mld6query/mld6query.8
+++ b/usr.sbin/mld6query/mld6query.8
@@ -1,3 +1,5 @@
+.\" $KAME: mld6query.8,v 1.5 2000/12/04 06:28:23 itojun Exp $
+.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
.\"
@@ -25,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $Id: mld6query.8,v 1.3 1999/08/20 10:00:06 itojun Exp $
+.\" $FreeBSD$
.\"
.Dd May 17, 1998
.Dt MLD6QUERY 8
diff --git a/usr.sbin/ndp/ndp.8 b/usr.sbin/ndp/ndp.8
index e2eae63..9ea9660 100644
--- a/usr.sbin/ndp/ndp.8
+++ b/usr.sbin/ndp/ndp.8
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.\" $KAME: ndp.8,v 1.12 2000/06/20 21:50:17 itojun Exp $
+.\" $KAME: ndp.8,v 1.15 2001/02/08 07:17:03 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -30,7 +30,7 @@
.\"
.Dd May 17, 1998
.Dt NDP 8
-.Os KAME
+.Os
.\"
.Sh NAME
.Nm ndp
@@ -39,10 +39,10 @@
.Sh SYNOPSIS
.Nm
.Fl a
-.Op Fl ntl
+.Op Fl nt
.Nm
.Fl A Ar wait
-.Op Fl ntl
+.Op Fl nt
.Nm
.Fl c
.Op Fl nt
@@ -106,7 +106,8 @@ Harmonize consistency between the routing table and the default router
list; install the top entry of the list into the kernel routing table.
.It Fl I Op Cm delete | Ar interface
Shows or specifies the default interface used as the default route when
-there is no default router. If no argument is given to the option,
+there is no default router.
+If no argument is given to the option,
the current default interface will be shown.
If an
.Ar interface
@@ -121,7 +122,8 @@ If additional arguments
are given,
.Nm
sets or clears the specified flags for the interface.
-Possible flags are as follows. All of the flags can begin with the
+Possible flags are as follows.
+All of the flags can begin with the
special character
.Ql - ,
which means the flag should be cleared.
@@ -131,10 +133,9 @@ which means the flag should be cleared.
.Ic nud
.Xc
turn on or off NUD (Neighbor Unreachability Detection) on the
-interface. NUD is usually turned on by default.
+interface.
+NUD is usually turned on by default.
.El
-.It Fl l
-Do not truncate numeric IPv6 address.
.It Fl n
Do not try to resolve numeric address to hostname.
.It Fl p
@@ -146,7 +147,7 @@ Show default router list.
.It Fl R
Flush all the entries in the default router list.
.It Fl s
-Register a NDP entry for a node.
+Register an NDP entry for a node.
The entry will be permanent unless the word
.Li temp
is given in the command.
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c
index a01886a..d1e74a2 100644
--- a/usr.sbin/ndp/ndp.c
+++ b/usr.sbin/ndp/ndp.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: ndp.c,v 1.46 2000/10/09 09:17:10 sumikawa Exp $ */
+/* $KAME: ndp.c,v 1.65 2001/05/08 04:36:34 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -84,6 +84,7 @@
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/time.h>
+#include <sys/queue.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -128,7 +129,6 @@ static int tflag;
static int32_t thiszone; /* time difference with gmt */
static int s = -1;
static int repeat = 0;
-static int lflag = 0;
char ntop_buf[INET6_ADDRSTRLEN]; /* inet_ntop() */
char host_buf[NI_MAXHOST]; /* getnameinfo() */
@@ -162,6 +162,13 @@ static char *sec2str __P((time_t t));
static char *ether_str __P((struct sockaddr_dl *sdl));
static void ts_print __P((const struct timeval *));
+static char *rtpref_str[] = {
+ "medium", /* 00 */
+ "high", /* 01 */
+ "rsv", /* 10 */
+ "low" /* 11 */
+};
+
int
main(argc, argv)
int argc;
@@ -173,7 +180,7 @@ main(argc, argv)
pid = getpid();
thiszone = gmt2local(0);
- while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != EOF)
+ while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != -1)
switch ((char)ch) {
case 'a':
aflag = 1;
@@ -213,7 +220,7 @@ main(argc, argv)
file(argv[2]);
exit(0);
case 'l' :
- lflag = 1;
+ /* obsolete, ignored */
break;
case 'r' :
rflag = 1;
@@ -504,11 +511,7 @@ delete(host)
if (sdl->sdl_family == AF_LINK &&
(rtm->rtm_flags & RTF_LLINFO) &&
!(rtm->rtm_flags & RTF_GATEWAY)) {
- switch (sdl->sdl_type) {
- case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
- case IFT_ISO88024: case IFT_ISO88025:
- goto delete;
- }
+ goto delete;
}
/*
* IPv4 arp command retries with sin_other = SIN_PROXY here.
@@ -541,6 +544,10 @@ delete:
return 0;
}
+#define W_ADDR 31
+#define W_LL 17
+#define W_IF 6
+
/*
* Dump the entire neighbor cache
*/
@@ -558,13 +565,16 @@ dump(addr)
struct in6_nbrinfo *nbi;
struct timeval time;
int addrwidth;
+ int llwidth;
+ int ifwidth;
char flgbuf[8];
+ char *ifname;
/* Print header */
if (!tflag && !cflag)
- printf("%-31.31s %-17.17s %6.6s %-9.9s %2s %4s %4s\n",
- "Neighbor", "Linklayer Address", "Netif", "Expire",
- "St", "Flgs", "Prbs");
+ printf("%-*.*s %-*.*s %*.*s %-9.9s %2s %4s %4s\n",
+ W_ADDR, W_ADDR, "Neighbor", W_LL, W_LL, "Linklayer Address",
+ W_IF, W_IF, "Netif", "Expire", "St", "Flgs", "Prbs");
again:;
mib[0] = CTL_NET;
@@ -590,6 +600,23 @@ again:;
rtm = (struct rt_msghdr *)next;
sin = (struct sockaddr_in6 *)(rtm + 1);
sdl = (struct sockaddr_dl *)((char *)sin + ROUNDUP(sin->sin6_len));
+
+ /*
+ * Some OSes can produce a route that has the LINK flag but
+ * has a non-AF_LINK gateway (e.g. fe80::xx%lo0 on FreeBSD
+ * and BSD/OS, where xx is not the interface identifier on
+ * lo0). Such routes entry would annoy getnbrinfo() below,
+ * so we skip them.
+ * XXX: such routes should have the GATEWAY flag, not the
+ * LINK flag. However, there are rotten routing software
+ * that advertises all routes that have the GATEWAY flag.
+ * Thus, KAME kernel intentionally does not set the LINK flag.
+ * What is to be fixed is not ndp, but such routing software
+ * (and the kernel workaround)...
+ */
+ if (sdl->sdl_family != AF_LINK)
+ continue;
+
if (addr) {
if (!IN6_ARE_ADDR_EQUAL(addr, &sin->sin6_addr))
continue;
@@ -617,16 +644,21 @@ again:;
if (tflag)
ts_print(&time);
- if (lflag) {
- addrwidth = strlen(host_buf);
- if (addrwidth < 31)
- addrwidth = 31;
- } else
- addrwidth = 31;
-
- printf("%-*.*s %-17.17s %6.6s", addrwidth, addrwidth, host_buf,
- ether_str(sdl),
- if_indextoname(sdl->sdl_index, ifix_buf));
+ addrwidth = strlen(host_buf);
+ if (addrwidth < W_ADDR)
+ addrwidth = W_ADDR;
+ llwidth = strlen(ether_str(sdl));
+ if (W_ADDR + W_LL - addrwidth > llwidth)
+ llwidth = W_ADDR + W_LL - addrwidth;
+ ifname = if_indextoname(sdl->sdl_index, ifix_buf);
+ if (!ifname)
+ ifname = "?";
+ ifwidth = strlen(ifname);
+ if (W_ADDR + W_LL + W_IF - addrwidth - llwidth > ifwidth)
+ ifwidth = W_ADDR + W_LL + W_IF - addrwidth - llwidth;
+
+ printf("%-*.*s %-*.*s %*.*s", addrwidth, addrwidth, host_buf,
+ llwidth, llwidth, ether_str(sdl), ifwidth, ifwidth, ifname);
/* Print neighbor discovery specific informations */
nbi = getnbrinfo(&sin->sin6_addr, sdl->sdl_index, 1);
@@ -634,8 +666,7 @@ again:;
if (nbi->expire > time.tv_sec) {
printf(" %-9.9s",
sec2str(nbi->expire - time.tv_sec));
- }
- else if (nbi->expire == 0)
+ } else if (nbi->expire == 0)
printf(" %-9.9s", "permanent");
else
printf(" %-9.9s", "expired");
@@ -644,9 +675,11 @@ again:;
case ND6_LLINFO_NOSTATE:
printf(" N");
break;
+#ifdef ND6_LLINFO_WAITDELETE
case ND6_LLINFO_WAITDELETE:
printf(" W");
break;
+#endif
case ND6_LLINFO_INCOMPLETE:
printf(" I");
break;
@@ -669,8 +702,7 @@ again:;
isrouter = nbi->isrouter;
prbs = nbi->asked;
- }
- else {
+ } else {
warnx("failed to get neighbor information");
printf(" ");
}
@@ -701,6 +733,8 @@ again:;
printf("\n");
}
+ if (buf != NULL)
+ free(buf);
if (repeat) {
printf("\n");
@@ -746,8 +780,7 @@ ether_str(sdl)
cp = (u_char *)LLADDR(sdl);
sprintf(ebuf, "%x:%x:%x:%x:%x:%x",
cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
- }
- else {
+ } else {
sprintf(ebuf, "(incomplete)");
}
@@ -776,8 +809,8 @@ void
usage()
{
printf("usage: ndp hostname\n");
- printf(" ndp -a[ntl]\n");
- printf(" ndp [-ntl] -A wait\n");
+ printf(" ndp -a[nt]\n");
+ printf(" ndp [-nt] -A wait\n");
printf(" ndp -c[nt]\n");
printf(" ndp -d[nt] hostname\n");
printf(" ndp -f[nt] filename\n");
@@ -866,6 +899,9 @@ ifinfo(argc, argv)
int i, s;
char *ifname = argv[0];
u_int32_t newflags;
+#ifdef IPV6CTL_USETEMPADDR
+ u_int8_t nullbuf[8];
+#endif
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
perror("ndp: socket");
@@ -913,6 +949,32 @@ ifinfo(argc, argv)
ND.basereachable / 1000, ND.basereachable % 1000);
printf(", reachable=%ds", ND.reachable);
printf(", retrans=%ds%dms", ND.retrans / 1000, ND.retrans % 1000);
+#ifdef IPV6CTL_USETEMPADDR
+ memset(nullbuf, 0, sizeof(nullbuf));
+ if (memcmp(nullbuf, ND.randomid, sizeof(nullbuf)) != 0) {
+ int j;
+ u_int8_t *rbuf;
+
+ for (i = 0; i < 3; i++) {
+ switch(i) {
+ case 0:
+ printf("\nRandom seed(0): ");
+ rbuf = ND.randomseed0;
+ break;
+ case 1:
+ printf("\nRandom seed(1): ");
+ rbuf = ND.randomseed1;
+ break;
+ case 2:
+ printf("\nRandom ID: ");
+ rbuf = ND.randomid;
+ break;
+ }
+ for (j = 0; j < 8; j++)
+ printf("%02x", rbuf[j]);
+ }
+ }
+#endif
if (ND.flags) {
printf("\nFlags: ");
if ((ND.flags & ND6_IFF_PERFORMNUD) != 0)
@@ -924,9 +986,60 @@ ifinfo(argc, argv)
close(s);
}
+#ifndef ND_RA_FLAG_RTPREF_MASK /* XXX: just for compilation on *BSD release */
+#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
+#endif
+
void
rtrlist()
{
+#ifdef ICMPV6CTL_ND6_DRLIST
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_DRLIST };
+ char *buf;
+ struct in6_defrouter *p, *ep;
+ size_t l;
+ struct timeval time;
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) {
+ err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)");
+ /*NOTREACHED*/
+ }
+ buf = malloc(l);
+ if (!buf) {
+ errx(1, "not enough core");
+ /*NOTREACHED*/
+ }
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
+ err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)");
+ /*NOTREACHED*/
+ }
+
+ ep = (struct in6_defrouter *)(buf + l);
+ for (p = (struct in6_defrouter *)buf; p < ep; p++) {
+ int rtpref;
+
+ if (getnameinfo((struct sockaddr *)&p->rtaddr,
+ p->rtaddr.sin6_len, host_buf, sizeof(host_buf), NULL, 0,
+ NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0)) != 0)
+ strlcpy(host_buf, "?", sizeof(host_buf));
+
+ printf("%s if=%s", host_buf,
+ if_indextoname(p->if_index, ifix_buf));
+ printf(", flags=%s%s",
+ p->flags & ND_RA_FLAG_MANAGED ? "M" : "",
+ p->flags & ND_RA_FLAG_OTHER ? "O" : "");
+ rtpref = ((p->flags & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff;
+ printf(", pref=%s", rtpref_str[rtpref]);
+
+ gettimeofday(&time, 0);
+ if (p->expire == 0)
+ printf(", expire=Never\n");
+ else
+ printf(", expire=%s\n",
+ sec2str(p->expire - time.tv_sec));
+ }
+ free(buf);
+#else
struct in6_drlist dr;
int s, i;
struct timeval time;
@@ -942,7 +1055,7 @@ rtrlist()
exit(1);
}
#define DR dr.defrouter[i]
- for (i = 0 ; DR.if_index && i < PRLSTSIZ ; i++) {
+ for (i = 0 ; DR.if_index && i < DRLSTSIZ ; i++) {
struct sockaddr_in6 sin6;
bzero(&sin6, sizeof(sin6));
@@ -967,11 +1080,128 @@ rtrlist()
}
#undef DR
close(s);
+#endif
}
void
plist()
{
+#ifdef ICMPV6CTL_ND6_PRLIST
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_PRLIST };
+ char *buf;
+ struct in6_prefix *p, *ep, *n;
+ struct sockaddr_in6 *advrtr;
+ size_t l;
+ struct timeval time;
+#ifdef NI_WITHSCOPEID
+ const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
+ int ninflags = (nflag ? NI_NUMERICHOST : 0) | NI_WITHSCOPEID;
+#else
+ const int niflags = NI_NUMERICHOST;
+ int ninflags = nflag ? NI_NUMERICHOST : 0;
+#endif
+ char namebuf[NI_MAXHOST];
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) {
+ err(1, "sysctl(ICMPV6CTL_ND6_PRLIST)");
+ /*NOTREACHED*/
+ }
+ buf = malloc(l);
+ if (!buf) {
+ errx(1, "not enough core");
+ /*NOTREACHED*/
+ }
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
+ err(1, "sysctl(ICMPV6CTL_ND6_PRLIST)");
+ /*NOTREACHED*/
+ }
+
+ ep = (struct in6_prefix *)(buf + l);
+ for (p = (struct in6_prefix *)buf; p < ep; p = n) {
+ advrtr = (struct sockaddr_in6 *)(p + 1);
+ n = (struct in6_prefix *)&advrtr[p->advrtrs];
+
+ if (getnameinfo((struct sockaddr *)&p->prefix,
+ p->prefix.sin6_len, namebuf, sizeof(namebuf),
+ NULL, 0, niflags) != 0)
+ strlcpy(namebuf, "?", sizeof(namebuf));
+ printf("%s/%d if=%s\n", namebuf, p->prefixlen,
+ if_indextoname(p->if_index, ifix_buf));
+
+ gettimeofday(&time, 0);
+ /*
+ * meaning of fields, especially flags, is very different
+ * by origin. notify the difference to the users.
+ */
+ printf("flags=%s%s%s%s%s",
+ p->raflags.onlink ? "L" : "",
+ p->raflags.autonomous ? "A" : "",
+ (p->flags & NDPRF_ONLINK) != 0 ? "O" : "",
+ (p->flags & NDPRF_DETACHED) != 0 ? "D" : "",
+#ifdef NDPRF_HOME
+ (p->flags & NDPRF_HOME) != 0 ? "H" : ""
+#else
+ ""
+#endif
+ );
+ if (p->vltime == ND6_INFINITE_LIFETIME)
+ printf(" vltime=infinity");
+ else
+ printf(" vltime=%ld", (long)p->vltime);
+ if (p->pltime == ND6_INFINITE_LIFETIME)
+ printf(", pltime=infinity");
+ else
+ printf(", pltime=%ld", (long)p->pltime);
+ if (p->expire == 0)
+ printf(", expire=Never");
+ else if (p->expire >= time.tv_sec)
+ printf(", expire=%s",
+ sec2str(p->expire - time.tv_sec));
+ else
+ printf(", expired");
+ printf(", ref=%d", p->refcnt);
+ printf("\n");
+ /*
+ * "advertising router" list is meaningful only if the prefix
+ * information is from RA.
+ */
+ if (p->advrtrs) {
+ int j;
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)(p + 1);
+ printf(" advertised by\n");
+ for (j = 0; j < p->advrtrs; j++) {
+ struct in6_nbrinfo *nbi;
+
+ if (getnameinfo((struct sockaddr *)sin6,
+ sin6->sin6_len, namebuf, sizeof(namebuf),
+ NULL, 0, ninflags) != 0)
+ strlcpy(namebuf, "?", sizeof(namebuf));
+ printf(" %s", namebuf);
+
+ nbi = getnbrinfo(&sin6->sin6_addr, p->if_index,
+ 0);
+ if (nbi) {
+ switch(nbi->state) {
+ case ND6_LLINFO_REACHABLE:
+ case ND6_LLINFO_STALE:
+ case ND6_LLINFO_DELAY:
+ case ND6_LLINFO_PROBE:
+ printf(" (reachable)\n");
+ break;
+ default:
+ printf(" (unreachable)\n");
+ }
+ } else
+ printf(" (no neighbor state)\n");
+ sin6++;
+ }
+ } else
+ printf(" No advertising router\n");
+ }
+ free(buf);
+#else
struct in6_prlist pr;
int s, i;
struct timeval time;
@@ -990,19 +1220,73 @@ plist()
}
#define PR pr.prefix[i]
for (i = 0; PR.if_index && i < PRLSTSIZ ; i++) {
- printf("%s/%d if=%s\n",
- inet_ntop(AF_INET6, &PR.prefix, ntop_buf,
- sizeof(ntop_buf)), PR.prefixlen,
+ struct sockaddr_in6 p6;
+ char namebuf[NI_MAXHOST];
+ int niflags;
+
+#ifdef NDPRF_ONLINK
+ p6 = PR.prefix;
+#else
+ memset(&p6, 0, sizeof(p6));
+ p6.sin6_family = AF_INET6;
+ p6.sin6_len = sizeof(p6);
+ p6.sin6_addr = PR.prefix;
+#endif
+
+ /*
+ * copy link index to sin6_scope_id field.
+ * XXX: KAME specific.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&p6.sin6_addr)) {
+ u_int16_t linkid;
+
+ memcpy(&linkid, &p6.sin6_addr.s6_addr[2],
+ sizeof(linkid));
+ linkid = ntohs(linkid);
+ p6.sin6_scope_id = linkid;
+ p6.sin6_addr.s6_addr[2] = 0;
+ p6.sin6_addr.s6_addr[3] = 0;
+ }
+
+ niflags = NI_NUMERICHOST;
+#ifdef __KAME__
+ niflags |= NI_WITHSCOPEID;
+#endif
+ if (getnameinfo((struct sockaddr *)&p6,
+ sizeof(p6), namebuf, sizeof(namebuf),
+ NULL, 0, niflags)) {
+ warnx("getnameinfo failed");
+ continue;
+ }
+ printf("%s/%d if=%s\n", namebuf, PR.prefixlen,
if_indextoname(PR.if_index, ifix_buf));
+
gettimeofday(&time, 0);
/*
* meaning of fields, especially flags, is very different
* by origin. notify the difference to the users.
*/
- printf(" %s", PR.origin == PR_ORIG_RA ? "" : "advertise: ");
+#if 0
+ printf(" %s",
+ PR.origin == PR_ORIG_RA ? "" : "advertise: ");
+#endif
+#ifdef NDPRF_ONLINK
+ printf("flags=%s%s%s%s%s",
+ PR.raflags.onlink ? "L" : "",
+ PR.raflags.autonomous ? "A" : "",
+ (PR.flags & NDPRF_ONLINK) != 0 ? "O" : "",
+ (PR.flags & NDPRF_DETACHED) != 0 ? "D" : "",
+#ifdef NDPRF_HOME
+ (PR.flags & NDPRF_HOME) != 0 ? "H" : ""
+#else
+ ""
+#endif
+ );
+#else
printf("flags=%s%s",
PR.raflags.onlink ? "L" : "",
PR.raflags.autonomous ? "A" : "");
+#endif
if (PR.vltime == ND6_INFINITE_LIFETIME)
printf(" vltime=infinity");
else
@@ -1018,6 +1302,10 @@ plist()
sec2str(PR.expire - time.tv_sec));
else
printf(", expired");
+#ifdef NDPRF_ONLINK
+ printf(", ref=%d", PR.refcnt);
+#endif
+#if 0
switch (PR.origin) {
case PR_ORIG_RA:
printf(", origin=RA");
@@ -1035,12 +1323,14 @@ plist()
printf(", origin=?");
break;
}
+#endif
printf("\n");
/*
* "advertising router" list is meaningful only if the prefix
* information is from RA.
*/
- if (PR.origin != PR_ORIG_RA)
+ if (0 && /* prefix origin is almost obsolted */
+ PR.origin != PR_ORIG_RA)
;
else if (PR.advrtrs) {
int j;
@@ -1073,8 +1363,7 @@ plist()
default:
printf(" (unreachable)\n");
}
- }
- else
+ } else
printf(" (no neighbor state)\n");
}
if (PR.advrtrs > DRLSTSIZ)
@@ -1085,6 +1374,7 @@ plist()
}
#undef PR
close(s);
+#endif
}
void
diff --git a/usr.sbin/prefix/Makefile b/usr.sbin/prefix/Makefile
index 4681577..69bd0e3 100644
--- a/usr.sbin/prefix/Makefile
+++ b/usr.sbin/prefix/Makefile
@@ -2,9 +2,10 @@
# $Id: Makefile,v 1.1.1.1 1999/08/08 23:31:13 itojun Exp $
# $FreeBSD$
-PROG= prefix
MAN= prefix.8
-CFLAGS+=-DINET6
+realinstall:
+ ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/prefix.sh ${DESTDIR}${BINDIR}/prefix
.include <bsd.prog.mk>
diff --git a/usr.sbin/prefix/prefix.c b/usr.sbin/prefix/prefix.c
deleted file mode 100644
index 84fbf26..0000000
--- a/usr.sbin/prefix/prefix.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * 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.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/time.h>
-
-#include <net/if.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
-#include <net/if_var.h>
-#endif /* __FreeBSD__ >= 3 */
-#include <net/if_dl.h>
-#include <net/if_types.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-#include <netinet/in_var.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define DEF_ADVVALIDLIFETIME 2592000
-#define DEF_ADVPREFERREDLIFETIME 604800
-struct in6_prefixreq prereq = {{NULL}, /* interface name */
- PR_ORIG_STATIC,
- 64, /* default plen */
- 2592000, /* vltime=30days */
- 604800, /* pltime=7days */
- /* ra onlink=1 autonomous=1 */
- {{1,1,0}},
- {NULL}}; /* prefix */
-struct in6_rrenumreq rrreq = {{NULL}, /* interface name */
- PR_ORIG_STATIC, /* default origin */
- 64, /* default match len */
- 0, /* default min match len */
- 128, /* default max match len */
- 0, /* default uselen */
- 0, /* default keeplen */
- {1,1,0}, /* default raflag mask */
- 2592000, /* vltime=30days */
- 604800, /* pltime=7days */
- /* ra onlink=1 autonomous=1 */
- {{1,1,0}},
- {NULL}, /* match prefix */
- {NULL} /* use prefix */
- };
-
-#define C(x) ((caddr_t) &x)
-
-struct prefix_cmds {
- const char *errmsg;
- int cmd;
- caddr_t req;
-} prcmds[] = {
- {"SIOCSIFPREFIX_IN6 failed", SIOCSIFPREFIX_IN6, C(prereq)},
- {"SIOCDIFPREFIX_IN6 failed", SIOCDIFPREFIX_IN6, C(prereq)},
- {"SIOCAIFPREFIX_IN6 failed", SIOCAIFPREFIX_IN6, C(rrreq)},
- {"SIOCCIFPREFIX_IN6 failed", SIOCCIFPREFIX_IN6, C(rrreq)},
- {"SIOCSGIFPREFIX_IN6 failed", SIOCSGIFPREFIX_IN6, C(rrreq)}
-};
-
-#define PREF_CMD_SET 0
-#define PREF_CMD_DELETE 1
-#define PREF_CMD_ADD 2
-#define PREF_CMD_CHANGE 3
-#define PREF_CMD_SETGLOBAL 4
-#define PREF_CMD_MAX 5
-
-u_int prcmd = PREF_CMD_SET; /* default command */
-
-char name[32];
-int flags;
-
-int newprefix_setdel, newprefix_match, newprefix_use, newprefix_uselen,
- newprefix_keeplen;
-
-void Perror __P((const char *cmd));
-int prefix __P((int argc, char *const *argv));
-void usage __P((void));
-void setlifetime __P((const char *atime, u_int32_t *btime));
-int all, explicit_prefix = 0;
-
-typedef void c_func __P((const char *cmd, int arg));
-c_func set_vltime, set_pltime, set_raf_onlink,
- set_raf_auto, set_rrf_decrvalid, set_rrf_decrprefd,
- get_setdelprefix, get_matchprefix, get_useprefix, set_matchlen,
- set_match_minlen, set_match_maxlen,
- set_use_uselen, set_use_keeplen, set_prefix_cmd;
-
-void getprefixlen __P((const char *, int));
-void getprefix __P((const char *, int));
-
-#define NEXTARG 0xffffff
-
-const
-struct cmd {
- const char *c_name;
- int c_parameter; /* NEXTARG means next argv */
- void (*c_func) __P((const char *, int));
-} cmds[] = {
- { "set", PREF_CMD_SET, set_prefix_cmd },
- { "delete", PREF_CMD_DELETE, set_prefix_cmd },
- { "prefixlen", NEXTARG, getprefixlen },
- { "add", PREF_CMD_ADD, set_prefix_cmd },
- { "change", PREF_CMD_CHANGE, set_prefix_cmd },
- { "setglobal", PREF_CMD_SETGLOBAL, set_prefix_cmd },
- { "matchpr", NEXTARG, get_matchprefix },
- { "usepr", NEXTARG, get_useprefix },
- { "mp_len", NEXTARG, set_matchlen },
- { "mp_minlen", NEXTARG, set_match_minlen },
- { "mp_maxlen", NEXTARG, set_match_maxlen },
- { "up_uselen", NEXTARG, set_use_uselen },
- { "up_keeplen", NEXTARG, set_use_keeplen },
- { "vltime", NEXTARG, set_vltime },
- { "pltime", NEXTARG, set_pltime },
- { "raf_onlink", 1, set_raf_onlink },
- { "-raf_onlink", 0, set_raf_onlink },
- { "raf_auto", 1, set_raf_auto },
- { "-raf_auto", 0, set_raf_auto },
- { "rrf_decrvalid", 1, set_rrf_decrvalid },
- { "-rrf_decrvalid", 0, set_rrf_decrvalid },
- { "rrf_decrprefd", 1, set_rrf_decrprefd },
- { "-rrf_decrprefd", 0, set_rrf_decrprefd },
- { 0, 0, get_setdelprefix },
- { 0, 0, 0 },
-};
-
-
-void
-usage()
-{
- fprintf(stderr, "%s",
- "usage: prefix interface prefix_value [parameters] [set|delete]\n"
- " prefix interface\n"
- " matchpr matchpr_value mp_len mp_len_value\n"
- " usepr usepr_value up_uselen up_uselen_value\n"
- " [parameters] [add|change|setglobal]\n"
- " prefix -a [-d] [-u]\n"
- " matchpr matchpr_value mp_len mp_len_value\n"
- " usepr usepr_value up_uselen up_uselen_value\n"
- " [parameters] [add|change|setglobal]\n");
- exit(1);
-}
-
-int
-main(argc, argv)
- int argc;
- char *const *argv;
-{
- int c;
- int downonly, uponly;
- int foundit = 0;
- int addrcount;
- struct if_msghdr *ifm, *nextifm;
- struct ifa_msghdr *ifam;
- struct sockaddr_dl *sdl;
- char *buf, *lim, *next;
-
-
- size_t needed;
- int mib[6];
-
- /* Parse leading line options */
- all = downonly = uponly = 0;
- while ((c = getopt(argc, argv, "adu")) != -1) {
- switch (c) {
- case 'a': /* scan all interfaces */
- all++;
- break;
- case 'd': /* restrict scan to "down" interfaces */
- downonly++;
- break;
- case 'u': /* restrict scan to "up" interfaces */
- uponly++;
- break;
- default:
- usage();
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- /* nonsense.. */
- if (uponly && downonly)
- usage();
-
- if (!all) {
- /* not listing, need an argument */
- if (argc < 1)
- usage();
-
- strncpy(name, *argv, sizeof(name));
- argc--, argv++;
- }
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0;
- mib[3] = AF_INET6; /* address family */
- mib[4] = NET_RT_IFLIST;
- mib[5] = 0;
-
- if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
- errx(1, "iflist-sysctl-estimate");
- if ((buf = malloc(needed)) == NULL)
- errx(1, "malloc");
- if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
- errx(1, "actual retrieval of interface table");
- lim = buf + needed;
-
- next = buf;
- while (next < lim) {
-
- ifm = (struct if_msghdr *)next;
-
- if (ifm->ifm_type == RTM_IFINFO) {
- sdl = (struct sockaddr_dl *)(ifm + 1);
- flags = ifm->ifm_flags;
- } else {
- fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n");
- fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO,
- ifm->ifm_type);
- fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen);
- fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next,
- lim);
- exit (1);
- }
-
- next += ifm->ifm_msglen;
- ifam = NULL;
- addrcount = 0;
- while (next < lim) {
-
- nextifm = (struct if_msghdr *)next;
-
- if (nextifm->ifm_type != RTM_NEWADDR)
- break;
-
- if (ifam == NULL)
- ifam = (struct ifa_msghdr *)nextifm;
-
- addrcount++;
- next += nextifm->ifm_msglen;
- }
-
- if (all) {
- if (uponly)
- if ((flags & IFF_UP) == 0)
- continue; /* not up */
- if (downonly)
- if (flags & IFF_UP)
- continue; /* not down */
- strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
- name[sdl->sdl_nlen] = '\0';
- } else {
- if (strlen(name) != sdl->sdl_nlen)
- continue; /* not same len */
- if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
- continue; /* not same name */
- }
-
- if (argc > 0)
- prefix(argc, argv);
-#if 0
- else {
- /* TODO: print prefix status by sysctl */
- }
-#endif
-
- if (all == 0) {
- foundit++; /* flag it as 'done' */
- break;
- }
- }
- free(buf);
-
- if (all == 0 && foundit == 0)
- errx(1, "interface %s does not exist", name);
-
-
- exit (0);
-}
-
-
-int
-prefix(int argc, char *const *argv)
-{
- int s;
-
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
- err(1, "socket");
-
- while (argc > 0) {
- register const struct cmd *p;
-
- for (p = cmds; p->c_name; p++)
- if (strcmp(*argv, p->c_name) == 0)
- break;
- if (p->c_func) {
- if (p->c_parameter == NEXTARG) {
- if (argv[1] == NULL)
- errx(1, "'%s' requires argument",
- p->c_name);
- (*p->c_func)(argv[1], 0);
- argc--, argv++;
- } else
- (*p->c_func)(*argv, p->c_parameter);
- }
- argc--, argv++;
- }
- if (prcmd > PREF_CMD_MAX) {
- Perror("ioctl: unknown prefix cmd");
- goto end;
- }
- if (prcmd == PREF_CMD_SET || prcmd == PREF_CMD_DELETE) {
- if (!newprefix_setdel)
- usage();
- } else { /* ADD|CHANGE|SETGLOBAL */
- if (!newprefix_match)
- usage();
- }
- if (!newprefix_use)
- rrreq.irr_u_uselen = 0; /* make clear that no use_prefix */
- else if (newprefix_keeplen == NULL && rrreq.irr_u_uselen < 64)
- /* init keeplen to make uselen + keeplen equal 64 */
- rrreq.irr_u_keeplen = 64 - rrreq.irr_u_uselen;
- if (explicit_prefix == 0) {
- /* Aggregatable address architecture defines all prefixes
- are 64. So, it is convenient to set prefixlen to 64 if
- it is not specified. */
- getprefixlen("64", 0);
- }
- strncpy(prcmds[prcmd].req, name, IFNAMSIZ);
- if (ioctl(s, prcmds[prcmd].cmd, prcmds[prcmd].req) < 0) {
- if (all && errno == EADDRNOTAVAIL)
- goto end;
- Perror(prcmds[prcmd].errmsg);
- }
- end:
- close(s);
- return(0);
-}
-#define PREFIX 0
-#define MPREFIX 1
-#define UPREFIX 2
-
-void
-Perror(cmd)
- const char *cmd;
-{
- switch (errno) {
-
- case ENXIO:
- errx(1, "%s: no such interface", cmd);
- break;
-
- case EPERM:
- errx(1, "%s: permission denied", cmd);
- break;
-
- default:
- err(1, "%s", cmd);
- }
-}
-
-#define SIN6(x) ((struct sockaddr_in6 *) &(x))
-struct sockaddr_in6 *sin6tab[] = {
-SIN6(prereq.ipr_prefix), SIN6(rrreq.irr_matchprefix),
-SIN6(rrreq.irr_useprefix)};
-
-void
-getprefixlen(const char *plen, int unused)
-{
- int len = atoi(plen);
-
- if ((len < 0) || (len > 128))
- errx(1, "%s: bad value", plen);
-
- /* set plen for prereq */
- prereq.ipr_plen = len;
- explicit_prefix = 1;
-}
-
-void
-getprefix(const char *prefix, int which)
-{
- register struct sockaddr_in6 *sin = sin6tab[which];
-
- /*
- * Delay the ioctl to set the interface prefix until flags are all set.
- * The prefix interpretation may depend on the flags,
- * and the flags may change when the prefix is set.
- */
-
- sin->sin6_len = sizeof(*sin);
- sin->sin6_family = AF_INET6;
-
- if (inet_pton(AF_INET6, prefix, &sin->sin6_addr) != 1)
- errx(1, "%s: bad value", prefix);
-}
-
-void
-get_setdelprefix(const char *prefix, int unused)
-{
- newprefix_setdel++;
- getprefix(prefix, PREFIX);
-}
-
-void
-get_matchprefix(const char *prefix, int unused)
-{
- newprefix_match++;
- prcmd = (prcmd == PREF_CMD_SET) ? PREF_CMD_ADD : prcmd;
- getprefix(prefix, MPREFIX);
-}
-
-void
-get_useprefix(const char *prefix, int unused)
-{
- newprefix_use++;
- if (newprefix_uselen == 0)
- rrreq.irr_u_uselen = 64;
- getprefix(prefix, UPREFIX);
-}
-
-static int
-get_plen(const char *plen)
-{
- int len;
-
- len = atoi(plen);
- if ((len < 0) || (len > 128))
- errx(1, "%s: bad value", plen);
- return len;
-}
-
-void
-set_matchlen(const char *plen, int unused)
-{
- rrreq.irr_m_len = get_plen(plen);
-}
-
-void
-set_match_minlen(const char *plen, int unused)
-{
- rrreq.irr_m_minlen = get_plen(plen);
-}
-
-void
-set_match_maxlen(const char *plen, int unused)
-{
- rrreq.irr_m_maxlen = get_plen(plen);
-}
-
-void
-set_use_uselen(const char *plen, int unused)
-{
- newprefix_uselen++;
- rrreq.irr_u_uselen = get_plen(plen);
-}
-
-void
-set_use_keeplen(const char *plen, int unused)
-{
- newprefix_keeplen++;
- rrreq.irr_u_keeplen = get_plen(plen);
-}
-
-void
-set_vltime(const char *ltime, int unused)
-{
- setlifetime(ltime, &prereq.ipr_vltime);
- rrreq.irr_vltime = prereq.ipr_vltime;
-}
-
-void
-set_pltime(const char *ltime, int unused)
-{
- setlifetime(ltime, &prereq.ipr_pltime);
- rrreq.irr_pltime = prereq.ipr_pltime;
-}
-
-void
-set_raf_onlink(const char *unused, int value)
-{
- /* raflagmask is only meaningful when newprefix_rrenum */
- rrreq.irr_raflagmask.onlink = 1;
- prereq.ipr_flags.prf_ra.onlink =
- rrreq.irr_flags.prf_ra.onlink = value ? 1 : 0;
-}
-
-void
-set_raf_auto(const char *unused, int value)
-{
- /* only meaningful when newprefix_rrenum */
- rrreq.irr_raflagmask.autonomous = 1;
- prereq.ipr_flags.prf_ra.autonomous =
- rrreq.irr_flags.prf_ra.autonomous = value ? 1 : 0;
-}
-
-void
-set_rrf_decrvalid(const char *unused, int value)
-{
- prereq.ipr_flags.prf_rr.decrvalid =
- rrreq.irr_flags.prf_rr.decrvalid = value ? 1 : 0;
-}
-
-void
-set_rrf_decrprefd(const char *unused, int value)
-{
- prereq.ipr_flags.prf_rr.decrprefd =
- rrreq.irr_flags.prf_rr.decrprefd = value ? 1 : 0;
-}
-
-void
-set_prefix_cmd(const char *unused, int cmd)
-{
- prcmd = cmd;
-}
-
-void
-setlifetime(const char *atime, u_int32_t *btime)
-{
- int days = 0, hours = 0, minutes = 0, seconds = 0;
- u_int32_t ttime;
- char *check;
-
- if (strcmp(atime, "infinity") == 0) {
- *btime = 0xffffffff;
- return;
- }
- ttime = strtoul(atime, &check ,10) & 0xffffffff;
- if (*check == '\0') {
- *btime = ttime;
- return;
- }
- if (sscanf(atime, "d%2dh%2dm%2ds%2d", &days, &hours, &minutes,
- &seconds) < 0) {
- Perror("wrong time format: valid is d00h00m00s00, \n"
- "where 00 can be any octal number, \n"
- "\'d\' is for days, \'h\' is for hours, \n"
- "\'m\' is for minutes, and \'s\' is for seconds \n");
- return;
- }
- *btime = 0;
- *btime += seconds;
- *btime += minutes * 60;
- *btime += hours * 3600;
- *btime += days * 86400;
- return;
-}
diff --git a/usr.sbin/prefix/prefix.sh b/usr.sbin/prefix/prefix.sh
new file mode 100644
index 0000000..ee727b3
--- /dev/null
+++ b/usr.sbin/prefix/prefix.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+# $KAME: prefix.sh,v 1.12 2001/05/26 23:38:10 itojun Exp $
+# $FreeBSD$
+
+# Copyright (c) 2001 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.
+
+iface=$1
+prefix=$2
+
+usage() {
+ echo "usage: prefix interface prefix [set|delete]"
+}
+
+# We're now invalidating the prefix ioctls and the corresponding command.
+echo "** The prefix command is almost invalidated. Please use ifconfig(8). **"
+
+if [ X"$iface" = X -o X"$prefix" = X ]; then
+ usage
+ exit 1
+fi
+
+if [ -z $3 ]; then
+ command=set
+else
+ command=$3
+fi
+
+case $command in
+ set)
+ laddr=`ifconfig $iface inet6 | grep 'inet6 fe80:' | head -1 | awk '{print $2}'`
+ if [ X"$laddr" = X ]; then
+ echo "prefix: no interface ID found"
+ exit 1
+ fi
+ hostid=`echo $laddr | sed -e 's/^fe80:[0-9a-fA-F]*:/fe80::/' -e 's/^fe80:://' -e 's/%.*//'`
+ address=$2$hostid
+ exec ifconfig $iface inet6 $address prefixlen 64 alias
+ ;;
+ delete)
+ addrs=`ifconfig $iface inet6 | grep "inet6 $prefix" | awk '{print $2}'`
+ for a in $addrs; do
+ ifconfig $iface inet6 $a -alias
+ done
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+esac
diff --git a/usr.sbin/rip6query/rip6query.8 b/usr.sbin/rip6query/rip6query.8
index dab1bbb..e16df23 100644
--- a/usr.sbin/rip6query/rip6query.8
+++ b/usr.sbin/rip6query/rip6query.8
@@ -1,3 +1,4 @@
+.\" $KAME: rip6query.8,v 1.4 2001/03/15 12:35:24 itojun Exp $
.\"
.\" Copyright (C) 1998 and 1999 WIDE Project.
.\" All rights reserved.
@@ -44,7 +45,7 @@
.Sh DESCRIPTION
.Nm
requests remote RIPng daemon on
-.Ar destionation
+.Ar destination
to dump RIPng routing information.
.Fl I
lets you specify outgoing
diff --git a/usr.sbin/rip6query/rip6query.c b/usr.sbin/rip6query/rip6query.c
index ed0f6f9..bc8efe7 100644
--- a/usr.sbin/rip6query/rip6query.c
+++ b/usr.sbin/rip6query/rip6query.c
@@ -1,3 +1,5 @@
+/* $KAME: rip6query.c,v 1.11 2001/05/08 04:36:37 itojun Exp $ */
+
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
@@ -41,6 +43,8 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/queue.h>
+
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
@@ -82,7 +86,7 @@ main(argc, argv)
char pbuf[10];
struct addrinfo hints, *res;
- while ((c = getopt(argc, argv, "I:")) != EOF) {
+ while ((c = getopt(argc, argv, "I:")) != -1) {
switch (c) {
case 'I':
ifidx = if_nametoindex(optarg);
@@ -102,7 +106,7 @@ main(argc, argv)
if (argc != 1) {
usage();
- exit(-1);
+ exit(1);
}
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
diff --git a/usr.sbin/route6d/route6d.8 b/usr.sbin/route6d/route6d.8
index 851e867..7da9b53 100644
--- a/usr.sbin/route6d/route6d.8
+++ b/usr.sbin/route6d/route6d.8
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.\" $KAME: route6d.8,v 1.8 2000/05/31 17:00:09 itojun Exp $
+.\" $KAME: route6d.8,v 1.10 2000/11/24 11:57:18 itojun Exp $
.\"
.\" Copyright (c) 1996 WIDE Project. All rights reserved.
.\"
@@ -16,13 +16,13 @@
.\" A PARTICULAR PURPOSE.
.Dd January 31, 1997
.Dt ROUTE6D 8
-.Os KAME
+.Os
.Sh NAME
.Nm route6d
.Nd RIP6 Routing Daemon
.Sh SYNOPSIS
.Nm
-.Op Fl adDhlqsS
+.Op Fl adDhlnqsS
.Bk -words
.Op Fl R Ar routelog
.Ek
@@ -146,6 +146,9 @@ For example, with
.Nm
will accept default route and routes in 6bone test address, but no others.
.\"
+.It Fl n
+Do not update the kernel routing table.
+.\"
.It Fl N Ar if1[,if2...]
Do not listen to, or advertise, route from/to interfaces specified by
.Ar if1,[if2...] .
diff --git a/usr.sbin/route6d/route6d.c b/usr.sbin/route6d/route6d.c
index 264206e..d41efd0 100644
--- a/usr.sbin/route6d/route6d.c
+++ b/usr.sbin/route6d/route6d.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: route6d.c,v 1.37 2000/10/10 13:02:30 itojun Exp $ */
+/* $KAME: route6d.c,v 1.64 2001/05/08 04:36:37 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -31,7 +31,7 @@
*/
#ifndef lint
-static char _rcsid[] = "$KAME: route6d.c,v 1.37 2000/10/10 13:02:30 itojun Exp $";
+static char _rcsid[] = "$KAME: route6d.c,v 1.64 2001/05/08 04:36:37 itojun Exp $";
#endif
#include <stdio.h>
@@ -72,9 +72,7 @@ static char _rcsid[] = "$KAME: route6d.c,v 1.37 2000/10/10 13:02:30 itojun Exp $
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <netdb.h>
-#ifdef HAVE_GETIFADDRS
#include <ifaddrs.h>
-#endif
#include <arpa/inet.h>
@@ -111,7 +109,8 @@ struct ifc { /* Configuration of an interface */
int ifc_index; /* if index */
int ifc_mtu; /* if mtu */
int ifc_metric; /* if metric */
- short ifc_flags; /* flags */
+ u_int ifc_flags; /* flags */
+ short ifc_cflags; /* IFC_XXX */
struct in6_addr ifc_mylladdr; /* my link-local address */
struct sockaddr_in6 ifc_ripsin; /* rip multicast address */
struct iff *ifc_filter; /* filter structure */
@@ -147,13 +146,13 @@ int ripsock; /* socket to send/receive RIP datagram */
struct rip6 *ripbuf; /* packet buffer for sending */
/*
- * Maintain the routes in a linked list. When the number of the routes
+ * Maintain the routes in a linked list. When the number of the routes
* grows, somebody would like to introduce a hash based or a radix tree
- * based strucutre. I believe the number of routes handled by RIP is
+ * based structure. I believe the number of routes handled by RIP is
* limited and I don't have to manage a complex data structure, however.
*
* One of the major drawbacks of the linear linked list is the difficulty
- * of representing the relationship between a couple of routes. This may
+ * of representing the relationship between a couple of routes. This may
* be a significant problem when we have to support route aggregation with
* supressing the specifices covered by the aggregate.
*/
@@ -201,6 +200,11 @@ int logopened = 0;
static u_long seq = 0;
+volatile int signo;
+volatile sig_atomic_t seenalrm;
+volatile sig_atomic_t seenquit;
+volatile sig_atomic_t seenusr1;
+
#define RRTF_AGGREGATE 0x08000000
#define RRTF_NOADVERTISE 0x10000000
#define RRTF_NH_NOT_LLADDR 0x20000000
@@ -208,9 +212,11 @@ static u_long seq = 0;
#define RRTF_CHANGED 0x80000000
int main __P((int, char **));
-void ripalarm __P((int));
+void sighandler __P((int));
+void ripalarm __P((void));
void riprecv __P((void));
void ripsend __P((struct ifc *, struct sockaddr_in6 *, int));
+int out_filter __P((struct riprt *, struct ifc *));
void init __P((void));
void sockopt __P((struct ifc *));
void ifconfig __P((void));
@@ -222,10 +228,10 @@ int rt_deladdr __P((struct ifc *, const struct sockaddr_in6 *,
const struct sockaddr_in6 *));
void filterconfig __P((void));
int getifmtu __P((int));
-const char *rttypes __P((struct rt_msghdr *rtm));
-const char *rtflags __P((struct rt_msghdr *rtm));
-const char *ifflags __P((int flags));
-void ifrt __P((struct ifc *, int));
+const char *rttypes __P((struct rt_msghdr *));
+const char *rtflags __P((struct rt_msghdr *));
+const char *ifflags __P((int));
+int ifrt __P((struct ifc *, int));
void ifrt_p2p __P((struct ifc *, int));
void applymask __P((struct in6_addr *, struct in6_addr *));
void applyplen __P((struct in6_addr *, int));
@@ -234,10 +240,12 @@ void ifdump __P((int));
void ifdump0 __P((FILE *, const struct ifc *));
void rtdump __P((int));
void rt_entry __P((struct rt_msghdr *, int));
-void rtdexit __P((int));
-void riprequest __P((struct ifc *, struct netinfo6 *, int, struct sockaddr_in6 *));
+void rtdexit __P((void));
+void riprequest __P((struct ifc *, struct netinfo6 *, int,
+ struct sockaddr_in6 *));
void ripflush __P((struct ifc *, struct sockaddr_in6 *));
void sendrequest __P((struct ifc *));
+int sin6mask2len __P((const struct sockaddr_in6 *));
int mask2len __P((const struct in6_addr *, int));
int sendpacket __P((struct sockaddr_in6 *, int));
int addroute __P((struct riprt *, const struct in6_addr *, struct ifc *));
@@ -250,7 +258,7 @@ char *hms __P((void));
const char *inet6_n2p __P((const struct in6_addr *));
struct ifac *ifa_match __P((const struct ifc *, const struct in6_addr *, int));
struct in6_addr *plen2mask __P((int));
-struct riprt *rtsearch __P((struct netinfo6 *));
+struct riprt *rtsearch __P((struct netinfo6 *, struct riprt **));
int ripinterval __P((int));
time_t ripsuptrig __P((void));
void fatal __P((const char *, ...))
@@ -286,7 +294,7 @@ main(argc, argv)
progname = *argv;
pid = getpid();
- while ((ch = getopt(argc, argv, "A:N:O:R:T:L:t:adDhlnqsS")) != EOF) {
+ while ((ch = getopt(argc, argv, "A:N:O:R:T:L:t:adDhlnqsS")) != -1) {
switch (ch) {
case 'A':
case 'N':
@@ -332,8 +340,10 @@ main(argc, argv)
}
argc -= optind;
argv += optind;
- if (argc > 0)
+ if (argc > 0) {
fatal("bogus extra arguments");
+ /*NOTREACHED*/
+ }
if (geteuid()) {
nflag = 1;
@@ -341,6 +351,15 @@ main(argc, argv)
}
openlog(progname, LOG_NDELAY|LOG_PID, LOG_DAEMON);
logopened++;
+
+ if ((ripbuf = (struct rip6 *)malloc(RIP6_MAXMTU)) == NULL)
+ fatal("malloc");
+ memset(ripbuf, 0, RIP6_MAXMTU);
+ ripbuf->rip6_cmd = RIP6_RESPONSE;
+ ripbuf->rip6_vers = RIP6_VERSION;
+ ripbuf->rip6_res1[0] = 0;
+ ripbuf->rip6_res1[1] = 0;
+
init();
ifconfig();
for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) {
@@ -353,8 +372,10 @@ main(argc, argv)
}
if (error)
exit(1);
- if (loopifcp == NULL)
+ if (loopifcp == NULL) {
fatal("No loopback found");
+ /*NOTREACHED*/
+ }
loopifindex = loopifcp->ifc_index;
for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next)
ifrt(ifcp, 0);
@@ -365,13 +386,17 @@ main(argc, argv)
if (dflag == 0) {
#if 1
- if (daemon(0, 0) < 0)
+ if (daemon(0, 0) < 0) {
fatal("daemon");
+ /*NOTREACHED*/
+ }
#else
if (fork())
exit(0);
- if (setsid() < 0)
+ if (setsid() < 0) {
fatal("setid");
+ /*NOTREACHED*/
+ }
#endif
}
pid = getpid();
@@ -380,26 +405,25 @@ main(argc, argv)
fclose(pidfile);
}
- if ((ripbuf = (struct rip6 *)malloc(RIP6_MAXMTU)) == NULL)
+ if ((ripbuf = (struct rip6 *)malloc(RIP6_MAXMTU)) == NULL) {
fatal("malloc");
+ /*NOTREACHED*/
+ }
memset(ripbuf, 0, RIP6_MAXMTU);
ripbuf->rip6_cmd = RIP6_RESPONSE;
ripbuf->rip6_vers = RIP6_VERSION;
ripbuf->rip6_res1[0] = 0;
ripbuf->rip6_res1[1] = 0;
- if (signal(SIGALRM, ripalarm) == SIG_ERR)
- fatal("signal: SIGALRM");
- if (signal(SIGQUIT, rtdexit) == SIG_ERR)
- fatal("signal: SIGQUIT");
- if (signal(SIGTERM, rtdexit) == SIG_ERR)
- fatal("signal: SIGTERM");
- if (signal(SIGUSR1, ifrtdump) == SIG_ERR)
- fatal("signal: SIGUSR1");
- if (signal(SIGHUP, ifrtdump) == SIG_ERR)
- fatal("signal: SIGHUP");
- if (signal(SIGINT, ifrtdump) == SIG_ERR)
- fatal("signal: SIGINT");
+ if (signal(SIGALRM, sighandler) == SIG_ERR ||
+ signal(SIGQUIT, sighandler) == SIG_ERR ||
+ signal(SIGTERM, sighandler) == SIG_ERR ||
+ signal(SIGUSR1, sighandler) == SIG_ERR ||
+ signal(SIGHUP, sighandler) == SIG_ERR ||
+ signal(SIGINT, sighandler) == SIG_ERR) {
+ fatal("signal");
+ /*NOTREACHED*/
+ }
/*
* To avoid rip packet congestion (not on a cable but in this
* process), wait for a moment to send the first RIP6_RESPONSE
@@ -418,12 +442,31 @@ main(argc, argv)
while (1) {
fd_set recvec;
+ if (seenalrm) {
+ ripalarm();
+ seenalrm = 0;
+ continue;
+ }
+ if (seenquit) {
+ rtdexit();
+ seenquit = 0;
+ continue;
+ }
+ if (seenusr1) {
+ ifrtdump(SIGUSR1);
+ seenusr1 = 0;
+ continue;
+ }
+
FD_COPY(&sockvec, &recvec);
+ signo = 0;
switch (select(FD_SETSIZE, &recvec, 0, 0, 0)) {
case -1:
- if (errno == EINTR)
- continue;
- fatal("select");
+ if (errno != EINTR) {
+ fatal("select");
+ /*NOTREACHED*/
+ }
+ continue;
case 0:
continue;
default:
@@ -441,13 +484,34 @@ main(argc, argv)
}
}
+void
+sighandler(sig)
+ int sig;
+{
+
+ signo = sig;
+ switch (signo) {
+ case SIGALRM:
+ seenalrm++;
+ break;
+ case SIGQUIT:
+ case SIGTERM:
+ seenquit++;
+ break;
+ case SIGUSR1:
+ case SIGHUP:
+ case SIGINT:
+ seenusr1++;
+ break;
+ }
+}
+
/*
* gracefully exits after resetting sockopts.
*/
/* ARGSUSED */
void
-rtdexit(sig)
- int sig;
+rtdexit()
{
struct riprt *rrt;
@@ -468,14 +532,13 @@ rtdexit(sig)
* Called periodically:
* 1. age out the learned route. remove it if necessary.
* 2. submit RIP6_RESPONSE packets.
- * Invoked in every SUPPLY_INTERVAL6 (30) seconds. I believe we don't have
+ * Invoked in every SUPPLY_INTERVAL6 (30) seconds. I believe we don't have
* to invoke this function in every 1 or 5 or 10 seconds only to age the
* routes more precisely.
*/
/* ARGSUSED */
void
-ripalarm(sig)
- int sig;
+ripalarm()
{
struct ifc *ifcp;
struct riprt *rrt, *rrt_prev, *rrt_next;
@@ -532,43 +595,63 @@ init()
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
error = getaddrinfo(NULL, port, &hints, &res);
- if (error)
+ if (error) {
fatal("%s", gai_strerror(error));
- if (res->ai_next)
+ /*NOTREACHED*/
+ }
+ if (res->ai_next) {
fatal(":: resolved to multiple address");
+ /*NOTREACHED*/
+ }
int0 = 0; int255 = 255;
ripsock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (ripsock < 0)
+ if (ripsock < 0) {
fatal("rip socket");
- if (bind(ripsock, res->ai_addr, res->ai_addrlen) < 0)
+ /*NOTREACHED*/
+ }
+ if (bind(ripsock, res->ai_addr, res->ai_addrlen) < 0) {
fatal("rip bind");
+ /*NOTREACHED*/
+ }
if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
- &int255, sizeof(int255)) < 0)
+ &int255, sizeof(int255)) < 0) {
fatal("rip IPV6_MULTICAST_HOPS");
+ /*NOTREACHED*/
+ }
if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
- &int0, sizeof(int0)) < 0)
+ &int0, sizeof(int0)) < 0) {
fatal("rip IPV6_MULTICAST_LOOP");
+ /*NOTREACHED*/
+ }
i = 1;
#ifdef IPV6_RECVPKTINFO
if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &i,
- sizeof(i)) < 0)
+ sizeof(i)) < 0) {
fatal("rip IPV6_RECVPKTINFO");
+ /*NOTREACHED*/
+ }
#else /* old adv. API */
if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_PKTINFO, &i,
- sizeof(i)) < 0)
+ sizeof(i)) < 0) {
fatal("rip IPV6_PKTINFO");
+ /*NOTREACHED*/
+ }
#endif
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET6;
hints.ai_socktype = SOCK_DGRAM;
error = getaddrinfo(RIP6_DEST, port, &hints, &res);
- if (error)
+ if (error) {
fatal("%s", gai_strerror(error));
- if (res->ai_next)
+ /*NOTREACHED*/
+ }
+ if (res->ai_next) {
fatal("%s resolved to multiple address", RIP6_DEST);
+ /*NOTREACHED*/
+ }
memcpy(&ripsin, res->ai_addr, res->ai_addrlen);
#ifdef FD_ZERO
@@ -579,8 +662,10 @@ init()
FD_SET(ripsock, &sockvec);
if (nflag == 0) {
- if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
+ if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
fatal("route socket");
+ /*NOTREACHED*/
+ }
FD_SET(rtsock, &sockvec);
} else
rtsock = -1; /*just for safety */
@@ -654,9 +739,7 @@ ripsend(ifcp, sin, flag)
{
struct riprt *rrt;
struct in6_addr *nh; /* next hop */
- struct in6_addr ia;
- struct iff *iffp;
- int maxrte, ok;
+ int maxrte;
if (ifcp == NULL) {
/*
@@ -687,14 +770,19 @@ ripsend(ifcp, sin, flag)
if ((flag & RRTF_SENDANYWAY) == 0 &&
(qflag || (ifcp->ifc_flags & IFF_LOOPBACK)))
return;
+
+ /* -N: no use */
if (iff_find(ifcp, 'N') != NULL)
return;
+
+ /* -T: generate default route only */
if (iff_find(ifcp, 'T') != NULL) {
struct netinfo6 rrt_info;
memset(&rrt_info, 0, sizeof(struct netinfo6));
rrt_info.rip6_dest = in6addr_any;
rrt_info.rip6_plen = 0;
rrt_info.rip6_metric = 1;
+ rrt_info.rip6_metric += ifcp->ifc_metric;
rrt_info.rip6_tag = htons(routetag & 0xffff);
np = ripbuf->rip6_nets;
*np = rrt_info;
@@ -702,52 +790,30 @@ ripsend(ifcp, sin, flag)
ripflush(ifcp, sin);
return;
}
+
maxrte = (ifcp->ifc_mtu - sizeof(struct ip6_hdr) -
sizeof(struct udphdr) -
sizeof(struct rip6) + sizeof(struct netinfo6)) /
sizeof(struct netinfo6);
+
nrt = 0; np = ripbuf->rip6_nets; nh = NULL;
for (rrt = riprt; rrt; rrt = rrt->rrt_next) {
if (rrt->rrt_rflags & RRTF_NOADVERTISE)
continue;
- /* Need to check filer here */
- ok = 1;
- for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
- if (iffp->iff_type != 'A')
- continue;
- if (rrt->rrt_info.rip6_plen <= iffp->iff_plen)
- continue;
- ia = rrt->rrt_info.rip6_dest;
- applyplen(&ia, iffp->iff_plen);
- if (IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr)) {
- ok = 0;
- break;
- }
- }
- if (!ok)
- continue;
- for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
- if (iffp->iff_type != 'O')
- continue;
- ok = 0;
- if (rrt->rrt_info.rip6_plen < iffp->iff_plen)
- continue;
- ia = rrt->rrt_info.rip6_dest;
- applyplen(&ia, iffp->iff_plen);
- if (IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr)) {
- ok = 1;
- break;
- }
- }
- if (!ok)
+
+ /* Need to check filter here */
+ if (out_filter(rrt, ifcp) == 0)
continue;
+
/* Check split horizon and other conditions */
if (tobeadv(rrt, ifcp) == 0)
continue;
+
/* Only considers the routes with flag if specified */
if ((flag & RRTF_CHANGED) &&
(rrt->rrt_rflags & RRTF_CHANGED) == 0)
continue;
+
/* Check nexthop */
if (rrt->rrt_index == ifcp->ifc_index &&
!IN6_IS_ADDR_UNSPECIFIED(&rrt->rrt_gw) &&
@@ -775,6 +841,7 @@ ripsend(ifcp, sin, flag)
nh = NULL;
np++; nrt++;
}
+
/* Put the route to the buffer */
*np = rrt->rrt_info;
np++; nrt++;
@@ -788,6 +855,78 @@ ripsend(ifcp, sin, flag)
}
/*
+ * outbound filter logic, per-route/interface.
+ */
+int
+out_filter(rrt, ifcp)
+ struct riprt *rrt;
+ struct ifc *ifcp;
+{
+ struct iff *iffp;
+ struct in6_addr ia;
+ int ok;
+
+ /*
+ * -A: filter out less specific routes, if we have aggregated
+ * route configured.
+ */
+ for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
+ if (iffp->iff_type != 'A')
+ continue;
+ if (rrt->rrt_info.rip6_plen <= iffp->iff_plen)
+ continue;
+ ia = rrt->rrt_info.rip6_dest;
+ applyplen(&ia, iffp->iff_plen);
+ if (IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr))
+ return 0;
+ }
+
+ /*
+ * if it is an aggregated route, advertise it only to the
+ * interfaces specified on -A.
+ */
+ if ((rrt->rrt_rflags & RRTF_AGGREGATE) != 0) {
+ ok = 0;
+ for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
+ if (iffp->iff_type != 'A')
+ continue;
+ if (rrt->rrt_info.rip6_plen == iffp->iff_plen &&
+ IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest,
+ &iffp->iff_addr)) {
+ ok = 1;
+ break;
+ }
+ }
+ if (!ok)
+ return 0;
+ }
+
+ /*
+ * -O: advertise only if prefix matches the configured prefix.
+ */
+ if (iff_find(ifcp, 'O')) {
+ ok = 0;
+ for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
+ if (iffp->iff_type != 'O')
+ continue;
+ if (rrt->rrt_info.rip6_plen < iffp->iff_plen)
+ continue;
+ ia = rrt->rrt_info.rip6_dest;
+ applyplen(&ia, iffp->iff_plen);
+ if (IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr)) {
+ ok = 1;
+ break;
+ }
+ }
+ if (!ok)
+ return 0;
+ }
+
+ /* the prefix should be advertised */
+ return 1;
+}
+
+/*
* Determine if the route is to be advertised on the specified interface.
* It checks options specified in the arguments and the split horizon rule.
*/
@@ -825,7 +964,7 @@ sendpacket(sin, len)
{
/*
* MSG_DONTROUTE should not be specified when it responds with a
- * RIP6_REQUEST message. SO_DONTROUTE has been specified to
+ * RIP6_REQUEST message. SO_DONTROUTE has been specified to
* other sockets.
*/
struct msghdr m;
@@ -833,7 +972,7 @@ sendpacket(sin, len)
struct iovec iov[2];
u_char cmsgbuf[256];
struct in6_pktinfo *pi;
- int index;
+ int idx;
struct sockaddr_in6 sincopy;
/* do not overwrite the given sin */
@@ -842,10 +981,10 @@ sendpacket(sin, len)
if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)
|| IN6_IS_ADDR_MULTICAST(&sin->sin6_addr)) {
- index = IN6_LINKLOCAL_IFINDEX(sin->sin6_addr);
+ idx = IN6_LINKLOCAL_IFINDEX(sin->sin6_addr);
SET_IN6_LINKLOCAL_IFINDEX(sin->sin6_addr, 0);
} else
- index = 0;
+ idx = 0;
m.msg_name = (caddr_t)sin;
m.msg_namelen = sizeof(*sin);
@@ -853,7 +992,7 @@ sendpacket(sin, len)
iov[0].iov_len = len;
m.msg_iov = iov;
m.msg_iovlen = 1;
- if (!index) {
+ if (!idx) {
m.msg_control = NULL;
m.msg_controllen = 0;
} else {
@@ -867,7 +1006,7 @@ sendpacket(sin, len)
cm->cmsg_type = IPV6_PKTINFO;
pi = (struct in6_pktinfo *)CMSG_DATA(cm);
memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*::*/
- pi->ipi6_ifindex = index;
+ pi->ipi6_ifindex = idx;
}
if (sendmsg(ripsock, &m, 0 /*MSG_DONTROUTE*/) < 0) {
@@ -879,7 +1018,7 @@ sendpacket(sin, len)
}
/*
- * Receive and process RIP packets. Update the routes/kernel forwarding
+ * Receive and process RIP packets. Update the routes/kernel forwarding
* table if necessary.
*/
void
@@ -891,7 +1030,7 @@ riprecv()
struct rip6 *rp;
struct netinfo6 *np, *nq;
struct riprt *rrt;
- int len, nn, need_trigger, index;
+ int len, nn, need_trigger, idx;
char buf[4 * RIP6_MAXMTU];
time_t t;
struct msghdr m;
@@ -902,6 +1041,7 @@ riprecv()
struct iff *iffp;
struct in6_addr ia;
int ok;
+ time_t t_half_lifetime;
need_trigger = 0;
@@ -914,21 +1054,23 @@ riprecv()
cm = (struct cmsghdr *)cmsgbuf;
m.msg_control = (caddr_t)cm;
m.msg_controllen = sizeof(cmsgbuf);
- if ((len = recvmsg(ripsock, &m, 0)) < 0)
+ if ((len = recvmsg(ripsock, &m, 0)) < 0) {
fatal("recvmsg");
- index = 0;
+ /*NOTREACHED*/
+ }
+ idx = 0;
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m);
cm;
cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) {
- if (cm->cmsg_level == IPPROTO_IPV6
- && cm->cmsg_type == IPV6_PKTINFO) {
+ if (cm->cmsg_level == IPPROTO_IPV6 &&
+ cm->cmsg_type == IPV6_PKTINFO) {
pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
- index = pi->ipi6_ifindex;
+ idx = pi->ipi6_ifindex;
break;
}
}
- if (index && IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr))
- SET_IN6_LINKLOCAL_IFINDEX(fsock.sin6_addr, index);
+ if (idx && IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr))
+ SET_IN6_LINKLOCAL_IFINDEX(fsock.sin6_addr, idx);
nh = fsock.sin6_addr;
nn = (len - sizeof(struct rip6) + sizeof(struct netinfo6)) /
@@ -941,8 +1083,8 @@ riprecv()
return;
}
if (rp->rip6_cmd == RIP6_REQUEST) {
- if (index && index < nindex2ifc) {
- ifcp = index2ifc[index];
+ if (idx && idx < nindex2ifc) {
+ ifcp = index2ifc[idx];
riprequest(ifcp, np, nn, &fsock);
} else {
riprequest(NULL, np, nn, &fsock);
@@ -952,13 +1094,13 @@ riprecv()
if (!IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr)) {
trace(1, "Packets from non-ll addr: %s\n",
- inet6_n2p(&fsock.sin6_addr));
+ inet6_n2p(&fsock.sin6_addr));
return; /* Ignore packets from non-link-local addr */
}
- index = IN6_LINKLOCAL_IFINDEX(fsock.sin6_addr);
- ifcp = (index < nindex2ifc) ? index2ifc[index] : NULL;
+ idx = IN6_LINKLOCAL_IFINDEX(fsock.sin6_addr);
+ ifcp = (idx < nindex2ifc) ? index2ifc[idx] : NULL;
if (!ifcp) {
- trace(1, "Packets to unknown interface index %d\n", index);
+ trace(1, "Packets to unknown interface index %d\n", idx);
return; /* Ignore it */
}
if (IN6_ARE_ADDR_EQUAL(&ifcp->ifc_mylladdr, &fsock.sin6_addr))
@@ -967,18 +1109,22 @@ riprecv()
trace(1, "Invalid command %d\n", rp->rip6_cmd);
return;
}
+
+ /* -N: no use */
if (iff_find(ifcp, 'N') != NULL)
return;
+
tracet(1, "Recv(%s): from %s.%d info(%d)\n",
- ifcp->ifc_name, inet6_n2p(&nh), ntohs(fsock.sin6_port), nn);
+ ifcp->ifc_name, inet6_n2p(&nh), ntohs(fsock.sin6_port), nn);
t = time(NULL);
+ t_half_lifetime = t - (RIP_LIFETIME/2);
for (; nn; nn--, np++) {
if (np->rip6_metric == NEXTHOP_METRIC) {
/* modify neighbor address */
if (IN6_IS_ADDR_LINKLOCAL(&np->rip6_dest)) {
nh = np->rip6_dest;
- SET_IN6_LINKLOCAL_IFINDEX(nh, index);
+ SET_IN6_LINKLOCAL_IFINDEX(nh, idx);
trace(1, "\tNexthop: %s\n", inet6_n2p(&nh));
} else if (IN6_IS_ADDR_UNSPECIFIED(&np->rip6_dest)) {
nh = fsock.sin6_addr;
@@ -986,7 +1132,7 @@ riprecv()
} else {
nh = fsock.sin6_addr;
trace(1, "\tInvalid Nexthop: %s\n",
- inet6_n2p(&np->rip6_dest));
+ inet6_n2p(&np->rip6_dest));
}
continue;
}
@@ -1027,7 +1173,9 @@ riprecv()
trace(2, " [junk outside prefix]");
}
- /* Listen-only filter */
+ /*
+ * -L: listen only if the prefix matches the configuration
+ */
ok = 1; /* if there's no L filter, it is ok */
for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
if (iffp->iff_type != 'L')
@@ -1057,7 +1205,7 @@ riprecv()
np->rip6_metric = HOPCNT_INFINITY6;
applyplen(&np->rip6_dest, np->rip6_plen);
- if ((rrt = rtsearch(np)) != NULL) {
+ if ((rrt = rtsearch(np, NULL)) != NULL) {
if (rrt->rrt_t == 0)
continue; /* Intf route has priority */
nq = &rrt->rrt_info;
@@ -1087,20 +1235,33 @@ riprecv()
rrt->rrt_rflags |= RRTF_CHANGED;
need_trigger = 1;
} else if (nq->rip6_metric == np->rip6_metric &&
- rrt->rrt_index == ifcp->ifc_index &&
- IN6_ARE_ADDR_EQUAL(&nh, &rrt->rrt_gw) &&
np->rip6_metric < HOPCNT_INFINITY6) {
- /* same metric, same route from same gw */
- rrt->rrt_t = t;
+ if (rrt->rrt_index == ifcp->ifc_index &&
+ IN6_ARE_ADDR_EQUAL(&nh, &rrt->rrt_gw)) {
+ /* same metric, same route from same gw */
+ rrt->rrt_t = t;
+ } else if (rrt->rrt_t < t_half_lifetime) {
+ /* Better route found */
+ rrt->rrt_index = ifcp->ifc_index;
+ /* Update routing table */
+ delroute(nq, &rrt->rrt_gw);
+ rrt->rrt_gw = nh;
+ *nq = *np;
+ addroute(rrt, &nh, ifcp);
+ rrt->rrt_rflags |= RRTF_CHANGED;
+ rrt->rrt_t = t;
+ }
}
/*
* if nq->rip6_metric == HOPCNT_INFINITY6 then
- * do not update age value. Do nothing.
+ * do not update age value. Do nothing.
*/
} else if (np->rip6_metric < HOPCNT_INFINITY6) {
/* Got a new valid route */
- if ((rrt = MALLOC(struct riprt)) == NULL)
+ if ((rrt = MALLOC(struct riprt)) == NULL) {
fatal("malloc: struct riprt");
+ /*NOTREACHED*/
+ }
memset(rrt, 0, sizeof(*rrt));
nq = &rrt->rrt_info;
@@ -1187,7 +1348,7 @@ riprequest(ifcp, np, nn, sin)
/* Specific response, don't split-horizon */
trace(1, "\tRIP Request\n");
for (i = 0; i < nn; i++, np++) {
- rrt = rtsearch(np);
+ rrt = rtsearch(np, NULL);
if (rrt)
np->rip6_metric = rrt->rrt_info.rip6_metric;
else
@@ -1207,17 +1368,20 @@ riprequest(ifcp, np, nn, sin)
void
ifconfig()
{
-#ifdef HAVE_GETIFADDRS
struct ifaddrs *ifap, *ifa;
struct ifc *ifcp;
struct ipv6_mreq mreq;
int s;
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
fatal("socket");
+ /*NOTREACHED*/
+ }
- if (getifaddrs(&ifap) != 0)
+ if (getifaddrs(&ifap) != 0) {
fatal("getifaddrs");
+ /*NOTREACHED*/
+ }
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr->sa_family != AF_INET6)
@@ -1228,8 +1392,10 @@ ifconfig()
continue;
if (!ifcp) {
/* new interface */
- if ((ifcp = MALLOC(struct ifc)) == NULL)
+ if ((ifcp = MALLOC(struct ifc)) == NULL) {
fatal("malloc: struct ifc");
+ /*NOTREACHED*/
+ }
memset(ifcp, 0, sizeof(*ifcp));
ifcp->ifc_index = -1;
ifcp->ifc_next = ifc;
@@ -1249,6 +1415,7 @@ ifconfig()
trace(1, "%s: <%s> -> ", ifcp->ifc_name,
ifflags(ifcp->ifc_flags));
trace(1, "<%s>\n", ifflags(ifa->ifa_flags));
+ ifcp->ifc_cflags |= IFC_CHANGED;
}
ifcp->ifc_flags = ifa->ifa_flags;
}
@@ -1257,117 +1424,17 @@ ifconfig()
&& 0 < ifcp->ifc_index && !ifcp->ifc_joined) {
mreq.ipv6mr_multiaddr = ifcp->ifc_ripsin.sin6_addr;
mreq.ipv6mr_interface = ifcp->ifc_index;
- if (setsockopt(ripsock, IPPROTO_IPV6,
- IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)
+ if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ &mreq, sizeof(mreq)) < 0) {
fatal("IPV6_JOIN_GROUP");
- trace(1, "join %s %s\n", ifcp->ifc_name, RIP6_DEST);
- ifcp->ifc_joined++;
- }
- }
- close(s);
- freeifaddrs(ifap);
-#else
- int s, i;
- char *buf;
- struct ifconf ifconf;
- struct ifreq *ifrp, ifr;
- struct ifc *ifcp;
- struct ipv6_mreq mreq;
- int bufsiz;
-
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
- fatal("socket");
-
- /* wild guess - v4, media, link, v6 * 3 */
- bufsiz = if_maxindex() * sizeof(struct ifreq) * 6;
- if ((buf = (char *)malloc(bufsiz)) == NULL)
- fatal("malloc");
-
- /*
- * ioctl(SIOCGIFCONF) does not return error on buffer size.
- * we'll try to guess the buffer size by trying it twice, with
- * different buffer size.
- */
- ifconf.ifc_buf = buf;
- ifconf.ifc_len = bufsiz / 2;
- if (ioctl(s, SIOCGIFCONF, (char *)&ifconf) < 0)
- fatal("ioctl: SIOCGIFCONF");
- i = ifconf.ifc_len;
- while (1) {
- char *newbuf;
-
- ifconf.ifc_buf = buf;
- ifconf.ifc_len = bufsiz;
- if (ioctl(s, SIOCGIFCONF, (char *)&ifconf) < 0)
- fatal("ioctl: SIOCGIFCONF");
- if (i == ifconf.ifc_len)
- break;
- i = ifconf.ifc_len;
- bufsiz *= 2;
- if ((newbuf = (char *)realloc(buf, bufsiz)) == NULL) {
- free(buf);
- fatal("realloc");
- }
- buf = newbuf;
- }
- for (i = 0; i < ifconf.ifc_len; ) {
- ifrp = (struct ifreq *)(buf + i);
- if (ifrp->ifr_addr.sa_family != AF_INET6)
- goto skip;
- ifcp = ifc_find(ifrp->ifr_name);
- strcpy(ifr.ifr_name, ifrp->ifr_name);
- if (ioctl(s, SIOCGIFFLAGS, (char *)&ifr) < 0)
- fatal("ioctl: SIOCGIFFLAGS");
- /* we are interested in multicast-capable interfaces */
- if ((ifr.ifr_flags & IFF_MULTICAST) == 0)
- goto skip;
- if (!ifcp) {
- /* new interface */
- if ((ifcp = MALLOC(struct ifc)) == NULL)
- fatal("malloc: struct ifc");
- memset(ifcp, 0, sizeof(*ifcp));
- ifcp->ifc_index = -1;
- ifcp->ifc_next = ifc;
- ifc = ifcp;
- nifc++;
- ifcp->ifc_name = allocopy(ifrp->ifr_name);
- ifcp->ifc_addr = 0;
- ifcp->ifc_filter = 0;
- ifcp->ifc_flags = ifr.ifr_flags;
- trace(1, "newif %s <%s>\n", ifcp->ifc_name,
- ifflags(ifcp->ifc_flags));
- if (!strcmp(ifcp->ifc_name, LOOPBACK_IF))
- loopifcp = ifcp;
- } else {
- /* update flag, this may be up again */
- if (ifcp->ifc_flags != ifr.ifr_flags) {
- trace(1, "%s: <%s> -> ", ifcp->ifc_name,
- ifflags(ifcp->ifc_flags));
- trace(1, "<%s>\n", ifflags(ifr.ifr_flags));
+ /*NOTREACHED*/
}
- ifcp->ifc_flags = ifr.ifr_flags;
- }
- ifconfig1(ifrp->ifr_name, &ifrp->ifr_addr, ifcp, s);
- if ((ifcp->ifc_flags & (IFF_LOOPBACK | IFF_UP)) == IFF_UP
- && 0 < ifcp->ifc_index && !ifcp->ifc_joined) {
- mreq.ipv6mr_multiaddr = ifcp->ifc_ripsin.sin6_addr;
- mreq.ipv6mr_interface = ifcp->ifc_index;
- if (setsockopt(ripsock, IPPROTO_IPV6,
- IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)
- fatal("IPV6_JOIN_GROUP");
trace(1, "join %s %s\n", ifcp->ifc_name, RIP6_DEST);
ifcp->ifc_joined++;
}
-skip:
- i += IFNAMSIZ;
- if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
- i += ifrp->ifr_addr.sa_len;
- else
- i += sizeof(struct sockaddr);
}
close(s);
- free(buf);
-#endif
+ freeifaddrs(ifap);
}
void
@@ -1378,17 +1445,19 @@ ifconfig1(name, sa, ifcp, s)
int s;
{
struct in6_ifreq ifr;
- struct sockaddr_in6 *sin;
+ const struct sockaddr_in6 *sin;
struct ifac *ifa;
int plen;
char buf[BUFSIZ];
- sin = (struct sockaddr_in6 *)sa;
+ sin = (const struct sockaddr_in6 *)sa;
ifr.ifr_addr = *sin;
strcpy(ifr.ifr_name, name);
- if (ioctl(s, SIOCGIFNETMASK_IN6, (char *)&ifr) < 0)
+ if (ioctl(s, SIOCGIFNETMASK_IN6, (char *)&ifr) < 0) {
fatal("ioctl: SIOCGIFNETMASK_IN6");
- plen = mask2len(&ifr.ifr_addr.sin6_addr, 16);
+ /*NOTREACHED*/
+ }
+ plen = sin6mask2len(&ifr.ifr_addr);
if ((ifa = ifa_match(ifcp, &sin->sin6_addr, plen)) != NULL) {
/* same interface found */
/* need check if something changed */
@@ -1398,8 +1467,10 @@ ifconfig1(name, sa, ifcp, s)
/*
* New address is found
*/
- if ((ifa = MALLOC(struct ifac)) == NULL)
+ if ((ifa = MALLOC(struct ifac)) == NULL) {
fatal("malloc: struct ifac");
+ /*NOTREACHED*/
+ }
memset(ifa, 0, sizeof(*ifa));
ifa->ifa_conf = ifcp;
ifa->ifa_next = ifcp->ifc_addr;
@@ -1408,8 +1479,10 @@ ifconfig1(name, sa, ifcp, s)
ifa->ifa_plen = plen;
if (ifcp->ifc_flags & IFF_POINTOPOINT) {
ifr.ifr_addr = *sin;
- if (ioctl(s, SIOCGIFDSTADDR_IN6, (char *)&ifr) < 0)
+ if (ioctl(s, SIOCGIFDSTADDR_IN6, (char *)&ifr) < 0) {
fatal("ioctl: SIOCGIFDSTADDR_IN6");
+ /*NOTREACHED*/
+ }
ifa->ifa_raddr = ifr.ifr_dstaddr.sin6_addr;
inet_ntop(AF_INET6, (void *)&ifa->ifa_raddr, buf, sizeof(buf));
trace(1, "found address %s/%d -- %s\n",
@@ -1428,12 +1501,15 @@ ifconfig1(name, sa, ifcp, s)
ifcp->ifc_mtu = getifmtu(ifcp->ifc_index);
if (ifcp->ifc_mtu > RIP6_MAXMTU)
ifcp->ifc_mtu = RIP6_MAXMTU;
- if (ioctl(s, SIOCGIFMETRIC, (char *)&ifr) < 0)
+ if (ioctl(s, SIOCGIFMETRIC, (char *)&ifr) < 0) {
fatal("ioctl: SIOCGIFMETRIC");
+ /*NOTREACHED*/
+ }
ifcp->ifc_metric = ifr.ifr_metric;
trace(1, "\tindex: %d, mtu: %d, metric: %d\n",
ifcp->ifc_index, ifcp->ifc_mtu, ifcp->ifc_metric);
- }
+ } else
+ ifcp->ifc_cflags |= IFC_CHANGED;
}
/*
@@ -1449,14 +1525,16 @@ rtrecv()
struct ifa_msghdr *ifam;
struct if_msghdr *ifm;
int len;
- struct ifc *ifcp;
+ struct ifc *ifcp, *ic;
int iface = 0, rtable = 0;
struct sockaddr_in6 *rta[RTAX_MAX];
+ struct sockaddr_in6 mask;
int i, addrs;
+ struct riprt *rrt;
if ((len = read(rtsock, buf, sizeof(buf))) < 0) {
perror("read from rtsock");
- exit(-1);
+ exit(1);
}
if (len < sizeof(*rtm)) {
trace(1, "short read from rtsock: %d (should be > %lu)\n",
@@ -1515,7 +1593,6 @@ rtrecv()
trace(1, "rtsock: %s (addrs=%x)\n",
rttypes((struct rt_msghdr *)p), addrs);
if (dflag >= 2) {
- int i;
for (i = 0;
i < ((struct rt_msghdr *)p)->rtm_msglen;
i++) {
@@ -1584,13 +1661,25 @@ rtrecv()
case RTM_LOCK:
/* should already be handled */
fatal("rtrecv: never reach here");
+ /*NOTREACHED*/
case RTM_DELETE:
- if (!rta[RTAX_DST] || !rta[RTAX_GATEWAY]
- || !rta[RTAX_NETMASK]) {
- trace(1, "\tsome of dst/gw/netamsk are unavailable, ignored\n");
+ if (!rta[RTAX_DST] || !rta[RTAX_GATEWAY]) {
+ trace(1, "\tsome of dst/gw/netamsk are "
+ "unavailable, ignored\n");
+ break;
+ }
+ if ((rtm->rtm_flags & RTF_HOST) != 0) {
+ mask.sin6_len = sizeof(mask);
+ memset(&mask.sin6_addr, 0xff,
+ sizeof(mask.sin6_addr));
+ rta[RTAX_NETMASK] = &mask;
+ } else if (!rta[RTAX_NETMASK]) {
+ trace(1, "\tsome of dst/gw/netamsk are "
+ "unavailable, ignored\n");
break;
}
- if (rt_del(rta[RTAX_DST], rta[RTAX_GATEWAY], rta[RTAX_NETMASK]) == 0) {
+ if (rt_del(rta[RTAX_DST], rta[RTAX_GATEWAY],
+ rta[RTAX_NETMASK]) == 0) {
rtable++; /*just to be sure*/
}
break;
@@ -1612,8 +1701,8 @@ rtrecv()
ifam->ifam_index);
break;
}
- rt_deladdr(ifcp, rta[RTAX_IFA], rta[RTAX_NETMASK]);
- iface++;
+ if (!rt_deladdr(ifcp, rta[RTAX_IFA], rta[RTAX_NETMASK]))
+ iface++;
break;
case RTM_OLDADD:
case RTM_OLDDEL:
@@ -1627,7 +1716,21 @@ rtrecv()
trace(1, "rtsock: reconfigure interfaces, refresh interface routes\n");
ifconfig();
for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next)
- ifrt(ifcp, 1);
+ if (ifcp->ifc_cflags & IFC_CHANGED) {
+ if (ifrt(ifcp, 1)) {
+ for (ic = ifc; ic; ic = ic->ifc_next) {
+ if (ifcp->ifc_index == ic->ifc_index)
+ continue;
+ if (ic->ifc_flags & IFF_UP)
+ ripsend(ic, &ic->ifc_ripsin,
+ RRTF_CHANGED);
+ }
+ /* Reset the flag */
+ for (rrt = riprt; rrt; rrt = rrt->rrt_next)
+ rrt->rrt_rflags &= ~RRTF_CHANGED;
+ }
+ ifcp->ifc_cflags &= ~IFC_CHANGED;
+ }
}
if (rtable) {
trace(1, "rtsock: read routing table again\n");
@@ -1663,11 +1766,10 @@ rt_del(sdst, sgw, smask)
return -1;
}
dst = &sdst->sin6_addr;
- if (sgw->sin6_family == AF_INET6
- && smask->sin6_family == AF_INET6) {
+ if (sgw->sin6_family == AF_INET6) {
/* easy case */
gw = &sgw->sin6_addr;
- prefix = mask2len(&smask->sin6_addr, 16);
+ prefix = sin6mask2len(smask);
} else if (sgw->sin6_family == AF_LINK) {
/*
* Interface route... a hard case. We need to get the prefix
@@ -1698,8 +1800,7 @@ rt_del(sdst, sgw, smask)
gw = &in6addr_loopback;
prefix = rrt->rrt_info.rip6_plen;
} else {
- trace(1, "\tunsupported af: (gw=%d, mask=%d)\n",
- sgw->sin6_family, smask->sin6_family);
+ trace(1, "\tunsupported af: (gw=%d)\n", sgw->sin6_family);
return -1;
}
@@ -1713,13 +1814,16 @@ rt_del(sdst, sgw, smask)
applyplen(&ni6.rip6_dest, ni6.rip6_plen); /*to be sure*/
trace(1, "\tfind route %s/%d\n", inet6_n2p(&ni6.rip6_dest),
ni6.rip6_plen);
- if (!rrt && (rrt = rtsearch(&ni6)) == NULL) {
+ if (!rrt && (rrt = rtsearch(&ni6, NULL)) == NULL) {
trace(1, "\tno route found\n");
return -1;
}
+#if 0
if ((rrt->rrt_flags & RTF_STATIC) == 0) {
trace(1, "\tyou can delete static routes only\n");
- } else if (memcmp(&rrt->rrt_gw, gw, sizeof(rrt->rrt_gw)) != 0) {
+ } else
+#endif
+ if (!IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, gw)) {
trace(1, "\tgw mismatch: %s <-> ",
inet6_n2p(&rrt->rrt_gw));
trace(1, "%s\n", inet6_n2p(gw));
@@ -1750,12 +1854,12 @@ rt_deladdr(ifcp, sifa, smask)
time_t t_lifetime;
int updated = 0;
- if (sifa->sin6_family != AF_INET6 || smask->sin6_family != AF_INET6) {
+ if (sifa->sin6_family != AF_INET6) {
trace(1, "\tother AF, ignored\n");
return -1;
}
addr = &sifa->sin6_addr;
- prefix = mask2len(&smask->sin6_addr, 16);
+ prefix = sin6mask2len(smask);
trace(1, "\tdeleting %s/%d from %s\n",
inet6_n2p(addr), prefix, ifcp->ifc_name);
@@ -1793,11 +1897,12 @@ rt_deladdr(ifcp, sifa, smask)
applyplen(&ni6.rip6_dest, ni6.rip6_plen);
trace(1, "\tfind interface route %s/%d on %d\n",
inet6_n2p(&ni6.rip6_dest), ni6.rip6_plen, ifcp->ifc_index);
- if ((rrt = rtsearch(&ni6)) != NULL) {
+ if ((rrt = rtsearch(&ni6, NULL)) != NULL) {
struct in6_addr none;
memset(&none, 0, sizeof(none));
- if (rrt->rrt_index == ifcp->ifc_index
- && memcmp(&rrt->rrt_gw, &none, sizeof(rrt->rrt_gw)) == 0) {
+ if (rrt->rrt_index == ifcp->ifc_index &&
+ (IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, &none) ||
+ IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw))) {
trace(1, "\troute found, age it\n");
if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) {
rrt->rrt_t = t_lifetime;
@@ -1821,15 +1926,14 @@ rt_deladdr(ifcp, sifa, smask)
trace(1, "\tfind p2p route %s/%d on %d\n",
inet6_n2p(&ni6.rip6_dest), ni6.rip6_plen,
ifcp->ifc_index);
- if ((rrt = rtsearch(&ni6)) != NULL) {
- if (rrt->rrt_index == ifcp->ifc_index
- && memcmp(&rrt->rrt_gw, &ifa->ifa_addr,
- sizeof(rrt->rrt_gw)) == 0) {
+ if ((rrt = rtsearch(&ni6, NULL)) != NULL) {
+ if (rrt->rrt_index == ifcp->ifc_index &&
+ IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, &ifa->ifa_addr)) {
trace(1, "\troute found, age it\n");
if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) {
rrt->rrt_t = t_lifetime;
rrt->rrt_info.rip6_metric =
- HOPCNT_INFINITY6;
+ HOPCNT_INFINITY6;
updated++;
}
} else {
@@ -1848,20 +1952,22 @@ rt_deladdr(ifcp, sifa, smask)
* Get each interface address and put those interface routes to the route
* list.
*/
-void
+int
ifrt(ifcp, again)
struct ifc *ifcp;
int again;
{
struct ifac *ifa;
- struct riprt *rrt;
+ struct riprt *rrt, *search_rrt, *prev_rrt, *loop_rrt;
struct netinfo6 *np;
+ time_t t_lifetime;
+ int need_trigger = 0;
if (ifcp->ifc_flags & IFF_LOOPBACK)
- return; /* ignore loopback */
+ return 0; /* ignore loopback */
if (ifcp->ifc_flags & IFF_POINTOPOINT) {
ifrt_p2p(ifcp, again);
- return;
+ return 0;
}
for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) {
@@ -1880,37 +1986,73 @@ ifrt(ifcp, again)
#endif
continue;
}
- if ((rrt = MALLOC(struct riprt)) == NULL)
- fatal("malloc: struct riprt");
- memset(rrt, 0, sizeof(*rrt));
- rrt->rrt_same = NULL;
- rrt->rrt_index = ifcp->ifc_index;
- rrt->rrt_t = 0; /* don't age */
- rrt->rrt_info.rip6_dest = ifa->ifa_addr;
- rrt->rrt_info.rip6_tag = htons(routetag & 0xffff);
- rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric;
- rrt->rrt_info.rip6_plen = ifa->ifa_plen;
- applyplen(&rrt->rrt_info.rip6_dest, ifa->ifa_plen);
- memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr));
- np = &rrt->rrt_info;
- if (rtsearch(np) == NULL) {
+ if (ifcp->ifc_flags & IFF_UP) {
+ if ((rrt = MALLOC(struct riprt)) == NULL)
+ fatal("malloc: struct riprt");
+ memset(rrt, 0, sizeof(*rrt));
+ rrt->rrt_same = NULL;
+ rrt->rrt_index = ifcp->ifc_index;
+ rrt->rrt_t = 0; /* don't age */
+ rrt->rrt_info.rip6_dest = ifa->ifa_addr;
+ rrt->rrt_info.rip6_tag = htons(routetag & 0xffff);
+ rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric;
+ rrt->rrt_info.rip6_plen = ifa->ifa_plen;
+ rrt->rrt_flags = RTF_CLONING;
+ rrt->rrt_rflags |= RRTF_CHANGED;
+ applyplen(&rrt->rrt_info.rip6_dest, ifa->ifa_plen);
+ memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr));
+#if 0
+ /* XXX why gateway address == network adddress? */
+ rrt->rrt_gw = ifa->ifa_addr;
+#endif
+ np = &rrt->rrt_info;
+ search_rrt = rtsearch(np, &prev_rrt);
+ if (search_rrt != NULL) {
+ if (search_rrt->rrt_info.rip6_metric >
+ rrt->rrt_info.rip6_metric) {
+ if (prev_rrt)
+ prev_rrt->rrt_next = rrt->rrt_next;
+ else
+ riprt = rrt->rrt_next;
+ delroute(&rrt->rrt_info, &rrt->rrt_gw);
+ free(rrt);
+ } else {
+ /* Already have better route */
+ if (!again) {
+ trace(1, "route: %s/%d: "
+ "already registered (%s)\n",
+ inet6_n2p(&np->rip6_dest), np->rip6_plen,
+ ifcp->ifc_name);
+ }
+ free(rrt);
+ continue;
+ }
+ }
/* Attach the route to the list */
trace(1, "route: %s/%d: register route (%s)\n",
inet6_n2p(&np->rip6_dest), np->rip6_plen,
ifcp->ifc_name);
rrt->rrt_next = riprt;
riprt = rrt;
+ addroute(rrt, &rrt->rrt_gw, ifcp);
+ sendrequest(ifcp);
+ ripsend(ifcp, &ifcp->ifc_ripsin, 0);
+ need_trigger = 1;
} else {
- /* Already found */
- if (!again) {
- trace(1, "route: %s/%d: "
- "already registered (%s)\n",
- inet6_n2p(&np->rip6_dest), np->rip6_plen,
- ifcp->ifc_name);
+ for (loop_rrt = riprt; loop_rrt; loop_rrt = loop_rrt->rrt_next) {
+ if (loop_rrt->rrt_index == ifcp->ifc_index) {
+ t_lifetime = time(NULL) - RIP_LIFETIME;
+ if (loop_rrt->rrt_t == 0 || loop_rrt->rrt_t > t_lifetime) {
+ loop_rrt->rrt_t = t_lifetime;
+ loop_rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6;
+ loop_rrt->rrt_rflags |= RRTF_CHANGED;
+ need_trigger = 1;
+ }
+ }
}
- free(rrt);
- }
+ }
}
+ return need_trigger;
}
/*
@@ -1924,7 +2066,7 @@ ifrt_p2p(ifcp, again)
int again;
{
struct ifac *ifa;
- struct riprt *rrt;
+ struct riprt *rrt, *orrt, *prevrrt;
struct netinfo6 *np;
struct in6_addr addr, dest;
int advert, ignore, i;
@@ -1933,7 +2075,7 @@ ifrt_p2p(ifcp, again)
#define P2PADVERT_DEST 4
#define P2PADVERT_MAX 4
const enum { CISCO, GATED, ROUTE6D } behavior = GATED;
- const char *category;
+ const char *category = "";
const char *noadv;
for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) {
@@ -1961,6 +2103,10 @@ ifrt_p2p(ifcp, again)
* do not install network route to route6d routing
* table (if we do, it would prevent route installation
* for other p2p interface that shares addr/plen).
+ *
+ * XXX what should we do if dest is ::? it will not
+ * get announced anyways (see following filter),
+ * but we need to think.
*/
advert |= P2PADVERT_ADDR;
advert |= P2PADVERT_DEST;
@@ -1968,23 +2114,39 @@ ifrt_p2p(ifcp, again)
break;
case ROUTE6D:
/*
- * just for testing...
+ * just for testing. actually the code is redundant
+ * given the current p2p interface address assignment
+ * rule for kame kernel.
+ *
+ * intent:
+ * A/n -> announce A/n
+ * A B/n, A and B share prefix -> A/n (= B/n)
+ * A B/n, do not share prefix -> A/128 and B/128
+ * actually, A/64 and A B/128 are the only cases
+ * permitted by the kernel:
+ * A/64 -> A/64
+ * A B/128 -> A/128 and B/128
*/
- if (IN6_ARE_ADDR_EQUAL(&addr, &dest))
+ if (!IN6_IS_ADDR_UNSPECIFIED(&ifa->ifa_raddr)) {
+ if (IN6_ARE_ADDR_EQUAL(&addr, &dest))
+ advert |= P2PADVERT_NETWORK;
+ else {
+ advert |= P2PADVERT_ADDR;
+ advert |= P2PADVERT_DEST;
+ ignore |= P2PADVERT_NETWORK;
+ }
+ } else
advert |= P2PADVERT_NETWORK;
- else {
- advert |= P2PADVERT_ADDR;
- advert |= P2PADVERT_DEST;
- ignore |= P2PADVERT_NETWORK;
- }
break;
}
for (i = 1; i <= P2PADVERT_MAX; i *= 2) {
if ((ignore & i) != 0)
continue;
- if ((rrt = MALLOC(struct riprt)) == NULL)
+ if ((rrt = MALLOC(struct riprt)) == NULL) {
fatal("malloc: struct riprt");
+ /*NOTREACHED*/
+ }
memset(rrt, 0, sizeof(*rrt));
rrt->rrt_same = NULL;
rrt->rrt_index = ifcp->ifc_index;
@@ -2000,11 +2162,13 @@ ifrt_p2p(ifcp, again)
case P2PADVERT_ADDR:
rrt->rrt_info.rip6_dest = ifa->ifa_addr;
rrt->rrt_info.rip6_plen = 128;
+ rrt->rrt_gw = in6addr_loopback;
category = "addr";
break;
case P2PADVERT_DEST:
rrt->rrt_info.rip6_dest = ifa->ifa_raddr;
rrt->rrt_info.rip6_plen = 128;
+ rrt->rrt_gw = ifa->ifa_addr;
category = "dest";
break;
}
@@ -2024,9 +2188,9 @@ ifrt_p2p(ifcp, again)
noadv = "";
rrt->rrt_info.rip6_tag = htons(routetag & 0xffff);
rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric;
- memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr));
np = &rrt->rrt_info;
- if (rtsearch(np) == NULL) {
+ orrt = rtsearch(np, &prevrrt);
+ if (!orrt) {
/* Attach the route to the list */
trace(1, "route: %s/%d: register route "
"(%s on %s%s)\n",
@@ -2034,6 +2198,19 @@ ifrt_p2p(ifcp, again)
category, ifcp->ifc_name, noadv);
rrt->rrt_next = riprt;
riprt = rrt;
+ } else if (rrt->rrt_index != orrt->rrt_index ||
+ rrt->rrt_info.rip6_metric != orrt->rrt_info.rip6_metric) {
+ /* swap route */
+ rrt->rrt_next = orrt->rrt_next;
+ if (prevrrt)
+ prevrrt->rrt_next = rrt;
+ else
+ riprt = rrt;
+ free(orrt);
+
+ trace(1, "route: %s/%d: update (%s on %s%s)\n",
+ inet6_n2p(&np->rip6_dest), np->rip6_plen,
+ category, ifcp->ifc_name, noadv);
} else {
/* Already found */
if (!again) {
@@ -2069,18 +2246,26 @@ getifmtu(ifindex)
mib[3] = AF_INET6;
mib[4] = NET_RT_IFLIST;
mib[5] = ifindex;
- if (sysctl(mib, 6, NULL, &msize, NULL, 0) < 0)
+ if (sysctl(mib, 6, NULL, &msize, NULL, 0) < 0) {
fatal("sysctl estimate NET_RT_IFLIST");
- if ((buf = malloc(msize)) == NULL)
+ /*NOTREACHED*/
+ }
+ if ((buf = malloc(msize)) == NULL) {
fatal("malloc");
- if (sysctl(mib, 6, buf, &msize, NULL, 0) < 0)
+ /*NOTREACHED*/
+ }
+ if (sysctl(mib, 6, buf, &msize, NULL, 0) < 0) {
fatal("sysctl NET_RT_IFLIST");
+ /*NOTREACHED*/
+ }
ifm = (struct if_msghdr *)buf;
mtu = ifm->ifm_data.ifi_mtu;
-#ifdef __FREEBSD__
- if (ifindex != ifm->ifm_index)
+#ifdef __FreeBSD__
+ if (ifindex != ifm->ifm_index) {
fatal("ifindex does not match with ifm_index");
-#endif /* __FREEBSD__ */
+ /*NOTREACHED*/
+ }
+#endif
free(buf);
return mtu;
}
@@ -2108,6 +2293,24 @@ do { \
RTTYPE("NEWADDR", RTM_NEWADDR);
RTTYPE("DELADDR", RTM_DELADDR);
RTTYPE("IFINFO", RTM_IFINFO);
+#ifdef RTM_OLDADD
+ RTTYPE("OLDADD", RTM_OLDADD);
+#endif
+#ifdef RTM_OLDDEL
+ RTTYPE("OLDDEL", RTM_OLDDEL);
+#endif
+#ifdef RTM_OIFINFO
+ RTTYPE("OIFINFO", RTM_OIFINFO);
+#endif
+#ifdef RTM_IFANNOUNCE
+ RTTYPE("IFANNOUNCE", RTM_IFANNOUNCE);
+#endif
+#ifdef RTM_NEWMADDR
+ RTTYPE("NEWMADDR", RTM_NEWMADDR);
+#endif
+#ifdef RTM_DELMADDR
+ RTTYPE("DELMADDR", RTM_DELMADDR);
+#endif
#undef RTTYPE
return NULL;
}
@@ -2118,11 +2321,14 @@ rtflags(rtm)
{
static char buf[BUFSIZ];
- strcpy(buf, "");
+ /*
+ * letter conflict should be okay. painful when *BSD diverges...
+ */
+ strlcpy(buf, "", sizeof(buf));
#define RTFLAG(s, f) \
do { \
if (rtm->rtm_flags & (f)) \
- strcat(buf, (s)); \
+ strlcat(buf, (s), sizeof(buf)); \
} while (0)
RTFLAG("U", RTF_UP);
RTFLAG("G", RTF_GATEWAY);
@@ -2135,12 +2341,42 @@ do { \
RTFLAG("m", RTF_MASK);
#endif
RTFLAG("C", RTF_CLONING);
+#ifdef RTF_CLONED
+ RTFLAG("c", RTF_CLONED);
+#endif
+#ifdef RTF_PRCLONING
+ RTFLAG("c", RTF_PRCLONING);
+#endif
+#ifdef RTF_WASCLONED
+ RTFLAG("W", RTF_WASCLONED);
+#endif
RTFLAG("X", RTF_XRESOLVE);
RTFLAG("L", RTF_LLINFO);
RTFLAG("S", RTF_STATIC);
RTFLAG("B", RTF_BLACKHOLE);
+#ifdef RTF_PROTO3
+ RTFLAG("3", RTF_PROTO3);
+#endif
RTFLAG("2", RTF_PROTO2);
RTFLAG("1", RTF_PROTO1);
+#ifdef RTF_BROADCAST
+ RTFLAG("b", RTF_BROADCAST);
+#endif
+#ifdef RTF_DEFAULT
+ RTFLAG("d", RTF_DEFAULT);
+#endif
+#ifdef RTF_ISAROUTER
+ RTFLAG("r", RTF_ISAROUTER);
+#endif
+#ifdef RTF_TUNNEL
+ RTFLAG("T", RTF_TUNNEL);
+#endif
+#ifdef RTF_AUTH
+ RTFLAG("A", RTF_AUTH);
+#endif
+#ifdef RTF_CRYPT
+ RTFLAG("E", RTF_CRYPT);
+#endif
#undef RTFLAG
return buf;
}
@@ -2151,13 +2387,13 @@ ifflags(flags)
{
static char buf[BUFSIZ];
- strcpy(buf, "");
+ strlcpy(buf, "", sizeof(buf));
#define IFFLAG(s, f) \
do { \
if (flags & f) { \
if (buf[0]) \
- strcat(buf, ","); \
- strcat(buf, s); \
+ strlcat(buf, ",", sizeof(buf)); \
+ strlcat(buf, s, sizeof(buf)); \
} \
} while (0)
IFFLAG("UP", IFF_UP);
@@ -2168,6 +2404,9 @@ do { \
#ifdef IFF_NOTRAILERS
IFFLAG("NOTRAILERS", IFF_NOTRAILERS);
#endif
+#ifdef IFF_SMART
+ IFFLAG("SMART", IFF_SMART);
+#endif
IFFLAG("RUNNING", IFF_RUNNING);
IFFLAG("NOARP", IFF_NOARP);
IFFLAG("PROMISC", IFF_PROMISC);
@@ -2219,10 +2458,11 @@ krtread(again)
continue;
}
} while (retry < 5 && errmsg != NULL);
- if (errmsg)
+ if (errmsg) {
fatal("%s (with %d retries, msize=%lu)", errmsg, retry,
(u_long)msize);
- else if (1 < retry)
+ /*NOTREACHED*/
+ } else if (1 < retry)
syslog(LOG_INFO, "NET_RT_DUMP %d retires", retry);
lim = buf + msize;
@@ -2241,7 +2481,7 @@ rt_entry(rtm, again)
struct sockaddr_in6 *sin6_dst, *sin6_gw, *sin6_mask;
struct sockaddr_in6 *sin6_genmask, *sin6_ifp;
char *rtmp, *ifname = NULL;
- struct riprt *rrt;
+ struct riprt *rrt, *orrt;
struct netinfo6 *np;
int s;
@@ -2298,8 +2538,10 @@ rt_entry(rtm, again)
if (IN6_IS_ADDR_MULTICAST(&sin6_dst->sin6_addr))
return;
- if ((rrt = MALLOC(struct riprt)) == NULL)
+ if ((rrt = MALLOC(struct riprt)) == NULL) {
fatal("malloc: struct riprt");
+ /*NOTREACHED*/
+ }
memset(rrt, 0, sizeof(*rrt));
np = &rrt->rrt_info;
rrt->rrt_same = NULL;
@@ -2320,13 +2562,13 @@ rt_entry(rtm, again)
/* Mask or plen */
if (rtm->rtm_flags & RTF_HOST)
np->rip6_plen = 128; /* Host route */
- else if (sin6_mask) {
- np->rip6_plen = mask2len(&sin6_mask->sin6_addr,
- sin6_mask->sin6_len - offsetof(struct sockaddr_in6, sin6_addr));
- } else
+ else if (sin6_mask)
+ np->rip6_plen = sin6mask2len(sin6_mask);
+ else
np->rip6_plen = 0;
- if (rtsearch(np)) {
+ orrt = rtsearch(np, NULL);
+ if (orrt && orrt->rrt_info.rip6_metric != HOPCNT_INFINITY6) {
/* Already found */
if (!again) {
trace(1, "route: %s/%d flags %s: already registered\n",
@@ -2381,8 +2623,18 @@ rt_entry(rtm, again)
}
/* Put it to the route list */
- rrt->rrt_next = riprt;
- riprt = rrt;
+ if (orrt && orrt->rrt_info.rip6_metric == HOPCNT_INFINITY6) {
+ /* replace route list */
+ rrt->rrt_next = orrt->rrt_next;
+ *orrt = *rrt;
+ trace(1, "route: %s/%d flags %s: replace new route\n",
+ inet6_n2p(&np->rip6_dest), np->rip6_plen,
+ rtflags(rtm));
+ free(rrt);
+ } else {
+ rrt->rrt_next = riprt;
+ riprt = rrt;
+ }
}
int
@@ -2398,7 +2650,7 @@ addroute(rrt, gw, ifcp)
int len;
np = &rrt->rrt_info;
- inet_ntop(AF_INET6, (void *)gw, (char *)buf1, sizeof(buf1));
+ inet_ntop(AF_INET6, (const void *)gw, (char *)buf1, sizeof(buf1));
inet_ntop(AF_INET6, (void *)&ifcp->ifc_mylladdr, (char *)buf2, sizeof(buf2));
tracet(1, "ADD: %s/%d gw %s [%d] ifa %s\n",
inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1,
@@ -2484,6 +2736,8 @@ delroute(np, gw)
rtm->rtm_seq = ++seq;
rtm->rtm_pid = pid;
rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
+ if (np->rip6_plen == sizeof(struct in6_addr) * 8)
+ rtm->rtm_flags |= RTF_HOST;
rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
sin = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];
/* Destination */
@@ -2551,12 +2805,12 @@ getroute(np, gw)
if (errno == ESRCH) /* No such route found */
return NULL;
perror("write to rtsock");
- exit(-1);
+ exit(1);
}
do {
if ((len = read(rtsock, buf, sizeof(buf))) < 0) {
perror("read from rtsock");
- exit(-1);
+ exit(1);
}
rtm = (struct rt_msghdr *)buf;
} while (rtm->rtm_seq != myseq || rtm->rtm_pid != pid);
@@ -2578,7 +2832,7 @@ inet6_n2p(p)
{
static char buf[BUFSIZ];
- return inet_ntop(AF_INET6, (void *)p, buf, sizeof(buf));
+ return inet_ntop(AF_INET6, (const void *)p, buf, sizeof(buf));
}
void
@@ -2662,7 +2916,7 @@ ifdump0(dump, ifcp)
case 'A':
ft = "Aggregate"; addr++; break;
case 'N':
- ft = "No-advertise"; break;
+ ft = "No-use"; break;
case 'O':
ft = "Advertise-only"; addr++; break;
case 'T':
@@ -2731,7 +2985,7 @@ rtdump(sig)
/*
* Parse the -A (and -O) options and put corresponding filter object to the
- * specified interface structures. Each of the -A/O option has the following
+ * specified interface structures. Each of the -A/O option has the following
* syntax: -A 5f09:c400::/32,ef0,ef1 (aggregate)
* -O 5f09:c400::/32,ef0,ef1 (only when match)
*/
@@ -2740,11 +2994,11 @@ filterconfig()
{
int i;
char *p, *ap, *iflp, *ifname;
- struct iff ftmp, *iff_obj;
- struct ifc *ifcp;
- struct riprt *rrt;
+ struct iff ftmp, *iff_obj;
+ struct ifc *ifcp;
+ struct riprt *rrt;
#if 0
- struct in6_addr gw;
+ struct in6_addr gw;
#endif
for (i = 0; i < nfilter; i++) {
@@ -2759,41 +3013,57 @@ filterconfig()
*p++ = '\0';
iflp = p;
}
- if ((p = index(ap, '/')) == NULL)
+ if ((p = index(ap, '/')) == NULL) {
fatal("no prefixlen specified for '%s'", ap);
+ /*NOTREACHED*/
+ }
*p++ = '\0';
- if (inet_pton(AF_INET6, ap, &ftmp.iff_addr) != 1)
+ if (inet_pton(AF_INET6, ap, &ftmp.iff_addr) != 1) {
fatal("invalid prefix specified for '%s'", ap);
+ /*NOTREACHED*/
+ }
ftmp.iff_plen = atoi(p);
ftmp.iff_next = NULL;
applyplen(&ftmp.iff_addr, ftmp.iff_plen);
ifonly:
ftmp.iff_type = filtertype[i];
- if (iflp == NULL || *iflp == '\0')
+ if (iflp == NULL || *iflp == '\0') {
fatal("no interface specified for '%s'", ap);
+ /*NOTREACHED*/
+ }
/* parse the interface listing portion */
while (iflp) {
ifname = iflp;
if ((iflp = index(iflp, ',')) != NULL)
*iflp++ = '\0';
ifcp = ifc_find(ifname);
- if (ifcp == NULL)
+ if (ifcp == NULL) {
fatal("no interface %s exists", ifname);
+ /*NOTREACHED*/
+ }
iff_obj = (struct iff *)malloc(sizeof(struct iff));
- if (iff_obj == NULL)
+ if (iff_obj == NULL) {
fatal("malloc of iff_obj");
+ /*NOTREACHED*/
+ }
memcpy((void *)iff_obj, (void *)&ftmp,
- sizeof(struct iff));
+ sizeof(struct iff));
/* link it to the interface filter */
iff_obj->iff_next = ifcp->ifc_filter;
ifcp->ifc_filter = iff_obj;
}
+
+ /*
+ * -A: aggregate configuration.
+ */
if (filtertype[i] != 'A')
continue;
/* put the aggregate to the kernel routing table */
rrt = (struct riprt *)malloc(sizeof(struct riprt));
- if (rrt == NULL)
+ if (rrt == NULL) {
fatal("malloc: rrt");
+ /*NOTREACHED*/
+ }
memset(rrt, 0, sizeof(struct riprt));
rrt->rrt_info.rip6_dest = ftmp.iff_addr;
rrt->rrt_info.rip6_plen = ftmp.iff_plen;
@@ -2813,12 +3083,13 @@ ifonly:
*/
delroute(&rrt->rrt_info, &gw);
#else
- /* it is more safe behavior */
+ /* it is safer behavior */
errno = EINVAL;
fatal("%s/%u already in routing table, "
"cannot aggregate",
inet6_n2p(&rrt->rrt_info.rip6_dest),
rrt->rrt_info.rip6_plen);
+ /*NOTREACHED*/
#endif
}
#endif
@@ -2860,31 +3131,46 @@ ifa_match(ifcp, ia, plen)
/*
* Return a pointer to riprt structure whose address and prefix length
* matches with the address and prefix length found in the argument.
- * Note: This is not a rtalloc(). Therefore exact match is necessary.
+ * Note: This is not a rtalloc(). Therefore exact match is necessary.
*/
-
struct riprt *
-rtsearch(np)
+rtsearch(np, prev_rrt)
struct netinfo6 *np;
+ struct riprt **prev_rrt;
{
struct riprt *rrt;
+ if (prev_rrt)
+ *prev_rrt = NULL;
for (rrt = riprt; rrt; rrt = rrt->rrt_next) {
if (rrt->rrt_info.rip6_plen == np->rip6_plen &&
IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest,
&np->rip6_dest))
return rrt;
+ if (prev_rrt)
+ *prev_rrt = rrt;
}
+ if (prev_rrt)
+ *prev_rrt = NULL;
return 0;
}
int
+sin6mask2len(sin6)
+ const struct sockaddr_in6 *sin6;
+{
+
+ return mask2len(&sin6->sin6_addr,
+ sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr));
+}
+
+int
mask2len(addr, lenlim)
const struct in6_addr *addr;
int lenlim;
{
int i = 0, j;
- u_char *p = (u_char *)addr;
+ const u_char *p = (const u_char *)addr;
for (j = 0; j < lenlim; j++, p++) {
if (*p != 0xff)
@@ -2984,9 +3270,12 @@ hms()
struct tm *tm;
t = time(NULL);
- if ((tm = localtime(&t)) == 0)
+ if ((tm = localtime(&t)) == 0) {
fatal("localtime");
- snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
+ /*NOTREACHED*/
+ }
+ snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
+ tm->tm_sec);
return buf;
}
@@ -3010,7 +3299,7 @@ ripsuptrig()
double r = rand();
t = (int)(RIP_TRIG_INT6_MIN +
- (RIP_TRIG_INT6_MAX - RIP_TRIG_INT6_MIN) * (r / RAND_MAX ));
+ (RIP_TRIG_INT6_MAX - RIP_TRIG_INT6_MIN) * (r / RAND_MAX));
sup_trig_update = time(NULL) + t;
return t;
}
@@ -3035,7 +3324,7 @@ fatal(fmt, va_alist)
vsnprintf(buf, sizeof(buf), fmt, ap);
perror(buf);
syslog(LOG_ERR, "%s: %s", buf, strerror(errno));
- rtdexit(0);
+ rtdexit();
va_end(ap);
}
@@ -3140,8 +3429,8 @@ iff_find(ifcp, type)
}
void
-setindex2ifc(index, ifcp)
- int index;
+setindex2ifc(idx, ifcp)
+ int idx;
struct ifc *ifcp;
{
int n;
@@ -3151,19 +3440,24 @@ setindex2ifc(index, ifcp)
nindex2ifc = 5; /*initial guess*/
index2ifc = (struct ifc **)
malloc(sizeof(*index2ifc) * nindex2ifc);
- if (index2ifc == NULL)
+ if (index2ifc == NULL) {
fatal("malloc");
+ /*NOTREACHED*/
+ }
memset(index2ifc, 0, sizeof(*index2ifc) * nindex2ifc);
}
n = nindex2ifc;
- while (nindex2ifc <= index)
+ while (nindex2ifc <= idx)
nindex2ifc *= 2;
if (n != nindex2ifc) {
p = (struct ifc **)realloc(index2ifc,
sizeof(*index2ifc) * nindex2ifc);
- if (p == NULL)
+ if (p == NULL) {
fatal("realloc");
+ /*NOTREACHED*/
+ }
+ memset(p + n, 0, sizeof(*index2ifc) * (nindex2ifc - n));
index2ifc = p;
}
- index2ifc[index] = ifcp;
+ index2ifc[idx] = ifcp;
}
diff --git a/usr.sbin/route6d/route6d.h b/usr.sbin/route6d/route6d.h
index b3a353f..5c59d6a 100644
--- a/usr.sbin/route6d/route6d.h
+++ b/usr.sbin/route6d/route6d.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: route6d.h,v 1.3 2000/02/25 06:15:06 itojun Exp $ */
+/* $KAME: route6d.h,v 1.4 2001/01/15 03:50:54 inoue Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -42,6 +42,8 @@
#define RIP6_REQUEST 1
#define RIP6_RESPONSE 2
+#define IFC_CHANGED 1
+
struct netinfo6 {
struct in6_addr rip6_dest;
u_short rip6_tag;
diff --git a/usr.sbin/rrenumd/lexer.l b/usr.sbin/rrenumd/lexer.l
index d906b0c..6ad9953 100644
--- a/usr.sbin/rrenumd/lexer.l
+++ b/usr.sbin/rrenumd/lexer.l
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: lexer.l,v 1.7 2000/11/08 02:40:53 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -32,9 +32,12 @@
*/
%{
+#define YY_NO_UNPUT
+
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/queue.h>
#include <string.h>
@@ -55,6 +58,10 @@ int lineno = 1;
#define LINEBUF_SIZE 1000
char linebuf[LINEBUF_SIZE];
+
+int parse __P((FILE **));
+void yyerror __P((const char *));
+int yylex __P((void));
%}
/* common section */
@@ -248,9 +255,11 @@ off {
int parse(FILE **fp)
{
+ extern int yyparse __P((void));
+
yyin = *fp;
- if(yyparse())
+ if (yyparse())
return(-1);
return(0);
diff --git a/usr.sbin/rrenumd/parser.y b/usr.sbin/rrenumd/parser.y
index 15ca06d..0cfe3b5 100644
--- a/usr.sbin/rrenumd/parser.y
+++ b/usr.sbin/rrenumd/parser.y
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: parser.y,v 1.8 2000/11/08 03:03:34 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -36,6 +36,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#include <sys/queue.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
@@ -48,6 +49,7 @@
#include <netdb.h>
#include <string.h>
+#include <stdio.h>
#include "rrenumd.h"
@@ -62,6 +64,7 @@ char errbuf[LINE_MAX];
extern int lineno;
extern void yyerror __P((const char *s));
+extern int yylex __P((void));
static struct payload_list * pllist_lookup __P((int seqnum));
static void pllist_enqueue __P((struct payload_list *pl_entry));
@@ -192,8 +195,9 @@ dest_addr :
hints.ai_protocol = 0;
error = getaddrinfo($1.cp, 0, &hints, &res);
if (error) {
- sprintf(errbuf, "name resolution failed for %s"
- ":%s", $1, gai_strerror(error));
+ snprintf(errbuf, sizeof(errbuf),
+ "name resolution failed for %s:%s",
+ $1.cp, gai_strerror(error));
yyerror(errbuf);
}
ss = (struct sockaddr_storage *)malloc(sizeof(*ss));
@@ -274,8 +278,9 @@ rrenum_statement_with_seqnum:
SEQNUM_CMD seqnum
{
if (pllist_lookup($2)) {
- sprintf(errbuf, "duplicate seqnum %d specified"
- " at %d", $2, lineno);
+ snprintf(errbuf, sizeof(errbuf),
+ "duplicate seqnum %ld specified at %d",
+ $2, lineno);
yyerror(errbuf);
}
}
@@ -294,9 +299,10 @@ seqnum:
| decstring
{
if ($1 > MAX_SEQNUM) {
- sprintf(errbuf, "seqnum %d is illegal for this"
- " program. should be between 0 and %d",
- $1, MAX_SEQNUM);
+ snprintf(errbuf, sizeof(errbuf),
+ "seqnum %ld is illegal for this program. "
+ "should be between 0 and %d",
+ $1, MAX_SEQNUM);
yyerror(errbuf);
}
$$ = $1;
@@ -307,8 +313,9 @@ rrenum_statement_without_seqnum:
rrenum_statement EOS
{
if (pllist_lookup(0)) {
- sprintf(errbuf, "duplicate seqnum %d specified"
- " at %d", 0, lineno);
+ snprintf(errbuf, sizeof(errbuf),
+ "duplicate seqnum %d specified at %d",
+ 0, lineno);
yyerror(errbuf);
}
$1->pl_irr.rr_seqnum = 0;
@@ -435,8 +442,8 @@ use_prefix_values:
rpu = (struct rr_pco_use *)(rpm + 1);
memset(rpu, 0, sizeof(*rpu));
- rpu->rpu_vltime = DEF_VLTIME;
- rpu->rpu_pltime = DEF_PLTIME;
+ rpu->rpu_vltime = htonl(DEF_VLTIME);
+ rpu->rpu_pltime = htonl(DEF_PLTIME);
rpu->rpu_ramask = 0;
rpu->rpu_flags = 0;
}
@@ -510,7 +517,7 @@ keeplen:
vltime:
/* empty */
{
- $$ = DEF_VLTIME;
+ $$ = htonl(DEF_VLTIME);
}
| VLTIME_CMD lifetime
{
@@ -521,7 +528,7 @@ vltime:
pltime:
/* empty */
{
- $$ = DEF_PLTIME;
+ $$ = htonl(DEF_PLTIME);
}
| PLTIME_CMD lifetime
{
@@ -573,8 +580,8 @@ raf_decrprefd:
;
flag:
- ON
- | OFF
+ ON { $$ = ON; }
+ | OFF { $$ = OFF; }
;
lifetime:
@@ -653,15 +660,16 @@ static void
pllist_enqueue(struct payload_list *pl_entry)
{
struct payload_list *pl, *pl_last;
- if (pl_head == NULL) {
- pl_head = pl_entry;
- return;
- }
+
+ pl_last = NULL;
for (pl = pl_head;
pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum;
pl_last = pl, pl = pl->pl_next)
continue;
- pl_last->pl_next = pl_entry;
+ if (pl_last)
+ pl_last->pl_next = pl_entry;
+ else
+ pl_head = pl_entry;
return;
}
diff --git a/usr.sbin/rrenumd/rrenumd.8 b/usr.sbin/rrenumd/rrenumd.8
index 42ea29d..09e3089 100644
--- a/usr.sbin/rrenumd/rrenumd.8
+++ b/usr.sbin/rrenumd/rrenumd.8
@@ -1,4 +1,4 @@
-.\" $KAME$
+.\" $KAME: rrenumd.8,v 1.6 2001/01/22 02:06:24 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -37,13 +37,19 @@
.Nd router renumbering daemon
.Sh SYNOPSIS
.Nm
+.Op Fl df
.Oo
.Fl c Ar conf_file | Fl s
.Oc
-.Op Fl df
.Sh DESCRIPTION
-.Nm Rrenumd
-assigns prefixes to subnets inside the site, or renumbers them.
+.Nm
+transmits router renumbering request packets,
+to renumber the routers in the site network.
+.Pp
+On KAME-based systems,
+router renumbering requests are received and processed by
+.Xr rtadvd 8 .
+For other systems, refer to relevant documents.
.Pp
The program will daemonize itself on invocation.
It reads configuration information from standard input if
@@ -78,8 +84,16 @@ Specify a configuration file where configuration information is kept.
.Sh RETURN VALUES
The program exits with 0 on success, and non-zero on failures.
.Sh SEE ALSO
-.Xr daemon 3 ,
-.Xr rrenumd.conf 5
+.Xr rrenumd.conf 5 ,
+.Xr rtadvd 8
+.Sh STANDARDS
+.Rs
+.%A Matt Crawford
+.%R RFC
+.%N 2894
+.%D August 2000
+.%T "Router Renumbering for IPv6"
+.Re
.Sh HISTORY
The
.Nm
diff --git a/usr.sbin/rrenumd/rrenumd.c b/usr.sbin/rrenumd/rrenumd.c
index fa3257d..686a869 100644
--- a/usr.sbin/rrenumd/rrenumd.c
+++ b/usr.sbin/rrenumd/rrenumd.c
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: rrenumd.c,v 1.20 2000/11/08 02:40:53 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -64,6 +64,8 @@
#define LL_ALLROUTERS "ff02::2"
#define SL_ALLROUTERS "ff05::2"
+#define RR_MCHLIM_DEFAULT 64
+
#ifndef IN6_IS_SCOPE_LINKLOCAL
#define IN6_IS_SCOPE_LINKLOCAL(a) \
((IN6_IS_ADDR_LINKLOCAL(a)) || \
@@ -93,7 +95,30 @@ int with_v4dest, with_v6dest;
struct in6_addr prefix; /* ADHOC */
int prefixlen = 64; /* ADHOC */
-extern int parse(FILE **fp);
+extern int parse __P((FILE **));
+
+static void show_usage __P((void));
+static void init_sin6 __P((struct sockaddr_in6 *, const char *));
+#if 0
+static void join_multi __P((const char *));
+#endif
+static void init_globals __P((void));
+static void config __P((FILE **));
+#ifdef IPSEC_POLICY_IPSEC
+static void sock6_open __P((struct flags *, char *));
+static void sock4_open __P((struct flags *, char *));
+#else
+static void sock6_open __P((struct flags *));
+static void sock4_open __P((struct flags *));
+#endif
+static void rrenum_output __P((struct payload_list *, struct dst_list *));
+static void rrenum_snd_eachdst __P((struct payload_list *));
+#if 0
+static void rrenum_snd_fullsequence __P((void));
+#endif
+static void rrenum_input __P((int));
+int main __P((int, char *[]));
+
/* Print usage. Don't call this after daemonized. */
static void
@@ -111,7 +136,7 @@ show_usage()
exit(1);
}
-void
+static void
init_sin6(struct sockaddr_in6 *sin6, const char *addr_ascii)
{
memset(sin6, 0, sizeof(*sin6));
@@ -122,7 +147,7 @@ init_sin6(struct sockaddr_in6 *sin6, const char *addr_ascii)
}
#if 0 /* XXX: not necessary ?? */
-void
+static void
join_multi(const char *addrname)
{
struct ipv6_mreq mreq;
@@ -151,7 +176,7 @@ join_multi(const char *addrname)
}
#endif
-void
+static void
init_globals()
{
static struct iovec rcviov;
@@ -193,7 +218,7 @@ init_globals()
sndmhdr.msg_controllen = sndcmsglen;
}
-void
+static void
config(FILE **fpp)
{
struct payload_list *pl;
@@ -236,7 +261,7 @@ config(FILE **fpp)
}
}
-void
+static void
sock6_open(struct flags *flags
#ifdef IPSEC_POLICY_IPSEC
, char *policy
@@ -297,7 +322,7 @@ sock6_open(struct flags *flags
/* XXX should handle in/out bound policy. */
if (setsockopt(s6, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
buf, ipsec_get_policylen(buf)) < 0)
- err(1, NULL);
+ err(1, "setsockopt(IPV6_IPSEC_POLICY)");
free(buf);
}
#else /* IPSEC_POLICY_IPSEC */
@@ -325,7 +350,7 @@ sock6_open(struct flags *flags
return;
}
-void
+static void
sock4_open(struct flags *flags
#ifdef IPSEC_POLICY_IPSEC
, char *policy
@@ -363,7 +388,7 @@ sock4_open(struct flags *flags
/* XXX should handle in/out bound policy. */
if (setsockopt(s4, IPPROTO_IP, IP_IPSEC_POLICY,
buf, ipsec_get_policylen(buf)) < 0)
- err(1, NULL);
+ err(1, "setsockopt(IP_IPSEC_POLICY)");
free(buf);
}
#else /* IPSEC_POLICY_IPSEC */
@@ -391,7 +416,7 @@ sock4_open(struct flags *flags
return;
}
-void
+static void
rrenum_output(struct payload_list *pl, struct dst_list *dl)
{
int i, msglen = 0;
@@ -404,8 +429,8 @@ rrenum_output(struct payload_list *pl, struct dst_list *dl)
sin6 = (struct sockaddr_in6 *)dl->dl_dst;
if (sin6 != NULL &&
- IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
- int hoplimit = 255;
+ IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+ int hoplimit = RR_MCHLIM_DEFAULT;
cm = CMSG_FIRSTHDR(&sndmhdr);
/* specify the outgoing interface */
@@ -438,7 +463,7 @@ rrenum_output(struct payload_list *pl, struct dst_list *dl)
strerror(errno));
}
-void
+static void
rrenum_snd_eachdst(struct payload_list *pl)
{
struct dst_list *dl;
@@ -448,7 +473,8 @@ rrenum_snd_eachdst(struct payload_list *pl)
}
}
-void
+#if 0
+static void
rrenum_snd_fullsequence()
{
struct payload_list *pl;
@@ -457,8 +483,9 @@ rrenum_snd_fullsequence()
rrenum_snd_eachdst(pl);
}
}
+#endif
-void
+static void
rrenum_input(int s)
{
int i;
@@ -603,9 +630,8 @@ main(int argc, char *argv[])
/* ADHOC: timeout each 30seconds */
memset(&timeout, 0, sizeof(timeout));
- timeout.tv_sec = 30;
- /* init temporal payload_list and send_counter*/
+ /* init temporary payload_list and send_counter*/
pl = pl_head;
send_counter = retry + 1;
while (1) {
@@ -622,7 +648,9 @@ main(int argc, char *argv[])
exit(0);
rrenum_snd_eachdst(pl);
send_counter--;
+ timeout.tv_sec = 30;
if (send_counter == 0) {
+ timeout.tv_sec = 0;
pl = pl->pl_next;
send_counter = retry + 1;
}
diff --git a/usr.sbin/rrenumd/rrenumd.conf.5 b/usr.sbin/rrenumd/rrenumd.conf.5
index 1fba85b..833bc6b 100644
--- a/usr.sbin/rrenumd/rrenumd.conf.5
+++ b/usr.sbin/rrenumd/rrenumd.conf.5
@@ -1,4 +1,4 @@
-.\" $KAME$
+.\" $KAME: rrenumd.conf.5,v 1.8 2001/02/06 02:17:23 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -62,8 +62,8 @@ square brackets (`[' and `]') are used to show optional
keywords and parameters.
The vertical bar (`|') is used to indicate
between a choice of optional parameters.
-Parentheses (`(' and
-`)') are used to group keywords and parameters when necessary.
+Curly braces (`{' and
+`}') are used to group keywords and parameters when necessary.
.\"
.Sh Interface specification
There are some statements that may or have to specify interface.
@@ -84,7 +84,8 @@ then debugging is enabled,
If
.Ic off
is specified,
-then debugging is disabled. It is disabled by default.
+then debugging is disabled.
+It is disabled by default.
.\"
.It Ic dest Ar dest-list Op Ar retrycmd ;
Specifies destinations to which router renumbering messages should be
@@ -102,12 +103,25 @@ specifies how many router renumbering messages are sent repeatedly.
.El
.It Op Ic add|change|setglobal
.Cm match-prefix Ar match-prefix-val
+.Bk -words
.Op /match-prefix-len
+.Ek
+.Bk -words
.Op Cm maxlen Ar maxlen-val
+.Ek
+.Bk -words
.Op Cm minlen Ar minlen-val
+.Ek
+.Bk -words
.Op Cm use-prefix Ar use-prefix-val
+.Ek
+.Bk -words
.Op /use-prefix-len
+.Ek
+.Bk -words
.Op Cm keeplen Ar keeplen-val
+.Ek
+.Bk -words
.Op Ar use-prefix-values ;
.Pp
Specifies contents of sending router renumbering message with seqnum 0.
@@ -121,11 +135,21 @@ has following syntax.
.Pp
{
.Op Cm vltime Ar vltime-val
+.Bk -words
.Op Cm pltime Ar pltime-val
+.Ek
+.Bk -words
.Op Cm raf_onlink Cm on|off
+.Ek
+.Bk -words
.Op Cm raf_auto Cm on|off
+.Ek
+.Bk -words
.Op Cm rrf_decrprefd Cm on|off
+.Ek
+.Bk -words
.Op Cm rrf_decrvalid Cm on|off
+.Ek
}
.Pp
Each value has following meaning.
@@ -163,7 +187,7 @@ copied to the starting part of prefixes to be added on
.Cm add|change|setglobal
command, as decimal bit number.
.It Cm keeplen Ar keeplen-val
-Specify the midium part of
+Specify the medium part of
.Ar use-prefix-val
just next to the starting part specified by
.Ar use-prefix-len
@@ -180,7 +204,8 @@ Valid value for
.Ar time
is decimal seconds number or special format as "d00h00m00s00",
where 00 can take any decimal number, and "d" means days, "h" means hours,
-"m" means minutes, "s" means seconds. And alternatively, special keyword
+"m" means minutes, "s" means seconds.
+And alternatively, special keyword
"infinity" can be also be specified.
.It Cm pltime Ar pltime-val
Assign an
@@ -192,38 +217,49 @@ is same as for
.Ar vltime-val .
.It Cm raf_onlink Cm on|off
Let the prefix to be added to have on-link or off-link nature
-for the assigned interface. If
+for the assigned interface.
+If
.Cm on
-is specified, the prefix have on-link nature. (e.g. the prefix
-belong to the link) If
+is specified, the prefix have on-link nature
+(e.g. the prefix
+belong to the link).
+If
.Cm off
-is specified, the prefix have off-link nature. (e.g. the
-prefix does not belong to the link)
+is specified, the prefix have off-link nature
+(e.g. the
+prefix does not belong to the link).
.It Cm raf_auto Cm on|off
Enable or disable the autonomous address auto configuration
-for the prefix to be added. If
+for the prefix to be added.
+If
.Cm on
is specified, autonomous address auto configuration is
-enabled. If
+enabled.
+If
.Cm off
is specified, it is disabled.
.It Cm rrf_decrprefd Cm on|off
-Enable or disable the decrementation of the pltime. If
+Enable or disable the decrementation of the pltime.
+If
.Cm on
-is specified, decrementation of the pltime is enabled. If
+is specified, decrementation of the pltime is enabled.
+If
.Cm off
is specified, decrementation of the pltime is disabled.
.It Cm rrf_decrvalid Cm on|off
-Enable or disable the decrementation of the vltime. If
+Enable or disable the decrementation of the vltime.
+If
.Cm on
-is specified, decrementation of the vltime is enabled. If
+is specified, decrementation of the vltime is enabled.
+If
.Cm off
is specified, decrementation of the vltime is disabled.
.El
.\"
.It seqnum Ar seqnum-val { Ar rrenum-cmd } ;
Specifies contents of sending router renumbering message with some
-specific seqnum. Multiple of this statement can be specified if they
+specific seqnum.
+Multiple of this statement can be specified if they
have different
.Ar seqnum-val
each other.
@@ -234,19 +270,20 @@ has just same syntax with above add|change|setglobal statement.
.Sh EXAMPLES
For each configuration file example shown below, we suppose
every IPv6 subnet has its own prefix beginning with
-fec0:0:0::/48 and with its own subnet number. (in this case,
-subnet number is 7th and 8th octet value of the prefix)
+fec0:0:0::/48 and with its own subnet number
+(in this case,
+subnet number is 7th and 8th octet value of the prefix).
.Pp
-If you want to assigne prefixes beginning with fec0:1:1::/48
+If you want to assign prefixes beginning with 3ffe:501:ffff::/48
to each subnet, then following configuration will be enough,
if each of your routers supports IPv6 multicast forwarding.
The subnet number of the existing fec0:0:0::/48 prefix and the
-newly assigned fec0:1:1::/48 prefix will be same.
+newly assigned 3ffe:501:ffff::/48 prefix will be same.
.\"
.Bd -literal -offset indent
dest ff05::2;
-add match-prefix fec0:0:0:: /48 use-prefix fec0:1:1:: /48 keeplen 16;
+add match-prefix fec0:0:0:: /48 use-prefix 3ffe:501:ffff:: /48 keeplen 16;
.Ed
.Pp
.\"
@@ -258,20 +295,21 @@ command.
.Bd -literal -offset indent
dest fec0:0:0:1:260:8ff:fe24:fb3a fec0:0:0:2:200:eff:fe2e:dfe1 fec0:0:0:3:5254:ff:fedc:5217;
-add match-prefix fec0:0:0:: /48 use-prefix fec0:1:1:: /48 keeplen 16;
+add match-prefix fec0:0:0:: /48 use-prefix 3ffe:501:ffff:: /48 keeplen 16;
.Ed
.Pp
.\"
If you are going to do renumbering, then following procedure will be natural.
.Bl -enum -offset indent
.It
-Assigne new prefix.
+Assign a new prefix.
.It
Set old prefix lifetimes to some appropriate transition
-period. In the followng example we use 1 week for valid
+period.
+In the followng example we use 1 week for valid
lifetime, and 0 for preferred lifetime.
-Also, enable old prefix lifetime expiration.
-(By default, it is static and does not expire)
+Also, enable old prefix lifetime expiration
+(By default, it is static and does not expire).
.It
After the transition period, old prefixes should become
invalid, and may have been deleted.
@@ -287,23 +325,24 @@ The following configuration file will do 1 and 2.
dest ff05::2;
seqnum 0 {
- add match-prefix fec0:0:0:: /48 use-prefix fec0:2:2:: /48 keeplen 16;
+ add match-prefix fec0:0:0:: /48 use-prefix 3ffe:501:fffe:: /48 keeplen 16;
};
seqnum 1 {
- change match-prefix fec0:1:1:: /48 use-prefix fec0:1:1:: /48 keeplen 16 vltime d7 pltime 0 rrf_decrvalid on rrf_decrprefd on;
+ change match-prefix 3ffe:501:ffff:: /48 use-prefix 3ffe:501:ffff:: /48 keeplen 16 vltime d7 pltime 0 rrf_decrvalid on rrf_decrprefd on;
};
.Ed
.Pp
.\"
-And the following configuration file will do 3. (should be
+And the following configuration file will do 3
+(should be
used for the router renumbering message to be sent 1 week
-afterward)
+afterward).
.\"
.Bd -literal -offset indent
dest ff05::2;
-change match-prefix fec0:1:1:: /48;
+change match-prefix 3ffe:501:ffff:: /48;
.Ed
.Pp
.\"
@@ -319,7 +358,7 @@ command is almost same with
.Cm change
command except that it deletes all pre-defined IPv6 global address.
.Sh SEE ALSO
-.Xr rrenumd 8
+.Xr rrenumd 8 ,
.Xr prefix 8
.Sh HISTORY
The
diff --git a/usr.sbin/rrenumd/rrenumd.h b/usr.sbin/rrenumd/rrenumd.h
index 4854cb4..df0280b 100644
--- a/usr.sbin/rrenumd/rrenumd.h
+++ b/usr.sbin/rrenumd/rrenumd.h
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: rrenumd.h,v 1.2 2000/07/03 02:54:09 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
diff --git a/usr.sbin/rtadvd/advcap.c b/usr.sbin/rtadvd/advcap.c
index 55a43ce..5cba1f5 100644
--- a/usr.sbin/rtadvd/advcap.c
+++ b/usr.sbin/rtadvd/advcap.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: advcap.c,v 1.3 2000/05/16 13:34:13 itojun Exp $ */
+/* $KAME: advcap.c,v 1.5 2001/02/01 09:12:08 jinmei Exp $ */
/*
* Copyright (c) 1983 The Regents of the University of California.
@@ -96,7 +96,7 @@ int getent __P((char *, char *, char *));
int tnchktc __P((void));
int tnamatch __P((char *));
static char *tskip __P((char *));
-int tgetnum __P((char *));
+long long tgetnum __P((char *));
int tgetflag __P((char *));
char *tgetstr __P((char *, char **));
static char *tdecode __P((char *, char **));
@@ -307,11 +307,11 @@ breakbreak:
* a # character. If the option is not found we return -1.
* Note that we handle octal numbers beginning with 0.
*/
-int
+long long
tgetnum(id)
char *id;
{
- register long int i;
+ register long long i;
register int base;
register char *bp = tbuf;
diff --git a/usr.sbin/rtadvd/advcap.h b/usr.sbin/rtadvd/advcap.h
index dc3f428..7b3715a 100644
--- a/usr.sbin/rtadvd/advcap.h
+++ b/usr.sbin/rtadvd/advcap.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME$ */
+/* $KAME: advcap.h,v 1.3 2001/02/01 09:12:08 jinmei Exp $ */
/*
* Copyright (C) 1994,1995 by Andrey A. Chernov, Moscow, Russia.
@@ -38,7 +38,7 @@ __BEGIN_DECLS
extern int agetent __P((char *, const char *));
extern int agetflag __P((const char *));
-extern int agetnum __P((const char *));
+extern long long agetnum __P((const char *));
extern char *agetstr __P((const char *, char **));
__END_DECLS
diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c
index ec294f1..01cfb4c 100644
--- a/usr.sbin/rtadvd/config.c
+++ b/usr.sbin/rtadvd/config.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: config.c,v 1.11 2000/05/16 13:34:13 itojun Exp $ */
+/* $KAME: config.c,v 1.37 2001/05/25 07:34:00 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
@@ -34,6 +34,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
@@ -62,6 +63,7 @@
#include <search.h>
#endif
#include <unistd.h>
+#include <ifaddrs.h>
#include "rtadvd.h"
#include "advcap.h"
@@ -71,6 +73,7 @@
static void makeentry __P((char *, int, char *, int));
static void get_prefix __P((struct rainfo *));
+static int getinet6sysctl __P((int));
extern struct rainfo *ralist;
@@ -82,9 +85,11 @@ getconfig(intface)
char tbuf[BUFSIZ];
struct rainfo *tmp;
long val;
+ long long val64;
char buf[BUFSIZ];
char *bp = buf;
char *addr;
+ static int forwarding = -1;
#define MUSTHAVE(var, cap) \
do { \
@@ -114,6 +119,13 @@ getconfig(intface)
tmp = (struct rainfo *)malloc(sizeof(*ralist));
memset(tmp, 0, sizeof(*tmp));
tmp->prefix.next = tmp->prefix.prev = &tmp->prefix;
+ tmp->route.next = tmp->route.prev = &tmp->route;
+
+ /* check if we are allowed to forward packets (if not determined) */
+ if (forwarding < 0) {
+ if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0)
+ exit(1);
+ }
/* get interface information */
if (agetflag("nolladdr"))
@@ -164,12 +176,22 @@ getconfig(intface)
tmp->hoplimit = val & 0xff;
MAYHAVE(val, "raflags", 0);
- tmp->managedflg= val & ND_RA_FLAG_MANAGED;
+ tmp->managedflg = val & ND_RA_FLAG_MANAGED;
tmp->otherflg = val & ND_RA_FLAG_OTHER;
#ifdef MIP6
if (mobileip6)
tmp->haflg = val & ND_RA_FLAG_HA;
#endif
+#ifndef ND_RA_FLAG_RTPREF_MASK
+#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
+#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */
+#endif
+ tmp->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+ if (tmp->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+ syslog(LOG_ERR, "<%s> invalid router preference on %s",
+ __FUNCTION__, intface);
+ exit(1);
+ }
MAYHAVE(val, "rltime", tmp->maxinterval * 3);
if (val && (val < tmp->maxinterval || val > MAXROUTERLIFETIME)) {
@@ -180,6 +202,21 @@ getconfig(intface)
tmp->maxinterval, MAXROUTERLIFETIME);
exit(1);
}
+ /*
+ * Basically, hosts MUST NOT send Router Advertisement messages at any
+ * time (RFC 2461, Section 6.2.3). However, it would sometimes be
+ * useful to allow hosts to advertise some parameters such as prefix
+ * information and link MTU. Thus, we allow hosts to invoke rtadvd
+ * only when router lifetime (on every advertising interface) is
+ * explicitly set zero. (see also the above section)
+ */
+ if (val && forwarding == 0) {
+ syslog(LOG_WARNING,
+ "<%s> non zero router lifetime is specified for %s, "
+ "which must not be allowed for hosts.",
+ __FUNCTION__, intface);
+ exit(1);
+ }
tmp->lifetime = val & 0xffff;
MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME);
@@ -191,20 +228,23 @@ getconfig(intface)
}
tmp->reachabletime = (u_int32_t)val;
- MAYHAVE(val, "retrans", DEF_ADVRETRANSTIMER);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> retrans time out of range", __FUNCTION__);
exit(1);
}
- tmp->retranstimer = (u_int32_t)val;
+ tmp->retranstimer = (u_int32_t)val64;
-#ifdef MIP6
- if (!mobileip6)
+#ifndef MIP6
+ if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) {
+ syslog(LOG_ERR,
+ "<%s> mobile-ip6 configuration not supported",
+ __FUNCTION__);
+ exit(1);
+ }
#else
- if (1)
-#endif
- {
+ if (!mobileip6) {
if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) {
syslog(LOG_ERR,
"<%s> mobile-ip6 configuration without "
@@ -212,9 +252,7 @@ getconfig(intface)
__FUNCTION__);
exit(1);
}
- }
-#ifdef MIP6
- else {
+ } else {
tmp->hapref = 0;
if ((val = agetnum("hapref")) >= 0)
tmp->hapref = (int16_t)val;
@@ -233,6 +271,15 @@ getconfig(intface)
#endif
/* prefix information */
+
+ /*
+ * This is an implementation specific parameter to consinder
+ * link propagation delays and poorly synchronized clocks when
+ * checking consistency of advertised lifetimes.
+ */
+ MAYHAVE(val, "clockskew", 0);
+ tmp->clockskew = val;
+
if ((pfxs = agetnum("addrs")) < 0) {
/* auto configure prefix information */
if (agetstr("addr", &bp) || agetstr("addr1", &bp)) {
@@ -281,7 +328,7 @@ getconfig(intface)
{
MAYHAVE(val, entbuf,
(ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO|
- ND_OPT_PI_FLAG_RTADDR));
+ ND_OPT_PI_FLAG_ROUTER));
} else
#endif
{
@@ -291,29 +338,44 @@ getconfig(intface)
pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK;
pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO;
#ifdef MIP6
- if (mobileip6)
- pfx->routeraddr = val & ND_OPT_PI_FLAG_RTADDR;
+ pfx->routeraddr = val & ND_OPT_PI_FLAG_ROUTER;
#endif
makeentry(entbuf, i, "vltime", added);
- MAYHAVE(val, entbuf, DEF_ADVVALIDLIFETIME);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> vltime out of range",
__FUNCTION__);
exit(1);
}
- pfx->validlifetime = (u_int32_t)val;
+ pfx->validlifetime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "vltimedecr", added);
+ if (agetflag(entbuf)) {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ pfx->vltimeexpire =
+ now.tv_sec + pfx->validlifetime;
+ }
makeentry(entbuf, i, "pltime", added);
- MAYHAVE(val, entbuf, DEF_ADVPREFERREDLIFETIME);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> pltime out of range",
__FUNCTION__);
exit(1);
}
- pfx->preflifetime = (u_int32_t)val;
+ pfx->preflifetime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "pltimedecr", added);
+ if (agetflag(entbuf)) {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ pfx->pltimeexpire =
+ now.tv_sec + pfx->preflifetime;
+ }
makeentry(entbuf, i, "addr", added);
addr = (char *)agetstr(entbuf, &bp);
@@ -368,6 +430,106 @@ getconfig(intface)
exit(1);
}
+ /* route information */
+
+ MAYHAVE(val, "routes", 0);
+ if (val < 0 || val > 0xffffffff) {
+ syslog(LOG_ERR,
+ "<%s> number of route information improper", __FUNCTION__);
+ exit(1);
+ }
+ tmp->routes = val;
+ for (i = 0; i < tmp->routes; i++) {
+ struct rtinfo *rti;
+ char entbuf[256];
+ int added = (tmp->routes > 1) ? 1 : 0;
+
+ /* allocate memory to store prefix information */
+ if ((rti = malloc(sizeof(struct rtinfo))) == NULL) {
+ syslog(LOG_ERR,
+ "<%s> can't allocate enough memory",
+ __FUNCTION__);
+ exit(1);
+ }
+ memset(rti, 0, sizeof(*rti));
+
+ /* link into chain */
+ insque(rti, &tmp->route);
+
+ makeentry(entbuf, i, "rtrplen", added);
+ MAYHAVE(val, entbuf, 64);
+ if (val < 0 || val > 128) {
+ syslog(LOG_ERR,
+ "<%s> prefixlen out of range",
+ __FUNCTION__);
+ exit(1);
+ }
+ rti->prefixlen = (int)val;
+
+ makeentry(entbuf, i, "rtrflags", added);
+ MAYHAVE(val, entbuf, 0);
+ rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+ if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+ syslog(LOG_ERR, "<%s> invalid router preference",
+ __FUNCTION__);
+ exit(1);
+ }
+
+ makeentry(entbuf, i, "rtrltime", added);
+ /*
+ * XXX: since default value of route lifetime is not defined in
+ * draft-draves-route-selection-01.txt, I took the default
+ * value of valid lifetime of prefix as its default.
+ * It need be much considered.
+ */
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
+ syslog(LOG_ERR,
+ "<%s> rtrltime out of range",
+ __FUNCTION__);
+ exit(1);
+ }
+ rti->ltime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "rtrprefix", added);
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL) {
+ syslog(LOG_ERR,
+ "<%s> need %s as an route for "
+ "interface %s",
+ __FUNCTION__, entbuf, intface);
+ exit(1);
+ }
+ if (inet_pton(AF_INET6, addr, &rti->prefix) != 1) {
+ syslog(LOG_ERR,
+ "<%s> inet_pton failed for %s",
+ __FUNCTION__, addr);
+ exit(1);
+ }
+#if 0
+ /*
+ * XXX: currently there's no restriction in route information
+ * prefix according to draft-draves-route-selection-01.txt,
+ * however I think the similar restriction be necessary.
+ */
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (IN6_IS_ADDR_MULTICAST(&rti->prefix)) {
+ syslog(LOG_ERR,
+ "<%s> multicast route (%s) must "
+ "not be advertised (IF=%s)",
+ __FUNCTION__, addr, intface);
+ exit(1);
+ }
+ if (IN6_IS_ADDR_LINKLOCAL(&rti->prefix)) {
+ syslog(LOG_NOTICE,
+ "<%s> link-local route (%s) must "
+ "not be advertised on %s",
+ __FUNCTION__, addr, intface);
+ exit(1);
+ }
+#endif
+ }
+
/* okey */
tmp->next = ralist;
ralist = tmp;
@@ -385,33 +547,26 @@ getconfig(intface)
static void
get_prefix(struct rainfo *rai)
{
- size_t len;
- u_char *buf, *lim, *next;
+ struct ifaddrs *ifap, *ifa;
+ struct prefix *pp;
+ struct in6_addr *a;
+ u_char *p, *ep, *m, *lim;
u_char ntopbuf[INET6_ADDRSTRLEN];
- if ((len = rtbuf_len()) < 0) {
+ if (getifaddrs(&ifap) < 0) {
syslog(LOG_ERR,
- "<%s> can't get buffer length for routing info",
+ "<%s> can't get interface addresses",
__FUNCTION__);
exit(1);
}
- if ((buf = malloc(len)) == NULL) {
- syslog(LOG_ERR,
- "<%s> can't allocate buffer", __FUNCTION__);
- exit(1);
- }
- if (get_rtinfo(buf, &len) < 0) {
- syslog(LOG_ERR,
- "<%s> can't get routing inforamtion", __FUNCTION__);
- exit(1);
- }
-
- lim = buf + len;
- next = get_next_msg(buf, lim, rai->ifindex, &len,
- RTADV_TYPE2BITMASK(RTM_GET));
- while (next < lim) {
- struct prefix *pp;
- struct in6_addr *a;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (strcmp(ifa->ifa_name, rai->ifname) != 0)
+ continue;
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+ if (IN6_IS_ADDR_LINKLOCAL(a))
+ continue;
/* allocate memory to store prefix info. */
if ((pp = malloc(sizeof(*pp))) == NULL) {
@@ -422,21 +577,35 @@ get_prefix(struct rainfo *rai)
}
memset(pp, 0, sizeof(*pp));
- /* set prefix and its length */
- a = get_addr(next);
- memcpy(&pp->prefix, a, sizeof(*a));
- if ((pp->prefixlen = get_prefixlen(next)) < 0) {
+ /* set prefix length */
+ m = (u_char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
+ lim = (u_char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len;
+ pp->prefixlen = prefixlen(m, lim);
+ if (pp->prefixlen < 0 || pp->prefixlen > 128) {
syslog(LOG_ERR,
"<%s> failed to get prefixlen "
- "or prefixl is invalid",
+ "or prefix is invalid",
__FUNCTION__);
exit(1);
}
+
+ /* set prefix, sweep bits outside of prefixlen */
+ memcpy(&pp->prefix, a, sizeof(*a));
+ p = (u_char *)&pp->prefix;
+ ep = (u_char *)(&pp->prefix + 1);
+ while (m < lim)
+ *p++ &= *m++;
+ while (p < ep)
+ *p++ = 0x00;
+
+ if (!inet_ntop(AF_INET6, &pp->prefix, ntopbuf,
+ sizeof(ntopbuf))) {
+ syslog(LOG_ERR, "<%s> inet_ntop failed", __FUNCTION__);
+ exit(1);
+ }
syslog(LOG_DEBUG,
"<%s> add %s/%d to prefix list on %s",
- __FUNCTION__,
- inet_ntop(AF_INET6, a, ntopbuf, INET6_ADDRSTRLEN),
- pp->prefixlen, rai->ifname);
+ __FUNCTION__, ntopbuf, pp->prefixlen, rai->ifname);
/* set other fields with protocol defaults */
pp->validlifetime = DEF_ADVVALIDLIFETIME;
@@ -450,14 +619,9 @@ get_prefix(struct rainfo *rai)
/* counter increment */
rai->pfxs++;
-
- /* forward pointer and get next prefix(if any) */
- next += len;
- next = get_next_msg(next, lim, rai->ifindex,
- &len, RTADV_TYPE2BITMASK(RTM_GET));
}
- free(buf);
+ freeifaddrs(ifap);
}
static void
@@ -493,6 +657,7 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
__FUNCTION__);
return; /* XXX: error or exit? */
}
+ memset(prefix, 0, sizeof(*prefix));
prefix->prefix = ipr->ipr_prefix.sin6_addr;
prefix->prefixlen = ipr->ipr_plen;
prefix->validlifetime = ipr->ipr_vltime;
@@ -510,7 +675,7 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
/* free the previous packet */
free(rai->ra_data);
- rai->ra_data = 0;
+ rai->ra_data = NULL;
/* reconstruct the packet */
rai->pfxs++;
@@ -617,10 +782,12 @@ make_packet(struct rainfo *rainfo)
struct nd_opt_prefix_info *ndopt_pi;
struct nd_opt_mtu *ndopt_mtu;
#ifdef MIP6
- struct nd_opt_advint *ndopt_advint;
- struct nd_opt_hai *ndopt_hai;
+ struct nd_opt_advinterval *ndopt_advint;
+ struct nd_opt_homeagent_info *ndopt_hai;
#endif
+ struct nd_opt_route_info *ndopt_rti;
struct prefix *pfx;
+ struct rtinfo *rti;
/* calculate total length */
packlen = sizeof(struct nd_router_advert);
@@ -641,9 +808,14 @@ make_packet(struct rainfo *rainfo)
packlen += sizeof(struct nd_opt_mtu);
#ifdef MIP6
if (mobileip6 && rainfo->maxinterval)
- packlen += sizeof(struct nd_opt_advint);
+ packlen += sizeof(struct nd_opt_advinterval);
if (mobileip6 && rainfo->hatime)
- packlen += sizeof(struct nd_opt_hai);
+ packlen += sizeof(struct nd_opt_homeagent_info);
+#endif
+#ifdef ND_OPT_ROUTE_INFO
+ for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next)
+ packlen += sizeof(struct nd_opt_route_info) +
+ ((rti->prefixlen + 0x3f) >> 6) * 8;
#endif
/* allocate memory for the packet */
@@ -653,6 +825,11 @@ make_packet(struct rainfo *rainfo)
__FUNCTION__);
exit(1);
}
+ if (rainfo->ra_data) {
+ /* free the previous packet */
+ free(rainfo->ra_data);
+ rainfo->ra_data = NULL;
+ }
rainfo->ra_data = buf;
/* XXX: what if packlen > 576? */
rainfo->ra_datalen = packlen;
@@ -665,7 +842,12 @@ make_packet(struct rainfo *rainfo)
ra->nd_ra_code = 0;
ra->nd_ra_cksum = 0;
ra->nd_ra_curhoplimit = (u_int8_t)(0xff & rainfo->hoplimit);
- ra->nd_ra_flags_reserved = 0;
+ ra->nd_ra_flags_reserved = 0; /* just in case */
+ /*
+ * XXX: the router preference field, which is a 2-bit field, should be
+ * initialized before other fields.
+ */
+ ra->nd_ra_flags_reserved = 0xff & rainfo->rtpref;
ra->nd_ra_flags_reserved |=
rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0;
ra->nd_ra_flags_reserved |=
@@ -689,36 +871,39 @@ make_packet(struct rainfo *rainfo)
ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
ndopt_mtu->nd_opt_mtu_len = 1;
ndopt_mtu->nd_opt_mtu_reserved = 0;
- ndopt_mtu->nd_opt_mtu_mtu = ntohl(rainfo->linkmtu);
+ ndopt_mtu->nd_opt_mtu_mtu = htonl(rainfo->linkmtu);
buf += sizeof(struct nd_opt_mtu);
}
#ifdef MIP6
if (mobileip6 && rainfo->maxinterval) {
- ndopt_advint = (struct nd_opt_advint *)buf;
- ndopt_advint->nd_opt_int_type = ND_OPT_ADV_INTERVAL;
- ndopt_advint->nd_opt_int_len = 1;
- ndopt_advint->nd_opt_int_reserved = 0;
- ndopt_advint->nd_opt_int_interval = ntohl(rainfo->maxinterval *
+ ndopt_advint = (struct nd_opt_advinterval *)buf;
+ ndopt_advint->nd_opt_adv_type = ND_OPT_ADVINTERVAL;
+ ndopt_advint->nd_opt_adv_len = 1;
+ ndopt_advint->nd_opt_adv_reserved = 0;
+ ndopt_advint->nd_opt_adv_interval = htonl(rainfo->maxinterval *
1000);
- buf += sizeof(struct nd_opt_advint);
+ buf += sizeof(struct nd_opt_advinterval);
}
#endif
#ifdef MIP6
if (rainfo->hatime) {
- ndopt_hai = (struct nd_opt_hai *)buf;
- ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
+ ndopt_hai = (struct nd_opt_homeagent_info *)buf;
+ ndopt_hai->nd_opt_hai_type = ND_OPT_HOMEAGENT_INFO;
ndopt_hai->nd_opt_hai_len = 1;
ndopt_hai->nd_opt_hai_reserved = 0;
- ndopt_hai->nd_opt_hai_pref = ntohs(rainfo->hapref);
- ndopt_hai->nd_opt_hai_lifetime = ntohs(rainfo->hatime);
- buf += sizeof(struct nd_opt_hai);
+ ndopt_hai->nd_opt_hai_preference = htons(rainfo->hapref);
+ ndopt_hai->nd_opt_hai_lifetime = htons(rainfo->hatime);
+ buf += sizeof(struct nd_opt_homeagent_info);
}
#endif
for (pfx = rainfo->prefix.next;
pfx != &rainfo->prefix; pfx = pfx->next) {
+ u_int32_t vltime, pltime;
+ struct timeval now;
+
ndopt_pi = (struct nd_opt_prefix_info *)buf;
ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
ndopt_pi->nd_opt_pi_len = 4;
@@ -733,16 +918,69 @@ make_packet(struct rainfo *rainfo)
#ifdef MIP6
if (pfx->routeraddr)
ndopt_pi->nd_opt_pi_flags_reserved |=
- ND_OPT_PI_FLAG_RTADDR;
+ ND_OPT_PI_FLAG_ROUTER;
#endif
- ndopt_pi->nd_opt_pi_valid_time = ntohl(pfx->validlifetime);
- ndopt_pi->nd_opt_pi_preferred_time =
- ntohl(pfx->preflifetime);
+ if (pfx->vltimeexpire || pfx->pltimeexpire)
+ gettimeofday(&now, NULL);
+ if (pfx->vltimeexpire == 0)
+ vltime = pfx->validlifetime;
+ else
+ vltime = (pfx->vltimeexpire > now.tv_sec) ?
+ pfx->vltimeexpire - now.tv_sec : 0;
+ if (pfx->pltimeexpire == 0)
+ pltime = pfx->preflifetime;
+ else
+ pltime = (pfx->pltimeexpire > now.tv_sec) ?
+ pfx->pltimeexpire - now.tv_sec : 0;
+ if (vltime < pltime) {
+ /*
+ * this can happen if vltime is decrement but pltime
+ * is not.
+ */
+ pltime = vltime;
+ }
+ ndopt_pi->nd_opt_pi_valid_time = htonl(vltime);
+ ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime);
ndopt_pi->nd_opt_pi_reserved2 = 0;
ndopt_pi->nd_opt_pi_prefix = pfx->prefix;
buf += sizeof(struct nd_opt_prefix_info);
}
+#ifdef ND_OPT_ROUTE_INFO
+ for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next) {
+ u_int8_t psize = (rti->prefixlen + 0x3f) >> 6;
+
+ ndopt_rti = (struct nd_opt_route_info *)buf;
+ ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO;
+ ndopt_rti->nd_opt_rti_len = 1 + psize;
+ ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen;
+ ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref;
+ ndopt_rti->nd_opt_rti_lifetime = rti->ltime;
+ memcpy(ndopt_rti + 1, &rti->prefix, psize * 8);
+ buf += sizeof(struct nd_opt_route_info) + psize * 8;
+ }
+#endif
+
return;
}
+
+static int
+getinet6sysctl(int code)
+{
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
+ int value;
+ size_t size;
+
+ mib[3] = code;
+ size = sizeof(value);
+ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0)
+ < 0) {
+ syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s",
+ __FUNCTION__, code,
+ strerror(errno));
+ return(-1);
+ }
+ else
+ return(value);
+}
diff --git a/usr.sbin/rtadvd/config.h b/usr.sbin/rtadvd/config.h
index f08a702..9000461 100644
--- a/usr.sbin/rtadvd/config.h
+++ b/usr.sbin/rtadvd/config.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME$ */
+/* $KAME: config.h,v 1.3 2000/05/16 13:34:13 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
diff --git a/usr.sbin/rtadvd/dump.c b/usr.sbin/rtadvd/dump.c
index 4b2801d..4e4be1a 100644
--- a/usr.sbin/rtadvd/dump.c
+++ b/usr.sbin/rtadvd/dump.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: dump.c,v 1.10 2000/05/23 11:31:25 itojun Exp $ */
+/* $KAME: dump.c,v 1.16 2001/03/21 17:41:13 jinmei Exp $ */
/*
* Copyright (C) 2000 WIDE Project.
@@ -31,6 +31,7 @@
*/
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/queue.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
@@ -71,6 +72,13 @@ static void if_dump __P((void));
#define LONGLONG "%llu"
#endif
+static char *rtpref_str[] = {
+ "medium", /* 00 */
+ "high", /* 01 */
+ "rsv", /* 10 */
+ "low" /* 11 */
+};
+
static char *
ether_str(sdl)
struct sockaddr_dl *sdl;
@@ -97,7 +105,9 @@ if_dump()
struct prefix *pfx;
char prefixbuf[INET6_ADDRSTRLEN];
int first;
+ struct timeval now;
+ gettimeofday(&now, NULL); /* XXX: unused in most cases */
for (rai = ralist; rai; rai = rai->next) {
fprintf(fp, "%s:\n", rai->ifname);
@@ -141,12 +151,15 @@ if_dump()
" DefaultLifetime: %d, MaxAdvInterval: %d, "
"MinAdvInterval: %d\n",
rai->lifetime, rai->maxinterval, rai->mininterval);
- fprintf(fp, " Flags: %s%s%s MTU: %d\n",
+ fprintf(fp, " Flags: %s%s%s, ",
rai->managedflg ? "M" : "", rai->otherflg ? "O" : "",
#ifdef MIP6
rai->haflg ? "H" :
#endif
- "", rai->linkmtu);
+ "");
+ fprintf(fp, "Preference: %s, ",
+ rtpref_str[(rai->rtpref >> 3) & 0xff]);
+ fprintf(fp, "MTU: %d\n", rai->linkmtu);
fprintf(fp, " ReachableTime: %d, RetransTimer: %d, "
"CurHopLimit: %d\n", rai->reachabletime,
rai->retranstimer, rai->hoplimit);
@@ -155,6 +168,9 @@ if_dump()
rai->hapref, rai->hatime);
#endif
+ if (rai->clockskew)
+ fprintf(fp, " Clock skew: %ldsec\n",
+ rai->clockskew);
for (first = 1, pfx = rai->prefix.next; pfx != &rai->prefix;
pfx = pfx->next) {
if (first) {
@@ -177,15 +193,27 @@ if_dump()
break;
}
if (pfx->validlifetime == ND6_INFINITE_LIFETIME)
- fprintf(fp, "vltime: infinity, ");
+ fprintf(fp, "vltime: infinity");
else
- fprintf(fp, "vltime: %ld, ",
+ fprintf(fp, "vltime: %ld",
(long)pfx->validlifetime);
+ if (pfx->vltimeexpire != 0)
+ fprintf(fp, "(decr,expire %ld), ", (long)
+ pfx->vltimeexpire > now.tv_sec ?
+ pfx->vltimeexpire - now.tv_sec : 0);
+ else
+ fprintf(fp, ", ");
if (pfx->preflifetime == ND6_INFINITE_LIFETIME)
- fprintf(fp, "pltime: infinity, ");
+ fprintf(fp, "pltime: infinity");
else
- fprintf(fp, "pltime: %ld, ",
+ fprintf(fp, "pltime: %ld",
(long)pfx->preflifetime);
+ if (pfx->pltimeexpire != 0)
+ fprintf(fp, "(decr,expire %ld), ", (long)
+ pfx->pltimeexpire > now.tv_sec ?
+ pfx->pltimeexpire - now.tv_sec : 0);
+ else
+ fprintf(fp, ", ");
fprintf(fp, "flags: %s%s%s",
pfx->onlinkflg ? "L" : "",
pfx->autoconfflg ? "A" : "",
diff --git a/usr.sbin/rtadvd/dump.h b/usr.sbin/rtadvd/dump.h
index 03dff70..cc3b472 100644
--- a/usr.sbin/rtadvd/dump.h
+++ b/usr.sbin/rtadvd/dump.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME$ */
+/* $KAME: dump.h,v 1.1 2000/05/23 11:31:26 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
diff --git a/usr.sbin/rtadvd/if.c b/usr.sbin/rtadvd/if.c
index b77f472..c6aa2e6 100644
--- a/usr.sbin/rtadvd/if.c
+++ b/usr.sbin/rtadvd/if.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: if.c,v 1.14 2000/10/25 04:28:34 jinmei Exp $ */
+/* $KAME: if.c,v 1.17 2001/01/21 15:27:30 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -259,17 +259,6 @@ rtbuf_len()
return(len);
}
-int
-get_rtinfo(char *buf, size_t *len)
-{
- int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET6, NET_RT_DUMP, 0};
-
- if (sysctl(mib, 6, buf, len, NULL, 0) < 0)
- return(-1);
-
- return(0);
-}
-
#define FILTER_MATCH(type, filter) ((0x1 << type) & filter)
#define SIN6(s) ((struct sockaddr_in6 *)(s))
#define SDL(s) ((struct sockaddr_dl *)(s))
@@ -357,7 +346,7 @@ get_next_msg(char *buf, char *lim, int ifindex, size_t *lenp, int filter)
return (char *)rtm;
}
-#undef FILTER_MATCH(type, filter)
+#undef FILTER_MATCH
struct in6_addr *
get_addr(char *buf)
diff --git a/usr.sbin/rtadvd/if.h b/usr.sbin/rtadvd/if.h
index f91e8d4..23f9a98 100644
--- a/usr.sbin/rtadvd/if.h
+++ b/usr.sbin/rtadvd/if.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: if.h,v 1.2 2000/05/16 13:34:13 itojun Exp $ */
+/* $KAME: if.h,v 1.6 2001/01/21 15:37:14 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -37,23 +37,22 @@ extern size_t ifblock_size;
extern char *ifblock;
struct nd_opt_hdr;
-struct sockaddr_dl *if_nametosdl __P((char *name));
-int if_getmtu __P((char *name));
-int if_getflags __P((int ifindex, int oifflags));
-int lladdropt_length __P((struct sockaddr_dl *sdl));
-void lladdropt_fill __P((struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt));
+struct sockaddr_dl *if_nametosdl __P((char *));
+int if_getmtu __P((char *));
+int if_getflags __P((int, int));
+int lladdropt_length __P((struct sockaddr_dl *));
+void lladdropt_fill __P((struct sockaddr_dl *, struct nd_opt_hdr *));
int rtbuf_len __P((void));
-int get_rtinfo __P((char *buf, size_t *len));
-char *get_next_msg __P((char *buf, char *lim, int ifindex, size_t *lenp,
- int filter));
-struct in6_addr *get_addr __P((char *buf));
-int get_rtm_ifindex __P((char *buf));
-int get_ifm_ifindex __P((char *buf));
-int get_ifam_ifindex __P((char *buf));
-int get_ifm_flags __P((char *buf));
-int get_prefixlen __P((char *buf));
-int rtmsg_type __P((char *buf));
-int ifmsg_type __P((char *buf));
-int rtmsg_len __P((char *buf));
-int ifmsg_len __P((char *buf));
+char *get_next_msg __P((char *, char *, int, size_t *, int));
+struct in6_addr *get_addr __P((char *));
+int get_rtm_ifindex __P((char *));
+int get_ifm_ifindex __P((char *));
+int get_ifam_ifindex __P((char *));
+int get_ifm_flags __P((char *));
+int get_prefixlen __P((char *));
+int prefixlen __P((u_char *, u_char *));
+int rtmsg_type __P((char *));
+int ifmsg_type __P((char *));
+int rtmsg_len __P((char *));
+int ifmsg_len __P((char *));
void init_iflist __P((void));
diff --git a/usr.sbin/rtadvd/pathnames.h b/usr.sbin/rtadvd/pathnames.h
index 9c68cc4..3afee55 100644
--- a/usr.sbin/rtadvd/pathnames.h
+++ b/usr.sbin/rtadvd/pathnames.h
@@ -1,4 +1,4 @@
+/* $KAME: pathnames.h,v 1.2 2000/05/16 13:34:13 itojun Exp $ */
/* $FreeBSD$ */
-/* $KAME$ */
#define _PATH_RTADVDCONF "/etc/rtadvd.conf"
diff --git a/usr.sbin/rtadvd/rrenum.c b/usr.sbin/rtadvd/rrenum.c
index a0edf9f..a5fbe20 100644
--- a/usr.sbin/rtadvd/rrenum.c
+++ b/usr.sbin/rtadvd/rrenum.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: rrenum.c,v 1.3 2000/05/16 13:34:14 itojun Exp $ */
+/* $KAME: rrenum.c,v 1.10 2001/01/21 15:32:16 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -50,6 +50,7 @@
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
+#include "rtadvd.h"
#include "rrenum.h"
#include "if.h"
@@ -138,13 +139,17 @@ rr_pco_check(int len, struct rr_pco_match *rpm)
}
static void
-do_use_prefix(int len, struct rr_pco_match *rpm, struct in6_rrenumreq *irr) {
+do_use_prefix(int len, struct rr_pco_match *rpm,
+ struct in6_rrenumreq *irr, int ifindex)
+{
struct rr_pco_use *rpu, *rpulim;
+ struct rainfo *rai;
+ struct prefix *pp;
rpu = (struct rr_pco_use *)(rpm + 1);
rpulim = (struct rr_pco_use *)((char *)rpm + len);
- if (rpu == rpulim) {
+ if (rpu == rpulim) { /* no use prefix */
if (rpm->rpm_code == RPM_PCO_ADD)
return;
@@ -176,16 +181,16 @@ do_use_prefix(int len, struct rr_pco_match *rpm, struct in6_rrenumreq *irr) {
(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK);
irr->irr_raf_mask_auto =
(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_AUTO);
- irr->irr_vltime = rpu->rpu_vltime;
- irr->irr_pltime = rpu->rpu_pltime;
+ irr->irr_vltime = ntohl(rpu->rpu_vltime);
+ irr->irr_pltime = ntohl(rpu->rpu_pltime);
irr->irr_raf_onlink =
- (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK);
+ (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK) == 0 ? 0 : 1;
irr->irr_raf_auto =
- (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO);
+ (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO) == 0 ? 0 : 1;
irr->irr_rrf_decrvalid =
- (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME);
+ (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME) == 0 ? 0 : 1;
irr->irr_rrf_decrprefd =
- (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME);
+ (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME) == 0 ? 0 : 1;
irr->irr_useprefix.sin6_len = sizeof(irr->irr_useprefix);
irr->irr_useprefix.sin6_family = AF_INET6;
irr->irr_useprefix.sin6_addr = rpu->rpu_prefix;
@@ -194,6 +199,40 @@ do_use_prefix(int len, struct rr_pco_match *rpm, struct in6_rrenumreq *irr) {
errno != EADDRNOTAVAIL)
syslog(LOG_ERR, "<%s> ioctl: %s", __FUNCTION__,
strerror(errno));
+
+ /* very adhoc: should be rewritten */
+ if (rpm->rpm_code == RPM_PCO_CHANGE &&
+ IN6_ARE_ADDR_EQUAL(&rpm->rpm_prefix, &rpu->rpu_prefix) &&
+ rpm->rpm_matchlen == rpu->rpu_uselen &&
+ rpu->rpu_uselen == rpu->rpu_keeplen) {
+ if ((rai = if_indextorainfo(ifindex)) == NULL)
+ continue; /* non-advertising IF */
+
+ for (pp = rai->prefix.next; pp != &rai->prefix;
+ pp = pp->next) {
+ struct timeval now;
+
+ if (prefix_match(&pp->prefix, pp->prefixlen,
+ &rpm->rpm_prefix,
+ rpm->rpm_matchlen)) {
+ /* change parameters */
+ pp->validlifetime = ntohl(rpu->rpu_vltime);
+ pp->preflifetime = ntohl(rpu->rpu_pltime);
+ if (irr->irr_rrf_decrvalid) {
+ gettimeofday(&now, 0);
+ pp->vltimeexpire =
+ now.tv_sec + pp->validlifetime;
+ } else
+ pp->vltimeexpire = 0;
+ if (irr->irr_rrf_decrprefd) {
+ gettimeofday(&now, 0);
+ pp->pltimeexpire =
+ now.tv_sec + pp->preflifetime;
+ } else
+ pp->pltimeexpire = 0;
+ }
+ }
+ }
}
}
@@ -234,7 +273,7 @@ do_pco(struct icmp6_router_renum *rr, int len, struct rr_pco_match *rpm)
(iflist[ifindex]->ifm_flags & IFF_UP) == 0)
continue;
/* TODO: interface scope check */
- do_use_prefix(len, rpm, &irr);
+ do_use_prefix(len, rpm, &irr, ifindex);
}
if (errno == ENXIO)
return 0;
@@ -392,9 +431,40 @@ rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi,
inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- rr_rcvifindex = pi->ipi6_ifindex;
+ /* packet validation based on Section 4.1 of RFC2894 */
+ if (len < sizeof(struct icmp6_router_renum)) {
+ syslog(LOG_NOTICE,
+ "<%s>: RR short message (size %d) from %s to %s on %s",
+ __FUNCTION__, len,
+ inet_ntop(AF_INET6, &from->sin6_addr,
+ ntopbuf[0], INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
+ return;
+ }
- /* TODO: some consistency check. */
+ /*
+ * If the IPv6 destination address is neither an All Routers multicast
+ * address [AARCH] nor one of the receiving router's unicast addresses,
+ * the message MUST be discarded and SHOULD be logged to network
+ * management.
+ * We rely on the kernel input routine for unicast addresses, and thus
+ * check multicast destinations only.
+ */
+ if (IN6_IS_ADDR_MULTICAST(&pi->ipi6_addr) &&
+ !IN6_ARE_ADDR_EQUAL(&in6a_site_allrouters, &pi->ipi6_addr)) {
+ syslog(LOG_NOTICE,
+ "<%s>: RR message with invalid destination (%s) "
+ "from %s on %s",
+ __FUNCTION__,
+ inet_ntop(AF_INET6, &dst, ntopbuf[0], INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &from->sin6_addr,
+ ntopbuf[1], INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
+ return;
+ }
+
+ rr_rcvifindex = pi->ipi6_ifindex;
switch (rr->rr_code) {
case ICMP6_ROUTER_RENUMBERING_COMMAND:
diff --git a/usr.sbin/rtadvd/rrenum.h b/usr.sbin/rtadvd/rrenum.h
index 3ab1e7d..ce94015 100644
--- a/usr.sbin/rtadvd/rrenum.h
+++ b/usr.sbin/rtadvd/rrenum.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME$ */
+/* $KAME: rrenum.h,v 1.3 2001/01/21 15:37:14 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
@@ -30,6 +30,5 @@
* SUCH DAMAGE.
*/
-void rr_input __P((int len, struct icmp6_router_renum *rr,
- struct in6_pktinfo *pi, struct sockaddr_in6 *from,
- struct in6_addr *dst));
+void rr_input __P((int, struct icmp6_router_renum *, struct in6_pktinfo *,
+ struct sockaddr_in6 *, struct in6_addr *));
diff --git a/usr.sbin/rtadvd/rtadvd.8 b/usr.sbin/rtadvd/rtadvd.8
index 3ddc77d..dcdcdab 100644
--- a/usr.sbin/rtadvd/rtadvd.8
+++ b/usr.sbin/rtadvd/rtadvd.8
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.\" $KAME: rtadvd.8,v 1.9 2000/05/27 13:37:01 jinmei Exp $
+.\" $KAME: rtadvd.8,v 1.17 2001/02/04 05:34:38 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -36,8 +36,8 @@
.Nd router advertisement daemon
.Sh SYNOPSIS
.Nm
+.Op Fl dDfMRs
.Op Fl c Ar configfile
-.Op Fl dDfRs
.Ar interface ...
.Sh DESCRIPTION
.Nm
@@ -77,6 +77,15 @@ Moreover, if the status of an advertising interface changes,
will start or stop sending router advertisements according
to the latest status.
.Pp
+Basically, hosts MUST NOT send Router Advertisement messages at any
+time (RFC 2461, Section 6.2.3).
+However, it would sometimes be useful to allow hosts to advertise some
+parameters such as prefix information and link MTU.
+Thus,
+.Nm
+can be invoked if router lifetime is explicitly set zero on every
+advertising interface.
+.Pp
The command line options are:
.Bl -tag -width indent
.\"
@@ -93,6 +102,15 @@ Print debugging information.
Even more debugging information is printed.
.It Fl f
Foreground mode (useful when debugging).
+.It Fl M
+Specify an interface to join the all-routers site-local multicast group.
+By default,
+.Nm
+tries to join the first advertising interface appeared in the command
+line.
+This option has meaning only with the
+.Fl R
+option, which enables routing renumbering protocol support.
.\".It Fl m
.\"Enables mobile IPv6 support.
.\"This changes the content of router advertisement option, as well as
@@ -100,6 +118,12 @@ Foreground mode (useful when debugging).
.It Fl R
Accept router renumbering requests.
If you enable it, certain IPsec setup is suggested for security reasons.
+On KAME-based systems,
+.Xr rrenumd 8
+generates router renumbering request packets.
+This option is currently disabled, and is ignored by
+.Nm
+with a warning message.
.It Fl s
Do not add or delete prefixes dynamically.
Only statically configured prefixes, if any, will be advertised.
@@ -138,17 +162,20 @@ in which
dumps its internal state.
.El
.Sh SEE ALSO
-.Xr daemon 3 ,
.Xr rtadvd.conf 5 ,
-.Xr rtsol 8
+.Xr rtsol 8 ,
+.Xr rrenumd 8
.Sh HISTORY
The
.Nm
command first appeared in WIDE Hydrangea IPv6 protocol stack kit.
.Sh CAVEAT
-Router advertisements should only be performed downstream.
-Erroneous upstream advertisements will cause
+There used to be some text that recommended users not to let
+.Nm
+advertise Router Advertisement messages on an upstream link to avoid
+undesirable
.Xr icmp6 4
-redirect packet storms in the subnet, as (per the specification) the
-advertising router is assumed to become the default router for
-end hosts in the subnet.
+redirect messages.
+However, based on the later discussion in the IETF ipng working group,
+all routers should rather advertise the messages regardless of
+the network topology, in order to ensure reachability.
diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c
index 000e612..e9931df 100644
--- a/usr.sbin/rtadvd/rtadvd.c
+++ b/usr.sbin/rtadvd/rtadvd.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: rtadvd.c,v 1.30 2000/06/22 20:16:12 itojun Exp $ */
+/* $KAME: rtadvd.c,v 1.50 2001/02/04 06:15:15 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -34,6 +34,7 @@
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/time.h>
+#include <sys/queue.h>
#include <net/if.h>
#include <net/route.h>
@@ -68,14 +69,18 @@ static size_t rcvcmsgbuflen;
static u_char *sndcmsgbuf = NULL;
static size_t sndcmsgbuflen;
static int do_dump;
+static int do_die;
struct msghdr sndmhdr;
struct iovec rcviov[2];
struct iovec sndiov[2];
struct sockaddr_in6 from;
struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6};
+struct in6_addr in6a_site_allrouters;
static char *dumpfilename = "/var/run/rtadvd.dump"; /* XXX: should be configurable */
static char *pidfilename = "/var/run/rtadvd.pid"; /* should be configurable */
-int sock, rtsock;
+static char *mcastif;
+int sock;
+int rtsock = -1;
#ifdef MIP6
int mobileip6 = 0;
#endif
@@ -120,7 +125,8 @@ u_int32_t ndopt_flags[] = {
};
int main __P((int, char *[]));
-static void die __P((int));
+static void set_die __P((int));
+static void die __P((void));
static void sock_open __P((void));
static void rtsock_open __P((void));
static void rtadvd_input __P((void));
@@ -133,7 +139,6 @@ static int prefix_check __P((struct nd_opt_prefix_info *, struct rainfo *,
static int nd6_options __P((struct nd_opt_hdr *, int,
union nd_opts *, u_int32_t));
static void free_ndopts __P((union nd_opts *));
-static struct rainfo *if_indextorainfo __P((int));
static void ra_output __P((struct rainfo *));
static void rtmsg_input __P((void));
static void rtadvd_set_dump_file __P((void));
@@ -157,9 +162,9 @@ main(argc, argv)
/* get command line options and arguments */
#ifdef MIP6
-#define OPTIONS "c:dDfmRs"
+#define OPTIONS "c:dDfM:mRs"
#else
-#define OPTIONS "c:dDfRs"
+#define OPTIONS "c:dDfM:Rs"
#endif
while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
#undef OPTIONS
@@ -176,13 +181,19 @@ main(argc, argv)
case 'f':
fflag = 1;
break;
+ case 'M':
+ mcastif = optarg;
+ break;
#ifdef MIP6
case 'm':
mobileip6 = 1;
break;
#endif
case 'R':
- accept_rr = 1;
+ fprintf(stderr, "rtadvd: "
+ "the -R option is currently ignored.\n");
+ /* accept_rr = 1; */
+ /* run anyway... */
break;
case 's':
sflag = 1;
@@ -194,9 +205,9 @@ main(argc, argv)
if (argc == 0) {
fprintf(stderr,
#ifdef MIP6
- "usage: rtadvd [-dDfmRs] [-c conffile] "
+ "usage: rtadvd [-dDfMmRs] [-c conffile] "
#else
- "usage: rtadvd [-dDfRs] [-c conffile] "
+ "usage: rtadvd [-dDfMRs] [-c conffile] "
#endif
"interfaces...\n");
exit(1);
@@ -243,12 +254,15 @@ main(argc, argv)
FD_ZERO(&fdset);
FD_SET(sock, &fdset);
maxfd = sock;
- rtsock_open();
- FD_SET(rtsock, &fdset);
- if (rtsock > sock)
+ if (sflag == 0) {
+ rtsock_open();
+ FD_SET(rtsock, &fdset);
+ if (rtsock > sock)
maxfd = rtsock;
+ } else
+ rtsock = -1;
- signal(SIGTERM, (void *)die);
+ signal(SIGTERM, (void *)set_die);
signal(SIGUSR1, (void *)rtadvd_set_dump_file);
while (1) {
@@ -259,6 +273,11 @@ main(argc, argv)
rtadvd_dump_file(dumpfilename);
}
+ if (do_die) {
+ die();
+ /*NOTREACHED*/
+ }
+
/* timer expiration check and reset the timer */
timeout = rtadvd_check_timer();
@@ -285,7 +304,7 @@ main(argc, argv)
}
if (i == 0) /* timeout */
continue;
- if (sflag == 0 && FD_ISSET(rtsock, &select_fd))
+ if (rtsock != -1 && FD_ISSET(rtsock, &select_fd))
rtmsg_input();
if (FD_ISSET(sock, &select_fd))
rtadvd_input();
@@ -300,9 +319,15 @@ rtadvd_set_dump_file()
}
static void
-die(sig)
+set_die(sig)
int sig;
{
+ do_die = 1;
+}
+
+static void
+die()
+{
struct rainfo *ra;
int i;
const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS;
@@ -331,13 +356,13 @@ rtmsg_input()
int n, type, ifindex = 0, plen;
size_t len;
char msg[2048], *next, *lim;
- u_char ifname[16];
+ u_char ifname[IF_NAMESIZE];
struct prefix *prefix;
struct rainfo *rai;
struct in6_addr *addr;
char addrbuf[INET6_ADDRSTRLEN];
- n = read(rtsock, msg, 2048);
+ n = read(rtsock, msg, sizeof(msg));
if (dflag > 1) {
syslog(LOG_DEBUG,
"<%s> received a routing message "
@@ -876,8 +901,8 @@ ra_input(int len, struct nd_router_advert *ra,
memset(&ndopts, 0, sizeof(ndopts));
if (nd6_options((struct nd_opt_hdr *)(ra + 1),
len - sizeof(struct nd_router_advert),
- &ndopts,
- NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
+ &ndopts, NDOPT_FLAG_SRCLINKADDR |
+ NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
syslog(LOG_ERR,
"<%s> ND option check failed for an RA from %s on %s",
__FUNCTION__,
@@ -905,7 +930,7 @@ ra_input(int len, struct nd_router_advert *ra,
/* Cur Hop Limit value */
if (ra->nd_ra_curhoplimit && rai->hoplimit &&
ra->nd_ra_curhoplimit != rai->hoplimit) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> CurHopLimit inconsistent on %s:"
" %d from %s, %d from us",
__FUNCTION__,
@@ -919,7 +944,7 @@ ra_input(int len, struct nd_router_advert *ra,
/* M flag */
if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) !=
rai->managedflg) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> M flag inconsistent on %s:"
" %s from %s, %s from us",
__FUNCTION__,
@@ -933,7 +958,7 @@ ra_input(int len, struct nd_router_advert *ra,
/* O flag */
if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) !=
rai->otherflg) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> O flag inconsistent on %s:"
" %s from %s, %s from us",
__FUNCTION__,
@@ -948,7 +973,7 @@ ra_input(int len, struct nd_router_advert *ra,
reachabletime = ntohl(ra->nd_ra_reachable);
if (reachabletime && rai->reachabletime &&
reachabletime != rai->reachabletime) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> ReachableTime inconsistent on %s:"
" %d from %s, %d from us",
__FUNCTION__,
@@ -963,7 +988,7 @@ ra_input(int len, struct nd_router_advert *ra,
retranstimer = ntohl(ra->nd_ra_retransmit);
if (retranstimer && rai->retranstimer &&
retranstimer != rai->retranstimer) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> RetranceTimer inconsistent on %s:"
" %d from %s, %d from us",
__FUNCTION__,
@@ -978,7 +1003,7 @@ ra_input(int len, struct nd_router_advert *ra,
if (ndopts.nd_opts_mtu) {
mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
if (mtu && rai->linkmtu && mtu != rai->linkmtu) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"<%s> MTU option value inconsistent on %s:"
" %d from %s, %d from us",
__FUNCTION__,
@@ -992,7 +1017,7 @@ ra_input(int len, struct nd_router_advert *ra,
/* Preferred and Valid Lifetimes for prefixes */
{
struct nd_optlist *optp = ndopts.nd_opts_list;
-
+
if (ndopts.nd_opts_pi) {
if (prefix_check(ndopts.nd_opts_pi, rai, from))
inconsistent++;
@@ -1005,10 +1030,8 @@ ra_input(int len, struct nd_router_advert *ra,
}
}
- if (inconsistent) {
- printf("RA input %d inconsistents\n", inconsistent);
+ if (inconsistent)
rai->rainconsistent++;
- }
done:
free_ndopts(&ndopts);
@@ -1024,6 +1047,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
struct prefix *pp;
int inconsistent = 0;
u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
+ struct timeval now;
#if 0 /* impossible */
if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION)
@@ -1061,8 +1085,36 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
}
preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time);
- if (preferred_time != pp->preflifetime) {
- syslog(LOG_WARNING,
+ if (pp->pltimeexpire) {
+ /*
+ * The lifetime is decremented in real time, so we should
+ * compare the expiration time.
+ * (RFC 2461 Section 6.2.7.)
+ * XXX: can we really expect that all routers on the link
+ * have synchronized clocks?
+ */
+ gettimeofday(&now, NULL);
+ preferred_time += now.tv_sec;
+
+ if (rai->clockskew &&
+ abs(preferred_time - pp->pltimeexpire) > rai->clockskew) {
+ syslog(LOG_INFO,
+ "<%s> prefeerred lifetime for %s/%d"
+ " (decr. in real time) inconsistent on %s:"
+ " %d from %s, %ld from us",
+ __FUNCTION__,
+ inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
+ prefixbuf, INET6_ADDRSTRLEN),
+ pinfo->nd_opt_pi_prefix_len,
+ rai->ifname, preferred_time,
+ inet_ntop(AF_INET6, &from->sin6_addr,
+ ntopbuf, INET6_ADDRSTRLEN),
+ pp->pltimeexpire);
+ inconsistent++;
+ }
+ }
+ else if (preferred_time != pp->preflifetime) {
+ syslog(LOG_INFO,
"<%s> prefeerred lifetime for %s/%d"
" inconsistent on %s:"
" %d from %s, %d from us",
@@ -1074,12 +1126,32 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
inet_ntop(AF_INET6, &from->sin6_addr,
ntopbuf, INET6_ADDRSTRLEN),
pp->preflifetime);
- inconsistent++;
}
valid_time = ntohl(pinfo->nd_opt_pi_valid_time);
- if (valid_time != pp->validlifetime) {
- syslog(LOG_WARNING,
+ if (pp->vltimeexpire) {
+ gettimeofday(&now, NULL);
+ valid_time += now.tv_sec;
+
+ if (rai->clockskew &&
+ abs(valid_time - pp->vltimeexpire) > rai->clockskew) {
+ syslog(LOG_INFO,
+ "<%s> valid lifetime for %s/%d"
+ " (decr. in real time) inconsistent on %s:"
+ " %d from %s, %ld from us",
+ __FUNCTION__,
+ inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
+ prefixbuf, INET6_ADDRSTRLEN),
+ pinfo->nd_opt_pi_prefix_len,
+ rai->ifname, preferred_time,
+ inet_ntop(AF_INET6, &from->sin6_addr,
+ ntopbuf, INET6_ADDRSTRLEN),
+ pp->vltimeexpire);
+ inconsistent++;
+ }
+ }
+ else if (valid_time != pp->validlifetime) {
+ syslog(LOG_INFO,
"<%s> valid lifetime for %s/%d"
" inconsistent on %s:"
" %d from %s, %d from us",
@@ -1118,6 +1190,26 @@ find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen)
return(NULL);
}
+/* check if p0/plen0 matches p1/plen1; return 1 if matches, otherwise 0. */
+int
+prefix_match(struct in6_addr *p0, int plen0,
+ struct in6_addr *p1, int plen1)
+{
+ int bytelen, bitlen;
+
+ if (plen0 < plen1)
+ return(0);
+ bytelen = plen1 / 8;
+ bitlen = plen1 % 8;
+ if (memcmp((void *)p0, (void *)p1, bytelen))
+ return(0);
+ if (p0->s6_addr[bytelen] >> (8 - bitlen) ==
+ p1->s6_addr[bytelen] >> (8 - bitlen))
+ return(1);
+
+ return(0);
+}
+
static int
nd6_options(struct nd_opt_hdr *hdr, int limit,
union nd_opts *ndopts, u_int32_t optflags)
@@ -1276,7 +1368,7 @@ sock_open()
__FUNCTION__, strerror(errno));
exit(1);
}
-#endif
+#endif
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
@@ -1293,7 +1385,8 @@ sock_open()
/*
* join all routers multicast address on each advertising interface.
*/
- if (inet_pton(AF_INET6, ALLROUTERS, &mreq.ipv6mr_multiaddr.s6_addr)
+ if (inet_pton(AF_INET6, ALLROUTERS_LINK,
+ &mreq.ipv6mr_multiaddr.s6_addr)
!= 1) {
syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
__FUNCTION__);
@@ -1301,15 +1394,47 @@ sock_open()
}
while(ra) {
mreq.ipv6mr_interface = ra->ifindex;
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- &mreq,
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
sizeof(mreq)) < 0) {
- syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP on %s: %s",
+ syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s",
__FUNCTION__, ra->ifname, strerror(errno));
exit(1);
}
ra = ra->next;
}
+
+ /*
+ * When attending router renumbering, join all-routers site-local
+ * multicast group.
+ */
+ if (accept_rr) {
+ if (inet_pton(AF_INET6, ALLROUTERS_SITE,
+ &in6a_site_allrouters) != 1) {
+ syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
+ __FUNCTION__);
+ exit(1);
+ }
+ mreq.ipv6mr_multiaddr = in6a_site_allrouters;
+ if (mcastif) {
+ if ((mreq.ipv6mr_interface = if_nametoindex(mcastif))
+ == 0) {
+ syslog(LOG_ERR,
+ "<%s> invalid interface: %s",
+ __FUNCTION__, mcastif);
+ exit(1);
+ }
+ } else
+ mreq.ipv6mr_interface = ralist->ifindex;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ &mreq, sizeof(mreq)) < 0) {
+ syslog(LOG_ERR,
+ "<%s> IPV6_JOIN_GROUP(site) on %s: %s",
+ __FUNCTION__,
+ mcastif ? mcastif : ralist->ifname,
+ strerror(errno));
+ exit(1);
+ }
+ }
/* initialize msghdr for receiving packets */
rcviov[0].iov_base = (caddr_t)answer;
@@ -1342,7 +1467,7 @@ rtsock_open()
}
}
-static struct rainfo *
+struct rainfo *
if_indextorainfo(int index)
{
struct rainfo *rai = ralist;
@@ -1370,6 +1495,8 @@ struct rainfo *rainfo;
return;
}
+ make_packet(rainfo); /* XXX: inefficient */
+
sndmhdr.msg_name = (caddr_t)&sin6_allnodes;
sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data;
sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen;
@@ -1474,7 +1601,7 @@ ra_timer_update(void *data, struct timeval *tm)
* Whenever a multicast advertisement is sent from an interface,
* the timer is reset to a uniformly-distributed random value
* between the interface's configured MinRtrAdvInterval and
- * MaxRtrAdvInterval(discovery-v2-02 6.2.4).
+ * MaxRtrAdvInterval (RFC2461 6.2.4).
*/
interval = rai->mininterval;
interval += random() % (rai->maxinterval - rai->mininterval);
diff --git a/usr.sbin/rtadvd/rtadvd.conf.5 b/usr.sbin/rtadvd/rtadvd.conf.5
index b6d4f5c..9b9faaa 100644
--- a/usr.sbin/rtadvd/rtadvd.conf.5
+++ b/usr.sbin/rtadvd/rtadvd.conf.5
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.\" $KAME: rtadvd.conf.5,v 1.32 2001/01/19 05:32:05 jinmei Exp $
+.\" $KAME: rtadvd.conf.5,v 1.35 2001/05/25 07:40:22 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -117,6 +117,16 @@ and Bit 6
.Li 0x40
.Pc
means Other stateful configuration flag bit.
+Bit 4
+.Po
+.Li 0x10
+.Pc
+and Bit 3
+.Po
+.Li 0x08
+.Pc
+are used to encode router preference.
+0x01 means high, 0x00 means medium, and 0x11 means low.
The default value is 0.
.It Cm \&rltime
(num) Router lifetime field
@@ -145,6 +155,17 @@ These items can be omitted, then
will automatically get appropriate prefixes from the kernel's routing table,
and advertise the prefixes with the default parameters.
.Bl -tag -width indent
+.It Cm \&clockskew
+(num) Time skew to adjust link propagation delays and clock skews
+betwen routers on the link
+.Pq unit: seconds .
+This value is used in consistency check for locally-configured and
+advertised prefix lifetimes, and has its meaning when the local router
+configures a prefix on the link with a lifetime that decrements in
+real time.
+If the value is 0, it means the consistency check will be skipped
+for such prefixes.
+The default value is 0.
.It Cm \&addrs
(num) Number of prefixes.
Its default is 0, so it must explicitly be set to positve values
@@ -193,10 +214,16 @@ is more than 0.
(num) Valid lifetime field
.Pq unit: seconds .
The default value is 2592000 (30 days).
+.It Cm \&vltimedecr
+(bool) This item means the advertised valid lifetime will decrements
+in real time, which is disabled by default.
.It Cm \&pltime
(num) Preferred lifetime field
.Pq unit: seconds .
The default value is 604800 (7 days).
+.It Cm \&pltimedecr
+(bool) This item means the advertised preferred lifetime will decrements
+in real time, which is disabled by default.
.El
.Pp
The following item is for ICMPv6 MTU option,
@@ -237,6 +264,75 @@ will not attach source link-layer address option to
router advertisement packets.
.El
.Pp
+The following item controls ICMPV6 home agent information option,
+which was defined with mobile IPv6 support.
+It will be attached to router advertisement header just like other options do.
+.Bl -tag -width indent
+.It Cm \&hapref
+(num) Specifies home agent preference.
+If set to non-zero,
+.Cm \&hatime
+must be present as well.
+.It Cm \&hatime
+(num) Specifies home agent lifetime.
+.El
+.Pp
+When mobile IPv6 support is turned on for
+.Xr rtadvd 8 ,
+advertisement interval option will be attached to router advertisement
+packet, by configuring
+.Cm \&maxinterval
+explicitly.
+.Pp
+The following items are for ICMPv6 route information option,
+which will be attached to router advertisement header.
+These items are optional.
+.Bl -tag -width indent
+.It Cm \&routes
+(num) Number of routes.
+Its default is 0, so it must explicitly be set to positve values
+if you want to specify any route information option.
+If its value is 0, no route information is sent.
+If its value is more than 1, you must specify the index of the routes
+for each item below.
+Indices vary from 0 to N-1, where N is the
+value of
+.Cm routes.
+Each index shall follow the name of each item, e.g.,
+.Dq rtrplen2 .
+.It Cm \&rtrplen
+(num) Prefix length field in route information option.
+The default value is 64.
+.It Cm \&rtrflags
+(num) Flags field in route information option.
+Bit 4
+.Po
+.Li 0x10
+.Pc
+and
+and Bit 3
+.Po
+.Li 0x08
+.Pc
+are used to encode router preference for the route.
+The default value is 0x00, i.e. medium router preference.
+.It Cm \&rtrprefix
+(str) The prefix filled into the Prefix field of route information option.
+Since
+.Dq \&:
+is used for
+.Xr termcap 5
+file format as well as IPv6 numeric address, the field MUST be quoted by
+doublequote character.
+This field cannot be
+omitted if the value of
+.Cm addrs
+is more than 0.
+.It Cm \&rtrltime
+(num) route lifetime field in route information option.
+.Pq unit: seconds .
+The default value is 2592000 (30 days). (not specified in draft-draves-router-selection-01.txt now)
+.El
You can also refer one line from another by using
.Cm tc
capability.
@@ -293,6 +389,12 @@ Thomas Narten, Erik Nordmark and W. A. Simpson,
Neighbor Discovery for IP version 6 (IPv6)
.Dc ,
RFC 2461
+.Pp
+Richard Draves,
+.Do
+Default Router Preferences and More-Specific Routes
+.Dc ,
+draft-ietf-ipngwg-router-selection-01.txt
.Sh HISTORY
The
.Xr rtadvd 8
diff --git a/usr.sbin/rtadvd/rtadvd.h b/usr.sbin/rtadvd/rtadvd.h
index 3ffc7e6..c05dcf4 100644
--- a/usr.sbin/rtadvd/rtadvd.h
+++ b/usr.sbin/rtadvd/rtadvd.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: rtadvd.h,v 1.8 2000/05/16 13:34:14 itojun Exp $ */
+/* $KAME: rtadvd.h,v 1.16 2001/04/10 15:08:31 suz Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
@@ -31,7 +31,8 @@
*/
#define ALLNODES "ff02::1"
-#define ALLROUTERS "ff02::2"
+#define ALLROUTERS_LINK "ff02::2"
+#define ALLROUTERS_SITE "ff05::2"
#define ANY "::"
#define RTSOLLEN 8
@@ -74,7 +75,9 @@ struct prefix {
struct prefix *prev; /* previous link */
u_int32_t validlifetime; /* AdvValidLifetime */
+ long vltimeexpire; /* expiration of vltime; decrement case only */
u_int32_t preflifetime; /* AdvPreferredLifetime */
+ long pltimeexpire; /* expiration of pltime; decrement case only */
u_int onlinkflg; /* bool: AdvOnLinkFlag */
u_int autoconfflg; /* bool: AdvAutonomousFlag */
#ifdef MIP6
@@ -85,6 +88,16 @@ struct prefix {
struct in6_addr prefix;
};
+struct rtinfo {
+ struct rtinfo *prev; /* previous link */
+ struct rtinfo *next; /* forward link */
+
+ u_int32_t ltime; /* route lifetime */
+ u_int rtpref; /* router preference */
+ int prefixlen;
+ struct in6_addr prefix;
+};
+
struct soliciter {
struct soliciter *next;
struct sockaddr_in6 addr;
@@ -116,17 +129,21 @@ struct rainfo {
#ifdef MIP6
int haflg; /* HAFlag */
#endif
+ int rtpref; /* router preference */
u_int32_t linkmtu; /* AdvLinkMTU */
u_int32_t reachabletime; /* AdvReachableTime */
u_int32_t retranstimer; /* AdvRetransTimer */
u_int hoplimit; /* AdvCurHopLimit */
struct prefix prefix; /* AdvPrefixList(link head) */
int pfxs; /* number of prefixes */
+ long clockskew; /* used for consisitency check of lifetimes */
#ifdef MIP6
u_short hapref; /* Home Agent Preference */
u_short hatime; /* Home Agent Lifetime */
#endif
+ struct rtinfo route; /* route information option (link head) */
+ int routes; /* number of route information options */
/* actual RA packet data and its length */
size_t ra_datalen;
@@ -145,6 +162,10 @@ struct rainfo {
void ra_timeout __P((void *));
void ra_timer_update __P((void *, struct timeval *));
+int prefix_match __P((struct in6_addr *, int, struct in6_addr *, int));
+struct rainfo *if_indextorainfo __P((int));
+
+extern struct in6_addr in6a_site_allrouters;
#ifdef MIP6
extern int mobileip6;
#endif
diff --git a/usr.sbin/rtadvd/timer.c b/usr.sbin/rtadvd/timer.c
index 7ccfb7e..439cbb2 100644
--- a/usr.sbin/rtadvd/timer.c
+++ b/usr.sbin/rtadvd/timer.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: timer.c,v 1.3 2000/05/22 22:23:07 itojun Exp $ */
+/* $KAME: timer.c,v 1.4 2000/05/27 11:30:43 jinmei Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
diff --git a/usr.sbin/rtadvd/timer.h b/usr.sbin/rtadvd/timer.h
index c5f8b85..3baf0d0 100644
--- a/usr.sbin/rtadvd/timer.h
+++ b/usr.sbin/rtadvd/timer.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: timer.h,v 1.2 2000/05/16 13:34:14 itojun Exp $ */
+/* $KAME: timer.h,v 1.3 2000/05/27 11:30:43 jinmei Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
diff --git a/usr.sbin/rtsold/Makefile b/usr.sbin/rtsold/Makefile
index 9181ed5..a677ba5 100644
--- a/usr.sbin/rtsold/Makefile
+++ b/usr.sbin/rtsold/Makefile
@@ -14,10 +14,8 @@
# $FreeBSD$
PROG= rtsold
-SRCS= rtsold.c rtsol.c if.c probe.c dump.c
+SRCS= rtsold.c rtsol.c if.c probe.c dump.c rtsock.c
CFLAGS+=-DINET6 -DHAVE_GETIFADDRS
-LDADD= -lkvm
-DPADD= ${LIBKVM}
MAN= rtsold.8
MLINKS= rtsold.8 rtsol.8
diff --git a/usr.sbin/rtsold/dump.c b/usr.sbin/rtsold/dump.c
index ce55ddd..0f75971 100644
--- a/usr.sbin/rtsold/dump.c
+++ b/usr.sbin/rtsold/dump.c
@@ -1,4 +1,4 @@
-/* $KAME: dump.c,v 1.7 2000/08/13 06:14:59 itojun Exp $ */
+/* $KAME: dump.c,v 1.8 2000/10/05 22:20:39 itojun Exp $ */
/*
* Copyright (C) 1999 WIDE Project.
diff --git a/usr.sbin/rtsold/if.c b/usr.sbin/rtsold/if.c
index 35f16d2..4566b73 100644
--- a/usr.sbin/rtsold/if.c
+++ b/usr.sbin/rtsold/if.c
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: if.c,v 1.15 2001/05/22 06:04:17 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -218,6 +218,9 @@ lladdropt_length(struct sockaddr_dl *sdl)
{
switch(sdl->sdl_type) {
case IFT_ETHER:
+#ifdef IFT_IEEE80211
+ case IFT_IEEE80211:
+#endif
return(ROUNDUP8(ETHER_ADDR_LEN + 2));
default:
return(0);
@@ -233,6 +236,9 @@ lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt)
switch(sdl->sdl_type) {
case IFT_ETHER:
+#ifdef IFT_IEEE80211
+ case IFT_IEEE80211:
+#endif
ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
addr = (char *)(ndopt + 1);
memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
@@ -295,6 +301,7 @@ if_nametosdl(char *name)
return(NULL);
memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len);
+ free(buf);
return(ret_sdl);
}
diff --git a/usr.sbin/rtsold/probe.c b/usr.sbin/rtsold/probe.c
index 3b29cb4..34bb66e 100644
--- a/usr.sbin/rtsold/probe.c
+++ b/usr.sbin/rtsold/probe.c
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: probe.c,v 1.10 2000/08/13 06:14:59 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
diff --git a/usr.sbin/rtsold/rtsock.c b/usr.sbin/rtsold/rtsock.c
new file mode 100644
index 0000000..f1c4be8
--- /dev/null
+++ b/usr.sbin/rtsold/rtsock.c
@@ -0,0 +1,179 @@
+/* $KAME: rtsock.c,v 1.3 2000/10/10 08:46:45 itojun Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * 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/param.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+
+#include <time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include "rtsold.h"
+
+#define ROUNDUP(a, size) \
+ (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
+
+#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
+ ((caddr_t)(ap) + \
+ ((ap)->sa_len ? ROUNDUP((ap)->sa_len, sizeof(u_long)) \
+ : sizeof(u_long)))
+
+#ifdef RTM_IFANNOUNCE /*NetBSD 1.5 or later*/
+static int rtsock_input_ifannounce __P((int, struct rt_msghdr *, char *));
+#endif
+
+static struct {
+ u_char type;
+ size_t minlen;
+ int (*func) __P((int, struct rt_msghdr *, char *));
+} rtsock_dispatch[] = {
+#ifdef RTM_IFANNOUNCE /*NetBSD 1.5 or later*/
+ { RTM_IFANNOUNCE, sizeof(struct if_announcemsghdr),
+ rtsock_input_ifannounce },
+#endif
+ { 0, NULL },
+};
+
+int
+rtsock_open()
+{
+
+ return socket(PF_ROUTE, SOCK_RAW, 0);
+}
+
+int
+rtsock_input(s)
+ int s;
+{
+ ssize_t n;
+ char msg[2048];
+ char *lim, *next;
+ struct rt_msghdr *rtm;
+ int idx;
+ size_t len;
+ int ret = 0;
+ const size_t lenlim =
+ offsetof(struct rt_msghdr, rtm_msglen) + sizeof(rtm->rtm_msglen);
+
+ n = read(s, msg, sizeof(msg));
+
+ lim = msg + n;
+ for (next = msg; next < lim; next += len) {
+ rtm = (struct rt_msghdr *)next;
+ if (lim - next < lenlim)
+ break;
+ len = rtm->rtm_msglen;
+ if (len < lenlim)
+ break;
+
+ if (dflag > 1) {
+ warnmsg(LOG_INFO, __FUNCTION__,
+ "rtmsg type %d, len=%lu", rtm->rtm_type,
+ (u_long)len);
+ }
+
+ for (idx = 0; rtsock_dispatch[idx].func; idx++) {
+ if (rtm->rtm_type != rtsock_dispatch[idx].type)
+ continue;
+ if (rtm->rtm_msglen < rtsock_dispatch[idx].minlen) {
+ warnmsg(LOG_INFO, __FUNCTION__,
+ "rtmsg type %d too short!", rtm->rtm_type);
+ continue;
+ }
+
+ ret = (*rtsock_dispatch[idx].func)(s, rtm, lim);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+#ifdef RTM_IFANNOUNCE /*NetBSD 1.5 or later*/
+static int
+rtsock_input_ifannounce(s, rtm, lim)
+ int s;
+ struct rt_msghdr *rtm;
+ char *lim;
+{
+ struct if_announcemsghdr *ifan;
+ struct ifinfo *ifinfo;
+
+ ifan = (struct if_announcemsghdr *)rtm;
+ if ((char *)(ifan + 1) > lim)
+ return -1;
+
+ switch (ifan->ifan_what) {
+ case IFAN_ARRIVAL:
+ /*
+ * XXX for NetBSD 1.5, interface index will monotonically be
+ * increased as new pcmcia card gets inserted.
+ * we may be able to do a name-based interface match,
+ * and call ifreconfig() to enable the interface again.
+ */
+ warnmsg(LOG_INFO, __FUNCTION__,
+ "interface %s inserted", ifan->ifan_name);
+ break;
+ case IFAN_DEPARTURE:
+ warnmsg(LOG_WARNING, __FUNCTION__,
+ "interface %s removed", ifan->ifan_name);
+ ifinfo = find_ifinfo(ifan->ifan_index);
+ if (ifinfo) {
+ if (dflag > 1) {
+ warnmsg(LOG_INFO, __FUNCTION__,
+ "bring interface %s to DOWN state",
+ ifan->ifan_name);
+ }
+ ifinfo->state = IFS_DOWN;
+ }
+ break;
+ }
+
+ return 0;
+}
+#endif
diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c
index 7f27aef..62a73d0 100644
--- a/usr.sbin/rtsold/rtsol.c
+++ b/usr.sbin/rtsold/rtsol.c
@@ -1,4 +1,4 @@
-/* $KAME$ */
+/* $KAME: rtsol.c,v 1.11 2000/08/13 06:14:59 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
diff --git a/usr.sbin/rtsold/rtsold.8 b/usr.sbin/rtsold/rtsold.8
index 2eaae80..1cf369e 100644
--- a/usr.sbin/rtsold/rtsold.8
+++ b/usr.sbin/rtsold/rtsold.8
@@ -1,4 +1,4 @@
-.\" $KAME: rtsold.8,v 1.14 2000/08/13 18:06:39 itojun Exp $
+.\" $KAME: rtsold.8,v 1.16 2000/10/15 13:19:05 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -31,7 +31,7 @@
.\"
.Dd May 17, 1998
.Dt RTSOLD 8
-.Os KAME
+.Os
.\"
.Sh NAME
.Nm rtsold
@@ -62,8 +62,8 @@ all-routers multicast address to discover new routers
and to get non link-local addresses.
.Pp
.Nm
-should be used on IPv6 host
-.Pq non-router node
+should be used on IPv6 hosts
+.Pq non-router nodes
only.
.Pp
If you invoke the program as
@@ -106,9 +106,9 @@ Every 60 seconds if the
option is specified and the
.Nm
daemon cannot get the interface status.
-This feature does not conform to IPv6 neighbor discovery
+This feature does not conform to the IPv6 neighbor discovery
specification, but is provided for mobile stations.
-Default interval for router advertisements, which is on the order of 10
+The default interval for router advertisements, which is on the order of 10
minutes, is slightly long for mobile stations.
This feature is provided
for such stations so that they can find new routers as soon as possible
@@ -117,14 +117,14 @@ when they attach to another link.
.Lp
Once
.Nm
-sends a Router Solicitation, and receives a valid Router Advertisement,
+has sent a Router Solicitation, and has received a valid Router Advertisement,
it refrains from sending additional solicitations on that interface, until
the next time one of the above events occurs.
.Lp
When sending a Router Solicitation on an interface,
.Nm
includes a Source Link-layer address option if the interface
-has its link-layer address.
+has a link-layer address.
.Pp
Upon receipt of signal
.Dv SIGUSR1 ,
@@ -137,7 +137,7 @@ will dump the current internal state into
.It Fl a
Autoprobe outgoing interface.
.Nm
-will try to find a non-loopback, non-p2p and IPv6-capable, interface.
+will try to find a non-loopback, non-point-to-point, IPv6-capable interface.
If
.Nm
finds multiple interfaces,
@@ -147,13 +147,13 @@ will exit with error.
.It Fl d
Enable debugging.
.It Fl D
-Enable more debugging including to print internal timer information.
+Enable more debugging including the printing of internal timer information.
.It Fl f
.Fl f
prevents
.Nm
from becoming a daemon (foreground mode).
-Warning messages are generated to standard error output,
+Warning messages are generated to standard error
instead of
.Xr syslog 3 .
.It Fl m
@@ -170,11 +170,15 @@ periodically sends Router Solicitation on an interface that does not support
ioctl.
.It Fl 1
Perform only one probe.
-Transmit Router Solicitation packet until valid Router Advertisement packet
-arrives all the interfaces more than once, then exit.
+Transmit Router Solicitation packets until at least one valid Router
+Advertisement packet has arrived on each
+.Ar interface ,
+then exit.
.El
.Sh RETURN VALUES
-The program exits with 0 on success, non-zero on failures.
+The
+.Nm
+program exits 0 on success, and >0 on failures.
.\"
.Sh FILES
.Bl -tag -width /var/run/rtsold.dump -compact
@@ -204,7 +208,7 @@ In some operating systems, when a PCMCIA network card is removed
and reinserted, the corresponding interface index is changed.
However,
.Nm
-does not assume such changes, and always uses the index that
+assumes such changes will not occur, and always uses the index that
it got at invocation. As a result,
.Nm
may not work if you reinsert a network card.
@@ -212,11 +216,11 @@ In such a case,
.Nm
should be killed and restarted.
.Pp
-IPv6 autoconfiguration specification assumes single interface host.
-You may see kernel error message if you try to autoconfigure a host with
+The IPv6 autoconfiguration specification assumes a single-interface host.
+You may see kernel error messages if you try to autoconfigure a host with
multiple interfaces.
Also, it seems contradictory for
.Nm
to accept multiple
-.Ar interfaces
-in argument.
+.Ar interface
+arguments.
diff --git a/usr.sbin/rtsold/rtsold.c b/usr.sbin/rtsold/rtsold.c
index a2e39df..a4bb0e4 100644
--- a/usr.sbin/rtsold/rtsold.c
+++ b/usr.sbin/rtsold/rtsold.c
@@ -1,4 +1,4 @@
-/* $KAME: rtsold.c,v 1.26 2000/08/13 18:17:15 itojun Exp $ */
+/* $KAME: rtsold.c,v 1.31 2001/05/22 06:03:06 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -110,7 +110,7 @@ main(argc, argv)
int argc;
char *argv[];
{
- int s, ch;
+ int s, rtsock, maxfd, ch;
int once = 0;
struct timeval *timeout;
struct fd_set fdset;
@@ -223,6 +223,13 @@ main(argc, argv)
errx(1, "failed to open a socket");
/*NOTREACHED*/
}
+ maxfd = s;
+ if ((rtsock = rtsock_open()) < 0) {
+ errx(1, "failed to open a socket");
+ /*NOTREACHED*/
+ }
+ if (rtsock > maxfd)
+ maxfd = rtsock;
/* configuration per interface */
if (ifinit()) {
@@ -263,6 +270,7 @@ main(argc, argv)
FD_ZERO(&fdset);
FD_SET(s, &fdset);
+ FD_SET(rtsock, &fdset);
while (1) { /* main loop */
int e;
struct fd_set select_fd = fdset;
@@ -289,8 +297,8 @@ main(argc, argv)
if (ifi == NULL)
break;
}
-
- if ((e = select(s + 1, &select_fd, NULL, NULL, timeout)) < 1) {
+ e = select(maxfd + 1, &select_fd, NULL, NULL, timeout);
+ if (e < 1) {
if (e < 0 && errno != EINTR) {
warnmsg(LOG_ERR, __FUNCTION__, "select: %s",
strerror(errno));
@@ -299,7 +307,9 @@ main(argc, argv)
}
/* packet reception */
- if (FD_ISSET(s, &fdset))
+ if (FD_ISSET(rtsock, &select_fd))
+ rtsock_input(rtsock);
+ if (FD_ISSET(s, &select_fd))
rtsol_input(s);
}
/* NOTREACHED */
@@ -597,7 +607,18 @@ rtsol_timer_update(struct ifinfo *ifinfo)
ifinfo->timer.tv_usec = interval % MILLION;
break;
case IFS_PROBE:
- ifinfo->timer.tv_sec = RTR_SOLICITATION_INTERVAL;
+ if (ifinfo->probes < MAX_RTR_SOLICITATIONS)
+ ifinfo->timer.tv_sec = RTR_SOLICITATION_INTERVAL;
+ else {
+ /*
+ * After sending MAX_RTR_SOLICITATIONS solicitations,
+ * we're just waiting for possible replies; there
+ * will be no more solicatation. Thus, we change
+ * the timer value to MAX_RTR_SOLICITATION_DELAY based
+ * on RFC 2461, Section 6.3.7.
+ */
+ ifinfo->timer.tv_sec = MAX_RTR_SOLICITATION_DELAY;
+ }
break;
default:
warnmsg(LOG_ERR, __FUNCTION__,
diff --git a/usr.sbin/rtsold/rtsold.h b/usr.sbin/rtsold/rtsold.h
index b6eec21..52175fa 100644
--- a/usr.sbin/rtsold/rtsold.h
+++ b/usr.sbin/rtsold/rtsold.h
@@ -1,4 +1,4 @@
-/* $KAME: rtsold.h,v 1.9 2000/08/13 06:15:00 itojun Exp $ */
+/* $KAME: rtsold.h,v 1.11 2000/10/10 06:18:04 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -89,3 +89,7 @@ extern void defrouter_probe __P((int ifindex));
/* dump.c */
extern void rtsold_dump_file __P((char *));
+
+/* rtsock.c */
+extern int rtsock_open __P((void));
+extern int rtsock_input __P((int));
diff --git a/usr.sbin/setkey/parse.y b/usr.sbin/setkey/parse.y
index 0eea4c1..1d43dc4 100644
--- a/usr.sbin/setkey/parse.y
+++ b/usr.sbin/setkey/parse.y
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: parse.y,v 1.29 2000/06/10 14:17:44 sakane Exp $ */
+/* $KAME: kame/kame/kame/setkey/parse.y,v 1.36 2001/06/07 15:53:12 sakane Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -57,6 +57,7 @@
u_int p_type;
u_int32_t p_spi;
+int p_no_spi;
struct sockaddr *p_src, *p_dst;
u_int p_prefs, p_prefd, p_upper;
u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
@@ -79,7 +80,6 @@ extern int m_len;
extern char cmdarg[8192];
extern int f_debug;
-int setkeymsg __P((void));
static struct addrinfo *parse_addr __P((char *, char *, int));
static int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int));
void parse_init __P((void));
@@ -107,7 +107,7 @@ extern void yyerror __P((const char *));
%token F_EXT EXTENSION NOCYCLICSEQ
%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
%token F_LIFETIME_HARD F_LIFETIME_SOFT
-%token DECSTRING QUOTEDSTRING HEXSTRING ANY
+%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
/* SPD management */
%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
%token F_POLICY PL_REQUESTS
@@ -118,7 +118,7 @@ extern void yyerror __P((const char *));
%type <num> DECSTRING
%type <val> ADDRESS PL_REQUESTS
%type <val> key_string policy_requests
-%type <val> QUOTEDSTRING HEXSTRING
+%type <val> QUOTEDSTRING HEXSTRING STRING
%%
commands
@@ -140,6 +140,7 @@ command
: add_command
| get_command
| delete_command
+ | deleteall_command
| flush_command
| dump_command
| spdadd_command
@@ -166,6 +167,16 @@ delete_command
EOT
;
+ /* deleteall command */
+deleteall_command
+ : DELETEALL { p_type = SADB_DELETE; }
+ ipaddress { p_src = pp_addr; }
+ ipaddress { p_dst = pp_addr; }
+ protocol_spec
+ { p_no_spi = 1; }
+ EOT
+ ;
+
/* get command */
get_command
: GET { p_type = SADB_GET; }
@@ -327,7 +338,7 @@ auth_alg
auth_key
: /*NOTHING*/
{
- if (p_alg_auth != SADB_AALG_NULL) {
+ if (p_alg_auth != SADB_X_AALG_NULL) {
yyerror("no key found.");
return -1;
}
@@ -541,10 +552,27 @@ port
upper_spec
: DECSTRING { p_upper = $1; }
| UP_PROTO { p_upper = $1; }
- | PR_ESP { p_upper = IPPROTO_ESP; };
- | PR_AH { p_upper = IPPROTO_AH; };
- | PR_IPCOMP { p_upper = IPPROTO_IPCOMP; };
| ANY { p_upper = IPSEC_ULPROTO_ANY; }
+ | STRING
+ {
+ struct protoent *ent;
+
+ ent = getprotobyname($1.buf);
+ if (ent)
+ p_upper = ent->p_proto;
+ else {
+ if (strcmp("icmp6", $1.buf) == 0) {
+ p_upper = IPPROTO_ICMPV6;
+ } else if(strcmp("ip4", $1.buf) == 0) {
+ p_upper = IPPROTO_IPV4;
+ } else {
+ yyerror("invalid upper layer protocol");
+ free($1.buf);
+ return -1;
+ }
+ }
+ free($1.buf);
+ }
;
policy_spec
@@ -665,27 +693,29 @@ setkeymsg()
struct sadb_address m_addr;
u_int len;
- len = sizeof(struct sadb_sa);
- m_sa.sadb_sa_len = PFKEY_UNIT64(len);
- m_sa.sadb_sa_exttype = SADB_EXT_SA;
- m_sa.sadb_sa_spi = htonl(p_spi);
- m_sa.sadb_sa_replay = p_replay;
- m_sa.sadb_sa_state = 0;
- m_sa.sadb_sa_auth = p_alg_auth;
- m_sa.sadb_sa_encrypt = p_alg_enc;
- m_sa.sadb_sa_flags = p_ext;
-
- memcpy(m_buf + m_len, &m_sa, len);
- m_len += len;
+ if (p_no_spi == 0) {
+ len = sizeof(struct sadb_sa);
+ m_sa.sadb_sa_len = PFKEY_UNIT64(len);
+ m_sa.sadb_sa_exttype = SADB_EXT_SA;
+ m_sa.sadb_sa_spi = htonl(p_spi);
+ m_sa.sadb_sa_replay = p_replay;
+ m_sa.sadb_sa_state = 0;
+ m_sa.sadb_sa_auth = p_alg_auth;
+ m_sa.sadb_sa_encrypt = p_alg_enc;
+ m_sa.sadb_sa_flags = p_ext;
+
+ memcpy(m_buf + m_len, &m_sa, len);
+ m_len += len;
- len = sizeof(struct sadb_x_sa2);
- m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
- m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
- m_sa2.sadb_x_sa2_mode = p_mode;
- m_sa2.sadb_x_sa2_reqid = p_reqid;
+ len = sizeof(struct sadb_x_sa2);
+ m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
+ m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ m_sa2.sadb_x_sa2_mode = p_mode;
+ m_sa2.sadb_x_sa2_reqid = p_reqid;
- memcpy(m_buf + m_len, &m_sa2, len);
- m_len += len;
+ memcpy(m_buf + m_len, &m_sa2, len);
+ m_len += len;
+ }
/* set src */
m_addr.sadb_address_len =
@@ -864,6 +894,7 @@ parse_init()
{
p_type = 0;
p_spi = 0;
+ p_no_spi = 0;
p_src = 0, p_dst = 0;
pp_prefix = p_prefs = p_prefd = ~0;
diff --git a/usr.sbin/setkey/scriptdump.pl b/usr.sbin/setkey/scriptdump.pl
index aa36544..33907dc 100644
--- a/usr.sbin/setkey/scriptdump.pl
+++ b/usr.sbin/setkey/scriptdump.pl
@@ -33,11 +33,11 @@ foreach $_ (<IN>) {
$akey =~ s/\s//g;
$akey =~ s/^/0x/g;
} elsif (/^\treplay=(\d+) flags=(0x\d+) state=/) {
- print "$mode $src $dst $proto $spi -m $ipsecmode";
+ print "$mode $src $dst $proto $spi";
$replay = $1;
print " -u $reqid" if $reqid;
if ($mode eq 'add') {
- print " -r $replay" if $replay;
+ print " -m $ipsecmode -r $replay" if $replay;
if ($proto eq 'esp') {
print " -E $ealgo $ekey" if $ealgo;
print " -A $aalgo $akey" if $aalgo;
diff --git a/usr.sbin/setkey/setkey.8 b/usr.sbin/setkey/setkey.8
index 7921800..368fc5d 100644
--- a/usr.sbin/setkey/setkey.8
+++ b/usr.sbin/setkey/setkey.8
@@ -1,5 +1,5 @@
-.\" $FreeBSD$
-.\" $KAME: setkey.8,v 1.28 2000/06/16 12:03:46 sakane Exp $
+.\" $KAME: setkey.8,v 1.49 2001/05/18 05:49:51 sakane Exp $
+.\" $FreeBSD$
.\"
.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
.\" All rights reserved.
@@ -28,9 +28,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 17, 1998
+.Dd November 20, 2000
.Dt SETKEY 8
-.Os KAME
+.Os
.\"
.Sh NAME
.Nm setkey
@@ -55,7 +55,7 @@
.\"
.Sh DESCRIPTION
.Nm
-addes, updates, dumpes, or flushes
+adds, updates, dumps, or flushes
Security Association Database (SAD) entries
as well as Security Policy Database (SPD) entries in the kernel.
.Pp
@@ -94,11 +94,14 @@ it has been expired but remains
because it is referenced by SPD entries.
.It Fl d
Enable to print debugging messages for command parser,
-without talking to kernel. It is not used usually.
+without talking to kernel.
+It is not used usually.
.It Fl x
Loop forever and dump all the messages transmitted to
.Dv PF_KEY
socket.
+.Fl xx
+makes each timestamps unformatted.
.It Fl h
Add hexadecimal dump on
.Fl x
@@ -108,14 +111,13 @@ Loop forever with short output on
.Fl D .
.It Fl v
Be verbose.
+The program will dump messages exchanged on
.Dv PF_KEY
-socket
-.Po
-including messages sent from other processes
-.Pc .
+socket, including messages sent from other processes to the kernel.
.El
.Pp
-Operations have the following grammar. Note that lines starting with
+Operations have the following grammar.
+Note that lines starting with
hashmarks ('#') are treated as comment lines.
.Bl -tag -width Ds
.It Xo
@@ -142,6 +144,13 @@ Show an SAD entry.
Remove an SAD entry.
.\"
.It Xo
+.Li deleteall
+.Ar src Ar dst Ar protocol
+.Li ;
+.Xc
+Remove all SAD entries that match the specification.
+.\"
+.It Xo
.Li flush
.Op Ar protocol
.Li ;
@@ -227,7 +236,7 @@ attached
.\"
.Pp
.It Ar extensions
-take some of the following:
+takes some of the following:
.Bl -tag -width Fl -compact
.\"
.It Fl m Ar mode
@@ -243,39 +252,49 @@ The default value is
.It Fl r Ar size
Specify window size of bytes for replay prevention.
.Ar size
-must be decimal number in 32-bit word. If
+must be decimal number in 32-bit word.
+If
.Ar size
is zero or not specified, replay check don't take place.
.\"
.It Fl u Ar id
-Specify the identifier of policy. See also
-.Xr ipsec_set_policy 3 .
+Specify the identifier of the policy entry in SPD.
+See
+.Ar policy .
.\"
.It Fl f Ar pad_option
+defines the content of the ESP padding.
.Ar pad_option
is one of following:
-.Li zero-pad , random-pad
-or
-.Li seq-pad
+.Bl -tag -width random-pad -compact
+.It Li zero-pad
+All of the padding are zero.
+.It Li random-pad
+A series of randomized values are set.
+.It Li seq-pad
+A series of sequential increasing numbers started from 1 are set.
+.El
.\"
.It Fl f Li nocyclic-seq
Don't allow cyclic sequence number.
.\"
.It Fl lh Ar time
.It Fl ls Ar time
-Specify hard/soft lifetime.
+Specify hard/soft life time duration of the SA.
.El
.\"
.Pp
.It Ar algorithm
.Bl -tag -width Fl -compact
.It Fl E Ar ealgo Ar key
-Specify encryption algorithm.
+Specify a encryption algorithm.
.It Fl A Ar aalgo Ar key
-Specify authentication algorithm.
+Specify a authentication algorithm.
If
.Fl A
-is used for esp, it will be treated as ESP payload authentication algorithm.
+is used with
+.Ar protocol Li esp ,
+it will be treated as ESP payload authentication algorithm.
.It Fl C Ar calgo Op Fl R
Specify compression algorithm.
If
@@ -302,23 +321,23 @@ field needs to be smaller than
in this case.
.El
.Pp
-.Li esp
-SAs accept
+.Ar protocol Li esp
+accepts
.Fl E
and
.Fl A .
-.Li esp-old
-SAs accept
+.Ar protocol Li esp-old
+accepts
.Fl E
only.
-.Li ah
+.Ar protocol Li ah
and
.Li ah-old
-SAs accept
+accept
.Fl A
only.
-.Li ipcomp
-SAs accept
+.Ar protocol Li ipcomp
+accepts
.Fl C
only.
.Pp
@@ -365,45 +384,57 @@ They must be in numeric form.
.Pp
.It Ar upperspec
Upper-layer protocol to be used.
-Currently
-.Li icmp ,
+You can use one of words in
+.Pa /etc/protocols
+as
+.Ar upperspec .
+Or
.Li icmp6 ,
.Li ip4 ,
-.Li tcp ,
-.Li udp
and
.Li any
can be specified.
.Li any
stands for
.Dq any protocol .
+Also you can use the protocol number.
.Pp
NOTE:
.Ar upperspec
does not work against forwarding case at this moment,
as it requires extra reassembly at forwarding node
.Pq not implemented at this moment .
+We have many protocols in
+.Pa /etc/protocols ,
+but protocols except of TCP, UDP and ICMP may not be suitable to use with IPSec.
+You have to consider and be careful to use them.
+.Li icmp
+.Li tcp
+.Li udp
+all protocols
.\"
.Pp
.It Ar policy
.Ar policy
is the one of following:
-.Pp
-.Bl -item -compact
-.It
+.Bd -literal -offset
+.Xo
.Fl P
.Ar direction
.Li discard
-.It
+.Xc
+.Xo
.Fl P
.Ar direction
.Li none
-.It
+.Xc
+.Xo
.Fl P
.Ar direction
.Li ipsec
.Ar protocol/mode/src-dst/level
-.El
+.Xc
+.Ed
.Pp
You must specify the direction of its policy as
.Ar direction .
@@ -430,18 +461,33 @@ is either
.Li transport
or
.Li tunnel .
-You must specify the end-points addresses of the SA as
+If
+.Ar mode
+is
+.Li tunnel ,
+you must specify the end-points addresses of the SA as
.Ar src
and
.Ar dst
with
.Sq -
between these addresses which is used to specify the SA to use.
+If
+.Ar mode
+is
+.Li transport ,
+both
+.Ar src
+and
+.Ar dst
+can be omited.
.Ar level
is to be one of the following:
-.Li default , use
+.Li default , use , require
or
-.Li require .
+.Li unique .
+If the SA is not available in every level, the kernel will request
+getting SA to the key exchange daemon.
.Li default
means the kernel consults to the system wide default against protocol you
specified, e.g.
@@ -451,7 +497,23 @@ sysctl variable, when the kernel processes the packet.
means that the kernel use a SA if it's available,
otherwise the kernel keeps normal operation.
.Li require
-means SA is required whenever the kernel deals with the packet.
+means SA is required whenever the kernel sends a packet matched
+with the policy.
+.Li unique
+is the same to require.
+In addition, it allows the policy to bind with the unique out-bound SA.
+If you use the SA by manual keying,
+you can put the decimal number as the policy identifier after
+.Li unique
+separated by colon
+.Sq \:
+like the following;
+.Li unique:number .
+.Li number
+must be between 1 and 32767.
+It corresponds to
+.Ar extensions Fl u .
+.Pp
Note that
.Dq Li discard
and
@@ -491,6 +553,12 @@ keyed-md5 128 ah: 96bit ICV (no document)
keyed-sha1 160 ah: 96bit ICV (no document)
160 ah-old: 128bit ICV (no document)
null 0 to 2048 for debugging
+hmac-sha2-256 256 ah: 96bit ICV (no document)
+ 256 ah-old: 128bit ICV (no document)
+hmac-sha2-384 384 ah: 96bit ICV (no document)
+ 384 ah-old: 128bit ICV (no document)
+hmac-sha2-512 512 ah: 96bit ICV (no document)
+ 512 ah-old: 128bit ICV (no document)
.Ed
.Pp
Followings are the list of encryption algorithms that can be used as
@@ -508,9 +576,9 @@ des-cbc 64 esp-old: rfc1829, esp: rfc2405
simple 0 to 2048 rfc2410
blowfish-cbc 40 to 448 rfc2451
cast128-cbc 40 to 128 rfc2451
-rc5-cbc 40 to 2040 rfc2451
des-deriv 64 ipsec-ciph-des-derived-01 (expired)
3des-deriv 192 no document
+rijndael-cbc 128/192/256 draft-ietf-ipsec-ciph-aes-cbc-00
.Ed
.Pp
Followings are the list of compression algorithms that can be used as
@@ -555,7 +623,8 @@ The command exits with 0 on success, and non-zero on errors.
.\"
.Sh SEE ALSO
.Xr ipsec_set_policy 3 ,
-.Xr sysctl 8
+.Xr sysctl 8 ,
+.Xr racoon 8
.\"
.Sh HISTORY
The
diff --git a/usr.sbin/setkey/setkey.c b/usr.sbin/setkey/setkey.c
index b1e1c1e..e729e7d 100644
--- a/usr.sbin/setkey/setkey.c
+++ b/usr.sbin/setkey/setkey.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: setkey.c,v 1.14 2000/06/10 06:47:09 sakane Exp $ */
+/* $KAME: setkey.c,v 1.18 2001/05/08 04:36:39 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -63,6 +63,8 @@ int postproc __P((struct sadb_msg *, int));
const char *numstr __P((int));
void shortdump_hdr __P((void));
void shortdump __P((struct sadb_msg *));
+static void printdate __P((void));
+static int32_t gmt2local __P((time_t));
#define MODE_SCRIPT 1
#define MODE_CMDDUMP 2
@@ -79,11 +81,14 @@ int f_mode = 0;
int f_cmddump = 0;
int f_policy = 0;
int f_hexdump = 0;
+int f_tflag = 0;
char *pname;
u_char m_buf[BUFSIZ];
u_int m_len;
+static time_t thiszone;
+
extern int lineno;
extern int parse __P((FILE **));
@@ -112,7 +117,9 @@ main(ac, av)
if (ac == 1) Usage();
- while ((c = getopt(ac, av, "acdf:hlvxDFP")) != EOF) {
+ thiszone = gmt2local(0);
+
+ while ((c = getopt(ac, av, "acdf:hlvxDFP")) != -1) {
switch (c) {
case 'c':
f_mode = MODE_SCRIPT;
@@ -142,6 +149,7 @@ main(ac, av)
break;
case 'x':
f_mode = MODE_PROMISC;
+ f_tflag++;
break;
case 'P':
f_policy = 1;
@@ -199,7 +207,7 @@ get_supported()
if (f_debug)
return 0;
- if (pfkey_send_register(so, PF_UNSPEC) < 0)
+ if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
return -1;
if (pfkey_recv_register(so) < 0)
@@ -275,6 +283,7 @@ promisc()
err(1, "recv");
/*NOTREACHED*/
}
+ printdate();
if (f_hexdump) {
int i;
for (i = 0; i < len; i++) {
@@ -541,7 +550,7 @@ shortdump(msg)
snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
printf("%s", buf);
} else
- printf(" ???/???");
+ printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */
printf(" ");
@@ -576,3 +585,64 @@ shortdump(msg)
printf("\n");
}
+
+/* From: tcpdump(1):gmt2local.c and util.c */
+/*
+ * Print the timestamp
+ */
+static void
+printdate()
+{
+ struct timeval tp;
+ int s;
+
+ if (gettimeofday(&tp, NULL) == -1) {
+ perror("gettimeofday");
+ return;
+ }
+
+ if (f_tflag == 1) {
+ /* Default */
+ s = (tp.tv_sec + thiszone ) % 86400;
+ (void)printf("%02d:%02d:%02d.%06u ",
+ s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec);
+ } else if (f_tflag > 1) {
+ /* Unix timeval style */
+ (void)printf("%u.%06u ",
+ (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec);
+ }
+
+ printf("\n");
+}
+
+/*
+ * Returns the difference between gmt and local time in seconds.
+ * Use gmtime() and localtime() to keep things simple.
+ */
+int32_t
+gmt2local(time_t t)
+{
+ register int dt, dir;
+ register struct tm *gmt, *loc;
+ struct tm sgmt;
+
+ if (t == 0)
+ t = time(NULL);
+ gmt = &sgmt;
+ *gmt = *gmtime(&t);
+ loc = localtime(&t);
+ dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
+ (loc->tm_min - gmt->tm_min) * 60;
+
+ /*
+ * If the year or julian day is different, we span 00:00 GMT
+ * and must add or subtract a day. Check the year first to
+ * avoid problems when the julian day wraps.
+ */
+ dir = loc->tm_year - gmt->tm_year;
+ if (dir == 0)
+ dir = loc->tm_yday - gmt->tm_yday;
+ dt += dir * 24 * 60 * 60;
+
+ return (dt);
+}
diff --git a/usr.sbin/setkey/token.l b/usr.sbin/setkey/token.l
index c2eaad5..208196e 100644
--- a/usr.sbin/setkey/token.l
+++ b/usr.sbin/setkey/token.l
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: token.l,v 1.13 2000/06/07 00:29:14 itojun Exp $ */
+/* $KAME: token.l,v 1.21 2001/05/18 05:35:01 sakane Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -47,7 +47,11 @@
#include <unistd.h>
#include <errno.h>
#include "vchar.h"
+#ifdef __NetBSD__
+#include "parse.h"
+#else
#include "y.tab.h"
+#endif
#define DECHO \
if (f_debug) {printf("<%d>", yy_start); ECHO ; printf("\n"); }
@@ -121,6 +125,7 @@ hostname {name}(({dot}{name})+{dot}?)?
add { PREPROC; return(ADD); }
delete { PREPROC; return(DELETE); }
+deleteall { PREPROC; return(DELETEALL); }
get { PREPROC; return(GET); }
flush { PREPROC; return(FLUSH); }
dump { PREPROC; return(DUMP); }
@@ -160,20 +165,23 @@ ipcomp { PREPROC; yylval.num = 0; return(PR_IPCOMP); }
{hyphen}A { PREPROC; return(F_AUTH); }
hmac-md5 { PREPROC; yylval.num = SADB_AALG_MD5HMAC; return(ALG_AUTH); }
hmac-sha1 { PREPROC; yylval.num = SADB_AALG_SHA1HMAC; return(ALG_AUTH); }
-keyed-md5 { PREPROC; yylval.num = SADB_AALG_MD5; return(ALG_AUTH); }
-keyed-sha1 { PREPROC; yylval.num = SADB_AALG_SHA; return(ALG_AUTH); }
-null { PREPROC; yylval.num = SADB_AALG_NULL; return(ALG_AUTH); }
+keyed-md5 { PREPROC; yylval.num = SADB_X_AALG_MD5; return(ALG_AUTH); }
+keyed-sha1 { PREPROC; yylval.num = SADB_X_AALG_SHA; return(ALG_AUTH); }
+hmac-sha2-256 { PREPROC; yylval.num = SADB_X_AALG_SHA2_256; return(ALG_AUTH); }
+hmac-sha2-384 { PREPROC; yylval.num = SADB_X_AALG_SHA2_384; return(ALG_AUTH); }
+hmac-sha2-512 { PREPROC; yylval.num = SADB_X_AALG_SHA2_512; return(ALG_AUTH); }
+null { PREPROC; yylval.num = SADB_X_AALG_NULL; return(ALG_AUTH); }
/* encryption alogorithm */
{hyphen}E { PREPROC; return(F_ENC); }
des-cbc { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC); }
3des-cbc { PREPROC; yylval.num = SADB_EALG_3DESCBC; return(ALG_ENC); }
simple { PREPROC; yylval.num = SADB_EALG_NULL; return(ALG_ENC); }
-blowfish-cbc { PREPROC; yylval.num = SADB_EALG_BLOWFISHCBC; return(ALG_ENC); }
-cast128-cbc { PREPROC; yylval.num = SADB_EALG_CAST128CBC; return(ALG_ENC); }
-rc5-cbc { PREPROC; yylval.num = SADB_EALG_RC5CBC; return(ALG_ENC); }
+blowfish-cbc { PREPROC; yylval.num = SADB_X_EALG_BLOWFISHCBC; return(ALG_ENC); }
+cast128-cbc { PREPROC; yylval.num = SADB_X_EALG_CAST128CBC; return(ALG_ENC); }
des-deriv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DESDERIV); }
des-32iv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DES32IV); }
+rijndael-cbc { PREPROC; yylval.num = SADB_X_EALG_RIJNDAELCBC; return(ALG_ENC); }
/* compression algorithms */
{hyphen}C { PREPROC; return(F_COMP); }
@@ -196,14 +204,6 @@ nocyclic-seq { PREPROC; return(NOCYCLICSEQ); }
{hyphen}lh { PREPROC; return(F_LIFETIME_HARD); }
{hyphen}ls { PREPROC; return(F_LIFETIME_SOFT); }
-
- /* upper layer protocols */
-icmp { PREPROC; yylval.num = IPPROTO_ICMP; return(UP_PROTO); }
-icmp6 { PREPROC; yylval.num = IPPROTO_ICMPV6; return(UP_PROTO); }
-ip4 { PREPROC; yylval.num = IPPROTO_IPV4; return(UP_PROTO); }
-tcp { PREPROC; yylval.num = IPPROTO_TCP; return(UP_PROTO); }
-udp { PREPROC; yylval.num = IPPROTO_UDP; return(UP_PROTO); }
-
/* ... */
any { PREPROC; return(ANY); }
{ws} { PREPROC; }
@@ -277,6 +277,12 @@ any { PREPROC; return(ANY); }
return(QUOTEDSTRING);
}
+[a-z0-9.\-]* {
+ yylval.val.len = yyleng;
+ yylval.val.buf = strdup(yytext);
+ return(STRING);
+ }
+
. {
yyfatal("Syntax error");
/*NOTREACHED*/
diff --git a/usr.sbin/traceroute6/traceroute6.8 b/usr.sbin/traceroute6/traceroute6.8
index 532f198..20f9d38 100644
--- a/usr.sbin/traceroute6/traceroute6.8
+++ b/usr.sbin/traceroute6/traceroute6.8
@@ -1,3 +1,5 @@
+.\" $KAME: traceroute6.8,v 1.8 2000/06/12 16:29:18 itojun Exp $
+.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
.\"
diff --git a/usr.sbin/traceroute6/traceroute6.c b/usr.sbin/traceroute6/traceroute6.c
index d715cc3..f5f3fbe 100644
--- a/usr.sbin/traceroute6/traceroute6.c
+++ b/usr.sbin/traceroute6/traceroute6.c
@@ -1,4 +1,4 @@
-/* $KAME: traceroute6.c,v 1.32 2000/07/07 12:21:34 itojun Exp $ */
+/* $KAME: traceroute6.c,v 1.42 2001/05/08 04:36:41 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -385,6 +385,7 @@ main(argc, argv)
int ch, i, on, probe, seq, hops, rcvcmsglen;
static u_char *rcvcmsgbuf;
char hbuf[NI_MAXHOST], src0[NI_MAXHOST];
+ char *ep;
/*
* Receive ICMP
@@ -394,6 +395,10 @@ main(argc, argv)
exit(5);
}
+ /* revoke privs */
+ seteuid(getuid());
+ setuid(getuid());
+
/* set a minimum set of socket options */
on = 1;
/* specify to tell receiving interface */
@@ -418,19 +423,21 @@ main(argc, argv)
err(1, "setsockopt(IPV6_HOPLIMIT)");
#endif
- /* revoke privs */
- seteuid(getuid());
- setuid(getuid());
-
seq = 0;
- while ((ch = getopt(argc, argv, "df:g:lm:np:q:rs:w:v")) != EOF)
+ while ((ch = getopt(argc, argv, "df:g:lm:np:q:rs:w:v")) != -1)
switch(ch) {
case 'd':
options |= SO_DEBUG;
break;
case 'f':
- first_hop = atoi(optarg);
+ ep = NULL;
+ first_hop = strtoul(optarg, &ep, 0);
+ if (!*argv || *ep) {
+ Fprintf(stderr,
+ "traceroute6: invalid min hoplimit.\n");
+ exit(1);
+ }
if (first_hop > max_hops) {
Fprintf(stderr,
"traceroute6: min hoplimit must be <= %d.\n", max_hops);
@@ -477,7 +484,13 @@ main(argc, argv)
lflag++;
break;
case 'm':
- max_hops = atoi(optarg);
+ ep = NULL;
+ max_hops = strtoul(optarg, &ep, 0);
+ if (!*argv || *ep) {
+ Fprintf(stderr,
+ "traceroute6: invalid max hoplimit.\n");
+ exit(1);
+ }
if (max_hops < first_hop) {
Fprintf(stderr,
"traceroute6: max hoplimit must be >= %d.\n", first_hop);
@@ -488,7 +501,13 @@ main(argc, argv)
nflag++;
break;
case 'p':
- port = atoi(optarg);
+ ep = NULL;
+ port = strtoul(optarg, &ep, 0);
+ if (!*argv || *ep) {
+ Fprintf(stderr,
+ "traceroute6: port.\n");
+ exit(1);
+ }
if (port < 1) {
Fprintf(stderr,
"traceroute6: port must be >0.\n");
@@ -496,7 +515,13 @@ main(argc, argv)
}
break;
case 'q':
- nprobes = atoi(optarg);
+ ep = NULL;
+ nprobes = strtoul(optarg, &ep, 0);
+ if (!*argv || *ep) {
+ Fprintf(stderr,
+ "traceroute6: invalid nprobes.\n");
+ exit(1);
+ }
if (nprobes < 1) {
Fprintf(stderr,
"traceroute6: nprobes must be >0.\n");
@@ -517,7 +542,13 @@ main(argc, argv)
verbose++;
break;
case 'w':
- waittime = atoi(optarg);
+ ep = NULL;
+ waittime = strtoul(optarg, &ep, 0);
+ if (!*argv || *ep) {
+ Fprintf(stderr,
+ "traceroute6: invalid wait time.\n");
+ exit(1);
+ }
if (waittime <= 1) {
Fprintf(stderr,
"traceroute6: wait must be >1 sec.\n");
@@ -530,7 +561,7 @@ main(argc, argv)
argc -= optind;
argv += optind;
- if (argc < 1)
+ if (argc < 1 || argc > 2)
usage();
#if 1
@@ -557,9 +588,20 @@ main(argc, argv)
}
memcpy(&Dst, res->ai_addr, res->ai_addrlen);
hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv;
+ if (!hostname) {
+ (void)fprintf(stderr, "traceroute6: not enough core\n");
+ exit(1);
+ }
- if (*++argv)
- datalen = atoi(*argv);
+ if (*++argv) {
+ ep = NULL;
+ datalen = strtoul(*argv, &ep, 0);
+ if (!*argv || *ep) {
+ Fprintf(stderr,
+ "traceroute6: invalid packet length.\n");
+ exit(1);
+ }
+ }
if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) {
Fprintf(stderr,
"traceroute6: packet size must be 0 <= s < %ld.\n",
@@ -787,7 +829,7 @@ main(argc, argv)
*/
if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf,
sizeof(hbuf), NULL, 0, NI_NUMERICHOST | niflag))
- strcpy(hbuf, "(invalid)");
+ strlcpy(hbuf, "(invalid)", sizeof(hbuf));
Fprintf(stderr, "traceroute6");
Fprintf(stderr, " to %s (%s)", hostname, hbuf);
if (source)
@@ -889,7 +931,7 @@ wait_for_reply(sock, mhdr)
struct timeval wait;
int cc = 0, fdsn;
- fdsn = howmany(sock+1, NFDBITS) * sizeof(fd_mask);
+ fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
err(1, "malloc");
memset(fdsp, 0, fdsn);
@@ -1074,7 +1116,7 @@ packet_ok(mhdr, cc, seq)
if (getnameinfo((struct sockaddr *)from, from->sin6_len,
hbuf, sizeof(hbuf), NULL, 0,
NI_NUMERICHOST | niflag) != 0)
- strcpy(hbuf, "invalid");
+ strlcpy(hbuf, "invalid", sizeof(hbuf));
Printf("packet too short (%d bytes) from %s\n", cc,
hbuf);
}
@@ -1088,7 +1130,7 @@ packet_ok(mhdr, cc, seq)
if (getnameinfo((struct sockaddr *)from, from->sin6_len,
hbuf, sizeof(hbuf), NULL, 0,
NI_NUMERICHOST | niflag) != 0)
- strcpy(hbuf, "invalid");
+ strlcpy(hbuf, "invalid", sizeof(hbuf));
Printf("data too short (%d bytes) from %s\n", cc, hbuf);
}
return(0);
@@ -1146,7 +1188,7 @@ packet_ok(mhdr, cc, seq)
if (getnameinfo((struct sockaddr *)from, from->sin6_len,
sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST | niflag) != 0)
- strcpy(sbuf, "invalid");
+ strlcpy(sbuf, "invalid", sizeof(hbuf));
Printf("\n%d bytes from %s to %s", cc, sbuf,
rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
dbuf, sizeof(dbuf))
@@ -1225,7 +1267,7 @@ print(mhdr, cc)
if (getnameinfo((struct sockaddr *)from, from->sin6_len,
hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST | niflag) != 0)
- strcpy(hbuf, "invalid");
+ strlcpy(hbuf, "invalid", sizeof(hbuf));
if (nflag)
Printf(" %s", hbuf);
else if (lflag)
@@ -1282,7 +1324,7 @@ inetname(sa)
first = 0;
if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
(cp = index(domain, '.')))
- (void) strcpy(domain, cp + 1);
+ (void) strlcpy(domain, cp + 1, sizeof(domain));
else
domain[0] = 0;
}
@@ -1301,7 +1343,7 @@ inetname(sa)
if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
NI_NUMERICHOST | niflag) != 0)
- strcpy(line, "invalid");
+ strlcpy(line, "invalid", sizeof(line));
return line;
}
@@ -1309,7 +1351,7 @@ void
usage()
{
(void)fprintf(stderr,
-"usage: traceroute6 [-dlnrv] [-f first_hop] [-m max_hops] [-p port#] \n"
-" [-q nqueries] [-s src_addr] [-g gateway] [-w wait] host [data size]\n");
+"usage: traceroute6 [-dlnrv] [-f firsthop] [-g gateway] [-m hoplimit] [-p port]\n"
+" [-q probes] [-s src] [-w waittime] target [datalen]\n");
exit(1);
}
OpenPOWER on IntegriCloud