Bug 152458 - rtadvd(8) needs to allow RA without a prefix info option
Summary: rtadvd(8) needs to allow RA without a prefix info option
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 7.3-STABLE
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-21 19:40 UTC by Steinar Haug
Modified: 2019-01-19 20:00 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Steinar Haug 2010-11-21 19:40:11 UTC
In IPv6 it should be possible to generate a Router Advertisement which
contains no prefix info option (the idea being that I want a host on the
LAN to populate its default router list but nothing else). However, I
cannot seem to get rtadvd to do this.

My Juniper routers can do this without any problem.

If I start rtadvd with no /etc/rtadvd.conf file, it sends RAs with a
prefix info option corresponding to the IPv6 address of the interface.
In the /etc/rtadvd.conf I can explicitly specify prefixes ("addr"),
but I can't find any way to specify that no prefix info option should
be sent.

If I start rtadvd with the -s option, it still sends RAs with a prefix
info option corresponding to the IPv6 address of the interface.

If I start rtadvd with a config file which specifies a prefix using
the "addr" option, I can get rtadvd to send RAs without the "auto"
flag - thus the prefix won't be used for SLAAC. E.g.:

em1:raflags="m":pinfoflags="l":addr="2001:8c0:8500:3::"

gives me a RA like the following (tcpdump output):


20:26:15.469184 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 56) fe80::214:22ff:fe1a:8439 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 56
        hop limit 64, Flags [managed], pref medium, router lifetime 1800s, reachable time 0s, retrans time 0s
          source link-address option (1), length 8 (1): 00:14:22:1a:84:39
          prefix info option (3), length 32 (4): 2001:8c0:8500:3::/64, Flags [onlink], valid time 2592000s, pref. time 604800s


But this is not quite the same as not announcing a prefix.

It's possible we simply have some missing functionality here.

How-To-Repeat: Start rtadvd. Observe using tcpdump or similar that a prefix info option is
always included in the RAs transmitted on the interface.
Comment 1 Bjoern A. Zeeb freebsd_committer freebsd_triage 2010-11-21 20:05:26 UTC
Responsible Changed
From-To: freebsd-bugs->bz

Take.
Comment 2 Bjoern A. Zeeb freebsd_committer freebsd_triage 2011-06-04 15:02:11 UTC
Responsible Changed
From-To: bz->hrs

hrs, given you are doing the complete code overhaul, let me 
assign that to you as well.
Comment 3 dfilter service freebsd_committer freebsd_triage 2011-06-06 04:07:00 UTC
Author: hrs
Date: Mon Jun  6 03:06:43 2011
New Revision: 222732
URL: http://svn.freebsd.org/changeset/base/222732

Log:
  - Implement RDNSS and DNSSL options (RFC 6106, IPv6 Router Advertisement
    Options for DNS Configuration) into rtadvd(8) and rtsold(8).  DNS
    information received by rtsold(8) will go to resolv.conf(5) by
    resolvconf(8) script.  This is based on work by J.R. Oldroyd (kern/156259)
    but revised extensively[1].
  
  - 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.
  
  - Correct bogus ND_OPT_ROUTE_INFO value to one in RFC 4191.
  
  Reviewed by:	bz[1]
  PR:		kern/156259 [1]
  PR:		bin/152458 [2]

Modified:
  head/sys/netinet/icmp6.h
  head/usr.sbin/rtadvd/Makefile
  head/usr.sbin/rtadvd/advcap.c
  head/usr.sbin/rtadvd/config.c
  head/usr.sbin/rtadvd/config.h
  head/usr.sbin/rtadvd/dump.c
  head/usr.sbin/rtadvd/dump.h
  head/usr.sbin/rtadvd/if.c
  head/usr.sbin/rtadvd/if.h
  head/usr.sbin/rtadvd/pathnames.h
  head/usr.sbin/rtadvd/rrenum.c
  head/usr.sbin/rtadvd/rrenum.h
  head/usr.sbin/rtadvd/rtadvd.8
  head/usr.sbin/rtadvd/rtadvd.c
  head/usr.sbin/rtadvd/rtadvd.conf
  head/usr.sbin/rtadvd/rtadvd.conf.5
  head/usr.sbin/rtadvd/rtadvd.h
  head/usr.sbin/rtadvd/timer.c
  head/usr.sbin/rtadvd/timer.h
  head/usr.sbin/rtsold/Makefile
  head/usr.sbin/rtsold/dump.c
  head/usr.sbin/rtsold/if.c
  head/usr.sbin/rtsold/probe.c
  head/usr.sbin/rtsold/rtsock.c
  head/usr.sbin/rtsold/rtsol.c
  head/usr.sbin/rtsold/rtsold.8
  head/usr.sbin/rtsold/rtsold.c
  head/usr.sbin/rtsold/rtsold.h

