From: Roy Marples Date: Sat, 7 Sep 2013 23:16:36 +0000 (+0000) Subject: Fix requesting >1 DHCPv6 address X-Git-Tag: v6.1.0~18 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7cece083bdc00e50c54af0c487adf34d7ed97eef;p=thirdparty%2Fdhcpcd.git Fix requesting >1 DHCPv6 address --- diff --git a/dhcp6.c b/dhcp6.c index 76a7328b..fc0e7ca3 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -1447,6 +1447,11 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l, ifo = ifp->options; i = 0; state = D6_STATE(ifp); + if (ifo->ia_type != D6_OPTION_IA_PD) { + TAILQ_FOREACH(ap, &state->addrs, next) { + ap->flags |= IPV6_AF_STALE; + } + } while ((o = dhcp6_findoption(ifo->ia_type, d, l))) { l -= ((const uint8_t *)o - d); d += ((const uint8_t *)o - d); @@ -1499,27 +1504,26 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l, return -1; } } else { - TAILQ_FOREACH(ap, &state->addrs, next) { - ap->flags |= IPV6_AF_STALE; - } if (dhcp6_findna(ifp, iaid, p, ol) == 0) { syslog(LOG_ERR, "%s: %s: DHCPv6 REPLY missing IA Address", ifp->name, sfrom); return -1; } - TAILQ_FOREACH_SAFE(ap, &state->addrs, next, nap) { - if (ap->flags & IPV6_AF_STALE) { - TAILQ_REMOVE(&state->addrs, ap, next); - if (ap->dadcallback) - eloop_q_timeout_delete(0, NULL, - ap->dadcallback); - free(ap); - } - } } i++; } + if (ifo->ia_type != D6_OPTION_IA_PD) { + TAILQ_FOREACH_SAFE(ap, &state->addrs, next, nap) { + if (ap->flags & IPV6_AF_STALE) { + TAILQ_REMOVE(&state->addrs, ap, next); + if (ap->dadcallback) + eloop_q_timeout_delete(0, NULL, + ap->dadcallback); + free(ap); + } + } + } return i; } diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index 5594e7d7..08404125 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 31, 2013 +.Dd September 7, 2013 .Dt DHCPCD.CONF 5 SMM .Os .Sh NAME @@ -170,9 +170,11 @@ If none is specified, a default is used. If the interface name is 4 characters or less then that is used, otherwise the interface index is used. +You can request more than one ia_na by specifying a unique iaid for each one. .It Ic ia_ta Op Ar iaid Request a DHCPv6 Temporary Address for .Ar iaid . +You can request more than one ia_ta by specifying a unique iaid for each one. .It Ic ia_pd Op Ar iaid Op Ar interface Op / Ar sla_id Op / Ar prefix_len Request a DHCPv6 Delegated Prefix for .Ar iaid . diff --git a/if-options.c b/if-options.c index 11c4f70c..858fad96 100644 --- a/if-options.c +++ b/if-options.c @@ -1022,6 +1022,8 @@ got_iaid: iaid->sla = NULL; iaid->sla_len = 0; } + if (ifo->ia_type != D6_OPTION_IA_PD) + break; for (p = fp; p; p = fp) { fp = strchr(p, ' '); if (fp) diff --git a/ipv6nd.c b/ipv6nd.c index 2c0569a4..b424b953 100644 --- a/ipv6nd.c +++ b/ipv6nd.c @@ -145,6 +145,8 @@ static struct icmp6_filter filt; struct rahead ipv6_routers = TAILQ_HEAD_INITIALIZER(ipv6_routers); +static void ipv6nd_handledata(void *arg); + #if DEBUG_MEMORY static void ipv6nd_cleanup(void) @@ -265,6 +267,12 @@ ipv6nd_naopen(void) goto eexit; #endif + if (sock == -1) { + if (ipv6nd_open() == -1) + goto eexit; + eloop_event_add(sock, ipv6nd_handledata, NULL); + } + ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt); if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt)) == -1) @@ -280,6 +288,7 @@ ipv6nd_naopen(void) return sock; eexit: + syslog(LOG_ERR, "%s: %m", __func__); #ifdef IPV6_SEND_DAD close(unspec_sock); unspec_sock = -1; @@ -1749,7 +1758,7 @@ ipv6nd_handledata(__unused void *arg) return; } } - + syslog(LOG_ERR, "invalid IPv6 type %d or code %d from %s", icp->icmp6_type, icp->icmp6_code, sfrom); } @@ -1792,5 +1801,3 @@ ipv6nd_startrs(struct interface *ifp) ipv6nd_sendrsprobe(ifp); return 0; } - -