+++ /dev/null
-#!/bin/sh
-#
-# $OpenBSD: rtsold,v 1.1 2011/07/06 18:55:36 robert Exp $
-
-daemon="/usr/sbin/rtsold"
-
-. /etc/rc.d/rc.subr
-
-rc_reload=NO
-
-rc_cmd $1
+++ /dev/null
-# $OpenBSD: Makefile,v 1.8 2004/01/02 23:52:17 itojun Exp $
-
-PROG= rtsol
-SRCS= rtsold.c rtsol.c if.c probe.c
-
-CPPFLAGS+=-DSMALL
-
-#MAN= rtsold.8
-NOMAN= yes
-
-LDADD+= -lutil
-DPADD+= ${LIBUTIL}
-
-.PATH: ${.CURDIR}/../../usr.sbin/rtsold
-
-.include <bsd.prog.mk>
+++ /dev/null
-# $OpenBSD: Makefile,v 1.7 2004/01/02 23:46:04 itojun Exp $
-
-PROG= rtsold
-SRCS= rtsold.c rtsol.c if.c probe.c dump.c
-
-MAN= rtsold.8
-MLINKS= rtsold.8 rtsol.8
-
-LDADD+= -lutil
-DPADD+= ${LIBUTIL}
-
-.include <bsd.prog.mk>
+++ /dev/null
-/* $OpenBSD: dump.c,v 1.15 2013/04/21 19:46:31 deraadt Exp $ */
-/* $KAME: dump.c,v 1.10 2002/05/31 10:10:03 itojun Exp $ */
-
-/*
- * 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:
- * 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/time.h>
-#include <sys/socket.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/icmp6.h>
-
-#include <syslog.h>
-#include <time.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include "rtsold.h"
-
-static FILE *fp;
-
-extern struct ifinfo *iflist;
-
-static void dump_interface_status(void);
-static char *sec2str(time_t);
-char *ifstatstr[] = {"IDLE", "DELAY", "PROBE", "DOWN", "TENTATIVE"};
-
-static void
-dump_interface_status(void)
-{
- struct ifinfo *ifinfo;
- struct timeval now;
-
- gettimeofday(&now, NULL);
-
- for (ifinfo = iflist; ifinfo; ifinfo = ifinfo->next) {
- fprintf(fp, "Interface %s\n", ifinfo->ifname);
- fprintf(fp, " probe interval: ");
- if (ifinfo->probeinterval) {
- fprintf(fp, "%d\n", ifinfo->probeinterval);
- fprintf(fp, " probe timer: %d\n", ifinfo->probetimer);
- } else {
- fprintf(fp, "infinity\n");
- fprintf(fp, " no probe timer\n");
- }
- fprintf(fp, " interface status: %s\n",
- ifinfo->active > 0 ? "active" : "inactive");
-#ifndef SMALL
- fprintf(fp, " other config: %s\n",
- ifinfo->otherconfig ? "on" : "off");
-#endif
- fprintf(fp, " rtsold status: %s\n", ifstatstr[ifinfo->state]);
- fprintf(fp, " carrier detection: %s\n",
- ifinfo->mediareqok ? "available" : "unavailable");
- fprintf(fp, " probes: %d, dadcount = %d\n",
- ifinfo->probes, ifinfo->dadcount);
- if (ifinfo->stoptimer)
- fprintf(fp, " no timer\n");
- else {
- fprintf(fp, " timer: interval=%lld:%ld, expire=%s\n",
- (long long)ifinfo->timer.tv_sec,
- ifinfo->timer.tv_usec,
- (ifinfo->expire.tv_sec < now.tv_sec) ? "expired"
- : sec2str(ifinfo->expire.tv_sec - now.tv_sec));
- }
- fprintf(fp, " number of valid RAs: %d\n", ifinfo->racnt);
- }
-}
-
-void
-rtsold_dump_file(char *dumpfile)
-{
- if ((fp = fopen(dumpfile, "w")) == NULL) {
- warnmsg(LOG_WARNING, __func__, "open a dump file(%s): %s",
- dumpfile, strerror(errno));
- return;
- }
- dump_interface_status();
- fclose(fp);
-}
-
-static char *
-sec2str(time_t total)
-{
- static char result[256];
- time_t days;
- int hours, mins, secs;
- int first = 1;
- char *p = result;
- char *ep = &result[sizeof(result)];
- int n;
-
- days = total / 3600 / 24;
- hours = (total / 3600) % 24;
- mins = (total / 60) % 60;
- secs = total % 60;
-
- if (days) {
- first = 0;
- n = snprintf(p, ep - p, "%lldd", (long long)days);
- if (n < 0 || n >= ep - p)
- return "?";
- p += n;
- }
- if (!first || hours) {
- first = 0;
- n = snprintf(p, ep - p, "%dh", hours);
- if (n < 0 || n >= ep - p)
- return "?";
- p += n;
- }
- if (!first || mins) {
- first = 0;
- n = snprintf(p, ep - p, "%dm", mins);
- if (n < 0 || n >= ep - p)
- return "?";
- p += n;
- }
- snprintf(p, ep - p, "%ds", secs);
- return(result);
-}
+++ /dev/null
-/* $OpenBSD: if.c,v 1.28 2014/11/18 20:54:29 krw Exp $ */
-/* $KAME: if.c,v 1.18 2002/05/31 10:10:03 itojun Exp $ */
-
-/*
- * 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.
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/ioctl.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/if_types.h>
-#include <net/route.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <netinet/icmp6.h>
-
-#include <netinet6/in6_var.h>
-
-#include <err.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <limits.h>
-#include <ifaddrs.h>
-#include <netdb.h>
-
-#include "rtsold.h"
-
-extern int rssock;
-static int ifsock;
-
-static int get_llflag(const char *);
-
-int
-ifinit(void)
-{
- ifsock = rssock;
-
- return(0);
-}
-
-int
-get_rdomain(char *name)
-{
- int rv = 0, s;
- struct ifreq ifr;
-
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
- warnmsg(LOG_ERR, __func__,
- "get_rdomain socket: %s", strerror(errno));
-
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGIFRDOMAIN, (caddr_t)&ifr) != -1)
- rv = ifr.ifr_rdomainid;
-
- close(s);
- return rv;
-}
-
-
-int
-interface_up(char *name)
-{
- struct ifreq ifr;
- int llflag;
-
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ioctl(ifsock, SIOCGIFXFLAGS, (caddr_t)&ifr) < 0)
- warn("SIOCGIFXFLAGS");
- ifr.ifr_flags &= ~IFXF_NOINET6;
- ifr.ifr_flags |= IFXF_AUTOCONF6;
- if (ioctl(ifsock, SIOCSIFXFLAGS, (caddr_t)&ifr) < 0)
- warn("SIOCSIFXFLAGS");
-
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
- warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s",
- strerror(errno));
- return(-1);
- }
- if (!(ifr.ifr_flags & IFF_UP)) {
- ifr.ifr_flags |= IFF_UP;
- if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
- warnmsg(LOG_ERR, __func__,
- "ioctl(SIOCSIFFLAGS): %s", strerror(errno));
- return(-1);
- }
-
- warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name);
-
- llflag = get_llflag(name);
- if (llflag < 0) {
- warnmsg(LOG_WARNING, __func__,
- "get_llflag() failed, anyway I'll try");
- return 0;
- }
-
- if (!(llflag & IN6_IFF_NOTREADY)) {
- warnmsg(LOG_DEBUG, __func__, "%s is ready", name);
- return(0);
- } else {
- if (llflag & IN6_IFF_TENTATIVE) {
- warnmsg(LOG_DEBUG, __func__, "%s is tentative",
- name);
- return IFS_TENTATIVE;
- }
- if (llflag & IN6_IFF_DUPLICATED)
- warnmsg(LOG_DEBUG, __func__, "%s is duplicated",
- name);
- return -1;
- }
-}
-
-int
-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));
- if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) {
- warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFFLAGS) on %s: %s",
- ifname, strerror(errno));
- return(-1);
- }
- /*
- * if one of UP and RUNNING flags is dropped,
- * the interface is not active.
- */
- if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
- goto inactive;
- }
-
- /* Next, check carrier on the interface, if possible */
- if (!ifinfo->mediareqok)
- goto active;
- memset(&ifmr, 0, sizeof(ifmr));
- strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
-
- if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
- if (errno != EINVAL) {
- warnmsg(LOG_DEBUG, __func__,
- "ioctl(SIOCGIFMEDIA) on %s: %s",
- ifname, strerror(errno));
- return(-1);
- }
- /*
- * EINVAL simply means that the interface does not support
- * the SIOCGIFMEDIA ioctl. We regard it alive.
- */
- ifinfo->mediareqok = 0;
- goto active;
- }
-
- if (ifmr.ifm_status & IFM_AVALID) {
- switch (ifmr.ifm_active & IFM_NMASK) {
- case IFM_ETHER:
- case IFM_IEEE80211:
- if (ifmr.ifm_status & IFM_ACTIVE)
- goto active;
- else
- goto inactive;
- break;
- default:
- goto inactive;
- }
- }
-
- inactive:
- return(0);
-
- active:
- return(1);
-}
-
-#define ROUNDUP8(a) (1 + (((a) - 1) | 7))
-
-int
-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);
- }
-}
-
-void
-lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt)
-{
- char *addr;
-
- ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */
-
- 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);
- break;
- default:
- warnmsg(LOG_ERR, __func__,
- "unsupported link type(%d)", sdl->sdl_type);
- exit(1);
- }
-
- return;
-}
-
-struct sockaddr_dl *
-if_nametosdl(char *name)
-{
- struct ifaddrs *ifap, *ifa;
- struct sockaddr_dl *sdl;
-
- if (getifaddrs(&ifap) != 0)
- return (NULL);
-
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (strcmp(ifa->ifa_name, name) != 0)
- continue;
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
-
- sdl = malloc(ifa->ifa_addr->sa_len);
- if (!sdl)
- continue; /*XXX*/
-
- memcpy(sdl, ifa->ifa_addr, ifa->ifa_addr->sa_len);
- freeifaddrs(ifap);
- return (sdl);
- }
-
- freeifaddrs(ifap);
- return (NULL);
-}
-
-int
-getinet6sysctl(int proto, int code)
-{
- int mib[] = { CTL_NET, PF_INET6, proto, 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)
- return -1;
- else
- return value;
-}
-
-int
-setinet6sysctl(int proto, int code, int newval)
-{
- int mib[] = { CTL_NET, PF_INET6, proto, 0 };
- int value;
- size_t size;
-
- mib[3] = code;
- size = sizeof(value);
- if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size,
- &newval, sizeof(newval)) < 0)
- return -1;
- else
- return value;
-}
-
-/* get ia6_flags for link-local addr on if. returns -1 on error. */
-static int
-get_llflag(const char *name)
-{
- struct ifaddrs *ifap, *ifa;
- struct in6_ifreq ifr6;
- struct sockaddr_in6 *sin6;
- int s;
-
- if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
- warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s",
- strerror(errno));
- exit(1);
- }
- if (getifaddrs(&ifap) != 0) {
- warnmsg(LOG_ERR, __func__, "getifaddrs: %s",
- strerror(errno));
- exit(1);
- }
-
- 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;
-
- memset(&ifr6, 0, sizeof(ifr6));
- strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
- memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
- if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
- warnmsg(LOG_ERR, __func__,
- "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
- exit(1);
- }
-
- freeifaddrs(ifap);
- close(s);
- return ifr6.ifr_ifru.ifru_flags6;
- }
-
- freeifaddrs(ifap);
- close(s);
- return -1;
-}
+++ /dev/null
-/* $OpenBSD: probe.c,v 1.14 2013/08/15 13:57:30 bluhm Exp $ */
-/* $KAME: probe.c,v 1.16 2002/06/10 20:00:36 itojun Exp $ */
-
-/*
- * 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:
- * 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/types.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/uio.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/if_dl.h>
-
-#include <netinet/in.h>
-#include <netinet6/in6_var.h>
-#include <netinet/icmp6.h>
-#include <netinet6/nd6.h>
-
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <syslog.h>
-#include <stdlib.h>
-
-#include "rtsold.h"
-
-static struct msghdr sndmhdr;
-static struct iovec sndiov[2];
-static int probesock;
-static void sendprobe(struct in6_addr *, struct ifinfo *);
-
-int
-probe_init(void)
-{
- 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, __func__, "malloc failed");
- return(-1);
- }
-
- if ((probesock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
- warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
- return(-1);
- }
-
- /* make the socket send-only */
- if (shutdown(probesock, 0)) {
- warnmsg(LOG_ERR, __func__, "shutdown: %s", strerror(errno));
- return(-1);
- }
-
- /* 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 = scmsglen;
- return(0);
-}
-
-/*
- * Probe if each router in the default router list is still alive.
- */
-void
-defrouter_probe(struct ifinfo *ifinfo)
-{
- u_char ntopbuf[INET6_ADDRSTRLEN];
- int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_DRLIST };
- char *buf;
- struct in6_defrouter *p, *ep;
- size_t l;
- int ifindex = ifinfo->sdl->sdl_index;
-
- if (!ifindex)
- return;
-
- if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) {
- warnmsg(LOG_ERR, __func__, "sysctl(ICMPV6CTL_ND6_DRLIST): %s",
- strerror(errno));
- return;
- }
- if (l == 0)
- return;
- buf = malloc(l);
- if (buf == NULL) {
- warnmsg(LOG_ERR, __func__, "malloc: %s", strerror(errno));
- return;
- }
- if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
- warnmsg(LOG_ERR, __func__, "sysctl(ICMPV6CTL_ND6_DRLIST): %s",
- strerror(errno));
- free(buf);
- return;
- }
-
- ep = (struct in6_defrouter *)(buf + l);
- for (p = (struct in6_defrouter *)buf; p < ep; p++) {
- if (p->if_index == ifindex) {
- /* sanity check */
- if (!IN6_IS_ADDR_LINKLOCAL(&p->rtaddr.sin6_addr)) {
- warnmsg(LOG_ERR, __func__,
- "default router list contains a "
- "non-link-local address(%s)",
- inet_ntop(AF_INET6,
- &p->rtaddr.sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN));
- continue; /* ignore the address */
- }
- sendprobe(&p->rtaddr.sin6_addr, ifinfo);
- }
- }
- free(buf);
-}
-
-static void
-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_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;
- sndmhdr.msg_iov[0].iov_len = 0;
-
- cm = CMSG_FIRSTHDR(&sndmhdr);
- /* specify the outgoing interface */
- cm->cmsg_level = IPPROTO_IPV6;
- cm->cmsg_type = IPV6_PKTINFO;
- cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
- pi = (struct in6_pktinfo *)CMSG_DATA(cm);
- memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/
- pi->ipi6_ifindex = ifindex;
-
- /* specify the hop limit of the packet for safety */
- cm = CMSG_NXTHDR(&sndmhdr, cm);
- cm->cmsg_level = IPPROTO_IPV6;
- cm->cmsg_type = IPV6_HOPLIMIT;
- cm->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
-
- warnmsg(LOG_DEBUG, __func__, "probe a router %s on %s",
- inet_ntop(AF_INET6, addr, ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(ifindex, ifnamebuf));
-
- if (sendmsg(probesock, &sndmhdr, 0))
- warnmsg(LOG_ERR, __func__, "sendmsg on %s: %s",
- if_indextoname(ifindex, ifnamebuf), strerror(errno));
-}
+++ /dev/null
-/* $OpenBSD: rtsol.c,v 1.19 2013/10/21 09:58:14 phessler Exp $ */
-/* $KAME: rtsol.c,v 1.15 2002/05/31 10:10:03 itojun Exp $ */
-
-/*
- * 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.
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/time.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/if_dl.h>
-
-#include <netinet/in.h>
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet/icmp6.h>
-
-#include <arpa/inet.h>
-
-#include <time.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <err.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <fcntl.h>
-
-#include "rtsold.h"
-
-#define ALLROUTER "ff02::2"
-
-static struct msghdr rcvmhdr;
-static struct msghdr sndmhdr;
-static struct iovec rcviov[2];
-static struct iovec sndiov[2];
-static struct sockaddr_in6 from;
-
-int rssock;
-
-static struct sockaddr_in6 sin6_allrouters = {sizeof(sin6_allrouters), AF_INET6};
-
-#ifndef SMALL
-void call_script(char *, char *);
-int safefile(const char *);
-#endif
-
-int
-sockopen(u_int rdomain)
-{
- static u_char *rcvcmsgbuf = NULL, *sndcmsgbuf = NULL;
- int rcvcmsglen, sndcmsglen, on;
- static u_char answer[1500];
- struct icmp6_filter filt;
-
- sndcmsglen = rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
- CMSG_SPACE(sizeof(int));
- if (rcvcmsgbuf == NULL && (rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
- warnmsg(LOG_ERR, __func__,
- "malloc for receive msghdr failed");
- return(-1);
- }
- if (sndcmsgbuf == NULL && (sndcmsgbuf = malloc(sndcmsglen)) == NULL) {
- warnmsg(LOG_ERR, __func__,
- "malloc for send msghdr failed");
- return(-1);
- }
- memset(&sin6_allrouters, 0, sizeof(struct sockaddr_in6));
- sin6_allrouters.sin6_family = AF_INET6;
- sin6_allrouters.sin6_len = sizeof(sin6_allrouters);
- if (inet_pton(AF_INET6, ALLROUTER,
- &sin6_allrouters.sin6_addr.s6_addr) != 1) {
- warnmsg(LOG_ERR, __func__, "inet_pton failed for %s",
- ALLROUTER);
- return(-1);
- }
-
- if ((rssock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
- warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
- return(-1);
- }
-
- /* Set our preferred routing table */
- if (setsockopt(rssock, SOL_SOCKET, SO_RTABLE,
- &rdomain, sizeof(rdomain)) < 0) {
- warnmsg(LOG_ERR, __func__, "IPV6_RECVPKTINFO: %s",
- strerror(errno));
- exit(1);
- }
-
- /* specify to tell receiving interface */
- on = 1;
- if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
- sizeof(on)) < 0) {
- warnmsg(LOG_ERR, __func__, "IPV6_RECVPKTINFO: %s",
- strerror(errno));
- exit(1);
- }
-
- on = 1;
- /* specify to tell value of hoplimit field of received IP6 hdr */
- if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
- sizeof(on)) < 0) {
- warnmsg(LOG_ERR, __func__, "IPV6_RECVHOPLIMIT: %s",
- strerror(errno));
- exit(1);
- }
-
- /* specfiy to accept only router advertisements on the socket */
- ICMP6_FILTER_SETBLOCKALL(&filt);
- ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
- if (setsockopt(rssock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
- sizeof(filt)) == -1) {
- warnmsg(LOG_ERR, __func__, "setsockopt(ICMP6_FILTER): %s",
- strerror(errno));
- return(-1);
- }
-
- /* initialize msghdr for receiving packets */
- 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);
- sndmhdr.msg_iov = sndiov;
- sndmhdr.msg_iovlen = 1;
- sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
- sndmhdr.msg_controllen = sndcmsglen;
-
- return(rssock);
-}
-
-void
-sendpacket(struct ifinfo *ifinfo)
-{
- struct in6_pktinfo *pi;
- struct cmsghdr *cm;
- int hoplimit = 255;
- struct sockaddr_in6 dst;
- ssize_t i;
-
- 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;
-
- cm = CMSG_FIRSTHDR(&sndmhdr);
- /* specify the outgoing interface */
- cm->cmsg_level = IPPROTO_IPV6;
- cm->cmsg_type = IPV6_PKTINFO;
- cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
- pi = (struct in6_pktinfo *)CMSG_DATA(cm);
- memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/
- pi->ipi6_ifindex = ifinfo->sdl->sdl_index;
-
- /* specify the hop limit of the packet */
- cm = CMSG_NXTHDR(&sndmhdr, cm);
- cm->cmsg_level = IPPROTO_IPV6;
- cm->cmsg_type = IPV6_HOPLIMIT;
- cm->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
-
- warnmsg(LOG_DEBUG, __func__,
- "send RS on %s, whose state is %d",
- ifinfo->ifname, ifinfo->state);
-
- i = sendmsg(rssock, &sndmhdr, 0);
-
- if (i < 0 || i != ifinfo->rs_datalen) {
- /*
- * ENETDOWN is not so serious, especially when using several
- * network cards on a mobile node. We ignore it.
- */
- if (errno != ENETDOWN || dflag > 0)
- warnmsg(LOG_ERR, __func__, "sendmsg on %s: %s",
- ifinfo->ifname, strerror(errno));
- }
-
- /* update counter */
- ifinfo->probes++;
-}
-
-void
-rtsol_input(int s)
-{
- u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
- int ifindex = 0, *hlimp = NULL;
- struct in6_pktinfo *pi = NULL;
- struct ifinfo *ifi = NULL;
- struct icmp6_hdr *icp;
- struct cmsghdr *cm;
- ssize_t i;
-#ifndef SMALL
- struct nd_router_advert *nd_ra;
-#endif
-
- /* get message */
- if ((i = recvmsg(s, &rcvmhdr, 0)) < 0) {
- warnmsg(LOG_ERR, __func__, "recvmsg: %s", strerror(errno));
- return;
- }
-
- /* extract optional information via Advanced API */
- for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr); cm;
- cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) {
- if (cm->cmsg_level == IPPROTO_IPV6 &&
- cm->cmsg_type == IPV6_PKTINFO &&
- cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
- pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
- ifindex = pi->ipi6_ifindex;
- }
- if (cm->cmsg_level == IPPROTO_IPV6 &&
- cm->cmsg_type == IPV6_HOPLIMIT &&
- cm->cmsg_len == CMSG_LEN(sizeof(int)))
- hlimp = (int *)CMSG_DATA(cm);
- }
-
- if (ifindex == 0) {
- warnmsg(LOG_ERR, __func__,
- "failed to get receiving interface");
- return;
- }
- if (hlimp == NULL) {
- warnmsg(LOG_ERR, __func__,
- "failed to get receiving hop limit");
- return;
- }
-
- if (i < sizeof(struct nd_router_advert)) {
- warnmsg(LOG_ERR, __func__,
- "packet size(%zd) is too short", i);
- return;
- }
-
- icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
-
- if (icp->icmp6_type != ND_ROUTER_ADVERT) {
- warnmsg(LOG_ERR, __func__,
- "invalid icmp type(%d) from %s on %s", icp->icmp6_type,
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
-
- if (icp->icmp6_code != 0) {
- warnmsg(LOG_ERR, __func__,
- "invalid icmp code(%d) from %s on %s", icp->icmp6_code,
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
-
- if (*hlimp != 255) {
- warnmsg(LOG_NOTICE, __func__,
- "invalid RA with hop limit(%d) from %s on %s",
- *hlimp,
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
-
- if (pi && !IN6_IS_ADDR_LINKLOCAL(&from.sin6_addr)) {
- warnmsg(LOG_NOTICE, __func__,
- "invalid RA with non link-local source from %s on %s",
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
-
- /* xxx: more validation? */
-
- if ((ifi = find_ifinfo(pi->ipi6_ifindex)) == NULL) {
- warnmsg(LOG_NOTICE, __func__,
- "received RA from %s on an unexpected IF(%s)",
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
-
- warnmsg(LOG_DEBUG, __func__,
- "received RA from %s on %s, state is %d",
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, INET6_ADDRSTRLEN),
- ifi->ifname, ifi->state);
-
-#ifndef SMALL
- nd_ra = (struct nd_router_advert *)icp;
-
- /*
- * Process the "O bit."
- * If the value of OtherConfigFlag changes from FALSE to TRUE, the
- * host should invoke the stateful autoconfiguration protocol,
- * requesting information.
- * [RFC 2462 Section 5.5.3]
- */
- if (((nd_ra->nd_ra_flags_reserved) & ND_RA_FLAG_OTHER) &&
- !ifi->otherconfig) {
- warnmsg(LOG_DEBUG, __func__,
- "OtherConfigFlag on %s is turned on", ifi->ifname);
- ifi->otherconfig = 1;
- call_script(otherconf_script, ifi->ifname);
- }
-#endif
-
- ifi->racnt++;
-
- switch (ifi->state) {
- case IFS_IDLE: /* should be ignored */
- case IFS_DELAY: /* right? */
- break;
- case IFS_PROBE:
- ifi->state = IFS_IDLE;
- ifi->probes = 0;
- rtsol_timer_update(ifi);
- break;
- }
-}
-
-#ifndef SMALL
-void
-call_script(char *scriptpath, char *ifname)
-{
- pid_t pid, wpid;
-
- if (scriptpath == NULL)
- return;
-
- /* launch the script */
- pid = fork();
- if (pid < 0) {
- warnmsg(LOG_ERR, __func__,
- "failed to fork: %s", strerror(errno));
- return;
- } else if (pid) {
- int wstatus;
-
- do {
- wpid = wait(&wstatus);
- } while (wpid != pid && wpid > 0);
-
- if (wpid < 0)
- warnmsg(LOG_ERR, __func__,
- "wait: %s", strerror(errno));
- else {
- warnmsg(LOG_DEBUG, __func__,
- "script \"%s\" terminated", scriptpath);
- }
- } else {
- char *argv[3];
- int fd;
-
- argv[0] = scriptpath;
- argv[1] = ifname;
- argv[2] = NULL;
-
- if (safefile(scriptpath) != 0) {
- warnmsg(LOG_ERR, __func__,
- "script \"%s\" cannot be executed safely",
- scriptpath);
- exit(1);
- }
-
- if ((fd = open("/dev/null", O_RDWR)) != -1) {
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- if (fd > STDERR_FILENO)
- close(fd);
- }
-
- execv(scriptpath, argv);
-
- warnmsg(LOG_ERR, __func__, "child: exec failed: %s",
- strerror(errno));
- exit(1);
- }
-
- return;
-}
-
-int
-safefile(const char *path)
-{
- struct stat s;
- uid_t myuid;
-
- /* no setuid */
- if (getuid() != geteuid()) {
- warnmsg(LOG_NOTICE, __func__,
- "setuid'ed execution not allowed\n");
- return (-1);
- }
-
- if (lstat(path, &s) != 0) {
- warnmsg(LOG_NOTICE, __func__, "lstat failed: %s",
- strerror(errno));
- return (-1);
- }
-
- /* the file must be owned by the running uid */
- myuid = getuid();
- if (s.st_uid != myuid) {
- warnmsg(LOG_NOTICE, __func__,
- "%s has invalid owner uid\n", path);
- return (-1);
- }
-
- switch (s.st_mode & S_IFMT) {
- case S_IFREG:
- break;
- default:
- warnmsg(LOG_NOTICE, __func__,
- "%s is an invalid file type 0x%o\n",
- path, (s.st_mode & S_IFMT));
- return (-1);
- }
-
- return (0);
-}
-#endif
+++ /dev/null
-.\" $OpenBSD: rtsold.8,v 1.33 2014/08/27 14:04:16 florian Exp $
-.\" $KAME: rtsold.8,v 1.17 2001/07/09 22:30:37 itojun Exp $
-.\"
-.\" 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.
-.\"
-.Dd $Mdocdate: August 27 2014 $
-.Dt RTSOLD 8
-.Os
-.\"
-.Sh NAME
-.Nm rtsold
-.Nd router solicitation daemon
-.\"
-.Sh SYNOPSIS
-.Nm rtsold
-.Op Fl 1DdFfm
-.Op Fl O Ar script-name
-.Ar interface ...
-.Nm rtsold
-.Op Fl 1DdFfm
-.Fl a
-.Pp
-.Nm rtsol
-.Op Fl DdF
-.Op Fl O Ar script-name
-.Ar interface ...
-.Nm rtsol
-.Op Fl DdF
-.Fl a
-.\"
-.Sh DESCRIPTION
-.Nm
-is the daemon program to send ICMPv6 Router Solicitation messages
-on the specified interfaces.
-If a node (re)attaches to a link,
-.Nm
-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
-.Nm
-should be used on IPv6 hosts
-.Pq non-router nodes
-only.
-The
-.Va net.inet6.ip6.forwarding
-.Xr sysctl 8
-should be set to zero
-(see also the
-.Fl F
-option below).
-.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
-.Dq rtsold -f1 interface ... .
-.Pp
-An interface may be configured at boot
-to be brought up using
-.Nm rtsol
-via a
-.Xr hostname.if 5
-file.
-See that man page for more information.
-.Pp
-.Nm
-sends at most 3 Router Solicitations on an interface
-after one of the following events:
-.Bl -bullet
-.It
-Just after invocation of
-.Nm
-daemon.
-.It
-The interface is up after a temporary interface failure.
-.Nm
-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 60 seconds if the
-.Fl m
-option is specified and the
-.Nm
-daemon cannot get the interface status.
-This feature does not conform to the IPv6 neighbor discovery
-specification, but is provided for mobile stations.
-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
-when they attach to another link.
-.El
-.Pp
-Once
-.Nm
-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.
-.Pp
-When sending a Router Solicitation on an interface,
-.Nm
-includes a Source Link-layer address option if the interface
-has a link-layer address.
-.Pp
-.Nm
-is able to do some additional configuration for interfaces
-where more than setting the host's address is needed.
-When the daemon receives a router advertisement
-with the
-.Dq Other Configuration
-flag set,
-the script specified using the
-.Fl O
-option is run.
-.Pp
-Upon receipt of signal
-.Dv SIGUSR1 ,
-.Nm
-will dump the current internal state into
-.Pa /var/run/rtsold.dump .
-.\"
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl 1
-Perform only one probe.
-Transmit Router Solicitation packets until at least one valid Router
-Advertisement packet has arrived on each
-.Ar interface ,
-then exit.
-.It Fl a
-Autoprobe outgoing interfaces.
-.Nm
-will try to find any non-loopback, non-point-to-point, IPv6-capable interfaces,
-and send router solicitation messages on all of them.
-.It Fl D
-Enable more debugging (than that offered by the
-.Fl d
-option) including the printing of internal timer information.
-.It Fl d
-Enable debugging.
-.It Fl F
-Automatically set the
-.Xr sysctl 8
-variables relating to
-.Nm
-(see above).
-Without this option,
-.Nm
-will obey the current
-.Xr sysctl 8
-settings.
-.It Fl f
-This option prevents
-.Nm
-from becoming a daemon (foreground mode).
-Warning messages are generated to standard error
-instead of
-.Xr syslog 3 .
-.It Fl m
-Enable mobility support.
-If this option is specified,
-.Nm
-sends probing packets to default routers that have advertised Router
-Advertisements
-when the node (re)attaches to an interface.
-Moreover, if the option is specified,
-.Nm
-periodically sends Router Solicitation on an interface that does not support
-.Dv SIOCGIFMEDIA
-ioctl.
-.It Fl O Ar script-name
-Specifies a script to handle the Other Configuration
-flag of the router advertisement (see above).
-.Ar script-name
-is invoked with a single argument of the receiving interface name,
-expecting the script will then start a protocol
-to provide additional configuration.
-.Ar script-name
-should be specified as the absolute path from root to the script file,
-and the file itself should be a regular file
-and owned by the same user running
-.Nm .
-.El
-.\"
-.Sh FILES
-.Bl -tag -width "/var/run/rtsold.dumpXX" -compact
-.It Pa /var/run/rtsold.dump
-Internal state dump file.
-.El
-.\"
-.Sh EXIT STATUS
-.Ex -std rtsold
-.\"
-.Sh SEE ALSO
-.Xr hostname.if 5 ,
-.Xr netstart 8 ,
-.Xr rtadvd 8 ,
-.Xr sysctl 8
-.\"
-.Sh HISTORY
-The
-.Nm
-command is based on the
-.Nm rtsol
-command, which first appeared in WIDE/KAME IPv6 protocol stack kit.
-.Nm rtsol
-is now integrated into
-.Nm rtsold .
-.\"
-.Sh BUGS
-In some operating systems, when a PCMCIA network card is removed
-and reinserted, the corresponding interface index is changed.
-However,
-.Nm
-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.
-In such a case,
-.Nm
-should be killed and restarted.
-.Pp
-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 interface
-arguments.
+++ /dev/null
-/* $OpenBSD: rtsold.c,v 1.54 2014/10/08 04:55:27 deraadt Exp $ */
-/* $KAME: rtsold.c,v 1.75 2004/01/03 00:00:07 itojun Exp $ */
-
-/*
- * 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.
- */
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/param.h>
-
-#include <net/if.h>
-#include <net/if_dl.h>
-
-#include <netinet/in.h>
-#include <netinet/icmp6.h>
-
-#include <signal.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <err.h>
-#include <stdarg.h>
-#include <ifaddrs.h>
-#include <util.h>
-#include <poll.h>
-
-#include "rtsold.h"
-
-struct ifinfo *iflist;
-static int log_upto = 999;
-static int fflag = 0;
-static int Fflag = 0; /* force setting sysctl parameters */
-
-int aflag = 0;
-int dflag = 0;
-
-char *otherconf_script;
-
-/* protocol constants */
-#define MAX_RTR_SOLICITATION_DELAY 1 /* second */
-#define RTR_SOLICITATION_INTERVAL 4 /* seconds */
-#define MAX_RTR_SOLICITATIONS 3 /* times */
-
-/*
- * implementation dependent constants in seconds
- * XXX: should be configurable
- */
-#define PROBE_INTERVAL 60
-
-int main(int, char **);
-
-/* static variables and functions */
-static int mobile_node = 0;
-#ifndef SMALL
-volatile sig_atomic_t do_dump;
-static char *dumpfilename = "/var/run/rtsold.dump"; /* XXX: should be configurable */
-#endif
-
-#if 0
-static int ifreconfig(char *);
-#endif
-int ifconfig(char *ifname);
-static int make_packet(struct ifinfo *);
-static struct timeval *rtsol_check_timer(void);
-
-#ifndef SMALL
-static void rtsold_set_dump_file(int);
-#endif
-static void usage(char *);
-
-int
-main(int argc, char *argv[])
-{
- int s, ch, once = 0;
- u_int rdomain;
- struct timeval *timeout;
- char *argv0, *opts;
- struct pollfd set[2];
-
- /*
- * Initialization
- */
- argv0 = argv[0];
-
- /* get option */
- if (argv0 && argv0[0] != '\0' && argv0[strlen(argv0) - 1] != 'd') {
- fflag = 1;
- once = 1;
- opts = "adDFO:";
- } else
- opts = "adDfFm1O:";
-
- while ((ch = getopt(argc, argv, opts)) != -1) {
- switch (ch) {
- case 'a':
- aflag = 1;
- break;
- case 'd':
- dflag = 1;
- break;
- case 'D':
- dflag = 2;
- break;
- case 'f':
- fflag = 1;
- break;
- case 'F':
- Fflag = 1;
- break;
- case 'm':
- mobile_node = 1;
- break;
- case '1':
- once = 1;
- break;
-#ifndef SMALL
- case 'O':
- otherconf_script = optarg;
- break;
-#endif
- default:
- usage(argv0);
- /*NOTREACHED*/
- }
- }
- argc -= optind;
- argv += optind;
-
- if ((!aflag && argc == 0) || (aflag && argc != 0)) {
- usage(argv0);
- /*NOTREACHED*/
- }
-
- /* set log level */
- if (dflag == 0)
- log_upto = LOG_NOTICE;
- if (!fflag) {
- char *ident;
-
- ident = strrchr(argv0, '/');
- if (!ident)
- ident = argv0;
- else
- ident++;
- openlog(ident, LOG_NDELAY|LOG_PID, LOG_DAEMON);
- if (log_upto >= 0)
- setlogmask(LOG_UPTO(log_upto));
- }
-
-#ifndef SMALL
- if (otherconf_script && *otherconf_script != '/') {
- errx(1, "configuration script (%s) must be an absolute path",
- otherconf_script);
- }
-#endif
-
- if (Fflag)
- setinet6sysctl(IPPROTO_IPV6, IPV6CTL_FORWARDING, 0);
- else {
- /* warn if forwarding is up */
- if (getinet6sysctl(IPPROTO_IPV6, IPV6CTL_FORWARDING))
- warnx("kernel is configured as a router, not a host");
- }
-
-#ifndef SMALL
- /* initialization to dump internal status to a file */
- signal(SIGUSR1, rtsold_set_dump_file);
-#endif
-
- if (!fflag)
- daemon(0, 0); /* act as a daemon */
-
- if (aflag)
- rdomain = getrtable();
- else
- rdomain = get_rdomain(*argv);
-
- /*
- * 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(rdomain)) < 0) {
- warnmsg(LOG_ERR, __func__, "failed to open a socket");
- exit(1);
- /*NOTREACHED*/
- }
- set[0].fd = s;
- set[0].events = POLLIN;
-
- set[1].fd = -1;
-
- /* configuration per interface */
- if (ifinit()) {
- warnmsg(LOG_ERR, __func__,
- "failed to initialize interfaces");
- exit(1);
- /*NOTREACHED*/
- }
- if (aflag) {
- argv = autoifprobe(rdomain);
- } else {
- warnmsg(LOG_DEBUG, __func__, "setting rdomain %u", rdomain);
- setrtable(rdomain);
- }
- while (argv && *argv) {
- if (ifconfig(*argv)) {
- warnmsg(LOG_ERR, __func__,
- "failed to initialize %s", *argv);
- exit(1);
- /*NOTREACHED*/
- }
- argv++;
- }
-
- /* setup for probing default routers */
- if (probe_init()) {
- warnmsg(LOG_ERR, __func__,
- "failed to setup for probing routers");
- exit(1);
- /*NOTREACHED*/
- }
-
- while (1) { /* main loop */
- int e;
-
-
-#ifndef SMALL
- if (do_dump) { /* SIGUSR1 */
- do_dump = 0;
- rtsold_dump_file(dumpfilename);
- }
-#endif
-
- timeout = rtsol_check_timer();
-
- if (once) {
- struct ifinfo *ifi;
-
- /* if we have no timeout, we are done (or failed) */
- if (timeout == NULL)
- break;
-
- /* if all interfaces have got RA packet, we are done */
- for (ifi = iflist; ifi; ifi = ifi->next) {
- if (ifi->state != IFS_DOWN && ifi->racnt == 0)
- break;
- }
- if (ifi == NULL)
- break;
- }
- e = poll(set, 2, timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFTIM);
- if (e < 1) {
- if (e < 0 && errno != EINTR) {
- warnmsg(LOG_ERR, __func__, "select: %s",
- strerror(errno));
- }
- continue;
- }
-
- /* packet reception */
- if (set[0].revents & POLLIN)
- rtsol_input(s);
- }
- /* NOTREACHED */
-
- return 0;
-}
-
-int
-ifconfig(char *ifname)
-{
- struct ifinfo *ifinfo;
- struct sockaddr_dl *sdl;
- int flags;
-
- if ((sdl = if_nametosdl(ifname)) == NULL) {
- warnmsg(LOG_ERR, __func__,
- "failed to get link layer information for %s", ifname);
- return(-1);
- }
- if (find_ifinfo(sdl->sdl_index)) {
- warnmsg(LOG_ERR, __func__,
- "interface %s was already configured", ifname);
- free(sdl);
- return(-1);
- }
-
- if ((ifinfo = calloc(1, sizeof(*ifinfo))) == NULL) {
- warnmsg(LOG_ERR, __func__, "memory allocation failed");
- free(sdl);
- return(-1);
- }
- ifinfo->sdl = sdl;
-
- strncpy(ifinfo->ifname, ifname, sizeof(ifinfo->ifname));
-
- /* construct a router solicitation message */
- 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.
- */
- ifinfo->mediareqok = 1;
- ifinfo->active = interface_status(ifinfo);
- if (!ifinfo->mediareqok) {
- /*
- * probe routers periodically even if the link status
- * does not change.
- */
- ifinfo->probeinterval = PROBE_INTERVAL;
- }
-
- /* activate interface: interface_up returns 0 on success */
- flags = interface_up(ifinfo->ifname);
- if (flags == 0)
- ifinfo->state = IFS_DELAY;
- else if (flags == IFS_TENTATIVE)
- ifinfo->state = IFS_TENTATIVE;
- else
- ifinfo->state = IFS_DOWN;
-
- rtsol_timer_update(ifinfo);
-
- /* link into chain */
- if (iflist)
- ifinfo->next = iflist;
- iflist = ifinfo;
-
- return(0);
-
-bad:
- 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)
-{
- struct ifinfo *ifi;
-
- for (ifi = iflist; ifi; ifi = ifi->next)
- if (ifi->sdl->sdl_index == ifindex)
- return(ifi);
- return(NULL);
-}
-
-static int
-make_packet(struct ifinfo *ifinfo)
-{
- size_t packlen = sizeof(struct nd_router_solicit), lladdroptlen = 0;
- struct nd_router_solicit *rs;
- char *buf;
-
- if ((lladdroptlen = lladdropt_length(ifinfo->sdl)) == 0) {
- warnmsg(LOG_INFO, __func__,
- "link-layer address option has null length"
- " on %s. Treat as not included.", ifinfo->ifname);
- }
- packlen += lladdroptlen;
- ifinfo->rs_datalen = packlen;
-
- /* allocate buffer */
- if ((buf = malloc(packlen)) == NULL) {
- warnmsg(LOG_ERR, __func__,
- "memory allocation failed for %s", ifinfo->ifname);
- return(-1);
- }
- ifinfo->rs_data = buf;
-
- /* fill in the message */
- rs = (struct nd_router_solicit *)buf;
- rs->nd_rs_type = ND_ROUTER_SOLICIT;
- rs->nd_rs_code = 0;
- rs->nd_rs_cksum = 0;
- rs->nd_rs_reserved = 0;
- buf += sizeof(*rs);
-
- /* fill in source link-layer address option */
- if (lladdroptlen)
- lladdropt_fill(ifinfo->sdl, (struct nd_opt_hdr *)buf);
-
- return(0);
-}
-
-static struct timeval *
-rtsol_check_timer(void)
-{
- static struct timeval returnval;
- struct timeval now, rtsol_timer;
- struct ifinfo *ifinfo;
- int flags, timers;
-
- gettimeofday(&now, NULL);
-
- timers = 0;
-
- for (ifinfo = iflist; ifinfo; ifinfo = ifinfo->next) {
- if (!ifinfo->stoptimer && timercmp(&ifinfo->expire, &now, <=)) {
- if (dflag > 1)
- warnmsg(LOG_DEBUG, __func__,
- "timer expiration on %s, "
- "state = %d", ifinfo->ifname,
- ifinfo->state);
-
- switch (ifinfo->state) {
- case IFS_DOWN:
- case IFS_TENTATIVE:
- /* interface_up returns 0 on success */
- flags = interface_up(ifinfo->ifname);
- if (flags == 0)
- ifinfo->state = IFS_DELAY;
- else if (flags == IFS_TENTATIVE)
- ifinfo->state = IFS_TENTATIVE;
- else
- ifinfo->state = IFS_DOWN;
- break;
- case IFS_IDLE:
- {
- int oldstatus = ifinfo->active;
- int probe = 0;
-
- ifinfo->active = interface_status(ifinfo);
-
- if (oldstatus != ifinfo->active) {
- warnmsg(LOG_DEBUG, __func__,
- "%s status is changed"
- " from %d to %d",
- ifinfo->ifname,
- oldstatus, ifinfo->active);
- probe = 1;
- ifinfo->state = IFS_DELAY;
- } else if (ifinfo->probeinterval &&
- (ifinfo->probetimer -=
- ifinfo->timer.tv_sec) <= 0) {
- /* probe timer expired */
- ifinfo->probetimer =
- ifinfo->probeinterval;
- probe = 1;
- ifinfo->state = IFS_PROBE;
- }
-
-#ifndef SMALL
- /*
- * If we need a probe, clear the previous
- * status wrt the "other" configuration.
- */
- if (probe)
- ifinfo->otherconfig = 0;
-#endif
-
- if (probe && mobile_node)
- defrouter_probe(ifinfo);
- break;
- }
- case IFS_DELAY:
- ifinfo->state = IFS_PROBE;
- sendpacket(ifinfo);
- break;
- case IFS_PROBE:
- if (ifinfo->probes < MAX_RTR_SOLICITATIONS)
- sendpacket(ifinfo);
- else {
- warnmsg(LOG_INFO, __func__,
- "No answer after sending %d RSs",
- ifinfo->probes);
- ifinfo->probes = 0;
- ifinfo->state = IFS_IDLE;
- }
- break;
- }
- rtsol_timer_update(ifinfo);
- }
- if (!ifinfo->stoptimer) {
- if (timers == 0)
- rtsol_timer = ifinfo->expire;
- else if (timercmp(&ifinfo->expire, &rtsol_timer, <))
- rtsol_timer = ifinfo->expire;
- timers++;
- }
- }
-
- if (timers == 0) {
- warnmsg(LOG_DEBUG, __func__, "there is no timer");
- return(NULL);
- } else if (timercmp(&rtsol_timer, &now, <))
- /* this may occur when the interval is too small */
- timerclear(&returnval);
- else
- timersub(&rtsol_timer, &now, &returnval);
-
- if (dflag > 1)
- warnmsg(LOG_DEBUG, __func__, "New timer is %lld:%08ld",
- (long long)returnval.tv_sec, returnval.tv_usec);
-
- return(&returnval);
-}
-
-void
-rtsol_timer_update(struct ifinfo *ifinfo)
-{
-#define MILLION 1000000
-#define DADRETRY 10 /* XXX: adhoc */
- long interval;
- struct timeval now;
-
- bzero(&ifinfo->timer, sizeof(ifinfo->timer));
- ifinfo->stoptimer = 0;
-
- switch (ifinfo->state) {
- case IFS_DOWN:
- case IFS_TENTATIVE:
- if (++ifinfo->dadcount > DADRETRY) {
- ifinfo->dadcount = 0;
- ifinfo->timer.tv_sec = PROBE_INTERVAL;
- } else
- ifinfo->timer.tv_sec = 1;
- break;
- case IFS_IDLE:
- if (mobile_node) {
- /* XXX should be configurable */
- ifinfo->timer.tv_sec = 3;
- } else
- ifinfo->stoptimer = 1;
- break;
- case IFS_DELAY:
- interval = arc4random_uniform(MAX_RTR_SOLICITATION_DELAY *
- MILLION);
- ifinfo->timer.tv_sec = interval / MILLION;
- ifinfo->timer.tv_usec = interval % MILLION;
- break;
- case IFS_PROBE:
- 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 solicitation. 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, __func__,
- "illegal interface state(%d) on %s",
- ifinfo->state, ifinfo->ifname);
- return;
- }
-
- /* reset the timer */
- if (ifinfo->stoptimer) {
- warnmsg(LOG_DEBUG, __func__,
- "stop timer for %s", ifinfo->ifname);
- } else {
- gettimeofday(&now, NULL);
- timeradd(&now, &ifinfo->timer, &ifinfo->expire);
-
- if (dflag > 1)
- warnmsg(LOG_DEBUG, __func__,
- "set timer for %s to %lld:%ld", ifinfo->ifname,
- (long long)ifinfo->timer.tv_sec,
- ifinfo->timer.tv_usec);
- }
-
-#undef MILLION
-}
-
-/* timer related utility functions */
-#define MILLION 1000000
-
-#ifndef SMALL
-static void
-rtsold_set_dump_file(int sig)
-{
- do_dump = 1;
-}
-#endif
-
-static void
-usage(char *progname)
-{
- if (progname && progname[0] != '\0' && progname[strlen(progname) - 1] != 'd') {
- fprintf(stderr,
- "usage: rtsol [-DdF] [-O script-name] interface ...\n"
- " rtsol [-DdF] -a\n");
- } else {
- fprintf(stderr,
- "usage: rtsold [-1DdFfm] [-O script-name] interface ...\n"
- " rtsold [-1DdFfm] -a\n");
- }
- exit(1);
-}
-
-void
-warnmsg(int priority, const char *func, const char *msg, ...)
-{
- va_list ap;
- char buf[BUFSIZ];
-
- va_start(ap, msg);
- if (fflag) {
- if (priority <= log_upto) {
- (void)vfprintf(stderr, msg, ap);
- (void)fprintf(stderr, "\n");
- }
- } else {
- snprintf(buf, sizeof(buf), "<%s> %s", func, msg);
- msg = buf;
- vsyslog(priority, msg, ap);
- }
- va_end(ap);
-}
-
-/*
- * return a list of interfaces which is suitable to sending an RS.
- */
-char **
-autoifprobe(u_int rdomain)
-{
- 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;
-
- target = NULL;
- /* find an ethernet */
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if ((ifa->ifa_flags & IFF_UP) == 0)
- continue;
- if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0)
- continue;
- if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
- continue;
- if ((ifa->ifa_flags & IFF_MULTICAST) == 0)
- continue;
-
- if (ifa->ifa_addr->sa_family != AF_INET6)
- continue;
- if (get_rdomain(ifa->ifa_name) != rdomain)
- continue;
-
- found = 0;
- for (i = 0; i < n; i++) {
- if (strcmp(argv[i], ifa->ifa_name) == 0) {
- found++;
- break;
- }
- }
- if (found)
- continue;
-
- /* if we find multiple candidates, just warn. */
- if (n != 0 && dflag > 1)
- warnx("multiple interfaces found");
-
- a = reallocarray(argv, n + 1, sizeof(char **));
- if (a == NULL)
- err(1, "realloc");
- argv = a;
- if ((argv[n] = strdup(ifa->ifa_name)) == NULL)
- err(1, "strdup");
- n++;
- }
-
- if (n) {
- a = reallocarray(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]);
- }
- }
- freeifaddrs(ifap);
- return argv;
-}
+++ /dev/null
-/* $OpenBSD: rtsold.h,v 1.17 2013/11/12 22:27:13 deraadt Exp $ */
-/* $KAME: rtsold.h,v 1.14 2002/05/31 10:10:03 itojun Exp $ */
-
-/*
- * 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.
- */
-
-struct ifinfo {
- struct ifinfo *next; /* pointer to the next interface */
-
- 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 */
- int mediareqok; /* wheter the IF supports SIOCGIFMEDIA */
- int otherconfig; /* need a separate protocol for the "other"
- * configuration */
- int state;
- int probes;
- int dadcount;
- struct timeval timer;
- struct timeval expire;
- int stoptimer;
- int errors; /* # of errors we've got - detect wedge */
-
- int racnt; /* total # of valid RAs it have got */
-
- size_t rs_datalen;
- u_char *rs_data;
-};
-
-/* per interface status */
-#define IFS_IDLE 0
-#define IFS_DELAY 1
-#define IFS_PROBE 2
-#define IFS_DOWN 3
-#define IFS_TENTATIVE 4
-
-/* rtsold.c */
-extern int dflag;
-extern char *otherconf_script;
-struct ifinfo *find_ifinfo(int ifindex);
-void rtsol_timer_update(struct ifinfo *);
-extern void warnmsg(int, const char *, const char *, ...)
- __attribute__((__format__(__printf__, 3, 4)));
-extern char **autoifprobe(u_int);
-
-/* if.c */
-extern int ifinit(void);
-int get_rdomain(char *);
-extern int interface_up(char *);
-extern int interface_status(struct ifinfo *);
-extern int lladdropt_length(struct sockaddr_dl *);
-extern void lladdropt_fill(struct sockaddr_dl *, struct nd_opt_hdr *);
-extern struct sockaddr_dl *if_nametosdl(char *);
-extern int getinet6sysctl(int, int);
-extern int setinet6sysctl(int, int, int);
-
-/* rtsol.c */
-extern int sockopen(u_int);
-extern void sendpacket(struct ifinfo *);
-extern void rtsol_input(int);
-
-/* probe.c */
-extern int probe_init(void);
-extern void defrouter_probe(struct ifinfo *);
-
-/* dump.c */
-extern void rtsold_dump_file(char *);