summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2012-12-11 08:45:33 +0000
committerRoy Marples <roy@marples.name>2012-12-11 08:45:33 +0000
commit3bd74cd01b6362d69e9bc3a008894fea65cc7fc8 (patch)
treede083fcebd127592b72d115f262f94fd2c7ceaa0
parent93c4152d3d5cad8b5cec0a8c07a2d41e5196f065 (diff)
downloaddhcpcd-3bd74cd01b6362d69e9bc3a008894fea65cc7fc8.tar.xz
Respect AUTO and ONLINK flags for each prefix in the RA.
-rw-r--r--ipv6.c6
-rw-r--r--ipv6.h3
-rw-r--r--ipv6rs.c44
3 files changed, 43 insertions, 10 deletions
diff --git a/ipv6.c b/ipv6.c
index 793cf6b8..c20d98ad 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -384,7 +384,11 @@ ipv6_remove_subnet(struct ra *rap, struct ipv6_addr *addr)
#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 @@ ipv6_build_routes(void)
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);
diff --git a/ipv6.h b/ipv6.h
index ef3b2352..7f889bc2 100644
--- a/ipv6.h
+++ b/ipv6.h
@@ -46,7 +46,8 @@ struct ipv6_addr {
uint32_t prefix_vltime;
uint32_t prefix_pltime;
struct in6_addr addr;
- int new;
+ uint8_t onlink;
+ uint8_t new;
char saddr[INET6_ADDRSTRLEN];
};
diff --git a/ipv6rs.c b/ipv6rs.c
index f48d01c7..d4877a9c 100644
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -291,6 +291,7 @@ ipv6rs_freedrop_addrs(struct ra *rap, int drop)
* 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 @@ ipv6rs_handledata(_unused void *arg)
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 @@ ipv6rs_handledata(_unused void *arg)
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 @@ ipv6rs_handledata(_unused void *arg)
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",