Sync with latest KAME.

Obtained from:	KAME
This commit is contained in:
kris 2000-07-05 10:14:11 +00:00
parent 4f67f09225
commit c8251f31e2
8 changed files with 334 additions and 166 deletions

View File

@ -15,7 +15,7 @@
PROG= rtsold
SRCS= rtsold.c rtsol.c if.c probe.c dump.c
CFLAGS+=-DINET6
CFLAGS+=-DINET6 -DHAVE_GETIFADDRS
LDADD+= -lkvm
DPADD+= ${LIBKVM}

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 WIDE Project.
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@ -13,7 +13,7 @@
* 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
@ -31,7 +31,9 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
@ -47,6 +49,7 @@ static FILE *fp;
extern struct ifinfo *iflist;
static void dump_interface_status __P((void));
static char *sec2str __P((time_t));
char *ifstatstr[] = {"IDLE", "DELAY", "PROBE", "DOWN", "TENTATIVE"};

View File

@ -1,7 +1,7 @@
/*
* 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:
@ -13,7 +13,7 @@
* 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
@ -35,12 +35,23 @@
#include <sys/ioctl.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
#endif /* __FreeBSD__ >= 3 */
#include <net/if_types.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/ethernet.h>
#ifdef __FreeBSD__
# include <net/ethernet.h>
#endif
#ifdef __NetBSD__
#include <net/if_ether.h>
#endif
#if defined(__bsdi__) || defined(__OpenBSD__)
# include <netinet/in.h>
# include <netinet/if_ether.h>
#endif
#include <netinet/in.h>
#include <netinet/icmp6.h>
@ -53,25 +64,27 @@
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <kvm.h>
#include <nlist.h>
#include <limits.h>
#ifdef HAVE_GETIFADDRS
#include <ifaddrs.h>
#endif
#include "rtsold.h"
extern int rssock;
static int ifsock;
static int getifa __P((char *name, struct in6_ifaddr *ifap));
static int get_llflag __P((const char *name));
#ifndef HAVE_GETIFADDRS
static unsigned int if_maxindex __P((void));
#endif
static void get_rtaddrs __P((int addrs, struct sockaddr *sa,
struct sockaddr **rti_info));
int
ifinit()
{
if ((ifsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "socket: %s", strerror(errno));
return(-1);
}
ifsock = rssock;
return(0);
}
@ -80,7 +93,7 @@ int
interface_up(char *name)
{
struct ifreq ifr;
struct in6_ifaddr ifa;
int llflag;
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
@ -100,24 +113,24 @@ interface_up(char *name)
warnmsg(LOG_DEBUG, __FUNCTION__, "checking if %s is ready...", name);
if (getifa(name, &ifa) < 0) {
llflag = get_llflag(name);
if (llflag < 0) {
warnmsg(LOG_WARNING, __FUNCTION__,
"getifa() failed, anyway I'll try");
"get_llflag() failed, anyway I'll try");
return 0;
}
if (!(ifa.ia6_flags & IN6_IFF_NOTREADY)) {
if (!(llflag & IN6_IFF_NOTREADY)) {
warnmsg(LOG_DEBUG, __FUNCTION__,
"%s is ready", name);
return(0);
}
else {
if (ifa.ia6_flags & IN6_IFF_TENTATIVE) {
} else {
if (llflag & IN6_IFF_TENTATIVE) {
warnmsg(LOG_DEBUG, __FUNCTION__, "%s is tentative",
name);
return IFS_TENTATIVE;
}
if (ifa.ia6_flags & IN6_IFF_DUPLICATED)
if (llflag & IN6_IFF_DUPLICATED)
warnmsg(LOG_DEBUG, __FUNCTION__, "%s is duplicated",
name);
return -1;
@ -130,7 +143,7 @@ interface_status(struct ifinfo *ifinfo)
char *ifname = ifinfo->ifname;
struct ifreq ifr;
struct ifmediareq ifmr;
/* get interface flags */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
@ -188,14 +201,14 @@ interface_status(struct ifinfo *ifinfo)
return(1);
}
#define ROUNDUP(a, size) \
#define ROUNDUP(a, size) \
(((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\
sizeof(u_long)) :\
sizeof(u_long)))
#define ROUNDUP8(a) (1 + (((a) - 1) | 7))
#define ROUNDUP8(a) (1 + (((a) - 1) | 7))
int
lladdropt_length(struct sockaddr_dl *sdl)
@ -258,6 +271,8 @@ if_nametosdl(char *name)
if ((sa = rti_info[RTAX_IFP]) != NULL) {
if (sa->sa_family == AF_LINK) {
sdl = (struct sockaddr_dl *)sa;
if (strlen(name) != sdl->sdl_nlen)
continue; /* not same len */
if (strncmp(&sdl->sdl_data[0],
name,
sdl->sdl_nlen) == 0) {
@ -297,91 +312,141 @@ getinet6sysctl(int code)
/*------------------------------------------------------------*/
static struct nlist nl[] = {
#define N_IFNET 0
{ "_ifnet" },
{ "" },
};
#define KREAD(x, y, z) { \
if (kvm_read(kvmd, (u_long)x, (void *)y, sizeof(z)) != sizeof(z)) { \
warnmsg(LOG_ERR, __FUNCTION__, "kvm_read failed"); \
goto bad; \
} \
}
/* get ia6_flags for link-local addr on if. returns -1 on error. */
static int
getifa(char *name, struct in6_ifaddr *ifap)
get_llflag(const char *name)
{
u_short index;
kvm_t *kvmd = NULL;
char buf[_POSIX2_LINE_MAX];
struct ifnet *ifp;
struct ifnet ifnet;
struct in6_ifaddr *ifa;
#ifdef HAVE_GETIFADDRS
struct ifaddrs *ifap, *ifa;
struct in6_ifreq ifr6;
struct sockaddr_in6 *sin6;
int s;
if (!ifap)
if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "socket(SOCK_DGRAM): %s",
strerror(errno));
exit(1);
index = (u_short)if_nametoindex(name);
if (index == 0) {
warnmsg(LOG_ERR, __FUNCTION__, "if_nametoindex failed for %s",
name);
goto bad;
}
if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__, "kvm_openfiles failed");
goto bad;
}
if (kvm_nlist(kvmd, nl) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "kvm_nlist failed");
goto bad;
}
if (nl[N_IFNET].n_value == 0) {
warnmsg(LOG_ERR, __FUNCTION__, "symbol \"%s\" not found",
nl[N_IFNET].n_name);
goto bad;
if (getifaddrs(&ifap) != 0) {
warnmsg(LOG_ERR, __FUNCTION__, "etifaddrs: %s",
strerror(errno));
exit(1);
}
KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *);
while (ifp) {
KREAD(ifp, &ifnet, struct ifnet);
if (ifnet.if_index == index)
break;
ifp = TAILQ_NEXT(&ifnet, if_link);
}
if (!ifp) {
warnmsg(LOG_ERR, __FUNCTION__, "interface \"%s\" not found",
name);
goto bad;
}
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (strlen(ifa->ifa_name) != strlen(name)
|| strncmp(ifa->ifa_name, name, strlen(name)) != 0)
continue;
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
continue;
ifa = (struct in6_ifaddr *)TAILQ_FIRST(&ifnet.if_addrhead);
while (ifa) {
KREAD(ifa, ifap, *ifap);
if (ifap->ia_addr.sin6_family == AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&ifap->ia_addr.sin6_addr)) {
kvm_close(kvmd);
return 0;
memset(&ifr6, 0, sizeof(ifr6));
strcpy(ifr6.ifr_name, name);
memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
warnmsg(LOG_ERR, __FUNCTION__,
"ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
exit(1);
}
ifa = (struct in6_ifaddr *)
TAILQ_NEXT((struct ifaddr *)ifap, ifa_link);
freeifaddrs(ifap);
close(s);
return ifr6.ifr_ifru.ifru_flags6;
}
warnmsg(LOG_ERR, __FUNCTION__, "no IPv6 link-local address for %s",
name);
bad:
if (kvmd)
kvm_close(kvmd);
freeifaddrs(ifap);
close(s);
return -1;
#else
int s;
unsigned int maxif;
struct ifreq *iflist;
struct ifconf ifconf;
struct ifreq *ifr, *ifr_end;
struct sockaddr_in6 *sin6;
struct in6_ifreq ifr6;
maxif = if_maxindex() + 1;
iflist = (struct ifreq *)malloc(maxif * BUFSIZ); /* XXX */
if (iflist == NULL) {
warnmsg(LOG_ERR, __FUNCTION__, "not enough core");
exit(1);
}
if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "socket(SOCK_DGRAM): %s",
strerror(errno));
exit(1);
}
memset(&ifconf, 0, sizeof(ifconf));
ifconf.ifc_req = iflist;
ifconf.ifc_len = maxif * BUFSIZ; /* XXX */
if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "ioctl(SIOCGIFCONF): %s",
strerror(errno));
exit(1);
}
/* Look for this interface in the list */
ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
for (ifr = ifconf.ifc_req;
ifr < ifr_end;
ifr = (struct ifreq *) ((char *) &ifr->ifr_addr
+ ifr->ifr_addr.sa_len)) {
if (strlen(ifr->ifr_name) != strlen(name)
|| strncmp(ifr->ifr_name, name, strlen(name)) != 0)
continue;
if (ifr->ifr_addr.sa_family != AF_INET6)
continue;
sin6 = (struct sockaddr_in6 *)&ifr->ifr_addr;
if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
continue;
memset(&ifr6, 0, sizeof(ifr6));
strcpy(ifr6.ifr_name, name);
memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
warnmsg(LOG_ERR, __FUNCTION__,
"ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
exit(1);
}
free(iflist);
close(s);
return ifr6.ifr_ifru.ifru_flags6;
}
free(iflist);
close(s);
return -1;
#endif
}
#ifndef HAVE_GETIFADDRS
static unsigned int
if_maxindex()
{
struct if_nameindex *p, *p0;
unsigned int max = 0;
p0 = if_nameindex();
for (p = p0; p && p->if_index && p->if_name; p++) {
if (max < p->if_index)
max = p->if_index;
}
if_freenameindex(p0);
return max;
}
#endif
static void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{
int i;
for (i = 0; i < RTAX_MAX; i++) {
if (addrs & (1 << i)) {
rti_info[i] = sa;

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@ -13,7 +13,7 @@
* 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
@ -36,7 +36,9 @@
#include <sys/uio.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
#endif /* __FreeBSD__ >= 3 */
#include <netinet/in.h>
#include <netinet6/in6_var.h>
@ -49,6 +51,7 @@
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <stdlib.h>
#include "rtsold.h"
@ -57,11 +60,19 @@ static struct iovec sndiov[2];
static int probesock;
static void sendprobe __P((struct in6_addr *addr, int ifindex));
int
probe_init()
{
static u_char sndcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int))];
int scmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int));
static u_char *sndcmsgbuf = NULL;
if (sndcmsgbuf == NULL &&
(sndcmsgbuf = (u_char *)malloc(scmsglen)) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__, "malloc failed");
return(-1);
}
if ((probesock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "socket: %s", strerror(errno));
@ -79,13 +90,13 @@ probe_init()
sndmhdr.msg_iov = sndiov;
sndmhdr.msg_iovlen = 1;
sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
sndmhdr.msg_controllen = sizeof(sndcmsgbuf);
sndmhdr.msg_controllen = scmsglen;
return(0);
}
/*
* Probe if each router in the default router list is still alive.
* Probe if each router in the default router list is still alive.
*/
void
defrouter_probe(int ifindex)

