changeset 1811:1de83da1e5a1 draft

Respect AUTO and ONLINK flags for each prefix in the RA.
author Roy Marples <roy@marples.name>
date Tue, 11 Dec 2012 08:45:33 +0000
parents d2a966e2a741
children 4a3829cb4406
files ipv6.c ipv6.h ipv6rs.c
diffstat 3 files changed, 43 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/ipv6.c	Thu Dec 06 10:53:42 2012 +0000
+++ b/ipv6.c	Tue Dec 11 08:45:33 2012 +0000
@@ -384,7 +384,11 @@
 #else
 		if (!find_route6(routes, rt))
 #endif
+		{
 			r = del_route6(rt);
+			if (r == -1 && errno == ESRCH)
+				r = 0;
+		}
 		free(rt);
 	}
 	return r;
@@ -410,6 +414,8 @@
 	TAILQ_FOREACH(rap, &ipv6_routers, next) {
 		if (options & DHCPCD_IPV6RA_OWN) {
 			TAILQ_FOREACH(addr, &rap->addrs, next) {
+				if (!addr->onlink)
+					continue;
 				rt = make_prefix(rap, addr);
 				if (rt)
 					TAILQ_INSERT_TAIL(&dnr, rt, next);
--- a/ipv6.h	Thu Dec 06 10:53:42 2012 +0000
+++ b/ipv6.h	Tue Dec 11 08:45:33 2012 +0000
@@ -46,7 +46,8 @@
 	uint32_t prefix_vltime;
 	uint32_t prefix_pltime;
 	struct in6_addr addr;
-	int new;
+	uint8_t onlink;
+	uint8_t new;
 	char saddr[INET6_ADDRSTRLEN];
 };
 
--- a/ipv6rs.c	Thu Dec 06 10:53:42 2012 +0000
+++ b/ipv6rs.c	Tue Dec 11 08:45:33 2012 +0000
@@ -291,6 +291,7 @@
 		 * This is safe because the RA is removed from the list
 		 * before we are called. */
 		if (drop && (options & DHCPCD_IPV6RA_OWN) &&
+		    !IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
 		    !ipv6rs_addrexists(ap))
 		{
 			syslog(LOG_INFO, "%s: deleting address %s",
@@ -568,21 +569,41 @@
 				    sizeof(ap->prefix.s6_addr)) == 0)
 					break;
 			if (ap == NULL) {
+				/* As we haven't added the prefix before
+				 * check if we can make an address with it */
+				if (!(pi->nd_opt_pi_flags_reserved &
+				    ND_OPT_PI_FLAG_AUTO) &&
+				    !(pi->nd_opt_pi_flags_reserved &
+				    ND_OPT_PI_FLAG_ONLINK))
+					break;
 				ap = xmalloc(sizeof(*ap));
 				ap->new = 1;
+				ap->onlink = 0;
 				ap->prefix_len = pi->nd_opt_pi_prefix_len;
 				memcpy(ap->prefix.s6_addr,
 				   pi->nd_opt_pi_prefix.s6_addr,
 				   sizeof(ap->prefix.s6_addr));
-				ipv6_makeaddr(&ap->addr, ifp->name,
-				    &ap->prefix, pi->nd_opt_pi_prefix_len);
-				cbp = inet_ntop(AF_INET6, ap->addr.s6_addr,
-				    ntopbuf, INET6_ADDRSTRLEN);
-				if (cbp)
-					snprintf(ap->saddr, sizeof(ap->saddr),
-					    "%s/%d", cbp, ap->prefix_len);
-				else
+				if (pi->nd_opt_pi_flags_reserved &
+				    ND_OPT_PI_FLAG_AUTO)
+				{
+					ipv6_makeaddr(&ap->addr, ifp->name,
+					    &ap->prefix,
+					    pi->nd_opt_pi_prefix_len);
+					cbp = inet_ntop(AF_INET6,
+					    ap->addr.s6_addr,
+					    ntopbuf, INET6_ADDRSTRLEN);
+					if (cbp)
+						snprintf(ap->saddr,
+						    sizeof(ap->saddr),
+						    "%s/%d",
+						    cbp, ap->prefix_len);
+					else
+						ap->saddr[0] = '\0';
+				} else {
+					memset(ap->addr.s6_addr, 0,
+					    sizeof(ap->addr.s6_addr));
 					ap->saddr[0] = '\0';
+				}
 				TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
 			} else if (ap->prefix_vltime !=
 			    ntohl(pi->nd_opt_pi_valid_time) ||
@@ -591,6 +612,10 @@
 				ap->new = 1;
 			else
 				ap->new = 0;
+			/* onlink should not change from on to off */
+			if (pi->nd_opt_pi_flags_reserved &
+			    ND_OPT_PI_FLAG_ONLINK)
+				ap->onlink = 1;
 			ap->prefix_vltime =
 			    ntohl(pi->nd_opt_pi_valid_time);
 			ap->prefix_pltime =
@@ -722,7 +747,8 @@
 		add_router(rap);
 	if (options & DHCPCD_IPV6RA_OWN && !(options & DHCPCD_TEST)) {
 		TAILQ_FOREACH(ap, &rap->addrs, next) {
-			if (ap->prefix_vltime == 0)
+			if (ap->prefix_vltime == 0 ||
+			    IN6_IS_ADDR_UNSPECIFIED(&ap->addr))
 				continue;
 			syslog(ap->new ? LOG_INFO : LOG_DEBUG,
 			    "%s: adding address %s",