+++ /dev/null
-# $OpenBSD: Makefile,v 1.9 2016/08/02 17:00:09 jca Exp $
-
-PROG= rtadvd
-SRCS= rtadvd.c advcap.c if.c config.c dump.c log.c
-
-CFLAGS+=-Wall
-MAN= rtadvd.8 rtadvd.conf.5
-
-LDADD= -levent
-DPADD+= ${LIBEVENT}
-
-.include <bsd.prog.mk>
+++ /dev/null
-/* $OpenBSD: advcap.c,v 1.18 2017/12/08 17:04:15 deraadt Exp $ */
-/* $KAME: advcap.c,v 1.9 2002/05/29 14:28:35 itojun Exp $ */
-
-/*
- * Copyright (c) 1983 The Regents of the University of California.
- * 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 University 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 REGENTS 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 REGENTS 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.
- */
-
-/*
- * remcap - routines for dealing with the remote host data base
- *
- * derived from termcap
- */
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include "pathnames.h"
-#include "log.h"
-
-#define MAXHOP 32 /* max number of tc= indirections */
-
-#define tgetent agetent
-#define tnchktc anchktc
-#define tnamatch anamatch
-#define tgetnum agetnum
-#define tgetflag agetflag
-#define tgetstr agetstr
-
-#if 0
-#define V_TERMCAP "REMOTE"
-#define V_TERM "HOST"
-#endif
-
-
-/*
- * termcap - routines for dealing with the terminal capability data base
- *
- * BUG: Should use a "last" pointer in tbuf, so that searching
- * for capabilities alphabetically would not be a n**2/2
- * process when large numbers of capabilities are given.
- * Note: If we add a last pointer now we will screw up the
- * tc capability. We really should compile termcap.
- *
- * Essentially all the work here is scanning and decoding escapes
- * in string capabilities. We don't use stdio because the editor
- * doesn't, and because living w/o it is not hard.
- */
-
-static char *tbuf;
-static int hopcount; /* detect infinite loops in termcap, init 0 */
-
-static char *remotefile;
-
-extern char *conffile;
-
-int tgetent(char *, char *);
-int getent(char *, char *, char *);
-int tnchktc(void);
-int tnamatch(char *);
-static char *tskip(char *);
-int64_t tgetnum(char *);
-int tgetflag(char *);
-char *tgetstr(char *, char **);
-static char *tdecode(char *, char **);
-
-/*
- * Get an entry for terminal name in buffer bp,
- * from the termcap file. Parse is very rudimentary;
- * we just notice escaped newlines.
- */
-int
-tgetent(char *bp, char *name)
-{
- char *cp;
-
- remotefile = cp = conffile ? conffile : _PATH_RTADVDCONF;
- return (getent(bp, name, cp));
-}
-
-int
-getent(char *bp, char *name, char *cp)
-{
- int c;
- int i = 0, cnt = 0;
- char ibuf[BUFSIZ];
- int tf;
-
- tbuf = bp;
- tf = 0;
- /*
- * TERMCAP can have one of two things in it. It can be the
- * name of a file to use instead of /etc/termcap. In this
- * case it better start with a "/". Or it can be an entry to
- * use so we don't have to read the file. In this case it
- * has to already have the newlines crunched out.
- */
- if (cp && *cp) {
- tf = open(cp, O_RDONLY);
- }
- if (tf < 0) {
- log_warn("open(\"%s\")", cp);
- return (-2);
- }
- for (;;) {
- cp = bp;
- for (;;) {
- if (i == cnt) {
- cnt = read(tf, ibuf, BUFSIZ);
- if (cnt <= 0) {
- close(tf);
- return (0);
- }
- i = 0;
- }
- c = ibuf[i++];
- if (c == '\n') {
- if (cp > bp && cp[-1] == '\\') {
- cp--;
- continue;
- }
- break;
- }
- if (cp >= bp + BUFSIZ) {
- dprintf(STDERR_FILENO, "Remcap entry too long\n");
- break;
- } else
- *cp++ = c;
- }
- *cp = 0;
-
- /*
- * The real work for the match.
- */
- if (tnamatch(name)) {
- close(tf);
- return (tnchktc());
- }
- }
-}
-
-/*
- * tnchktc: check the last entry, see if it's tc=xxx. If so,
- * recursively find xxx and append that entry (minus the names)
- * to take the place of the tc=xxx entry. This allows termcap
- * entries to say "like an HP2621 but doesn't turn on the labels".
- * Note that this works because of the left to right scan.
- */
-int
-tnchktc(void)
-{
- char *p, *q;
- char tcname[16]; /* name of similar terminal */
- char tcbuf[BUFSIZ];
- char *holdtbuf = tbuf;
- int l;
-
- p = tbuf + strlen(tbuf) - 2; /* before the last colon */
- while (*--p != ':')
- if (p < tbuf) {
- dprintf(STDERR_FILENO, "Bad remcap entry\n");
- return (0);
- }
- p++;
- /* p now points to beginning of last field */
- if (p[0] != 't' || p[1] != 'c')
- return (1);
- strlcpy(tcname, p + 3, sizeof tcname);
- q = tcname;
- while (*q && *q != ':')
- q++;
- *q = 0;
- if (++hopcount > MAXHOP) {
- dprintf(STDERR_FILENO, "Infinite tc= loop\n");
- return (0);
- }
- if (getent(tcbuf, tcname, remotefile) != 1) {
- log_warnx("Could not parse %s: "
- "Unresolvable reference to %s.", remotefile, tcname);
- return (0);
- }
- for (q = tcbuf; *q++ != ':'; )
- ;
- l = p - holdtbuf + strlen(q);
- if (l > BUFSIZ) {
- dprintf(STDERR_FILENO, "Remcap entry too long\n");
- q[BUFSIZ - (p-holdtbuf)] = 0;
- }
- strlcpy(p, q, holdtbuf + BUFSIZ - p);
- tbuf = holdtbuf;
- return (1);
-}
-
-/*
- * Tnamatch deals with name matching. The first field of the termcap
- * entry is a sequence of names separated by |'s, so we compare
- * against each such name. The normal : terminator after the last
- * name (before the first field) stops us.
- */
-int
-tnamatch(char *np)
-{
- char *Np, *Bp;
-
- Bp = tbuf;
- if (*Bp == '#')
- return (0);
- for (;;) {
- for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
- continue;
- if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
- return (1);
- while (*Bp && *Bp != ':' && *Bp != '|')
- Bp++;
- if (*Bp == 0 || *Bp == ':')
- return (0);
- Bp++;
- }
-}
-
-/*
- * Skip to the next field. Notice that this is very dumb, not
- * knowing about \: escapes or any such. If necessary, :'s can be put
- * into the termcap file in octal.
- */
-static char *
-tskip(char *bp)
-{
- int dquote;
-
- dquote = 0;
- while (*bp) {
- switch (*bp) {
- case ':':
- if (!dquote)
- goto breakbreak;
- else
- bp++;
- break;
- case '\\':
- bp++;
- if (isdigit((unsigned char)*bp)) {
- while (isdigit((unsigned char)*bp++))
- ;
- } else
- bp++;
- case '"':
- dquote = (dquote ? 1 : 0);
- bp++;
- break;
- default:
- bp++;
- break;
- }
- }
-breakbreak:
- if (*bp == ':')
- bp++;
- return (bp);
-}
-
-/*
- * Return the (numeric) option id.
- * Numeric options look like
- * li#80
- * i.e. the option string is separated from the numeric value by
- * a # character. If the option is not found we return -1.
- * Note that we handle octal numbers beginning with 0.
- */
-int64_t
-tgetnum(char *id)
-{
- int64_t i;
- int base;
- char *bp = tbuf;
-
- for (;;) {
- bp = tskip(bp);
- if (*bp == 0)
- return (-1);
- if (strncmp(bp, id, strlen(id)) != 0)
- continue;
- bp += strlen(id);
- if (*bp == '@')
- return (-1);
- if (*bp != '#')
- continue;
- bp++;
- base = 10;
- if (*bp == '0')
- base = 8;
- i = 0;
- while (isdigit((unsigned char)*bp))
- i *= base, i += *bp++ - '0';
- return (i);
- }
-}
-
-/*
- * Handle a flag option.
- * Flag options are given "naked", i.e. followed by a : or the end
- * of the buffer. Return 1 if we find the option, or 0 if it is
- * not given.
- */
-int
-tgetflag(char *id)
-{
- char *bp = tbuf;
-
- for (;;) {
- bp = tskip(bp);
- if (!*bp)
- return (0);
- if (strncmp(bp, id, strlen(id)) == 0) {
- bp += strlen(id);
- if (!*bp || *bp == ':')
- return (1);
- else if (*bp == '@')
- return (0);
- }
- }
-}
-
-/*
- * Get a string valued option.
- * These are given as
- * cl=^Z
- * Much decoding is done on the strings, and the strings are
- * placed in area, which is a ref parameter which is updated.
- * No checking on area overflow.
- */
-char *
-tgetstr(char *id, char **area)
-{
- char *bp = tbuf;
-
- for (;;) {
- bp = tskip(bp);
- if (!*bp)
- return (0);
- if (strncmp(bp, id, strlen(id)) != 0)
- continue;
- bp += strlen(id);
- if (*bp == '@')
- return (0);
- if (*bp != '=')
- continue;
- bp++;
- return (tdecode(bp, area));
- }
-}
-
-/*
- * Tdecode does the grung work to decode the
- * string capability escapes.
- */
-static char *
-tdecode(char *str, char **area)
-{
- char *cp;
- int c;
- char *dp;
- int i;
- char term;
-
- term = ':';
- cp = *area;
-again:
- if (*str == '"') {
- term = '"';
- str++;
- }
- while ((c = *str++) && c != term) {
- switch (c) {
-
- case '^':
- c = *str++ & 037;
- break;
-
- case '\\':
- dp = "E\033^^\\\\::n\nr\rt\tb\bf\f\"\"";
- c = *str++;
-nextc:
- if (*dp++ == c) {
- c = *dp++;
- break;
- }
- dp++;
- if (*dp)
- goto nextc;
- if (isdigit((unsigned char)c)) {
- c -= '0', i = 2;
- do
- c <<= 3, c |= *str++ - '0';
- while (--i && isdigit((unsigned char)*str));
- }
- break;
- }
- *cp++ = c;
- }
- if (c == term && term != ':') {
- term = ':';
- goto again;
- }
- *cp++ = 0;
- str = *area;
- *area = cp;
- return (str);
-}
+++ /dev/null
-/* $OpenBSD: advcap.h,v 1.7 2012/12/05 23:20:26 deraadt Exp $ */
-/* $KAME: advcap.h,v 1.4 2001/06/08 04:46:19 jinmei Exp $ */
-
-/*
- * Copyright (C) 1994,1995 by Andrey A. Chernov, Moscow, Russia.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- */
-
-/* Based on Id: termcap.h,v 1.8 1996/09/10 12:42:10 peter Exp */
-
-#ifndef _ADVCAP_H_
-#define _ADVCAP_H_
-
-__BEGIN_DECLS
-
-extern int agetent(char *, const char *);
-extern int agetflag(const char *);
-extern int64_t agetnum(const char *);
-extern char *agetstr(const char *, char **);
-
-__END_DECLS
-
-#endif /* _ADVCAP_H_ */
+++ /dev/null
-/* $OpenBSD: config.c,v 1.62 2017/08/08 09:03:02 jca Exp $ */
-/* $KAME: config.c,v 1.62 2002/05/29 10:13:10 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/ioctl.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/sysctl.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/if_dl.h>
-
-#include <netinet/in.h>
-#include <netinet6/in6_var.h>
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet/icmp6.h>
-
-#include <arpa/inet.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <ifaddrs.h>
-#include <stdint.h>
-#include <event.h>
-
-#include "rtadvd.h"
-#include "advcap.h"
-#include "if.h"
-#include "config.h"
-#include "log.h"
-
-static void makeentry(char *, size_t, int, char *);
-static int getinet6sysctl(int);
-
-extern struct ralist ralist;
-
-void
-getconfig(char *intface)
-{
- int stat, i;
- char tbuf[BUFSIZ];
- struct rainfo *tmp;
- long val;
- int64_t val64;
- char buf[BUFSIZ];
- char *bp = buf;
- char *addr;
- static int forwarding = -1;
-
-#define MUSTHAVE(var, cap) \
- do { \
- int64_t t; \
- if ((t = agetnum(cap)) < 0) { \
- fatalx("need %s for interface %s", \
- cap, intface); \
- } \
- var = t; \
- } while (0)
-#define MAYHAVE(var, cap, def) \
- do { \
- if ((var = agetnum(cap)) < 0) \
- var = def; \
- } while (0)
-
- if ((stat = agetent(tbuf, intface)) <= 0) {
- memset(tbuf, 0, sizeof(tbuf));
- log_info("Could not parse configuration file for %s"
- " or the configuration file doesn't exist."
- " Treat it as default", intface);
- }
-
- if ((tmp = calloc(1, sizeof(*tmp))) == NULL)
- fatal(NULL);
-
- TAILQ_INIT(&tmp->prefixes);
- TAILQ_INIT(&tmp->rtinfos);
- TAILQ_INIT(&tmp->rdnsss);
- TAILQ_INIT(&tmp->dnssls);
-
- /* check if we are allowed to forward packets (if not determined) */
- if (forwarding < 0) {
- if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0)
- exit(1);
- }
-
- /* make sure that the user-specified interface name fits */
- if (strlcpy(tmp->ifname, intface,
- sizeof(tmp->ifname)) >= sizeof(tmp->ifname))
- fatalx("invalid interface name");
-
- /* get interface information */
- if (agetflag("nolladdr"))
- tmp->advlinkopt = 0;
- else
- tmp->advlinkopt = 1;
- if (tmp->advlinkopt) {
- if ((tmp->sdl = if_nametosdl(intface)) == NULL)
- fatalx("can't get information of %s", intface);
-
- tmp->ifindex = tmp->sdl->sdl_index;
- } else
- tmp->ifindex = if_nametoindex(intface);
- if ((tmp->phymtu = if_getmtu(intface)) == 0) {
- tmp->phymtu = IPV6_MMTU;
- log_warn("can't get interface mtu of %s. Treat as %d",
- intface, IPV6_MMTU);
- }
-
- /*
- * set router configuration variables.
- */
- MAYHAVE(val, "maxinterval", DEF_MAXRTRADVINTERVAL);
- if (val < MIN_MAXINTERVAL || val > MAX_MAXINTERVAL)
- fatalx("maxinterval (%ld) on %s is invalid "
- "(must be between %u and %u)", val,
- intface, MIN_MAXINTERVAL, MAX_MAXINTERVAL);
-
- tmp->maxinterval = (u_int)val;
- MAYHAVE(val, "mininterval", tmp->maxinterval/3);
- if (val < MIN_MININTERVAL || val > (tmp->maxinterval * 3) / 4)
- fatalx("mininterval (%ld) on %s is invalid "
- "(must be between %u and %u)",
- val, intface, MIN_MININTERVAL, (tmp->maxinterval * 3) / 4);
-
- tmp->mininterval = (u_int)val;
-
- MAYHAVE(val, "chlim", DEF_ADVCURHOPLIMIT);
- tmp->hoplimit = val & 0xff;
-
- MAYHAVE(val, "raflags", 0);
- tmp->managedflg = val & ND_RA_FLAG_MANAGED;
- tmp->otherflg = val & ND_RA_FLAG_OTHER;
- tmp->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
- if (tmp->rtpref == ND_RA_FLAG_RTPREF_RSV)
- fatalx("invalid router preference (%02x) on %s",
- tmp->rtpref, intface);
-
- MAYHAVE(val, "rltime", tmp->maxinterval * 3);
- if (val && (val < tmp->maxinterval || val > MAX_ROUTERLIFETIME))
- fatalx("router lifetime (%ld) on %s is invalid "
- "(must be 0 or between %d and %d)",
- val, intface,
- tmp->maxinterval, MAX_ROUTERLIFETIME);
-
- /*
- * Basically, hosts MUST NOT send Router Advertisement messages at any
- * time (RFC 2461, Section 6.2.3). However, it would sometimes be
- * useful to allow hosts to advertise some parameters such as prefix
- * information and link MTU. Thus, we allow hosts to invoke rtadvd
- * only when router lifetime (on every advertising interface) is
- * explicitely set to zero. (see also the above section)
- */
- if (val && forwarding == 0)
- fatalx("non zero router lifetime is specified for %s, "
- "which must not be allowed for hosts. you must "
- "change router lifetime or enable IPv6 forwarding.",
- intface);
-
- tmp->lifetime = val & 0xffff;
-
- MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME);
- if (val < 0 || val > MAX_REACHABLETIME)
- log_warnx("reachable time (%ld) on %s is invalid"
- " (must be no greater than %d)",
- val, intface, MAX_REACHABLETIME);
-
- tmp->reachabletime = (u_int32_t)val;
-
- MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER);
- if (val64 < 0 || val64 > 0xffffffff)
- fatalx("retrans time (%lld) on %s out of range",
- (long long)val64, intface);
-
- tmp->retranstimer = (u_int32_t)val64;
-
- if (agetnum("hapref") != -1 || agetnum("hatime") != -1)
- fatalx("mobile-ip6 configuration not supported");
-
- /* prefix information */
-
- /*
- * This is an implementation specific parameter to consider
- * link propagation delays and poorly synchronized clocks when
- * checking consistency of advertised lifetimes.
- */
- MAYHAVE(val, "clockskew", 0);
- tmp->clockskew = val;
-
- tmp->pfxs = 0;
- for (i = -1; i < MAXPREFIX; i++) {
- struct prefix *pfx;
- char entbuf[256];
-
- makeentry(entbuf, sizeof(entbuf), i, "addr");
- addr = agetstr(entbuf, &bp);
- if (addr == NULL)
- continue;
-
- /* allocate memory to store prefix information */
- if ((pfx = calloc(1, sizeof(*pfx))) == NULL)
- fatal(NULL);
-
- /* link into chain */
- TAILQ_INSERT_TAIL(&tmp->prefixes, pfx, entry);
- tmp->pfxs++;
-
- pfx->origin = PREFIX_FROM_CONFIG;
-
- if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1)
- fatal("inet_pton failed for %s", addr);
-
- if (IN6_IS_ADDR_MULTICAST(&pfx->prefix))
- fatalx("multicast prefix (%s) must"
- " not be advertised on %s",
- addr, intface);
-
- if (IN6_IS_ADDR_LINKLOCAL(&pfx->prefix))
- log_info("link-local prefix (%s) will be"
- " advertised on %s",
- addr, intface);
-
- makeentry(entbuf, sizeof(entbuf), i, "prefixlen");
- MAYHAVE(val, entbuf, 64);
- if (val < 0 || val > 128)
- fatalx("prefixlen (%ld) for %s "
- "on %s out of range",
- val, addr, intface);
-
- pfx->prefixlen = (int)val;
-
- makeentry(entbuf, sizeof(entbuf), i, "pinfoflags");
- MAYHAVE(val, entbuf,
- (ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO));
- pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK;
- pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO;
-
- makeentry(entbuf, sizeof(entbuf), i, "vltime");
- MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
- if (val64 < 0 || val64 > 0xffffffff)
- fatalx("vltime (%lld) for"
- " %s/%d on %s is out of range",
- (long long)val64,
- addr, pfx->prefixlen, intface);
-
- pfx->validlifetime = (u_int32_t)val64;
-
- makeentry(entbuf, sizeof(entbuf), i, "vltimedecr");
- if (agetflag(entbuf)) {
- struct timeval now;
- gettimeofday(&now, 0);
- pfx->vltimeexpire =
- now.tv_sec + pfx->validlifetime;
- }
-
- makeentry(entbuf, sizeof(entbuf), i, "pltime");
- MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME);
- if (val64 < 0 || val64 > 0xffffffff)
- fatalx("pltime (%lld) for %s/%d on %s"
- " is out of range",
- (long long)val64,
- addr, pfx->prefixlen, intface);
-
- pfx->preflifetime = (u_int32_t)val64;
-
- makeentry(entbuf, sizeof(entbuf), i, "pltimedecr");
- if (agetflag(entbuf)) {
- struct timeval now;
- gettimeofday(&now, 0);
- pfx->pltimeexpire =
- now.tv_sec + pfx->preflifetime;
- }
- }
- if (tmp->pfxs == 0 && !agetflag("noifprefix"))
- get_prefix(tmp);
-
- for (i = -1; i < MAXRTINFO; i++) {
- struct rtinfo *rti;
- char entbuf[256];
- const char *flagstr;
-
- makeentry(entbuf, sizeof(entbuf), i, "rtprefix");
- addr = agetstr(entbuf, &bp);
- if (addr == NULL)
- continue;
-
- rti = malloc(sizeof(struct rtinfo));
- if (rti == NULL)
- fatal(NULL);
-
- if (inet_pton(AF_INET6, addr, &rti->prefix) != 1)
- fatal("inet_pton failed for %s", addr);
-
- makeentry(entbuf, sizeof(entbuf), i, "rtplen");
- MAYHAVE(val, entbuf, 64);
- if (val < 0 || val > 128)
- fatalx("route prefixlen (%ld) for %s "
- "on %s out of range",
- val, addr, intface);
-
- rti->prefixlen = (int)val;
-
- makeentry(entbuf, sizeof(entbuf), i, "rtflags");
- if ((flagstr = agetstr(entbuf, &bp))) {
- val = 0;
- if (strchr(flagstr, 'h'))
- val |= ND_RA_FLAG_RTPREF_HIGH;
- if (strchr(flagstr, 'l')) {
- if (val & ND_RA_FLAG_RTPREF_HIGH)
- fatalx("the \'h\' and \'l\'"
- " route preferences are"
- " exclusive");
-
- val |= ND_RA_FLAG_RTPREF_LOW;
- }
- } else
- MAYHAVE(val, entbuf, 0);
-
- rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
- if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV)
- fatalx("invalid route preference (%02x)"
- " for %s/%d on %s",
- rti->rtpref, addr, rti->prefixlen, intface);
-
- makeentry(entbuf, sizeof(entbuf), i, "rtltime");
- MAYHAVE(val64, entbuf, -1);
- if (val64 == -1)
- val64 = tmp->lifetime;
- if (val64 < 0 || val64 >= 0xffffffff)
- fatalx("route lifetime (%d) "
- " for %s/%d on %s out of range",
- rti->rtpref, addr, rti->prefixlen, intface);
-
- rti->lifetime = (uint32_t)val64;
-
- TAILQ_INSERT_TAIL(&tmp->rtinfos, rti, entry);
- }
-
- for (i = -1; i < MAXRDNSS; ++i) {
- struct rdnss *rds;
- char entbuf[256];
- char *tmpaddr;
-
- makeentry(entbuf, sizeof(entbuf), i, "rdnss");
- addr = agetstr(entbuf, &bp);
- if (addr == NULL)
- continue;
-
- /* servers are separated by commas in the config file */
- val = 1;
- tmpaddr = addr;
- while (*tmpaddr++)
- if (*tmpaddr == ',')
- ++val;
-
- rds = malloc(sizeof(struct rdnss) + val * sizeof(struct in6_addr));
- if (rds == NULL)
- fatal(NULL);
-
- TAILQ_INSERT_TAIL(&tmp->rdnsss, rds, entry);
-
- rds->servercnt = val;
-
- makeentry(entbuf, sizeof(entbuf), i, "rdnssltime");
- MAYHAVE(val, entbuf, (tmp->maxinterval * 3) / 2);
- if (val < tmp->maxinterval || val > tmp->maxinterval * 2) {
- log_warnx("%s (%ld) on %s is invalid "
- "(should be between %d and %d)",
- entbuf, val, intface, tmp->maxinterval,
- tmp->maxinterval * 2);
- }
- rds->lifetime = val;
-
- val = 0;
- while ((tmpaddr = strsep(&addr, ","))) {
- if (inet_pton(AF_INET6, tmpaddr, &rds->servers[val]) !=
- 1)
- fatal("inet_pton failed for %s", tmpaddr);
-
- val++;
- }
- }
-
- for (i = -1; i < MAXDNSSL; ++i) {
- struct dnssl *dsl;
- char entbuf[256];
- char *tmpsl;
-
- makeentry(entbuf, sizeof(entbuf), i, "dnssl");
- addr = agetstr(entbuf, &bp);
- if (addr == NULL)
- continue;
-
- dsl = malloc(sizeof(struct dnssl));
- if (dsl == NULL)
- fatal(NULL);
-
- TAILQ_INIT(&dsl->dnssldoms);
-
- while ((tmpsl = strsep(&addr, ","))) {
- struct dnssldom *dnsd;
- size_t len;
-
- len = strlen(tmpsl);
-
- /* if the domain is not "dot-terminated", add it */
- if (tmpsl[len - 1] != '.')
- len += 1;
-
- dnsd = malloc(sizeof(struct dnssldom) + len + 1);
- if (dnsd == NULL)
- fatal(NULL);
-
- dnsd->length = len;
- strlcpy(dnsd->domain, tmpsl, len + 1);
- dnsd->domain[len - 1] = '.';
- dnsd->domain[len] = '\0';
-
- TAILQ_INSERT_TAIL(&dsl->dnssldoms, dnsd, entry);
- }
-
- TAILQ_INSERT_TAIL(&tmp->dnssls, dsl, entry);
-
- makeentry(entbuf, sizeof(entbuf), i, "dnsslltime");
- MAYHAVE(val, entbuf, (tmp->maxinterval * 3) / 2);
- if (val < tmp->maxinterval || val > tmp->maxinterval * 2) {
- log_warnx("%s (%ld) on %s is invalid "
- "(should be between %d and %d)",
- entbuf, val, intface, tmp->maxinterval,
- tmp->maxinterval * 2);
- }
- dsl->lifetime = val;
- }
-
- MAYHAVE(val, "mtu", 0);
- if (val < 0 || val > 0xffffffff)
- fatalx("mtu (%ld) on %s out of range", val, intface);
-
- tmp->linkmtu = (u_int32_t)val;
- if (tmp->linkmtu == 0) {
- char *mtustr;
-
- if ((mtustr = agetstr("mtu", &bp)) &&
- strcmp(mtustr, "auto") == 0)
- tmp->linkmtu = tmp->phymtu;
- } else if (tmp->linkmtu < IPV6_MMTU || tmp->linkmtu > tmp->phymtu)
- fatalx("advertised link mtu (%u) on %s is invalid (must"
- " be between least MTU (%d) and physical link MTU (%d)",
- tmp->linkmtu, intface, IPV6_MMTU, tmp->phymtu);
-
- /* route information */
- MAYHAVE(val, "routes", -1);
- if (val != -1)
- log_info("route information option is not available");
-
- /* okey */
- SLIST_INSERT_HEAD(&ralist, tmp, entry);
-
- /* construct the sending packet */
- make_packet(tmp);
-
- /* set timer */
- ra_timer_update(tmp);
-}
-
-void
-get_prefix(struct rainfo *rai)
-{
- struct ifaddrs *ifap, *ifa;
- struct prefix *pp;
- struct in6_addr *a;
- u_char *p, *ep, *m, *lim;
- u_char ntopbuf[INET6_ADDRSTRLEN];
-
- if (getifaddrs(&ifap) < 0)
- fatal("can't get interface addresses");
-
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- int plen;
-
- if (strcmp(ifa->ifa_name, rai->ifname) != 0)
- continue;
- if (ifa->ifa_addr->sa_family != AF_INET6)
- continue;
- a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
- if (IN6_IS_ADDR_LINKLOCAL(a))
- continue;
- /* get prefix length */
- m = (u_char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
- lim = (u_char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len;
- plen = prefixlen(m, lim);
- if (plen <= 0 || plen > 128)
- fatalx("failed to get prefixlen or prefix is invalid");
- if (plen == 128) /* XXX */
- continue;
- if (find_prefix(rai, a, plen)) {
- /* ignore a duplicated prefix. */
- continue;
- }
-
- /* allocate memory to store prefix info. */
- if ((pp = calloc(1, sizeof(*pp))) == NULL)
- fatal(NULL);
-
- /* set prefix, sweep bits outside of prefixlen */
- pp->prefixlen = plen;
- memcpy(&pp->prefix, a, sizeof(*a));
- if (1)
- {
- p = (u_char *)&pp->prefix;
- ep = (u_char *)(&pp->prefix + 1);
- while (m < lim && p < ep)
- *p++ &= *m++;
- while (p < ep)
- *p++ = 0x00;
- }
- if (!inet_ntop(AF_INET6, &pp->prefix, ntopbuf,
- sizeof(ntopbuf)))
- fatal("inet_ntop failed");
- log_debug("add %s/%d to prefix list on %s",
- ntopbuf, pp->prefixlen, rai->ifname);
-
- /* set other fields with protocol defaults */
- pp->validlifetime = DEF_ADVVALIDLIFETIME;
- pp->preflifetime = DEF_ADVPREFERREDLIFETIME;
- pp->onlinkflg = 1;
- pp->autoconfflg = 1;
- pp->origin = PREFIX_FROM_KERNEL;
-
- /* link into chain */
- TAILQ_INSERT_TAIL(&rai->prefixes, pp, entry);
-
- /* counter increment */
- rai->pfxs++;
- }
-
- freeifaddrs(ifap);
-}
-
-static void
-makeentry(char *buf, size_t len, int id, char *string)
-{
-
- if (id < 0)
- strlcpy(buf, string, len);
- else
- snprintf(buf, len, "%s%d", string, id);
-}
-
-/*
- * Add a prefix to the list of specified interface and reconstruct
- * the outgoing packet.
- * The prefix must not be in the list.
- * XXX: other parameters of the prefix (e.g. lifetime) ought
- * to be specified.
- */
-void
-make_prefix(struct rainfo *rai, int ifindex, struct in6_addr *addr, int plen)
-{
- struct prefix *prefix;
- u_char ntopbuf[INET6_ADDRSTRLEN];
-
- if ((prefix = calloc(1, sizeof(*prefix))) == NULL) {
- log_warn(NULL);
- return; /* XXX: error or exit? */
- }
- prefix->prefix = *addr;
- prefix->prefixlen = plen;
- prefix->validlifetime = DEF_ADVVALIDLIFETIME;
- prefix->preflifetime = DEF_ADVPREFERREDLIFETIME;
- prefix->onlinkflg = 1;
- prefix->autoconfflg = 1;
- prefix->origin = PREFIX_FROM_DYNAMIC;
-
- TAILQ_INSERT_TAIL(&rai->prefixes, prefix, entry);
-
- log_debug("new prefix %s/%d was added on %s",
- inet_ntop(AF_INET6, &prefix->prefix,
- ntopbuf, INET6_ADDRSTRLEN),
- prefix->prefixlen, rai->ifname);
-
- /* free the previous packet */
- free(rai->ra_data);
- rai->ra_data = NULL;
-
- /* reconstruct the packet */
- rai->pfxs++;
- make_packet(rai);
-
- /*
- * reset the timer so that the new prefix will be advertised quickly.
- */
- rai->initcounter = 0;
- ra_timer_update(rai);
- evtimer_add(&rai->timer.ev, &rai->timer.tm);
-}
-
-/*
- * Delete a prefix to the list of specified interface and reconstruct
- * the outgoing packet.
- * The prefix must be in the list.
- */
-void
-delete_prefix(struct rainfo *rai, struct prefix *prefix)
-{
- u_char ntopbuf[INET6_ADDRSTRLEN];
-
- TAILQ_REMOVE(&rai->prefixes, prefix, entry);
- log_debug("prefix %s/%d was deleted on %s",
- inet_ntop(AF_INET6, &prefix->prefix, ntopbuf, INET6_ADDRSTRLEN),
- prefix->prefixlen, rai->ifname);
- free(prefix);
- rai->pfxs--;
- make_packet(rai);
-}
-
-void
-make_packet(struct rainfo *rainfo)
-{
- size_t packlen, lladdroptlen = 0;
- char *buf;
- struct nd_router_advert *ra;
- struct nd_opt_prefix_info *ndopt_pi;
- struct nd_opt_mtu *ndopt_mtu;
- struct nd_opt_route_info *ndopt_rti;
- struct nd_opt_rdnss *ndopt_rdnss;
- struct nd_opt_dnssl *ndopt_dnssl;
- struct prefix *pfx;
- struct rtinfo *rti;
- struct rdnss *rds;
- struct dnssl *dsl;
- struct dnssldom *dnsd;
-
- /* calculate total length */
- packlen = sizeof(struct nd_router_advert);
- if (rainfo->advlinkopt) {
- if ((lladdroptlen = lladdropt_length(rainfo->sdl)) == 0) {
- log_info("link-layer address option has"
- " null length on %s. Treat as not included.",
- rainfo->ifname);
- rainfo->advlinkopt = 0;
- }
- packlen += lladdroptlen;
- }
- if (rainfo->pfxs)
- packlen += sizeof(struct nd_opt_prefix_info) * rainfo->pfxs;
- if (rainfo->linkmtu)
- packlen += sizeof(struct nd_opt_mtu);
- TAILQ_FOREACH(rti, &rainfo->rtinfos, entry)
- packlen += sizeof(struct nd_opt_route_info) +
- ((rti->prefixlen + 0x3f) >> 6) * 8;
- TAILQ_FOREACH(rds, &rainfo->rdnsss, entry)
- packlen += sizeof(struct nd_opt_rdnss) + 16 * rds->servercnt;
- TAILQ_FOREACH(dsl, &rainfo->dnssls, entry) {
- size_t domains_size = 0;
-
- packlen += sizeof(struct nd_opt_dnssl);
-
- /*
- * Each domain in the packet ends with a null byte. Account for
- * that here.
- */
- TAILQ_FOREACH(dnsd, &dsl->dnssldoms, entry)
- domains_size += dnsd->length + 1;
-
- domains_size = (domains_size + 7) & ~7;
-
- packlen += domains_size;
- }
-
- /* allocate memory for the packet */
- if ((buf = malloc(packlen)) == NULL)
- fatal(NULL);
- /* free the previous packet */
- free(rainfo->ra_data);
- rainfo->ra_data = buf;
- /* XXX: what if packlen > 576? */
- rainfo->ra_datalen = packlen;
-
- /*
- * construct the packet
- */
- ra = (struct nd_router_advert *)buf;
- ra->nd_ra_type = ND_ROUTER_ADVERT;
- ra->nd_ra_code = 0;
- ra->nd_ra_cksum = 0;
- ra->nd_ra_curhoplimit = (u_int8_t)(0xff & rainfo->hoplimit);
- ra->nd_ra_flags_reserved = 0; /* just in case */
- /*
- * XXX: the router preference field, which is a 2-bit field, should be
- * initialized before other fields.
- */
- ra->nd_ra_flags_reserved = 0xff & rainfo->rtpref;
- ra->nd_ra_flags_reserved |=
- rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0;
- ra->nd_ra_flags_reserved |=
- rainfo->otherflg ? ND_RA_FLAG_OTHER : 0;
- ra->nd_ra_router_lifetime = htons(rainfo->lifetime);
- ra->nd_ra_reachable = htonl(rainfo->reachabletime);
- ra->nd_ra_retransmit = htonl(rainfo->retranstimer);
- buf += sizeof(*ra);
-
- if (rainfo->advlinkopt) {
- lladdropt_fill(rainfo->sdl, (struct nd_opt_hdr *)buf);
- buf += lladdroptlen;
- }
-
- if (rainfo->linkmtu) {
- ndopt_mtu = (struct nd_opt_mtu *)buf;
- ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
- ndopt_mtu->nd_opt_mtu_len = 1;
- ndopt_mtu->nd_opt_mtu_reserved = 0;
- ndopt_mtu->nd_opt_mtu_mtu = htonl(rainfo->linkmtu);
- buf += sizeof(struct nd_opt_mtu);
- }
-
- TAILQ_FOREACH(pfx, &rainfo->prefixes, entry) {
- u_int32_t vltime, pltime;
- struct timeval now;
-
- ndopt_pi = (struct nd_opt_prefix_info *)buf;
- ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
- ndopt_pi->nd_opt_pi_len = 4;
- ndopt_pi->nd_opt_pi_prefix_len = pfx->prefixlen;
- ndopt_pi->nd_opt_pi_flags_reserved = 0;
- if (pfx->onlinkflg)
- ndopt_pi->nd_opt_pi_flags_reserved |=
- ND_OPT_PI_FLAG_ONLINK;
- if (pfx->autoconfflg)
- ndopt_pi->nd_opt_pi_flags_reserved |=
- ND_OPT_PI_FLAG_AUTO;
- if (pfx->vltimeexpire || pfx->pltimeexpire)
- gettimeofday(&now, NULL);
- if (pfx->vltimeexpire == 0)
- vltime = pfx->validlifetime;
- else
- vltime = (u_int32_t)(pfx->vltimeexpire > now.tv_sec ?
- pfx->vltimeexpire - now.tv_sec : 0);
- if (pfx->pltimeexpire == 0)
- pltime = pfx->preflifetime;
- else
- pltime = (u_int32_t)(pfx->pltimeexpire > now.tv_sec ?
- pfx->pltimeexpire - now.tv_sec : 0);
- if (vltime < pltime) {
- /*
- * this can happen if vltime is decremented but pltime
- * is not.
- */
- pltime = vltime;
- }
- ndopt_pi->nd_opt_pi_valid_time = htonl(vltime);
- ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime);
- ndopt_pi->nd_opt_pi_reserved2 = 0;
- ndopt_pi->nd_opt_pi_prefix = pfx->prefix;
-
- buf += sizeof(struct nd_opt_prefix_info);
- }
-
- TAILQ_FOREACH(rti, &rainfo->rtinfos, entry) {
- uint8_t psize = (rti->prefixlen + 0x3f) >> 6;
-
- ndopt_rti = (struct nd_opt_route_info *)buf;
- ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO;
- ndopt_rti->nd_opt_rti_len = 1 + psize;
- ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen;
- ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref;
- ndopt_rti->nd_opt_rti_lifetime = htonl(rti->lifetime);
- memcpy(ndopt_rti + 1, &rti->prefix, psize * 8);
- buf += sizeof(struct nd_opt_route_info) + psize * 8;
- }
-
- TAILQ_FOREACH(rds, &rainfo->rdnsss, entry) {
- ndopt_rdnss = (struct nd_opt_rdnss *)buf;
- ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS;
- /*
- * An IPv6 address is 16 bytes, so multiply the number of
- * addresses by two to get a size in units of 8 bytes.
- */
- ndopt_rdnss->nd_opt_rdnss_len = 1 + rds->servercnt * 2;
- ndopt_rdnss->nd_opt_rdnss_reserved = 0;
- ndopt_rdnss->nd_opt_rdnss_lifetime = htonl(rds->lifetime);
-
- buf += sizeof(struct nd_opt_rdnss);
-
- memcpy(buf, rds->servers, rds->servercnt * 16);
- buf += rds->servercnt * 16;
- }
-
- TAILQ_FOREACH(dsl, &rainfo->dnssls, entry) {
- u_int32_t size;
-
- ndopt_dnssl = (struct nd_opt_dnssl *)buf;
- ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL;
- ndopt_dnssl->nd_opt_dnssl_reserved = 0;
- ndopt_dnssl->nd_opt_dnssl_lifetime = htonl(dsl->lifetime);
-
- size = 0;
- TAILQ_FOREACH(dnsd, &dsl->dnssldoms, entry)
- size += dnsd->length + 1;
- /* align size on the next 8 byte boundary */
- size = (size + 7) & ~7;
- ndopt_dnssl->nd_opt_dnssl_len = 1 + size / 8;
-
- buf += sizeof(struct nd_opt_dnssl);
-
- TAILQ_FOREACH(dnsd, &dsl->dnssldoms, entry) {
- char *curlabel_begin;
- char *curlabel_end;
-
- curlabel_begin = dnsd->domain;
- while ((curlabel_end = strchr(curlabel_begin, '.'))
- != NULL && curlabel_end > curlabel_begin)
- {
- size_t curlabel_size;
-
- curlabel_size = curlabel_end - curlabel_begin;
- *buf++ = curlabel_size;
- memcpy(buf, curlabel_begin, curlabel_size);
- buf += curlabel_size;
- curlabel_begin = curlabel_end + 1;
- }
-
- /* null-terminate the current domain */
- *buf++ = '\0';
- }
-
- /* zero out the end of the current option */
- while (((uintptr_t)buf) % 8 != 0)
- *buf++ = '\0';
- }
-}
-
-static int
-getinet6sysctl(int code)
-{
- int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 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) {
- log_warn("failed to get ip6 sysctl(%d)", code);
- return(-1);
- } else
- return(value);
-}
+++ /dev/null
-/* $OpenBSD: config.h,v 1.10 2016/02/08 23:19:00 jca Exp $ */
-/* $KAME: config.h,v 1.3 2000/05/16 13:34:13 itojun Exp $ */
-
-/*
- * Copyright (C) 1995, 1996, 1997, 1998, and 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.
- */
-
-extern void getconfig(char *);
-extern void delete_prefix(struct rainfo *, struct prefix *);
-extern void make_prefix(struct rainfo *, int, struct in6_addr *, int);
-extern void make_packet(struct rainfo *);
-extern void get_prefix(struct rainfo *);
-
-
-/*
- * it is highly unlikely to have 100 prefix, rdnss or dnssl information options,
- * so it should be okay to limit it
- */
-#define MAXPREFIX 100
-#define MAXRTINFO 100
-#define MAXRDNSS 100
-#define MAXDNSSL 100
+++ /dev/null
-/* $OpenBSD: dump.c,v 1.23 2017/04/05 13:38:18 jca Exp $ */
-/* $KAME: dump.c,v 1.27 2002/05/29 14:23:55 itojun Exp $ */
-
-/*
- * Copyright (C) 2000 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/socket.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/if_dl.h>
-
-#include <netinet/in.h>
-
-/* XXX: the following two are non-standard include files */
-#include <netinet6/in6_var.h>
-#include <netinet6/nd6.h>
-
-#include <arpa/inet.h>
-
-#include <time.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <netdb.h>
-#include <event.h>
-
-#include "rtadvd.h"
-#include "if.h"
-#include "log.h"
-#include "dump.h"
-
-extern struct ralist ralist;
-
-static char *ether_str(struct sockaddr_dl *);
-char *lifetime(int);
-
-static char *rtpref_str[] = {
- "medium", /* 00 */
- "high", /* 01 */
- "rsv", /* 10 */
- "low" /* 11 */
-};
-
-static char *
-ether_str(struct sockaddr_dl *sdl)
-{
- static char hbuf[NI_MAXHOST];
- u_char *cp;
-
- if (sdl->sdl_alen) {
- cp = (u_char *)LLADDR(sdl);
- snprintf(hbuf, sizeof(hbuf), "%02x:%02x:%02x:%02x:%02x:%02x",
- cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
- } else
- snprintf(hbuf, sizeof(hbuf), "NONE");
-
- return(hbuf);
-}
-
-char *
-lifetime(int lt)
-{
- char *str;
-
- if (lt == ND6_INFINITE_LIFETIME) {
- if (asprintf(&str, "infinity") < 0)
- return (NULL);
- } else {
- if (asprintf(&str, "%ld", (long)lt) < 0)
- return (NULL);
- }
- return str;
-}
-
-void
-rtadvd_dump(void)
-{
- struct rainfo *rai;
- struct prefix *pfx;
- struct rdnss *rds;
- struct dnssl *dsl;
- struct dnssldom *dnsd;
- char prefixbuf[INET6_ADDRSTRLEN];
- int first;
- struct timeval now, next;
- char *origin, *vltime, *pltime, *flags;
- char *vltimexpire, *pltimexpire;
- char ctimebuf[26];
-
- gettimeofday(&now, NULL);
- SLIST_FOREACH(rai, &ralist, entry) {
- log_info("%s:", rai->ifname);
-
- log_info(" Status: %s",
- (iflist[rai->ifindex]->ifm_flags & IFF_UP) ? "UP" : "DOWN");
-
- /* control information */
- if (rai->lastsent.tv_sec) {
- time_t t = rai->lastsent.tv_sec;
- (void)strlcpy(ctimebuf, ctime(&t), sizeof(ctimebuf));
- ctimebuf[strcspn(ctimebuf, "\n")] = '\0';
- log_info(" Last RA sent: %s", ctimebuf);
- }
- if (evtimer_pending(&rai->timer.ev, &next)) {
- time_t t = next.tv_sec;
- (void)strlcpy(ctimebuf, ctime(&t), sizeof(ctimebuf));
- ctimebuf[strcspn(ctimebuf, "\n")] = '\0';
- log_info(" Next RA will be sent: %s", ctimebuf);
- } else
- log_info(" RA timer is stopped");
- log_info(" waits: %u, initcount: %u",
- rai->waiting, rai->initcounter);
-
- /* statistics */
- log_info(" statistics: RA(out/in/inconsistent): "
- "%llu/%llu/%llu, RS(input): %llu",
- (unsigned long long)rai->raoutput,
- (unsigned long long)rai->rainput,
- (unsigned long long)rai->rainconsistent,
- (unsigned long long)rai->rsinput);
-
- /* interface information */
- if (rai->advlinkopt)
- log_info(" Link-layer address: %s",
- ether_str(rai->sdl));
- log_info(" MTU: %d", rai->phymtu);
-
- /* Router configuration variables */
- log_info(" DefaultLifetime: %d, MaxAdvInterval: %d, "
- "MinAdvInterval: %d, "
- "Flags: %s%s, Preference: %s, MTU: %d",
- rai->lifetime, rai->maxinterval, rai->mininterval,
- rai->managedflg ? "M" : "-", rai->otherflg ? "O" : "-",
- rtpref_str[(rai->rtpref >> 3) & 0xff], rai->linkmtu);
- log_info(" ReachableTime: %d, RetransTimer: %d, "
- "CurHopLimit: %d", rai->reachabletime,
- rai->retranstimer, rai->hoplimit);
- if (rai->clockskew)
- log_info(" Clock skew: %ldsec",
- rai->clockskew);
- first = 1;
- TAILQ_FOREACH(pfx, &rai->prefixes, entry) {
- if (first) {
- log_info(" Prefixes:");
- first = 0;
- }
- switch (pfx->origin) {
- case PREFIX_FROM_KERNEL:
- origin = "KERNEL";
- break;
- case PREFIX_FROM_CONFIG:
- origin = "CONFIG";
- break;
- case PREFIX_FROM_DYNAMIC:
- origin = "DYNAMIC";
- break;
- default:
- origin = "";
- }
- if (pfx->vltimeexpire != 0) {
- /* truncate to onwire value */
- if (asprintf(&vltimexpire, "(decr,expire %u)",
- (u_int32_t)(pfx->vltimeexpire > now.tv_sec ?
- pfx->vltimeexpire - now.tv_sec : 0)) == -1)
- vltimexpire = NULL;
- } else
- vltimexpire = NULL;
-
- if (pfx->pltimeexpire != 0) {
- /* truncate to onwire value */
- if (asprintf(&pltimexpire, "(decr,expire %u)",
- (u_int32_t)(pfx->pltimeexpire > now.tv_sec ?
- pfx->pltimeexpire - now.tv_sec : 0)) == -1)
- pltimexpire = NULL;
- } else
- pltimexpire = NULL;
-
- vltime = lifetime(pfx->validlifetime);
- pltime = lifetime(pfx->preflifetime);
- asprintf(&flags, "%s%s",
- pfx->onlinkflg ? "L" : "-",
- pfx->autoconfflg ? "A" : "-");
- log_info(" %s/%d(%s, vltime: %s%s, "
- "pltime: %s%s, flags: %s)",
- inet_ntop(AF_INET6, &pfx->prefix, prefixbuf,
- sizeof(prefixbuf)), pfx->prefixlen, origin,
- vltime, (vltimexpire)? vltimexpire : "",
- pltime, (pltimexpire)? pltimexpire : "", flags);
-
- free(vltimexpire);
- vltimexpire = NULL;
- free(pltimexpire);
- pltimexpire = NULL;
- free(vltime);
- free(pltime);
- free(flags);
- }
-
- if (!TAILQ_EMPTY(&rai->rdnsss))
- log_info(" Recursive DNS servers:");
- TAILQ_FOREACH(rds, &rai->rdnsss, entry) {
- log_info(" Servers:");
- for (first = 0; first < rds->servercnt; ++first) {
- inet_ntop(AF_INET6, &rds->servers[first],
- prefixbuf, sizeof(prefixbuf));
- log_info(" %s", prefixbuf);
- }
- log_info(" Lifetime: %u", rds->lifetime);
- }
-
- if (!TAILQ_EMPTY(&rai->dnssls))
- log_info(" DNS search lists:");
- TAILQ_FOREACH(dsl, &rai->dnssls, entry) {
- log_info(" Domains:");
-
- TAILQ_FOREACH(dnsd, &dsl->dnssldoms, entry)
- log_info(" %s", dnsd->domain);
-
- log_info(" Lifetime: %u", dsl->lifetime);
- }
- }
-}
+++ /dev/null
-/* $OpenBSD: dump.h,v 1.5 2016/02/08 23:19:00 jca Exp $ */
-/* $KAME: dump.h,v 1.1 2000/05/23 11:31:26 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.
- */
-
-void rtadvd_dump(void);
+++ /dev/null
-/* $OpenBSD: if.c,v 1.46 2017/08/12 07:38:26 florian Exp $ */
-/* $KAME: if.c,v 1.17 2001/01/21 15:27:30 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/socket.h>
-#include <sys/sysctl.h>
-#include <sys/queue.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <net/if_types.h>
-#include <ifaddrs.h>
-#include <net/route.h>
-#include <net/if_dl.h>
-#include <netinet/in.h>
-#include <netinet/icmp6.h>
-#include <netinet/if_ether.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <event.h>
-
-#include "rtadvd.h"
-#include "if.h"
-#include "log.h"
-
-#define ROUNDUP(a, size) \
- (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
-
-#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
- ((char *)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\
- sizeof(u_long)) :\
- sizeof(u_long)))
-
-struct if_msghdr **iflist;
-static void get_iflist(char **buf, size_t *size);
-static void parse_iflist(struct if_msghdr ***ifmlist_p, char *buf,
- size_t bufsize);
-
-extern int ioctl_sock;
-
-static void
-get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
-{
- int i;
-
- for (i = 0; i < RTAX_MAX; i++) {
- if (addrs & (1 << i)) {
- rti_info[i] = sa;
- NEXT_SA(sa);
- }
- else
- rti_info[i] = NULL;
- }
-}
-
-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
-if_getmtu(char *name)
-{
- struct ifreq ifr;
- u_long mtu = 0;
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_addr.sa_family = AF_INET6;
- if (strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)) >=
- sizeof(ifr.ifr_name))
- fatalx("strlcpy");
- if (ioctl(ioctl_sock, SIOCGIFMTU, (char *)&ifr) >= 0)
- mtu = ifr.ifr_mtu;
- else
- log_warn("s: %d", ioctl_sock);
- return (mtu);
-}
-
-/* give interface index and its old flags, then new flags returned */
-int
-if_getflags(int ifindex, int oifflags)
-{
- struct ifreq ifr;
-
- if_indextoname(ifindex, ifr.ifr_name);
- if (ioctl(ioctl_sock, SIOCGIFFLAGS, (char *)&ifr) < 0) {
- log_warn("ioctl:SIOCGIFFLAGS: failed for %s", ifr.ifr_name);
- return (oifflags & ~IFF_UP);
- }
- return (ifr.ifr_flags);
-}
-
-#define ROUNDUP8(a) (1 + (((a) - 1) | 7))
-int
-lladdropt_length(struct sockaddr_dl *sdl)
-{
- switch (sdl->sdl_type) {
- case IFT_CARP:
- case IFT_ETHER:
- 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_CARP:
- case IFT_ETHER:
- ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
- addr = (char *)(ndopt + 1);
- memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
- break;
- default:
- fatalx("unsupported link type(%d)", sdl->sdl_type);
- }
-}
-
-#define SIN6(s) ((struct sockaddr_in6 *)(s))
-int
-validate_msg(char *buf)
-{
- struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
- struct ifa_msghdr *ifam;
- struct sockaddr *sa, *dst, *ifa, *rti_info[RTAX_MAX];
-
- /* just for safety */
- if (!rtm->rtm_msglen) {
- log_warnx("rtm_msglen is 0 (rtm=%p)", rtm);
- return -1;
- }
- if (rtm->rtm_version != RTM_VERSION)
- return -1;
-
- switch (rtm->rtm_type) {
- case RTM_ADD:
- case RTM_DELETE:
- if (rtm->rtm_tableid != 0)
- return -1;
-
- /* address related checks */
- sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
- get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
- if ((dst = rti_info[RTAX_DST]) == NULL ||
- dst->sa_family != AF_INET6)
- return -1;
-
- if (IN6_IS_ADDR_LINKLOCAL(&SIN6(dst)->sin6_addr) ||
- IN6_IS_ADDR_MULTICAST(&SIN6(dst)->sin6_addr))
- return -1;
-
- if (rti_info[RTAX_NETMASK] == NULL)
- return -1;
-
- /* found */
- return 0;
- /* NOTREACHED */
- case RTM_NEWADDR:
- case RTM_DELADDR:
- ifam = (struct ifa_msghdr *)rtm;
-
- /* address related checks */
- sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
- get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
- if ((ifa = rti_info[RTAX_IFA]) == NULL ||
- (ifa->sa_family != AF_INET &&
- ifa->sa_family != AF_INET6))
- return -1;
-
- if (ifa->sa_family == AF_INET6 &&
- (IN6_IS_ADDR_LINKLOCAL(&SIN6(ifa)->sin6_addr) ||
- IN6_IS_ADDR_MULTICAST(&SIN6(ifa)->sin6_addr)))
- return -1;
-
- /* found */
- return 0;
- /* NOTREACHED */
- case RTM_IFINFO:
- /* found */
- return 0;
- /* NOTREACHED */
- }
- return -1;
-}
-
-struct in6_addr *
-get_addr(char *buf)
-{
- struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
- struct sockaddr *sa, *rti_info[RTAX_MAX];
-
- sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen);
- get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
-
- return(&SIN6(rti_info[RTAX_DST])->sin6_addr);
-}
-
-int
-get_rtm_ifindex(char *buf)
-{
- struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
-
- return rtm->rtm_index;
-}
-
-int
-get_ifm_ifindex(char *buf)
-{
- struct if_msghdr *ifm = (struct if_msghdr *)buf;
-
- return ((int)ifm->ifm_index);
-}
-
-int
-get_ifam_ifindex(char *buf)
-{
- struct ifa_msghdr *ifam = (struct ifa_msghdr *)buf;
-
- return ((int)ifam->ifam_index);
-}
-
-int
-get_ifm_flags(char *buf)
-{
- struct if_msghdr *ifm = (struct if_msghdr *)buf;
-
- return (ifm->ifm_flags);
-}
-
-int
-get_prefixlen(char *buf)
-{
- struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
- struct sockaddr *sa, *rti_info[RTAX_MAX];
- u_char *p, *lim;
-
- sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen);
- get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
- sa = rti_info[RTAX_NETMASK];
-
- p = (u_char *)(&SIN6(sa)->sin6_addr);
- lim = (u_char *)sa + sa->sa_len;
- return prefixlen(p, lim);
-}
-
-int
-prefixlen(u_char *p, u_char *lim)
-{
- int masklen;
-
- for (masklen = 0; p < lim; p++) {
- switch (*p) {
- case 0xff:
- masklen += 8;
- break;
- case 0xfe:
- masklen += 7;
- break;
- case 0xfc:
- masklen += 6;
- break;
- case 0xf8:
- masklen += 5;
- break;
- case 0xf0:
- masklen += 4;
- break;
- case 0xe0:
- masklen += 3;
- break;
- case 0xc0:
- masklen += 2;
- break;
- case 0x80:
- masklen += 1;
- break;
- case 0x00:
- break;
- default:
- return(-1);
- }
- }
-
- return(masklen);
-}
-
-int
-rtmsg_type(char *buf)
-{
- struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
-
- return(rtm->rtm_type);
-}
-
-int
-rtmsg_len(char *buf)
-{
- struct rt_msghdr *rtm = (struct rt_msghdr *)buf;
-
- return(rtm->rtm_msglen);
-}
-
-/*
- * alloc buffer and get if_msghdrs block from kernel,
- * and put them into the buffer
- */
-static void
-get_iflist(char **buf, size_t *size)
-{
- int mib[6];
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0;
- mib[3] = AF_INET6;
- mib[4] = NET_RT_IFLIST;
- mib[5] = 0;
- while (1) {
- if (sysctl(mib, 6, NULL, size, NULL, 0) == -1)
- fatal("sysctl: iflist size get failed");
- if (*size == 0)
- break;
- if ((*buf = realloc(*buf, *size)) == NULL)
- fatal(NULL);
- if (sysctl(mib, 6, *buf, size, NULL, 0) == -1) {
- if (errno == ENOMEM)
- continue;
- fatal("sysctl: iflist get failed");
- }
- break;
- }
-}
-
-/*
- * alloc buffer and parse if_msghdrs block passed as arg,
- * and init the buffer as list of pointers ot each of the if_msghdr.
- */
-static void
-parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
-{
- int iflentry_size, malloc_size;
- struct if_msghdr *ifm;
- struct ifa_msghdr *ifam;
- char *lim;
-
- /*
- * Estimate least size of an iflist entry, to be obtained from kernel.
- * Should add sizeof(sockaddr) ??
- */
- iflentry_size = sizeof(struct if_msghdr);
- /* roughly estimate max list size of pointers to each if_msghdr */
- malloc_size = (bufsize/iflentry_size) * sizeof(size_t);
- if ((*ifmlist_p = malloc(malloc_size)) == NULL)
- fatal(NULL);
-
- lim = buf + bufsize;
- for (ifm = (struct if_msghdr *)buf; ifm < (struct if_msghdr *)lim;) {
- if (ifm->ifm_msglen == 0) {
- log_warnx("ifm_msglen is 0 (buf=%p lim=%p ifm=%p)",
- buf, lim, ifm);
- return;
- }
- if (ifm->ifm_type == RTM_IFINFO) {
- if (ifm->ifm_version == RTM_VERSION)
- (*ifmlist_p)[ifm->ifm_index] = ifm;
- } else {
- fatalx("out of sync parsing NET_RT_IFLIST,"
- " expected %d, got %d, msglen = %d,"
- " buf:%p, ifm:%p, lim:%p",
- RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen,
- buf, ifm, lim);
- }
- for (ifam = (struct ifa_msghdr *)
- ((char *)ifm + ifm->ifm_msglen);
- ifam < (struct ifa_msghdr *)lim;
- ifam = (struct ifa_msghdr *)
- ((char *)ifam + ifam->ifam_msglen)) {
- /* just for safety */
- if (!ifam->ifam_msglen) {
- log_warnx("ifa_msglen is 0 "
- "(buf=%p lim=%p ifam=%p)",
- buf, lim, ifam);
- return;
- }
- if (ifam->ifam_type != RTM_NEWADDR)
- break;
- }
- ifm = (struct if_msghdr *)ifam;
- }
-}
-
-void
-init_iflist(void)
-{
- static size_t ifblock_size;
- static char *ifblock;
-
- if (ifblock) {
- free(ifblock);
- ifblock_size = 0;
- }
- free(iflist);
- /* get iflist block from kernel */
- get_iflist(&ifblock, &ifblock_size);
-
- /* make list of pointers to each if_msghdr */
- parse_iflist(&iflist, ifblock, ifblock_size);
-}
+++ /dev/null
-/* $OpenBSD: if.h,v 1.14 2017/08/10 19:07:14 jca Exp $ */
-/* $KAME: if.h,v 1.6 2001/01/21 15:37:14 itojun Exp $ */
-
-/*
- * Copyright (C) 1995, 1996, 1997, 1998, and 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.
- */
-
-#define RTADV_TYPE2BITMASK(type) (0x1 << type)
-
-extern struct if_msghdr **iflist;
-
-struct nd_opt_hdr;
-struct sockaddr_dl *if_nametosdl(char *);
-int if_getmtu(char *);
-int if_getflags(int, int);
-int lladdropt_length(struct sockaddr_dl *);
-void lladdropt_fill(struct sockaddr_dl *, struct nd_opt_hdr *);
-int validate_msg(char *);
-struct in6_addr *get_addr(char *);
-int get_rtm_ifindex(char *);
-int get_ifm_ifindex(char *);
-int get_ifam_ifindex(char *);
-int get_ifm_flags(char *);
-int get_prefixlen(char *);
-int prefixlen(u_char *, u_char *);
-int rtmsg_type(char *);
-int ifmsg_type(char *);
-int rtmsg_len(char *);
-void init_iflist(void);
+++ /dev/null
-/* $OpenBSD: log.c,v 1.4 2017/07/12 06:09:59 florian Exp $ */
-
-/*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "log.h"
-
-int debug;
-int verbose;
-const char *log_procname;
-
-void
-log_init(int n_debug)
-{
- extern char *__progname;
-
- debug = n_debug;
-
- if (!debug)
- openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
-
- tzset();
-}
-
-void
-log_verbose(int v)
-{
- verbose = v;
-}
-
-void
-logit(int pri, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vlog(pri, fmt, ap);
- va_end(ap);
-}
-
-void
-vlog(int pri, const char *fmt, va_list ap)
-{
- char *nfmt;
-
- if (debug) {
- /* best effort in out of mem situations */
- if (asprintf(&nfmt, "%s\n", fmt) == -1) {
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- } else {
- vfprintf(stderr, nfmt, ap);
- free(nfmt);
- }
- fflush(stderr);
- } else
- vsyslog(pri, fmt, ap);
-}
-
-void
-log_warn(const char *emsg, ...)
-{
- char *nfmt;
- va_list ap;
-
- /* best effort to even work in out of memory situations */
- if (emsg == NULL)
- logit(LOG_ERR, "%s", strerror(errno));
- else {
- va_start(ap, emsg);
-
- if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
- /* we tried it... */
- vlog(LOG_ERR, emsg, ap);
- logit(LOG_ERR, "%s", strerror(errno));
- } else {
- vlog(LOG_ERR, nfmt, ap);
- free(nfmt);
- }
- va_end(ap);
- }
-}
-
-void
-log_warnx(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vlog(LOG_ERR, emsg, ap);
- va_end(ap);
-}
-
-void
-log_info(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vlog(LOG_INFO, emsg, ap);
- va_end(ap);
-}
-
-void
-log_debug(const char *emsg, ...)
-{
- va_list ap;
-
- if (verbose) {
- va_start(ap, emsg);
- vlog(LOG_DEBUG, emsg, ap);
- va_end(ap);
- }
-}
-
-static void
-vfatalc(int code, const char *emsg, va_list ap)
-{
- static char s[BUFSIZ];
- const char *sep;
-
- if (emsg != NULL) {
- (void)vsnprintf(s, sizeof(s), emsg, ap);
- sep = ": ";
- } else {
- s[0] = '\0';
- sep = "";
- }
- if (code)
- logit(LOG_CRIT, "fatal in %s: %s%s%s",
- log_procname, s, sep, strerror(code));
- else
- logit(LOG_CRIT, "fatal in %s%s%s", log_procname, sep, s);
-}
-
-void
-fatal(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vfatalc(errno, emsg, ap);
- va_end(ap);
- exit(1);
-}
-
-void
-fatalx(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vfatalc(0, emsg, ap);
- va_end(ap);
- exit(1);
-}
+++ /dev/null
-/* $OpenBSD: log.h,v 1.4 2017/07/12 06:09:59 florian Exp $ */
-
-/*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef LOG_H
-#define LOG_H
-
-#include <stdarg.h>
-
-extern const char *log_procname;
-
-void log_init(int);
-void log_verbose(int);
-void logit(int, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)));
-void vlog(int, const char *, va_list)
- __attribute__((__format__ (printf, 2, 0)));
-void log_warn(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_warnx(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_info(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_debug(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-__dead void fatal(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-__dead void fatalx(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-
-#endif /* LOG_H */
+++ /dev/null
-/* $OpenBSD: pathnames.h,v 1.4 2000/05/23 11:23:23 itojun Exp $ */
-/* $KAME: pathnames.h,v 1.2 2000/05/16 13:34:13 itojun Exp $ */
-
-#define _PATH_RTADVDCONF "/etc/rtadvd.conf"
+++ /dev/null
-.\" $OpenBSD: rtadvd.8,v 1.35 2017/09/14 12:56:36 sthen Exp $
-.\" $KAME: rtadvd.8,v 1.18 2002/04/28 10:43:02 jinmei 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: September 14 2017 $
-.Dt RTADVD 8
-.Os
-.Sh NAME
-.Nm rtadvd
-.Nd router advertisement daemon
-.Sh SYNOPSIS
-.Nm
-.Op Fl ds
-.Op Fl c Ar configfile
-.Ar interface ...
-.Sh DESCRIPTION
-.Nm
-sends router advertisement packets to the specified interfaces.
-.Pp
-The program will daemonize itself on invocation.
-It will then send router advertisement packets periodically, as well
-as in response to router solicitation messages sent by end hosts.
-.Pp
-Router advertisements can be configured on a per-interface basis, as
-described in
-.Xr rtadvd.conf 5 .
-.Pp
-If there is no configuration file entry for an interface,
-or if the configuration file does not exist at all,
-.Nm
-sets all the parameters to their default values.
-In particular,
-.Nm
-reads all the interface routes from the routing table and advertises
-them as on-link prefixes.
-.Pp
-.Nm
-also watches the routing table.
-By default, if an interface direct route is
-added/deleted on an advertising interface and no static prefixes are
-specified by the configuration file,
-.Nm
-adds/deletes the corresponding prefix to/from its advertising list,
-respectively.
-The
-.Fl s
-option may be used to disable this behavior.
-Moreover, if the status of an advertising interface changes,
-.Nm
-will start or stop sending router advertisements according
-to the latest status.
-.Pp
-Basically, hosts MUST NOT send Router Advertisement messages at any
-time (RFC 4861, Section 6.2.4).
-However, it would sometimes be useful to allow hosts to advertise some
-parameters such as prefix information and link MTU.
-Thus,
-.Nm
-can be invoked if router lifetime is explicitly set to zero on every
-advertising interface.
-.Pp
-The command line options are:
-.Bl -tag -width indent
-.\"
-.It Fl c Ar configfile
-Specify an alternate location,
-.Ar configfile ,
-for the configuration file.
-By default,
-.Pa /etc/rtadvd.conf
-is used.
-.It Fl d
-Do not daemonize.
-If this option is specified,
-.Nm
-will run in the foreground and log to
-.Em stderr .
-.It Fl s
-Do not add or delete prefixes dynamically.
-Only statically configured prefixes, if any, will be advertised.
-.El
-.Pp
-Upon receipt of signal
-.Dv SIGUSR1 ,
-.Nm
-will dump the current internal state into
-.Xr syslog 3 .
-.Pp
-Use
-.Dv SIGTERM
-to kill
-.Nm
-gracefully.
-In this case,
-.Nm
-will transmit router advertisement with router lifetime 0
-to all the interfaces
-.Pq in accordance with RFC 4861 6.2.5 .
-.Sh FILES
-.Bl -tag -width "/etc/rtadvd.conf" -compact
-.It Pa /etc/rtadvd.conf
-The default configuration file.
-.El
-.Sh EXIT STATUS
-.Ex -std rtadvd
-.Sh SEE ALSO
-.Xr rtadvd.conf 5 ,
-.Xr slaacd 8 ,
-.Xr syslogd 8
-.Sh HISTORY
-The
-.Nm
-command first appeared in the WIDE Hydrangea IPv6 protocol stack kit.
-.Sh BUGS
-There used to be some text that recommended users not to let
-.Nm
-advertise Router Advertisement messages on an upstream link to avoid
-undesirable
-.Xr icmp6 4
-redirect messages.
-However, based on later discussion in the IETF IPng working group,
-all routers should rather advertise the messages regardless of
-the network topology, in order to ensure reachability.
+++ /dev/null
-/* $OpenBSD: rtadvd.c,v 1.92 2018/07/16 07:56:04 claudio Exp $ */
-/* $KAME: rtadvd.c,v 1.66 2002/05/29 14:18:36 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/socket.h>
-#include <sys/uio.h>
-#include <sys/time.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/route.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 <stdlib.h>
-#include <err.h>
-#include <errno.h>
-#include <event.h>
-#include <string.h>
-#include <pwd.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <paths.h>
-
-#include "rtadvd.h"
-#include "advcap.h"
-#include "if.h"
-#include "config.h"
-#include "dump.h"
-#include "log.h"
-
-struct msghdr rcvmhdr;
-static u_char *rcvcmsgbuf;
-static size_t rcvcmsgbuflen;
-static u_char *sndcmsgbuf = NULL;
-static size_t sndcmsgbuflen;
-struct msghdr sndmhdr;
-struct iovec rcviov[2];
-struct iovec sndiov[2];
-static char *rtsockbuf;
-static size_t rtsockbuflen;
-struct sockaddr_in6 from;
-struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6};
-int sock;
-int rtsock = -1;
-int ioctl_sock;
-int dflag = 0, sflag = 0;
-
-u_char *conffile = NULL;
-
-struct ralist ralist;
-
-struct nd_opt {
- SLIST_ENTRY(nd_opt) entry;
- struct nd_opt_hdr *opt;
-};
-
-union nd_opts {
- struct nd_opt_hdr *nd_opt_array[9];
- struct {
- struct nd_opt_hdr *zero;
- struct nd_opt_hdr *src_lladdr;
- struct nd_opt_hdr *tgt_lladdr;
- struct nd_opt_prefix_info *pi;
- struct nd_opt_rd_hdr *rh;
- struct nd_opt_mtu *mtu;
- SLIST_HEAD(nd_optlist, nd_opt) list;
- } nd_opt_each;
-};
-#define nd_opts_src_lladdr nd_opt_each.src_lladdr
-#define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr
-#define nd_opts_pi nd_opt_each.pi
-#define nd_opts_rh nd_opt_each.rh
-#define nd_opts_mtu nd_opt_each.mtu
-#define nd_opts_list nd_opt_each.list
-
-#define NDOPT_FLAG_SRCLINKADDR (1 << 0)
-#define NDOPT_FLAG_TGTLINKADDR (1 << 1)
-#define NDOPT_FLAG_PREFIXINFO (1 << 2)
-#define NDOPT_FLAG_RDHDR (1 << 3)
-#define NDOPT_FLAG_MTU (1 << 4)
-#define NDOPT_FLAG_RDNSS (1 << 5)
-#define NDOPT_FLAG_DNSSL (1 << 6)
-#define NDOPT_FLAG_ROUTE_INFO (1 << 7)
-
-u_int32_t ndopt_flags[] = {
- [ND_OPT_SOURCE_LINKADDR] = NDOPT_FLAG_SRCLINKADDR,
- [ND_OPT_TARGET_LINKADDR] = NDOPT_FLAG_TGTLINKADDR,
- [ND_OPT_PREFIX_INFORMATION] = NDOPT_FLAG_PREFIXINFO,
- [ND_OPT_REDIRECTED_HEADER] = NDOPT_FLAG_RDHDR,
- [ND_OPT_MTU] = NDOPT_FLAG_MTU,
- [ND_OPT_ROUTE_INFO] = NDOPT_FLAG_ROUTE_INFO,
- [ND_OPT_RDNSS] = NDOPT_FLAG_RDNSS,
- [ND_OPT_DNSSL] = NDOPT_FLAG_DNSSL,
-};
-
-static __dead void usage(void);
-static void sock_open(void);
-static void rtsock_open(void);
-static void rs_input(int, struct nd_router_solicit *,
- struct in6_pktinfo *, struct sockaddr_in6 *);
-static void ra_input(int, struct nd_router_advert *,
- struct in6_pktinfo *, struct sockaddr_in6 *);
-static int prefix_check(struct nd_opt_prefix_info *, struct rainfo *,
- struct sockaddr_in6 *);
-static int nd6_options(struct nd_opt_hdr *, int,
- union nd_opts *, u_int32_t);
-static void free_ndopts(union nd_opts *);
-static void ra_output(struct rainfo *, struct sockaddr_in6 *);
-static struct rainfo *if_indextorainfo(int);
-static int rdaemon(int);
-
-static void dump_cb(int, short, void *);
-static void die_cb(int, short, void *);
-static void rtsock_cb(int, short, void *);
-static void sock_cb(int, short, void *);
-static void timer_cb(int, short, void *);
-
-int
-main(int argc, char *argv[])
-{
- struct passwd *pw;
- int ch;
- int devnull = -1;
- struct event ev_sock;
- struct event ev_rtsock;
- struct event ev_sigterm;
- struct event ev_sigusr1;
- struct rainfo *rai;
-
- log_procname = getprogname();
- log_init(1); /* log to stderr until daemonized */
-
- closefrom(3);
-
- /* get command line options and arguments */
- while ((ch = getopt(argc, argv, "c:ds")) != -1) {
- switch (ch) {
- case 'c':
- conffile = optarg;
- break;
- case 'd':
- dflag = 1;
- break;
- case 's':
- sflag = 1;
- break;
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
- if (argc == 0)
- usage();
-
- if (!dflag) {
- devnull = open(_PATH_DEVNULL, O_RDWR, 0);
- if (devnull == -1)
- fatal("open(\"" _PATH_DEVNULL "\")");
- } else
- log_verbose(1);
-
- SLIST_INIT(&ralist);
-
- /* get iflist block from kernel */
- init_iflist();
-
- if (conffile == NULL)
- log_init(dflag);
-
- if ((ioctl_sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
- fatal("socket");
-
- while (argc--)
- getconfig(*argv++);
-
- if (inet_pton(AF_INET6, ALLNODES, &sin6_allnodes.sin6_addr) != 1)
- fatal("inet_pton failed");
-
- sock_open();
-
- if (sflag == 0)
- rtsock_open();
-
- if ((pw = getpwnam(RTADVD_USER)) == NULL)
- fatal("getpwnam(" RTADVD_USER ")");
- if (chroot(pw->pw_dir) == -1)
- fatal("chroot");
- if (chdir("/") == -1)
- fatal("chdir(\"/\")");
- if (setgroups(1, &pw->pw_gid) == -1 ||
- setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
- setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
- fatal("cannot drop privileges");
-
- if (!dflag) {
- if (rdaemon(devnull) == -1)
- fatal("rdaemon");
- }
-
- if (conffile != NULL)
- log_init(dflag);
-
- if (pledge("stdio inet route", NULL) == -1)
- err(1, "pledge");
-
- event_init();
-
- signal_set(&ev_sigterm, SIGTERM, die_cb, NULL);
- signal_add(&ev_sigterm, NULL);
- signal_set(&ev_sigusr1, SIGUSR1, dump_cb, NULL);
- signal_add(&ev_sigusr1, NULL);
-
- event_set(&ev_sock, sock, EV_READ|EV_PERSIST, sock_cb, NULL);
- event_add(&ev_sock, NULL);
- if (rtsock != -1) {
- event_set(&ev_rtsock, rtsock, EV_READ|EV_PERSIST, rtsock_cb,
- NULL);
- event_add(&ev_rtsock, NULL);
- }
-
- SLIST_FOREACH(rai, &ralist, entry) {
- evtimer_set(&rai->timer.ev, timer_cb, rai);
- evtimer_add(&rai->timer.ev, &rai->timer.tm);
- }
-
- event_dispatch();
-
- log_warn("event_dispatch returned");
-
- return 1;
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s [-ds] [-c configfile] interface ...\n",
- getprogname());
- exit(1);
-}
-
-static void
-dump_cb(int sig, short event, void *arg)
-{
- rtadvd_dump();
-}
-
-static void
-die_cb(int sig, short event, void *arg)
-{
- struct rainfo *ra;
- int i;
- const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS;
-
- log_debug("cease to be an advertising router");
-
- SLIST_FOREACH(ra, &ralist, entry) {
- ra->lifetime = 0;
- make_packet(ra);
- }
- for (i = 0; i < retrans; i++) {
- SLIST_FOREACH(ra, &ralist, entry)
- ra_output(ra, &sin6_allnodes);
- sleep(MIN_DELAY_BETWEEN_RAS);
- }
- exit(0);
- /*NOTREACHED*/
-}
-
-static void
-rtsock_cb(int fd, short event, void *arg)
-{
- int n, type, ifindex = 0, oldifflags, plen;
- char *rtm;
- u_char ifname[IF_NAMESIZE];
- struct prefix *prefix;
- struct rainfo *rai;
- struct in6_addr *addr;
- char addrbuf[INET6_ADDRSTRLEN];
-
- n = read(rtsock, rtsockbuf, rtsockbuflen);
- log_debug("received a routing message "
- "(type = %d, len = %d)", rtmsg_type(rtsockbuf), n);
-
- rtm = rtsockbuf;
- if (validate_msg(rtm) == -1)
- return;
-
- type = rtmsg_type(rtm);
- switch (type) {
- case RTM_ADD:
- case RTM_DELETE:
- ifindex = get_rtm_ifindex(rtm);
- break;
- case RTM_NEWADDR:
- case RTM_DELADDR:
- ifindex = get_ifam_ifindex(rtm);
- break;
- case RTM_IFINFO:
- ifindex = get_ifm_ifindex(rtm);
- break;
- default:
- /* should not reach here */
- log_debug("unknown rtmsg %d on %s",
- type, if_indextoname(ifindex, ifname));
- return;
- }
-
- if ((rai = if_indextorainfo(ifindex)) == NULL) {
- log_debug("route changed on "
- "non advertising interface(%s)",
- if_indextoname(ifindex, ifname));
- return;
- }
- oldifflags = iflist[ifindex]->ifm_flags;
-
- switch (type) {
- case RTM_ADD:
- /* init ifflags because it may have changed */
- iflist[ifindex]->ifm_flags =
- if_getflags(ifindex, iflist[ifindex]->ifm_flags);
-
- if (sflag)
- break; /* we aren't interested in prefixes */
-
- addr = get_addr(rtm);
- plen = get_prefixlen(rtm);
- /* sanity check for plen */
- /* as RFC2373, prefixlen is at least 4 */
- if (plen < 4 || plen > 127) {
- log_info("new interface route's"
- " plen %d is invalid for a prefix", plen);
- break;
- }
- prefix = find_prefix(rai, addr, plen);
- if (prefix) {
- log_debug("new prefix(%s/%d) "
- "added on %s, "
- "but it was already in list",
- inet_ntop(AF_INET6, addr,
- addrbuf, INET6_ADDRSTRLEN),
- plen, rai->ifname);
- break;
- }
- make_prefix(rai, ifindex, addr, plen);
- break;
- case RTM_DELETE:
- /* init ifflags because it may have changed */
- iflist[ifindex]->ifm_flags =
- if_getflags(ifindex, iflist[ifindex]->ifm_flags);
-
- if (sflag)
- break;
-
- addr = get_addr(rtm);
- plen = get_prefixlen(rtm);
- /* sanity check for plen */
- /* as RFC2373, prefixlen is at least 4 */
- if (plen < 4 || plen > 127) {
- log_info("deleted interface route's "
- "plen %d is invalid for a prefix", plen);
- break;
- }
- prefix = find_prefix(rai, addr, plen);
- if (prefix == NULL) {
- log_debug("prefix(%s/%d) was "
- "deleted on %s, "
- "but it was not in list",
- inet_ntop(AF_INET6, addr,
- addrbuf, INET6_ADDRSTRLEN),
- plen, rai->ifname);
- break;
- }
- delete_prefix(rai, prefix);
- break;
- case RTM_NEWADDR:
- case RTM_DELADDR:
- /* init ifflags because it may have changed */
- iflist[ifindex]->ifm_flags =
- if_getflags(ifindex, iflist[ifindex]->ifm_flags);
- break;
- case RTM_IFINFO:
- iflist[ifindex]->ifm_flags = get_ifm_flags(rtm);
- break;
- default:
- /* should not reach here */
- log_debug("unknown rtmsg %d on %s",
- type, if_indextoname(ifindex, ifname));
- return;
- }
-
- /* check if an interface flag is changed */
- if ((oldifflags & IFF_UP) != 0 && /* UP to DOWN */
- (iflist[ifindex]->ifm_flags & IFF_UP) == 0) {
- log_info("interface %s becomes down. stop timer.",
- rai->ifname);
- evtimer_del(&rai->timer.ev);
- } else if ((oldifflags & IFF_UP) == 0 && /* DOWN to UP */
- (iflist[ifindex]->ifm_flags & IFF_UP) != 0) {
- log_info("interface %s becomes up. restart timer.",
- rai->ifname);
-
- rai->initcounter = 0; /* reset the counter */
- rai->waiting = 0; /* XXX */
- ra_timer_update(rai);
- evtimer_add(&rai->timer.ev, &rai->timer.tm);
- }
-}
-
-void
-sock_cb(int fd, short event, void *arg)
-{
- ssize_t len;
- int *hlimp = NULL;
- struct icmp6_hdr *icp;
- int ifindex = 0;
- struct cmsghdr *cm;
- struct in6_pktinfo *pi = NULL;
- u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
- struct in6_addr dst = in6addr_any;
-
- /*
- * Get message. We reset msg_controllen since the field could
- * be modified if we had received a message before setting
- * receive options.
- */
- rcvmhdr.msg_controllen = rcvcmsgbuflen;
- if ((len = recvmsg(sock, &rcvmhdr, 0)) < 0)
- 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;
- dst = pi->ipi6_addr;
- }
- 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) {
- log_warnx("failed to get receiving interface");
- return;
- }
- if (hlimp == NULL) {
- log_warnx("failed to get receiving hop limit");
- return;
- }
-
- /*
- * If we happen to receive data on an interface which is now down,
- * just discard the data.
- */
- if ((iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) {
- log_info("received data on a disabled interface (%s)",
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
-
- if (len < sizeof(struct icmp6_hdr)) {
- log_warnx("packet size(%zd) is too short", len);
- return;
- }
-
- icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
-
- switch (icp->icmp6_type) {
- case ND_ROUTER_SOLICIT:
- /*
- * Message verification - RFC-2461 6.1.1
- * XXX: these checks must be done in the kernel as well,
- * but we can't completely rely on them.
- */
- if (*hlimp != 255) {
- log_info("RS with invalid hop limit(%d) "
- "received from %s on %s",
- *hlimp,
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
- if (icp->icmp6_code) {
- log_info("RS with invalid ICMP6 code(%d) "
- "received 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 (len < sizeof(struct nd_router_solicit)) {
- log_info("RS from %s on %s too short (len = %zd)",
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf), len);
- return;
- }
- rs_input(len, (struct nd_router_solicit *)icp, pi, &from);
- break;
- case ND_ROUTER_ADVERT:
- /*
- * Message verification - RFC-2461 6.1.2
- * XXX: there's a same dilemma as above...
- */
- if (*hlimp != 255) {
- log_info("RA with invalid hop limit(%d) "
- "received from %s on %s",
- *hlimp,
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
- if (icp->icmp6_code) {
- log_info("RA with invalid ICMP6 code(%d) "
- "received 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 (len < sizeof(struct nd_router_advert)) {
- log_info("RA from %s on %s too short (len = %zd)",
- inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf), len);
- return;
- }
- ra_input(len, (struct nd_router_advert *)icp, pi, &from);
- break;
- default:
- /*
- * Note that this case is POSSIBLE, especially just
- * after invocation of the daemon. This is because we
- * could receive message after opening the socket and
- * before setting ICMP6 type filter(see sock_open()).
- */
- log_warnx("invalid icmp type(%d)", icp->icmp6_type);
- }
-}
-
-static void
-rs_input(int len, struct nd_router_solicit *rs,
- struct in6_pktinfo *pi, struct sockaddr_in6 *from)
-{
- u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
- union nd_opts ndopts;
- struct rainfo *ra;
-
- log_debug("RS received from %s on %s",
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
-
- /* ND option check */
- memset(&ndopts, 0, sizeof(ndopts));
- SLIST_INIT(&ndopts.nd_opts_list);
- if (nd6_options((struct nd_opt_hdr *)(rs + 1),
- len - sizeof(struct nd_router_solicit),
- &ndopts, NDOPT_FLAG_SRCLINKADDR)) {
- log_debug("ND option check failed for an RS from %s on %s",
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
-
- /*
- * If the IP source address is the unspecified address, there
- * must be no source link-layer address option in the message.
- * (RFC-2461 6.1.1)
- */
- if (IN6_IS_ADDR_UNSPECIFIED(&from->sin6_addr) &&
- ndopts.nd_opts_src_lladdr) {
- log_warnx("RS from unspecified src on %s has a link-layer"
- " address option",
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- goto done;
- }
-
- SLIST_FOREACH(ra, &ralist, entry) {
- if (pi->ipi6_ifindex == ra->ifindex)
- break;
- }
- if (ra == NULL) {
- log_info("RS received on non advertising interface(%s)",
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- goto done;
- }
-
- ra->rsinput++; /* increment statistics */
-
- if (ndopts.nd_opts_src_lladdr)
- ra_output(ra, from);
- else {
- /*
- * Decide whether to send RA according to the rate-limit
- * consideration.
- */
- long delay; /* must not be greater than 1000000 */
- struct timeval interval, now, min_delay, tm_tmp, next,
- computed;
-
- /*
- * If there is already a waiting RS packet, don't
- * update the timer.
- */
- if (ra->waiting++)
- goto done;
-
- gettimeofday(&now, NULL);
-
- /*
- * Compute a random delay. If the computed value
- * corresponds to a time later than the time the next
- * multicast RA is scheduled to be sent, ignore the random
- * delay and send the advertisement at the
- * already-scheduled time. RFC-2461 6.2.6
- */
- delay = arc4random_uniform(MAX_RA_DELAY_TIME);
- interval.tv_sec = 0;
- interval.tv_usec = delay;
- /*
- * Could happen if an interface has transitioned from DOWN to
- * UP and we haven't re-enabled the timer yet.
- */
- if (!evtimer_pending(&ra->timer.ev, &next))
- goto done;
- timeradd(&now, &interval, &computed);
- if (timercmp(&computed, &next, >)) {
- log_debug("random delay is larger than "
- "the rest of normal timer");
- goto done;
- }
-
- /*
- * If we sent a multicast Router Advertisement within
- * the last MIN_DELAY_BETWEEN_RAS seconds, schedule
- * the advertisement to be sent at a time corresponding to
- * MIN_DELAY_BETWEEN_RAS plus the random value after the
- * previous advertisement was sent.
- */
- min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS;
- min_delay.tv_usec = 0;
- timeradd(&ra->lastsent, &min_delay, &tm_tmp);
- if (timercmp(&computed, &tm_tmp, <))
- computed = tm_tmp;
- timersub(&computed, &now, &computed);
- evtimer_add(&ra->timer.ev, &computed);
- }
-
- done:
- free_ndopts(&ndopts);
-}
-
-static void
-ra_input(int len, struct nd_router_advert *ra,
- struct in6_pktinfo *pi, struct sockaddr_in6 *from)
-{
- struct rainfo *rai;
- u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
- union nd_opts ndopts;
- char *on_off[] = {"OFF", "ON"};
- u_int32_t reachabletime, retranstimer, mtu;
- int inconsistent = 0;
-
- log_debug("RA received from %s on %s",
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
-
- /* ND option check */
- memset(&ndopts, 0, sizeof(ndopts));
- SLIST_INIT(&ndopts.nd_opts_list);
- if (nd6_options((struct nd_opt_hdr *)(ra + 1),
- len - sizeof(struct nd_router_advert),
- &ndopts, NDOPT_FLAG_SRCLINKADDR | NDOPT_FLAG_PREFIXINFO
- | NDOPT_FLAG_MTU | NDOPT_FLAG_ROUTE_INFO
- | NDOPT_FLAG_RDNSS | NDOPT_FLAG_DNSSL)) {
- log_warnx("ND option check failed for an RA from %s on %s",
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, ifnamebuf));
- return;
- }
-
- /*
- * RA consistency check according to RFC-2461 6.2.7
- */
- if ((rai = if_indextorainfo(pi->ipi6_ifindex)) == NULL)
- goto done; /* not our interface */
-
- rai->rainput++; /* increment statistics */
-
- /* Cur Hop Limit value */
- if (ra->nd_ra_curhoplimit && rai->hoplimit &&
- ra->nd_ra_curhoplimit != rai->hoplimit) {
- log_info("CurHopLimit inconsistent on %s: %d from %s,"
- " %d from us",
- rai->ifname,
- ra->nd_ra_curhoplimit,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- rai->hoplimit);
- inconsistent++;
- }
- /* M flag */
- if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) !=
- rai->managedflg) {
- log_info("M flag inconsistent on %s: %s from %s, %s from us",
- rai->ifname, on_off[rai->managedflg ? 0 : 1],
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- on_off[rai->managedflg ? 1 : 0]);
- inconsistent++;
- }
- /* O flag */
- if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) !=
- rai->otherflg) {
- log_info("O flag inconsistent on %s: %s from %s, %s from us",
- rai->ifname, on_off[rai->otherflg ? 0 : 1],
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- on_off[rai->otherflg ? 1 : 0]);
- inconsistent++;
- }
- /* Reachable Time */
- reachabletime = ntohl(ra->nd_ra_reachable);
- if (reachabletime && rai->reachabletime &&
- reachabletime != rai->reachabletime) {
- log_info("ReachableTime inconsistent on %s:"
- " %d from %s, %d from us",
- rai->ifname, reachabletime,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- rai->reachabletime);
- inconsistent++;
- }
- /* Retrans Timer */
- retranstimer = ntohl(ra->nd_ra_retransmit);
- if (retranstimer && rai->retranstimer &&
- retranstimer != rai->retranstimer) {
- log_info("RetransTimer inconsistent on %s:"
- " %d from %s, %d from us",
- rai->ifname, retranstimer,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- rai->retranstimer);
- inconsistent++;
- }
- /* Values in the MTU options */
- if (ndopts.nd_opts_mtu) {
- mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
- if (mtu && rai->linkmtu && mtu != rai->linkmtu) {
- log_info("MTU option value inconsistent on %s:"
- " %d from %s, %d from us",
- rai->ifname, mtu,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- rai->linkmtu);
- inconsistent++;
- }
- }
- /* Preferred and Valid Lifetimes for prefixes */
- {
- struct nd_opt *optp;
-
- if (ndopts.nd_opts_pi)
- if (prefix_check(ndopts.nd_opts_pi, rai, from))
- inconsistent++;
- SLIST_FOREACH(optp, &ndopts.nd_opts_list, entry) {
- if (prefix_check((struct nd_opt_prefix_info *)optp->opt,
- rai, from))
- inconsistent++;
- }
- }
-
- if (inconsistent)
- rai->rainconsistent++;
-
- done:
- free_ndopts(&ndopts);
-}
-
-/* return a non-zero value if the received prefix is inconsistent with ours */
-static int
-prefix_check(struct nd_opt_prefix_info *pinfo,
- struct rainfo *rai, struct sockaddr_in6 *from)
-{
- time_t preferred_time, valid_time;
- struct prefix *pp;
- int inconsistent = 0;
- u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
- struct timeval now;
-
- /*
- * log if the advertised prefix has link-local scope(sanity check?)
- */
- if (IN6_IS_ADDR_LINKLOCAL(&pinfo->nd_opt_pi_prefix))
- log_info("link-local prefix %s/%d is advertised "
- "from %s on %s",
- inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- prefixbuf, INET6_ADDRSTRLEN),
- pinfo->nd_opt_pi_prefix_len,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- rai->ifname);
-
- if ((pp = find_prefix(rai, &pinfo->nd_opt_pi_prefix,
- pinfo->nd_opt_pi_prefix_len)) == NULL) {
- log_info("prefix %s/%d from %s on %s is not in our list",
- inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- prefixbuf, INET6_ADDRSTRLEN),
- pinfo->nd_opt_pi_prefix_len,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- rai->ifname);
- return(0);
- }
-
- preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time);
- if (pp->pltimeexpire) {
- /*
- * The lifetime is decremented in real time, so we should
- * compare the expiration time.
- * (RFC 2461 Section 6.2.7.)
- * XXX: can we really expect that all routers on the link
- * have synchronized clocks?
- */
- gettimeofday(&now, NULL);
- preferred_time += now.tv_sec;
-
- if (rai->clockskew &&
- llabs(preferred_time - pp->pltimeexpire) > rai->clockskew) {
- log_info("preferred lifetime for %s/%d"
- " (decr. in real time) inconsistent on %s:"
- " %lld from %s, %lld from us",
- inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- prefixbuf, INET6_ADDRSTRLEN),
- pinfo->nd_opt_pi_prefix_len,
- rai->ifname, (long long)preferred_time,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- (long long)pp->pltimeexpire);
- inconsistent++;
- }
- } else if (preferred_time != pp->preflifetime)
- log_info("preferred lifetime for %s/%d"
- " inconsistent on %s:"
- " %lld from %s, %d from us",
- inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- prefixbuf, INET6_ADDRSTRLEN),
- pinfo->nd_opt_pi_prefix_len,
- rai->ifname, (long long)preferred_time,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- pp->preflifetime);
-
- valid_time = ntohl(pinfo->nd_opt_pi_valid_time);
- if (pp->vltimeexpire) {
- gettimeofday(&now, NULL);
- valid_time += now.tv_sec;
-
- if (rai->clockskew &&
- llabs(valid_time - pp->vltimeexpire) > rai->clockskew) {
- log_info("valid lifetime for %s/%d"
- " (decr. in real time) inconsistent on %s:"
- " %lld from %s, %lld from us",
- inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- prefixbuf, INET6_ADDRSTRLEN),
- pinfo->nd_opt_pi_prefix_len,
- rai->ifname, (long long)preferred_time,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- (long long)pp->vltimeexpire);
- inconsistent++;
- }
- } else if (valid_time != pp->validlifetime) {
- log_info("valid lifetime for %s/%d"
- " inconsistent on %s:"
- " %lld from %s, %d from us",
- inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- prefixbuf, INET6_ADDRSTRLEN),
- pinfo->nd_opt_pi_prefix_len,
- rai->ifname, (long long)valid_time,
- inet_ntop(AF_INET6, &from->sin6_addr,
- ntopbuf, INET6_ADDRSTRLEN),
- pp->validlifetime);
- inconsistent++;
- }
-
- return(inconsistent);
-}
-
-struct prefix *
-find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen)
-{
- struct prefix *pp;
- int bytelen, bitlen;
- u_char bitmask;
-
- TAILQ_FOREACH(pp, &rai->prefixes, entry) {
- if (plen != pp->prefixlen)
- continue;
- bytelen = plen / 8;
- bitlen = plen % 8;
- bitmask = 0xff << (8 - bitlen);
- if (memcmp(prefix, &pp->prefix, bytelen))
- continue;
- if (bitlen == 0 ||
- ((prefix->s6_addr[bytelen] & bitmask) ==
- (pp->prefix.s6_addr[bytelen] & bitmask))) {
- return(pp);
- }
- }
-
- return(NULL);
-}
-
-static int
-nd6_options(struct nd_opt_hdr *hdr, int limit,
- union nd_opts *ndopts, u_int32_t optflags)
-{
- int optlen = 0;
-
- for (; limit > 0; limit -= optlen) {
- if (limit < sizeof(struct nd_opt_hdr)) {
- log_info("short option header");
- goto bad;
- }
-
- hdr = (struct nd_opt_hdr *)((char *)hdr + optlen);
- if (hdr->nd_opt_len == 0) {
- log_warnx("bad ND option length(0) (type = %d)",
- hdr->nd_opt_type);
- goto bad;
- }
- optlen = hdr->nd_opt_len << 3;
- if (optlen > limit) {
- log_info("short option");
- goto bad;
- }
-
- if (hdr->nd_opt_type > ND_OPT_MTU &&
- hdr->nd_opt_type != ND_OPT_ROUTE_INFO &&
- hdr->nd_opt_type != ND_OPT_RDNSS &&
- hdr->nd_opt_type != ND_OPT_DNSSL)
- {
- log_info("unknown ND option(type %d)",
- hdr->nd_opt_type);
- continue;
- }
-
- if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) {
- log_info("unexpected ND option(type %d)",
- hdr->nd_opt_type);
- continue;
- }
-
- /*
- * Option length check. Do it here for all fixed-length
- * options.
- */
- if ((hdr->nd_opt_type == ND_OPT_RDNSS && (optlen < 24 ||
- ((optlen - sizeof(struct nd_opt_rdnss)) % 16 != 0))) ||
- (hdr->nd_opt_type == ND_OPT_DNSSL && optlen < 16) ||
- (hdr->nd_opt_type == ND_OPT_MTU &&
- (optlen != sizeof(struct nd_opt_mtu))) ||
- ((hdr->nd_opt_type == ND_OPT_PREFIX_INFORMATION &&
- optlen != sizeof(struct nd_opt_prefix_info)))) {
- log_info("invalid option length");
- continue;
- }
-
- switch (hdr->nd_opt_type) {
- case ND_OPT_SOURCE_LINKADDR:
- ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
- break;
- case ND_OPT_TARGET_LINKADDR:
- case ND_OPT_REDIRECTED_HEADER:
- case ND_OPT_ROUTE_INFO:
- case ND_OPT_RDNSS:
- case ND_OPT_DNSSL:
- break; /* we don't care about these options */
- case ND_OPT_MTU:
- if (ndopts->nd_opt_array[hdr->nd_opt_type]) {
- log_info("duplicated ND option (type = %d)",
- hdr->nd_opt_type);
- }
- ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
- break;
- case ND_OPT_PREFIX_INFORMATION:
- {
- struct nd_opt *pfx;
-
- if (ndopts->nd_opts_pi == 0) {
- ndopts->nd_opts_pi =
- (struct nd_opt_prefix_info *)hdr;
- continue;
- }
- if ((pfx = malloc(sizeof(*pfx))) == NULL) {
- log_warn(NULL);
- goto bad;
- }
-
- pfx->opt = hdr;
- SLIST_INSERT_HEAD(&ndopts->nd_opts_list, pfx, entry);
-
- break;
- }
- default: /* impossible */
- break;
- }
- }
-
- return(0);
-
- bad:
- free_ndopts(ndopts);
-
- return(-1);
-}
-
-static void
-free_ndopts(union nd_opts *ndopts)
-{
- struct nd_opt *opt;
-
- while (!SLIST_EMPTY(&ndopts->nd_opts_list)) {
- opt = SLIST_FIRST(&ndopts->nd_opts_list);
- SLIST_REMOVE_HEAD(&ndopts->nd_opts_list, entry);
- free(opt);
- }
-}
-
-static void
-sock_open(void)
-{
- struct rainfo *ra;
- struct icmp6_filter filt;
- struct ipv6_mreq mreq;
- int on;
- /* XXX: should be max MTU attached to the node */
- static u_char answer[1500];
-
- rcvcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
- CMSG_SPACE(sizeof(int));
- rcvcmsgbuf = malloc(rcvcmsgbuflen);
- if (rcvcmsgbuf == NULL)
- fatal(NULL);
-
- sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
- CMSG_SPACE(sizeof(int));
- sndcmsgbuf = malloc(sndcmsgbuflen);
- if (sndcmsgbuf == NULL)
- fatal(NULL);
-
- if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
- fatal("socket");
-
- /* specify to tell receiving interface */
- on = 1;
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on))
- < 0)
- fatal("IPV6_RECVPKTINFO");
-
- on = 1;
- /* specify to tell value of hoplimit field of received IP6 hdr */
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on))
- < 0)
- fatal("IPV6_RECVHOPLIMIT");
-
- ICMP6_FILTER_SETBLOCKALL(&filt);
- ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
- ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
- if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt))
- < 0)
- fatal("ICMP6_FILTER");
-
- /*
- * join all routers multicast address on each advertising interface.
- */
- if (inet_pton(AF_INET6, ALLROUTERS_LINK, &mreq.ipv6mr_multiaddr.s6_addr)
- != 1)
- fatal("inet_pton");
- SLIST_FOREACH(ra, &ralist, entry) {
- mreq.ipv6mr_interface = ra->ifindex;
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
- sizeof(mreq)) < 0)
- fatal("IPV6_JOIN_GROUP(link) on %s", ra->ifname);
- }
-
- /* initialize msghdr for receiving packets */
- rcviov[0].iov_base = answer;
- rcviov[0].iov_len = sizeof(answer);
- rcvmhdr.msg_name = &from;
- rcvmhdr.msg_namelen = sizeof(from);
- rcvmhdr.msg_iov = rcviov;
- rcvmhdr.msg_iovlen = 1;
- rcvmhdr.msg_control = rcvcmsgbuf;
- rcvmhdr.msg_controllen = rcvcmsgbuflen;
-
- /* initialize msghdr for sending packets */
- sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
- sndmhdr.msg_iov = sndiov;
- sndmhdr.msg_iovlen = 1;
- sndmhdr.msg_control = sndcmsgbuf;
- sndmhdr.msg_controllen = sndcmsgbuflen;
-}
-
-/* open a routing socket to watch the routing table */
-static void
-rtsock_open(void)
-{
- unsigned int rtfilter;
-
- if ((rtsock = socket(PF_ROUTE, SOCK_RAW, AF_INET6)) < 0)
- fatal("socket");
-
- rtfilter =
- ROUTE_FILTER(RTM_ADD) |
- ROUTE_FILTER(RTM_DELETE) |
- ROUTE_FILTER(RTM_NEWADDR) |
- ROUTE_FILTER(RTM_DELADDR) |
- ROUTE_FILTER(RTM_IFINFO);
-
- if (setsockopt(rtsock, PF_ROUTE, ROUTE_MSGFILTER,
- &rtfilter, sizeof(rtfilter)) == -1)
- fatal("setsockopt(ROUTE_MSGFILTER)");
-
- rtsockbuflen = 2048;
- rtsockbuf = malloc(rtsockbuflen);
- if (rtsockbuf == NULL)
- fatal(NULL);
-}
-
-static struct rainfo *
-if_indextorainfo(int index)
-{
- struct rainfo *rai;
-
- SLIST_FOREACH(rai, &ralist, entry) {
- if (rai->ifindex == index)
- return(rai);
- }
-
- return(NULL); /* search failed */
-}
-
-static void
-ra_output(struct rainfo *rainfo, struct sockaddr_in6 *to)
-{
- struct cmsghdr *cm;
- struct in6_pktinfo *pi;
- ssize_t len;
-
- if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) {
- log_debug("%s is not up, skip sending RA", rainfo->ifname);
- return;
- }
-
- make_packet(rainfo); /* XXX: inefficient */
-
- sndmhdr.msg_name = to;
- sndmhdr.msg_iov[0].iov_base = rainfo->ra_data;
- sndmhdr.msg_iov[0].iov_len = rainfo->ra_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 = rainfo->ifindex;
-
- /* specify the hop limit of the packet */
- {
- int hoplimit = 255;
-
- 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));
- }
-
- log_debug("send RA on %s, # of waitings = %u",
- rainfo->ifname, rainfo->waiting);
-
- len = sendmsg(sock, &sndmhdr, 0);
- if (len < 0) {
- log_warn("sendmsg on %s", rainfo->ifname);
- return;
- }
-
- rainfo->raoutput++;
-
- if (memcmp(to, &sin6_allnodes, sizeof(sin6_allnodes)) == 0) {
- /* update counter */
- if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS)
- rainfo->initcounter++;
- /* update timestamp */
- gettimeofday(&rainfo->lastsent, NULL);
-
- /* reset waiting counter */
- rainfo->waiting = 0;
- }
-}
-
-/* process RA timer */
-void
-timer_cb(int fd, short event, void *data)
-{
- struct rainfo *rai = (struct rainfo *)data;
-
- log_debug("RA timer on %s is expired", rai->ifname);
-
- ra_output(rai, &sin6_allnodes);
-
- ra_timer_update(rai);
- evtimer_add(&rai->timer.ev, &rai->timer.tm);
-}
-
-/* update RA timer */
-void
-ra_timer_update(struct rainfo *rai)
-{
- struct timeval *tm = &rai->timer.tm;
- long interval;
-
- /*
- * Whenever a multicast advertisement is sent from an interface,
- * the timer is reset to a uniformly-distributed random value
- * between the interface's configured MinRtrAdvInterval and
- * MaxRtrAdvInterval (RFC2461 6.2.4).
- */
- interval = rai->mininterval;
- interval += arc4random_uniform(rai->maxinterval - rai->mininterval);
-
- /*
- * For the first few advertisements (up to
- * MAX_INITIAL_RTR_ADVERTISEMENTS), if the randomly chosen interval
- * is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL, the timer
- * SHOULD be set to MAX_INITIAL_RTR_ADVERT_INTERVAL instead.
- * (RFC-2461 6.2.4)
- */
- if (rai->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS &&
- interval > MAX_INITIAL_RTR_ADVERT_INTERVAL)
- interval = MAX_INITIAL_RTR_ADVERT_INTERVAL;
-
- tm->tv_sec = interval;
- tm->tv_usec = 0;
-
- log_debug("RA timer on %s set to %lld.%lds", rai->ifname,
- (long long)tm->tv_sec, tm->tv_usec);
-}
-
-int
-rdaemon(int devnull)
-{
- if (devnull == -1) {
- errno = EBADF;
- return (-1);
- }
- if (fcntl(devnull, F_GETFL) == -1)
- return (-1);
-
- switch (fork()) {
- case -1:
- return (-1);
- case 0:
- break;
- default:
- _exit(0);
- }
-
- if (setsid() == -1)
- return (-1);
-
- (void)dup2(devnull, STDIN_FILENO);
- (void)dup2(devnull, STDOUT_FILENO);
- (void)dup2(devnull, STDERR_FILENO);
- if (devnull > 2)
- (void)close(devnull);
-
- return (0);
-}
+++ /dev/null
-# $OpenBSD: rtadvd.conf,v 1.8 2013/06/01 01:30:54 brad Exp $
-# $KAME: rtadvd.conf,v 1.12 2001/01/21 14:56:38 itojun Exp $
-#
-# Note: All of the following parameters have default values defined
-# in specifications, and hence you usually do not have to set them
-# by hand unless you need special non-default values.
-#
-# You even do not need to create the configuration file. rtadvd
-# would usually work well without a configuration file.
-# See also: rtadvd(8)
-
-# per-interface definitions.
-# Mainly IPv6 prefixes are configured in this part. However, rtadvd
-# automatically learns appropriate prefixes from the kernel's routing
-# table, and advertises the prefixes, so you don't have to configure
-# this part, either.
-# If you don't want the automatic advertisement, (uncomment and) configure
-# this part by hand, and then invoke rtadvd with the -s option.
-
-#ef0:\
-# :addr="2001:db8:ffff:1000::":prefixlen#64:\
-# :rtprefix="2001:db8:ffff:1001::":\
-# :rdnss="2001:db8:ffff:1000::1":dnssl="example.com":
+++ /dev/null
-.\" $OpenBSD: rtadvd.conf.5,v 1.40 2018/06/13 14:18:26 florian Exp $
-.\" $KAME: rtadvd.conf.5,v 1.46 2003/06/17 08:26:35 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: June 13 2018 $
-.Dt RTADVD.CONF 5
-.Os
-.Sh NAME
-.Nm rtadvd.conf
-.Nd config file for router advertisement daemon
-.Sh DESCRIPTION
-This file describes how the router advertisement packets must be constructed
-for each of the interfaces.
-.Pp
-As described in
-.Xr rtadvd 8 ,
-you do not have to set this configuration file up at all,
-unless you need some special configurations.
-You may even omit the file as a whole.
-In such cases, the
-.Nm rtadvd
-daemon will automatically configure itself using default values
-specified in the specification.
-.Pp
-It obeys the infamous
-.Xr termcap 5
-file format.
-Each line in the file describes a network interface.
-Fields are separated by a colon
-.Pq Sq \&: ,
-and each field contains one capability description.
-Lines may be concatenated by the
-.Sq \e
-character.
-The comment marker is the
-.Sq \&#
-character.
-.Sh CAPABILITIES
-Capabilities describe the value to be filled into ICMPv6 router
-advertisement messages and to control
-.Xr rtadvd 8
-behavior.
-Therefore, you are encouraged to read IETF neighbor discovery documents
-if you would like to modify the sample configuration file.
-.Pp
-Note that almost all items have default values.
-If you omit an item, the default value of the item will be used.
-.Pp
-There are two items which control the interval of sending router advertisements.
-These items can be omitted, then
-.Nm rtadvd
-will use the default values.
-.Bl -tag -width indent
-.It Cm \&maxinterval
-(num) The maximum time allowed between sending unsolicited
-multicast router advertisements
-.Pq unit: seconds .
-The default value is 600.
-Its value must be no less than 4 seconds
-and no greater than 1800 seconds.
-.It Cm \&mininterval
-(num) The minimum time allowed between sending unsolicited multicast
-router advertisements
-.Pq unit: seconds .
-The default value is one third of the value of
-.Cm maxinterval .
-Its value must be no less than 3 seconds and no greater than .75 *
-the value of
-.Cm maxinterval .
-.El
-.Pp
-The following items are for ICMPv6 router advertisement message
-header.
-These items can be omitted, then
-.Nm rtadvd
-will use the default values.
-.Bl -tag -width indent
-.It Cm \&chlim
-(num) The value for Cur Hop Limit field.
-The default value is 64.
-.It Cm \&raflags
-(num) Flags field in router advertisement message header.
-Bit 7
-.Pq 0x80
-means Managed address configuration flag bit,
-and Bit 6
-.Pq 0x40
-means Other stateful configuration flag bit.
-Bit 4
-.Pq 0x10
-and
-Bit 3
-.Pq 0x08
-are used to encode the route preference for the route as follows:
-.Pp
-.Bl -tag -width "0x08XXX" -offset indent -compact
-.It 0x08
-High
-.It 0x00
-Medium (the default)
-.It 0x18
-Low
-.El
-.Pp
-The default value is 0.
-.It Cm \&rltime
-(num) Router lifetime field
-.Pq unit: seconds .
-Its value must be no greater than 9000.
-When
-.Nm rtadvd
-runs on a host, this value must explicitly set 0 on all the
-advertising interfaces as described in
-.Xr rtadvd 8 .
-The default value is 1800.
-.It Cm \&rtime
-(num) Reachable time field
-.Pq unit: milliseconds .
-The default value is 0, which means unspecified by this router.
-.It Cm \&retrans
-(num) Retrans Timer field
-.Pq unit: milliseconds .
-The default value is 0, which means unspecified by this router.
-.El
-.Pp
-The following items are for ICMPv6 prefix information option,
-which will be attached to router advertisement header.
-These items can be omitted, then
-.Nm rtadvd
-will automatically get appropriate prefixes from the kernel's routing table,
-and advertise the prefixes with the default parameters, unless the
-.Cm noifprefix
-flag is specified.
-Keywords other than
-.Cm clockskew
-can be augmented with a number, like
-.Dq Li prefix2 ,
-to specify multiple prefixes.
-.Bl -tag -width indent
-.It Cm \&clockskew
-(num) Time skew to adjust link propagation delays and clock skews
-between routers on the link
-.Pq unit: seconds .
-This value is used in consistency check for locally-configured and
-advertised prefix lifetimes, and has its meaning when the local router
-configures a prefix on the link with a lifetime that decrements in
-real time.
-If the value is 0, it means the consistency check will be skipped
-for such prefixes.
-The default value is 0.
-.It Cm \&prefixlen
-(num) Prefix length field.
-The default value is 64.
-.It Cm \&pinfoflags
-(num) Flags field in prefix information option.
-Bit 7
-.Pq 0x80
-means On-link flag bit,
-and Bit 6
-.Pq 0x40
-means Autonomous address-configuration flag bit.
-The default value is 0xc0, i.e., both bits are set.
-.It Cm \&addr
-(str) The address filled into Prefix field.
-Since
-.Dq \&:
-is used for the
-.Xr termcap 5
-file format as well as IPv6 numeric addresses, the field MUST be quoted
-using double quotes.
-.It Cm \&noifprefix
-(bool) Specifies whether
-.Nm rtadvd
-should gather prefix information from the interface if no
-.Cm addr
-is specified.
-If no
-.Cm addr
-is given, and
-.Cm noifprefix
-is set,
-.Nm rtadvd
-will send RA packets with no prefix information.
-.It Cm \&vltime
-(num) Valid lifetime field
-.Pq unit: seconds .
-The default value is 2592000 (30 days).
-.It Cm \&vltimedecr
-(bool) This item means the advertised valid lifetime will decrement
-in real time, which is disabled by default.
-.It Cm \&pltime
-(num) Preferred lifetime field
-.Pq unit: seconds .
-The default value is 604800 (7 days).
-.It Cm \&pltimedecr
-(bool) This item means the advertised preferred lifetime will decrement
-in real time, which is disabled by default.
-.El
-.Pp
-The following item is for ICMPv6 MTU option,
-which will be attached to router advertisement header.
-This item can be omitted, then
-.Nm rtadvd
-will use the default value.
-.Bl -tag -width indent
-.It Cm \&mtu
-(num or str) MTU (maximum transmission unit) field.
-If 0 is specified, it means that the option will not be included.
-The default value is 0.
-If the special string
-.Dq auto
-is specified for this item, MTU option will be included and its value
-will be set to the interface MTU automatically.
-.El
-.Pp
-The following items are for ICMPv6 route information option,
-which will be attached to router advertisement header.
-These items are optional.
-Each item can be augmented with a number, like
-.Dq Li rtplen2 ,
-to specify multiple routes.
-.Bl -tag -width indent
-.It Cm \&rtprefix
-(str) The prefix filled into the Prefix field of route information option.
-Since
-.Dq \&:
-is used for
-.Xr termcap 5
-file format as well as IPv6 numeric address, the field MUST be quoted by
-doublequote character.
-.It Cm \&rtplen
-(num) Prefix length field in route information option.
-The default value is 64.
-.It Cm \&rtflags
-(str or num) A 8-bit flags field in route information option.
-Currently only the preference values are defined.
-The notation for those is the same as that of the raflags field.
-.It Cm \&rtltime
-(num) route lifetime field in route information option.
-.Pq unit: seconds .
-The default value is same as router lifetime.
-.El
-.Pp
-The following items are for ICMPv6 RDNSS option, used to give a list of
-recursive DNS servers to hosts.
-If this item is omitted, no information about DNS servers will be advertised.
-.Bl -tag -width indent
-.It Cm \&rdnss
-(str) The list of advertised recursive DNS servers, separated by commas.
-.It Cm \&rdnssltime
-(num) Validity of the list of DNS servers
-.Pq unit: seconds .
-The default value is 1.5 * the value of maxinterval.
-.El
-.Pp
-The following items are used for ICMPv6 DNSSL option which specifies a
-list of DNS suffixes advertised to hosts.
-If this option is not specified, no DNS suffix will be sent to hosts.
-.Bl -tag -width indent
-.It Cm \&dnssl
-(str) The list of advertised DNS suffixes, separated by commas.
-.It Cm \&dnsslltime
-(num) Validity of the list of DNS suffixes
-.Pq unit: seconds .
-The default value is 1.5 * the value of maxinterval.
-.El
-.Pp
-The following item controls ICMPv6 source link-layer address option,
-which will be attached to router advertisement header.
-As noted above, you can just omit the item, then
-.Nm rtadvd
-will use the default value.
-.Bl -tag -width indent
-.It Cm \&nolladdr
-(bool) By default
-.Po
-if
-.Cm \&nolladdr
-is not specified
-.Pc ,
-.Xr rtadvd 8
-will try to get link-layer address for the interface from the kernel,
-and attach that in source link-layer address option.
-If this capability exists,
-.Xr rtadvd 8
-will not attach source link-layer address option to
-router advertisement packets.
-.El
-.Pp
-You can also refer one line from another by using
-.Cm tc
-capability.
-See
-.Xr termcap 5
-for details on the capability.
-.Sh EXAMPLES
-As presented above, all of the advertised parameters have default values
-defined in specifications, and hence you usually do not have to set them
-by hand, unless you need special non-default values.
-It can cause interoperability problem if you use an ill-configured
-parameter.
-.Pp
-To override a configuration parameter, you can specify the parameter alone.
-With the following configuration,
-.Xr rtadvd 8
-overrides the router lifetime parameter for the
-.Li ne0
-interface.
-.Bd -literal -offset indent
-ne0:\e
- :rltime#0:
-.Ed
-.Pp
-The following example manually configures prefixes advertised from the
-.Li ef0
-interface.
-The configuration must be used with the
-.Fl s
-option to
-.Xr rtadvd 8 .
-.Bd -literal -offset indent
-ef0:\e
- :addr="2001:db8:ffff:1000::":prefixlen#64:
-.Ed
-.Pp
-The following example configures two recursive DNS servers for the
-.Li em0
-interface and sets the DNS search suffix to
-.Do
-example.com
-.Dc .
-.Bd -literal -offset indent
-em0:\e
- :rdnss="2001:db8:ffff:1000::1,2001:db8:ffff:1000::2":\e
- :dnssl="example.com":
-.Ed
-.Pp
-The following example presents the default values in an explicit manner.
-The configuration is provided just for reference purposes;
-YOU DO NOT NEED TO HAVE IT AT ALL.
-.Bd -literal -offset indent
-default:\e
- :chlim#64:raflags#0:rltime#1800:rtime#0:retrans#0:\e
- :pinfoflags#192:vltime#2592000:pltime#604800:mtu#0:
-ef0:\e
- :addr="2001:db8:ffff:1000::":prefixlen#64:tc=default:
-.Ed
-.Sh SEE ALSO
-.Xr termcap 5 ,
-.Xr rtadvd 8
-.Sh STANDARDS
-.Rs
-.%A R. Draves
-.%A D. Thaler
-.%D 2005
-.%R RFC 4191
-.%T Default Router Preferences and More-Specific Routes
-.Re
-.Pp
-.Rs
-.%A T. Narten
-.%A E. Nordmark
-.%A W. Simpson
-.%A H. Soliman
-.%D 2007
-.%R RFC 4861
-.%T Neighbor Discovery for IP version 6 (IPv6)
-.Re
-.Pp
-.Rs
-.%A J. Jeong
-.%A S. Park
-.%A L. Beloeil
-.%A S. Madanapalli
-.%D 2017
-.%R RFC 8106
-.%T IPv6 Router Advertisement Options for DNS Configuration
-.Re
-.Sh HISTORY
-The
-.Xr rtadvd 8
-and the configuration file
-.Nm
-first appeared in WIDE Hydrangea IPv6 protocol stack kit.
-.\" .Sh BUGS
-.\" (to be written)
+++ /dev/null
-/* $OpenBSD: rtadvd.h,v 1.29 2016/09/25 13:54:39 florian Exp $ */
-/* $KAME: rtadvd.h,v 1.20 2002/05/29 10:13:10 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.
- */
-
-#define RTADVD_USER "_rtadvd"
-
-#define ALLNODES "ff02::1"
-#define ALLROUTERS_LINK "ff02::2"
-
-/* protocol constants and default values */
-#define DEF_MAXRTRADVINTERVAL 600
-#define DEF_ADVLINKMTU 0
-#define DEF_ADVREACHABLETIME 0
-#define DEF_ADVRETRANSTIMER 0
-#define DEF_ADVCURHOPLIMIT 64
-#define DEF_ADVVALIDLIFETIME 2592000
-#define DEF_ADVPREFERREDLIFETIME 604800
-
-#define MAX_ROUTERLIFETIME 9000
-#define MIN_MAXINTERVAL 4
-#define MAX_MAXINTERVAL 1800
-#define MIN_MININTERVAL 3
-#define MAX_REACHABLETIME 3600000
-
-#define MAX_INITIAL_RTR_ADVERT_INTERVAL 16
-#define MAX_INITIAL_RTR_ADVERTISEMENTS 3
-#define MAX_FINAL_RTR_ADVERTISEMENTS 3
-#define MIN_DELAY_BETWEEN_RAS 3
-#define MAX_RA_DELAY_TIME 500000 /* usec */
-
-#define PREFIX_FROM_KERNEL 1
-#define PREFIX_FROM_CONFIG 2
-#define PREFIX_FROM_DYNAMIC 3
-
-struct rtadvd_timer {
- struct event ev;
- struct timeval tm;
-};
-
-struct prefix {
- TAILQ_ENTRY(prefix) entry;
-
- u_int32_t validlifetime; /* AdvValidLifetime */
- time_t vltimeexpire; /* expiration of vltime; decrement case only */
- u_int32_t preflifetime; /* AdvPreferredLifetime */
- time_t pltimeexpire; /* expiration of pltime; decrement case only */
- u_int onlinkflg; /* bool: AdvOnLinkFlag */
- u_int autoconfflg; /* bool: AdvAutonomousFlag */
- int prefixlen;
- int origin; /* from kernel or config */
- struct in6_addr prefix;
-};
-
-struct rtinfo {
- TAILQ_ENTRY(rtinfo) entry;
-
- uint32_t lifetime;
- int rtpref;
- int prefixlen;
- struct in6_addr prefix;
-};
-
-/*
- * `struct rdnss` may contain an arbitrary number of `servers` and `struct
- * dnssldom` will contain a variable-sized `domain`. Space required for these
- * elements will be dynamically allocated. We do not use flexible array members
- * here because this breaks compile on some architectures using gcc2. Instead,
- * we just have an array with a single (unused) element.
- */
-
-struct rdnss {
- TAILQ_ENTRY(rdnss) entry;
-
- u_int32_t lifetime;
- int servercnt;
- struct in6_addr servers[1];
-};
-
-struct dnssldom {
- TAILQ_ENTRY(dnssldom) entry;
-
- u_int32_t length;
- char domain[1];
-};
-
-struct dnssl {
- TAILQ_ENTRY(dnssl) entry;
-
- u_int32_t lifetime;
- TAILQ_HEAD(dnssldomlist, dnssldom) dnssldoms;
-};
-
-struct rainfo {
- /* pointer for list */
- SLIST_ENTRY(rainfo) entry;
-
- /* timer related parameters */
- struct rtadvd_timer timer;
- unsigned int initcounter; /* counter for the first few advertisements */
- struct timeval lastsent; /* timestamp when the latest RA was sent */
- unsigned int waiting; /* number of RS waiting for RA */
-
- /* interface information */
- int ifindex;
- int advlinkopt; /* bool: whether include link-layer addr opt */
- struct sockaddr_dl *sdl;
- char ifname[IF_NAMESIZE];
- int phymtu; /* mtu of the physical interface */
-
- /* Router configuration variables */
- u_short lifetime; /* AdvDefaultLifetime */
- u_int maxinterval; /* MaxRtrAdvInterval */
- u_int mininterval; /* MinRtrAdvInterval */
- int managedflg; /* AdvManagedFlag */
- int otherflg; /* AdvOtherConfigFlag */
- int rtpref; /* router preference */
- u_int32_t linkmtu; /* AdvLinkMTU */
- u_int32_t reachabletime; /* AdvReachableTime */
- u_int32_t retranstimer; /* AdvRetransTimer */
- u_int hoplimit; /* AdvCurHopLimit */
- TAILQ_HEAD(prefixlist, prefix) prefixes; /* AdvPrefixList(link head) */
- int pfxs; /* number of prefixes */
- TAILQ_HEAD(rtinfolist, rtinfo) rtinfos;
- TAILQ_HEAD(rdnsslist, rdnss) rdnsss; /* advertised recursive dns servers */
- TAILQ_HEAD(dnssllist, dnssl) dnssls;
- long clockskew; /* used for consistency check of lifetimes */
-
-
- /* actual RA packet data and its length */
- size_t ra_datalen;
- u_char *ra_data;
-
- /* statistics */
- uint64_t raoutput; /* number of RAs sent */
- uint64_t rainput; /* number of RAs received */
- uint64_t rainconsistent; /* number of RAs inconsistent with ours */
- uint64_t rsinput; /* number of RSs received */
-};
-SLIST_HEAD(ralist, rainfo);
-
-void ra_timer_update(struct rainfo *);
-
-struct prefix *find_prefix(struct rainfo *, struct in6_addr *, int);