Modified: head/sys/netinet/icmp6.h
==============================================================================
--- head/sys/netinet/icmp6.h	Mon Jun  6 02:46:22 2011	(r222731)
+++ head/sys/netinet/icmp6.h	Mon Jun  6 03:06:43 2011	(r222732)
@@ -297,8 +297,9 @@ struct nd_opt_hdr {		/* Neighbor discove
 #define ND_OPT_PREFIX_INFORMATION	3
 #define ND_OPT_REDIRECTED_HEADER	4
 #define ND_OPT_MTU			5
-
-#define ND_OPT_ROUTE_INFO		200	/* draft-ietf-ipngwg-router-preference, not officially assigned yet */
+#define ND_OPT_ROUTE_INFO		24	/* RFC 4191 */
+#define ND_OPT_RDNSS			25	/* RFC 6016 */
+#define ND_OPT_DNSSL			31	/* RFC 6016 */
 
 struct nd_opt_prefix_info {	/* prefix information */
 	u_int8_t	nd_opt_pi_type;
@@ -338,6 +339,22 @@ struct nd_opt_route_info {	/* route info
 	/* prefix follows */
 } __packed;
 
+struct nd_opt_rdnss {		/* RDNSS option (RFC 6106) */
+	u_int8_t	nd_opt_rdnss_type;
+	u_int8_t	nd_opt_rdnss_len;
+	u_int16_t	nd_opt_rdnss_reserved;
+	u_int32_t	nd_opt_rdnss_lifetime;
+	/* followed by list of recursive DNS servers */
+} __packed;
+
+struct nd_opt_dnssl {		/* DNSSL option (RFC 6106) */
+	u_int8_t	nd_opt_dnssl_type;
+	u_int8_t	nd_opt_dnssl_len;
+	u_int16_t	nd_opt_dnssl_reserved;
+	u_int32_t	nd_opt_dnssl_lifetime;
+	/* followed by list of DNS search domains */
+} __packed;
+
 /*
  * icmp6 namelookup
  */

Modified: head/usr.sbin/rtadvd/Makefile
==============================================================================
--- head/usr.sbin/rtadvd/Makefile	Mon Jun  6 02:46:22 2011	(r222731)
+++ head/usr.sbin/rtadvd/Makefile	Mon Jun  6 03:06:43 2011	(r222732)
@@ -23,6 +23,6 @@ LDADD=	-lutil
 
 CFLAGS+= -DHAVE_ARC4RANDOM -DHAVE_POLL_H -DROUTEINFO
 
-WARNS?=	1
+WARNS?=	6
 
 .include <bsd.prog.mk>

Modified: head/usr.sbin/rtadvd/advcap.c
==============================================================================
--- head/usr.sbin/rtadvd/advcap.c	Mon Jun  6 02:46:22 2011	(r222731)
+++ head/usr.sbin/rtadvd/advcap.c	Mon Jun  6 03:06:43 2011	(r222732)
@@ -64,8 +64,6 @@
 #define V_TERM		"HOST"
 #endif
 
-char	*RM;
-
 /*
  * termcap - routines for dealing with the terminal capability data base
  *
@@ -83,12 +81,11 @@ char	*RM;
 static	char *tbuf;
 static	int hopcount;	/* detect infinite loops in termcap, init 0 */
 
-static	char *remotefile;
-
-extern char *conffile;
+static const char *remotefile;
+extern const char *conffile;
 
 int tgetent(char *, char *);
-int getent(char *, char *, char *);
+int getent(char *, char *, const char *);
 int tnchktc(void);
 int tnamatch(char *);
 static char *tskip(char *);
@@ -103,22 +100,18 @@ static char *tdecode(char *, char **);
  * we just notice escaped newlines.
  */
 int
-tgetent(bp, name)
-	char *bp, *name;
+tgetent(char *bp, char *name)
 {
-	char *cp;
-
-	remotefile = cp = conffile ? conffile : _PATH_RTADVDCONF;
-	return (getent(bp, name, cp));
+	return (getent(bp, name, conffile));
 }
 
 int
-getent(bp, name, cp)
-	char *bp, *name, *cp;
+getent(char *bp, char *name, const char *cfile)
 {
 	int c;
 	int i = 0, cnt = 0;
 	char ibuf[BUFSIZ];
+	char *cp;
 	int tf;
 
 	tbuf = bp;
@@ -130,9 +123,9 @@ getent(bp, name, cp)
 	 * 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(RM = cp, O_RDONLY);
-	}
+	if (cfile && *cfile)
+		tf = open(cfile, O_RDONLY);
+
 	if (tf < 0) {
 		syslog(LOG_INFO,
 		       "<%s> open: %s", __func__, strerror(errno));
@@ -184,7 +177,7 @@ getent(bp, name, cp)
  * Note that this works because of the left to right scan.
  */
 int
-tnchktc()
+tnchktc(void)
 {
 	char *p, *q;
 	char tcname[16];	/* name of similar terminal */
@@ -233,8 +226,7 @@ tnchktc()
  * name (before the first field) stops us.
  */
 int
-tnamatch(np)
-	char *np;
+tnamatch(char *np)
 {
 	char *Np, *Bp;
 
@@ -260,8 +252,7 @@ tnamatch(np)
  * into the termcap file in octal.
  */
 static char *
-tskip(bp)
-	char *bp;
+tskip(char *bp)
 {
 	int dquote;
 
@@ -305,8 +296,7 @@ breakbreak:
  * Note that we handle octal numbers beginning with 0.
  */
 int64_t
-tgetnum(id)
-	char *id;
+tgetnum(char *id)
 {
 	int64_t i;
 	int base;
@@ -341,8 +331,7 @@ tgetnum(id)
  * not given.
  */
 int
-tgetflag(id)
-	char *id;
+tgetflag(char *id)
 {
 	char *bp = tbuf;
 
@@ -369,8 +358,7 @@ tgetflag(id)
  * No checking on area overflow.
  */
 char *
-tgetstr(id, area)
-	char *id, **area;
+tgetstr(char *id, char **area)
 {
 	char *bp = tbuf;
 
@@ -395,13 +383,11 @@ tgetstr(id, area)
  * string capability escapes.
  */
 static char *
-tdecode(str, area)
-	char *str;
-	char **area;
+tdecode(char *str, char **area)
 {
 	char *cp;
 	int c;
-	char *dp;
+	const char *dp;
 	int i;
 	char term;
 

Modified: head/usr.sbin/rtadvd/config.c
==============================================================================
--- head/usr.sbin/rtadvd/config.c	Mon Jun  6 02:46:22 2011	(r222731)
+++ head/usr.sbin/rtadvd/config.c	Mon Jun  6 03:06:43 2011	(r222732)
@@ -4,7 +4,7 @@
 /*
  * 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:
@@ -16,7 +16,7 @@
  * 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
@@ -34,7 +34,6 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/time.h>
-#include <sys/sysctl.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
@@ -53,6 +52,7 @@
 #include <stdio.h>
 #include <syslog.h>
 #include <errno.h>
+#include <netdb.h>
 #include <string.h>
 #include <search.h>
 #include <stdlib.h>
@@ -65,29 +65,55 @@
 #include "if.h"
 #include "config.h"
 
+/* label of tcapcode + number + domain name + zero octet */
+static char entbuf[10 + 3 + NI_MAXHOST + 1];
+static char oentbuf[10 + 3 + NI_MAXHOST + 1];
+static char abuf[DNAME_LABELENC_MAXLEN];
+
 static time_t prefix_timo = (60 * 120);	/* 2 hours.
 					 * XXX: should be configurable. */
-extern struct rainfo *ralist;
 
 static struct rtadvd_timer *prefix_timeout(void *);
-static void makeentry(char *, size_t, int, char *);
-static int getinet6sysctl(int);
+static void makeentry(char *, size_t, int, const char *);
+static size_t dname_labelenc(char *, const char *);
 
-void
-getconfig(intface)
-	char *intface;
+/* Encode domain name label encoding in RFC 1035 Section 3.1 */
+static size_t
+dname_labelenc(char *dst, const char *src)
 {
-	int stat, i;
-	char tbuf[BUFSIZ];
-	struct rainfo *tmp;
-	long val;
-	int64_t val64;
-	char buf[BUFSIZ];
-	char *bp = buf;
-	char *addr, *flagstr;
-	static int forwarding = -1;
+	char *dst_origin;
+	char *p;
+	size_t len;
 
-#define MUSTHAVE(var, cap)	\
+	dst_origin = dst;
+	len = strlen(src);
+
+	/* Length fields per 63 octets + '\0' (<= DNAME_LABELENC_MAXLEN) */
+	memset(dst, 0, len + len / 64 + 1 + 1);
+
+	syslog(LOG_DEBUG, "<%s> labelenc = %s", __func__, src);
+	while (src && (len = strlen(src)) != 0) {
+		/* Put a length field with 63 octet limitation first. */
+		p = strchr(src, '.');
+		if (p == NULL)
+			*dst++ = len = MIN(63, len);
+		else
+			*dst++ = len = MIN(63, p - src);
+		/* Copy 63 octets at most. */
+		memcpy(dst, src, len);
+		dst += len;
+		if (p == NULL) /* the last label */
+			break;
+		src = p + 1;
+	}
+	/* Always need a 0-length label at the tail. */
+	*dst++ = '\0';
+
+	syslog(LOG_DEBUG, "<%s> labellen = %d", __func__, dst - dst_origin);
+	return (dst - dst_origin);
+}
+
+#define	MUSTHAVE(var, cap)						\
     do {								\
 	int64_t t;							\
 	if ((t = agetnum(cap)) < 0) {					\
@@ -97,60 +123,158 @@ getconfig(intface)
 	}								\
 	var = t;							\
      } while (0)
-#define MAYHAVE(var, cap, def)	\
+
+#define	MAYHAVE(var, cap, def)						\
      do {								\
 	if ((var = agetnum(cap)) < 0)					\
 		var = def;						\
      } while (0)
 
+#define	ELM_MALLOC(p,error_action)					\
+	do {								\
+		p = malloc(sizeof(*p));					\
+		if (p == NULL) {					\
+			syslog(LOG_ERR, "<%s> malloc failed: %s",	\
+			    __func__, strerror(errno));			\
+			error_action;					\
+		}							\
+		memset(p, 0, sizeof(*p));				\
+	} while(0)
+
+int
+rmconfig(int idx)
+{
+	struct rainfo *rai;
+	struct prefix *pfx;
+	struct soliciter *sol;
+	struct rdnss *rdn;
+	struct rdnss_addr *rdna;
+	struct dnssl *dns;
+	struct rtinfo *rti;
+
+	rai = if_indextorainfo(idx);
+	if (rai == NULL) {
+		syslog(LOG_ERR, "<%s>: rainfo not found (idx=%d)",
+		    __func__, idx);
+		return (-1);
+	}
+
+	TAILQ_REMOVE(&railist, rai, rai_next);
+	syslog(LOG_DEBUG, "<%s>: rainfo (idx=%d) removed.",
+	    __func__, idx);
+
+	/* Free all of allocated memories for this entry. */
+	rtadvd_remove_timer(rai->rai_timer);
+
+	if (rai->rai_ra_data != NULL)
+		free(rai->rai_ra_data);
+
+	if (rai->rai_sdl != NULL)
+		free(rai->rai_sdl);
+
+	while ((pfx = TAILQ_FIRST(&rai->rai_prefix)) != NULL) {
+		TAILQ_REMOVE(&rai->rai_prefix, pfx, pfx_next);
+		free(pfx);
+	}
+	while ((sol = TAILQ_FIRST(&rai->rai_soliciter)) != NULL) {
+		TAILQ_REMOVE(&rai->rai_soliciter, sol, sol_next);
+		free(sol);
+	}
+	while ((rdn = TAILQ_FIRST(&rai->rai_rdnss)) != NULL) {
+		TAILQ_REMOVE(&rai->rai_rdnss, rdn, rd_next);
+		while ((rdna = TAILQ_FIRST(&rdn->rd_list)) != NULL) {
+			TAILQ_REMOVE(&rdn->rd_list, rdna, ra_next);
+			free(rdna);
+		}
+		free(rdn);
+	}
+	while ((dns = TAILQ_FIRST(&rai->rai_dnssl)) != NULL) {
+		TAILQ_REMOVE(&rai->rai_dnssl, dns, dn_next);
+		free(dns);
+	}
+	while ((rti = TAILQ_FIRST(&rai->rai_route)) != NULL) {
+		TAILQ_REMOVE(&rai->rai_route, rti, rti_next);
+		free(rti);
+	}
+	free(rai);
+	
+	return (0);
+}
+
+int
+getconfig(int idx)
+{
+	int stat, i;
+	char tbuf[BUFSIZ];
+	struct rainfo *rai;
+	long val;
+	int64_t val64;
+	char buf[BUFSIZ];
+	char *bp = buf;
+	char *addr, *flagstr;
+	char intface[IFNAMSIZ];
+
+	if (if_indextoname(idx, intface) == NULL) {
+		syslog(LOG_ERR, "<%s> invalid index number (%d)",
+		    __func__, idx);
+		return (-1);
+	}
+
 	if ((stat = agetent(tbuf, intface)) <= 0) {
 		memset(tbuf, 0, sizeof(tbuf));
 		syslog(LOG_INFO,
-		       "<%s> %s isn't defined in the configuration file"
-		       " or the configuration file doesn't exist."
-		       " Treat it as default",
-		        __func__, intface);
+		    "<%s> %s isn't defined in the configuration file"
+		    " or the configuration file doesn't exist."
+		    " Treat it as default",
+		     __func__, intface);
 	}
 
-	tmp = (struct rainfo *)malloc(sizeof(*ralist));
-	if (tmp == NULL) {
+	rai = malloc(sizeof(*rai));
+	if (rai == NULL) {
 		syslog(LOG_INFO, "<%s> %s: can't allocate enough memory",
 		    __func__, intface);
 		exit(1);
 	}
-	memset(tmp, 0, sizeof(*tmp));
-	tmp->prefix.next = tmp->prefix.prev = &tmp->prefix;
+	memset(rai, 0, sizeof(*rai));
+	TAILQ_INIT(&rai->rai_prefix);
 #ifdef ROUTEINFO
-	tmp->route.next = tmp->route.prev = &tmp->route;
+	TAILQ_INIT(&rai->rai_route);
 #endif
-
-	/* check if we are allowed to forward packets (if not determined) */
-	if (forwarding < 0) {
-		if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0)
-			exit(1);
-	}
+	TAILQ_INIT(&rai->rai_rdnss);
+	TAILQ_INIT(&rai->rai_dnssl);
+	TAILQ_INIT(&rai->rai_soliciter);
+
+	/* gather on-link prefixes from the network interfaces. */
+	if (agetflag("noifprefix"))
+		rai->rai_advifprefix = 0;
+	else
+		rai->rai_advifprefix = 1;
 
 	/* get interface information */
 	if (agetflag("nolladdr"))
-		tmp->advlinkopt = 0;
+		rai->rai_advlinkopt = 0;
 	else
-		tmp->advlinkopt = 1;
-	if (tmp->advlinkopt) {
-		if ((tmp->sdl = if_nametosdl(intface)) == NULL) {
+		rai->rai_advlinkopt = 1;
+	if (rai->rai_advlinkopt) {
+		if ((rai->rai_sdl = if_nametosdl(intface)) == NULL) {
 			syslog(LOG_ERR,
-			       "<%s> can't get information of %s",
-			       __func__, intface);
-			exit(1);
+			    "<%s> can't get information of %s",
+			    __func__, intface);
+			return (-1);
 		}
-		tmp->ifindex = tmp->sdl->sdl_index;
+		rai->rai_ifindex = rai->rai_sdl->sdl_index;
 	} else
-		tmp->ifindex = if_nametoindex(intface);
-	strncpy(tmp->ifname, intface, sizeof(tmp->ifname));
-	if ((tmp->phymtu = if_getmtu(intface)) == 0) {
-		tmp->phymtu = IPV6_MMTU;
+		rai->rai_ifindex = if_nametoindex(intface);
+	strncpy(rai->rai_ifname, intface, sizeof(rai->rai_ifname));
+	syslog(LOG_DEBUG,
+	    "<%s> ifindex = %d on %s", __func__, rai->rai_ifindex,
+	    rai->rai_ifname);
+
+	if ((rai->rai_phymtu = if_getmtu(intface)) == 0) {
+		rai->rai_phymtu = IPV6_MMTU;
 		syslog(LOG_WARNING,
-		       "<%s> can't get interface mtu of %s. Treat as %d",
-		       __func__, intface, IPV6_MMTU);
+		    "<%s> can't get interface mtu of %s. Treat as %d",
+		    __func__, intface, IPV6_MMTU);
 	}
 
 	/*
@@ -159,25 +283,27 @@ getconfig(intface)
 	MAYHAVE(val, "maxinterval", DEF_MAXRTRADVINTERVAL);
 	if (val < MIN_MAXINTERVAL || val > MAX_MAXINTERVAL) {
 		syslog(LOG_ERR,
-		       "<%s> maxinterval (%ld) on %s is invalid "
-		       "(must be between %u and %u)", __func__, val,
-		       intface, MIN_MAXINTERVAL, MAX_MAXINTERVAL);
-		exit(1);
-	}
-	tmp->maxinterval = (u_int)val;
-	MAYHAVE(val, "mininterval", tmp->maxinterval/3);
-	if (val < MIN_MININTERVAL || val > (tmp->maxinterval * 3) / 4) {
+		    "<%s> maxinterval (%ld) on %s is invalid "
+		    "(must be between %u and %u)", __func__, val,
+		    intface, MIN_MAXINTERVAL, MAX_MAXINTERVAL);
+		return (-1);
+	}
+	rai->rai_maxinterval = (u_int)val;
+
+	MAYHAVE(val, "mininterval", rai->rai_maxinterval/3);
+	if ((u_int)val < MIN_MININTERVAL ||
+	    (u_int)val > (rai->rai_maxinterval * 3) / 4) {
 		syslog(LOG_ERR,
-		       "<%s> mininterval (%ld) on %s is invalid "
-		       "(must be between %d and %d)",
-		       __func__, val, intface, MIN_MININTERVAL,
-		       (tmp->maxinterval * 3) / 4);
-		exit(1);
+		    "<%s> mininterval (%ld) on %s is invalid "
+		    "(must be between %d and %d)",
+		    __func__, val, intface, MIN_MININTERVAL,
+		    (rai->rai_maxinterval * 3) / 4);
+		return (-1);
 	}
-	tmp->mininterval = (u_int)val;
+	rai->rai_mininterval = (u_int)val;
 
 	MAYHAVE(val, "chlim", DEF_ADVCURHOPLIMIT);
-	tmp->hoplimit = val & 0xff;
+	rai->rai_hoplimit = val & 0xff;
 
 	if ((flagstr = (char *)agetstr("raflags", &bp))) {
 		val = 0;
@@ -191,77 +317,61 @@ getconfig(intface)
 			if ((val & ND_RA_FLAG_RTPREF_HIGH)) {
 				syslog(LOG_ERR, "<%s> the \'h\' and \'l\'"
 				    " router flags are exclusive", __func__);
-				exit(1);
+				return (-1);
 			}
 			val |= ND_RA_FLAG_RTPREF_LOW;
 		}
-	} else {
+	} else
 		MAYHAVE(val, "raflags", 0);
-	}
-	tmp->managedflg = val & ND_RA_FLAG_MANAGED;
-	tmp->otherflg = val & ND_RA_FLAG_OTHER;
+
+	rai->rai_managedflg = val & ND_RA_FLAG_MANAGED;
+	rai->rai_otherflg = val & ND_RA_FLAG_OTHER;
 #ifndef ND_RA_FLAG_RTPREF_MASK
 #define ND_RA_FLAG_RTPREF_MASK	0x18 /* 00011000 */
 #define ND_RA_FLAG_RTPREF_RSV	0x10 /* 00010000 */
 #endif
-	tmp->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
-	if (tmp->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+	rai->rai_rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+	if (rai->rai_rtpref == ND_RA_FLAG_RTPREF_RSV) {
 		syslog(LOG_ERR, "<%s> invalid router preference (%02x) on %s",
-		       __func__, tmp->rtpref, intface);
-		exit(1);
+		    __func__, rai->rai_rtpref, intface);
+		return (-1);
 	}
 
-	MAYHAVE(val, "rltime", tmp->maxinterval * 3);
-	if (val && (val < tmp->maxinterval || val > MAXROUTERLIFETIME)) {
-		syslog(LOG_ERR,
-		       "<%s> router lifetime (%ld) on %s is invalid "
-		       "(must be 0 or between %d and %d)",
-		       __func__, val, intface,
-		       tmp->maxinterval,
-		       MAXROUTERLIFETIME);
-		exit(1);
-	}
-	/*
-	 * 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
-	 * explicitly set zero. (see also the above section)
-	 */
-	if (val && forwarding == 0) {
+	MAYHAVE(val, "rltime", rai->rai_maxinterval * 3);
+	if ((u_int)val && ((u_int)val < rai->rai_maxinterval ||
+	    (u_int)val > MAXROUTERLIFETIME)) {
 		syslog(LOG_ERR,
-		       "<%s> non zero router lifetime is specified for %s, "
-		       "which must not be allowed for hosts.  you must "
-		       "change router lifetime or enable IPv6 forwarding.",
-		       __func__, intface);
-		exit(1);
+		    "<%s> router lifetime (%ld) on %s is invalid "
+		    "(must be 0 or between %d and %d)",
+		    __func__, val, intface, rai->rai_maxinterval,
+		    MAXROUTERLIFETIME);
+		return (-1);
 	}
-	tmp->lifetime = val & 0xffff;
+	rai->rai_lifetime = val & 0xffff;
 
 	MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME);
 	if (val < 0 || val > MAXREACHABLETIME) {
 		syslog(LOG_ERR,
-		       "<%s> reachable time (%ld) on %s is invalid "
-		       "(must be no greater than %d)",
-		       __func__, val, intface, MAXREACHABLETIME);
-		exit(1);
+		    "<%s> reachable time (%ld) on %s is invalid "
+		    "(must be no greater than %d)",
+		    __func__, val, intface, MAXREACHABLETIME);
+		return (-1);
 	}
-	tmp->reachabletime = (u_int32_t)val;
+	rai->rai_reachabletime = (u_int32_t)val;
 
 	MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER);
 	if (val64 < 0 || val64 > 0xffffffff) {
 		syslog(LOG_ERR, "<%s> retrans time (%lld) on %s out of range",
-		       __func__, (long long)val64, intface);
-		exit(1);
+		    __func__, (long long)val64, intface);
+		return (-1);
 	}
-	tmp->retranstimer = (u_int32_t)val64;
+	rai->rai_retranstimer = (u_int32_t)val64;
 
 	if (agetnum("hapref") != -1 || agetnum("hatime") != -1) {
 		syslog(LOG_ERR,
-		       "<%s> mobile-ip6 configuration not supported",
-		       __func__);
-		exit(1);
+		    "<%s> mobile-ip6 configuration not supported",
+		    __func__);
+		return (-1);
 	}
 	/* prefix information */
 
@@ -271,12 +381,11 @@ getconfig(intface)
 	 * checking consistency of advertised lifetimes.
 	 */
 	MAYHAVE(val, "clockskew", 0);
-	tmp->clockskew = val;
+	rai->rai_clockskew = val;
 
-	tmp->pfxs = 0;
+	rai->rai_pfxs = 0;
 	for (i = -1; i < MAXPREFIX; i++) {
 		struct prefix *pfx;
-		char entbuf[256];
 
 		makeentry(entbuf, sizeof(entbuf), i, "addr");
 		addr = (char *)agetstr(entbuf, &bp);
@@ -284,49 +393,41 @@ getconfig(intface)
 			continue;
 
 		/* allocate memory to store prefix information */
-		if ((pfx = malloc(sizeof(struct prefix))) == NULL) {
-			syslog(LOG_ERR,
-			       "<%s> can't allocate enough memory",
-			       __func__);
-			exit(1);
-		}
-		memset(pfx, 0, sizeof(*pfx));
+		ELM_MALLOC(pfx, exit(1));
 
 		/* link into chain */
-		insque(pfx, &tmp->prefix);
-		tmp->pfxs++;
-		pfx->rainfo = tmp;
-
-		pfx->origin = PREFIX_FROM_CONFIG;
+		TAILQ_INSERT_TAIL(&rai->rai_prefix, pfx, pfx_next);
+		rai->rai_pfxs++;
+		pfx->pfx_origin = PREFIX_FROM_CONFIG;
 
-		if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1) {
+		if (inet_pton(AF_INET6, addr, &pfx->pfx_prefix) != 1) {
 			syslog(LOG_ERR,
-			       "<%s> inet_pton failed for %s",
-			       __func__, addr);
-			exit(1);
+			    "<%s> inet_pton failed for %s",
+			    __func__, addr);
+			return (-1);
 		}
-		if (IN6_IS_ADDR_MULTICAST(&pfx->prefix)) {
+		if (IN6_IS_ADDR_MULTICAST(&pfx->pfx_prefix)) {
 			syslog(LOG_ERR,
-			       "<%s> multicast prefix (%s) must "
-			       "not be advertised on %s",
-			       __func__, addr, intface);
-			exit(1);
+			    "<%s> multicast prefix (%s) must "
+			    "not be advertised on %s",
+			    __func__, addr, intface);
+			return (-1);
 		}
-		if (IN6_IS_ADDR_LINKLOCAL(&pfx->prefix))
+		if (IN6_IS_ADDR_LINKLOCAL(&pfx->pfx_prefix))
 			syslog(LOG_NOTICE,
-			       "<%s> link-local prefix (%s) will be"
-			       " advertised on %s",
-			       __func__, addr, intface);
+			    "<%s> link-local prefix (%s) will be"
+			    " advertised on %s",
+			    __func__, addr, intface);
 
 		makeentry(entbuf, sizeof(entbuf), i, "prefixlen");
 		MAYHAVE(val, entbuf, 64);
 		if (val < 0 || val > 128) {
 			syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s "
-			       "on %s out of range",
-			       __func__, val, addr, intface);
-			exit(1);
+			    "on %s out of range",
+			    __func__, val, addr, intface);
+			return (-1);
 		}
-		pfx->prefixlen = (int)val;
+		pfx->pfx_prefixlen = (int)val;
 
 		makeentry(entbuf, sizeof(entbuf), i, "pinfoflags");
 		if ((flagstr = (char *)agetstr(entbuf, &bp))) {
@@ -339,8 +440,8 @@ getconfig(intface)
 			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;
+		pfx->pfx_onlinkflg = val & ND_OPT_PI_FLAG_ONLINK;
+		pfx->pfx_autoconfflg = val & ND_OPT_PI_FLAG_AUTO;
 
 		makeentry(entbuf, sizeof(entbuf), i, "vltime");
 		MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
@@ -348,17 +449,17 @@ getconfig(intface)
 			syslog(LOG_ERR, "<%s> vltime (%lld) for "
 			    "%s/%d on %s is out of range",
 			    __func__, (long long)val64,
-			    addr, pfx->prefixlen, intface);
-			exit(1);
+			    addr, pfx->pfx_prefixlen, intface);
+			return (-1);
 		}
-		pfx->validlifetime = (u_int32_t)val64;
+		pfx->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;
+			pfx->pfx_vltimeexpire =
+				now.tv_sec + pfx->pfx_validlifetime;
 		}
 
 		makeentry(entbuf, sizeof(entbuf), i, "pltime");
@@ -368,44 +469,45 @@ getconfig(intface)
 			    "<%s> pltime (%lld) for %s/%d on %s "
 			    "is out of range",
 			    __func__, (long long)val64,
-			    addr, pfx->prefixlen, intface);
-			exit(1);
+			    addr, pfx->pfx_prefixlen, intface);
+			return (-1);
 		}
