- improved the -a option. it can probe a interface automatically when

the interface wake up.  it can be started anytime even when there is
  no network interface on the list of intarfaces in the kernel.
- get a correct link ID for each interface at initialization
  (using scope libraries if HAVE_SCOPELIB is defined).
- fill in sin6_scope_id correctly before sendmsg().

Obtained from:	KAME
MFC after:	1 week
This commit is contained in:
ume 2003-08-17 11:11:32 +00:00
parent a163dd71aa
commit d5caa62eec
5 changed files with 136 additions and 96 deletions

View File

@ -1,4 +1,4 @@
/* $KAME: probe.c,v 1.10 2000/08/13 06:14:59 itojun Exp $ */
/* $KAME: probe.c,v 1.16 2002/06/10 20:00:36 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
@ -40,6 +40,7 @@
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet6/in6_var.h>
@ -59,7 +60,7 @@
static struct msghdr sndmhdr;
static struct iovec sndiov[2];
static int probesock;
static void sendprobe __P((struct in6_addr *, int));
static void sendprobe __P((struct in6_addr *, struct ifinfo *));
int
probe_init()
@ -98,11 +99,12 @@ probe_init()
* Probe if each router in the default router list is still alive.
*/
void
defrouter_probe(int ifindex)
defrouter_probe(struct ifinfo *ifinfo)
{
u_char ntopbuf[INET6_ADDRSTRLEN];
struct in6_drlist dr;
int s, i;
u_char ntopbuf[INET6_ADDRSTRLEN];
int ifindex = ifinfo->sdl->sdl_index;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
@ -128,8 +130,7 @@ defrouter_probe(int ifindex)
ntopbuf, INET6_ADDRSTRLEN));
continue; /* ignore the address */
}
sendprobe(&dr.defrouter[i].rtaddr,
dr.defrouter[i].if_index);
sendprobe(&dr.defrouter[i].rtaddr, ifinfo);
}
}
@ -138,18 +139,20 @@ defrouter_probe(int ifindex)
}
static void
sendprobe(struct in6_addr *addr, int ifindex)
sendprobe(struct in6_addr *addr, struct ifinfo *ifinfo)
{
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
struct sockaddr_in6 sa6_probe;
struct in6_pktinfo *pi;
struct cmsghdr *cm;
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
u_int32_t ifindex = ifinfo->sdl->sdl_index;
int hoplimit = 1;
memset(&sa6_probe, 0, sizeof(sa6_probe));
sa6_probe.sin6_family = AF_INET6;
sa6_probe.sin6_len = sizeof(sa6_probe);
sa6_probe.sin6_addr = *addr;
sa6_probe.sin6_scope_id = ifinfo->linkid;
sndmhdr.msg_name = (caddr_t)&sa6_probe;
sndmhdr.msg_iov[0].iov_base = NULL;

View File

@ -1,4 +1,4 @@
/* $KAME: rtsol.c,v 1.12 2001/11/12 11:47:11 jinmei Exp $ */
/* $KAME: rtsol.c,v 1.26 2003/05/27 06:48:27 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -35,7 +35,6 @@
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/queue.h>
#include <sys/wait.h>
#include <sys/stat.h>
@ -52,6 +51,7 @@
#include <arpa/inet.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <err.h>
@ -68,6 +68,7 @@ static struct msghdr sndmhdr;
static struct iovec rcviov[2];
static struct iovec sndiov[2];
static struct sockaddr_in6 from;
static int rcvcmsglen;
int rssock;
@ -80,11 +81,10 @@ static int safefile __P((const char *));
int
sockopen()
{
int on;
struct icmp6_filter filt;
static u_char answer[1500];
int rcvcmsglen, sndcmsglen;
static u_char *rcvcmsgbuf = NULL, *sndcmsgbuf = NULL;
int sndcmsglen, on;
static u_char answer[1500];
struct icmp6_filter filt;
sndcmsglen = rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int));
@ -163,11 +163,9 @@ sockopen()
rcviov[0].iov_base = (caddr_t)answer;
rcviov[0].iov_len = sizeof(answer);
rcvmhdr.msg_name = (caddr_t)&from;
rcvmhdr.msg_namelen = sizeof(from);
rcvmhdr.msg_iov = rcviov;
rcvmhdr.msg_iovlen = 1;
rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
rcvmhdr.msg_controllen = rcvcmsglen;
/* initialize msghdr for sending packets */
sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
@ -186,8 +184,12 @@ sendpacket(struct ifinfo *ifinfo)
struct cmsghdr *cm;
int hoplimit = 255;
int i;
struct sockaddr_in6 dst;
sndmhdr.msg_name = (caddr_t)&sin6_allrouters;
dst = sin6_allrouters;
dst.sin6_scope_id = ifinfo->linkid;
sndmhdr.msg_name = (caddr_t)&dst;
sndmhdr.msg_iov[0].iov_base = (caddr_t)ifinfo->rs_data;
sndmhdr.msg_iov[0].iov_len = ifinfo->rs_datalen;
@ -228,17 +230,17 @@ sendpacket(struct ifinfo *ifinfo)
void
rtsol_input(int s)
{
int i;
int *hlimp = NULL;
struct icmp6_hdr *icp;
int ifindex = 0;
struct cmsghdr *cm;
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
int ifindex = 0, i, *hlimp = NULL;
struct in6_pktinfo *pi = NULL;
struct ifinfo *ifi = NULL;
struct icmp6_hdr *icp;
struct nd_router_advert *nd_ra;
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
struct cmsghdr *cm;
/* get message */
/* get message. namelen and controllen must always be initialized. */
rcvmhdr.msg_namelen = sizeof(from);
rcvmhdr.msg_controllen = rcvcmsglen;
if ((i = recvmsg(s, &rcvmhdr, 0)) < 0) {
warnmsg(LOG_ERR, __func__, "recvmsg: %s", strerror(errno));
return;

View File

@ -1,4 +1,4 @@
.\" $KAME: rtsold.8,v 1.16 2000/10/15 13:19:05 itojun Exp $
.\" $KAME: rtsold.8,v 1.20 2003/04/11 12:46:12 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@ -56,9 +56,8 @@
.Fl a
.\"
.Sh DESCRIPTION
The
.Nm
utility is the daemon program to send ICMPv6 Router Solicitation messages
is the daemon program to send ICMPv6 Router Solicitation messages
on the specified interfaces.
If a node (re)attaches to a link,
.Nm
@ -66,10 +65,9 @@ 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.
.Pp
The
.Nm
utility should be used on IPv6 hosts
(non-router nodes)
should be used on IPv6 hosts
.Pq non-router nodes
only.
.Pp
If you invoke the program as
@ -98,9 +96,8 @@ Just after invocation of
daemon.
.It
The interface is up after a temporary interface failure.
The
.Nm
utility detects such failures by periodically probing to see if the status
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.
@ -154,13 +151,12 @@ Upon receipt of signal
will dump the current internal state into
.Pa /var/run/rtsold.dump .
.\"
.Sh OPTIONS
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl a
Autoprobe outgoing interface.
The
.Nm
utility
will try to find a non-loopback, non-point-to-point, IPv6-capable interface.
If
.Nm
@ -173,7 +169,8 @@ Enable debugging.
.It Fl D
Enable more debugging including the printing of internal timer information.
.It Fl f
Prevent
.Fl f
prevents
.Nm
from becoming a daemon (foreground mode).
Warning messages are generated to standard error
@ -212,8 +209,10 @@ must be the absolute path from root to the script file, be a regular
file, and be created by the same owner who runs
.Nm .
.El
.Sh DIAGNOSTICS
.Ex -std rtsold rtsol
.Sh RETURN VALUES
The
.Nm
program exits 0 on success, and >0 on failures.
.\"
.Sh FILES
.Bl -tag -width /var/run/rtsold.dump -compact
@ -231,13 +230,12 @@ dumps internal state on.
.Sh HISTORY
The
.Nm
utility is based on the
command is based on the
.Nm rtsol
utility, which first appeared in WIDE/KAME IPv6 protocol stack kit.
The
command, which first appeared in WIDE/KAME IPv6 protocol stack kit.
.Nm rtsol
utility is now integrated into
.Nm .
is now integrated into
.Xr rtsold 8 .
.\"
.Sh BUGS
In some operating systems, when a PCMCIA network card is removed

View File

@ -1,4 +1,4 @@
/* $KAME: rtsold.c,v 1.31 2001/05/22 06:03:06 jinmei Exp $ */
/* $KAME: rtsold.c,v 1.67 2003/05/17 18:16:15 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -101,7 +101,6 @@ static int do_dump;
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 *));
#if 0
static int ifreconfig __P((char *));
#endif
@ -114,7 +113,6 @@ static void TIMEVAL_SUB __P((struct timeval *, struct timeval *,
static void rtsold_set_dump_file __P((int));
static void usage __P((char *));
static char **autoifprobe __P((void));
int
main(argc, argv)
@ -177,25 +175,7 @@ main(argc, argv)
argc -= optind;
argv += optind;
if (aflag) {
int i;
if (argc != 0) {
usage(argv0);
/*NOTREACHED*/
}
argv = autoifprobe();
if (!argv) {
errx(1, "could not autoprobe interface");
/*NOTREACHED*/
}
for (i = 0; argv[i]; i++)
;
argc = i;
}
if (argc == 0) {
if ((!aflag && argc == 0) || (aflag && argc != 0)) {
usage(argv0);
/*NOTREACHED*/
}
@ -292,7 +272,9 @@ main(argc, argv)
exit(1);
/*NOTREACHED*/
}
while (argc--) {
if (aflag)
argv = autoifprobe();
while (argv && *argv) {
if (ifconfig(*argv)) {
warnmsg(LOG_ERR, __func__,
"failed to initialize %s", *argv);
@ -391,7 +373,7 @@ main(argc, argv)
return 0;
}
static int
int
ifconfig(char *ifname)
{
struct ifinfo *ifinfo;
@ -424,6 +406,15 @@ ifconfig(char *ifname)
if (make_packet(ifinfo))
goto bad;
/* set link ID of this interface. */
#ifdef HAVE_SCOPELIB
if (inet_zoneid(AF_INET6, 2, ifname, &ifinfo->linkid))
goto bad;
#else
/* XXX: assume interface IDs as link IDs */
ifinfo->linkid = ifinfo->sdl->sdl_index;
#endif
/*
* check if the interface is available.
* also check if SIOCGIFMEDIA ioctl is OK on the interface.
@ -462,6 +453,22 @@ ifconfig(char *ifname)
return(-1);
}
void
iflist_init()
{
struct ifinfo *ifi, *next;
for (ifi = iflist; ifi; ifi = next) {
next = ifi->next;
if (ifi->sdl)
free(ifi->sdl);
if (ifi->rs_data)
free(ifi->rs_data);
free(ifi);
iflist = NULL;
}
}
#if 0
static int
ifreconfig(char *ifname)
@ -602,7 +609,7 @@ rtsol_check_timer()
ifinfo->otherconfig = 0;
if (probe && mobile_node)
defrouter_probe(ifinfo->sdl->sdl_index);
defrouter_probe(ifinfo);
break;
}
case IFS_DELAY:
@ -804,13 +811,27 @@ warnmsg(priority, func, msg, va_alist)
va_end(ap);
}
static char **
/*
* return a list of interfaces which is suitable to sending an RS.
*/
char **
autoifprobe()
{
static char ifname[IFNAMSIZ + 1];
static char *argv[2];
static char **argv = NULL;
static int n = 0;
char **a;
int i, found;
struct ifaddrs *ifap, *ifa, *target;
/* initialize */
while (n--)
free(argv[n]);
if (argv) {
free(argv);
argv = NULL;
}
n = 0;
if (getifaddrs(&ifap) != 0)
return NULL;
@ -829,32 +850,43 @@ autoifprobe()
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
if (target && strcmp(target->ifa_name, ifa->ifa_name) == 0)
found = 0;
for (i = 0; i < n; i++) {
if (strcmp(argv[i], ifa->ifa_name) == 0) {
found++;
break;
}
}
if (found)
continue;
if (!target)
target = ifa;
else {
/* if we find multiple candidates, failure. */
if (dflag > 1)
warnx("multiple interfaces found");
target = NULL;
break;
/* if we find multiple candidates, just warn. */
if (n != 0 && dflag > 1)
warnx("multiple interfaces found");
a = (char **)realloc(argv, (n + 1) * sizeof(char **));
if (a == NULL)
err(1, "realloc");
argv = a;
argv[n] = strdup(ifa->ifa_name);
if (!argv[n])
err(1, "malloc");
n++;
argv[n] = NULL;
}
if (n) {
a = (char **)realloc(argv, (n + 1) * sizeof(char **));
if (a == NULL)
err(1, "realloc");
argv = a;
argv[n] = NULL;
if (dflag > 0) {
for (i = 0; i < n; i++)
warnx("probing %s", argv[i]);
}
}
if (target) {
strncpy(ifname, target->ifa_name, sizeof(ifname) - 1);
ifname[sizeof(ifname) - 1] = '\0';
argv[0] = ifname;
argv[1] = NULL;
if (dflag > 0)
warnx("probing %s", argv[0]);
}
freeifaddrs(ifap);
if (target)
return argv;
else
return (char **)NULL;
return argv;
}

View File

@ -1,4 +1,4 @@
/* $KAME: rtsold.h,v 1.11 2000/10/10 06:18:04 itojun Exp $ */
/* $KAME: rtsold.h,v 1.19 2003/04/16 09:48:15 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -36,6 +36,7 @@ struct ifinfo {
struct sockaddr_dl *sdl; /* link-layer address */
char ifname[IF_NAMESIZE]; /* interface name */
u_int32_t linkid; /* link ID of this interface */
int active; /* interface status */
int probeinterval; /* interval of probe timer (if necessary) */
int probetimer; /* rest of probe timer */
@ -65,11 +66,15 @@ struct ifinfo {
/* rtsold.c */
extern struct timeval tm_max;
extern int dflag;
extern int aflag;
extern char *otherconf_script;
extern int ifconfig __P((char *));
extern void iflist_init __P((void));
struct ifinfo *find_ifinfo __P((int));
void rtsol_timer_update __P((struct ifinfo *));
extern void warnmsg __P((int, const char *, const char *, ...))
__attribute__((__format__(__printf__, 3, 4)));
extern char **autoifprobe __P((void));
/* if.c */
extern int ifinit __P((void));
@ -87,7 +92,7 @@ extern void rtsol_input __P((int));
/* probe.c */
extern int probe_init __P((void));
extern void defrouter_probe __P((int));
extern void defrouter_probe __P((struct ifinfo *));
/* dump.c */
extern void rtsold_dump_file __P((char *));