svn commit: r231802 - in stable/8/usr.sbin: . rtadvctl rtadvd

Hiroki Sato hrs at FreeBSD.org
Thu Feb 16 01:32:24 UTC 2012


Author: hrs
Date: Thu Feb 16 01:32:23 2012
New Revision: 231802
URL: http://svn.freebsd.org/changeset/base/231802

Log:
  MFC r222732,222771,222820,222824,222972,223752,224006,224144,224148,225519,22568
  3,228990:
  
  - Implement RDNSS and DNSSL options (RFC 6106, IPv6 Router Advertisement
    Options for DNS Configuration).
  
  - rtadvd(8) now supports "noifprefix" to disable gathering on-link prefixes
    from interfaces when no "addr" is specified[2].  An entry in rtadvd.conf
    with "noifprefix" + no "addr" generates an RA message with no prefix
    information option.
  
  - rtadvd(8) now supports RTM_IFANNOUNCE message to fix crashes when an
    interface is added or removed.
  
  - Implement burst unsolicited RA sending into the internal RA timer framework
    when AdvSendAdvertisements and/or configuration entries are changed as
    described in RFC 4861 6.2.4.  This fixes issues that make termination of the
    rtadvd(8) daemon take very long time.
  
  - rtadvd(8) now accepts non-existent interfaces as well in the command line.
  
  - Add control socket support and rtadvctl(8) utility to show the RA information
    in rtadvd(8).  Dumping by SIGUSR1 has been removed in favor of it.

Added:
  stable/8/usr.sbin/rtadvctl/Makefile   (contents, props changed)
  stable/8/usr.sbin/rtadvctl/rtadvctl.8   (contents, props changed)
  stable/8/usr.sbin/rtadvctl/rtadvctl.c   (contents, props changed)
  stable/8/usr.sbin/rtadvd/control.c
     - copied, changed from r224640, head/usr.sbin/rtadvd/control.c
  stable/8/usr.sbin/rtadvd/control.h
     - copied, changed from r224640, head/usr.sbin/rtadvd/control.h
  stable/8/usr.sbin/rtadvd/control_client.c
     - copied, changed from r224640, head/usr.sbin/rtadvd/control_client.c
  stable/8/usr.sbin/rtadvd/control_client.h
     - copied, changed from r224640, head/usr.sbin/rtadvd/control_client.h
  stable/8/usr.sbin/rtadvd/control_server.c
     - copied, changed from r224640, head/usr.sbin/rtadvd/control_server.c
  stable/8/usr.sbin/rtadvd/control_server.h
     - copied, changed from r224640, head/usr.sbin/rtadvd/control_server.h
  stable/8/usr.sbin/rtadvd/timer_subr.c
     - copied unchanged from r224640, head/usr.sbin/rtadvd/timer_subr.c
  stable/8/usr.sbin/rtadvd/timer_subr.h
     - copied unchanged from r224640, head/usr.sbin/rtadvd/timer_subr.h
Directory Properties:
  stable/8/usr.sbin/rtadvctl/   (props changed)
Deleted:
  stable/8/usr.sbin/rtadvd/dump.c
  stable/8/usr.sbin/rtadvd/dump.h
Modified:
  stable/8/usr.sbin/Makefile
  stable/8/usr.sbin/rtadvd/Makefile
  stable/8/usr.sbin/rtadvd/advcap.c
  stable/8/usr.sbin/rtadvd/config.c
  stable/8/usr.sbin/rtadvd/config.h
  stable/8/usr.sbin/rtadvd/if.c
  stable/8/usr.sbin/rtadvd/if.h
  stable/8/usr.sbin/rtadvd/pathnames.h
  stable/8/usr.sbin/rtadvd/rrenum.c
  stable/8/usr.sbin/rtadvd/rrenum.h
  stable/8/usr.sbin/rtadvd/rtadvd.8
  stable/8/usr.sbin/rtadvd/rtadvd.c
  stable/8/usr.sbin/rtadvd/rtadvd.conf
  stable/8/usr.sbin/rtadvd/rtadvd.conf.5
  stable/8/usr.sbin/rtadvd/rtadvd.h
  stable/8/usr.sbin/rtadvd/timer.c
  stable/8/usr.sbin/rtadvd/timer.h
Directory Properties:
  stable/8/usr.sbin/rtadvd/   (props changed)