View File

@ -1,7 +1,7 @@
/*
* 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:
@ -13,7 +13,7 @@
* 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
@ -55,7 +55,7 @@
#include <syslog.h>
#include "rtsold.h"
#define ALLROUTER "ff02::2"
#define ALLROUTER "ff02::2"
static struct msghdr rcvmhdr;
static struct msghdr sndmhdr;
@ -63,7 +63,7 @@ static struct iovec rcviov[2];
static struct iovec sndiov[2];
static struct sockaddr_in6 from;
static int rssock;
int rssock;
static struct sockaddr_in6 sin6_allrouters = {sizeof(sin6_allrouters), AF_INET6};
@ -73,11 +73,21 @@ sockopen()
int on;
struct icmp6_filter filt;
static u_char answer[1500];
static u_char rcvcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int))];
static u_char sndcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int))];
int rcvcmsglen, sndcmsglen;
static u_char *rcvcmsgbuf = NULL, *sndcmsgbuf = NULL;
sndcmsglen = rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int));
if (rcvcmsgbuf == NULL && (rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__,
"malloc for receive msghdr failed");
return(-1);
}
if (sndcmsgbuf == NULL && (sndcmsgbuf = malloc(sndcmsglen)) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__,
"malloc for send msghdr failed");
return(-1);
}
memset(&sin6_allrouters, 0, sizeof(struct sockaddr_in6));
if (inet_pton(AF_INET6, ALLROUTER,
&sin6_allrouters.sin6_addr.s6_addr) != 1) {
@ -93,21 +103,39 @@ sockopen()
/* specify to tell receiving interface */
on = 1;
#ifdef IPV6_RECVPKTINFO
if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
sizeof(on)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "IPV6_RECVPKTINFO: %s",
strerror(errno));
exit(1);
}
#else /* old adv. API */
if (setsockopt(rssock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
sizeof(on)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "IPV6_PKTINFO: %s",
strerror(errno));
exit(1);
}
#endif
on = 1;
/* specify to tell value of hoplimit field of received IP6 hdr */
#ifdef IPV6_RECVHOPLIMIT
if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
sizeof(on)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "IPV6_RECVHOPLIMIT: %s",
strerror(errno));
exit(1);
}
#else /* old adv. API */
if (setsockopt(rssock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
sizeof(on)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "IPV6_HOPLIMIT: %s",
strerror(errno));
exit(1);
}
#endif
/* specfiy to accept only router advertisements on the socket */
ICMP6_FILTER_SETBLOCKALL(&filt);
@ -127,14 +155,14 @@ sockopen()
rcvmhdr.msg_iov = rcviov;
rcvmhdr.msg_iovlen = 1;
rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
rcvmhdr.msg_controllen = sizeof(rcvcmsgbuf);
rcvmhdr.msg_controllen = rcvcmsglen;
/* initialize msghdr for sending packets */
sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
sndmhdr.msg_iov = sndiov;
sndmhdr.msg_iovlen = 1;
sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
sndmhdr.msg_controllen = sizeof(sndcmsgbuf);
sndmhdr.msg_controllen = sndcmsglen;
return(rssock);
}

