From d5caa62eecc2a8e2d9c03b0c74c3a7a625bba329 Mon Sep 17 00:00:00 2001 From: ume Date: Sun, 17 Aug 2003 11:11:32 +0000 Subject: [PATCH] - 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 --- usr.sbin/rtsold/probe.c | 19 +++--- usr.sbin/rtsold/rtsol.c | 34 +++++----- usr.sbin/rtsold/rtsold.8 | 36 +++++------ usr.sbin/rtsold/rtsold.c | 134 ++++++++++++++++++++++++--------------- usr.sbin/rtsold/rtsold.h | 9 ++- 5 files changed, 136 insertions(+), 96 deletions(-) diff --git a/usr.sbin/rtsold/probe.c b/usr.sbin/rtsold/probe.c index 9b86c63c65ea..b7e7cc626a5d 100644 --- a/usr.sbin/rtsold/probe.c +++ b/usr.sbin/rtsold/probe.c @@ -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 #include +#include #include #include @@ -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; diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c index cbcad8a24d91..46050167020e 100644 --- a/usr.sbin/rtsold/rtsol.c +++ b/usr.sbin/rtsold/rtsol.c @@ -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 #include #include -#include #include #include #include @@ -52,6 +51,7 @@ #include #include +#include #include #include #include @@ -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; diff --git a/usr.sbin/rtsold/rtsold.8 b/usr.sbin/rtsold/rtsold.8 index a3656377287a..2490890a0766 100644 --- a/usr.sbin/rtsold/rtsold.8 +++ b/usr.sbin/rtsold/rtsold.8 @@ -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 diff --git a/usr.sbin/rtsold/rtsold.c b/usr.sbin/rtsold/rtsold.c index 82cae73b62e7..be9d7120a219 100644 --- a/usr.sbin/rtsold/rtsold.c +++ b/usr.sbin/rtsold/rtsold.c @@ -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; } diff --git a/usr.sbin/rtsold/rtsold.h b/usr.sbin/rtsold/rtsold.h index 976a34b4701b..09577a50898f 100644 --- a/usr.sbin/rtsold/rtsold.h +++ b/usr.sbin/rtsold/rtsold.h @@ -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 *));