-		pfx->preflifetime = (u_int32_t)val64;
+		pfx->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;
+			pfx->pfx_pltimeexpire =
+			    now.tv_sec + pfx->pfx_preflifetime;
 		}
 	}
-	if (tmp->pfxs == 0)
-		get_prefix(tmp);
+	if (rai->rai_advifprefix && rai->rai_pfxs == 0)
+		get_prefix(rai);
 
 	MAYHAVE(val, "mtu", 0);
-	if (val < 0 || val > 0xffffffff) {
+	if (val < 0 || (u_int)val > 0xffffffff) {
 		syslog(LOG_ERR,
-		       "<%s> mtu (%ld) on %s out of range",
-		       __func__, val, intface);
-		exit(1);
+		    "<%s> mtu (%ld) on %s out of range",
+		    __func__, val, intface);
+		return (-1);
 	}
-	tmp->linkmtu = (u_int32_t)val;
-	if (tmp->linkmtu == 0) {
+	rai->rai_linkmtu = (u_int32_t)val;
+	if (rai->rai_linkmtu == 0) {
 		char *mtustr;
 
 		if ((mtustr = (char *)agetstr("mtu", &bp)) &&
 		    strcmp(mtustr, "auto") == 0)
-			tmp->linkmtu = tmp->phymtu;
+			rai->rai_linkmtu = rai->rai_phymtu;
 	}
-	else if (tmp->linkmtu < IPV6_MMTU || tmp->linkmtu > tmp->phymtu) {
+	else if (rai->rai_linkmtu < IPV6_MMTU ||
+	    rai->rai_linkmtu > rai->rai_phymtu) {
 		syslog(LOG_ERR,
-		       "<%s> advertised link mtu (%lu) on %s is invalid (must "
-		       "be between least MTU (%d) and physical link MTU (%d)",
-		       __func__, (unsigned long)tmp->linkmtu, intface,
-		       IPV6_MMTU, tmp->phymtu);
-		exit(1);
+		    "<%s> advertised link mtu (%lu) on %s is invalid (must "
+		    "be between least MTU (%d) and physical link MTU (%d)",
+		    __func__, (unsigned long)rai->rai_linkmtu, intface,
+		    IPV6_MMTU, rai->rai_phymtu);
+		return (-1);
 	}
 
 #ifdef SIOCSIFINFO_IN6
@@ -415,65 +517,56 @@ getconfig(intface)
 
 		if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
 			syslog(LOG_ERR, "<%s> socket: %s", __func__,
-			       strerror(errno));
+			    strerror(errno));
 			exit(1);
 		}
 		memset(&ndi, 0, sizeof(ndi));
 		strncpy(ndi.ifname, intface, IFNAMSIZ);