View File

@ -1,6 +1,6 @@
.\" 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:
@ -12,7 +12,7 @@
.\" 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
@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: rtsold.8,v 1.4 1999/09/30 00:57:15 jinmei Exp $
.\" $Id: rtsold.8,v 1.9 2000/07/04 14:44:38 jinmei Exp $
.\" $FreeBSD$
.\"
.Dd May 17, 1998
@ -53,11 +53,26 @@ If a node (re)attaches to a link,
sends some Router Solicitations on the link destined to the link-local scope
all-routers multicast address to discover new routers
and to get non link-local addresses.
.Lp
.Pp
If you invoke the program as
.Nm rtsol ,
it will transmit probes from the specified
.Ar interface ,
without becoming a daemon.
In other words,
.Nm rtsol
behaves as
.Do
.Nm
.Fl f1
.Ar interfaces
.Dc .
.Pp
Specifically,
.Nm
sends at most 3 Router Solicitations on an interface
after one of the following events:
.Pp
.Bl -bullet -compact
.It
Just after invocation of
@ -66,32 +81,32 @@ daemon.
.It
The interface is up after a temporary interface failure.
.Nm Rtsold
detects it by periodically probing if the status of the
interface is active or not.
Note that some network cards and drivers do not allow users
to extract link state.
detects such failures by periodically probing to see if the status
of the interface is active or not.
Note that some network cards and drivers do not allow the extraction
of link state.
In such cases,
.Nm
cannot detect the change of the interface status.
.It
Every one minute if
Every 60 seconds if the
.Fl m
option is specified and
option is specified and the
.Nm
daemon cannot get the interface status.
This feature does not conform to IPv6 neighbor discovery
specification, but is provided for mobile stations.
Default interval of router advertisements, which is on the order of 10
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
when they attach another link.
when they attach to another link.
.El
.Lp
Once
.Nm
sends a Router Solicitation, and receives a valid Router Advertisement,
it desists from sending additional solicitations on that interface, until
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,
@ -103,7 +118,7 @@ Upon receipt of signal
.Dv SIGUSR1 ,
.Nm
will dump the current internal state into
.Pa /var/tmp/rtsold.dump.
.Pa /var/run/rtsold.dump.
.\"
.Sh OPTIONS
.Bl -tag -width indent
@ -134,18 +149,9 @@ periodically sends Router Solicitation on an interface that does not support
ioctl.
.It Fl 1
Perform only one probe.
Transmit Router Solcitation packet until valid Router Advertisement packet
Transmit Router Solicitation packet until valid Router Advertisement packet
arrives all the interfaces more than once, then exit.
.El
.Pp
If you invoke the program as
.Nm rtsol ,
it will behave as
.Do
.Nm
.Fl f1
.Ar interfaces
.Dc .
.Sh RETURN VALUES
The program exits with 0 on success, non-zero on failures.
.\"
@ -154,7 +160,7 @@ The program exits with 0 on success, non-zero on failures.
.It Pa /var/run/rtsold.pid
the pid of the currently running
.Nm rtsold .
.It Pa /var/tmp/rtsold.dump
.It Pa /var/run/rtsold.dump
dumps internal state on.
.El
.\"
@ -165,11 +171,22 @@ dumps internal state on.
.Sh HISTORY
The
.Nm
command is based on
command is based on the
.Nm rtsol
command, which first appeared in WIDE/KAME IPv6 protocol stack kit.
.Nm rtsol
is now integrated into
.Xr rtsold 8 .
.\" .Sh BUGS
.\" (to be written)
.\"
.Sh BUGS
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
it got at invocation. As a result,
.Nm
may not work if you reinsert a network card.
In such a case,
.Nm
should be killed and restarted.

