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 <h...@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 h...@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 <h...@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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to