Modified: stable/8/usr.sbin/Makefile
==============================================================================
--- stable/8/usr.sbin/Makefile	Thu Feb 16 00:46:11 2012	(r231801)
+++ stable/8/usr.sbin/Makefile	Thu Feb 16 01:32:23 2012	(r231802)
@@ -160,6 +160,7 @@ SUBDIR=	${_ac} \
 	${_rpc.ypupdated} \
 	${_rpc.ypxfrd} \
 	${_rrenumd} \
+	${_rtadvctl} \
 	${_rtadvd} \
 	rtprio \
 	${_rtsold} \
@@ -284,6 +285,7 @@ _ndp=		ndp
 _rip6query=	rip6query
 _route6d=	route6d
 _rrenumd=	rrenumd
+_rtadvctl=	rtadvctl
 _rtadvd=	rtadvd
 _rtsold=	rtsold
 _traceroute6=	traceroute6

Added: stable/8/usr.sbin/rtadvctl/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.sbin/rtadvctl/Makefile	Thu Feb 16 01:32:23 2012	(r231802)
@@ -0,0 +1,13 @@
+# $FreeBSD$
+#
+.PATH:	${.CURDIR}/../rtadvd
+
+PROG=	rtadvctl
+MAN=	rtadvctl.8
+
+SRCS=	rtadvctl.c control.c control_client.c if.c timer_subr.c
+
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../rtadvd
+WARNS?=	1
+
+.include <bsd.prog.mk>

Added: stable/8/usr.sbin/rtadvctl/rtadvctl.8
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.sbin/rtadvctl/rtadvctl.8	Thu Feb 16 01:32:23 2012	(r231802)
@@ -0,0 +1,104 @@
+.\" Copyright (C) 2011 Hiroki Sato <hrs at FreeBSD.org>.
+.\" 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 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 16, 2011
+.Dt RTADVCTL 8
+.Os
+.Sh NAME
+.Nm rtadvctl
+.Nd control program for
+.Xr rtadvd 8 daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl v
+.Ar subcommand
+.Op Ar interface ...
+.Sh DESCRIPTION
+.Nm
+is a utility that communicates with
+.Xr rtadvd 8
+daemon and displays information about Router Advertisement messages being
+sent on each interface.
+.Pp
+This utility provides several options and subcommands.
+The options are as follows:
+.Bl -tag -width indent
+.\"
+.It Fl v
+Increase verbosity level.
+When specified once, the
+.Nm
+utility shows additional information about prefixes, RDNSS, and DNSSL
+options.
+When given twice, it additionally shows information about
+inactive interfaces and some statistics.
+.El
+.Pp
+The subcommands are as follows:
+.Bl -tag -width indent
+.\"
+.It reload Op interfaces...
+Specifies to reload the configuration file.  If one or more
+.Ar interface
+is specified, configuration entries for the interfaces will be reloaded
+selectively.
+.It enable interfaces...
+Specifies to mark the interface as enable and to try to reload the
+configuration entry.
+This subcommand is useful for dynamically-added interfaces.
+.Pp
+The
+.Xr rtadvd 8
+daemon marks an interface as enable if the interface exists and the
+configuration file has a valid entry for that when it is invoked.
+.It disable interfaces...
+Specifies to mark the interface as disable.
+.It shutdown
+Makes the
+.Xr rtadvd 8
+daemon shut down.
+Note that the
+.Xr rtadvd 8
+daemon will send several RAs with zero lifetime to invalidate the old
+information on each interface.
+It will take at most nine seconds.
+.It show Op interfaces...
+Displays information on Router Advertisement messages being sent
+on each interface.
+.El
+.Sh SEE ALSO
+.Xr rtadvd 8 ,
+.Xr rtadvd.conf 5
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+.Nm
+was written by
+.An "Hiroki Sato" Aq hrs at FreeBSD.org .

