- 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 d21c6d5071
commit e63e485957
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. * Copyright (C) 1998 WIDE Project.
@ -40,6 +40,7 @@
#include <net/if.h> #include <net/if.h>
#include <net/if_var.h> #include <net/if_var.h>
#include <net/if_dl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet6/in6_var.h> #include <netinet6/in6_var.h>
@ -59,7 +60,7 @@
static struct msghdr sndmhdr; static struct msghdr sndmhdr;
static struct iovec sndiov[2]; static struct iovec sndiov[2];
static int probesock; static int probesock;
static void sendprobe __P((struct in6_addr *, int)); static void sendprobe __P((struct in6_addr *, struct ifinfo *));
int int
probe_init() probe_init()
@ -98,11 +99,12 @@ probe_init()
* 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 void
defrouter_probe(int ifindex) defrouter_probe(struct ifinfo *ifinfo)
{ {
u_char ntopbuf[INET6_ADDRSTRLEN];
struct in6_drlist dr; struct in6_drlist dr;
int s, i; int s, i;
u_char ntopbuf[INET6_ADDRSTRLEN]; int ifindex = ifinfo->sdl->sdl_index;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno)); warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
@ -128,8 +130,7 @@ defrouter_probe(int ifindex)
ntopbuf, INET6_ADDRSTRLEN)); ntopbuf, INET6_ADDRSTRLEN));
continue; /* ignore the address */ continue; /* ignore the address */
} }
sendprobe(&dr.defrouter[i].rtaddr, sendprobe(&dr.defrouter[i].rtaddr, ifinfo);
dr.defrouter[i].if_index);
} }
} }
@ -138,18 +139,20 @@ closeandend:
} }
static void 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 sockaddr_in6 sa6_probe;
struct in6_pktinfo *pi; struct in6_pktinfo *pi;
struct cmsghdr *cm; struct cmsghdr *cm;
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; u_int32_t ifindex = ifinfo->sdl->sdl_index;
int hoplimit = 1; int hoplimit = 1;
memset(&sa6_probe, 0, sizeof(sa6_probe)); memset(&sa6_probe, 0, sizeof(sa6_probe));
sa6_probe.sin6_family = AF_INET6; sa6_probe.sin6_family = AF_INET6;
sa6_probe.sin6_len = sizeof(sa6_probe); sa6_probe.sin6_len = sizeof(sa6_probe);
sa6_probe.sin6_addr = *addr; sa6_probe.sin6_addr = *addr;
sa6_probe.sin6_scope_id = ifinfo->linkid;
sndmhdr.msg_name = (caddr_t)&sa6_probe; sndmhdr.msg_name = (caddr_t)&sa6_probe;
sndmhdr.msg_iov[0].iov_base = NULL; 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. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -35,7 +35,6 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/time.h> #include <sys/time.h>
#include <fcntl.h>
#include <sys/queue.h> #include <sys/queue.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -52,6 +51,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <time.h> #include <time.h>
#include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <err.h> #include <err.h>
@ -68,6 +68,7 @@ static struct msghdr sndmhdr;
static struct iovec rcviov[2]; static struct iovec rcviov[2];
static struct iovec sndiov[2]; static struct iovec sndiov[2];
static struct sockaddr_in6 from; static struct sockaddr_in6 from;
static int rcvcmsglen;
int rssock; int rssock;
@ -80,11 +81,10 @@ static int safefile __P((const char *));
int int
sockopen() sockopen()
{ {
int on;
struct icmp6_filter filt;
static u_char answer[1500];
int rcvcmsglen, sndcmsglen;
static u_char *rcvcmsgbuf = NULL, *sndcmsgbuf = NULL; 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)) + sndcmsglen = rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int)); CMSG_SPACE(sizeof(int));
@ -163,11 +163,9 @@ sockopen()
rcviov[0].iov_base = (caddr_t)answer; rcviov[0].iov_base = (caddr_t)answer;
rcviov[0].iov_len = sizeof(answer); rcviov[0].iov_len = sizeof(answer);
rcvmhdr.msg_name = (caddr_t)&from; rcvmhdr.msg_name = (caddr_t)&from;
rcvmhdr.msg_namelen = sizeof(from);
rcvmhdr.msg_iov = rcviov; rcvmhdr.msg_iov = rcviov;
rcvmhdr.msg_iovlen = 1; rcvmhdr.msg_iovlen = 1;
rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
rcvmhdr.msg_controllen = rcvcmsglen;
/* initialize msghdr for sending packets */ /* initialize msghdr for sending packets */
sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
@ -186,8 +184,12 @@ sendpacket(struct ifinfo *ifinfo)
struct cmsghdr *cm; struct cmsghdr *cm;
int hoplimit = 255; int hoplimit = 255;
int i; 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_base = (caddr_t)ifinfo->rs_data;
sndmhdr.msg_iov[0].iov_len = ifinfo->rs_datalen; sndmhdr.msg_iov[0].iov_len = ifinfo->rs_datalen;
@ -228,17 +230,17 @@ sendpacket(struct ifinfo *ifinfo)
void void
rtsol_input(int s) rtsol_input(int s)
{ {
int i; u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
int *hlimp = NULL; int ifindex = 0, i, *hlimp = NULL;
struct icmp6_hdr *icp;
int ifindex = 0;
struct cmsghdr *cm;
struct in6_pktinfo *pi = NULL; struct in6_pktinfo *pi = NULL;
struct ifinfo *ifi = NULL; struct ifinfo *ifi = NULL;
struct icmp6_hdr *icp;
struct nd_router_advert *nd_ra; 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) { if ((i = recvmsg(s, &rcvmhdr, 0)) < 0) {
warnmsg(LOG_ERR, __func__, "recvmsg: %s", strerror(errno)); warnmsg(LOG_ERR, __func__, "recvmsg: %s", strerror(errno));
return; 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. .\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved. .\" All rights reserved.
@ -56,9 +56,8 @@
.Fl a .Fl a
.\" .\"
.Sh DESCRIPTION .Sh DESCRIPTION
The
.Nm .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. on the specified interfaces.
If a node (re)attaches to a link, If a node (re)attaches to a link,
.Nm .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 all-routers multicast address to discover new routers
and to get non link-local addresses. and to get non link-local addresses.
.Pp .Pp
The
.Nm .Nm
utility should be used on IPv6 hosts should be used on IPv6 hosts
(non-router nodes) .Pq non-router nodes
only. only.
.Pp .Pp
If you invoke the program as If you invoke the program as
@ -98,9 +96,8 @@ Just after invocation of
daemon. daemon.
.It .It
The interface is up after a temporary interface failure. The interface is up after a temporary interface failure.
The
.Nm .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. of the interface is active or not.
Note that some network cards and drivers do not allow the extraction Note that some network cards and drivers do not allow the extraction
of link state. of link state.
@ -154,13 +151,12 @@ Upon receipt of signal
will dump the current internal state into will dump the current internal state into
.Pa /var/run/rtsold.dump . .Pa /var/run/rtsold.dump .
.\" .\"
.Sh OPTIONS .Pp
The options are as follows:
.Bl -tag -width indent .Bl -tag -width indent
.It Fl a .It Fl a
Autoprobe outgoing interface. Autoprobe outgoing interface.
The
.Nm .Nm
utility
will try to find a non-loopback, non-point-to-point, IPv6-capable interface. will try to find a non-loopback, non-point-to-point, IPv6-capable interface.
If If
.Nm .Nm
@ -173,7 +169,8 @@ Enable debugging.
.It Fl D .It Fl D
Enable more debugging including the printing of internal timer information. Enable more debugging including the printing of internal timer information.
.It Fl f .It Fl f
Prevent .Fl f
prevents
.Nm .Nm
from becoming a daemon (foreground mode). from becoming a daemon (foreground mode).
Warning messages are generated to standard error 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 file, and be created by the same owner who runs
.Nm . .Nm .
.El .El
.Sh DIAGNOSTICS .Sh RETURN VALUES
.Ex -std rtsold rtsol The
.Nm
program exits 0 on success, and >0 on failures.
.\" .\"
.Sh FILES .Sh FILES
.Bl -tag -width /var/run/rtsold.dump -compact .Bl -tag -width /var/run/rtsold.dump -compact
@ -231,13 +230,12 @@ dumps internal state on.
.Sh HISTORY .Sh HISTORY
The The
.Nm .Nm
utility is based on the command is based on the
.Nm rtsol .Nm rtsol
utility, which first appeared in WIDE/KAME IPv6 protocol stack kit. command, which first appeared in WIDE/KAME IPv6 protocol stack kit.
The
.Nm rtsol .Nm rtsol
utility is now integrated into is now integrated into
.Nm . .Xr rtsold 8 .
.\" .\"
.Sh BUGS .Sh BUGS
In some operating systems, when a PCMCIA network card is removed 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. * 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 *dumpfilename = "/var/run/rtsold.dump"; /* XXX: should be configurable */
static char *pidfilename = "/var/run/rtsold.pid"; /* should be configurable */ static char *pidfilename = "/var/run/rtsold.pid"; /* should be configurable */
static int ifconfig __P((char *));
#if 0 #if 0
static int ifreconfig __P((char *)); static int ifreconfig __P((char *));
#endif #endif
@ -114,7 +113,6 @@ static void TIMEVAL_SUB __P((struct timeval *, struct timeval *,
static void rtsold_set_dump_file __P((int)); static void rtsold_set_dump_file __P((int));
static void usage __P((char *)); static void usage __P((char *));
static char **autoifprobe __P((void));
int int
main(argc, argv) main(argc, argv)
@ -177,25 +175,7 @@ main(argc, argv)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (aflag) { if ((!aflag && argc == 0) || (aflag && argc != 0)) {
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) {
usage(argv0); usage(argv0);
/*NOTREACHED*/ /*NOTREACHED*/
} }
@ -292,7 +272,9 @@ main(argc, argv)
exit(1); exit(1);
/*NOTREACHED*/ /*NOTREACHED*/
} }
while (argc--) { if (aflag)
argv = autoifprobe();
while (argv && *argv) {
if (ifconfig(*argv)) { if (ifconfig(*argv)) {
warnmsg(LOG_ERR, __func__, warnmsg(LOG_ERR, __func__,
"failed to initialize %s", *argv); "failed to initialize %s", *argv);
@ -391,7 +373,7 @@ main(argc, argv)
return 0; return 0;
} }
static int int
ifconfig(char *ifname) ifconfig(char *ifname)
{ {
struct ifinfo *ifinfo; struct ifinfo *ifinfo;
@ -424,6 +406,15 @@ ifconfig(char *ifname)
if (make_packet(ifinfo)) if (make_packet(ifinfo))
goto bad; 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. * check if the interface is available.
* also check if SIOCGIFMEDIA ioctl is OK on the interface. * also check if SIOCGIFMEDIA ioctl is OK on the interface.
@ -462,6 +453,22 @@ bad:
return(-1); 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 #if 0
static int static int
ifreconfig(char *ifname) ifreconfig(char *ifname)
@ -602,7 +609,7 @@ rtsol_check_timer()
ifinfo->otherconfig = 0; ifinfo->otherconfig = 0;
if (probe && mobile_node) if (probe && mobile_node)
defrouter_probe(ifinfo->sdl->sdl_index); defrouter_probe(ifinfo);
break; break;
} }
case IFS_DELAY: case IFS_DELAY:
@ -804,13 +811,27 @@ warnmsg(priority, func, msg, va_alist)
va_end(ap); va_end(ap);
} }
static char ** /*
* return a list of interfaces which is suitable to sending an RS.
*/
char **
autoifprobe() autoifprobe()
{ {
static char ifname[IFNAMSIZ + 1]; static char **argv = NULL;
static char *argv[2]; static int n = 0;
char **a;
int i, found;
struct ifaddrs *ifap, *ifa, *target; struct ifaddrs *ifap, *ifa, *target;
/* initialize */
while (n--)
free(argv[n]);
if (argv) {
free(argv);
argv = NULL;
}
n = 0;
if (getifaddrs(&ifap) != 0) if (getifaddrs(&ifap) != 0)
return NULL; return NULL;
@ -829,32 +850,43 @@ autoifprobe()
if (ifa->ifa_addr->sa_family != AF_INET6) if (ifa->ifa_addr->sa_family != AF_INET6)
continue; 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; continue;
if (!target) /* if we find multiple candidates, just warn. */
target = ifa; if (n != 0 && dflag > 1)
else { warnx("multiple interfaces found");
/* if we find multiple candidates, failure. */
if (dflag > 1) a = (char **)realloc(argv, (n + 1) * sizeof(char **));
warnx("multiple interfaces found"); if (a == NULL)
target = NULL; err(1, "realloc");
break; 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); freeifaddrs(ifap);
if (target) return argv;
return argv;
else
return (char **)NULL;
} }

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. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -36,6 +36,7 @@ struct ifinfo {
struct sockaddr_dl *sdl; /* link-layer address */ struct sockaddr_dl *sdl; /* link-layer address */
char ifname[IF_NAMESIZE]; /* interface name */ char ifname[IF_NAMESIZE]; /* interface name */
u_int32_t linkid; /* link ID of this interface */
int active; /* interface status */ int active; /* interface status */
int probeinterval; /* interval of probe timer (if necessary) */ int probeinterval; /* interval of probe timer (if necessary) */
int probetimer; /* rest of probe timer */ int probetimer; /* rest of probe timer */
@ -65,11 +66,15 @@ struct ifinfo {
/* rtsold.c */ /* rtsold.c */
extern struct timeval tm_max; extern struct timeval tm_max;
extern int dflag; extern int dflag;
extern int aflag;
extern char *otherconf_script; extern char *otherconf_script;
extern int ifconfig __P((char *));
extern void iflist_init __P((void));
struct ifinfo *find_ifinfo __P((int)); struct ifinfo *find_ifinfo __P((int));
void rtsol_timer_update __P((struct ifinfo *)); void rtsol_timer_update __P((struct ifinfo *));
extern void warnmsg __P((int, const char *, const char *, ...)) extern void warnmsg __P((int, const char *, const char *, ...))
__attribute__((__format__(__printf__, 3, 4))); __attribute__((__format__(__printf__, 3, 4)));
extern char **autoifprobe __P((void));
/* if.c */ /* if.c */
extern int ifinit __P((void)); extern int ifinit __P((void));
@ -87,7 +92,7 @@ extern void rtsol_input __P((int));
/* probe.c */ /* probe.c */
extern int probe_init __P((void)); extern int probe_init __P((void));
extern void defrouter_probe __P((int)); extern void defrouter_probe __P((struct ifinfo *));
/* dump.c */ /* dump.c */
extern void rtsold_dump_file __P((char *)); extern void rtsold_dump_file __P((char *));