bin/144343: The rtadvd cannot avoid the prefix that doesn't want to advertise.

Tatsuki Makino tatsuki_makino at hotmail.com
Sat Feb 27 11:50:02 UTC 2010


>Number:         144343
>Category:       bin
>Synopsis:       The rtadvd cannot avoid the prefix that doesn't want to advertise.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat Feb 27 11:50:01 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Tatsuki Makino
>Release:        FreeBSD 6.4-RELEASE-p9 i386
>Organization:
>Environment:
FreeBSD T0.test 6.4-RELEASE-p9 FreeBSD 6.4-RELEASE-p9 #0: Thu Jan  7 11:28:17 GMT 2010     root at T0.test:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
When one network interface has 2 prefixes or more, all prefixes are advertised. I don't hope for it.
When choice prefixes to advertise by configuration file, it is limited only to static prefixes. I want also to advertise dynamic prefix.
>How-To-Repeat:
-- Host T0:

 /etc/rc.conf (snipped)
 ipv6_gateway_enable="YES"
 rtadvd_enable="YES"
 rtadvd_interfaces="rl0"

 rl0 has these addresses as follows
 inet6 2001:db8:0:0::0 prefixlen 64 # fixed
 inet6 2001:db8:0:1:: prefixlen 64 # add or remove dynamically
 inet6 2001:db8:0:2:: prefixlen 64 # add or remove dynamically
 inet6 2001:db8:0:3:: prefixlen 64 # add or remove dynamically
 (snip)
 inet6 2001:db8:0:ffff:: prefixlen 64 # add or remove dynamically

--

-- Host T2:

 /etc/sysctl.conf (snipped)
 net.inet6.ip6.use_tempaddr=1
 net.inet6.ip6.prefer_tempaddr=1

 rl0 has these addresses as follows
 ether XX:XX:XX:XX:XX:XX
 inet6 2001:db8:0:0::1 prefixlen 64 # fixed (A)
 inet6 2001:db8:0:0:XXXX:XXff:feXX:XXXX prefixlen 64 # or this (B)

--

rl0 on T0 and rl0 on T2 are connected via cable.
When T2 used inet6 address (A), T2 generate tempaddr. I don't want to tempaddr for 2001:db8:0:0/64.
When T2 used inet6 address (B), T2 log a lot of messages as "in6_ifadd: 2001:db8::XXXX:XXff:feXX:XXXX is already configured".
>Fix:
Patch it (written for 6.4-RELEASE).
Build and install.
Configure /etc/rtadvd.conf as follows

rl0:\
 :ignoreaddr="2001:db8::":ignoreprefixlen#8:

Start rtadvd.

I don't know it is useful for you...
If it is not useful for you, close this PR immediately.

Patch attached with submission follows:

diff -u -r -N -d /usr/src/usr.sbin/rtadvd/config.c usr.sbin/rtadvd/config.c
--- /usr/src/usr.sbin/rtadvd/config.c	2008-10-02 02:57:24.000000000 +0000
+++ usr.sbin/rtadvd/config.c	2010-02-27 08:06:36.000000000 +0000
@@ -123,6 +123,7 @@
 #ifdef ROUTEINFO
 	tmp->route.next = tmp->route.prev = &tmp->route;
 #endif
+	tmp->ignore_prefix.next = tmp->ignore_prefix.prev = &tmp->ignore_prefix;
 
 	/* check if we are allowed to forward packets (if not determined) */
 	if (forwarding < 0) {
@@ -381,6 +382,51 @@
 				now.tv_sec + pfx->preflifetime;
 		}
 	}
