From: Roy Marples Date: Wed, 14 Nov 2012 10:30:30 +0000 (+0000) Subject: Merge multiple options together as per RFC4861 section 6.3.4 X-Git-Tag: v5.6.3~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=560c572f2b53a84a73005d350862f1d376db0557;p=thirdparty%2Fdhcpcd.git Merge multiple options together as per RFC4861 section 6.3.4 --- diff --git a/ipv6rs.c b/ipv6rs.c index d5112f9e..7449de7e 100644 --- a/ipv6rs.c +++ b/ipv6rs.c @@ -756,6 +756,8 @@ handle_flag: if (new_data) syslog(LOG_WARNING, "%s: no support for DHCPv6 management", ifp->name); + if (options & DHCPCD_TEST) + exit(EXIT_SUCCESS); // if (dhcp6_start(ifp, 1) == -1) // syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name); } else if (rap->flags & ND_RA_FLAG_OTHER) { @@ -765,11 +767,12 @@ handle_flag: if (new_data) syslog(LOG_DEBUG, "%s: No DHCPv6 instruction in RA", ifp->name); + if (options & DHCPCD_TEST) + exit(EXIT_SUCCESS); } /* Expire should be called last as the rap object could be destroyed */ - if (!(options & DHCPCD_TEST)) - ipv6rs_expire(ifp); + ipv6rs_expire(ifp); } int @@ -793,9 +796,11 @@ ipv6rs_env(char **env, const char *prefix, const struct interface *ifp) int i; char buffer[32]; const char *optn; + char **pref, **mtu, **rdnss, **dnssl, ***var, *new; i = 0; l = 0; + pref = rdnss = dnssl = NULL; get_monotonic(&now); TAILQ_FOREACH(rap, &ipv6_routers, next) { i++; @@ -811,27 +816,46 @@ ipv6rs_env(char **env, const char *prefix, const struct interface *ifp) TAILQ_FOREACH(rao, &rap->options, next) { if (rao->option == NULL) continue; - l++; - if (env == NULL) - continue; switch (rao->type) { case ND_OPT_PREFIX_INFORMATION: optn = "prefix"; + var = &pref; break; case ND_OPT_MTU: optn = "mtu"; + var = &mtu; break; case ND_OPT_RDNSS: optn = "rdnss"; + var = &rdnss; break; case ND_OPT_DNSSL: optn = "dnssl"; + var = &dnssl; break; default: continue; } - snprintf(buffer, sizeof(buffer), "ra%d_%s", i, optn); - setvar(&env, prefix, buffer, rao->option); + if (*var == NULL) { + *var = env ? env : &new; + l++; + } else if (env) { + new = realloc(**var, + strlen(**var) + 1 + + strlen(rao->option) + 1); + if (new) { + **var = new; + new += strlen(new); + *new++ = ' '; + strcpy(new, rao->option); + continue; + } + } + if (env) { + snprintf(buffer, sizeof(buffer), + "ra%d_%s", i, optn); + setvar(&env, prefix, buffer, rao->option); + } } } @@ -865,7 +889,7 @@ ipv6rs_expire(void *arg) struct ipv6_addr *ap, *apn; struct ra_opt *rao, *raon; struct timeval now, lt, expire, next; - int expired; + int expired, valid; ifp = arg; get_monotonic(&now); @@ -879,6 +903,7 @@ ipv6rs_expire(void *arg) lt.tv_usec = 0; timeradd(&rap->received, <, &expire); if (timercmp(&now, &expire, >)) { + valid = 0; if (!rap->expired) { syslog(LOG_INFO, "%s: %s: expired default Router", @@ -886,6 +911,7 @@ ipv6rs_expire(void *arg) rap->expired = expired = 1; } } else { + valid = 1; timersub(&expire, &now, <); if (!timerisset(&next) || timercmp(&next, <, >)) next = lt; @@ -925,10 +951,16 @@ ipv6rs_expire(void *arg) free(rao); continue; } + valid = 1; timersub(&rao->expire, &now, <); if (!timerisset(&next) || timercmp(&next, <, >)) next = lt; } + + /* No valid lifetimes are left on the RA, so we might + * as well punt it. */ + if (!valid) + ipv6rs_free_ra(rap); } if (timerisset(&next))