Module Name: src Committed By: roy Date: Wed Oct 29 01:08:31 UTC 2014
Modified Files: src/external/bsd/dhcpcd/dist: arp.c arp.h auth.c auth.h bpf-filter.h common.c common.h config.h control.c control.h defs.h dev.h dhcp-common.c dhcp-common.h dhcp.c dhcp.h dhcp6.c dhcp6.h dhcpcd-definitions.conf dhcpcd-embedded.c dhcpcd-embedded.h dhcpcd-run-hooks.8.in dhcpcd-run-hooks.in dhcpcd.8.in dhcpcd.c dhcpcd.conf dhcpcd.conf.5.in dhcpcd.h duid.c duid.h eloop.c eloop.h if-bsd.c if-options.c if-options.h if.c if.h ipv4.c ipv4.h ipv4ll.c ipv4ll.h ipv6.c ipv6.h ipv6nd.c ipv6nd.h script.c script.h Log Message: Sync To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/external/bsd/dhcpcd/dist/arp.c \ src/external/bsd/dhcpcd/dist/arp.h src/external/bsd/dhcpcd/dist/auth.c \ src/external/bsd/dhcpcd/dist/auth.h src/external/bsd/dhcpcd/dist/common.c \ src/external/bsd/dhcpcd/dist/common.h \ src/external/bsd/dhcpcd/dist/config.h \ src/external/bsd/dhcpcd/dist/control.c \ src/external/bsd/dhcpcd/dist/control.h \ src/external/bsd/dhcpcd/dist/defs.h src/external/bsd/dhcpcd/dist/dev.h \ src/external/bsd/dhcpcd/dist/dhcp-common.c \ src/external/bsd/dhcpcd/dist/dhcp-common.h \ src/external/bsd/dhcpcd/dist/dhcp.h src/external/bsd/dhcpcd/dist/dhcp6.c \ src/external/bsd/dhcpcd/dist/dhcp6.h \ src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf \ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c \ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h \ src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in \ src/external/bsd/dhcpcd/dist/dhcpcd.h src/external/bsd/dhcpcd/dist/duid.c \ src/external/bsd/dhcpcd/dist/duid.h src/external/bsd/dhcpcd/dist/eloop.c \ src/external/bsd/dhcpcd/dist/eloop.h \ src/external/bsd/dhcpcd/dist/if-options.h \ src/external/bsd/dhcpcd/dist/if.c src/external/bsd/dhcpcd/dist/if.h \ src/external/bsd/dhcpcd/dist/ipv4.c src/external/bsd/dhcpcd/dist/ipv4.h \ src/external/bsd/dhcpcd/dist/ipv4ll.c \ src/external/bsd/dhcpcd/dist/ipv4ll.h src/external/bsd/dhcpcd/dist/ipv6.c \ src/external/bsd/dhcpcd/dist/ipv6.h src/external/bsd/dhcpcd/dist/ipv6nd.h \ src/external/bsd/dhcpcd/dist/script.h cvs rdiff -u -r1.6 -r1.7 src/external/bsd/dhcpcd/dist/bpf-filter.h cvs rdiff -u -r1.19 -r1.20 src/external/bsd/dhcpcd/dist/dhcp.c cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in cvs rdiff -u -r1.33 -r1.34 src/external/bsd/dhcpcd/dist/dhcpcd.8.in cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/dhcpcd.c \ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in cvs rdiff -u -r1.12 -r1.13 src/external/bsd/dhcpcd/dist/dhcpcd.conf \ src/external/bsd/dhcpcd/dist/if-bsd.c cvs rdiff -u -r1.14 -r1.15 src/external/bsd/dhcpcd/dist/if-options.c \ src/external/bsd/dhcpcd/dist/ipv6nd.c cvs rdiff -u -r1.11 -r1.12 src/external/bsd/dhcpcd/dist/script.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/dhcpcd/dist/arp.c diff -u src/external/bsd/dhcpcd/dist/arp.c:1.3 src/external/bsd/dhcpcd/dist/arp.c:1.4 --- src/external/bsd/dhcpcd/dist/arp.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/arp.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: arp.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: arp.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -42,7 +42,7 @@ #include <syslog.h> #include <unistd.h> -#define ELOOP_QUEUE 2 +#define ELOOP_QUEUE 5 #include "config.h" #include "arp.h" #include "ipv4.h" @@ -97,31 +97,15 @@ eexit: return -1; } -static void -arp_failure(struct interface *ifp) +void +arp_report_conflicted(const struct arp_state *astate, const struct arp_msg *amsg) { - const struct dhcp_state *state = D_CSTATE(ifp); - - /* If we failed without a magic cookie then we need to try - * and defend our IPv4LL address. */ - if ((state->offer != NULL && - state->offer->cookie != htonl(MAGIC_COOKIE)) || - (state->new != NULL && - state->new->cookie != htonl(MAGIC_COOKIE))) - { - ipv4ll_handle_failure(ifp); - return; - } + char buf[HWADDR_LEN * 3]; - unlink(state->leasefile); - if (!state->lease.frominfo) - dhcp_decline(ifp); - eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); - if (state->lease.frominfo) - dhcpcd_startinterface(ifp); - else - eloop_timeout_add_sec(ifp->ctx->eloop, - DHCP_ARP_FAIL, dhcpcd_startinterface, ifp); + syslog(LOG_ERR, "%s: hardware address %s claims %s", + astate->iface->name, + hwaddr_ntoa(amsg->sha, astate->iface->hwlen, buf, sizeof(buf)), + inet_ntoa(astate->failed)); } static void @@ -131,19 +115,14 @@ arp_packet(void *arg) const struct interface *ifn; uint8_t arp_buffer[ARP_LEN]; struct arphdr ar; - uint32_t reply_s; - uint32_t reply_t; - uint8_t *hw_s, *hw_t; + struct arp_msg arm; ssize_t bytes; struct dhcp_state *state; - struct if_options *opts = ifp->options; - const char *hwaddr; - struct in_addr ina; - char hwbuf[HWADDR_LEN * 3]; + struct arp_state *astate, *astaten; + unsigned char *hw_s, *hw_t; int flags; state = D_STATE(ifp); - state->fail.s_addr = 0; flags = 0; while (!(flags & RAW_EOF)) { bytes = if_readrawpacket(ifp, ETHERTYPE_ARP, @@ -158,10 +137,13 @@ arp_packet(void *arg) if ((size_t)bytes < sizeof(ar)) continue; memcpy(&ar, arp_buffer, sizeof(ar)); + /* Families must match */ + if (ar.ar_hrd != htons(ifp->family)) + continue; /* Protocol must be IP. */ if (ar.ar_pro != htons(ETHERTYPE_IP)) continue; - if (ar.ar_pln != sizeof(reply_s)) + if (ar.ar_pln != sizeof(arm.sip.s_addr)) continue; /* Only these types are recognised */ if (ar.ar_op != htons(ARPOP_REPLY) && @@ -182,77 +164,26 @@ arp_packet(void *arg) } if (ifn) continue; - /* Copy out the IP addresses */ - memcpy(&reply_s, hw_s + ar.ar_hln, ar.ar_pln); - memcpy(&reply_t, hw_t + ar.ar_hln, ar.ar_pln); - - /* Check for arping */ - if (state->arping_index && - state->arping_index <= opts->arping_len && - (reply_s == opts->arping[state->arping_index - 1] || - (reply_s == 0 && - reply_t == opts->arping[state->arping_index - 1]))) - { - ina.s_addr = reply_s; - hwaddr = hwaddr_ntoa((unsigned char *)hw_s, - (size_t)ar.ar_hln, hwbuf, sizeof(hwbuf)); - syslog(LOG_INFO, - "%s: found %s on hardware address %s", - ifp->name, inet_ntoa(ina), hwaddr); - if (dhcpcd_selectprofile(ifp, hwaddr) == -1 && - dhcpcd_selectprofile(ifp, inet_ntoa(ina)) == -1) - { - state->probes = 0; - /* We didn't find a profile for this - * address or hwaddr, so move to the next - * arping profile */ - if (state->arping_index < - ifp->options->arping_len) - { - arp_probe(ifp); - return; - } - } - dhcp_close(ifp); - eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); - dhcpcd_startinterface(ifp); - return; - } - - /* RFC 2131 3.1.5, Client-server interaction - * RFC 3927 2.2.1, Probe Conflict Detection */ - if (state->offer && - (reply_s == state->offer->yiaddr || - (reply_s == 0 && reply_t == state->offer->yiaddr))) - state->fail.s_addr = state->offer->yiaddr; - - /* RFC 3927 2.5, Conflict Defense */ - if (IN_LINKLOCAL(htonl(state->addr.s_addr)) && - reply_s == state->addr.s_addr) - state->fail.s_addr = state->addr.s_addr; - - if (state->fail.s_addr) { - syslog(LOG_ERR, "%s: hardware address %s claims %s", - ifp->name, - hwaddr_ntoa((unsigned char *)hw_s, - (size_t)ar.ar_hln, hwbuf, sizeof(hwbuf)), - inet_ntoa(state->fail)); - errno = EEXIST; - arp_failure(ifp); - return; + /* Copy out the HW and IP addresses */ + memcpy(&arm.sha, hw_s, ar.ar_hln); + memcpy(&arm.sip.s_addr, hw_s + ar.ar_hln, ar.ar_pln); + memcpy(&arm.tha, hw_t, ar.ar_hln); + memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln); + + /* Run the conflicts */ + TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) { + if (astate->conflicted_cb) + astate->conflicted_cb(astate, &arm); } } } -void -arp_announce(void *arg) +static void +arp_open(struct interface *ifp) { - struct interface *ifp = arg; - struct dhcp_state *state = D_STATE(ifp); - struct timeval tv; + struct dhcp_state *state; - if (state->new == NULL) - return; + state = D_STATE(ifp); if (state->arp_fd == -1) { state->arp_fd = if_openrawsocket(ifp, ETHERTYPE_ARP); if (state->arp_fd == -1) { @@ -262,126 +193,157 @@ arp_announce(void *arg) eloop_event_add(ifp->ctx->eloop, state->arp_fd, arp_packet, ifp, NULL, NULL); } - if (++state->claims < ANNOUNCE_NUM) +} + +static void +arp_announced(void *arg) +{ + struct arp_state *astate = arg; + + if (astate->announced_cb) { + astate->announced_cb(astate); + return; + } + + /* Nothing more to do, so free us */ + arp_free(astate); +} + +static void +arp_announce1(void *arg) +{ + struct arp_state *astate = arg; + struct interface *ifp = astate->iface; + + if (++astate->claims < ANNOUNCE_NUM) syslog(LOG_DEBUG, "%s: sending ARP announce (%d of %d), " "next in %d.0 seconds", - ifp->name, state->claims, ANNOUNCE_NUM, ANNOUNCE_WAIT); + ifp->name, astate->claims, ANNOUNCE_NUM, ANNOUNCE_WAIT); else syslog(LOG_DEBUG, "%s: sending ARP announce (%d of %d)", - ifp->name, state->claims, ANNOUNCE_NUM); + ifp->name, astate->claims, ANNOUNCE_NUM); if (arp_send(ifp, ARPOP_REQUEST, - state->new->yiaddr, state->new->yiaddr) == -1) + astate->addr.s_addr, astate->addr.s_addr) == -1) syslog(LOG_ERR, "send_arp: %m"); - if (state->claims < ANNOUNCE_NUM) { - eloop_timeout_add_sec(ifp->ctx->eloop, - ANNOUNCE_WAIT, arp_announce, ifp); - return; - } - if (state->new->cookie != htonl(MAGIC_COOKIE)) { - /* Check if doing DHCP */ - if (!(ifp->options->options & DHCPCD_DHCP)) - return; - /* We should pretend to be at the end - * of the DHCP negotation cycle unless we rebooted */ - if (state->interval != 0) - state->interval = 64; - state->probes = 0; - state->claims = 0; - tv.tv_sec = state->interval - DHCP_RAND_MIN; - tv.tv_usec = (suseconds_t)arc4random_uniform( - (DHCP_RAND_MAX - DHCP_RAND_MIN) * 1000000); - timernorm(&tv); - eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_discover, ifp); - } else { - eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0); - close(state->arp_fd); - state->arp_fd = -1; - } + eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT, + astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced, + astate); } void -arp_probe(void *arg) +arp_announce(struct arp_state *astate) { - struct interface *ifp = arg; - struct dhcp_state *state = D_STATE(ifp); - struct in_addr addr; - struct timeval tv; - int arping = 0; - if (state->arp_fd == -1) { - state->arp_fd = if_openrawsocket(ifp, ETHERTYPE_ARP); - if (state->arp_fd == -1) { - syslog(LOG_ERR, "%s: %s: %m", __func__, ifp->name); - return; - } - eloop_event_add(ifp->ctx->eloop, - state->arp_fd, arp_packet, ifp, NULL, NULL); - } + arp_open(astate->iface); + astate->claims = 0; + arp_announce1(astate); +} - if (state->arping_index < ifp->options->arping_len) { - addr.s_addr = ifp->options->arping[state->arping_index]; - arping = 1; - } else if (state->offer) { - if (state->offer->yiaddr) - addr.s_addr = state->offer->yiaddr; - else - addr.s_addr = state->offer->ciaddr; - } else - addr.s_addr = state->addr.s_addr; - - if (state->probes == 0) { - if (arping) - syslog(LOG_DEBUG, "%s: searching for %s", - ifp->name, inet_ntoa(addr)); - else - syslog(LOG_DEBUG, "%s: checking for %s", - ifp->name, inet_ntoa(addr)); - } - if (++state->probes < PROBE_NUM) { +static void +arp_probed(void *arg) +{ + struct arp_state *astate = arg; + + astate->probed_cb(astate); +} + +static void +arp_probe1(void *arg) +{ + struct arp_state *astate = arg; + struct interface *ifp = astate->iface; + struct timeval tv; + + if (++astate->probes < PROBE_NUM) { tv.tv_sec = PROBE_MIN; tv.tv_usec = (suseconds_t)arc4random_uniform( (PROBE_MAX - PROBE_MIN) * 1000000); timernorm(&tv); - eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe, ifp); + eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe1, astate); } else { tv.tv_sec = ANNOUNCE_WAIT; tv.tv_usec = 0; - if (arping) { - state->probes = 0; - if (++state->arping_index < ifp->options->arping_len) - eloop_timeout_add_tv(ifp->ctx->eloop, - &tv, arp_probe, ifp); - else - eloop_timeout_add_tv(ifp->ctx->eloop, - &tv, dhcpcd_startinterface, ifp); - } else - eloop_timeout_add_tv(ifp->ctx->eloop, - &tv, dhcp_bind, ifp); + eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probed, astate); } syslog(LOG_DEBUG, "%s: sending ARP probe (%d of %d), next in %0.1f seconds", - ifp->name, state->probes ? state->probes : PROBE_NUM, PROBE_NUM, + ifp->name, astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM, timeval_to_double(&tv)); - if (arp_send(ifp, ARPOP_REQUEST, 0, addr.s_addr) == -1) + if (arp_send(ifp, ARPOP_REQUEST, 0, astate->addr.s_addr) == -1) syslog(LOG_ERR, "send_arp: %m"); } void -arp_start(struct interface *ifp) +arp_probe(struct arp_state *astate) { - struct dhcp_state *state = D_STATE(ifp); - state->probes = 0; - state->arping_index = 0; - arp_probe(ifp); + arp_open(astate->iface); + astate->probes = 0; + syslog(LOG_DEBUG, "%s: probing for %s", + astate->iface->name, inet_ntoa(astate->addr)); + arp_probe1(astate); +} + + +struct arp_state * +arp_new(struct interface *ifp) { + struct arp_state *astate; + struct dhcp_state *state; + + astate = calloc(1, sizeof(*astate)); + if (astate == NULL) { + syslog(LOG_ERR, "%s: %s: %m", ifp->name, __func__); + return NULL; + } + + astate->iface = ifp; + state = D_STATE(ifp); + TAILQ_INSERT_TAIL(&state->arp_states, astate, next); + return astate; +} + +void +arp_cancel(struct arp_state *astate) +{ + + eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate); +} + +void +arp_free(struct arp_state *astate) +{ + struct dhcp_state *state; + + if (astate) { + eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate); + state = D_STATE(astate->iface); + TAILQ_REMOVE(&state->arp_states, astate, next); + if (state->arp_ipv4ll == astate) + state->arp_ipv4ll = NULL; + free(astate); + } +} + +void +arp_free_but(struct arp_state *astate) +{ + struct arp_state *p, *n; + struct dhcp_state *state; + + state = D_STATE(astate->iface); + TAILQ_FOREACH_SAFE(p, &state->arp_states, next, n) { + if (p != astate) + arp_free(p); + } } void arp_close(struct interface *ifp) { struct dhcp_state *state = D_STATE(ifp); + struct arp_state *astate; if (state == NULL) return; @@ -391,5 +353,8 @@ arp_close(struct interface *ifp) close(state->arp_fd); state->arp_fd = -1; } -} + while ((astate = TAILQ_FIRST(&state->arp_states))) { + arp_free(astate); + } +} Index: src/external/bsd/dhcpcd/dist/arp.h diff -u src/external/bsd/dhcpcd/dist/arp.h:1.3 src/external/bsd/dhcpcd/dist/arp.h:1.4 --- src/external/bsd/dhcpcd/dist/arp.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/arp.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: arp.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: arp.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -44,8 +44,35 @@ #include "dhcpcd.h" -void arp_announce(void *); -void arp_probe(void *); -void arp_start(struct interface *); +struct arp_msg { + uint16_t op; + unsigned char sha[HWADDR_LEN]; + struct in_addr sip; + unsigned char tha[HWADDR_LEN]; + struct in_addr tip; +}; + +struct arp_state { + TAILQ_ENTRY(arp_state) next; + struct interface *iface; + + void (*probed_cb)(struct arp_state *); + void (*announced_cb)(struct arp_state *); + void (*conflicted_cb)(struct arp_state *, const struct arp_msg *); + + struct in_addr addr; + int probes; + int claims; + struct in_addr failed; +}; +TAILQ_HEAD(arp_statehead, arp_state); + +void arp_report_conflicted(const struct arp_state *, const struct arp_msg *); +void arp_announce(struct arp_state *); +void arp_probe(struct arp_state *); +struct arp_state *arp_new(struct interface *); +void arp_cancel(struct arp_state *); +void arp_free(struct arp_state *); +void arp_free_but(struct arp_state *); void arp_close(struct interface *); #endif Index: src/external/bsd/dhcpcd/dist/auth.c diff -u src/external/bsd/dhcpcd/dist/auth.c:1.3 src/external/bsd/dhcpcd/dist/auth.c:1.4 --- src/external/bsd/dhcpcd/dist/auth.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/auth.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: auth.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: auth.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/auth.h diff -u src/external/bsd/dhcpcd/dist/auth.h:1.3 src/external/bsd/dhcpcd/dist/auth.h:1.4 --- src/external/bsd/dhcpcd/dist/auth.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/auth.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: auth.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: auth.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/common.c diff -u src/external/bsd/dhcpcd/dist/common.c:1.3 src/external/bsd/dhcpcd/dist/common.c:1.4 --- src/external/bsd/dhcpcd/dist/common.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/common.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: common.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: common.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/common.h diff -u src/external/bsd/dhcpcd/dist/common.h:1.3 src/external/bsd/dhcpcd/dist/common.h:1.4 --- src/external/bsd/dhcpcd/dist/common.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/common.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: common.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: common.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/config.h diff -u src/external/bsd/dhcpcd/dist/config.h:1.3 src/external/bsd/dhcpcd/dist/config.h:1.4 --- src/external/bsd/dhcpcd/dist/config.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/config.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: config.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: config.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* netbsd */ #define SYSCONFDIR "/etc" Index: src/external/bsd/dhcpcd/dist/control.c diff -u src/external/bsd/dhcpcd/dist/control.c:1.3 src/external/bsd/dhcpcd/dist/control.c:1.4 --- src/external/bsd/dhcpcd/dist/control.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/control.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: control.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: control.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/control.h diff -u src/external/bsd/dhcpcd/dist/control.h:1.3 src/external/bsd/dhcpcd/dist/control.h:1.4 --- src/external/bsd/dhcpcd/dist/control.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/control.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: control.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: control.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/defs.h diff -u src/external/bsd/dhcpcd/dist/defs.h:1.3 src/external/bsd/dhcpcd/dist/defs.h:1.4 --- src/external/bsd/dhcpcd/dist/defs.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/defs.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: defs.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: defs.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -30,7 +30,7 @@ #define CONFIG_H #define PACKAGE "dhcpcd" -#define VERSION "6.5.1" +#define VERSION "6.6.0" #ifndef CONFIG # define CONFIG SYSCONFDIR "/" PACKAGE ".conf" Index: src/external/bsd/dhcpcd/dist/dev.h diff -u src/external/bsd/dhcpcd/dist/dev.h:1.3 src/external/bsd/dhcpcd/dist/dev.h:1.4 --- src/external/bsd/dhcpcd/dist/dev.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dev.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dev.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: dev.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/dhcp-common.c diff -u src/external/bsd/dhcpcd/dist/dhcp-common.c:1.3 src/external/bsd/dhcpcd/dist/dhcp-common.c:1.4 --- src/external/bsd/dhcpcd/dist/dhcp-common.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcp-common.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcp-common.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: dhcp-common.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/dhcp-common.h diff -u src/external/bsd/dhcpcd/dist/dhcp-common.h:1.3 src/external/bsd/dhcpcd/dist/dhcp-common.h:1.4 --- src/external/bsd/dhcpcd/dist/dhcp-common.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcp-common.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dhcp-common.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: dhcp-common.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/dhcp.h diff -u src/external/bsd/dhcpcd/dist/dhcp.h:1.3 src/external/bsd/dhcpcd/dist/dhcp.h:1.4 --- src/external/bsd/dhcpcd/dist/dhcp.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcp.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dhcp.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: dhcp.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -36,6 +36,7 @@ #include <limits.h> #include <stdint.h> +#include "arp.h" #include "auth.h" #include "dhcp-common.h" @@ -68,7 +69,6 @@ #define DHCP_MAX 64 #define DHCP_RAND_MIN -1 #define DHCP_RAND_MAX 1 -#define DHCP_ARP_FAIL 2 #ifdef RFC2131_STRICT /* Be strictly conformant for section 4.1.1 */ @@ -198,7 +198,7 @@ enum DHS { DHS_REBOOT, DHS_INFORM, DHS_RENEW_REQUESTED, - DHS_INIT_IPV4LL, + DHS_IPV4LL_BOUND, DHS_PROBE }; @@ -214,12 +214,6 @@ struct dhcp_state { time_t nakoff; uint32_t xid; int socket; - int probes; - int claims; - int conflicts; - time_t defend; - struct in_addr fail; - size_t arping_index; int raw_fd; int arp_fd; @@ -237,6 +231,14 @@ struct dhcp_state { unsigned char *clientid; struct authstate auth; + struct arp_statehead arp_states; + + size_t arping_index; + + struct arp_state *arp_ipv4ll; + unsigned int conflicts; + time_t defend; + char randomstate[128]; }; #define D_STATE(ifp) \ @@ -283,7 +285,8 @@ void dhcp_stop(struct interface *); void dhcp_decline(struct interface *); void dhcp_discover(void *); void dhcp_inform(struct interface *); -void dhcp_bind(void *); +void dhcp_probe(struct interface *); +void dhcp_bind(struct interface *, struct arp_state *); void dhcp_reboot_newopts(struct interface *, unsigned long long); void dhcp_close(struct interface *); void dhcp_free(struct interface *); Index: src/external/bsd/dhcpcd/dist/dhcp6.c diff -u src/external/bsd/dhcpcd/dist/dhcp6.c:1.3 src/external/bsd/dhcpcd/dist/dhcp6.c:1.4 --- src/external/bsd/dhcpcd/dist/dhcp6.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcp6.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcp6.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: dhcp6.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/dhcp6.h diff -u src/external/bsd/dhcpcd/dist/dhcp6.h:1.3 src/external/bsd/dhcpcd/dist/dhcp6.h:1.4 --- src/external/bsd/dhcpcd/dist/dhcp6.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcp6.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dhcp6.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: dhcp6.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf diff -u src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.3 src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.4 --- src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -# $NetBSD: dhcpcd-definitions.conf,v 1.3 2014/10/17 23:42:24 roy Exp $ +# $NetBSD: dhcpcd-definitions.conf,v 1.4 2014/10/29 01:08:31 roy Exp $ # Copyright (c) 2006-2014 Roy Marples # All rights reserved Index: src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c diff -u src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.3 src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.4 --- src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcpcd-embedded.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: dhcpcd-embedded.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * DO NOT EDIT Index: src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h diff -u src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.3 src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.4 --- src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dhcpcd-embedded.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: dhcpcd-embedded.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in:1.3 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in:1.4 --- src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #!/bin/sh -# $NetBSD: dhcpcd-run-hooks.in,v 1.3 2014/10/17 23:42:24 roy Exp $ +# $NetBSD: dhcpcd-run-hooks.in,v 1.4 2014/10/29 01:08:31 roy Exp $ # dhcpcd client configuration script Index: src/external/bsd/dhcpcd/dist/dhcpcd.h diff -u src/external/bsd/dhcpcd/dist/dhcpcd.h:1.3 src/external/bsd/dhcpcd/dist/dhcpcd.h:1.4 --- src/external/bsd/dhcpcd/dist/dhcpcd.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dhcpcd.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: dhcpcd.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/duid.c diff -u src/external/bsd/dhcpcd/dist/duid.c:1.3 src/external/bsd/dhcpcd/dist/duid.c:1.4 --- src/external/bsd/dhcpcd/dist/duid.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/duid.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: duid.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: duid.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/duid.h diff -u src/external/bsd/dhcpcd/dist/duid.h:1.3 src/external/bsd/dhcpcd/dist/duid.h:1.4 --- src/external/bsd/dhcpcd/dist/duid.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/duid.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: duid.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: duid.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/eloop.c diff -u src/external/bsd/dhcpcd/dist/eloop.c:1.3 src/external/bsd/dhcpcd/dist/eloop.c:1.4 --- src/external/bsd/dhcpcd/dist/eloop.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/eloop.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: eloop.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: eloop.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/eloop.h diff -u src/external/bsd/dhcpcd/dist/eloop.h:1.3 src/external/bsd/dhcpcd/dist/eloop.h:1.4 --- src/external/bsd/dhcpcd/dist/eloop.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/eloop.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: eloop.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: eloop.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/if-options.h diff -u src/external/bsd/dhcpcd/dist/if-options.h:1.3 src/external/bsd/dhcpcd/dist/if-options.h:1.4 --- src/external/bsd/dhcpcd/dist/if-options.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/if-options.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: if-options.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: if-options.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -65,6 +65,7 @@ #define DHCPCD_LASTLEASE (1ULL << 7) #define DHCPCD_INFORM (1ULL << 8) #define DHCPCD_REQUEST (1ULL << 9) + #define DHCPCD_IPV4LL (1ULL << 10) #define DHCPCD_DUID (1ULL << 11) #define DHCPCD_PERSISTENT (1ULL << 12) @@ -78,7 +79,7 @@ #define DHCPCD_QUIET (1ULL << 21) #define DHCPCD_BACKGROUND (1ULL << 22) #define DHCPCD_VENDORRAW (1ULL << 23) -#define DHCPCD_TIMEOUT_IPV4LL (1ULL << 24) +#define DHCPCD_NOWAITIP (1ULL << 24) /* To force daemonise */ #define DHCPCD_WAITIP (1ULL << 25) #define DHCPCD_SLAACPRIVATE (1ULL << 26) #define DHCPCD_CSR_WARNED (1ULL << 27) Index: src/external/bsd/dhcpcd/dist/if.c diff -u src/external/bsd/dhcpcd/dist/if.c:1.3 src/external/bsd/dhcpcd/dist/if.c:1.4 --- src/external/bsd/dhcpcd/dist/if.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/if.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: if.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/if.h diff -u src/external/bsd/dhcpcd/dist/if.h:1.3 src/external/bsd/dhcpcd/dist/if.h:1.4 --- src/external/bsd/dhcpcd/dist/if.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/if.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: if.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: if.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/ipv4.c diff -u src/external/bsd/dhcpcd/dist/ipv4.c:1.3 src/external/bsd/dhcpcd/dist/ipv4.c:1.4 --- src/external/bsd/dhcpcd/dist/ipv4.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/ipv4.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv4.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: ipv4.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -136,6 +136,22 @@ ipv4_iffindaddr(struct interface *ifp, } struct ipv4_addr * +ipv4_iffindlladdr(struct interface *ifp) +{ + struct ipv4_state *state; + struct ipv4_addr *ap; + + state = IPV4_STATE(ifp); + if (state) { + TAILQ_FOREACH(ap, &state->addrs, next) { + if (IN_LINKLOCAL(htonl(ap->addr.s_addr))) + return ap; + } + } + return NULL; +} + +struct ipv4_addr * ipv4_findaddr(struct dhcpcd_ctx *ctx, const struct in_addr *addr) { struct interface *ifp; @@ -770,10 +786,7 @@ ipv4_applyaddr(void *arg) if (ifn->options->options & DHCPCD_ARP) { - nstate->claims = 0; - nstate->probes = 0; - nstate->conflicts = 0; - arp_probe(ifn); + dhcp_bind(ifn, NULL); } else { ipv4_addaddr(ifn, &nstate->lease); @@ -855,6 +868,7 @@ ipv4_applyaddr(void *arg) delete_address(ifp); state->added = 1; + state->defend = 0; state->addr.s_addr = lease->addr.s_addr; state->net.s_addr = lease->net.s_addr; Index: src/external/bsd/dhcpcd/dist/ipv4.h diff -u src/external/bsd/dhcpcd/dist/ipv4.h:1.3 src/external/bsd/dhcpcd/dist/ipv4.h:1.4 --- src/external/bsd/dhcpcd/dist/ipv4.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/ipv4.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ipv4.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: ipv4.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -74,6 +74,7 @@ int ipv4_routedeleted(struct dhcpcd_ctx struct ipv4_addr *ipv4_iffindaddr(struct interface *, const struct in_addr *, const struct in_addr *); +struct ipv4_addr *ipv4_iffindlladdr(struct interface *); struct ipv4_addr *ipv4_findaddr(struct dhcpcd_ctx *, const struct in_addr *); void ipv4_handleifa(struct dhcpcd_ctx *, int, struct if_head *, const char *, const struct in_addr *, const struct in_addr *, const struct in_addr *); Index: src/external/bsd/dhcpcd/dist/ipv4ll.c diff -u src/external/bsd/dhcpcd/dist/ipv4ll.c:1.3 src/external/bsd/dhcpcd/dist/ipv4ll.c:1.4 --- src/external/bsd/dhcpcd/dist/ipv4ll.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/ipv4ll.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv4ll.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: ipv4ll.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -35,7 +35,7 @@ #include <syslog.h> #include <unistd.h> -#define ELOOP_QUEUE 2 +#define ELOOP_QUEUE 6 #include "config.h" #include "arp.h" #include "common.h" @@ -73,101 +73,183 @@ ipv4ll_make_lease(uint32_t addr) return dhcp; } -static struct dhcp_message * -ipv4ll_find_lease(uint32_t old_addr) +static in_addr_t +ipv4ll_pick_addr(const struct arp_state *astate) { - uint32_t addr; + in_addr_t addr; + struct interface *ifp; + const struct dhcp_state *state; for (;;) { - addr = htonl(LINKLOCAL_ADDR | - (uint32_t)(abs((int)arc4random_uniform(0xFD00)) + 0x0100)); - if (addr != old_addr && - IN_LINKLOCAL(ntohl(addr))) + /* RFC 3927 Section 2.1 states that the first 256 and + * last 256 addresses are reserved for future use. + * See ipv4ll_start for why we don't use arc4_random. */ + addr = ntohl(LINKLOCAL_ADDR | ((random() % 0xFD00) + 0x0100)); + + /* No point using a failed address */ + if (addr == astate->failed.s_addr) + continue; + + state = D_CSTATE(astate->iface); + /* Ensure we don't have the address on another interface */ + TAILQ_FOREACH(ifp, astate->iface->ctx->ifaces, next) { + state = D_CSTATE(ifp); + if (state && state->addr.s_addr == addr) + break; + } + + /* Yay, this should be a unique and workable IPv4LL address */ + if (ifp == NULL) break; } - return ipv4ll_make_lease(addr); + return addr; } -void -ipv4ll_start(void *arg) +static void +ipv4ll_probed(struct arp_state *astate) { - struct interface *ifp = arg; - struct dhcp_state *state = D_STATE(ifp); - uint32_t addr; + struct dhcp_state *state = D_STATE(astate->iface); - eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); - state->probes = 0; - state->claims = 0; - if (state->addr.s_addr) { - state->conflicts = 0; - if (IN_LINKLOCAL(htonl(state->addr.s_addr))) { - arp_announce(ifp); - return; - } - } - - if (state->offer == NULL) - addr = 0; - else { - addr = state->offer->yiaddr; - free(state->offer); - } - /* We maybe rebooting an IPv4LL address. */ - if (!IN_LINKLOCAL(htonl(addr))) { - syslog(LOG_INFO, "%s: probing for an IPv4LL address", - ifp->name); - addr = 0; - } - if (addr == 0) - state->offer = ipv4ll_find_lease(addr); - else - state->offer = ipv4ll_make_lease(addr); - if (state->offer == NULL) + free(state->offer); + state->offer = ipv4ll_make_lease(astate->addr.s_addr); + if (state->offer == NULL) { syslog(LOG_ERR, "%s: %m", __func__); - else { - state->lease.frominfo = 0; - arp_probe(ifp); + return; } + dhcp_bind(astate->iface, astate); } -void -ipv4ll_handle_failure(void *arg) +static void +ipv4ll_announced(struct arp_state *astate) { - struct interface *ifp = arg; - struct dhcp_state *state = D_STATE(ifp); - time_t up; + struct dhcp_state *state = D_STATE(astate->iface); + + state->conflicts = 0; + /* Need to keep the arp state so we can defend our IP. */ +} + +static void +ipv4ll_probe(void *arg) +{ + + arp_probe(arg); +} + +static void +ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg) +{ + struct dhcp_state *state = D_STATE(astate->iface); + in_addr_t fail; + + fail = 0; + /* RFC 3927 2.2.1, Probe Conflict Detection */ + if (amsg->sip.s_addr == astate->addr.s_addr || + (amsg->sip.s_addr == 0 && amsg->tip.s_addr == astate->addr.s_addr)) + fail = astate->addr.s_addr; + + /* RFC 3927 2.5, Conflict Defense */ + if (IN_LINKLOCAL(htonl(state->addr.s_addr)) && + amsg->sip.s_addr == state->addr.s_addr) + fail = state->addr.s_addr; + + if (fail == 0) + return; + + astate->failed.s_addr = fail; + arp_report_conflicted(astate, amsg); + + if (astate->failed.s_addr == state->addr.s_addr) { + time_t up; - if (state->fail.s_addr == state->addr.s_addr) { /* RFC 3927 Section 2.5 */ up = uptime(); if (state->defend + DEFEND_INTERVAL > up) { syslog(LOG_WARNING, - "%s: IPv4LL %d second defence failed", - ifp->name, DEFEND_INTERVAL); - dhcp_drop(ifp, "EXPIRE"); - state->conflicts = -1; + "%s: IPv4LL %d second defence failed for %s", + astate->iface->name, DEFEND_INTERVAL, + inet_ntoa(state->addr)); + dhcp_drop(astate->iface, "EXPIRE"); } else { - syslog(LOG_DEBUG, "%s: defended IPv4LL address", - ifp->name); + syslog(LOG_DEBUG, "%s: defended IPv4LL address %s", + astate->iface->name, inet_ntoa(state->addr)); state->defend = up; return; } } - free(state->offer); - state->offer = NULL; - eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); - if (++state->conflicts > MAX_CONFLICTS) { + arp_cancel(astate); + if (++state->conflicts == MAX_CONFLICTS) syslog(LOG_ERR, "%s: failed to acquire an IPv4LL address", - ifp->name); - if (ifp->options->options & DHCPCD_DHCP) { - state->interval = RATE_LIMIT_INTERVAL / 2; - dhcp_discover(ifp); + astate->iface->name); + astate->addr.s_addr = ipv4ll_pick_addr(astate); + eloop_timeout_add_sec(astate->iface->ctx->eloop, + state->conflicts >= MAX_CONFLICTS ? + RATE_LIMIT_INTERVAL : PROBE_WAIT, + ipv4ll_probe, astate); +} + +void +ipv4ll_start(void *arg) +{ + struct interface *ifp = arg; + struct dhcp_state *state = D_STATE(ifp); + struct arp_state *astate; + struct ipv4_addr *ap; + + if (state->arp_ipv4ll) + return; + + /* RFC 3927 Section 2.1 states that the random number generator + * SHOULD be seeded with a value derived from persistent information + * such as the IEEE 802 MAC address so that it usually picks + * the same address without persistent storage. */ + if (state->conflicts == 0) { + unsigned int seed; + + if (sizeof(seed) > ifp->hwlen) { + seed = 0; + memcpy(&seed, ifp->hwaddr, ifp->hwlen); } else - eloop_timeout_add_sec(ifp->ctx->eloop, - RATE_LIMIT_INTERVAL, ipv4ll_start, ifp); - } else { - eloop_timeout_add_sec(ifp->ctx->eloop, - PROBE_WAIT, ipv4ll_start, ifp); + memcpy(&seed, ifp->hwaddr + ifp->hwlen - sizeof(seed), + sizeof(seed)); + initstate(seed, state->randomstate, sizeof(state->randomstate)); + } + + if ((astate = arp_new(ifp)) == NULL) + return; + + state->arp_ipv4ll = astate; + astate->probed_cb = ipv4ll_probed; + astate->announced_cb = ipv4ll_announced; + astate->conflicted_cb = ipv4ll_conflicted; + + if (IN_LINKLOCAL(htonl(state->addr.s_addr))) { + astate->addr = state->addr; + arp_announce(astate); + return; + } + + if (state->offer && IN_LINKLOCAL(ntohl(state->offer->yiaddr))) { + astate->addr.s_addr = state->offer->yiaddr; + free(state->offer); + state->offer = NULL; + ap = ipv4_iffindaddr(ifp, &astate->addr, NULL); + } else + ap = ipv4_iffindlladdr(ifp); + if (ap) { + astate->addr = ap->addr; + ipv4ll_probed(astate); + return; + } + + setstate(state->randomstate); + /* We maybe rebooting an IPv4LL address. */ + if (!IN_LINKLOCAL(htonl(astate->addr.s_addr))) { + syslog(LOG_INFO, "%s: probing for an IPv4LL address", + ifp->name); + astate->addr.s_addr = INADDR_ANY; } + if (astate->addr.s_addr == INADDR_ANY) + astate->addr.s_addr = ipv4ll_pick_addr(astate); + arp_probe(astate); } Index: src/external/bsd/dhcpcd/dist/ipv4ll.h diff -u src/external/bsd/dhcpcd/dist/ipv4ll.h:1.3 src/external/bsd/dhcpcd/dist/ipv4ll.h:1.4 --- src/external/bsd/dhcpcd/dist/ipv4ll.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/ipv4ll.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ipv4ll.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: ipv4ll.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -31,6 +31,7 @@ #define IPV4LL_H void ipv4ll_start(void *); +void ipv4ll_claimed(void *); void ipv4ll_handle_failure(void *); #endif Index: src/external/bsd/dhcpcd/dist/ipv6.c diff -u src/external/bsd/dhcpcd/dist/ipv6.c:1.3 src/external/bsd/dhcpcd/dist/ipv6.c:1.4 --- src/external/bsd/dhcpcd/dist/ipv6.c:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/ipv6.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv6.c,v 1.3 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: ipv6.c,v 1.4 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/ipv6.h diff -u src/external/bsd/dhcpcd/dist/ipv6.h:1.3 src/external/bsd/dhcpcd/dist/ipv6.h:1.4 --- src/external/bsd/dhcpcd/dist/ipv6.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/ipv6.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ipv6.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: ipv6.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/ipv6nd.h diff -u src/external/bsd/dhcpcd/dist/ipv6nd.h:1.3 src/external/bsd/dhcpcd/dist/ipv6nd.h:1.4 --- src/external/bsd/dhcpcd/dist/ipv6nd.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/ipv6nd.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ipv6nd.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: ipv6nd.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/script.h diff -u src/external/bsd/dhcpcd/dist/script.h:1.3 src/external/bsd/dhcpcd/dist/script.h:1.4 --- src/external/bsd/dhcpcd/dist/script.h:1.3 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/script.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: script.h,v 1.3 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: script.h,v 1.4 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/bpf-filter.h diff -u src/external/bsd/dhcpcd/dist/bpf-filter.h:1.6 src/external/bsd/dhcpcd/dist/bpf-filter.h:1.7 --- src/external/bsd/dhcpcd/dist/bpf-filter.h:1.6 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/bpf-filter.h Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: bpf-filter.h,v 1.6 2014/10/17 23:42:24 roy Exp $ */ +/* $NetBSD: bpf-filter.h,v 1.7 2014/10/29 01:08:31 roy Exp $ */ /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/dhcp.c diff -u src/external/bsd/dhcpcd/dist/dhcp.c:1.19 src/external/bsd/dhcpcd/dist/dhcp.c:1.20 --- src/external/bsd/dhcpcd/dist/dhcp.c:1.19 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcp.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcp.c,v 1.19 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: dhcp.c,v 1.20 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -1418,11 +1418,6 @@ dhcp_close(struct interface *ifp) if (state == NULL) return; - if (state->arp_fd != -1) { - eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0); - close(state->arp_fd); - state->arp_fd = -1; - } if (state->raw_fd != -1) { eloop_event_delete(ifp->ctx->eloop, state->raw_fd, 0); close(state->raw_fd); @@ -1676,7 +1671,7 @@ send_message(struct interface *iface, ui default: if (!(iface->ctx->options & DHCPCD_TEST)) dhcp_drop(iface, "FAIL"); - dhcp_close(iface); + dhcp_free(iface); eloop_timeout_delete(iface->ctx->eloop, NULL, iface); callback = NULL; @@ -1738,16 +1733,13 @@ dhcp_discover(void *arg) struct if_options *ifo = ifp->options; time_t timeout = ifo->timeout; - /* If we're rebooting and we're not daemonised then we need - * to shorten the normal timeout to ensure we try correctly - * for a fallback or IPv4LL address. */ - if (state->state == DHS_REBOOT && - !(ifp->ctx->options & DHCPCD_DAEMONISED)) - { + /* If we're rebooting then we need to shorten the normal timeout + * to ensure we try for a fallback or IPv4LL address. */ + if (state->state == DHS_REBOOT) { if (ifo->reboot >= timeout) timeout = 2; else - timeout -= ifo->reboot; + timeout = ifo->reboot; } state->state = DHS_DISCOVER; @@ -1758,12 +1750,8 @@ dhcp_discover(void *arg) timeout, dhcp_fallback, ifp); else if (ifo->options & DHCPCD_IPV4LL && !IN_LINKLOCAL(htonl(state->addr.s_addr))) - { - if (IN_LINKLOCAL(htonl(state->fail.s_addr))) - timeout = RATE_LIMIT_INTERVAL; eloop_timeout_add_sec(ifp->ctx->eloop, timeout, ipv4ll_start, ifp); - } if (ifo->options & DHCPCD_REQUEST) syslog(LOG_INFO, "%s: soliciting a DHCP lease (requesting %s)", ifp->name, inet_ntoa(ifo->req_addr)); @@ -1792,7 +1780,6 @@ dhcp_expire(void *arg) eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); dhcp_drop(ifp, "EXPIRE"); unlink(state->leasefile); - state->interval = 0; dhcp_discover(ifp); } @@ -1823,6 +1810,13 @@ dhcp_renew(void *arg) } static void +dhcp_arp_announced(struct arp_state *astate) +{ + + arp_close(astate->iface); +} + +static void dhcp_rebind(void *arg) { struct interface *ifp = arg; @@ -1841,9 +1835,8 @@ dhcp_rebind(void *arg) } void -dhcp_bind(void *arg) +dhcp_bind(struct interface *ifp, struct arp_state *astate) { - struct interface *ifp = arg; struct dhcp_state *state = D_STATE(ifp); struct if_options *ifo = ifp->options; struct dhcp_lease *lease = &state->lease; @@ -1853,7 +1846,6 @@ dhcp_bind(void *arg) if (state->state == DHS_BOUND) goto applyaddr; state->reason = NULL; - state->xid = 0; free(state->old); state->old = state->new; state->new = state->offer; @@ -1933,7 +1925,7 @@ dhcp_bind(void *arg) return; } if (state->reason == NULL) { - if (state->old) { + if (state->old && state->new->cookie != htonl(MAGIC_COOKIE)) { if (state->old->yiaddr == state->new->yiaddr && lease->server.s_addr) state->reason = "RENEW"; @@ -1958,7 +1950,11 @@ dhcp_bind(void *arg) " seconds", ifp->name, lease->renewaltime, lease->rebindtime); } - state->state = DHS_BOUND; + if (!(ifo->options & DHCPCD_STATIC) && + state->new->cookie != htonl(MAGIC_COOKIE)) + state->state = DHS_IPV4LL_BOUND; + else + state->state = DHS_BOUND; if (!state->lease.frominfo && !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))) if (write_lease(ifp, state->new) == -1) @@ -1966,14 +1962,23 @@ dhcp_bind(void *arg) applyaddr: ipv4_applyaddr(ifp); - if (dhcpcd_daemonise(ifp->ctx) == 0) { - if (!ipv4ll) + if (dhcpcd_daemonise(ifp->ctx)) + return; + if (ifo->options & DHCPCD_ARP) { + if (state->added) { + if (astate == NULL) { + /* We don't care about what happens + * to the ARP announcement */ + astate = arp_new(ifp); + astate->announced_cb = + dhcp_arp_announced; + } + if (astate) { + arp_announce(astate); + arp_free_but(astate); + } + } else if (!ipv4ll) arp_close(ifp); - if (ifo->options & DHCPCD_ARP) { - state->claims = 0; - if (state->added) - arp_announce(ifp); - } } } @@ -1983,7 +1988,7 @@ dhcp_timeout(void *arg) struct interface *ifp = arg; struct dhcp_state *state = D_STATE(ifp); - dhcp_bind(ifp); + dhcp_bind(ifp, NULL); state->interval = 0; dhcp_discover(ifp); } @@ -2029,7 +2034,7 @@ dhcp_static(struct interface *ifp) state->offer = dhcp_message_new(&ifo->req_addr, &ifo->req_mask); if (state->offer) { eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); - dhcp_bind(ifp); + dhcp_bind(ifp, NULL); } } @@ -2065,7 +2070,7 @@ dhcp_inform(struct interface *ifp) dhcp_message_new(&ifo->req_addr, &ifo->req_mask); if (state->offer) { ifo->options |= DHCPCD_STATIC; - dhcp_bind(ifp); + dhcp_bind(ifp, NULL); ifo->options &= ~DHCPCD_STATIC; } } @@ -2102,6 +2107,7 @@ dhcp_reboot(struct interface *ifp) if (state == NULL) return; ifo = ifp->options; + state->state = DHS_REBOOT; state->interval = 0; if (ifo->options & DHCPCD_LINK && ifp->carrier == LINK_DOWN) { @@ -2120,21 +2126,21 @@ dhcp_reboot(struct interface *ifp) syslog(LOG_INFO, "%s: informing address of %s", ifp->name, inet_ntoa(state->lease.addr)); } else if (state->offer->cookie == 0) { - if (ifo->options & DHCPCD_IPV4LL) { - state->claims = 0; - if (state->added) - arp_announce(ifp); - } else - dhcp_discover(ifp); return; } else { syslog(LOG_INFO, "%s: rebinding lease of %s", ifp->name, inet_ntoa(state->lease.addr)); } - state->state = DHS_REBOOT; state->xid = dhcp_xid(ifp); state->lease.server.s_addr = 0; eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); + + /* Need to add this before dhcp_expire and friends. */ + if (!ifo->fallback && ifo->reboot && ifo->options & DHCPCD_IPV4LL && + !IN_LINKLOCAL(htonl(state->addr.s_addr))) + eloop_timeout_add_sec(ifp->ctx->eloop, + ifo->reboot, ipv4ll_start, ifp); + if (ifo->fallback) eloop_timeout_add_sec(ifp->ctx->eloop, ifo->reboot, dhcp_fallback, ifp); @@ -2162,16 +2168,19 @@ dhcp_drop(struct interface *ifp, const c struct timespec ts; #endif + state = D_STATE(ifp); /* dhcp_start may just have been called and we don't yet have a state * but we do have a timeout, so punt it. */ - eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); - - state = D_STATE(ifp); - if (state == NULL) + if (state == NULL) { + eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); return; - dhcp_auth_reset(&state->auth); - dhcp_close(ifp); - arp_close(ifp); + } + /* Don't reset DHCP state if we have an IPv4LL address and link is up */ + if (state->state != DHS_IPV4LL_BOUND || ifp->carrier != LINK_UP) { + eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); + dhcp_auth_reset(&state->auth); + dhcp_close(ifp); + } if (ifp->options->options & DHCPCD_RELEASE) { unlink(state->leasefile); if (ifp->carrier != LINK_DOWN && @@ -2299,6 +2308,103 @@ whitelisted_ip(const struct if_options * } static void +dhcp_arp_probed(struct arp_state *astate) +{ + struct dhcp_state *state; + struct if_options *ifo; + + /* We didn't find a profile for this + * address or hwaddr, so move to the next + * arping profile */ + state = D_STATE(astate->iface); + ifo = astate->iface->options; + if (state->arping_index < ifo->arping_len) { + if (++state->arping_index < ifo->arping_len) { + astate->addr.s_addr = + ifo->arping[state->arping_index - 1]; + arp_probe(astate); + } + dhcpcd_startinterface(astate->iface); + return; + } + dhcp_close(astate->iface); + eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate->iface); + dhcp_bind(astate->iface, astate); +} + +static void +dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg) +{ + struct dhcp_state *state; + struct if_options *ifo; + + state = D_STATE(astate->iface); + ifo = astate->iface->options; + if (state->arping_index && + state->arping_index <= ifo->arping_len && + (amsg->sip.s_addr == ifo->arping[state->arping_index - 1] || + (amsg->sip.s_addr == 0 && + amsg->tip.s_addr == ifo->arping[state->arping_index - 1]))) + { + char buf[HWADDR_LEN * 3]; + + astate->failed.s_addr = ifo->arping[state->arping_index - 1]; + arp_report_conflicted(astate, amsg); + hwaddr_ntoa(amsg->sha, astate->iface->hwlen, buf, sizeof(buf)); + if (dhcpcd_selectprofile(astate->iface, buf) == -1 && + dhcpcd_selectprofile(astate->iface, + inet_ntoa(astate->failed)) == -1) + { + /* We didn't find a profile for this + * address or hwaddr, so move to the next + * arping profile */ + dhcp_arp_probed(astate); + return; + } + dhcp_close(astate->iface); + arp_close(astate->iface); + eloop_timeout_delete(astate->iface->ctx->eloop, NULL, + astate->iface); + dhcpcd_startinterface(astate->iface); + } + + if (state->offer == NULL) + return; + + /* RFC 2131 3.1.5, Client-server interaction */ + if (amsg->sip.s_addr == state->offer->yiaddr || + (amsg->sip.s_addr == 0 && amsg->tip.s_addr == state->offer->yiaddr)) + { + astate->failed.s_addr = state->offer->yiaddr; + arp_report_conflicted(astate, amsg); + unlink(state->leasefile); + if (!state->lease.frominfo) + dhcp_decline(astate->iface); + eloop_timeout_delete(astate->iface->ctx->eloop, NULL, + astate->iface); + eloop_timeout_add_sec(astate->iface->ctx->eloop, + DHCP_RAND_MAX, dhcp_discover, astate->iface); + } +} + +void +dhcp_probe(struct interface *ifp) +{ + const struct dhcp_state *state; + struct arp_state *astate; + + astate = arp_new(ifp); + if (astate) { + state = D_CSTATE(ifp); + astate->addr = state->addr; + astate->probed_cb = dhcp_arp_probed; + astate->conflicted_cb = dhcp_arp_conflicted; + astate->announced_cb = dhcp_arp_announced; + arp_probe(astate); + } +} + +static void dhcp_handledhcp(struct interface *iface, struct dhcp_message **dhcpp, const struct in_addr *from) { @@ -2438,7 +2544,8 @@ dhcp_handledhcp(struct interface *iface, iface->name, msg); free(msg); } - if (state->state == DHS_DISCOVER && + if ((state->state == DHS_DISCOVER || + state->state == DHS_IPV4LL_BOUND) && get_option_uint8(iface->ctx, &tmp, dhcp, DHO_AUTOCONFIGURE) == 0) { @@ -2446,7 +2553,8 @@ dhcp_handledhcp(struct interface *iface, case 0: log_dhcp(LOG_WARNING, "IPv4LL disabled from", iface, dhcp, from); - dhcp_close(iface); + dhcp_drop(iface, "EXPIRE"); + arp_close(iface); eloop_timeout_delete(iface->ctx->eloop, NULL, iface); eloop_timeout_add_sec(iface->ctx->eloop, @@ -2499,7 +2607,7 @@ dhcp_handledhcp(struct interface *iface, } if ((type == 0 || type == DHCP_OFFER) && - state->state == DHS_DISCOVER) + (state->state == DHS_DISCOVER || state->state == DHS_IPV4LL_BOUND)) { lease->frominfo = 0; lease->addr.s_addr = dhcp->yiaddr; @@ -2580,15 +2688,20 @@ dhcp_handledhcp(struct interface *iface, * then we can't ARP for duplicate detection. */ addr.s_addr = state->offer->yiaddr; if (!ipv4_iffindaddr(iface, &addr, NULL)) { - state->claims = 0; - state->probes = 0; - state->conflicts = 0; - arp_probe(iface); + struct arp_state *astate; + + astate = arp_new(iface); + if (astate) { + astate->addr = addr; + astate->probed_cb = dhcp_arp_probed; + astate->conflicted_cb = dhcp_arp_conflicted; + arp_probe(astate); + } return; } } - dhcp_bind(iface); + dhcp_bind(iface, NULL); } static size_t @@ -2672,6 +2785,7 @@ dhcp_handlepacket(void *arg) syslog(LOG_ERR, "%s: dhcp if_readrawpacket: %m", ifp->name); dhcp_close(ifp); + arp_close(ifp); break; } if (valid_udp_packet(ifp->ctx->packet, bytes, @@ -2793,6 +2907,8 @@ dhcp_dump(struct interface *ifp) ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state)); if (state == NULL) goto eexit; + state->raw_fd = state->arp_fd = -1; + TAILQ_INIT(&state->arp_states); snprintf(state->leasefile, sizeof(state->leasefile), LEASEFILE, ifp->name); state->new = read_lease(ifp); @@ -2819,6 +2935,8 @@ dhcp_free(struct interface *ifp) struct dhcp_state *state = D_STATE(ifp); struct dhcpcd_ctx *ctx; + dhcp_close(ifp); + arp_close(ifp); if (state) { free(state->old); free(state->new); @@ -2868,6 +2986,7 @@ dhcp_init(struct interface *ifp) return -1; /* 0 is a valid fd, so init to -1 */ state->raw_fd = state->arp_fd = -1; + TAILQ_INIT(&state->arp_states); } state->state = DHS_INIT; @@ -2963,16 +3082,20 @@ dhcp_start1(void *arg) return; } - /* Close any pre-existing sockets as we're starting over */ - dhcp_close(ifp); - state = D_STATE(ifp); state->start_uptime = uptime(); free(state->offer); state->offer = NULL; if (state->arping_index < ifo->arping_len) { - arp_start(ifp); + struct arp_state *astate; + + astate = arp_new(ifp); + if (astate) { + astate->probed_cb = dhcp_arp_probed; + astate->conflicted_cb = dhcp_arp_conflicted; + dhcp_arp_probed(astate); + } return; } @@ -3041,11 +3164,13 @@ dhcp_start1(void *arg) return; } - if (state->offer == NULL) + if (state->offer == NULL || state->offer->cookie == 0) { + /* If we don't have an address yet, enter the reboot + * state to ensure at least fallback in short order. */ + if (state->addr.s_addr == INADDR_ANY) + state->state = DHS_REBOOT; dhcp_discover(ifp); - else if (state->offer->cookie == 0 && ifo->options & DHCPCD_IPV4LL) - ipv4ll_start(ifp); - else + } else dhcp_reboot(ifp); } Index: src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.9 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.10 --- src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.9 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd-run-hooks.8.in,v 1.9 2014/10/17 23:42:24 roy Exp $ +.\" $NetBSD: dhcpcd-run-hooks.8.in,v 1.10 2014/10/29 01:08:31 roy Exp $ .\" Copyright (c) 2006-2014 Roy Marples .\" All rights reserved .\" Index: src/external/bsd/dhcpcd/dist/dhcpcd.8.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.33 src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.34 --- src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.33 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.8.in Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd.8.in,v 1.33 2014/10/17 23:42:24 roy Exp $ +.\" $NetBSD: dhcpcd.8.in,v 1.34 2014/10/29 01:08:31 roy Exp $ .\" Copyright (c) 2006-2014 Roy Marples .\" All rights reserved .\" Index: src/external/bsd/dhcpcd/dist/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.13 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.14 --- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.13 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcpcd.c,v 1.13 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: dhcpcd.c,v 1.14 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -188,28 +188,15 @@ static void handle_exit_timeout(void *arg) { struct dhcpcd_ctx *ctx; - int timeout; ctx = arg; syslog(LOG_ERR, "timed out"); - if (!(ctx->options & DHCPCD_IPV4) || - !(ctx->options & DHCPCD_TIMEOUT_IPV4LL)) - { - if (ctx->options & DHCPCD_MASTER) { - /* We've timed out, so remove the waitip requirements. - * If the user doesn't like this they can always set - * an infinite timeout. */ - ctx->options &= - ~(DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6); - dhcpcd_daemonise(ctx); - } else - eloop_exit(ctx->eloop, EXIT_FAILURE); + if (!(ctx->options & DHCPCD_MASTER)) { + eloop_exit(ctx->eloop, EXIT_FAILURE); return; } - ctx->options &= ~DHCPCD_TIMEOUT_IPV4LL; - timeout = (PROBE_NUM * PROBE_MAX) + (PROBE_WAIT * 2) + DHCP_MAX_DELAY; - syslog(LOG_WARNING, "allowing %d seconds for IPv4LL timeout", timeout); - eloop_timeout_add_sec(ctx->eloop, timeout, handle_exit_timeout, ctx); + ctx->options |= DHCPCD_NOWAITIP; + dhcpcd_daemonise(ctx); } int @@ -260,7 +247,7 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) int sidpipe[2], fd; if (ctx->options & DHCPCD_DAEMONISE && - !(ctx->options & DHCPCD_DAEMONISED)) + !(ctx->options & (DHCPCD_DAEMONISED | DHCPCD_NOWAITIP))) { if (!dhcpcd_ipwaited(ctx)) return 0; @@ -329,6 +316,7 @@ stop_interface(struct interface *ifp) dhcp6_drop(ifp, NULL); ipv6nd_drop(ifp); dhcp_drop(ifp, "STOP"); + arp_close(ifp); eloop_timeout_delete(ctx->eloop, NULL, ifp); if (ifp->options->options & DHCPCD_DEPARTED) script_runreason(ifp, "DEPARTED"); @@ -371,14 +359,20 @@ configure_interface1(struct interface *i if (ifo->metric != -1) ifp->metric = (unsigned int)ifo->metric; + if (!(ifo->options & DHCPCD_IPV4)) + ifo->options &= ~(DHCPCD_DHCP | DHCPCD_IPV4LL); + if (!(ifo->options & DHCPCD_IPV6)) - ifo->options &= ~DHCPCD_IPV6RS; + ifo->options &= ~(DHCPCD_IPV6RS | DHCPCD_DHCP6); if (ifo->options & DHCPCD_SLAACPRIVATE) ifo->options |= DHCPCD_IPV6RA_OWN; /* We want to disable kernel interface RA as early as possible. */ if (ifo->options & DHCPCD_IPV6RS) { + /* If not doing any DHCP, disable the RDNSS requirement. */ + if (!(ifo->options & (DHCPCD_DHCP | DHCPCD_DHCP6))) + ifo->options &= ~DHCPCD_IPV6RA_REQRDNSS; ra_global = if_checkipv6(ifp->ctx, NULL, ifp->ctx->options & DHCPCD_IPV6RA_OWN ? 1 : 0); ra_iface = if_checkipv6(ifp->ctx, ifp, @@ -574,6 +568,7 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx * * do nothing. */ ipv6_free_ll_callbacks(ifp); dhcp_drop(ifp, "EXPIRE"); + arp_close(ifp); } } else if (carrier == LINK_UP && ifp->flags & IFF_UP) { if (ifp->carrier != LINK_UP) { @@ -1706,8 +1701,6 @@ main(int argc, char **argv) if (dhcpcd_daemonise(&ctx)) goto exit_success; } else if (t > 0) { - if (ctx.options & DHCPCD_IPV4LL) - ctx.options |= DHCPCD_TIMEOUT_IPV4LL; eloop_timeout_add_sec(ctx.eloop, t, handle_exit_timeout, &ctx); } Index: src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.13 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.14 --- src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.13 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd.conf.5.in,v 1.13 2014/10/17 23:42:24 roy Exp $ +.\" $NetBSD: dhcpcd.conf.5.in,v 1.14 2014/10/29 01:08:31 roy Exp $ .\" Copyright (c) 2006-2014 Roy Marples .\" All rights reserved .\" @@ -456,7 +456,8 @@ Suppress any dhcpcd output to the consol .It Ic reboot Ar seconds Allow .Ar reboot -seconds before moving to the DISCOVER phase if we have an old lease to use. +seconds before moving to the DISCOVER phase if we have an old lease to use +and moving from DISCOVER to IPv4LL if no reply. The default is 5 seconds. A setting of 0 seconds causes .Nm dhcpcd Index: src/external/bsd/dhcpcd/dist/dhcpcd.conf diff -u src/external/bsd/dhcpcd/dist/dhcpcd.conf:1.12 src/external/bsd/dhcpcd/dist/dhcpcd.conf:1.13 --- src/external/bsd/dhcpcd/dist/dhcpcd.conf:1.12 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.conf Wed Oct 29 01:08:31 2014 @@ -1,4 +1,4 @@ -# $NetBSD: dhcpcd.conf,v 1.12 2014/10/17 23:42:24 roy Exp $ +# $NetBSD: dhcpcd.conf,v 1.13 2014/10/29 01:08:31 roy Exp $ # A sample configuration for dhcpcd. # See dhcpcd.conf(5) for details. Index: src/external/bsd/dhcpcd/dist/if-bsd.c diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.12 src/external/bsd/dhcpcd/dist/if-bsd.c:1.13 --- src/external/bsd/dhcpcd/dist/if-bsd.c:1.12 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/if-bsd.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if-bsd.c,v 1.12 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: if-bsd.c,v 1.13 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/if-options.c diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.14 src/external/bsd/dhcpcd/dist/if-options.c:1.15 --- src/external/bsd/dhcpcd/dist/if-options.c:1.14 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/if-options.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if-options.c,v 1.14 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: if-options.c,v 1.15 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon Index: src/external/bsd/dhcpcd/dist/ipv6nd.c diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.14 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.15 --- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.14 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/ipv6nd.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv6nd.c,v 1.14 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: ipv6nd.c,v 1.15 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -1610,7 +1610,7 @@ ipv6nd_startrs(struct interface *ifp) MAX_RTR_SOLICITATION_DELAY * 1000000); timernorm(&tv); syslog(LOG_DEBUG, - "%s: delaying IPv6 router solictation for %0.1f seconds", + "%s: delaying IPv6 router solicitation for %0.1f seconds", ifp->name, timeval_to_double(&tv)); eloop_timeout_add_tv(ifp->ctx->eloop, &tv, ipv6nd_startrs1, ifp); return; Index: src/external/bsd/dhcpcd/dist/script.c diff -u src/external/bsd/dhcpcd/dist/script.c:1.11 src/external/bsd/dhcpcd/dist/script.c:1.12 --- src/external/bsd/dhcpcd/dist/script.c:1.11 Fri Oct 17 23:42:24 2014 +++ src/external/bsd/dhcpcd/dist/script.c Wed Oct 29 01:08:31 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: script.c,v 1.11 2014/10/17 23:42:24 roy Exp $"); + __RCSID("$NetBSD: script.c,v 1.12 2014/10/29 01:08:31 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -338,7 +338,11 @@ make_env(const struct interface *ifp, co } } *--p = '\0'; - if (strcmp(reason, "TEST") == 0) { + if (strcmp(reason, "TEST") == 0 || + strcmp(reason, "PREINIT") == 0 || + strcmp(reason, "CARRIER") == 0 || + strcmp(reason, "UNKNOWN") == 0) + { env[9] = strdup("if_up=false"); env[10] = strdup("if_down=false"); } else if (1 == 2 /* appease ifdefs */