+	/* ignore prefix */
+	tmp->ignore_pfxs = 0;
+	for (i = -1; i < MAXPREFIX; i++) {
+		struct prefix *pfx;
+		char entbuf[256];
+
+		makeentry(entbuf, sizeof(entbuf), i, "ignoreaddr");
+		addr = (char *)agetstr(entbuf, &bp);
+		if (addr == NULL)
+			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));
+
+		/* link into chain */
+		insque(pfx, &tmp->ignore_prefix);
+		tmp->ignore_pfxs++;
+		pfx->rainfo = tmp;
+
+		pfx->origin = PREFIX_FROM_CONFIG;
+
+		if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1) {
+			syslog(LOG_ERR,
+			       "<%s> inet_pton failed for %s",
+			       __func__, addr);
+			exit(1);
+		}
+
+		makeentry(entbuf, sizeof(entbuf), i, "ignoreprefixlen");
+		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);
+		}
+		pfx->prefixlen = (int)val;
+
+	}
 	if (tmp->pfxs == 0)
 		get_prefix(tmp);
 
@@ -641,6 +687,10 @@
 			/* ignore a duplicated prefix. */
 			continue;
 		}
+		if (find_ignore_prefix(rai, a, plen)) {
+			/* ignore a ignored prefix. */
+			continue;
+		}
 
 		/* allocate memory to store prefix info. */
 		if ((pp = malloc(sizeof(*pp))) == NULL) {
diff -u -r -N -d /usr/src/usr.sbin/rtadvd/rtadvd.c usr.sbin/rtadvd/rtadvd.c
--- /usr/src/usr.sbin/rtadvd/rtadvd.c	2008-10-02 02:57:24.000000000 +0000
+++ usr.sbin/rtadvd/rtadvd.c	2010-02-26 16:17:07.000000000 +0000
@@ -490,6 +490,18 @@
 				    __func__, plen);
 				break;
 			}
+			if (find_ignore_prefix(rai, addr, plen)) {
+				if (dflag > 1) {
+					syslog(LOG_DEBUG,
+					    "<%s> new prefix(%s/%d) "
+					    "ignored on %s",
+					    __func__,
+					    inet_ntop(AF_INET6, addr,
+					    (char *)addrbuf, INET6_ADDRSTRLEN),
+					    plen, rai->ifname);
+				}
+				break;
+			}
 			prefix = find_prefix(rai, addr, plen);
 			if (prefix) {
 				if (prefix->timer) {
@@ -1263,6 +1275,20 @@
 	return(0);
 }
 
+struct prefix *
+find_ignore_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen)
+{
+	struct prefix *pp;
+
+	for (pp = rai->ignore_prefix.next; pp != &rai->ignore_prefix; pp = pp->next) {
+		if (prefix_match(prefix, plen, &pp->prefix, pp->prefixlen)) {
+			return pp;
+		}
+	}
+
+	return(NULL);
+}
+
 static int
 nd6_options(struct nd_opt_hdr *hdr, int limit,
 	    union nd_opts *ndopts, u_int32_t optflags)
diff -u -r -N -d /usr/src/usr.sbin/rtadvd/rtadvd.h usr.sbin/rtadvd/rtadvd.h
--- /usr/src/usr.sbin/rtadvd/rtadvd.h	2008-10-02 02:57:24.000000000 +0000
+++ usr.sbin/rtadvd/rtadvd.h	2010-02-26 16:11:21.000000000 +0000
@@ -149,6 +149,10 @@
 
 	/* info about soliciter */
 	struct soliciter *soliciter;	/* recent solication source */
+
+	/* prefixes not advertised */
+	struct prefix ignore_prefix;	/* AdvPrefixList(link head) */
+	int	ignore_pfxs;		/* number of prefixes */
 };
 
 struct rtadvd_timer *ra_timeout __P((void *));
@@ -157,5 +161,6 @@
 int prefix_match __P((struct in6_addr *, int, struct in6_addr *, int));
 struct rainfo *if_indextorainfo __P((int));
 struct prefix *find_prefix __P((struct rainfo *, struct in6_addr *, int));
+struct prefix *find_ignore_prefix __P((struct rainfo *, struct in6_addr *, int));
 
 extern struct in6_addr in6a_site_allrouters;


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list