View File

@ -1,7 +1,7 @@
/*
* 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:
@ -13,7 +13,7 @@
* 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
@ -31,7 +31,9 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <netinet/in.h>
@ -55,36 +57,39 @@ static int log_upto = 999;
static int fflag = 0;
/* protocol constatns */
#define MAX_RTR_SOLICITATION_DELAY 1 /* second */
#define RTR_SOLICITATION_INTERVAL 4 /* seconds */
#define MAX_RTR_SOLICITATIONS 3 /* times */
#define MAX_RTR_SOLICITATION_DELAY 1 /* second */
#define RTR_SOLICITATION_INTERVAL 4 /* seconds */
#define MAX_RTR_SOLICITATIONS 3 /* times */
/* implementation dependent constants */
#define PROBE_INTERVAL 60 /* secondes XXX: should be configurable */
#define PROBE_INTERVAL 60 /* secondes XXX: should be configurable */
/* utility macros */
/* a < b */
#define TIMEVAL_LT(a, b) (((a).tv_sec < (b).tv_sec) ||\
#define TIMEVAL_LT(a, b) (((a).tv_sec < (b).tv_sec) ||\
(((a).tv_sec == (b).tv_sec) && \
((a).tv_usec < (b).tv_usec)))
/* a <= b */
#define TIMEVAL_LEQ(a, b) (((a).tv_sec < (b).tv_sec) ||\
#define TIMEVAL_LEQ(a, b) (((a).tv_sec < (b).tv_sec) ||\
(((a).tv_sec == (b).tv_sec) &&\
((a).tv_usec <= (b).tv_usec)))
/* a == b */
#define TIMEVAL_EQ(a, b) (((a).tv_sec==(b).tv_sec) && ((a).tv_usec==(b).tv_usec))
#define TIMEVAL_EQ(a, b) (((a).tv_sec==(b).tv_sec) && ((a).tv_usec==(b).tv_usec))
int main __P((int argc, char *argv[]));
/* static variables and functions */
static int mobile_node = 0;
static int do_dump;
static char *dumpfilename = "/var/tmp/rtsold.dump"; /* XXX: should be configurable */
static char *dumpfilename = "/var/run/rtsold.dump"; /* XXX: should be configurable */
static char *pidfilename = "/var/run/rtsold.pid"; /* should be configurable */
static int ifconfig __P((char *ifname));
#if 0
static int ifreconfig __P((char *ifname));
#endif
static int make_packet __P((struct ifinfo *ifinfo));
static struct timeval *rtsol_check_timer __P((void));
static void TIMEVAL_ADD __P((struct timeval *a, struct timeval *b,
@ -92,7 +97,7 @@ static void TIMEVAL_ADD __P((struct timeval *a, struct timeval *b,
static void TIMEVAL_SUB __P((struct timeval *a, struct timeval *b,
struct timeval *result));
static void rtsold_set_dump_file __P(());
static void rtsold_set_dump_file __P((void));
static void usage __P((char *progname));
int
@ -161,8 +166,10 @@ main(argc, argv)
setlogmask(LOG_UPTO(log_upto));
}
#ifndef HAVE_ARC4RANDOM
/* random value initilization */
srandom((u_long)time(NULL));
#endif
/* warn if accept_rtadv is down */
if (!getinet6sysctl(IPV6CTL_ACCEPT_RTADV))
@ -172,19 +179,23 @@ main(argc, argv)
if (signal(SIGUSR1, (void *)rtsold_set_dump_file) < 0)
errx(1, "failed to set signal for dump status");
/*
* Open a socket for sending RS and receiving RA.
* This should be done before calling ifinit(), since the function
* uses the socket.
*/
if ((s = sockopen()) < 0)
errx(1, "failed to open a socket");
/* configuration per interface */
if (ifinit())
errx(1, "failed to initilizatoin interfaces");
while (argc--) {
if (ifconfig(*argv))
errx(1, "failed to initilize %s", *argv);
errx(1, "failed to initialize %s", *argv);
argv++;
}
/* open a socket for sending RS and receiving RA */
if ((s = sockopen()) < 0)
errx(1, "failed to open a socket");
/* setup for probing default routers */
if (probe_init())
errx(1, "failed to setup for probing routers");
@ -210,7 +221,6 @@ main(argc, argv)
FD_ZERO(&fdset);
FD_SET(s, &fdset);
while (1) { /* main loop */
extern int errno;
int e;
struct fd_set select_fd = fdset;
@ -218,7 +228,7 @@ main(argc, argv)
do_dump = 0;
rtsold_dump_file(dumpfilename);
}
timeout = rtsol_check_timer();
if (once) {
@ -269,11 +279,13 @@ ifconfig(char *ifname)
if (find_ifinfo(sdl->sdl_index)) {
warnmsg(LOG_ERR, __FUNCTION__,
"interface %s was already cofigured", ifname);
free(sdl);
return(-1);
}
if ((ifinfo = malloc(sizeof(*ifinfo))) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__, "memory allocation failed");
free(sdl);
return(-1);
}
memset(ifinfo, 0, sizeof(*ifinfo));
@ -318,11 +330,38 @@ ifconfig(char *ifname)
return(0);
bad:
free(ifinfo);
free(ifinfo->sdl);
free(ifinfo);
return(-1);
}
#if 0
static int
ifreconfig(char *ifname)
{
struct ifinfo *ifi, *prev;
int rv;
prev = NULL;
for (ifi = iflist; ifi; ifi = ifi->next) {
if (strncmp(ifi->ifname, ifname, sizeof(ifi->ifname)) == 0)
break;
prev = ifi;
}
prev->next = ifi->next;
rv = ifconfig(ifname);
/* reclaim it after ifconfig() in case ifname is pointer inside ifi */
if (ifi->rs_data)
free(ifi->rs_data);
free(ifi->sdl);
free(ifi);
return rv;
}
#endif
struct ifinfo *
find_ifinfo(int ifindex)
{
@ -480,8 +519,8 @@ rtsol_check_timer()
void
rtsol_timer_update(struct ifinfo *ifinfo)
{
#define MILLION 1000000
#define DADRETRY 10 /* XXX: adhoc */
#define MILLION 1000000
#define DADRETRY 10 /* XXX: adhoc */
long interval;
struct timeval now;
@ -499,14 +538,18 @@ rtsol_timer_update(struct ifinfo *ifinfo)
break;
case IFS_IDLE:
if (mobile_node) {
/* XXX should be configurable */
/* XXX should be configurable */
ifinfo->timer.tv_sec = 3;
}
else
ifinfo->timer = tm_max; /* stop timer(valid?) */
break;
case IFS_DELAY:
#ifndef HAVE_ARC4RANDOM
interval = random() % (MAX_RTR_SOLICITATION_DELAY * MILLION);
#else
interval = arc4random() % (MAX_RTR_SOLICITATION_DELAY * MILLION);
#endif
ifinfo->timer.tv_sec = interval / MILLION;
ifinfo->timer.tv_usec = interval % MILLION;
break;
@ -541,7 +584,7 @@ rtsol_timer_update(struct ifinfo *ifinfo)
}
/* timer related utility functions */
#define MILLION 1000000
#define MILLION 1000000
/* result = a + b */
static void

View File

@ -1,7 +1,7 @@
/*
* 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:
@ -13,7 +13,7 @@
* 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
@ -33,7 +33,7 @@ struct ifinfo {
struct ifinfo *next; /* pointer to the next interface */
struct sockaddr_dl *sdl; /* link-layer address */
char ifname[16]; /* interface name */
char ifname[IF_NAMESIZE]; /* interface name */
int active; /* interface status */
int probeinterval; /* interval of probe timer(if necessary) */
int probetimer; /* rest of probe timer */
@ -43,6 +43,7 @@ struct ifinfo {
int dadcount;
struct timeval timer;
struct timeval expire;
int errors; /* # of errors we've got - detect wedge */
int racnt; /* total # of valid RAs it have got */
@ -51,11 +52,11 @@ struct ifinfo {
};
/* per interface status */
#define IFS_IDLE 0
#define IFS_DELAY 1
#define IFS_PROBE 2
#define IFS_DOWN 3
#define IFS_TENTATIVE 4
#define IFS_IDLE 0
#define IFS_DELAY 1
#define IFS_PROBE 2
#define IFS_DOWN 3
#define IFS_TENTATIVE 4
/* rtsold.c */
extern struct timeval tm_max;