Added: stable/8/usr.sbin/rtadvctl/rtadvctl.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.sbin/rtadvctl/rtadvctl.c	Thu Feb 16 01:32:23 2012	(r231802)
@@ -0,0 +1,925 @@
+/*-
+ * Copyright (C) 2011 Hiroki Sato <hrs at FreeBSD.org>
+ * 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 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.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <err.h>
+
+#include "pathnames.h"
+#include "rtadvd.h"
+#include "if.h"
+#include "timer_subr.h"
+#include "timer.h"
+#include "control.h"
+#include "control_client.h"
+
+#define RA_IFSTATUS_INACTIVE	0
+#define RA_IFSTATUS_RA_RECV	1
+#define RA_IFSTATUS_RA_SEND	2
+
+static int vflag = LOG_ERR;
+
+static void	usage(void);
+
+static int	action_propset(char *);
+static int	action_propget(char *, struct ctrl_msg_pl *);
+static int	action_plgeneric(int, char *, char *);
+
+static int	action_enable(int, char **);
+static int	action_disable(int, char **);
+static int	action_reload(int, char **);
+static int	action_echo(int, char **);
+static int	action_version(int, char **);
+static int	action_shutdown(int, char **);
+
+static int	action_show(int, char **);
+static int	action_show_prefix(struct prefix *);
+static int	action_show_rtinfo(struct rtinfo *);
+static int	action_show_rdnss(void *);
+static int	action_show_dnssl(void *);
+
+static int	csock_client_open(struct sockinfo *);
+static size_t	dname_labeldec(char *, size_t, const char *);
+static void	mysyslog(int, const char *, ...);
+
+static const char *rtpref_str[] = {
+	"medium",		/* 00 */
+	"high",			/* 01 */
+	"rsv",			/* 10 */
+	"low"			/* 11 */
+};
+
+static struct dispatch_table {
+	const char	*dt_comm;
+	int (*dt_act)(int, char **);
+} dtable[] = {
+	{ "show", action_show },
+	{ "reload", action_reload },
+	{ "shutdown", action_shutdown },
+	{ "enable", action_enable },
+	{ "disable", action_disable },
+	{ NULL, NULL },
+	{ "echo", action_echo },
+	{ "version", action_version },
+	{ NULL, NULL },
+};
+
+static char errmsgbuf[1024];
+static char *errmsg = NULL;
+
+static void
+mysyslog(int priority, const char * restrict fmt, ...)
+{
+	va_list ap;
+
+	if (vflag >= priority) {
+		va_start(ap, fmt);
+		vfprintf(stderr, fmt, ap);
+		fprintf(stderr, "\n");
+		va_end(ap);
+	}
+}
+
+static void
+usage(void)
+{
+	int i;
+
+	for (i = 0; (size_t)i < sizeof(dtable)/sizeof(dtable[0]); i++) {
+		if (dtable[i].dt_comm == NULL)
+			break;
+		printf("%s\n", dtable[i].dt_comm);
+	}
+
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int i;
+	int ch;
+	int (*action)(int, char **) = NULL;
+	int error;
+
+	while ((ch = getopt(argc, argv, "Dv")) != -1) {
+		switch (ch) {
+		case 'D':
+			vflag = LOG_DEBUG;
+			break;
+		case 'v':
+			vflag++;
+			break;
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc == 0)
+		usage();
+
+	for (i = 0; (size_t)i < sizeof(dtable)/sizeof(dtable[0]); i++) {
+		if (dtable[i].dt_comm == NULL ||
+		    strcmp(dtable[i].dt_comm, argv[0]) == 0) {
+			action = dtable[i].dt_act;
+			break;
+		}
+	}
+
+	if (action == NULL)
+		usage();
+
+	error = (dtable[i].dt_act)(--argc, ++argv);
+	if (error) {
+		fprintf(stderr, "%s failed", dtable[i].dt_comm);
+		if (errmsg != NULL)
+			fprintf(stderr, ": %s", errmsg);
+		fprintf(stderr, ".\n");
+	}
+
+	return (error);
+}
+
+static int
+csock_client_open(struct sockinfo *s)
+{
+	struct sockaddr_un sun;
+
+	if ((s->si_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
+		err(1, "cannot open control socket.");
+
+	memset(&sun, 0, sizeof(sun));
+	sun.sun_family = AF_UNIX;
+	sun.sun_len = sizeof(sun);
+	strlcpy(sun.sun_path, s->si_name, sizeof(sun.sun_path));
+
+	if (connect(s->si_fd, (struct sockaddr *)&sun, sizeof(sun)) == -1)
+		err(1, "connect: %s", s->si_name);
+
+	mysyslog(LOG_DEBUG,
+	    "<%s> connected to %s", __func__, sun.sun_path);
+
+	return (0);
+}
+
+static int
+action_plgeneric(int action, char *plstr, char *buf)
+{
+	struct ctrl_msg_hdr *cm;
+	struct ctrl_msg_pl cp;
+	struct sockinfo *s;
+	char *msg;
+	char *p;
+	char *q;
+
+	s = &ctrlsock;
+	csock_client_open(s);
+
+	cm = (struct ctrl_msg_hdr *)buf;
+	msg = (char *)buf + sizeof(*cm);
+
+	cm->cm_version = CM_VERSION;
+	cm->cm_type = action;
+	cm->cm_len = sizeof(*cm);
+
+	if (plstr != NULL) {
+		memset(&cp, 0, sizeof(cp));
+		p = strchr(plstr, ':');
+		q = strchr(plstr, '=');
+		if (p != NULL && q != NULL && p > q)
+			return (1);
+
+		if (p == NULL) {		/* No : */
+			cp.cp_ifname = NULL;
+			cp.cp_key = plstr;
+		} else if  (p == plstr) {	/* empty */
+			cp.cp_ifname = NULL;
+			cp.cp_key = plstr + 1;
+		} else {
+			*p++ = '\0';
+			cp.cp_ifname = plstr;
+			cp.cp_key = p;
+		}
+		if (q == NULL)
+			cp.cp_val = NULL;
+		else {
+			*q++ = '\0';
+			cp.cp_val = q;
+		}
+		cm->cm_len += cm_pl2bin(msg, &cp);
+
+		mysyslog(LOG_DEBUG, "<%s> key=%s, val_len=%d, ifname=%s",
+		    __func__,cp.cp_key, cp.cp_val_len, cp.cp_ifname);
+	}
+
+	return (cm_handler_client(s->si_fd, CM_STATE_MSG_DISPATCH, buf));
+}
+
+static int
+action_propget(char *argv, struct ctrl_msg_pl *cp)
+{
+	int error;
+	struct ctrl_msg_hdr *cm;
+	char buf[CM_MSG_MAXLEN];
+	char *msg;
+
+	memset(cp, 0, sizeof(*cp));
+	cm = (struct ctrl_msg_hdr *)buf;
+	msg = (char *)buf + sizeof(*cm);
+
+	error = action_plgeneric(CM_TYPE_REQ_GET_PROP, argv, buf);
+	if (error || cm->cm_len <= sizeof(*cm))
+		return (1);
+
+	cm_bin2pl(msg, cp);
+	mysyslog(LOG_DEBUG, "<%s> type=%d, len=%d",
+	    __func__, cm->cm_type, cm->cm_len);
+	mysyslog(LOG_DEBUG, "<%s> key=%s, val_len=%d, ifname=%s",
+	    __func__,cp->cp_key, cp->cp_val_len, cp->cp_ifname);
+
+	return (0);
+}
+
+static int
+action_propset(char *argv)
+{
+	char buf[CM_MSG_MAXLEN];
+
+	return (action_plgeneric(CM_TYPE_REQ_SET_PROP, argv, buf));
+}
+
+static int
+action_disable(int argc, char **argv)
+{
+	char *action_argv;
+	char argv_disable[IFNAMSIZ + sizeof(":disable=")];
+	int i;
+	int error;
+
+	if (argc < 1)
+		return (1);
+
+	error = 0;
+	for (i = 0; i < argc; i++) {
+		sprintf(argv_disable, "%s:disable=", argv[i]);
+		action_argv = argv_disable;
+		error += action_propset(action_argv);
+	}
+
+	return (error);
+}
+
+static int
+action_enable(int argc, char **argv)
+{
+	char *action_argv;
+	char argv_enable[IFNAMSIZ + sizeof(":enable=")];
+	int i;
+	int error;
+
+	if (argc < 1)
+		return (1);
+
+	error = 0;
+	for (i = 0; i < argc; i++) {
+		sprintf(argv_enable, "%s:enable=", argv[i]);
+		action_argv = argv_enable;
+		error += action_propset(action_argv);
+	}
+
+	return (error);
+}
+
+static int
+action_reload(int argc, char **argv)
+{
+	char *action_argv;
+	char argv_reload[IFNAMSIZ + sizeof(":reload=")];
+	int i;
+	int error;
+
+	if (argc == 0) {
+		action_argv = strdup(":reload=");
+		return (action_propset(action_argv));
+	}
+
+	error = 0;
+	for (i = 0; i < argc; i++) {
+		sprintf(argv_reload, "%s:reload=", argv[i]);
+		action_argv = argv_reload;
+		error += action_propset(action_argv);
+	}
+
+	return (error);
+}
+
+static int
+action_echo(int argc __unused, char **argv __unused)
+{
+	char *action_argv;
+
+	action_argv = strdup("echo");
+	return (action_propset(action_argv));
+}
+
+static int
+action_shutdown(int argc __unused, char **argv __unused)
+{
+	char *action_argv;
+
+	action_argv = strdup("shutdown");
+	return (action_propset(action_argv));
+}
+
+/* XXX */
+static int
+action_version(int argc __unused, char **argv __unused)
+{
+	char *action_argv;
+	struct ctrl_msg_pl cp;
+	int error;
+
+	action_argv = strdup(":version=");
+	error = action_propget(action_argv, &cp);
+	if (error)
+		return (error);
+
+	printf("version=%s\n", cp.cp_val);
+	return (0);
+}
+
+static int
+action_show(int argc, char **argv)
+{
+	char *action_argv;
+	char argv_ifilist[sizeof(":ifilist=")] = ":ifilist=";
+	char argv_ifi[IFNAMSIZ + sizeof(":ifi=")];
+	char argv_rai[IFNAMSIZ + sizeof(":rai=")];
+	char argv_rti[IFNAMSIZ + sizeof(":rti=")];
+	char argv_pfx[IFNAMSIZ + sizeof(":pfx=")];
+	char argv_ifi_ra_timer[IFNAMSIZ + sizeof(":ifi_ra_timer=")];
+	char argv_rdnss[IFNAMSIZ + sizeof(":rdnss=")];
+	char argv_dnssl[IFNAMSIZ + sizeof(":dnssl=")];
+	char ssbuf[SSBUFLEN];
+
+	struct ctrl_msg_pl cp;
+	struct ifinfo *ifi;
+	TAILQ_HEAD(, ifinfo) ifl = TAILQ_HEAD_INITIALIZER(ifl);
+	char *endp;
+	char *p;
+	int error;
+	int i;
+	int len;
+
+	if (argc == 0) {
+		action_argv = argv_ifilist;
+		error = action_propget(action_argv, &cp);
+		if (error)
+			return (error);
+
+		p = cp.cp_val;
+		endp = p + cp.cp_val_len;
+		while (p < endp) {
+			ifi = malloc(sizeof(*ifi));
+			if (ifi == NULL)
+				return (1);
+			memset(ifi, 0, sizeof(*ifi));
+
+			strcpy(ifi->ifi_ifname, p);
+			ifi->ifi_ifindex = if_nametoindex(ifi->ifi_ifname);
+			TAILQ_INSERT_TAIL(&ifl, ifi, ifi_next);
+			p += strlen(ifi->ifi_ifname) + 1;
+		}
+	} else {
+		for (i = 0; i < argc; i++) {
+			ifi = malloc(sizeof(*ifi));
+			if (ifi == NULL)
+				return (1);
+			memset(ifi, 0, sizeof(*ifi));
+
+			strcpy(ifi->ifi_ifname, argv[i]);
+			ifi->ifi_ifindex = if_nametoindex(ifi->ifi_ifname);
+			if (ifi->ifi_ifindex == 0) {
+				sprintf(errmsgbuf, "invalid interface %s",
+				    ifi->ifi_ifname);
+				errmsg = errmsgbuf;
+				return (1);
+			}
+
+			TAILQ_INSERT_TAIL(&ifl, ifi, ifi_next);
+		}
+	}
+
+	TAILQ_FOREACH(ifi, &ifl, ifi_next) {
+		struct ifinfo *ifi_s;
+		struct rtadvd_timer *rat;
+		struct rainfo *rai;
+		struct rtinfo *rti;
+		struct prefix *pfx;
+		int c;
+		int ra_ifstatus;
+
+		sprintf(argv_ifi, "%s:ifi=", ifi->ifi_ifname);
+		action_argv = argv_ifi;
+		error = action_propget(action_argv, &cp);
+		if (error)
+			return (error);
+		ifi_s = (struct ifinfo *)cp.cp_val;
+
+		if (!(ifi_s->ifi_persist) && vflag < LOG_NOTICE)
+			continue;
+
+		printf("%s: flags=<", ifi->ifi_ifname);
+
+		c = 0;
+		if (ifi_s->ifi_ifindex == 0)
+			c += printf("NONEXISTENT");
+		else
+			c += printf("%s", (ifi_s->ifi_flags & IFF_UP) ?
+			    "UP" : "DOWN");
+		switch (ifi_s->ifi_state) {
+		case IFI_STATE_CONFIGURED:
+			c += printf("%s%s", (c) ? "," : "", "CONFIGURED");
+			break;
+		case IFI_STATE_TRANSITIVE:
+			c += printf("%s%s", (c) ? "," : "", "TRANSITIVE");
+			break;
+		}
+		if (ifi_s->ifi_persist)
+			c += printf("%s%s", (c) ? "," : "", "PERSIST");
+		printf(">");
+
+		ra_ifstatus = RA_IFSTATUS_INACTIVE;
+		if ((ifi_s->ifi_flags & IFF_UP) &&
+		    ((ifi_s->ifi_state == IFI_STATE_CONFIGURED) ||
+			(ifi_s->ifi_state == IFI_STATE_TRANSITIVE))) {
+#if (__FreeBSD_version < 900000)
+			/*
+			 * RA_RECV: !ip6.forwarding && ip6.accept_rtadv
+			 * RA_SEND: ip6.forwarding
+			 */
+			if (getinet6sysctl(IPV6CTL_FORWARDING) == 0) {
+				if (getinet6sysctl(IPV6CTL_ACCEPT_RTADV))
+					ra_ifstatus = RA_IFSTATUS_RA_RECV;
+				else
+					ra_ifstatus = RA_IFSTATUS_INACTIVE;
+			} else
+				ra_ifstatus = RA_IFSTATUS_RA_SEND;
+#else
+			/*
+			 * RA_RECV: ND6_IFF_ACCEPT_RTADV
+			 * RA_SEND: ip6.forwarding
+			 */
+			if (ifi_s->ifi_nd_flags & ND6_IFF_ACCEPT_RTADV)
+				ra_ifstatus = RA_IFSTATUS_RA_RECV;
+			else if (getinet6sysctl(IPV6CTL_FORWARDING))
+				ra_ifstatus = RA_IFSTATUS_RA_SEND;
+			else
+				ra_ifstatus = RA_IFSTATUS_INACTIVE;
+#endif
+		}
+
+		c = 0;
+		printf(" status=<");
+		if (ra_ifstatus == RA_IFSTATUS_INACTIVE)
+			printf("%s%s", (c) ? "," : "", "INACTIVE");
+		else if (ra_ifstatus == RA_IFSTATUS_RA_RECV)
+			printf("%s%s", (c) ? "," : "", "RA_RECV");
+		else if (ra_ifstatus == RA_IFSTATUS_RA_SEND)
+			printf("%s%s", (c) ? "," : "", "RA_SEND");
+		printf("> ");
+
+		switch (ifi_s->ifi_state) {
+		case IFI_STATE_CONFIGURED:
+		case IFI_STATE_TRANSITIVE:
+			break;
+		default:
+			printf("\n");
+			continue;
+		}
+
+		printf("mtu %d\n", ifi_s->ifi_phymtu);
+
+		sprintf(argv_rai, "%s:rai=", ifi->ifi_ifname);
+		action_argv = argv_rai;
+
+		error = action_propget(action_argv, &cp);
+		if (error)
+			continue;
+
+		rai = (struct rainfo *)cp.cp_val;
+
+		printf("\tDefaultLifetime: %s",
+		    sec2str(rai->rai_lifetime, ssbuf));
+		if (ra_ifstatus != RA_IFSTATUS_RA_SEND &&
+		    rai->rai_lifetime == 0)
+			printf(" (RAs will be sent with zero lifetime)");
+
+		printf("\n");
+
+		printf("\tMinAdvInterval/MaxAdvInterval: ");
+		printf("%s/", sec2str(rai->rai_mininterval, ssbuf));
+		printf("%s\n", sec2str(rai->rai_maxinterval, ssbuf));
+		if (rai->rai_linkmtu)
+			printf("\tAdvLinkMTU: %d", rai->rai_linkmtu);
+		else
+			printf("\tAdvLinkMTU: <none>");
+
+		printf(", ");
+
+		printf("Flags: ");
+		if (rai->rai_managedflg || rai->rai_otherflg) {
+			printf("%s", rai->rai_managedflg ? "M" : "");
+			printf("%s", rai->rai_otherflg ? "O" : "");
+		} else
+			printf("<none>");
+
+		printf(", ");
+
+		printf("Preference: %s\n",
+		    rtpref_str[(rai->rai_rtpref >> 3) & 0xff]);
+
+		printf("\tReachableTime: %s, ",
+		    sec2str(rai->rai_reachabletime, ssbuf));
+		printf("RetransTimer: %s, "
+		    "CurHopLimit: %d\n",
+		    sec2str(rai->rai_retranstimer, ssbuf),
+		    rai->rai_hoplimit);
+		printf("\tAdvIfPrefixes: %s\n",
+		    rai->rai_advifprefix ? "yes" : "no");
+
+		/* RA timer */
+		rat = NULL;
+		if (ifi_s->ifi_ra_timer != NULL) {
+			sprintf(argv_ifi_ra_timer, "%s:ifi_ra_timer=",
+			    ifi->ifi_ifname);
+			action_argv = argv_ifi_ra_timer;
+
+			error = action_propget(action_argv, &cp);
+			if (error)
+				return (error);
+
+			rat = (struct rtadvd_timer *)cp.cp_val;
+		}
+		printf("\tNext RA send: %s",
+		    (rat == NULL) ? "never\n" :
+		    ctime((time_t *)&rat->rat_tm.tv_sec));
+		printf("\tLast RA sent: %s",
+		    (ifi_s->ifi_ra_lastsent.tv_sec == 0) ? "never\n" :
+		    ctime((time_t *)&ifi_s->ifi_ra_lastsent.tv_sec));
+		if (rai->rai_clockskew)
+			printf("\tClock skew: %" PRIu16 "sec\n",
+			    rai->rai_clockskew);
+
+		if (vflag < LOG_WARNING)
+			continue;
+
+		/* route information */
+		sprintf(argv_rti, "%s:rti=", ifi->ifi_ifname);
+		action_argv = argv_rti;
+		error = action_propget(action_argv, &cp);
+		if (error)
+			return (error);
+
+		rti = (struct rtinfo *)cp.cp_val;
+		len = cp.cp_val_len / sizeof(*rti);
+		if (len > 0) {
+			printf("\tRoute Info:\n");
+
+			for (i = 0; i < len; i++)
+				action_show_rtinfo(&rti[i]);
+		}
+
+		/* prefix information */
+		sprintf(argv_pfx, "%s:pfx=", ifi->ifi_ifname);
+		action_argv = argv_pfx;
+
+		error = action_propget(action_argv, &cp);
+		if (error)
+			continue;
+
+		pfx = (struct prefix *)cp.cp_val;
+		len = cp.cp_val_len / sizeof(*pfx);
+
+		if (len > 0) {
+			printf("\tPrefixes (%d):\n", len);
+
+			for (i = 0; i < len; i++)
+				action_show_prefix(&pfx[i]);
+		}
+
+		/* RDNSS information */
+		sprintf(argv_rdnss, "%s:rdnss=", ifi->ifi_ifname);
+		action_argv = argv_rdnss;
+
+		error = action_propget(action_argv, &cp);
+		if (error)
+			continue;
+
+		len = *((uint16_t *)cp.cp_val);
+
+		if (len > 0) {
+			printf("\tRDNSS entries:\n");
+			action_show_rdnss(cp.cp_val);
+		}
+
+		/* DNSSL information */
+		sprintf(argv_dnssl, "%s:dnssl=", ifi->ifi_ifname);
+		action_argv = argv_dnssl;
+
+		error = action_propget(action_argv, &cp);
+		if (error)
+			continue;
+
+		len = *((uint16_t *)cp.cp_val);
+
+		if (len > 0) {
+			printf("\tDNSSL entries:\n");
+			action_show_dnssl(cp.cp_val);
+		}
+
+		if (vflag < LOG_NOTICE)
+			continue;
+
+		printf("\n");
+
+		printf("\tCounters\n"
+		    "\t RA burst counts: %" PRIu16 " (interval: %s)\n"
+		    "\t RS wait counts: %" PRIu16 "\n",
+		    ifi_s->ifi_burstcount,
+		    sec2str(ifi_s->ifi_burstinterval, ssbuf),
+		    ifi_s->ifi_rs_waitcount);
+
+		printf("\tOutputs\n"
+		    "\t RA: %" PRIu64 "\n", ifi_s->ifi_raoutput);
+
+		printf("\tInputs\n"
+		    "\t RA: %" PRIu64 " (normal)\n"
+		    "\t RA: %" PRIu64 " (inconsistent)\n"
+		    "\t RS: %" PRIu64 "\n",
+		    ifi_s->ifi_rainput,
+		    ifi_s->ifi_rainconsistent,
+		    ifi_s->ifi_rsinput);
+
+		printf("\n");
+
+#if 0	/* Not implemented yet */
+		printf("\tReceived RAs:\n");
+#endif
+	}
+
+	return (0);
+}
+
+static int
+action_show_rtinfo(struct rtinfo *rti)
+{
+	char ntopbuf[INET6_ADDRSTRLEN];
+	char ssbuf[SSBUFLEN];
+
+	printf("\t  %s/%d (pref: %s, ltime: %s)\n",
+	    inet_ntop(AF_INET6, &rti->rti_prefix,
+		ntopbuf, sizeof(ntopbuf)),
+	    rti->rti_prefixlen,
+	    rtpref_str[0xff & (rti->rti_rtpref >> 3)],
+	    (rti->rti_ltime == ND6_INFINITE_LIFETIME) ?
+	    "infinity" : sec2str(rti->rti_ltime, ssbuf));
+
+	return (0);
+}
+
+static int
+action_show_prefix(struct prefix *pfx)
+{
+	char ntopbuf[INET6_ADDRSTRLEN];
+	char ssbuf[SSBUFLEN];
+	struct timeval now;
+
+	gettimeofday(&now, NULL);
+	printf("\t  %s/%d", inet_ntop(AF_INET6, &pfx->pfx_prefix,
+		ntopbuf, sizeof(ntopbuf)), pfx->pfx_prefixlen);
+
+	printf(" (");
+	switch (pfx->pfx_origin) {
+	case PREFIX_FROM_KERNEL:
+		printf("KERNEL");
+		break;
+	case PREFIX_FROM_CONFIG:
+		printf("CONFIG");
+		break;
+	case PREFIX_FROM_DYNAMIC:
+		printf("DYNAMIC");
+		break;
+	}
+
+	printf(",");
+
+	printf(" vltime=%s",
+	    (pfx->pfx_validlifetime == ND6_INFINITE_LIFETIME) ?
+	    "infinity" : sec2str(pfx->pfx_validlifetime, ssbuf));
+
+	if (pfx->pfx_vltimeexpire > 0)
+		printf("(expire: %s)",
+		    ((long)pfx->pfx_vltimeexpire > now.tv_sec) ?
+		    sec2str(pfx->pfx_vltimeexpire - now.tv_sec, ssbuf) :
+		    "0");
+
+	printf(",");
+
+	printf(" pltime=%s",
+	    (pfx->pfx_preflifetime == ND6_INFINITE_LIFETIME) ?
+	    "infinity" : sec2str(pfx->pfx_preflifetime, ssbuf));
+
+	if (pfx->pfx_pltimeexpire > 0)
+		printf("(expire %s)",
+		    ((long)pfx->pfx_pltimeexpire > now.tv_sec) ?
+		    sec2str(pfx->pfx_pltimeexpire - now.tv_sec, ssbuf) :
+		    "0");
+
+	printf(",");
+
+	printf(" flags=");
+	if (pfx->pfx_onlinkflg || pfx->pfx_autoconfflg) {
+		printf("%s", pfx->pfx_onlinkflg ? "L" : "");
+		printf("%s", pfx->pfx_autoconfflg ? "A" : "");
+	} else
+		printf("<none>");
+
+	if (pfx->pfx_timer) {
+		struct timeval *rest;
+
+		rest = rtadvd_timer_rest(pfx->pfx_timer);
+		if (rest) { /* XXX: what if not? */
+			printf(" expire=%s", sec2str(rest->tv_sec, ssbuf));
+		}
+	}
+
+	printf(")\n");
+
+	return (0);
+}
+
+static int
+action_show_rdnss(void *msg)
+{
+	struct rdnss *rdn;
+	struct rdnss_addr *rda;
+	uint16_t *rdn_cnt;
+	uint16_t *rda_cnt;
+	int i;
+	int j;
+	char *p;
+	uint32_t	ltime;
+	char ntopbuf[INET6_ADDRSTRLEN];
+	char ssbuf[SSBUFLEN];
+
+	p = msg;
+	rdn_cnt = (uint16_t *)p;
+	p += sizeof(*rdn_cnt);
+
+	if (*rdn_cnt > 0) {
+		for (i = 0; i < *rdn_cnt; i++) {
+			rdn = (struct rdnss *)p;
+			ltime = rdn->rd_ltime;
+			p += sizeof(*rdn);
+
+			rda_cnt = (uint16_t *)p;
+			p += sizeof(*rda_cnt);
+			if (*rda_cnt > 0)
+				for (j = 0; j < *rda_cnt; j++) {
+					rda = (struct rdnss_addr *)p;
+					printf("\t  %s (ltime=%s)\n",
+					    inet_ntop(AF_INET6,
+						&rda->ra_dns,
+						ntopbuf,
+						sizeof(ntopbuf)),
+					    sec2str(ltime, ssbuf));
+					p += sizeof(*rda);
+				}
+		}
+	}
+
+	return (0);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-stable mailing list