-		if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&ndi) < 0) {
+		if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&ndi) < 0)
 			syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %s",
-			     __func__, intface, strerror(errno));
-		}
+			    __func__, intface, strerror(errno));
 
 		/* reflect the RA info to the host variables in kernel */
-		ndi.ndi.chlim = tmp->hoplimit;
-		ndi.ndi.retrans = tmp->retranstimer;
-		ndi.ndi.basereachable = tmp->reachabletime;
-		if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&ndi) < 0) {
+		ndi.ndi.chlim = rai->rai_hoplimit;
+		ndi.ndi.retrans = rai->rai_retranstimer;
+		ndi.ndi.basereachable = rai->rai_reachabletime;
+		if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&ndi) < 0)
 			syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %s",
-			     __func__, intface, strerror(errno));
-		}
+			    __func__, intface, strerror(errno));
+
 		close(s);
 	}
 #endif
 
 	/* route information */
 #ifdef ROUTEINFO
-	tmp->routes = 0;
+	rai->rai_routes = 0;
 	for (i = -1; i < MAXROUTE; i++) {
 		struct rtinfo *rti;
-		char entbuf[256], oentbuf[256];
 
 		makeentry(entbuf, sizeof(entbuf), i, "rtprefix");
 		addr = (char *)agetstr(entbuf, &bp);
 		if (addr == NULL) {
 			makeentry(oentbuf, sizeof(oentbuf), i, "rtrprefix");
 			addr = (char *)agetstr(oentbuf, &bp);
-			if (addr) {
+			if (addr)
 				fprintf(stderr, "%s was obsoleted.  Use %s.\n",
-					oentbuf, entbuf);
-			}
+				    oentbuf, entbuf);
 		}
 		if (addr == NULL)
 			continue;
 
 		/* allocate memory to store prefix information */
-		if ((rti = malloc(sizeof(struct rtinfo))) == NULL) {
-			syslog(LOG_ERR,
-			       "<%s> can't allocate enough memory",
-			       __func__);
-			exit(1);
-		}
-		memset(rti, 0, sizeof(*rti));
+		ELM_MALLOC(rti, exit(1));
 
 		/* link into chain */
-		insque(rti, &tmp->route);
-		tmp->routes++;
+		TAILQ_INSERT_TAIL(&rai->rai_route, rti, rti_next);
+		rai->rai_routes++;
 
-		if (inet_pton(AF_INET6, addr, &rti->prefix) != 1) {
+		if (inet_pton(AF_INET6, addr, &rti->rti_prefix) != 1) {
 			syslog(LOG_ERR, "<%s> inet_pton failed for %s",
-			       __func__, addr);
-			exit(1);
+			    __func__, addr);
+			return (-1);
 		}
 #if 0
 		/*
@@ -485,17 +578,17 @@ getconfig(intface)
 		MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
 		if (IN6_IS_ADDR_MULTICAST(&rti->prefix)) {
 			syslog(LOG_ERR,
-			       "<%s> multicast route (%s) must "
-			       "not be advertised on %s",
-			       __func__, addr, intface);
-			exit(1);
+			    "<%s> multicast route (%s) must "
+			    "not be advertised on %s",
+			    __func__, addr, intface);
+			return (-1);
 		}
 		if (IN6_IS_ADDR_LINKLOCAL(&rti->prefix)) {
 			syslog(LOG_NOTICE,
-			       "<%s> link-local route (%s) will "
-			       "be advertised on %s",
-			       __func__, addr, intface);
-			exit(1);
+			    "<%s> link-local route (%s) will "
+			    "be advertised on %s",
+			    __func__, addr, intface);
+			return (-1);
 		}
 #endif
 
@@ -505,19 +598,19 @@ getconfig(intface)
 		if (val == 256) {
 			makeentry(oentbuf, sizeof(oentbuf), i, "rtrplen");
 			MAYHAVE(val, oentbuf, 256);
-			if (val != 256) {
+			if (val != 256)
 				fprintf(stderr, "%s was obsoleted.  Use %s.\n",
-					oentbuf, entbuf);
-			} else
+				    oentbuf, entbuf);
+			else
 				val = 64;
 		}
 		if (val < 0 || val > 128) {
 			syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s on %s "
-			       "out of range",
-			       __func__, val, addr, intface);
-			exit(1);
+			    "out of range",
+			    __func__, val, addr, intface);
+			return (-1);
 		}
-		rti->prefixlen = (int)val;
+		rti->rti_prefixlen = (int)val;
 
 		makeentry(entbuf, sizeof(entbuf), i, "rtflags");
 		if ((flagstr = (char *)agetstr(entbuf, &bp))) {
@@ -541,17 +634,17 @@ getconfig(intface)
 			MAYHAVE(val, oentbuf, 256);
 			if (val != 256) {
 				fprintf(stderr, "%s was obsoleted.  Use %s.\n",
-					oentbuf, entbuf);
+				    oentbuf, entbuf);
 			} else
 				val = 0;
 		}
-		rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
-		if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+		rti->rti_rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+		if (rti->rti_rtpref == ND_RA_FLAG_RTPREF_RSV) {
 			syslog(LOG_ERR, "<%s> invalid route preference (%02x) "
-			       "for %s/%d on %s",
-			       __func__, rti->rtpref, addr,
-			       rti->prefixlen, intface);
-			exit(1);
+			    "for %s/%d on %s",
+			    __func__, rti->rti_rtpref, addr,
+			    rti->rti_prefixlen, intface);
+			return (-1);
 		}
 
 		/*
@@ -565,60 +658,143 @@ getconfig(intface)
 		if (val64 == -1) {
 			makeentry(oentbuf, sizeof(oentbuf), i, "rtrltime");
 			MAYHAVE(val64, oentbuf, -1);
-			if (val64 != -1) {
+			if (val64 != -1)
 				fprintf(stderr, "%s was obsoleted.  Use %s.\n",
-					oentbuf, entbuf);
-			} else {
+				    oentbuf, entbuf);
+			else {
 				fprintf(stderr, "%s should be specified "
-					"for interface %s.\n",
-					entbuf, intface);
-				val64 = tmp->lifetime;
+				    "for interface %s.\n", entbuf, intface);

*** 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-unsubscribe@freebsd.org"
Comment 4 Hiroki Sato freebsd_committer freebsd_triage 2011-06-06 04:38:07 UTC
State Changed
From-To: open->feedback

A new directive "noifprefix" is added.  It will be great if you could try it 
and let me know if it works or not for your purpose.  Thank you.
Comment 5 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 07:58:25 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped
Comment 6 Oleksandr Tymoshenko freebsd_committer freebsd_triage 2019-01-19 20:00:47 UTC
There was a commit referencing this bug, but it's still not closed and has been inactive for some time. Closing as "fixed". Please re-open it if the issue hasn't been completely resolved.