Module Name: src Committed By: roy Date: Sat May 16 23:31:32 UTC 2015
Modified Files: src/external/bsd/dhcpcd/dist: arp.c arp.h auth.h common.c common.h config.h control.c defs.h dhcp-common.c dhcp-common.h dhcp.c dhcp6.c dhcpcd-definitions.conf dhcpcd-embedded.c dhcpcd-embedded.h dhcpcd-run-hooks.8.in dhcpcd.8.in dhcpcd.c dhcpcd.conf.5.in dhcpcd.h eloop.c eloop.h if-bsd.c if-options.c if-options.h ipv4.c ipv4.h ipv6.c ipv6.h ipv6nd.c ipv6nd.h script.c src/external/bsd/dhcpcd/dist/dhcpcd-hooks: 20-resolv.conf Log Message: Sync To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 src/external/bsd/dhcpcd/dist/arp.c \ src/external/bsd/dhcpcd/dist/common.c \ src/external/bsd/dhcpcd/dist/dhcp6.c src/external/bsd/dhcpcd/dist/ipv6.h cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/arp.h cvs rdiff -u -r1.8 -r1.9 src/external/bsd/dhcpcd/dist/auth.h \ 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/dhcp-common.c \ src/external/bsd/dhcpcd/dist/dhcp-common.h \ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c \ src/external/bsd/dhcpcd/dist/eloop.h cvs rdiff -u -r1.17 -r1.18 src/external/bsd/dhcpcd/dist/defs.h cvs rdiff -u -r1.30 -r1.31 src/external/bsd/dhcpcd/dist/dhcp.c cvs rdiff -u -r1.7 -r1.8 src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf \ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in cvs rdiff -u -r1.41 -r1.42 src/external/bsd/dhcpcd/dist/dhcpcd.8.in cvs rdiff -u -r1.24 -r1.25 src/external/bsd/dhcpcd/dist/dhcpcd.c cvs rdiff -u -r1.20 -r1.21 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in \ src/external/bsd/dhcpcd/dist/if-bsd.c cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/dhcpcd.h \ src/external/bsd/dhcpcd/dist/eloop.c \ src/external/bsd/dhcpcd/dist/if-options.h \ src/external/bsd/dhcpcd/dist/ipv4.h cvs rdiff -u -r1.23 -r1.24 src/external/bsd/dhcpcd/dist/if-options.c \ src/external/bsd/dhcpcd/dist/ipv6nd.c cvs rdiff -u -r1.14 -r1.15 src/external/bsd/dhcpcd/dist/ipv4.c cvs rdiff -u -r1.11 -r1.12 src/external/bsd/dhcpcd/dist/ipv6.c \ src/external/bsd/dhcpcd/dist/ipv6nd.h cvs rdiff -u -r1.19 -r1.20 src/external/bsd/dhcpcd/dist/script.c cvs rdiff -u -r1.6 -r1.7 \ src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf 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.12 src/external/bsd/dhcpcd/dist/arp.c:1.13 --- src/external/bsd/dhcpcd/dist/arp.c:1.12 Sat May 2 15:18:36 2015 +++ src/external/bsd/dhcpcd/dist/arp.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: arp.c,v 1.12 2015/05/02 15:18:36 roy Exp $"); + __RCSID("$NetBSD: arp.c,v 1.13 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -297,17 +297,19 @@ arp_probe(struct arp_state *astate) arp_probe1(astate); } -static struct arp_state * +struct arp_state * arp_find(struct interface *ifp, const struct in_addr *addr) { struct arp_state *astate; struct dhcp_state *state; - state = D_STATE(ifp); + if ((state = D_STATE(ifp)) == NULL) + goto out; TAILQ_FOREACH(astate, &state->arp_states, next) { if (astate->addr.s_addr == addr->s_addr && astate->iface == ifp) return astate; } +out: errno = ESRCH; return NULL; } @@ -380,7 +382,7 @@ arp_close(struct interface *ifp) return; if (state->arp_fd != -1) { - eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0); + eloop_event_delete(ifp->ctx->eloop, state->arp_fd); close(state->arp_fd); state->arp_fd = -1; } Index: src/external/bsd/dhcpcd/dist/common.c diff -u src/external/bsd/dhcpcd/dist/common.c:1.12 src/external/bsd/dhcpcd/dist/common.c:1.13 --- src/external/bsd/dhcpcd/dist/common.c:1.12 Sat May 2 15:18:36 2015 +++ src/external/bsd/dhcpcd/dist/common.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: common.c,v 1.12 2015/05/02 15:18:36 roy Exp $"); + __RCSID("$NetBSD: common.c,v 1.13 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -28,11 +28,6 @@ * SUCH DAMAGE. */ -#ifdef __APPLE__ -# include <mach/mach_time.h> -# include <mach/kern_return.h> -#endif - #include <sys/param.h> #include <sys/time.h> @@ -84,64 +79,6 @@ get_hostname(char *buf, size_t buflen, i return buf; } -/* Handy function to get the time. - * We only care about time advancements, not the actual time itself - * Which is why we use CLOCK_MONOTONIC, but it is not available on all - * platforms. - */ -#define NO_MONOTONIC "host does not support a monotonic clock - timing can skew" -int -get_monotonic(struct timespec *ts) -{ - -#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, ts); -#elif defined(__APPLE__) - /* We can use mach kernel functions here. - * This is crap though - why can't they implement clock_gettime?*/ - static struct mach_timebase_info info = { 0, 0 }; - static double factor = 0.0; - uint64_t nano; - long rem; - - if (!posix_clock_set) { - if (mach_timebase_info(&info) == KERN_SUCCESS) { - factor = (double)info.numer / (double)info.denom; - clock_monotonic = posix_clock_set = 1; - } - } - if (clock_monotonic) { - nano = mach_absolute_time(); - if ((info.denom != 1 || info.numer != 1) && factor != 0.0) - nano *= factor; - ts->tv_sec = nano / NSEC_PER_SEC; - ts->tv_nsec = nano % NSEC_PER_SEC; - if (ts->tv_nsec < 0) { - ts->tv_sec--; - ts->tv_nsec += NSEC_PER_SEC; - } - return 0; - } -#endif - -#if 0 - /* Something above failed, so fall back to gettimeofday */ - if (!posix_clock_set) { - logger(NULL, LOG_WARNING, NO_MONOTONIC); - posix_clock_set = 1; - } -#endif - { - struct timeval tv; - if (gettimeofday(&tv, NULL) == 0) { - TIMEVAL_TO_TIMESPEC(&tv, ts); - return 0; - } - } - - return -1; -} - #if USE_LOGFILE void logger_open(struct dhcpcd_ctx *ctx) @@ -269,42 +206,64 @@ logger(struct dhcpcd_ctx *ctx, int pri, ssize_t setvar(struct dhcpcd_ctx *ctx, - char ***e, const char *prefix, const char *var, const char *value) + char **e, const char *prefix, const char *var, const char *value) { size_t len = strlen(var) + strlen(value) + 3; if (prefix) len += strlen(prefix) + 1; - **e = malloc(len); - if (**e == NULL) { + *e = malloc(len); + if (*e == NULL) { logger(ctx, LOG_ERR, "%s: %m", __func__); return -1; } if (prefix) - snprintf(**e, len, "%s_%s=%s", prefix, var, value); + snprintf(*e, len, "%s_%s=%s", prefix, var, value); else - snprintf(**e, len, "%s=%s", var, value); - (*e)++; + snprintf(*e, len, "%s=%s", var, value); return (ssize_t)len; } ssize_t setvard(struct dhcpcd_ctx *ctx, - char ***e, const char *prefix, const char *var, size_t value) + char **e, const char *prefix, const char *var, size_t value) { + char buffer[32]; snprintf(buffer, sizeof(buffer), "%zu", value); return setvar(ctx, e, prefix, var, buffer); } +ssize_t +addvar(struct dhcpcd_ctx *ctx, + char ***e, const char *prefix, const char *var, const char *value) +{ + ssize_t len; + + len = setvar(ctx, *e, prefix, var, value); + if (len != -1) + (*e)++; + return (ssize_t)len; +} + +ssize_t +addvard(struct dhcpcd_ctx *ctx, + char ***e, const char *prefix, const char *var, size_t value) +{ + char buffer[32]; + + snprintf(buffer, sizeof(buffer), "%zu", value); + return addvar(ctx, e, prefix, var, buffer); +} + time_t uptime(void) { struct timespec tv; - if (get_monotonic(&tv) == -1) + if (clock_gettime(CLOCK_MONOTONIC, &tv) == -1) return -1; return tv.tv_sec; } Index: src/external/bsd/dhcpcd/dist/dhcp6.c diff -u src/external/bsd/dhcpcd/dist/dhcp6.c:1.12 src/external/bsd/dhcpcd/dist/dhcp6.c:1.13 --- src/external/bsd/dhcpcd/dist/dhcp6.c:1.12 Sat May 2 15:18:36 2015 +++ src/external/bsd/dhcpcd/dist/dhcp6.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcp6.c,v 1.12 2015/05/02 15:18:36 roy Exp $"); + __RCSID("$NetBSD: dhcp6.c,v 1.13 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -1022,6 +1022,9 @@ dhcp6_sendmessage(struct interface *ifp, const char *broad_uni; const struct in6_addr alldhcp = IN6ADDR_LINKLOCAL_ALLDHCP_INIT; + if (!callback && ifp->carrier == LINK_DOWN) + return 0; + memset(&dst, 0, sizeof(dst)); dst.sin6_family = AF_INET6; dst.sin6_port = htons(DHCP6_SERVER_PORT); @@ -1109,16 +1112,17 @@ dhcp6_sendmessage(struct interface *ifp, } logsend: - logger(ifp->ctx, LOG_DEBUG, - "%s: %s %s (xid 0x%02x%02x%02x)," - " next in %0.1f seconds", - ifp->name, - broad_uni, - dhcp6_get_op(state->send->type), - state->send->xid[0], - state->send->xid[1], - state->send->xid[2], - timespec_to_double(&state->RT)); + if (ifp->carrier != LINK_DOWN) + logger(ifp->ctx, LOG_DEBUG, + "%s: %s %s (xid 0x%02x%02x%02x)," + " next in %0.1f seconds", + ifp->name, + broad_uni, + dhcp6_get_op(state->send->type), + state->send->xid[0], + state->send->xid[1], + state->send->xid[2], + timespec_to_double(&state->RT)); /* Wait the initial delay */ if (state->IMD) { @@ -1129,6 +1133,9 @@ logsend: } } + if (ifp->carrier == LINK_DOWN) + return 0; + /* Update the elapsed time */ dhcp6_updateelapsed(ifp, state->send, state->send_len); if (ifp->options->auth.options & DHCPCD_AUTH_SEND && @@ -2109,7 +2116,7 @@ dhcp6_validatelease(struct interface *if state->renew = state->rebind = state->expire = 0; state->lowpl = ND6_INFINITE_LIFETIME; if (!acquired) { - get_monotonic(&aq); + clock_gettime(CLOCK_MONOTONIC, &aq); acquired = &aq; } nia = dhcp6_findia(ifp, m, len, sfrom, acquired); @@ -2184,7 +2191,7 @@ dhcp6_readlease(struct interface *ifp, i if ((now = time(NULL)) == -1) goto ex; - get_monotonic(&acquired); + clock_gettime(CLOCK_MONOTONIC, &acquired); acquired.tv_sec -= now - st.st_mtime; /* Check to see if the lease is still valid */ @@ -2618,7 +2625,7 @@ dhcp6_handledata(void *arg) if (bytes == -1) { logger(dctx, LOG_ERR, "%s: recvmsg: %m", __func__); close(ctx->dhcp_fd); - eloop_event_delete(dctx->eloop, ctx->dhcp_fd, 0); + eloop_event_delete(dctx->eloop, ctx->dhcp_fd); ctx->dhcp_fd = -1; return; } @@ -3394,7 +3401,7 @@ dhcp6_freedrop(struct interface *ifp, in } if (ifp == NULL && ctx->ipv6) { if (ctx->ipv6->dhcp_fd != -1) { - eloop_event_delete(ctx->eloop, ctx->ipv6->dhcp_fd, 0); + eloop_event_delete(ctx->eloop, ctx->ipv6->dhcp_fd); close(ctx->ipv6->dhcp_fd); ctx->ipv6->dhcp_fd = -1; } Index: src/external/bsd/dhcpcd/dist/ipv6.h diff -u src/external/bsd/dhcpcd/dist/ipv6.h:1.12 src/external/bsd/dhcpcd/dist/ipv6.h:1.13 --- src/external/bsd/dhcpcd/dist/ipv6.h:1.12 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/ipv6.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ipv6.h,v 1.12 2015/05/02 15:18:37 roy Exp $ */ +/* $NetBSD: ipv6.h,v 1.13 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -33,6 +33,19 @@ #include <sys/uio.h> #include <netinet/in.h> +#ifndef __linux__ +# ifndef __QNX__ +# include <sys/endian.h> +# endif +# include <net/if.h> +# ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */ +# include <net/if_var.h> +# endif +# ifndef __sun +# include <netinet6/in6_var.h> +# endif +#endif + #include "config.h" #include "dhcpcd.h" @@ -268,6 +281,7 @@ void ipv6_buildroutes(struct dhcpcd_ctx #else #define ipv6_init(a) (NULL) #define ipv6_start(a) (-1) +#define ipv6_iffindaddr(a, b) (NULL) #define ipv6_free_ll_callbacks(a) {} #define ipv6_free(a) {} #define ipv6_drop(a) {} Index: src/external/bsd/dhcpcd/dist/arp.h diff -u src/external/bsd/dhcpcd/dist/arp.h:1.9 src/external/bsd/dhcpcd/dist/arp.h:1.10 --- src/external/bsd/dhcpcd/dist/arp.h:1.9 Sat May 2 15:18:36 2015 +++ src/external/bsd/dhcpcd/dist/arp.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: arp.h,v 1.9 2015/05/02 15:18:36 roy Exp $ */ +/* $NetBSD: arp.h,v 1.10 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -75,6 +75,7 @@ struct arp_state *arp_new(struct interfa void arp_cancel(struct arp_state *); void arp_free(struct arp_state *); void arp_free_but(struct arp_state *); +struct arp_state *arp_find(struct interface *, const struct in_addr *); void arp_close(struct interface *); void arp_handleifa(int, struct interface *, const struct in_addr *, int); Index: src/external/bsd/dhcpcd/dist/auth.h diff -u src/external/bsd/dhcpcd/dist/auth.h:1.8 src/external/bsd/dhcpcd/dist/auth.h:1.9 --- src/external/bsd/dhcpcd/dist/auth.h:1.8 Fri Jan 30 09:47:05 2015 +++ src/external/bsd/dhcpcd/dist/auth.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: auth.h,v 1.8 2015/01/30 09:47:05 roy Exp $ */ +/* $NetBSD: auth.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -32,6 +32,10 @@ #include "config.h" +#ifdef HAVE_SYS_QUEUE_H +#include <sys/queue.h> +#endif + #define DHCPCD_AUTH_SEND (1 << 0) #define DHCPCD_AUTH_REQUIRE (1 << 1) #define DHCPCD_AUTH_RDM_COUNTER (1 << 2) Index: src/external/bsd/dhcpcd/dist/common.h diff -u src/external/bsd/dhcpcd/dist/common.h:1.8 src/external/bsd/dhcpcd/dist/common.h:1.9 --- src/external/bsd/dhcpcd/dist/common.h:1.8 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/common.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: common.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */ +/* $NetBSD: common.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -56,8 +56,8 @@ #define USEC_PER_SEC 1000000L #define USEC_PER_NSEC 1000L #define NSEC_PER_SEC 1000000000L +#define NSEC_PER_MSEC 1000000L #define MSEC_PER_SEC 1000L -#define MSEC_PER_NSEC 1000000L /* Some systems don't define timespec macros */ #ifndef timespecclear @@ -97,12 +97,12 @@ } while (0 /* CONSTCOND */); #define ts_to_ms(ms, tv) do { \ ms = (tv)->tv_sec * MSEC_PER_SEC; \ - ms += (tv)->tv_nsec / MSEC_PER_NSEC; \ + ms += (tv)->tv_nsec / NSEC_PER_MSEC; \ } while (0 /* CONSTCOND */); #define ms_to_ts(tv, ms) do { \ (tv)->tv_sec = ms / MSEC_PER_SEC; \ (tv)->tv_nsec = (suseconds_t)(ms - ((tv)->tv_sec * MSEC_PER_SEC)) \ - * MSEC_PER_NSEC; \ + * NSEC_PER_MSEC; \ } while (0 /* CONSTCOND */); #ifndef TIMEVAL_TO_TIMESPEC @@ -140,6 +140,10 @@ # endif #endif +#ifndef __arraycount +#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) +#endif + /* We don't really need this as our supported systems define __restrict * automatically for us, but it is here for completeness. */ #ifndef __restrict @@ -182,8 +186,12 @@ void logger_close(struct dhcpcd_ctx *); #endif ssize_t setvar(struct dhcpcd_ctx *, - char ***, const char *, const char *, const char *); + char **, const char *, const char *, const char *); ssize_t setvard(struct dhcpcd_ctx *, + char **, const char *, const char *, size_t); +ssize_t addvar(struct dhcpcd_ctx *, + char ***, const char *, const char *, const char *); +ssize_t addvard(struct dhcpcd_ctx *, char ***, const char *, const char *, size_t); time_t uptime(void); Index: src/external/bsd/dhcpcd/dist/config.h diff -u src/external/bsd/dhcpcd/dist/config.h:1.8 src/external/bsd/dhcpcd/dist/config.h:1.9 --- src/external/bsd/dhcpcd/dist/config.h:1.8 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/config.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: config.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */ +/* $NetBSD: config.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */ /* netbsd */ #define SYSCONFDIR "/etc" @@ -7,7 +7,7 @@ #define LIBEXECDIR "/libexec" #define DBDIR "/var/db" #define RUNDIR "/var/run" -#include <sys/queue.h> +#define HAVE_SYS_QUEUE_H #define HAVE_SPAWN_H #define HAVE_KQUEUE #define HAVE_KQUEUE1 Index: src/external/bsd/dhcpcd/dist/control.c diff -u src/external/bsd/dhcpcd/dist/control.c:1.8 src/external/bsd/dhcpcd/dist/control.c:1.9 --- src/external/bsd/dhcpcd/dist/control.c:1.8 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/control.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: control.c,v 1.8 2015/03/26 10:26:37 roy Exp $"); + __RCSID("$NetBSD: control.c,v 1.9 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -95,7 +95,7 @@ control_delete(struct fd_list *fd) { TAILQ_REMOVE(&fd->ctx->control_fds, fd, next); - eloop_event_delete(fd->ctx->eloop, fd->fd, 0); + eloop_event_delete(fd->ctx->eloop, fd->fd); close(fd->fd); control_queue_free(fd); free(fd); @@ -306,14 +306,14 @@ control_stop(struct dhcpcd_ctx *ctx) if (ctx->control_fd == -1) return 0; - eloop_event_delete(ctx->eloop, ctx->control_fd, 0); + eloop_event_delete(ctx->eloop, ctx->control_fd); close(ctx->control_fd); ctx->control_fd = -1; if (unlink(ctx->control_sock) == -1) retval = -1; if (ctx->control_unpriv_fd != -1) { - eloop_event_delete(ctx->eloop, ctx->control_unpriv_fd, 0); + eloop_event_delete(ctx->eloop, ctx->control_unpriv_fd); close(ctx->control_unpriv_fd); ctx->control_unpriv_fd = -1; if (unlink(UNPRIVSOCKET) == -1) @@ -323,7 +323,7 @@ control_stop(struct dhcpcd_ctx *ctx) freeit: while ((l = TAILQ_FIRST(&ctx->control_fds))) { TAILQ_REMOVE(&ctx->control_fds, l, next); - eloop_event_delete(ctx->eloop, l->fd, 0); + eloop_event_delete(ctx->eloop, l->fd); close(l->fd); control_queue_free(l); free(l); @@ -402,7 +402,7 @@ control_writeone(void *arg) TAILQ_INSERT_TAIL(&fd->free_queue, data, next); if (TAILQ_FIRST(&fd->queue) == NULL) - eloop_event_delete(fd->ctx->eloop, fd->fd, 1); + eloop_event_remove_writecb(fd->ctx->eloop, fd->fd); } int Index: src/external/bsd/dhcpcd/dist/dhcp-common.c diff -u src/external/bsd/dhcpcd/dist/dhcp-common.c:1.8 src/external/bsd/dhcpcd/dist/dhcp-common.c:1.9 --- src/external/bsd/dhcpcd/dist/dhcp-common.c:1.8 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/dhcp-common.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcp-common.c,v 1.8 2015/03/26 10:26:37 roy Exp $"); + __RCSID("$NetBSD: dhcp-common.c,v 1.9 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -79,6 +79,8 @@ dhcp_print_option_encoding(const struct printf(" ip6address"); else if (opt->type & FLAG) printf(" flag"); + else if (opt->type & BITFLAG) + printf(" bitflags"); else if (opt->type & RFC3397) printf(" domain"); else if (opt->type & DOMAIN) @@ -89,9 +91,9 @@ dhcp_print_option_encoding(const struct printf(" raw"); else if (opt->type & BINHEX) printf(" binhex"); - else if (opt->type & STRING) + else if (opt->type & STRING) printf(" string"); - if (opt->type & RFC3361) + if (opt->type & RFC3361) printf(" rfc3361"); if (opt->type & RFC3442) printf(" rfc3442"); @@ -562,7 +564,7 @@ dhcp_optlen(const struct dhcp_opt *opt, sz = sizeof(uint32_t); else if (opt->type & UINT16) sz = sizeof(uint16_t); - else if (opt->type & UINT8) + else if (opt->type & (UINT8 | BITFLAG)) sz = sizeof(uint8_t); else if (opt->type & ADDRIPV6) sz = ADDR6SZ; @@ -572,15 +574,9 @@ dhcp_optlen(const struct dhcp_opt *opt, return (dl < sz ? 0 : sz); } -#ifdef INET6 -#define PO_IFNAME -#else -#define PO_IFNAME __unused -#endif - -ssize_t -print_option(char *s, size_t len, int type, const uint8_t *data, size_t dl, - PO_IFNAME const char *ifname) +static ssize_t +print_option(char *s, size_t len, const struct dhcp_opt *opt, + const uint8_t *data, size_t dl, const char *ifname) { const uint8_t *e, *t; uint16_t u16; @@ -592,7 +588,11 @@ print_option(char *s, size_t len, int ty size_t l; char *tmp; - if (type & RFC3397) { +#ifndef INET6 + UNUSED(ifname); +#endif + + if (opt->type & RFC3397) { sl = decode_rfc3397(NULL, 0, data, dl); if (sl == 0 || sl == -1) return sl; @@ -601,32 +601,32 @@ print_option(char *s, size_t len, int ty if (tmp == NULL) return -1; decode_rfc3397(tmp, l, data, dl); - sl = print_string(s, len, type, (uint8_t *)tmp, l - 1); + sl = print_string(s, len, opt->type, (uint8_t *)tmp, l - 1); free(tmp); return sl; } #ifdef INET - if (type & RFC3361) { + if (opt->type & RFC3361) { if ((tmp = decode_rfc3361(data, dl)) == NULL) return -1; l = strlen(tmp); - sl = print_string(s, len, type, (uint8_t *)tmp, l); + sl = print_string(s, len, opt->type, (uint8_t *)tmp, l); free(tmp); return sl; } - if (type & RFC3442) + if (opt->type & RFC3442) return decode_rfc3442(s, len, data, dl); - if (type & RFC5969) + if (opt->type & RFC5969) return decode_rfc5969(s, len, data, dl); #endif - if (type & STRING) - return print_string(s, len, type, data, dl); + if (opt->type & STRING) + return print_string(s, len, opt->type, data, dl); - if (type & FLAG) { + if (opt->type & FLAG) { if (s) { *s++ = '1'; *s = '\0'; @@ -634,27 +634,50 @@ print_option(char *s, size_t len, int ty return 1; } + if (opt->type & BITFLAG) { + /* bitflags are a string, MSB first, such as ABCDEFGH + * where A is 10000000, B is 01000000, etc. */ + bytes = 0; + for (l = 0, sl = sizeof(opt->bitflags) - 1; + l < sizeof(opt->bitflags); + l++, sl--) + { + /* Don't print NULL or 0 flags */ + if (opt->bitflags[l] != '\0' && + opt->bitflags[l] != '0' && + *data & (1 << sl)) + { + if (s) + *s++ = opt->bitflags[l]; + bytes++; + } + } + if (s) + *s = '\0'; + return bytes; + } + if (!s) { - if (type & UINT8) + if (opt->type & UINT8) l = 3; - else if (type & UINT16) { + else if (opt->type & UINT16) { l = 5; dl /= 2; - } else if (type & SINT16) { + } else if (opt->type & SINT16) { l = 6; dl /= 2; - } else if (type & UINT32) { + } else if (opt->type & UINT32) { l = 10; dl /= 4; - } else if (type & SINT32) { + } else if (opt->type & SINT32) { l = 11; dl /= 4; - } else if (type & ADDRIPV4) { + } else if (opt->type & ADDRIPV4) { l = 16; dl /= 4; } #ifdef INET6 - else if (type & ADDRIPV6) { + else if (opt->type & ADDRIPV6) { e = data + dl; l = 0; while (data < e) { @@ -683,36 +706,36 @@ print_option(char *s, size_t len, int ty bytes++; len--; } - if (type & UINT8) { + if (opt->type & UINT8) { sl = snprintf(s, len, "%u", *data); data++; - } else if (type & UINT16) { + } else if (opt->type & UINT16) { memcpy(&u16, data, sizeof(u16)); u16 = ntohs(u16); sl = snprintf(s, len, "%u", u16); data += sizeof(u16); - } else if (type & SINT16) { + } else if (opt->type & SINT16) { memcpy(&u16, data, sizeof(u16)); s16 = (int16_t)ntohs(u16); sl = snprintf(s, len, "%d", s16); data += sizeof(u16); - } else if (type & UINT32) { + } else if (opt->type & UINT32) { memcpy(&u32, data, sizeof(u32)); u32 = ntohl(u32); sl = snprintf(s, len, "%u", u32); data += sizeof(u32); - } else if (type & SINT32) { + } else if (opt->type & SINT32) { memcpy(&u32, data, sizeof(u32)); s32 = (int32_t)ntohl(u32); sl = snprintf(s, len, "%d", s32); data += sizeof(u32); - } else if (type & ADDRIPV4) { + } else if (opt->type & ADDRIPV4) { memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); sl = snprintf(s, len, "%s", inet_ntoa(addr)); data += sizeof(addr.s_addr); } #ifdef INET6 - else if (type & ADDRIPV6) { + else if (opt->type & ADDRIPV6) { ssize_t r; r = ipv6_printaddr(s, len, data, ifname); @@ -776,7 +799,7 @@ dhcp_envoption1(struct dhcpcd_ctx *ctx, if (opt->len && opt->len < ol) ol = opt->len; - len = print_option(NULL, 0, opt->type, od, ol, ifname); + len = print_option(NULL, 0, opt, od, ol, ifname); if (len < 0) return 0; if (vname) @@ -798,7 +821,7 @@ dhcp_envoption1(struct dhcpcd_ctx *ctx, else v += snprintf(val, e, "%s=", prefix); if (len != 0) - print_option(v, (size_t)len + 1, opt->type, od, ol, ifname); + print_option(v, (size_t)len + 1, opt, od, ol, ifname); return e; } @@ -819,7 +842,8 @@ dhcp_envoption(struct dhcpcd_ctx *ctx, c /* If no embedded or encapsulated options, it's easy */ if (opt->embopts_len == 0 && opt->encopts_len == 0) { - if (dhcp_envoption1(ctx, env == NULL ? NULL : &env[0], + if (!(opt->type & RESERVED) && + dhcp_envoption1(ctx, env == NULL ? NULL : &env[0], prefix, opt, 1, od, ol, ifname)) return 1; return 0; @@ -860,10 +884,12 @@ dhcp_envoption(struct dhcpcd_ctx *ctx, c /* Use the option prefix if the embedded option * name is different. * This avoids new_fqdn_fqdn which would be silly. */ - ov = strcmp(opt->var, eopt->var); - if (dhcp_envoption1(ctx, env == NULL ? NULL : &env[n], - pfx, eopt, ov, od, e, ifname)) - n++; + if (!(eopt->type & RESERVED)) { + ov = strcmp(opt->var, eopt->var); + if (dhcp_envoption1(ctx, env == NULL ? NULL : &env[n], + pfx, eopt, ov, od, e, ifname)) + n++; + } od += e; ol -= e; } Index: src/external/bsd/dhcpcd/dist/dhcp-common.h diff -u src/external/bsd/dhcpcd/dist/dhcp-common.h:1.8 src/external/bsd/dhcpcd/dist/dhcp-common.h:1.9 --- src/external/bsd/dhcpcd/dist/dhcp-common.h:1.8 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/dhcp-common.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: dhcp-common.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */ +/* $NetBSD: dhcp-common.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -68,6 +68,8 @@ #define RAW (1 << 23) #define ESCSTRING (1 << 24) #define ESCFILE (1 << 25) +#define BITFLAG (1 << 26) +#define RESERVED (1 << 27) struct dhcp_opt { uint32_t option; /* Also used for IANA Enterpise Number */ @@ -76,6 +78,7 @@ struct dhcp_opt { char *var; int index; /* Index counter for many instances of the same option */ + char bitflags[8]; /* Embedded options. * The option code is irrelevant here. */ @@ -105,8 +108,6 @@ int make_option_mask(const struct dhcp_o size_t encode_rfc1035(const char *src, uint8_t *dst); ssize_t decode_rfc3397(char *, size_t, const uint8_t *, size_t); ssize_t print_string(char *, size_t, int, const uint8_t *, size_t); -ssize_t print_option(char *, size_t, int, const uint8_t *, size_t, - const char *); int dhcp_set_leasefile(char *, size_t, int, const struct interface *, const char *); Index: src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c diff -u src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.8 src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.9 --- src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.8 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcpcd-embedded.c,v 1.8 2015/03/26 10:26:37 roy Exp $"); + __RCSID("$NetBSD: dhcpcd-embedded.c,v 1.9 2015/05/16 23:31:32 roy Exp $"); /* * DO NOT EDIT! @@ -122,7 +122,7 @@ const char * const dhcpcd_embedded_conf[ "embed ascii scope_list", "define 80 norequest flag rapid_commit", "define 81 embed fqdn", -"embed byte flags", +"embed bitflags=0000NEOS flags", "embed byte rcode1", "embed byte rcode2", "embed domain fqdn", @@ -201,6 +201,26 @@ const char * const dhcpcd_embedded_conf[ "encap 0 string nvt", "encap 1 binhex vpn_id", "encap 255 flag global", +"definend 1 binhex source_address", +"definend 2 binhex target_address", +"definend 3 index embed prefix_information", +"embed byte length", +"embed bitflags=LA flags", +"embed uint32 vltime", +"embed uint32 pltime", +"embed uint32 reserved", +"embed array ip6address prefix", +"definend 5 embed mtu", +"embed uint16 reserved", +"embed uint32 mtu", +"definend 25 index embed rdnss", +"embed uint16 reserved", +"embed uint32 lifetime", +"embed array ip6address servers", +"definend 31 index embed dnssl", +"embed uint16 reserved", +"embed uint32 lifetime", +"embed domain search", "define6 1 binhex client_id", "define6 2 binhex server_id", "define6 3 norequest index embed ia_na", @@ -272,7 +292,7 @@ const char * const dhcpcd_embedded_conf[ "embed binhex remote_id", "define6 38 binhex subscriber_id", "define6 39 embed fqdn", -"embed byte flags", +"embed bitflags=00000NOS flags", "embed domain fqdn", "define6 40 array ip6address pana_agent", "define6 41 string posix_timezone", Index: src/external/bsd/dhcpcd/dist/eloop.h diff -u src/external/bsd/dhcpcd/dist/eloop.h:1.8 src/external/bsd/dhcpcd/dist/eloop.h:1.9 --- src/external/bsd/dhcpcd/dist/eloop.h:1.8 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/eloop.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: eloop.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */ +/* $NetBSD: eloop.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -32,16 +32,79 @@ #include <time.h> +#ifdef HAVE_CONFIG_H #include "config.h" +#else +/* Attempt to autodetect kqueue or epoll. + * If we can't, the system has to support pselect, which is a POSIX call. */ +#if (defined(__unix__) || defined(unix)) && !defined(USG) +#include <sys/param.h> +#endif +#if defined(BSD) +/* Assume BSD has a working sys/queue.h and kqueue(2) interface */ +#define HAVE_SYS_QUEUE_H +#define HAVE_KQUEUE +#elif defined(__linux__) +/* Assume Linux has a working epoll(3) interface */ +#define HAVE_EPOLL +#endif +#endif + +/* Our structures require TAILQ macros, which really every libc should + * ship as they are useful beyond belief. + * Sadly some libc's don't have sys/queue.h and some that do don't have + * the TAILQ_FOREACH macro. For those that don't, the application using + * this implementation will need to ship a working queue.h somewhere. + * If we don't have sys/queue.h found in config.h, then + * allow QUEUE_H to override loading queue.h in the current directory. */ +#ifndef TAILQ_FOREACH +#ifdef HAVE_SYS_QUEUE_H +#include <sys/queue.h> +#elif defined(QUEUE_H) +#define __QUEUE_HEADER(x) #x +#define _QUEUE_HEADER(x) __QUEUE_HEADER(x) +#include _QUEUE_HEADER(QUEUE_H) +#else +#include "queue.h" +#endif +#endif +/* Some systems don't define timespec macros */ +#ifndef timespecclear +#define timespecclear(tsp) (tsp)->tv_sec = (time_t)((tsp)->tv_nsec = 0L) +#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec) +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#define timespecadd(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ + if ((vsp)->tv_nsec >= 1000000000L) { \ + (vsp)->tv_sec++; \ + (vsp)->tv_nsec -= 1000000000L; \ + } \ + } while (/* CONSTCOND */ 0) +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (/* CONSTCOND */ 0) +#endif + +/* eloop queues are really only for deleting timeouts registered + * for a function or object. + * The idea being that one interface as different timeouts for + * say DHCP and DHCPv6. */ #ifndef ELOOP_QUEUE #define ELOOP_QUEUE 1 #endif -/* EXIT_FAILURE is a non zero value and EXIT_SUCCESS is zero. - * To add a CONTINUE definition, simply do the opposite of EXIT_FAILURE. */ -#define ELOOP_CONTINUE -EXIT_FAILURE - struct eloop_event { TAILQ_ENTRY(eloop_event) next; int fd; @@ -62,9 +125,7 @@ struct eloop_timeout { int queue; }; -struct eloop_ctx { - struct dhcpcd_ctx *ctx; - +struct eloop { size_t events_len; TAILQ_HEAD (event_head, eloop_event) events; struct event_head free_events; @@ -74,6 +135,10 @@ struct eloop_ctx { void (*timeout0)(void *); void *timeout0_arg; + const int *signals; + size_t signals_len; + void (*signal_cb)(int, void *); + void *signal_cb_ctx; #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) int poll_fd; @@ -86,33 +151,43 @@ struct eloop_ctx { int exitcode; }; -#define eloop_timeout_add_tv(a, b, c, d) \ - eloop_q_timeout_add_tv(a, ELOOP_QUEUE, b, c, d) -#define eloop_timeout_add_sec(a, b, c, d) \ - eloop_q_timeout_add_sec(a, ELOOP_QUEUE, b, c, d) -#define eloop_timeout_delete(a, b, c) \ - eloop_q_timeout_delete(a, ELOOP_QUEUE, b, c) - -int eloop_event_add(struct eloop_ctx *, int, +int eloop_event_add(struct eloop *, int, void (*)(void *), void *, void (*)(void *), void *); -void eloop_event_delete(struct eloop_ctx *, int, int); -int eloop_q_timeout_add_sec(struct eloop_ctx *, int queue, - time_t, void (*)(void *), void *); -int eloop_q_timeout_add_tv(struct eloop_ctx *, int queue, +#define eloop_event_delete(eloop, fd) \ + eloop_event_delete_write((eloop), (fd), 0) +#define eloop_event_remove_writecb(eloop, fd) \ + eloop_event_delete_write((eloop), (fd), 1) +void eloop_event_delete_write(struct eloop *, int, int); + +#define eloop_timeout_add_tv(eloop, tv, cb, ctx) \ + eloop_q_timeout_add_tv((eloop), ELOOP_QUEUE, (tv), (cb), (ctx)) +#define eloop_timeout_add_sec(eloop, tv, cb, ctx) \ + eloop_q_timeout_add_sec((eloop), ELOOP_QUEUE, (tv), (cb), (ctx)) +#define eloop_timeout_add_msec(eloop, ms, cb, ctx) \ + eloop_q_timeout_add_msec((eloop), ELOOP_QUEUE, (ms), (cb), (ctx)) +#define eloop_timeout_delete(eloop, cb, ctx) \ + eloop_q_timeout_delete((eloop), ELOOP_QUEUE, (cb), (ctx)) +int eloop_q_timeout_add_tv(struct eloop *, int, const struct timespec *, void (*)(void *), void *); -#if !defined(HAVE_KQUEUE) -int eloop_timeout_add_now(struct eloop_ctx *, void (*)(void *), void *); -#endif -void eloop_q_timeout_delete(struct eloop_ctx *, int, void (*)(void *), void *); -struct eloop_ctx * eloop_init(struct dhcpcd_ctx *); +int eloop_q_timeout_add_sec(struct eloop *, int, + time_t, void (*)(void *), void *); +int eloop_q_timeout_add_msec(struct eloop *, int, + long, void (*)(void *), void *); +void eloop_q_timeout_delete(struct eloop *, int, void (*)(void *), void *); + +int eloop_signal_set_cb(struct eloop *, const int *, size_t, + void (*)(int, void *), void *); +int eloop_signal_mask(struct eloop *, sigset_t *oldset); + +struct eloop * eloop_new(void); #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) -int eloop_requeue(struct eloop_ctx *); +int eloop_requeue(struct eloop *); #else -#define eloop_requeue(a) (0) +#define eloop_requeue(eloop) (0) #endif -void eloop_free(struct eloop_ctx *); -void eloop_exit(struct eloop_ctx *, int); -int eloop_start(struct eloop_ctx *); +void eloop_free(struct eloop *); +void eloop_exit(struct eloop *, int); +int eloop_start(struct eloop *, sigset_t *); #endif Index: src/external/bsd/dhcpcd/dist/defs.h diff -u src/external/bsd/dhcpcd/dist/defs.h:1.17 src/external/bsd/dhcpcd/dist/defs.h:1.18 --- src/external/bsd/dhcpcd/dist/defs.h:1.17 Sat May 2 15:18:36 2015 +++ src/external/bsd/dhcpcd/dist/defs.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: defs.h,v 1.17 2015/05/02 15:18:36 roy Exp $ */ +/* $NetBSD: defs.h,v 1.18 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -30,7 +30,7 @@ #define CONFIG_H #define PACKAGE "dhcpcd" -#define VERSION "6.8.2" +#define VERSION "6.9.0" #ifndef CONFIG # define CONFIG SYSCONFDIR "/" PACKAGE ".conf" Index: src/external/bsd/dhcpcd/dist/dhcp.c diff -u src/external/bsd/dhcpcd/dist/dhcp.c:1.30 src/external/bsd/dhcpcd/dist/dhcp.c:1.31 --- src/external/bsd/dhcpcd/dist/dhcp.c:1.30 Sat May 2 15:18:36 2015 +++ src/external/bsd/dhcpcd/dist/dhcp.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcp.c,v 1.30 2015/05/02 15:18:36 roy Exp $"); + __RCSID("$NetBSD: dhcp.c,v 1.31 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -1277,35 +1277,35 @@ dhcp_env(char **env, const char *prefix, /* Set some useful variables that we derive from the DHCP * message but are not necessarily in the options */ addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr; - setvar(ifp->ctx, &ep, prefix, "ip_address", inet_ntoa(addr)); + addvar(ifp->ctx, &ep, prefix, "ip_address", inet_ntoa(addr)); if (get_option_addr(ifp->ctx, &net, dhcp, DHO_SUBNETMASK) == -1) { net.s_addr = ipv4_getnetmask(addr.s_addr); - setvar(ifp->ctx, &ep, prefix, + addvar(ifp->ctx, &ep, prefix, "subnet_mask", inet_ntoa(net)); } snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net)); - setvar(ifp->ctx, &ep, prefix, "subnet_cidr", cidr); + addvar(ifp->ctx, &ep, prefix, "subnet_cidr", cidr); if (get_option_addr(ifp->ctx, &brd, dhcp, DHO_BROADCAST) == -1) { brd.s_addr = addr.s_addr | ~net.s_addr; - setvar(ifp->ctx, &ep, prefix, + addvar(ifp->ctx, &ep, prefix, "broadcast_address", inet_ntoa(brd)); } addr.s_addr = dhcp->yiaddr & net.s_addr; - setvar(ifp->ctx, &ep, prefix, + addvar(ifp->ctx, &ep, prefix, "network_number", inet_ntoa(addr)); } if (*dhcp->bootfile && !(overl & 1)) { print_string(safe, sizeof(safe), STRING, dhcp->bootfile, sizeof(dhcp->bootfile)); - setvar(ifp->ctx, &ep, prefix, "filename", safe); + addvar(ifp->ctx, &ep, prefix, "filename", safe); } if (*dhcp->servername && !(overl & 2)) { print_string(safe, sizeof(safe), STRING | DOMAIN, dhcp->servername, sizeof(dhcp->servername)); - setvar(ifp->ctx, &ep, prefix, "server_name", safe); + addvar(ifp->ctx, &ep, prefix, "server_name", safe); } /* Zero our indexes */ @@ -1440,7 +1440,7 @@ dhcp_close(struct interface *ifp) return; if (state->raw_fd != -1) { - eloop_event_delete(ifp->ctx->eloop, state->raw_fd, 0); + eloop_event_delete(ifp->ctx->eloop, state->raw_fd); close(state->raw_fd); state->raw_fd = -1; } @@ -1596,12 +1596,16 @@ send_message(struct interface *ifp, uint struct ipv4_addr *ia; #endif - if (!callback) + s = -1; + if (!callback) { + /* No carrier? Don't bother sending the packet. */ + if (ifp->carrier == LINK_DOWN) + return; logger(ifp->ctx, LOG_DEBUG, "%s: sending %s with xid 0x%x", ifp->name, ifo->options & DHCPCD_BOOTP ? "BOOTP" : get_dhcp_op(type), state->xid); - else { + } else { if (state->interval == 0) state->interval = 4; else { @@ -1613,6 +1617,10 @@ send_message(struct interface *ifp, uint tv.tv_nsec = (suseconds_t)arc4random_uniform( (DHCP_RAND_MAX - DHCP_RAND_MIN) * NSEC_PER_SEC); timespecnorm(&tv); + /* No carrier? Don't bother sending the packet. + * However, we do need to advance the timeout. */ + if (ifp->carrier == LINK_DOWN) + goto fail; logger(ifp->ctx, LOG_DEBUG, "%s: sending %s (xid 0x%x), next in %0.1f seconds", ifp->name, @@ -1638,8 +1646,7 @@ send_message(struct interface *ifp, uint if (s == -1 && errno != EADDRINUSE) logger(ifp->ctx, LOG_ERR, "%s: dhcp_openudp: %m", ifp->name); - } else - s = -1; + } /* If we couldn't open a UDP port for our IP address * then we cannot renew. @@ -1862,6 +1869,104 @@ dhcp_rebind(void *arg) send_rebind(ifp); } +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); +#ifdef IN_IFF_TENTATIVE + ipv4_finaliseaddr(astate->iface); + arp_close(astate->iface); +#else + dhcp_bind(astate->iface, astate); +#endif +} + +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 && + (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); + } + + /* RFC 2131 3.1.5, Client-server interaction + * NULL amsg means IN_IFF_DUPLICATED */ + if (amsg == NULL || (state->offer && + (amsg->sip.s_addr == state->offer->yiaddr || + (amsg->sip.s_addr == 0 && + amsg->tip.s_addr == state->offer->yiaddr)))) + { +#ifdef IN_IFF_DUPLICATED + struct ipv4_addr *ia; +#endif + + if (amsg) + astate->failed.s_addr = state->offer->yiaddr; + else + astate->failed = astate->addr; + arp_report_conflicted(astate, amsg); + unlink(state->leasefile); + if (!state->lease.frominfo) + dhcp_decline(astate->iface); +#ifdef IN_IFF_DUPLICATED + ia = ipv4_iffindaddr(astate->iface, &astate->addr, NULL); + if (ia) + ipv4_deladdr(astate->iface, &ia->addr, &ia->net); +#endif + 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_bind(struct interface *ifp, struct arp_state *astate) { @@ -1872,6 +1977,9 @@ dhcp_bind(struct interface *ifp, struct if (state->state == DHS_BOUND) goto applyaddr; +#ifdef IN_IFF_TENTATIVE + state->added |= STATE_TENTATIVE; +#endif state->reason = NULL; free(state->old); state->old = state->new; @@ -1989,6 +2097,16 @@ dhcp_bind(struct interface *ifp, struct "%s: write_lease: %m", __func__); applyaddr: +#ifdef IN_IFF_TENTATIVE + if (astate == NULL) { + astate = arp_new(ifp, &lease->addr); + if (astate) { + astate->probed_cb = dhcp_arp_probed; + astate->conflicted_cb = dhcp_arp_conflicted; + } + } +#endif + ipv4_applyaddr(ifp); if (ifo->options & DHCPCD_ARP && !(ifp->ctx->options & DHCPCD_FORKED)) @@ -2345,104 +2463,6 @@ 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); -#ifdef IN_IFF_TENTATIVE - ipv4_finaliseaddr(astate->iface); - arp_close(astate->iface); -#else - dhcp_bind(astate->iface, astate); -#endif -} - -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 && - (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); - } - - /* RFC 2131 3.1.5, Client-server interaction - * NULL amsg means IN_IFF_DUPLICATED */ - if (amsg == NULL || (state->offer && - (amsg->sip.s_addr == state->offer->yiaddr || - (amsg->sip.s_addr == 0 && - amsg->tip.s_addr == state->offer->yiaddr)))) - { -#ifdef IN_IFF_DUPLICATED - struct ipv4_addr *ia; -#endif - - if (amsg) - astate->failed.s_addr = state->offer->yiaddr; - else - astate->failed = astate->addr; - arp_report_conflicted(astate, amsg); - unlink(state->leasefile); - if (!state->lease.frominfo) - dhcp_decline(astate->iface); -#ifdef IN_IFF_DUPLICATED - ia = ipv4_iffindaddr(astate->iface, &astate->addr, NULL); - if (ia) - ipv4_deladdr(astate->iface, &ia->addr, &ia->net); -#endif - 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); - } -} - -static void dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, const struct in_addr *from) { @@ -2762,28 +2782,22 @@ dhcp_handledhcp(struct interface *ifp, s #ifndef IN_IFF_TENTATIVE if (ifo->options & DHCPCD_ARP && state->addr.s_addr != state->offer->yiaddr) -#endif { addr.s_addr = state->offer->yiaddr; -#ifndef IN_IFF_TENTATIVE /* If the interface already has the address configured * then we can't ARP for duplicate detection. */ ia = ipv4_findaddr(ifp->ctx, &addr); if (ia) { -#endif astate = arp_new(ifp, &addr); if (astate) { astate->probed_cb = dhcp_arp_probed; astate->conflicted_cb = dhcp_arp_conflicted; -#ifndef IN_IFF_TENTATIVE arp_probe(astate); -#endif } -#ifndef IN_IFF_TENTATIVE return; } -#endif } +#endif dhcp_bind(ifp, astate); } @@ -2954,7 +2968,7 @@ dhcp_handleudp(void *arg) * from the raw fd */ if (read(ctx->udp_fd, buffer, sizeof(buffer)) == -1) { logger(ctx, LOG_ERR, "%s: %m", __func__); - eloop_event_delete(ctx->eloop, ctx->udp_fd, 0); + eloop_event_delete(ctx->eloop, ctx->udp_fd); close(ctx->udp_fd); ctx->udp_fd = -1; } @@ -3049,7 +3063,7 @@ dhcp_free(struct interface *ifp) } if (ifp == NULL) { if (ctx->udp_fd != -1) { - eloop_event_delete(ctx->eloop, ctx->udp_fd, 0); + eloop_event_delete(ctx->eloop, ctx->udp_fd); close(ctx->udp_fd); ctx->udp_fd = -1; } Index: src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf diff -u src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.7 src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.8 --- src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.7 Fri Jan 30 09:47:05 2015 +++ src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -# $NetBSD: dhcpcd-definitions.conf,v 1.7 2015/01/30 09:47:05 roy Exp $ +# $NetBSD: dhcpcd-definitions.conf,v 1.8 2015/05/16 23:31:32 roy Exp $ # Copyright (c) 2006-2015 Roy Marples # All rights reserved @@ -109,7 +109,7 @@ define 80 norequest flag rapid_commit # DHCP Fully Qualified Domain Name, RFC4702 define 81 embed fqdn -embed byte flags +embed bitflags=0000NEOS flags embed byte rcode1 embed byte rcode2 embed domain fqdn @@ -289,6 +289,36 @@ encap 255 flag global # Option 255 End ############################################################################## +# ND6 options, RFC4861 +definend 1 binhex source_address +definend 2 binhex target_address + +definend 3 index embed prefix_information +embed byte length +embed bitflags=LA flags +embed uint32 vltime +embed uint32 pltime +embed uint32 reserved +embed array ip6address prefix + +# option 4 is only for Redirect messages + +definend 5 embed mtu +embed uint16 reserved +embed uint32 mtu + +# ND6 options, RFC6101 +definend 25 index embed rdnss +embed uint16 reserved +embed uint32 lifetime +embed array ip6address servers + +definend 31 index embed dnssl +embed uint16 reserved +embed uint32 lifetime +embed domain search + +############################################################################## # DHCPv6 options, RFC3315 define6 1 binhex client_id define6 2 binhex server_id @@ -399,7 +429,7 @@ define6 38 binhex subscriber_id # DHCPv6 Fully Qualified Domain Name, RFC4704 define6 39 embed fqdn -embed byte flags +embed bitflags=00000NOS flags embed domain fqdn # DHCPv6 PANA Authentication Agnet, RC5192 Index: src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h diff -u src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.7 src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.8 --- src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.7 Fri Jan 30 09:47:05 2015 +++ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: dhcpcd-embedded.h,v 1.7 2015/01/30 09:47:05 roy Exp $ */ +/* $NetBSD: dhcpcd-embedded.h,v 1.8 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -28,6 +28,7 @@ */ #define INITDEFINES 121 +#define INITDEFINENDS 6 #define INITDEFINE6S 68 extern const char * const dhcpcd_embedded_conf[]; Index: src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.13 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.14 --- src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.13 Fri Jan 30 09:47:05 2015 +++ src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd-run-hooks.8.in,v 1.13 2015/01/30 09:47:05 roy Exp $ +.\" $NetBSD: dhcpcd-run-hooks.8.in,v 1.14 2015/05/16 23:31:32 roy Exp $ .\" Copyright (c) 2006-2015 Roy Marples .\" All rights reserved .\" @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 3, 2014 +.Dd May 14, 2015 .Dt DHCPCD-RUN-HOOKS 8 .Os .Sh NAME @@ -187,11 +187,6 @@ is down, otherwise .It Ev $if_oneup .Dv true if any interface is up, otherwise false. -.It Ev $if_ipwaited -.Dv true -if any interface has been assigned an IP address which matches any wait -requirements specified in -.Xr dhcpcd.conf 5 . .It Ev $profile the name of the profile selected from .Xr dhcpcd.conf 5 . Index: src/external/bsd/dhcpcd/dist/dhcpcd.8.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.41 src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.42 --- src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.41 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/dhcpcd.8.in Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd.8.in,v 1.41 2015/03/26 10:26:37 roy Exp $ +.\" $NetBSD: dhcpcd.8.in,v 1.42 2015/05/16 23:31:32 roy Exp $ .\" Copyright (c) 2006-2015 Roy Marples .\" All rights reserved .\" @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 17, 2015 +.Dd May 9, 2015 .Dt DHCPCD 8 .Os .Sh NAME @@ -418,7 +418,7 @@ If fails to contact a DHCP server then it returns a failure instead of falling back on IPv4LL. .It Fl S, Fl Fl static Ar value -Configures a static +Configures a static DHCP .Ar value . If you set .Ic ip_address @@ -432,6 +432,11 @@ Here is an example which configures a st .D1 -S routers=192.168.0.1 \e .D1 -S domain_name_servers=192.168.0.1 \e .D1 eth0 +.Pp +You cannot presently set static DHCPv6 values. +Use the +.Fl e , Fl Fl env +option instead. .It Fl t , Fl Fl timeout Ar seconds Timeout after .Ar seconds , Index: src/external/bsd/dhcpcd/dist/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.24 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.25 --- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.24 Sat May 2 15:18:36 2015 +++ src/external/bsd/dhcpcd/dist/dhcpcd.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcpcd.c,v 1.24 2015/05/02 15:18:36 roy Exp $"); + __RCSID("$NetBSD: dhcpcd.c,v 1.25 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -69,19 +69,16 @@ const char dhcpcd_copyright[] = "Copyrig #include "script.h" #ifdef USE_SIGNALS -const int dhcpcd_handlesigs[] = { +const int dhcpcd_signals[] = { SIGTERM, SIGINT, SIGALRM, SIGHUP, SIGUSR1, SIGUSR2, - SIGPIPE, - 0 + SIGPIPE }; - -/* Handling signals needs *some* context */ -static struct dhcpcd_ctx *dhcpcd_ctx; +const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals); #endif #if defined(USE_SIGNALS) || !defined(THERE_IS_NO_FORK) @@ -170,6 +167,14 @@ free_globals(struct dhcpcd_ctx *ctx) } #endif #ifdef INET6 + if (ctx->nd_opts) { + for (opt = ctx->nd_opts; + ctx->nd_opts_len > 0; + opt++, ctx->nd_opts_len--) + free_dhcp_opt_embenc(opt); + free(ctx->nd_opts); + ctx->nd_opts = NULL; + } if (ctx->dhcp6_opts) { for (opt = ctx->dhcp6_opts; ctx->dhcp6_opts_len > 0; @@ -218,26 +223,50 @@ dhcpcd_oneup(struct dhcpcd_ctx *ctx) return 0; } -int -dhcpcd_ipwaited(struct dhcpcd_ctx *ctx) +static int +dhcpcd_ifipwaited(struct interface *ifp, unsigned long long opts) { - if (ctx->options & DHCPCD_WAITIP4 && - !ipv4_addrexists(ctx, NULL)) + if (opts & DHCPCD_WAITIP4 && !ipv4_ifaddrexists(ifp)) return 0; - if (ctx->options & DHCPCD_WAITIP6 && - !ipv6nd_findaddr(ctx, NULL, 0) && - !dhcp6_findaddr(ctx, NULL, 0)) + if (opts & DHCPCD_WAITIP6 && !ipv6_iffindaddr(ifp, NULL)) return 0; - if (ctx->options & DHCPCD_WAITIP && - !(ctx->options & (DHCPCD_WAITIP4 | DHCPCD_WAITIP6)) && - !ipv4_addrexists(ctx, NULL) && - !ipv6nd_findaddr(ctx, NULL, 0) && - !dhcp6_findaddr(ctx, NULL, 0)) + if (opts & DHCPCD_WAITIP && + !(opts & (DHCPCD_WAITIP4 | DHCPCD_WAITIP6)) && + !ipv4_ifaddrexists(ifp) && + !ipv6_iffindaddr(ifp, NULL)) return 0; return 1; } +static int +dhcpcd_ipwaited(struct dhcpcd_ctx *ctx) +{ + struct interface *ifp; + + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + if (ifp->options->options & DHCPCD_WAITOPTS) { + if (!dhcpcd_ifipwaited(ifp, ifp->options->options)) { + logger(ctx, LOG_DEBUG, + "%s: waiting for an ip address", + ifp->name); + return 0; + } + } + } + + if (!(ctx->options & DHCPCD_WAITOPTS)) + return 1; + + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + if (dhcpcd_ifipwaited(ifp, ctx->options)) + return 1; + } + + logger(ctx, LOG_DEBUG, "waiting for an ip address"); + return 0; +} + /* Returns the pid of the child, otherwise 0. */ pid_t dhcpcd_daemonise(struct dhcpcd_ctx *ctx) @@ -590,7 +619,7 @@ dhcpcd_pollup(void *arg) struct timespec tv; tv.tv_sec = 0; - tv.tv_nsec = IF_POLL_UP * MSEC_PER_NSEC; + tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC; eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcpcd_pollup, ifp); return; } @@ -643,7 +672,8 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx * script_runreason(ifp, "NOCARRIER"); #ifdef NOCARRIER_PRESERVE_IP arp_close(ifp); - ipv4_buildroutes(ifp->ctx); + if_sortinterfaces(ctx); + ipv4_preferanother(ifp); ipv6nd_expire(ifp, 0); #else dhcpcd_drop(ifp, 0); @@ -757,7 +787,7 @@ dhcpcd_startinterface(void *arg) * Loop until both IFF_UP and IFF_RUNNING are set */ if ((carrier = if_carrier(ifp)) == LINK_UNKNOWN) { tv.tv_sec = 0; - tv.tv_nsec = IF_POLL_UP * MSEC_PER_NSEC; + tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC; eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcpcd_startinterface, ifp); } else @@ -877,7 +907,7 @@ handle_link(void *arg) ctx = arg; if (if_managelink(ctx) == -1) { logger(ctx, LOG_ERR, "if_managelink: %m"); - eloop_event_delete(ctx->eloop, ctx->link_fd, 0); + eloop_event_delete(ctx->eloop, ctx->link_fd); close(ctx->link_fd); ctx->link_fd = -1; } @@ -1119,21 +1149,17 @@ stop_all_interfaces(struct dhcpcd_ctx *c } #ifdef USE_SIGNALS -struct dhcpcd_siginfo dhcpcd_siginfo; #define sigmsg "received %s, %s" -void -dhcpcd_handle_signal(void *arg) +static void +signal_cb(int sig, void *arg) { - struct dhcpcd_ctx *ctx; - struct dhcpcd_siginfo *si; + struct dhcpcd_ctx *ctx = arg; struct interface *ifp; - int do_release, exit_code;; + int do_release, exit_code; - ctx = dhcpcd_ctx; - si = arg; do_release = 0; exit_code = EXIT_FAILURE; - switch (si->signo) { + switch (sig) { case SIGINT: logger(ctx, LOG_INFO, sigmsg, "SIGINT", "stopping"); break; @@ -1172,7 +1198,7 @@ dhcpcd_handle_signal(void *arg) logger(ctx, LOG_ERR, "received signal %d, " "but don't know what to do with it", - si->signo); + sig); return; } @@ -1180,47 +1206,6 @@ dhcpcd_handle_signal(void *arg) stop_all_interfaces(ctx, do_release); eloop_exit(ctx->eloop, exit_code); } - -#ifndef HAVE_KQUEUE -static void -handle_signal(int sig, __unused siginfo_t *siginfo, __unused void *context) -{ - - /* So that we can operate safely under a signal we instruct - * eloop to pass a copy of the siginfo structure to handle_signal1 - * as the very first thing to do. */ - dhcpcd_siginfo.signo = sig; - eloop_timeout_add_now(dhcpcd_ctx->eloop, - dhcpcd_handle_signal, &dhcpcd_siginfo); -} -#endif - -static int -signal_init(sigset_t *oldset) -{ - sigset_t newset; -#ifndef HAVE_KQUEUE - int i; - struct sigaction sa; -#endif - - sigfillset(&newset); - if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) - return -1; - -#ifndef HAVE_KQUEUE - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = handle_signal; - sa.sa_flags = SA_SIGINFO; - sigemptyset(&sa.sa_mask); - - for (i = 0; dhcpcd_handlesigs[i]; i++) { - if (sigaction(dhcpcd_handlesigs[i], &sa, NULL) == -1) - return -1; - } -#endif - return 0; -} #endif static void @@ -1242,7 +1227,7 @@ dhcpcd_getinterfaces(void *arg) } if (write(fd->fd, &len, sizeof(len)) != sizeof(len)) return; - eloop_event_delete(fd->ctx->eloop, fd->fd, 1); + eloop_event_remove_writecb(fd->ctx->eloop, fd->fd); TAILQ_FOREACH(ifp, fd->ctx->ifaces, next) { if (send_interface(fd, ifp) == -1) logger(ifp->ctx, LOG_ERR, @@ -1344,7 +1329,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx reload_config(ctx); /* XXX: Respect initial commandline options? */ - reconf_reboot(ctx, do_reboot, argc, argv, optind); + reconf_reboot(ctx, do_reboot, argc, argv, optind - 1); return 0; } @@ -1362,8 +1347,8 @@ main(int argc, char **argv) pid_t pid; #endif #ifdef USE_SIGNALS - int sig; - const char *siga; + int sig = 0; + const char *siga = NULL; #endif /* Test for --help and --version */ @@ -1378,11 +1363,6 @@ main(int argc, char **argv) } memset(&ctx, 0, sizeof(ctx)); -#ifdef USE_SIGNALS - dhcpcd_ctx = &ctx; - sig = 0; - siga = NULL; -#endif closefrom(3); ctx.log_fd = -1; @@ -1486,6 +1466,9 @@ main(int argc, char **argv) #endif #ifdef INET6 if (family == 0 || family == AF_INET6) { + printf("\nND options:\n"); + ipv6nd_printoptions(&ctx, + ifo->nd_override, ifo->nd_override_len); printf("\nDHCPv6 options:\n"); dhcp6_printoptions(&ctx, ifo->dhcp6_override, ifo->dhcp6_override_len); @@ -1558,8 +1541,7 @@ main(int argc, char **argv) /* Freeing allocated addresses from dumping leases can trigger * eloop removals as well, so init here. */ - ctx.eloop = eloop_init(&ctx); - if (ctx.eloop == NULL) { + if ((ctx.eloop = eloop_new()) == NULL) { logger(&ctx, LOG_ERR, "%s: eloop_init: %m", __func__); goto exit_failure; } @@ -1747,9 +1729,16 @@ main(int argc, char **argv) logger(&ctx, LOG_DEBUG, PACKAGE "-" VERSION " starting"); ctx.options |= DHCPCD_STARTED; #ifdef USE_SIGNALS + if (eloop_signal_set_cb(ctx.eloop, + dhcpcd_signals, dhcpcd_signals_len, + signal_cb, &ctx) == -1) + { + logger(&ctx, LOG_ERR, "eloop_signal_mask: %m"); + goto exit_failure; + } /* Save signal mask, block and redirect signals to our handler */ - if (signal_init(&ctx.sigset) == -1) { - logger(&ctx, LOG_ERR, "signal_setup: %m"); + if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) { + logger(&ctx, LOG_ERR, "eloop_signal_mask: %m"); goto exit_failure; } #endif @@ -1846,7 +1835,11 @@ main(int argc, char **argv) dhcpcd_prestartinterface, ifp); } - i = eloop_start(ctx.eloop); + i = eloop_start(ctx.eloop, &ctx.sigset); + if (i < 0) { + syslog(LOG_ERR, "eloop_start: %m"); + goto exit_failure; + } goto exit1; exit_success: @@ -1867,7 +1860,7 @@ exit1: } free(ctx.duid); if (ctx.link_fd != -1) { - eloop_event_delete(ctx.eloop, ctx.link_fd, 0); + eloop_event_delete(ctx.eloop, ctx.link_fd); close(ctx.link_fd); } Index: src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.20 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.21 --- src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.20 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd.conf.5.in,v 1.20 2015/05/02 15:18:37 roy Exp $ +.\" $NetBSD: dhcpcd.conf.5.in,v 1.21 2015/05/16 23:31:32 roy Exp $ .\" Copyright (c) 2006-2015 Roy Marples .\" All rights reserved .\" @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 6, 2015 +.Dd May 15, 2015 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -463,14 +463,39 @@ You can specify more separated by commas, spaces or more .Ic option lines. +.Ar option Prepend dhcp6_ to .Ar option to request a DHCPv6 option. DHCPv4 options are mapped to DHCPv6 where applicable. +.Pp +Prepend nd_ to +.Ar option +to handle ND options, but this only works for the +.Ic nooption , +.Ic reject +and +.Ic require +options. .It Ic nooption Ar option -Remove the option from the DHCP message. -This should only be used when a DHCP server sends a non requested option -that should not be processed. +Remove the option from the message before it's processed. +.It Ic require Ar option +Requires the +.Ar option +to be present in all messages, otherwise the message is ignored. +To enforce that +.Nm dhcpcd +only responds to DHCP servers and not BOOTP servers, you can +.Ic require +.Ar dhcp_message_type . +This isn't an exact science though because a BOOTP server can send DHCP like +options. +.It Ic reject Ar option +Reject a message that contains the +.Ar option . +This is useful when you cannot use +.Ic require +to select / de-select BOOTP messages. .It Ic destination Ar option If .Nm @@ -500,27 +525,6 @@ will timeout before moving back to the D .It Ic release .Nm dhcpcd will release the lease prior to stopping the interface. -.It Ic require Ar option -Requires the -.Ar option -to be present in all DHCP messages, otherwise the message is ignored. -It can be a variable to be used in -.Xr dhcpcd-run-hooks 8 -or the numerical value. -You can specify more options separated by commas, spaces or more require lines. -To enforce that -.Nm dhcpcd -only responds to DHCP servers and not BOOTP servers, you can -.Ic require -.Ar dhcp_message_type . -This isn't an exact science though because a BOOTP server can send DHCP like -options. -.It Ic reject Ar option -Reject a DHCP message that contains the -.Ar option . -This is useful when you cannot use -.Ic require -to select / de-select BOOTP messages. .It Ic script Ar script Use .Ar script @@ -631,9 +635,10 @@ Use the last four bytes of the hardware of a randomly generated number. .El .Ss Defining new options -DHCP allows for the use of custom options. +DHCP, ND and DHCPv6 allow for the use of custom options. Each option needs to be started with the -.Ic define +.Ic define , +.If definend or .Ic define6 directive. @@ -656,6 +661,17 @@ with a name of .Ar variable exported to .Xr dhcpcd-run-hooks 8 . +.It Ic definend Ar code Ar type Ar variable +Defines the ND option +.Ar code +of +.Ar type +with a name of +.Ar variable +exported to +.Xr dhcpcd-run-hooks 8 , +with a prefix of +.Va _nd . .It Ic define6 Ar code Ar type Ar variable Defines the DHCPv6 option .Ar code @@ -688,6 +704,11 @@ is not the same as defined in the parent it is prefixed with the parent .Ar variable first with an underscore. +If the +.Ar variable +has the name of +.Ar reserved +then it is not processed. .It Ic encap Ar code Ar type Ar variable Defines an encapsulated variable within the defined option. The length is determined by the @@ -721,35 +742,42 @@ Lengths can be specified for string and with other data embedded afterwards in the same option. .Bl -tag -width indent .It Ic ipaddress -An IPv4 address, 4 bytes +An IPv4 address, 4 bytes. .It Ic ip6address -An IPv6 address, 16 bytes +An IPv6 address, 16 bytes. .It Ic string Op : Ic length A NVT ASCII string of printable characters. .It Ic byte -A byte +A byte. +.It Ic bitflags : Ic flags +A byte represented as a string of flags, most significant bit first. +For example, using ABCDEFGH then A would equal 10000000, B 01000000, +C 00100000, etc. +If the bit is not set, the flag is not printed. +A flag of 0 is not printed even if the bit postition is set. +This is to allow reservation of the first bits while assinging the last bits. .It Ic int16 -A signed 16bit integer, 2 bytes +A signed 16bit integer, 2 bytes. .It Ic uint16 -An unsigned 16bit integer, 2 bytes +An unsigned 16bit integer, 2 bytes. .It Ic int32 -A signed 32bit integer, 4 bytes +A signed 32bit integer, 4 bytes. .It Ic uint32 -An unsigned 32bit integer, 4 bytes -.It Ic flag -A fixed value (1) to indicate that the option is present, 0 bytes +An unsigned 32bit integer, 4 bytes. +.It Ic flag +A fixed value (1) to indicate that the option is present, 0 bytes. .It Ic domain -A RFC 3397 encoded string +A RFC 3397 encoded string. .It Ic dname -A RFC 1035 validated string +A RFC 1035 validated string. .It Ic binhex Op : Ic length -Binary data expressed as hexadecimal +Binary data expressed as hexadecimal. .It Ic embed -Contains embedded options (implies encap as well) +Contains embedded options (implies encap as well). .It Ic encap -Contains encapsulated options (implies embed as well) +Contains encapsulated options (implies embed as well). .It Ic option -References an option from the global definition +References an option from the global definition. .El .Ss Example definition .D1 # DHCP option 81, Fully Qualified Domain Name, RFC4702 Index: src/external/bsd/dhcpcd/dist/if-bsd.c diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.20 src/external/bsd/dhcpcd/dist/if-bsd.c:1.21 --- src/external/bsd/dhcpcd/dist/if-bsd.c:1.20 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/if-bsd.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if-bsd.c,v 1.20 2015/05/02 15:18:37 roy Exp $"); + __RCSID("$NetBSD: if-bsd.c,v 1.21 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -1128,7 +1128,7 @@ if_getlifetime6(struct ipv6_addr *ia) (uint32_t)(lifetime->ia6t_expire - MIN(t, lifetime->ia6t_expire)); /* Calculate the created time */ - get_monotonic(&ia->created); + clock_gettime(CLOCK_MONOTONIC, &ia->created); ia->created.tv_sec -= lifetime->ia6t_vltime - ia->prefix_vltime; } else Index: src/external/bsd/dhcpcd/dist/dhcpcd.h diff -u src/external/bsd/dhcpcd/dist/dhcpcd.h:1.10 src/external/bsd/dhcpcd/dist/dhcpcd.h:1.11 --- src/external/bsd/dhcpcd/dist/dhcpcd.h:1.10 Thu Mar 26 10:26:37 2015 +++ src/external/bsd/dhcpcd/dist/dhcpcd.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: dhcpcd.h,v 1.10 2015/03/26 10:26:37 roy Exp $ */ +/* $NetBSD: dhcpcd.h,v 1.11 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -34,6 +34,10 @@ #include <net/if.h> #include "config.h" +#ifdef HAVE_SYS_QUEUE_H +#include <sys/queue.h> +#endif + #include "defs.h" #include "control.h" #include "if-options.h" @@ -107,7 +111,7 @@ struct dhcpcd_ctx { #ifdef USE_SIGNALS sigset_t sigset; #endif - struct eloop_ctx *eloop; + struct eloop *eloop; int control_fd; int control_unpriv_fd; @@ -137,6 +141,8 @@ struct dhcpcd_ctx { unsigned char secret[SECRET_LEN]; size_t secret_len; + struct dhcp_opt *nd_opts; + size_t nd_opts_len; struct dhcp_opt *dhcp6_opts; size_t dhcp6_opts_len; struct ipv6_ctx *ipv6; @@ -154,16 +160,11 @@ struct dhcpcd_ctx { }; #ifdef USE_SIGNALS -struct dhcpcd_siginfo { - int signo; -}; - -extern const int dhcpcd_handlesigs[]; -void dhcpcd_handle_signal(void *); +extern const int dhcpcd_signals[]; +extern const size_t dhcpcd_signals_len; #endif int dhcpcd_oneup(struct dhcpcd_ctx *); -int dhcpcd_ipwaited(struct dhcpcd_ctx *); pid_t dhcpcd_daemonise(struct dhcpcd_ctx *); int dhcpcd_handleargs(struct dhcpcd_ctx *, struct fd_list *, int, char **); Index: src/external/bsd/dhcpcd/dist/eloop.c diff -u src/external/bsd/dhcpcd/dist/eloop.c:1.10 src/external/bsd/dhcpcd/dist/eloop.c:1.11 --- src/external/bsd/dhcpcd/dist/eloop.c:1.10 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/eloop.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: eloop.c,v 1.10 2015/05/02 15:18:37 roy Exp $"); + __RCSID("$NetBSD: eloop.c,v 1.11 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -30,6 +30,7 @@ #include <sys/time.h> +#include <assert.h> #include <errno.h> #include <limits.h> #include <signal.h> @@ -37,11 +38,26 @@ #include <string.h> #include <unistd.h> +/* config.h should define HAVE_KQUEUE, HAVE_EPOLL, etc */ #include "config.h" -#include "common.h" -#include "dhcpcd.h" #include "eloop.h" +#ifndef UNUSED +#define UNUSED(a) (void)((a)) +#endif +#ifndef __unused +#ifdef __GNUC__ +#define __unused __attribute__((__unused__)) +#else +#define __unused +#endif +#endif + +#ifndef MSEC_PER_SEC +#define MSEC_PER_SEC 1000L +#define NSEC_PER_MSEC 1000000L +#endif + #if defined(HAVE_KQUEUE) #include <sys/event.h> #include <fcntl.h> @@ -54,35 +70,67 @@ #define UPTR(x) (x) #define LENC(x) ((int)(x)) #endif -#define eloop_event_setup_fds(ctx) +#define eloop_event_setup_fds(eloop) #elif defined(HAVE_EPOLL) #include <sys/epoll.h> -#define eloop_event_setup_fds(ctx) +#define eloop_event_setup_fds(eloop) #else #include <poll.h> static void -eloop_event_setup_fds(struct eloop_ctx *ctx) +eloop_event_setup_fds(struct eloop *eloop) { struct eloop_event *e; size_t i; i = 0; - TAILQ_FOREACH(e, &ctx->events, next) { - ctx->fds[i].fd = e->fd; - ctx->fds[i].events = 0; + TAILQ_FOREACH(e, &eloop->events, next) { + eloop->fds[i].fd = e->fd; + eloop->fds[i].events = 0; if (e->read_cb) - ctx->fds[i].events |= POLLIN; + eloop->fds[i].events |= POLLIN; if (e->write_cb) - ctx->fds[i].events |= POLLOUT; - ctx->fds[i].revents = 0; - e->pollfd = &ctx->fds[i]; + eloop->fds[i].events |= POLLOUT; + eloop->fds[i].revents = 0; + e->pollfd = &eloop->fds[i]; i++; } } + +#ifndef pollts +/* Wrapper around pselect, to imitate the NetBSD pollts call. */ +static int +pollts(struct pollfd * fds, nfds_t nfds, + const struct timespec *ts, const sigset_t *sigmask) +{ + fd_set read_fds; + nfds_t n; + int maxfd, r; + + FD_ZERO(&read_fds); + maxfd = 0; + for (n = 0; n < nfds; n++) { + if (fds[n].events & POLLIN) { + FD_SET(fds[n].fd, &read_fds); + if (fds[n].fd > maxfd) + maxfd = fds[n].fd; + } + } + + r = pselect(maxfd + 1, &read_fds, NULL, NULL, ts, sigmask); + if (r > 0) { + for (n = 0; n < nfds; n++) { + fds[n].revents = + FD_ISSET(fds[n].fd, &read_fds) ? POLLIN : 0; + } + } + + return r; +} +#endif #endif int -eloop_event_add(struct eloop_ctx *ctx, int fd, +eloop_event_add(struct eloop *eloop, int fd, void (*read_cb)(void *), void *read_cb_arg, void (*write_cb)(void *), void *write_cb_arg) { @@ -95,6 +143,13 @@ eloop_event_add(struct eloop_ctx *ctx, i struct pollfd *nfds; #endif + assert(eloop != NULL); + assert(read_cb != NULL || write_cb != NULL); + if (fd == -1) { + errno = EINVAL; + return -1; + } + #ifdef HAVE_EPOLL memset(&epe, 0, sizeof(epe)); epe.data.fd = fd; @@ -104,7 +159,7 @@ eloop_event_add(struct eloop_ctx *ctx, i #endif /* We should only have one callback monitoring the fd */ - TAILQ_FOREACH(e, &ctx->events, next) { + TAILQ_FOREACH(e, &eloop->events, next) { if (e->fd == fd) { int error; @@ -117,11 +172,11 @@ eloop_event_add(struct eloop_ctx *ctx, i else if (e->write_cb) EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, UPTR(e)); - error = kevent(ctx->poll_fd, ke, + error = kevent(eloop->poll_fd, ke, e->write_cb || write_cb ? 2 : 1, NULL, 0, NULL); #elif defined(HAVE_EPOLL) epe.data.ptr = e; - error = epoll_ctl(ctx->poll_fd, EPOLL_CTL_MOD, + error = epoll_ctl(eloop->poll_fd, EPOLL_CTL_MOD, fd, &epe); #else error = 0; @@ -134,14 +189,14 @@ eloop_event_add(struct eloop_ctx *ctx, i e->write_cb = write_cb; e->write_cb_arg = write_cb_arg; } - eloop_event_setup_fds(ctx); + eloop_event_setup_fds(eloop); return error; } } /* Allocate a new event if no free ones already allocated */ - if ((e = TAILQ_FIRST(&ctx->free_events))) { - TAILQ_REMOVE(&ctx->free_events, e, next); + if ((e = TAILQ_FIRST(&eloop->free_events))) { + TAILQ_REMOVE(&eloop->free_events, e, next); } else { e = malloc(sizeof(*e)); if (e == NULL) @@ -149,14 +204,15 @@ eloop_event_add(struct eloop_ctx *ctx, i } /* Ensure we can actually listen to it */ - ctx->events_len++; + eloop->events_len++; #if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) - if (ctx->events_len > ctx->fds_len) { - nfds = realloc(ctx->fds, sizeof(*ctx->fds) * (ctx->fds_len+5)); + if (eloop->events_len > eloop->fds_len) { + nfds = realloc(eloop->fds, + sizeof(*eloop->fds) * (eloop->fds_len + 5)); if (nfds == NULL) goto err; - ctx->fds_len += 5; - ctx->fds = nfds; + eloop->fds_len += 5; + eloop->fds = nfds; } #endif @@ -168,15 +224,17 @@ eloop_event_add(struct eloop_ctx *ctx, i e->write_cb_arg = write_cb_arg; #if defined(HAVE_KQUEUE) - EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, EV_ADD, 0, 0, UPTR(e)); - if (write_cb) + if (read_cb != NULL) + EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, + EV_ADD, 0, 0, UPTR(e)); + if (write_cb != NULL) EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, EV_ADD, 0, 0, UPTR(e)); - if (kevent(ctx->poll_fd, ke, write_cb ? 2 : 1, NULL, 0, NULL) == -1) + if (kevent(eloop->poll_fd, ke, write_cb ? 2 : 1, NULL, 0, NULL) == -1) goto err; #elif defined(HAVE_EPOLL) epe.data.ptr = e; - if (epoll_ctl(ctx->poll_fd, EPOLL_CTL_ADD, fd, &epe) == -1) + if (epoll_ctl(eloop->poll_fd, EPOLL_CTL_ADD, fd, &epe) == -1) goto err; #endif @@ -186,21 +244,20 @@ eloop_event_add(struct eloop_ctx *ctx, i * message (which is likely to be that the DHCP addresses are wrong) * we insert new events at the queue head as the link fd will be * the first event added. */ - TAILQ_INSERT_HEAD(&ctx->events, e, next); - eloop_event_setup_fds(ctx); + TAILQ_INSERT_HEAD(&eloop->events, e, next); + eloop_event_setup_fds(eloop); return 0; err: - logger(ctx->ctx, LOG_ERR, "%s: %m", __func__); if (e) { - ctx->events_len--; - TAILQ_INSERT_TAIL(&ctx->free_events, e, next); + eloop->events_len--; + TAILQ_INSERT_TAIL(&eloop->free_events, e, next); } return -1; } void -eloop_event_delete(struct eloop_ctx *ctx, int fd, int write_only) +eloop_event_delete_write(struct eloop *eloop, int fd, int write_only) { struct eloop_event *e; #if defined(HAVE_KQUEUE) @@ -209,30 +266,31 @@ eloop_event_delete(struct eloop_ctx *ctx struct epoll_event epe; #endif - TAILQ_FOREACH(e, &ctx->events, next) { + assert(eloop != NULL); + + TAILQ_FOREACH(e, &eloop->events, next) { if (e->fd == fd) { - if (write_only) { - if (e->write_cb) { + if (write_only && e->read_cb != NULL) { + if (e->write_cb != NULL) { e->write_cb = NULL; e->write_cb_arg = NULL; #if defined(HAVE_KQUEUE) EV_SET(&ke[0], (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, UPTR(NULL)); - kevent(ctx->poll_fd, ke, 1, NULL, 0, + kevent(eloop->poll_fd, ke, 1, NULL, 0, NULL); #elif defined(HAVE_EPOLL) memset(&epe, 0, sizeof(epe)); epe.data.fd = e->fd; epe.data.ptr = e; epe.events = EPOLLIN; - epoll_ctl(ctx->poll_fd, EPOLL_CTL_MOD, - fd, &epe); + epoll_ctl(eloop->poll_fd, + EPOLL_CTL_MOD, fd, &epe); #endif } - } else { - TAILQ_REMOVE(&ctx->events, e, next); + TAILQ_REMOVE(&eloop->events, e, next); #if defined(HAVE_KQUEUE) EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, EV_DELETE, 0, 0, UPTR(NULL)); @@ -240,32 +298,36 @@ eloop_event_delete(struct eloop_ctx *ctx EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, UPTR(NULL)); - kevent(ctx->poll_fd, ke, e->write_cb ? 2 : 1, + kevent(eloop->poll_fd, ke, e->write_cb ? 2 : 1, NULL, 0, NULL); #elif defined(HAVE_EPOLL) /* NULL event is safe because we * rely on epoll_pwait which as added * after the delete without event was fixed. */ - epoll_ctl(ctx->poll_fd, EPOLL_CTL_DEL, + epoll_ctl(eloop->poll_fd, EPOLL_CTL_DEL, fd, NULL); #endif - TAILQ_INSERT_TAIL(&ctx->free_events, e, next); - ctx->events_len--; + TAILQ_INSERT_TAIL(&eloop->free_events, e, next); + eloop->events_len--; } - eloop_event_setup_fds(ctx); + eloop_event_setup_fds(eloop); break; } } } int -eloop_q_timeout_add_tv(struct eloop_ctx *ctx, int queue, +eloop_q_timeout_add_tv(struct eloop *eloop, int queue, const struct timespec *when, void (*callback)(void *), void *arg) { struct timespec now, w; struct eloop_timeout *t, *tt = NULL; - get_monotonic(&now); + assert(eloop != NULL); + assert(when != NULL); + assert(callback != NULL); + + clock_gettime(CLOCK_MONOTONIC, &now); timespecadd(&now, when, &w); /* Check for time_t overflow. */ if (timespeccmp(&w, &now, <)) { @@ -274,23 +336,20 @@ eloop_q_timeout_add_tv(struct eloop_ctx } /* Remove existing timeout if present */ - TAILQ_FOREACH(t, &ctx->timeouts, next) { + TAILQ_FOREACH(t, &eloop->timeouts, next) { if (t->callback == callback && t->arg == arg) { - TAILQ_REMOVE(&ctx->timeouts, t, next); + TAILQ_REMOVE(&eloop->timeouts, t, next); break; } } if (t == NULL) { /* No existing, so allocate or grab one from the free pool */ - if ((t = TAILQ_FIRST(&ctx->free_timeouts))) { - TAILQ_REMOVE(&ctx->free_timeouts, t, next); + if ((t = TAILQ_FIRST(&eloop->free_timeouts))) { + TAILQ_REMOVE(&eloop->free_timeouts, t, next); } else { - t = malloc(sizeof(*t)); - if (t == NULL) { - logger(ctx->ctx, LOG_ERR, "%s: %m", __func__); + if ((t = malloc(sizeof(*t))) == NULL) return -1; - } } } @@ -301,97 +360,108 @@ eloop_q_timeout_add_tv(struct eloop_ctx /* The timeout list should be in chronological order, * soonest first. */ - TAILQ_FOREACH(tt, &ctx->timeouts, next) { + TAILQ_FOREACH(tt, &eloop->timeouts, next) { if (timespeccmp(&t->when, &tt->when, <)) { TAILQ_INSERT_BEFORE(tt, t, next); return 0; } } - TAILQ_INSERT_TAIL(&ctx->timeouts, t, next); + TAILQ_INSERT_TAIL(&eloop->timeouts, t, next); return 0; } int -eloop_q_timeout_add_sec(struct eloop_ctx *ctx, int queue, time_t when, +eloop_q_timeout_add_sec(struct eloop *eloop, int queue, time_t when, void (*callback)(void *), void *arg) { struct timespec tv; tv.tv_sec = when; tv.tv_nsec = 0; - return eloop_q_timeout_add_tv(ctx, queue, &tv, callback, arg); + return eloop_q_timeout_add_tv(eloop, queue, &tv, callback, arg); } -#if !defined(HAVE_KQUEUE) int -eloop_timeout_add_now(struct eloop_ctx *ctx, +eloop_q_timeout_add_msec(struct eloop *eloop, int queue, long when, void (*callback)(void *), void *arg) { + struct timespec tv; - if (ctx->timeout0 != NULL) { - logger(ctx->ctx, LOG_WARNING, - "%s: timeout0 already set", __func__); - return eloop_q_timeout_add_sec(ctx, 0, 0, callback, arg); - } + tv.tv_sec = when / MSEC_PER_SEC; + tv.tv_nsec = (when % MSEC_PER_SEC) * NSEC_PER_MSEC; + return eloop_q_timeout_add_tv(eloop, queue, &tv, callback, arg); +} - ctx->timeout0 = callback; - ctx->timeout0_arg = arg; +#if !defined(HAVE_KQUEUE) +static int +eloop_timeout_add_now(struct eloop *eloop, + void (*callback)(void *), void *arg) +{ + + assert(eloop->timeout0 == NULL); + eloop->timeout0 = callback; + eloop->timeout0_arg = arg; return 0; } #endif void -eloop_q_timeout_delete(struct eloop_ctx *ctx, int queue, +eloop_q_timeout_delete(struct eloop *eloop, int queue, void (*callback)(void *), void *arg) { struct eloop_timeout *t, *tt; - TAILQ_FOREACH_SAFE(t, &ctx->timeouts, next, tt) { + assert(eloop != NULL); + + TAILQ_FOREACH_SAFE(t, &eloop->timeouts, next, tt) { if ((queue == 0 || t->queue == queue) && t->arg == arg && (!callback || t->callback == callback)) { - TAILQ_REMOVE(&ctx->timeouts, t, next); - TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next); + TAILQ_REMOVE(&eloop->timeouts, t, next); + TAILQ_INSERT_TAIL(&eloop->free_timeouts, t, next); } } } void -eloop_exit(struct eloop_ctx *ctx, int code) +eloop_exit(struct eloop *eloop, int code) { - ctx->exitcode = code; - ctx->exitnow = 1; + assert(eloop != NULL); + + eloop->exitcode = code; + eloop->exitnow = 1; } #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) static int -eloop_open(struct eloop_ctx *ctx) +eloop_open(struct eloop *eloop) { + #if defined(HAVE_KQUEUE1) - return (ctx->poll_fd = kqueue1(O_CLOEXEC)); + return (eloop->poll_fd = kqueue1(O_CLOEXEC)); #elif defined(HAVE_KQUEUE) int i; - if ((ctx->poll_fd = kqueue()) == -1) + if ((eloop->poll_fd = kqueue()) == -1) return -1; - if ((i = fcntl(ctx->poll_fd, F_GETFD, 0)) == -1 || - fcntl(ctx->poll_fd, F_SETFD, i | FD_CLOEXEC) == -1) + if ((i = fcntl(eloop->poll_fd, F_GETFD, 0)) == -1 || + fcntl(eloop->poll_fd, F_SETFD, i | FD_CLOEXEC) == -1) { - close(ctx->poll_fd); - ctx->poll_fd = -1; + close(eloop->poll_fd); + eloop->poll_fd = -1; return -1; } - return ctx->poll_fd; + return eloop->poll_fd; #elif defined (HAVE_EPOLL) - return (ctx->poll_fd = epoll_create1(EPOLL_CLOEXEC)); + return (eloop->poll_fd = epoll_create1(EPOLL_CLOEXEC)); #endif } int -eloop_requeue(struct eloop_ctx *ctx) +eloop_requeue(struct eloop *eloop) { struct eloop_event *e; int error; @@ -402,15 +472,15 @@ eloop_requeue(struct eloop_ctx *ctx) struct epoll_event epe; #endif - if (ctx->poll_fd != -1) - close(ctx->poll_fd); - if (eloop_open(ctx) == -1) + assert(eloop != NULL); + + if (eloop->poll_fd != -1) + close(eloop->poll_fd); + if (eloop_open(eloop) == -1) return -1; #if defined (HAVE_KQUEUE) - i = 0; - while (dhcpcd_handlesigs[i]) - i++; - TAILQ_FOREACH(e, &ctx->events, next) { + i = eloop->signals_len; + TAILQ_FOREACH(e, &eloop->events, next) { i++; if (e->write_cb) i++; @@ -419,11 +489,11 @@ eloop_requeue(struct eloop_ctx *ctx) if ((ke = malloc(sizeof(*ke) * i)) == NULL) return -1; - for (i = 0; dhcpcd_handlesigs[i]; i++) - EV_SET(&ke[i], (uintptr_t)dhcpcd_handlesigs[i], + for (i = 0; i < eloop->signals_len; i++) + EV_SET(&ke[i], (uintptr_t)eloop->signals[i], EVFILT_SIGNAL, EV_ADD, 0, 0, UPTR(NULL)); - TAILQ_FOREACH(e, &ctx->events, next) { + TAILQ_FOREACH(e, &eloop->events, next) { EV_SET(&ke[i], (uintptr_t)e->fd, EVFILT_READ, EV_ADD, 0, 0, UPTR(e)); i++; @@ -434,20 +504,20 @@ eloop_requeue(struct eloop_ctx *ctx) } } - error = kevent(ctx->poll_fd, ke, LENC(i), NULL, 0, NULL); + error = kevent(eloop->poll_fd, ke, LENC(i), NULL, 0, NULL); free(ke); #elif defined(HAVE_EPOLL) error = 0; - TAILQ_FOREACH(e, &ctx->events, next) { + TAILQ_FOREACH(e, &eloop->events, next) { memset(&epe, 0, sizeof(epe)); epe.data.fd = e->fd; epe.events = EPOLLIN; if (e->write_cb) epe.events |= EPOLLOUT; epe.data.ptr = e; - if (epoll_ctl(ctx->poll_fd, EPOLL_CTL_ADD, e->fd, &epe) == -1) + if (epoll_ctl(eloop->poll_fd, EPOLL_CTL_ADD, e->fd, &epe) == -1) error = -1; } #endif @@ -456,102 +526,179 @@ eloop_requeue(struct eloop_ctx *ctx) } #endif -struct eloop_ctx * -eloop_init(struct dhcpcd_ctx *dctx) +int +eloop_signal_set_cb(struct eloop *eloop, + const int *signals, size_t signals_len, + void (*signal_cb)(int, void *), void *signal_cb_ctx) +{ + + assert(eloop != NULL); + + eloop->signals = signals; + eloop->signals_len = signals_len; + eloop->signal_cb = signal_cb; + eloop->signal_cb_ctx = signal_cb_ctx; + return eloop_requeue(eloop); +} + +#ifndef HAVE_KQUEUE +struct eloop_siginfo { + int sig; + struct eloop *eloop; +}; +static struct eloop_siginfo _eloop_siginfo; +static struct eloop *_eloop; + +static void +eloop_signal1(void *arg) +{ + struct eloop_siginfo *si = arg; + + si->eloop->signal_cb(si->sig, si->eloop->signal_cb_ctx); +} + +static void +eloop_signal3(int sig, __unused siginfo_t *siginfo, __unused void *arg) +{ + + /* So that we can operate safely under a signal we instruct + * eloop to pass a copy of the siginfo structure to handle_signal1 + * as the very first thing to do. */ + _eloop_siginfo.eloop = _eloop; + _eloop_siginfo.sig = sig; + eloop_timeout_add_now(_eloop_siginfo.eloop, + eloop_signal1, &_eloop_siginfo); +} +#endif + +int +eloop_signal_mask(struct eloop *eloop, sigset_t *oldset) { - struct eloop_ctx *ctx; + sigset_t newset; +#ifndef HAVE_KQUEUE + size_t i; + struct sigaction sa; +#endif + + assert(eloop != NULL); + + sigfillset(&newset); + if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) + return -1; + +#ifdef HAVE_KQUEUE + UNUSED(eloop); +#else + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = eloop_signal3; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + + for (i = 0; i < eloop->signals_len; i++) { + if (sigaction(eloop->signals[i], &sa, NULL) == -1) + return -1; + } +#endif + return 0; +} + +struct eloop * +eloop_new(void) +{ + struct eloop *eloop; struct timespec now; /* Check we have a working monotonic clock. */ - if (get_monotonic(&now) == -1) + if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) return NULL; - ctx = calloc(1, sizeof(*ctx)); - if (ctx) { - ctx->ctx = dctx; - TAILQ_INIT(&ctx->events); - TAILQ_INIT(&ctx->free_events); - TAILQ_INIT(&ctx->timeouts); - TAILQ_INIT(&ctx->free_timeouts); - ctx->exitcode = EXIT_FAILURE; + eloop = calloc(1, sizeof(*eloop)); + if (eloop) { + TAILQ_INIT(&eloop->events); + TAILQ_INIT(&eloop->free_events); + TAILQ_INIT(&eloop->timeouts); + TAILQ_INIT(&eloop->free_timeouts); + eloop->exitcode = EXIT_FAILURE; #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) - ctx->poll_fd = -1; + eloop->poll_fd = -1; + eloop_open(eloop); #endif - if (eloop_requeue(ctx) == -1) { - free(ctx); - return NULL; - } } - return ctx; + return eloop; } -void eloop_free(struct eloop_ctx *ctx) +void eloop_free(struct eloop *eloop) { struct eloop_event *e; struct eloop_timeout *t; - if (ctx == NULL) + if (eloop == NULL) return; - while ((e = TAILQ_FIRST(&ctx->events))) { - TAILQ_REMOVE(&ctx->events, e, next); + while ((e = TAILQ_FIRST(&eloop->events))) { + TAILQ_REMOVE(&eloop->events, e, next); free(e); } - while ((e = TAILQ_FIRST(&ctx->free_events))) { - TAILQ_REMOVE(&ctx->free_events, e, next); + while ((e = TAILQ_FIRST(&eloop->free_events))) { + TAILQ_REMOVE(&eloop->free_events, e, next); free(e); } - while ((t = TAILQ_FIRST(&ctx->timeouts))) { - TAILQ_REMOVE(&ctx->timeouts, t, next); + while ((t = TAILQ_FIRST(&eloop->timeouts))) { + TAILQ_REMOVE(&eloop->timeouts, t, next); free(t); } - while ((t = TAILQ_FIRST(&ctx->free_timeouts))) { - TAILQ_REMOVE(&ctx->free_timeouts, t, next); + while ((t = TAILQ_FIRST(&eloop->free_timeouts))) { + TAILQ_REMOVE(&eloop->free_timeouts, t, next); free(t); } #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) - close(ctx->poll_fd); + close(eloop->poll_fd); #else - free(ctx->fds); + free(eloop->fds); #endif - free(ctx); + free(eloop); } int -eloop_start(struct eloop_ctx *ctx) +eloop_start(struct eloop *eloop, sigset_t *signals) { int n; struct eloop_event *e; struct eloop_timeout *t; struct timespec now, ts, *tsp; void (*t0)(void *); -#if defined(HAVE_EPOLL) || !defined(USE_SIGNALS) - int timeout; -#endif #if defined(HAVE_KQUEUE) struct kevent ke; + UNUSED(signals); #elif defined(HAVE_EPOLL) struct epoll_event epe; #endif +#ifndef HAVE_KQUEUE + int timeout; + + _eloop = eloop; +#endif + + assert(eloop != NULL); for (;;) { - if (ctx->exitnow) + if (eloop->exitnow) break; /* Run all timeouts first */ - if (ctx->timeout0) { - t0 = ctx->timeout0; - ctx->timeout0 = NULL; - t0(ctx->timeout0_arg); + if (eloop->timeout0) { + t0 = eloop->timeout0; + eloop->timeout0 = NULL; + t0(eloop->timeout0_arg); continue; } - if ((t = TAILQ_FIRST(&ctx->timeouts))) { - get_monotonic(&now); + if ((t = TAILQ_FIRST(&eloop->timeouts))) { + clock_gettime(CLOCK_MONOTONIC, &now); if (timespeccmp(&now, &t->when, >)) { - TAILQ_REMOVE(&ctx->timeouts, t, next); + TAILQ_REMOVE(&eloop->timeouts, t, next); t->callback(t->arg); - TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next); + TAILQ_INSERT_TAIL(&eloop->free_timeouts, t, next); continue; } timespecsub(&t->when, &now, &ts); @@ -560,12 +707,10 @@ eloop_start(struct eloop_ctx *ctx) /* No timeouts, so wait forever */ tsp = NULL; - if (tsp == NULL && ctx->events_len == 0) { - logger(ctx->ctx, LOG_ERR, "nothing to do"); + if (tsp == NULL && eloop->events_len == 0) break; - } -#if defined(HAVE_EPOLL) || !defined(USE_SIGNALS) +#ifndef HAVE_KQUEUE if (tsp == NULL) timeout = -1; else if (tsp->tv_sec > INT_MAX / 1000 || @@ -578,27 +723,25 @@ eloop_start(struct eloop_ctx *ctx) #endif #if defined(HAVE_KQUEUE) - n = kevent(ctx->poll_fd, NULL, 0, &ke, 1, tsp); + n = kevent(eloop->poll_fd, NULL, 0, &ke, 1, tsp); #elif defined(HAVE_EPOLL) -#ifdef USE_SIGNALS - n = epoll_pwait(ctx->poll_fd, &epe, 1, timeout, - &ctx->ctx->sigset); -#else - n = epoll_wait(ctx->poll_fd, &epe, 1, timeout); -#endif -#else -#ifdef USE_SIGNALS - n = pollts(ctx->fds, (nfds_t)ctx->events_len, tsp, - &ctx->ctx->sigset); + if (signals) + n = epoll_pwait(eloop->poll_fd, &epe, 1, + timeout, signals); + else + n = epoll_wait(eloop->poll_fd, &epe, 1, timeout); #else - n = poll(ctx->fds, (nfds_t)ctx->events_len, timeout); -#endif + if (signals) + n = pollts(eloop->fds, (nfds_t)eloop->events_len, + tsp, signals); + else + n = poll(eloop->fds, (nfds_t)eloop->events_len, + timeout); #endif if (n == -1) { if (errno == EINTR) continue; - logger(ctx->ctx, LOG_ERR, "poll: %m"); - break; + return -errno; } /* Process any triggered events. @@ -607,10 +750,8 @@ eloop_start(struct eloop_ctx *ctx) #if defined(HAVE_KQUEUE) if (n) { if (ke.filter == EVFILT_SIGNAL) { - struct dhcpcd_siginfo si; - - si.signo = (int)ke.ident; - dhcpcd_handle_signal(&si); + eloop->signal_cb((int)ke.ident, + eloop->signal_cb_ctx); continue; } e = (struct eloop_event *)ke.udata; @@ -625,12 +766,13 @@ eloop_start(struct eloop_ctx *ctx) #elif defined(HAVE_EPOLL) if (n) { e = (struct eloop_event *)epe.data.ptr; - if (epe.events & EPOLLOUT && e->write_cb) { + if (epe.events & EPOLLOUT && e->write_cb != NULL) { e->write_cb(e->write_cb_arg); continue; } if (epe.events & - (EPOLLIN | EPOLLERR | EPOLLHUP)) + (EPOLLIN | EPOLLERR | EPOLLHUP) && + e->read_cb != NULL) { e->read_cb(e->read_cb_arg); continue; @@ -638,14 +780,14 @@ eloop_start(struct eloop_ctx *ctx) } #else if (n > 0) { - TAILQ_FOREACH(e, &ctx->events, next) { + TAILQ_FOREACH(e, &eloop->events, next) { if (e->pollfd->revents & POLLOUT && - e->write_cb) + e->write_cb != NULL) { e->write_cb(e->write_cb_arg); break; } - if (e->pollfd->revents) { + if (e->pollfd->revents && e->read_cb != NULL) { e->read_cb(e->read_cb_arg); break; } @@ -654,5 +796,5 @@ eloop_start(struct eloop_ctx *ctx) #endif } - return ctx->exitcode; + return eloop->exitcode; } Index: src/external/bsd/dhcpcd/dist/if-options.h diff -u src/external/bsd/dhcpcd/dist/if-options.h:1.10 src/external/bsd/dhcpcd/dist/if-options.h:1.11 --- src/external/bsd/dhcpcd/dist/if-options.h:1.10 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/if-options.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if-options.h,v 1.10 2015/05/02 15:18:37 roy Exp $ */ +/* $NetBSD: if-options.h,v 1.11 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -114,6 +114,8 @@ #define DHCPCD_IPV6RA_ACCEPT_NOPUBLIC (1ULL << 56) #define DHCPCD_BOOTP (1ULL << 57) +#define DHCPCD_WAITOPTS (DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6) + #define DHCPCD_WARNINGS (DHCPCD_CSR_WARNED | \ DHCPCD_ROUTER_HOST_ROUTE_WARNED) #define DHCPCD_CONF (DHCPCD_NOPFXDLG | DHCPCD_PFXDLGONLY) @@ -153,11 +155,15 @@ struct if_options { uint8_t requiremask[256 / NBBY]; uint8_t nomask[256 / NBBY]; uint8_t rejectmask[256 / NBBY]; + uint8_t dstmask[256 / NBBY]; + uint8_t requestmasknd[(UINT16_MAX + 1) / NBBY]; + uint8_t requiremasknd[(UINT16_MAX + 1) / NBBY]; + uint8_t nomasknd[(UINT16_MAX + 1) / NBBY]; + uint8_t rejectmasknd[(UINT16_MAX + 1) / NBBY]; uint8_t requestmask6[(UINT16_MAX + 1) / NBBY]; uint8_t requiremask6[(UINT16_MAX + 1) / NBBY]; uint8_t nomask6[(UINT16_MAX + 1) / NBBY]; uint8_t rejectmask6[(UINT16_MAX + 1) / NBBY]; - uint8_t dstmask[256 / NBBY]; uint32_t leasetime; time_t timeout; time_t reboot; @@ -191,6 +197,8 @@ struct if_options { struct dhcp_opt *dhcp_override; size_t dhcp_override_len; + struct dhcp_opt *nd_override; + size_t nd_override_len; struct dhcp_opt *dhcp6_override; size_t dhcp6_override_len; uint32_t vivco_en; Index: src/external/bsd/dhcpcd/dist/ipv4.h diff -u src/external/bsd/dhcpcd/dist/ipv4.h:1.10 src/external/bsd/dhcpcd/dist/ipv4.h:1.11 --- src/external/bsd/dhcpcd/dist/ipv4.h:1.10 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/ipv4.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ipv4.h,v 1.10 2015/05/02 15:18:37 roy Exp $ */ +/* $NetBSD: ipv4.h,v 1.11 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -77,15 +77,18 @@ int ipv4_ifcmp(const struct interface *, uint8_t inet_ntocidr(struct in_addr); int inet_cidrtoaddr(int, struct in_addr *); uint32_t ipv4_getnetmask(uint32_t); +int ipv4_ifaddrexists(const struct interface *); int ipv4_addrexists(struct dhcpcd_ctx *, const struct in_addr *); #define STATE_ADDED 0x01 #define STATE_FAKE 0x02 +#define STATE_TENTATIVE 0x04 void ipv4_buildroutes(struct dhcpcd_ctx *); void ipv4_finaliseaddr(struct interface *); int ipv4_deladdr(struct interface *ifp, const struct in_addr *, const struct in_addr *); +int ipv4_preferanother(struct interface *ifp); void ipv4_applyaddr(void *); int ipv4_handlert(struct dhcpcd_ctx *, int, struct rt *); void ipv4_freerts(struct rt_head *); @@ -109,7 +112,7 @@ void ipv4_ctxfree(struct dhcpcd_ctx *); #define ipv4_freeroutes(a) {} #define ipv4_free(a) {} #define ipv4_ctxfree(a) {} -#define ipv4_addrexists(a, b) (0) +#define ipv4_ifaddrexists(a) (0) #endif #endif Index: src/external/bsd/dhcpcd/dist/if-options.c diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.23 src/external/bsd/dhcpcd/dist/if-options.c:1.24 --- src/external/bsd/dhcpcd/dist/if-options.c:1.23 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/if-options.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if-options.c,v 1.23 2015/05/02 15:18:37 roy Exp $"); + __RCSID("$NetBSD: if-options.c,v 1.24 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -103,6 +103,7 @@ #define O_REJECT O_BASE + 40 #define O_IPV6RA_ACCEPT_NOPUBLIC O_BASE + 41 #define O_BOOTP O_BASE + 42 +#define O_DEFINEND O_BASE + 43 const struct option cf_options[] = { {"background", no_argument, NULL, 'b'}, @@ -178,6 +179,7 @@ const struct option cf_options[] = { {"dev", required_argument, NULL, O_DEV}, {"nodev", no_argument, NULL, O_NODEV}, {"define", required_argument, NULL, O_DEFINE}, + {"definend", required_argument, NULL, O_DEFINEND}, {"define6", required_argument, NULL, O_DEFINE6}, {"embed", required_argument, NULL, O_EMBED}, {"encap", required_argument, NULL, O_ENCAP}, @@ -522,11 +524,22 @@ set_option_space(struct dhcpcd_ctx *ctx, { #if !defined(INET) && !defined(INET6) - /* Satisfy use */ - ctx = NULL; + UNUSED(ctx); #endif #ifdef INET6 + if (strncmp(arg, "nd_", strlen("nd_")) == 0) { + *d = ctx->nd_opts; + *dl = ctx->nd_opts_len; + *od = ifo->nd_override; + *odl = ifo->nd_override_len; + *request = ifo->requestmasknd; + *require = ifo->requiremasknd; + *no = ifo->nomasknd; + *reject = ifo->rejectmasknd; + return arg + strlen("nd_"); + } + if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) { *d = ctx->dhcp6_opts; *dl = ctx->dhcp6_opts_len; @@ -636,7 +649,7 @@ parse_option(struct dhcpcd_ctx *ctx, con int e, i, t; long l; unsigned long u; - char *p = NULL, *fp, *np, **nconf; + char *p = NULL, *bp, *fp, *np, **nconf; ssize_t s; struct in_addr addr, addr2; in_addr_t *naddr; @@ -1469,6 +1482,12 @@ err_sla: dop = &ifo->dhcp_override; dop_len = &ifo->dhcp_override_len; /* FALLTHROUGH */ + case O_DEFINEND: + if (dop == NULL) { + dop = &ifo->nd_override; + dop_len = &ifo->nd_override_len; + } + /* FALLTHROUGH */ case O_DEFINE6: if (dop == NULL) { dop = &ifo->dhcp6_override; @@ -1538,13 +1557,18 @@ err_sla: /* length */ if (np) { *np++ = '\0'; + bp = NULL; /* No bitflag */ l = (long)strtou(np, NULL, 0, 0, LONG_MAX, &e); if (e) { - logger(ctx, LOG_ERR, "failed to convert length"); + logger(ctx,LOG_ERR, "failed to convert length"); return -1; } - } else + } else { l = 0; + bp = strchr(arg, '='); /* bitflag assignment */ + if (bp) + *bp++ = '\0'; + } t = 0; if (strcasecmp(arg, "request") == 0) { t |= REQUEST; @@ -1593,6 +1617,8 @@ err_sla: t |= STRING; else if (strcasecmp(arg, "byte") == 0) t |= UINT8; + else if (strcasecmp(arg, "bitflags") == 0) + t |= BITFLAG; else if (strcasecmp(arg, "uint16") == 0) t |= UINT16; else if (strcasecmp(arg, "int16") == 0) @@ -1640,6 +1666,11 @@ err_sla: logger(ctx, LOG_WARNING, "ignoring array for strings"); t &= ~ARRAY; } + if (t & BITFLAG) { + if (bp == NULL) + logger(ctx, LOG_WARNING, + "missing bitflag assignment"); + } /* variable */ if (!fp) { if (!(t & OPTION)) { @@ -1653,10 +1684,16 @@ err_sla: fp = strwhite(arg); if (fp) *fp++ = '\0'; - np = strdup(arg); - if (np == NULL) { - logger(ctx, LOG_ERR, "%s: %m", __func__); - return -1; + if (strcasecmp(arg, "reserved")) { + np = strdup(arg); + if (np == NULL) { + logger(ctx, LOG_ERR, + "%s: %m", __func__); + return -1; + } + } else { + np = NULL; + t |= RESERVED; } } if (opt != O_EMBED) { @@ -1691,11 +1728,25 @@ err_sla: ndop->type = t; ndop->len = (size_t)l; ndop->var = np; + if (bp) { + dl = strlen(bp); + memcpy(ndop->bitflags, bp, dl); + memset(ndop->bitflags + dl, 0, + sizeof(ndop->bitflags) - dl); + } else + memset(ndop->bitflags, 0, sizeof(ndop->bitflags)); /* Save the define for embed and encap options */ - if (opt == O_DEFINE || opt == O_DEFINE6 || opt == O_VENDOPT) + switch (opt) { + case O_DEFINE: + case O_DEFINEND: + case O_DEFINE6: + case O_VENDOPT: *ldop = ndop; - else if (opt == O_ENCAP) + break; + case O_ENCAP: *edop = ndop; + break; + } break; case O_VENDCLASS: fp = strwhite(arg); @@ -2103,6 +2154,14 @@ read_config(struct dhcpcd_ctx *ctx, ifo->dhcp_override_len = INITDEFINES; #endif +#if defined(INET6) && defined(INITDEFINENDS) + ifo->nd_override = + calloc(INITDEFINENDS, sizeof(*ifo->nd_override)); + if (ifo->nd_override == NULL) + logger(ctx, LOG_ERR, "%s: %m", __func__); + else + ifo->nd_override_len = INITDEFINENDS; +#endif #if defined(INET6) && defined(INITDEFINE6S) ifo->dhcp6_override = calloc(INITDEFINE6S, sizeof(*ifo->dhcp6_override)); @@ -2175,15 +2234,24 @@ read_config(struct dhcpcd_ctx *ctx, ifo->dhcp_override_len = 0; #ifdef INET6 + ctx->nd_opts = ifo->nd_override; + ctx->nd_opts_len = ifo->nd_override_len; ctx->dhcp6_opts = ifo->dhcp6_override; ctx->dhcp6_opts_len = ifo->dhcp6_override_len; #else + for (i = 0, opt = ifo->nd_override; + i < ifo->nd_override_len; + i++, opt++) + free_dhcp_opt_embenc(opt); + free(ifo->nd_override); for (i = 0, opt = ifo->dhcp6_override; i < ifo->dhcp6_override_len; i++, opt++) free_dhcp_opt_embenc(opt); free(ifo->dhcp6_override); #endif + ifo->nd_override = NULL; + ifo->nd_override_len = 0; ifo->dhcp6_override = NULL; ifo->dhcp6_override_len = 0; @@ -2337,6 +2405,11 @@ free_options(struct if_options *ifo) opt++, ifo->dhcp_override_len--) free_dhcp_opt_embenc(opt); free(ifo->dhcp_override); + for (opt = ifo->nd_override; + ifo->nd_override_len > 0; + opt++, ifo->nd_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->nd_override); for (opt = ifo->dhcp6_override; ifo->dhcp6_override_len > 0; opt++, ifo->dhcp6_override_len--) Index: src/external/bsd/dhcpcd/dist/ipv6nd.c diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.23 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.24 --- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.23 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/ipv6nd.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv6nd.c,v 1.23 2015/05/02 15:18:37 roy Exp $"); + __RCSID("$NetBSD: ipv6nd.c,v 1.24 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -157,6 +157,31 @@ static void ipv6nd_handledata(void *); #define IPV6_RECVPKTINFO IPV6_PKTINFO #endif +void +ipv6nd_printoptions(const struct dhcpcd_ctx *ctx, + const struct dhcp_opt *opts, size_t opts_len) +{ + size_t i, j; + const struct dhcp_opt *opt, *opt2; + int cols; + + for (i = 0, opt = ctx->nd_opts; + i < ctx->nd_opts_len; i++, opt++) + { + for (j = 0, opt2 = opts; j < opts_len; j++, opt2++) + if (opt2->option == opt->option) + break; + if (j == opts_len) { + cols = printf("%03d %s", opt->option, opt->var); + dhcp_print_option_encoding(opt, cols); + } + } + for (i = 0, opt = opts; i < opts_len; i++, opt++) { + cols = printf("%03d %s", opt->option, opt->var); + dhcp_print_option_encoding(opt, cols); + } +} + static int ipv6nd_open(struct dhcpcd_ctx *dctx) { @@ -220,7 +245,7 @@ ipv6nd_open(struct dhcpcd_ctx *dctx) eexit: if (ctx->nd_fd != -1) { - eloop_event_delete(dctx->eloop, ctx->nd_fd, 0); + eloop_event_delete(dctx->eloop, ctx->nd_fd); close(ctx->nd_fd); ctx->nd_fd = -1; } @@ -325,14 +350,16 @@ ipv6nd_expire(struct interface *ifp, uin struct ra *rap; struct timespec now; - get_monotonic(&now); + if (ifp->ctx->ipv6 == NULL) + return; + + clock_gettime(CLOCK_MONOTONIC, &now); TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) { if (rap->iface == ifp) { - rap->received = now; + rap->acquired = now; rap->expired = seconds ? 0 : 1; if (seconds) { - struct ra_opt *rao; struct ipv6_addr *ap; rap->lifetime = seconds; @@ -343,9 +370,6 @@ ipv6nd_expire(struct interface *ifp, uin } } ipv6_addaddrs(&rap->addrs); - TAILQ_FOREACH(rao, &rap->options, next) { - timespecclear(&rao->expire); - } } } } @@ -397,18 +421,6 @@ ipv6nd_neighbour(struct dhcpcd_ctx *ctx, } } -static void -ipv6nd_free_opts(struct ra *rap) -{ - struct ra_opt *rao; - - while ((rao = TAILQ_FIRST(&rap->options))) { - TAILQ_REMOVE(&rap->options, rao, next); - free(rao->option); - free(rao); - } -} - struct ipv6_addr * ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr, short flags) @@ -435,19 +447,26 @@ ipv6nd_findaddr(struct dhcpcd_ctx *ctx, return NULL; } -void ipv6nd_freedrop_ra(struct ra *rap, int drop) +static void +ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra) { eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap->iface); eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap); - if (!drop) + if (remove_ra && !drop_ra) TAILQ_REMOVE(rap->iface->ctx->ipv6->ra_routers, rap, next); - ipv6_freedrop_addrs(&rap->addrs, drop, NULL); - ipv6nd_free_opts(rap); + ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL); free(rap->data); free(rap); } +void +ipv6nd_freedrop_ra(struct ra *rap, int drop) +{ + + ipv6nd_removefreedrop_ra(rap, 1, drop); +} + ssize_t ipv6nd_free(struct interface *ifp) { @@ -480,7 +499,7 @@ ipv6nd_free(struct interface *ifp) } if (ifp == NULL) { if (ctx->ipv6->nd_fd != -1) { - eloop_event_delete(ctx->eloop, ctx->ipv6->nd_fd, 0); + eloop_event_delete(ctx->eloop, ctx->ipv6->nd_fd); close(ctx->ipv6->nd_fd); ctx->ipv6->nd_fd = -1; } @@ -531,7 +550,6 @@ ipv6nd_scriptrun(struct ra *rap) { int hasdns, hasaddress, pid; struct ipv6_addr *ap; - const struct ra_opt *rao; hasaddress = 0; /* If all addresses have completed DAD run the script */ @@ -557,16 +575,7 @@ ipv6nd_scriptrun(struct ra *rap) if (!(rap->iface->options->options & DHCPCD_IPV6RA_REQRDNSS)) hasdns = 1; else { - hasdns = 0; - TAILQ_FOREACH(rao, &rap->options, next) { - if (rao->type == ND_OPT_RDNSS && - rao->option && - timespecisset(&rao->expire)) - { - hasdns = 1; - break; - } - } + hasdns = rap->hasdns; } script_runreason(rap->iface, "ROUTERADVERT"); @@ -729,24 +738,19 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, struct icmp6_hdr *icp, size_t len) { struct ipv6_ctx *ctx = dctx->ipv6; - size_t olen, l, n; - ssize_t r; + size_t i, olen; struct nd_router_advert *nd_ra; struct nd_opt_prefix_info *pi; struct nd_opt_mtu *mtu; struct nd_opt_rdnss *rdnss; - struct nd_opt_dnssl *dnssl; - uint32_t lifetime, mtuv; - uint8_t *p, *op; - struct in6_addr addr; + uint32_t mtuv; + uint8_t *p; char buf[INET6_ADDRSTRLEN]; const char *cbp; struct ra *rap; struct nd_opt_hdr *ndo; - struct ra_opt *rao; struct ipv6_addr *ap; - char *opt, *opt2, *tmp; - struct timespec expire; + struct dhcp_opt *dho; uint8_t new_rap, new_data; #ifdef IPV6_MANAGETEMPADDR uint8_t new_ap; @@ -830,7 +834,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, rap->from = ctx->from.sin6_addr; strlcpy(rap->sfrom, ctx->sfrom, sizeof(rap->sfrom)); TAILQ_INIT(&rap->addrs); - TAILQ_INIT(&rap->options); new_rap = 1; } else new_rap = 0; @@ -846,7 +849,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, rap->data_len = len; } - get_monotonic(&rap->received); + clock_gettime(CLOCK_MONOTONIC, &rap->acquired); rap->flags = nd_ra->nd_ra_flags_reserved; if (new_rap == 0 && rap->lifetime == 0) logger(ifp->ctx, LOG_WARNING, "%s: %s router available", @@ -861,6 +864,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, rap->retrans = ntohl(nd_ra->nd_ra_retransmit); if (rap->lifetime) rap->expired = 0; + rap->hasdns = 0; ipv6_settempstale(ifp); TAILQ_FOREACH(ap, &rap->addrs, next) { @@ -869,7 +873,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, len -= sizeof(struct nd_router_advert); p = ((uint8_t *)icp) + sizeof(struct nd_router_advert); - lifetime = ~0U; for (; len > 0; p += olen, len -= olen) { if (len < sizeof(struct nd_opt_hdr)) { logger(ifp->ctx, LOG_ERR, @@ -889,7 +892,34 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, break; } - opt = opt2 = NULL; + if (has_option_mask(ifp->options->rejectmasknd, + ndo->nd_opt_type)) + { + for (i = 0, dho = dctx->nd_opts; + i < dctx->nd_opts_len; + i++, dho++) + { + if (dho->option == ndo->nd_opt_type) + break; + } + if (dho != NULL) + logger(ifp->ctx, LOG_WARNING, + "%s: reject RA (option %s) from %s", + ifp->name, dho->var, ctx->sfrom); + else + logger(ifp->ctx, LOG_WARNING, + "%s: reject RA (option %d) from %s", + ifp->name, ndo->nd_opt_type, ctx->sfrom); + if (new_rap) + ipv6nd_removefreedrop_ra(rap, 0, 0); + else + ipv6nd_free_ra(rap); + return; + } + + if (has_option_mask(ifp->options->nomasknd, ndo->nd_opt_type)) + continue; + switch (ndo->nd_opt_type) { case ND_OPT_PREFIX_INFORMATION: pi = (struct nd_opt_prefix_info *)(void *)ndo; @@ -966,7 +996,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, ap->saddr[0] = '\0'; } ap->dadcallback = ipv6nd_dadcallback; - ap->created = ap->acquired = rap->received; + ap->created = ap->acquired = rap->acquired; TAILQ_INSERT_TAIL(&rap->addrs, ap, next); #ifdef IPV6_MANAGETEMPADDR @@ -986,7 +1016,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, new_ap = 0; #endif ap->flags &= ~IPV6_AF_STALE; - ap->acquired = rap->received; + ap->acquired = rap->acquired; } if (pi->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) @@ -996,16 +1026,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, ap->prefix_pltime = ntohl(pi->nd_opt_pi_preferred_time); ap->nsprobes = 0; - cbp = inet_ntop(AF_INET6, &ap->prefix, buf, sizeof(buf)); - if (cbp) { - l = strlen(cbp); - opt = malloc(l + 5); - if (opt) { - snprintf(opt, l + 5, "%s/%d", cbp, - ap->prefix_len); - opt2 = strdup(ap->saddr); - } - } #ifdef IPV6_MANAGETEMPADDR /* RFC4941 Section 3.3.3 */ @@ -1025,8 +1045,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, } } #endif - - lifetime = ap->prefix_vltime; break; case ND_OPT_MTU: @@ -1038,140 +1056,40 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, break; } rap->mtu = mtuv; - snprintf(buf, sizeof(buf), "%d", mtuv); - opt = strdup(buf); break; case ND_OPT_RDNSS: - rdnss = (struct nd_opt_rdnss *)p; - lifetime = ntohl(rdnss->nd_opt_rdnss_lifetime); - op = (uint8_t *)ndo; - op += offsetof(struct nd_opt_rdnss, - nd_opt_rdnss_lifetime); - op += sizeof(rdnss->nd_opt_rdnss_lifetime); - l = 0; - for (n = (size_t)ndo->nd_opt_len - 1; n > 1; n -= 2, - op += sizeof(addr)) - { - r = ipv6_printaddr(NULL, 0, op, ifp->name); - if (r != -1) - l += (size_t)r + 1; - } - op = (uint8_t *)ndo; - op += offsetof(struct nd_opt_rdnss, - nd_opt_rdnss_lifetime); - op += sizeof(rdnss->nd_opt_rdnss_lifetime); - tmp = opt = malloc(l); - if (opt == NULL) - continue; - for (n = (size_t)ndo->nd_opt_len - 1; n > 1; n -= 2, - op += sizeof(addr)) - { - r = ipv6_printaddr(tmp, l, op, - ifp->name); - if (r != -1) { - l -= ((size_t)r + 1); - tmp += (size_t)r; - *tmp++ = ' '; - } - } - if (tmp != opt) - (*--tmp) = '\0'; - else - *opt = '\0'; - break; - - case ND_OPT_DNSSL: - dnssl = (struct nd_opt_dnssl *)p; - lifetime = ntohl(dnssl->nd_opt_dnssl_lifetime); - op = p + offsetof(struct nd_opt_dnssl, - nd_opt_dnssl_lifetime); - op += sizeof(dnssl->nd_opt_dnssl_lifetime); - n = (size_t)(dnssl->nd_opt_dnssl_len - 1) * 8; - r = decode_rfc3397(NULL, 0, op, n); - if (r < 1) { - logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG, - "%s: invalid DNSSL option", - ifp->name); - continue; - } else { - l = (size_t)r + 1; - tmp = malloc(l); - if (tmp) { - decode_rfc3397(tmp, l, op, n); - l -= 1; - n = (size_t)print_string(NULL, 0, - STRING | ARRAY | DOMAIN, - (const uint8_t *)tmp, l); - n++; - opt = malloc(n); - if (opt) { - print_string(opt, n, - STRING | ARRAY | DOMAIN, - (const uint8_t *)tmp, l); - } else - logger(ifp->ctx, LOG_ERR, - "%s: %m", __func__); - free(tmp); - } - } - break; + rdnss = (struct nd_opt_rdnss *)(void *)p; + if (rdnss->nd_opt_rdnss_lifetime && + rdnss->nd_opt_rdnss_len > 1) + rap->hasdns = 1; default: continue; } + } - if (opt == NULL) { - logger(ifp->ctx, LOG_ERR, "%s: %m", __func__); - continue; - } - - n = ndo->nd_opt_type; -extra_opt: - TAILQ_FOREACH(rao, &rap->options, next) { - if (rao->type == n && - strcmp(rao->option, opt) == 0) - break; - } - if (lifetime == 0 || *opt == '\0') { - if (rao) { - TAILQ_REMOVE(&rap->options, rao, next); - free(rao->option); - free(rao); - } - free(opt); - free(opt2); - continue; - } - - if (rao == NULL) { - rao = malloc(sizeof(*rao)); - if (rao == NULL) { - logger(ifp->ctx, LOG_ERR, "%s: %m", __func__); - continue; - } - rao->type = (uint16_t)n; - rao->option = opt; - TAILQ_INSERT_TAIL(&rap->options, rao, next); - } else - free(opt); - if (lifetime == ~0U) - timespecclear(&rao->expire); - else { - expire.tv_sec = (time_t)lifetime; - expire.tv_nsec = 0; - timespecadd(&rap->received, &expire, &rao->expire); - } - if (rao && rao->type == ND_OPT_PREFIX_INFORMATION && opt2) { - n = _ND_OPT_PREFIX_ADDR; - opt = opt2; - opt2 = NULL; - goto extra_opt; + for (i = 0, dho = dctx->nd_opts; + i < dctx->nd_opts_len; + i++, dho++) + { + if (has_option_mask(ifp->options->requiremasknd, + dho->option)) + { + logger(ifp->ctx, LOG_WARNING, + "%s: reject RA (no option %s) from %s", + ifp->name, dho->var, ctx->sfrom); + if (new_rap) + ipv6nd_removefreedrop_ra(rap, 0, 0); + else + ipv6nd_free_ra(rap); + return; } } if (new_rap) add_router(ifp->ctx->ipv6, rap); + if (!ipv6nd_ra_has_public_addr(rap) && !(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC) && (!(rap->flags & ND_RA_FLAG_MANAGED) || @@ -1191,7 +1109,7 @@ extra_opt: } ipv6_addaddrs(&rap->addrs); #ifdef IPV6_MANAGETEMPADDR - ipv6_addtempaddrs(ifp, &rap->received); + ipv6_addtempaddrs(ifp, &rap->acquired); #endif /* Find any freshly added routes, such as the subnet route. @@ -1289,119 +1207,155 @@ ipv6nd_hasradhcp(const struct interface return 0; } +static const uint8_t * +ipv6nd_getoption(struct dhcpcd_ctx *ctx, + size_t *os, unsigned int *code, size_t *len, + const uint8_t *od, size_t ol, struct dhcp_opt **oopt) +{ + const struct nd_opt_hdr *o; + size_t i; + struct dhcp_opt *opt; + + if (od) { + *os = sizeof(*o); + if (ol < *os) { + errno = EINVAL; + return NULL; + } + o = (const struct nd_opt_hdr *)od; + if (o->nd_opt_len > ol) { + errno = EINVAL; + return NULL; + } + *len = ND_OPTION_LEN(o); + *code = o->nd_opt_type; + } else + o = NULL; + + for (i = 0, opt = ctx->nd_opts; + i < ctx->nd_opts_len; i++, opt++) + { + if (opt->option == *code) { + *oopt = opt; + break; + } + } + + if (o) + return ND_COPTION_DATA(o); + return NULL; +} + ssize_t ipv6nd_env(char **env, const char *prefix, const struct interface *ifp) { - size_t i, l, len; - const struct ra *rap; - const struct ra_opt *rao; - char buffer[32]; - const char *optn; - char **pref, **addr, **mtu, **rdnss, **dnssl, ***var, *new; + size_t i, j, n, len; + struct ra *rap; + char ndprefix[32], abuf[24]; + struct dhcp_opt *opt; + const struct nd_opt_hdr *o; + struct ipv6_addr *ia; + struct timespec now; - i = l = 0; + clock_gettime(CLOCK_MONOTONIC, &now); + i = n = 0; TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) { if (rap->iface != ifp) continue; i++; + if (prefix != NULL) + snprintf(ndprefix, sizeof(ndprefix), + "%s_nd%zu", prefix, i); + else + snprintf(ndprefix, sizeof(ndprefix), + "nd%zu", i); + if (env) + setvar(rap->iface->ctx, &env[n], ndprefix, + "from", rap->sfrom); + n++; + if (env) + setvard(rap->iface->ctx, &env[n], ndprefix, + "acquired", (size_t)rap->acquired.tv_sec); + n++; + if (env) + setvard(rap->iface->ctx, &env[n], ndprefix, + "now", (size_t)now.tv_sec); + n++; + + /* Zero our indexes */ if (env) { - snprintf(buffer, sizeof(buffer), - "ra%zu_from", i); - setvar(ifp->ctx, &env, prefix, buffer, rap->sfrom); - } - l++; - - pref = addr = mtu = rdnss = dnssl = NULL; - TAILQ_FOREACH(rao, &rap->options, next) { - if (rao->option == NULL) - continue; - var = NULL; - switch(rao->type) { - case ND_OPT_PREFIX_INFORMATION: - optn = "prefix"; - var = &pref; - break; - case _ND_OPT_PREFIX_ADDR: - optn = "addr"; - var = &addr; - 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; + for (j = 0, opt = rap->iface->ctx->nd_opts; + j < rap->iface->ctx->nd_opts_len; + j++, opt++) + dhcp_zero_index(opt); + for (j = 0, opt = rap->iface->options->nd_override; + j < rap->iface->options->nd_override_len; + j++, opt++) + dhcp_zero_index(opt); + } + + /* Unlike DHCP, ND6 options *may* occur more than once. + * There is also no provision for option concatenation + * unlike DHCP. */ + len = rap->data_len - + ((size_t)((const uint8_t *)ND_CFIRST_OPTION(rap) - + rap->data)); + + for (o = ND_CFIRST_OPTION(rap); + len >= (ssize_t)sizeof(*o); + o = ND_CNEXT_OPTION(o)) + { + if ((size_t)o->nd_opt_len * 8 > len) { + errno = EINVAL; break; - default: - continue; } - if (*var == NULL) { - *var = env ? env : &new; - l++; - } else if (env) { - /* With single only options, last one takes - * precedence */ - if (rao->type == ND_OPT_MTU) { - new = strchr(**var, '='); - if (new == NULL) { - logger(ifp->ctx, LOG_ERR, - "new is null"); - continue; - } else - new++; - len = (size_t)(new - **var) + - strlen(rao->option) + 1; - if (len > strlen(**var)) - new = realloc(**var, len); - else - new = **var; - if (new) { - **var = new; - new = strchr(**var, '='); - if (new) { - len -= - (size_t) - (new - **var); - strlcpy(new + 1, - rao->option, - len - 1); - } else - logger(ifp->ctx, - LOG_ERR, - "new is null"); - } - continue; - } - len = strlen(rao->option) + 1; - new = realloc(**var, strlen(**var) + 1 + len); - if (new) { - **var = new; - new += strlen(new); - *new++ = ' '; - strlcpy(new, rao->option, len); - } else - logger(ifp->ctx, LOG_ERR, - "%s: %m", __func__); + len -= (size_t)(o->nd_opt_len * 8); + if (has_option_mask(rap->iface->options->nomasknd, + o->nd_opt_type)) continue; + for (j = 0, opt = rap->iface->options->nd_override; + j < rap->iface->options->nd_override_len; + j++, opt++) + if (opt->option == o->nd_opt_type) + break; + if (j == rap->iface->options->nd_override_len) { + for (j = 0, opt = rap->iface->ctx->nd_opts; + j < rap->iface->ctx->nd_opts_len; + j++, opt++) + if (opt->option == o->nd_opt_type) + break; + if (j == rap->iface->ctx->nd_opts_len) + opt = NULL; } + if (opt) { + n += dhcp_envoption(rap->iface->ctx, + env == NULL ? NULL : &env[n], + ndprefix, rap->iface->name, + opt, ipv6nd_getoption, + ND_COPTION_DATA(o), ND_OPTION_LEN(o)); + } + } + + /* We need to output the addresses we actually made + * from the prefix information options as well. */ + j = 0; + TAILQ_FOREACH(ia, &rap->addrs, next) { + if (!(ia->flags & IPV6_AF_AUTOCONF) +#ifdef IPV6_AF_TEMPORARY + || ia->flags & IPV6_AF_TEMPORARY +#endif + ) + continue; + j++; if (env) { - snprintf(buffer, sizeof(buffer), - "ra%zu_%s", i, optn); - setvar(ifp->ctx, &env, - prefix, buffer, rao->option); + snprintf(abuf, sizeof(abuf), "addr%zu", j); + setvar(rap->iface->ctx, &env[n], ndprefix, + abuf, ia->saddr); } + n++; } } - - if (env) - setvard(ifp->ctx, &env, prefix, "ra_count", i); - l++; - return (ssize_t)l; + return (ssize_t)n; } void @@ -1424,12 +1378,11 @@ ipv6nd_expirera(void *arg) { struct interface *ifp; struct ra *rap, *ran; - struct ra_opt *rao, *raon; struct timespec now, lt, expire, next; uint8_t expired, valid, validone; ifp = arg; - get_monotonic(&now); + clock_gettime(CLOCK_MONOTONIC, &now); expired = 0; timespecclear(&next); @@ -1441,7 +1394,7 @@ ipv6nd_expirera(void *arg) if (rap->lifetime) { lt.tv_sec = (time_t)rap->lifetime; lt.tv_nsec = 0; - timespecadd(&rap->received, <, &expire); + timespecadd(&rap->acquired, <, &expire); if (rap->lifetime == 0 || timespeccmp(&now, &expire, >)) { if (!rap->expired) { @@ -1460,43 +1413,10 @@ ipv6nd_expirera(void *arg) } } - /* Addresses are expired in ipv6_addaddrs - * so that DHCPv6 addresses can be removed also. */ - TAILQ_FOREACH_SAFE(rao, &rap->options, next, raon) { - if (rap->expired) { - switch(rao->type) { - case ND_OPT_RDNSS: /* FALLTHROUGH */ - case ND_OPT_DNSSL: - /* RFC6018 end of section 5.2 states - * that if tha RA has a lifetime of 0 - * then we should expire these - * options */ - TAILQ_REMOVE(&rap->options, rao, next); - expired = 1; - free(rao->option); - free(rao); - continue; - } - } - if (!timespecisset(&rao->expire)) - continue; - if (timespeccmp(&now, &rao->expire, >)) { - /* Expired prefixes are logged above */ - if (rao->type != ND_OPT_PREFIX_INFORMATION) - logger(ifp->ctx, LOG_WARNING, - "%s: %s: expired option %d", - ifp->name, rap->sfrom, rao->type); - TAILQ_REMOVE(&rap->options, rao, next); - expired = 1; - free(rao->option); - free(rao); - continue; - } - valid = 1; - timespecsub(&rao->expire, &now, <); - if (!timespecisset(&next) || timespeccmp(&next, <, >)) - next = lt; - } + /* XXX FixMe! + * We need to extract the lifetime from each option and check + * if that has expired or not. + * If it has, zero the option out in the returned data. */ /* No valid lifetimes are left on the RA, so we might * as well punt it. */ @@ -1646,7 +1566,7 @@ ipv6nd_handledata(void *arg) len = recvmsg(ctx->nd_fd, &ctx->rcvhdr, 0); if (len == -1) { logger(dctx, LOG_ERR, "recvmsg: %m"); - eloop_event_delete(dctx->eloop, ctx->nd_fd, 0); + eloop_event_delete(dctx->eloop, ctx->nd_fd); close(ctx->nd_fd); ctx->nd_fd = -1; return; Index: src/external/bsd/dhcpcd/dist/ipv4.c diff -u src/external/bsd/dhcpcd/dist/ipv4.c:1.14 src/external/bsd/dhcpcd/dist/ipv4.c:1.15 --- src/external/bsd/dhcpcd/dist/ipv4.c:1.14 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/ipv4.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv4.c,v 1.14 2015/05/02 15:18:37 roy Exp $"); + __RCSID("$NetBSD: ipv4.c,v 1.15 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -35,6 +35,7 @@ #include <arpa/inet.h> #include <net/route.h> +#include <assert.h> #include <ctype.h> #include <errno.h> #include <stdlib.h> @@ -159,6 +160,15 @@ ipv4_findaddr(struct dhcpcd_ctx *ctx, co } int +ipv4_ifaddrexists(const struct interface *ifp) +{ + const struct dhcp_state *state; + + state = D_CSTATE(ifp); + return (state && state->addr.s_addr != INADDR_ANY); +} + +int ipv4_addrexists(struct dhcpcd_ctx *ctx, const struct in_addr *addr) { struct interface *ifp; @@ -744,6 +754,7 @@ ipv4_deladdr(struct interface *ifp, int r; struct ipv4_state *state; struct ipv4_addr *ap; + struct arp_state *astate; logger(ifp->ctx, LOG_DEBUG, "%s: deleting IP address %s/%d", ifp->name, inet_ntoa(*addr), inet_ntocidr(*net)); @@ -753,14 +764,8 @@ ipv4_deladdr(struct interface *ifp, errno != ENODEV) logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__); - dstate = D_STATE(ifp); - if (dstate->addr.s_addr == addr->s_addr && - dstate->net.s_addr == net->s_addr) - { - dstate->added = 0; - dstate->addr.s_addr = 0; - dstate->net.s_addr = 0; - } + if ((astate = arp_find(ifp, addr)) != NULL) + arp_free(astate); state = IPV4_STATE(ifp); TAILQ_FOREACH(ap, &state->addrs, next) { @@ -772,6 +777,18 @@ ipv4_deladdr(struct interface *ifp, break; } } + + /* Have to do this last incase the function arguments + * were these very pointers. */ + dstate = D_STATE(ifp); + if (dstate && + dstate->addr.s_addr == addr->s_addr && + dstate->net.s_addr == net->s_addr) + { + dstate->added = 0; + dstate->addr.s_addr = 0; + dstate->net.s_addr = 0; + } return r; } @@ -815,6 +832,7 @@ ipv4_addaddr(struct interface *ifp, cons { struct ipv4_state *state; struct ipv4_addr *ia; + struct dhcp_state *dstate; if ((state = ipv4_getstate(ifp)) == NULL) { logger(ifp->ctx, LOG_ERR, "%s: ipv4_getstate: %m", __func__); @@ -852,6 +870,17 @@ ipv4_addaddr(struct interface *ifp, cons ia->addr_flags = IN_IFF_TENTATIVE; #endif TAILQ_INSERT_TAIL(&state->addrs, ia, next); + + dstate = D_STATE(ifp); +#ifdef IN_IFF_TENTATIVE + dstate->added |= STATE_ADDED; +#else + dstate->added = STATE_ADDED; +#endif + dstate->defend = 0; + dstate->addr.s_addr = lease->addr.s_addr; + dstate->net.s_addr = lease->net.s_addr; + return 0; } @@ -860,6 +889,8 @@ ipv4_finalisert(struct interface *ifp) { const struct dhcp_state *state = D_CSTATE(ifp); + assert(state != NULL); + /* Find any freshly added routes, such as the subnet route. * We do this because we cannot rely on recieving the kernel * notification right now via our link socket. */ @@ -884,13 +915,48 @@ ipv4_finaliseaddr(struct interface *ifp) ipv4_iffindaddr(ifp, &lease->addr, NULL)) delete_address(ifp); - state->added = STATE_ADDED; - state->defend = 0; - state->addr.s_addr = lease->addr.s_addr; - state->net.s_addr = lease->net.s_addr; + state->added &= (uint8_t)~(STATE_FAKE | STATE_TENTATIVE); ipv4_finalisert(ifp); } +int +ipv4_preferanother(struct interface *ifp) +{ + struct dhcp_state *state = D_STATE(ifp), *nstate; + struct interface *ifn; + int preferred; + + if (state == NULL) + return 0; + + preferred = 0; + if (!state->added) + goto out; + + TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) { + if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0) + break; /* We are already the most preferred */ + nstate = D_STATE(ifn); + if (nstate && !nstate->added && + nstate->lease.addr.s_addr == state->addr.s_addr) + { + preferred = 1; + delete_address(ifp); + if (ifn->options->options & DHCPCD_ARP) + dhcp_bind(ifn, NULL); + else { + ipv4_addaddr(ifn, &nstate->lease); + nstate->added = STATE_ADDED; + } + break; + } + } + +out: + ipv4_buildroutes(ifp->ctx); + return preferred; +} + void ipv4_applyaddr(void *arg) { @@ -907,38 +973,15 @@ ipv4_applyaddr(void *arg) dhcp = state->new; lease = &state->lease; + if_sortinterfaces(ifp->ctx); if (dhcp == NULL) { if ((ifo->options & (DHCPCD_EXITING | DHCPCD_PERSISTENT)) != (DHCPCD_EXITING | DHCPCD_PERSISTENT)) { - if (state->added) { - struct in_addr addr; - - addr = state->addr; + if (state->added && !ipv4_preferanother(ifp)) { delete_address(ifp); - TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) { - if (ifn == ifp || - strcmp(ifn->name, ifp->name) == 0) - continue; - nstate = D_STATE(ifn); - if (nstate && !nstate->added && - nstate->addr.s_addr == addr.s_addr) - { - if (ifn->options->options & - DHCPCD_ARP) - { - dhcp_bind(ifn, NULL); - } else { - ipv4_addaddr(ifn, - &nstate->lease); - nstate->added = - STATE_ADDED; - } - break; - } - } + ipv4_buildroutes(ifp->ctx); } - ipv4_buildroutes(ifp->ctx); script_runreason(ifp, state->reason); } else ipv4_buildroutes(ifp->ctx); @@ -946,29 +989,30 @@ ipv4_applyaddr(void *arg) } /* Ensure only one interface has the address */ + r = 0; TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) { - if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0) + if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0) { + r = 1; /* past ourselves */ continue; + } nstate = D_STATE(ifn); if (nstate && nstate->added && nstate->addr.s_addr == lease->addr.s_addr) { - if (ifn->metric <= ifp->metric) { + if (r == 0) { logger(ifp->ctx, LOG_INFO, "%s: preferring %s on %s", ifp->name, inet_ntoa(lease->addr), ifn->name); - state->addr.s_addr = lease->addr.s_addr; - state->net.s_addr = lease->net.s_addr; - ipv4_finalisert(ifp); + state->added &= (uint8_t)~STATE_TENTATIVE; + return; } logger(ifp->ctx, LOG_INFO, "%s: preferring %s on %s", ifn->name, inet_ntoa(lease->addr), ifp->name); ipv4_deladdr(ifn, &nstate->addr, &nstate->net); - nstate->added = 0; break; } } Index: src/external/bsd/dhcpcd/dist/ipv6.c diff -u src/external/bsd/dhcpcd/dist/ipv6.c:1.11 src/external/bsd/dhcpcd/dist/ipv6.c:1.12 --- src/external/bsd/dhcpcd/dist/ipv6.c:1.11 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/ipv6.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv6.c,v 1.11 2015/05/02 15:18:37 roy Exp $"); + __RCSID("$NetBSD: ipv6.c,v 1.12 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -38,19 +38,6 @@ #include <netinet/in.h> #include <netinet/if_ether.h> -#ifndef __linux__ -# ifndef __QNX__ -# include <sys/endian.h> -# endif -# include <net/if.h> -# ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */ -# include <net/if_var.h> -# endif -# ifndef __sun -# include <netinet6/in6_var.h> -# endif -#endif - #include <errno.h> #include <ifaddrs.h> #include <inttypes.h> @@ -688,24 +675,36 @@ ipv6_addaddr(struct ipv6_addr *ap, const struct timespec n; if (now == NULL) { - get_monotonic(&n); + clock_gettime(CLOCK_MONOTONIC, &n); now = &n; } timespecsub(now, &ap->acquired, &n); - if (ap->prefix_pltime != ND6_INFINITE_LIFETIME) + if (ap->prefix_pltime != ND6_INFINITE_LIFETIME) { ap->prefix_pltime -= (uint32_t)n.tv_sec; + /* This can happen when confirming a + * deprecated but still valid lease. */ + if (ap->prefix_pltime > pltime) + ap->prefix_pltime = 0; + } if (ap->prefix_vltime != ND6_INFINITE_LIFETIME) ap->prefix_vltime -= (uint32_t)n.tv_sec; - } - if (if_addaddress6(ap) == -1) { - logger(ap->iface->ctx, LOG_ERR, "if_addaddress6: %m"); #if 0 logger(ap->iface->ctx, LOG_DEBUG, + "%s: acquired %lld.%.9ld, now %lld.%.9ld, diff %lld.%.9ld", + ap->iface->name, + (long long)ap->acquired.tv_sec, ap->acquired.tv_nsec, + (long long)now->tv_sec, now->tv_nsec, + (long long)n.tv_sec, n.tv_nsec); + logger(ap->iface->ctx, LOG_DEBUG, "%s: adj pltime %"PRIu32" seconds, " "vltime %"PRIu32" seconds", ap->iface->name, ap->prefix_pltime, ap->prefix_vltime); #endif + } + + if (if_addaddress6(ap) == -1) { + logger(ap->iface->ctx, LOG_ERR, "if_addaddress6: %m"); /* Restore real pltime and vltime */ ap->prefix_pltime = pltime; ap->prefix_vltime = vltime; @@ -829,7 +828,7 @@ ipv6_addaddrs(struct ipv6_addrhead *addr if (ap->flags & IPV6_AF_NEW) i++; if (!timespecisset(&now)) - get_monotonic(&now); + clock_gettime(CLOCK_MONOTONIC, &now); ipv6_addaddr(ap, &now); } } @@ -875,7 +874,7 @@ ipv6_freedrop_addrs(struct ipv6_addrhead DHCPCD_EXITING) && apf) { if (!timespecisset(&now)) - get_monotonic(&now); + clock_gettime(CLOCK_MONOTONIC, &now); ipv6_addaddr(apf, &now); } if (drop == 2) @@ -1466,7 +1465,7 @@ ipv6_tempdadcallback(void *arg) ia->iface->name); return; } - get_monotonic(&tv); + clock_gettime(CLOCK_MONOTONIC, &tv); if ((ia1 = ipv6_createtempaddr(ia, &tv)) == NULL) logger(ia->iface->ctx, LOG_ERR, "ipv6_createtempaddr: %m"); @@ -1571,9 +1570,7 @@ again: cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf)); if (cbp) snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", - cbp, ia->prefix_len); - else - ia->saddr[0] = '\0'; + cbp, ia->prefix_len); else ia->saddr[0] = '\0'; TAILQ_INSERT_TAIL(&state->addrs, ia, next); return ia; @@ -1692,7 +1689,7 @@ ipv6_regentempaddr(void *arg) logger(ia->iface->ctx, LOG_DEBUG, "%s: regen temp addr %s", ia->iface->name, ia->saddr); - get_monotonic(&tv); + clock_gettime(CLOCK_MONOTONIC, &tv); ia1 = ipv6_createtempaddr(ia, &tv); if (ia1) ipv6_addaddr(ia1, &tv); Index: src/external/bsd/dhcpcd/dist/ipv6nd.h diff -u src/external/bsd/dhcpcd/dist/ipv6nd.h:1.11 src/external/bsd/dhcpcd/dist/ipv6nd.h:1.12 --- src/external/bsd/dhcpcd/dist/ipv6nd.h:1.11 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/ipv6nd.h Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ipv6nd.h,v 1.11 2015/05/02 15:18:37 roy Exp $ */ +/* $NetBSD: ipv6nd.h,v 1.12 2015/05/16 23:31:32 roy Exp $ */ /* * dhcpcd - DHCP client daemon @@ -36,13 +36,6 @@ #include "dhcpcd.h" #include "ipv6.h" -struct ra_opt { - TAILQ_ENTRY(ra_opt) next; - uint16_t type; - struct timespec expire; - char *option; -}; - struct ra { TAILQ_ENTRY(ra) next; struct interface *iface; @@ -50,14 +43,14 @@ struct ra { char sfrom[INET6_ADDRSTRLEN]; unsigned char *data; size_t data_len; - struct timespec received; + struct timespec acquired; unsigned char flags; uint32_t lifetime; uint32_t reachable; uint32_t retrans; uint32_t mtu; struct ipv6_addrhead addrs; - TAILQ_HEAD(, ra_opt) options; + uint8_t hasdns; uint8_t expired; uint8_t no_public_warned; }; @@ -73,6 +66,17 @@ struct rs_state { #define RS_STATE(a) ((struct rs_state *)(ifp)->if_data[IF_DATA_IPV6ND]) #define RS_STATE_RUNNING(a) (ipv6nd_hasra((a)) && ipv6nd_dadcompleted((a))) +#define ND_CFIRST_OPTION(m) \ + ((const struct nd_opt_hdr *) \ + ((const uint8_t *)(m)->data + sizeof(struct nd_router_advert))) +#define ND_OPTION_LEN(o) ((size_t)((o)->nd_opt_len * 8) - \ + sizeof(struct nd_opt_hdr)) +#define ND_CNEXT_OPTION(o) \ + ((const struct nd_opt_hdr *)((const uint8_t *)(o) + \ + (size_t)((o)->nd_opt_len * 8))) +#define ND_COPTION_DATA(o) \ + ((const uint8_t *)(o) + sizeof(struct nd_opt_hdr)) + #define MAX_RTR_SOLICITATION_DELAY 1 /* seconds */ #define MAX_UNICAST_SOLICIT 3 /* 3 transmissions */ #define RTR_SOLICITATION_INTERVAL 4 /* seconds */ @@ -93,6 +97,8 @@ struct rs_state { #define IPV6ND_ROUTER (1 << 1) #ifdef INET6 +void ipv6nd_printoptions(const struct dhcpcd_ctx *, + const struct dhcp_opt *, size_t); void ipv6nd_startrs(struct interface *); ssize_t ipv6nd_env(char **, const char *, const struct interface *); struct ipv6_addr *ipv6nd_findaddr(struct dhcpcd_ctx *, @@ -113,7 +119,6 @@ void ipv6nd_drop(struct interface *); void ipv6nd_neighbour(struct dhcpcd_ctx *, struct in6_addr *, int); #else #define ipv6nd_startrs(a) {} -#define ipv6nd_findaddr(a, b, c) (0) #define ipv6nd_free(a) {} #define ipv6nd_hasra(a) (0) #define ipv6nd_dadcompleted(a) (0) Index: src/external/bsd/dhcpcd/dist/script.c diff -u src/external/bsd/dhcpcd/dist/script.c:1.19 src/external/bsd/dhcpcd/dist/script.c:1.20 --- src/external/bsd/dhcpcd/dist/script.c:1.19 Sat May 2 15:18:37 2015 +++ src/external/bsd/dhcpcd/dist/script.c Sat May 16 23:31:32 2015 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: script.c,v 1.19 2015/05/02 15:18:37 roy Exp $"); + __RCSID("$NetBSD: script.c,v 1.20 2015/05/16 23:31:32 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -94,8 +94,9 @@ exec_script(const struct dhcpcd_ctx *ctx { pid_t pid; posix_spawnattr_t attr; - int i; + int r; #ifdef USE_SIGNALS + size_t i; short flags; sigset_t defsigs; #else @@ -110,15 +111,15 @@ exec_script(const struct dhcpcd_ctx *ctx flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF; posix_spawnattr_setflags(&attr, flags); sigemptyset(&defsigs); - for (i = 0; dhcpcd_handlesigs[i]; i++) - sigaddset(&defsigs, dhcpcd_handlesigs[i]); + for (i = 0; i < dhcpcd_signals_len; i++) + sigaddset(&defsigs, dhcpcd_signals[i]); posix_spawnattr_setsigdefault(&attr, &defsigs); posix_spawnattr_setsigmask(&attr, &ctx->sigset); #endif errno = 0; - i = posix_spawn(&pid, argv[0], NULL, &attr, argv, env); - if (i) { - errno = i; + r = posix_spawn(&pid, argv[0], NULL, &attr, argv, env); + if (r) { + errno = r; return -1; } return pid; @@ -287,7 +288,7 @@ make_env(const struct interface *ifp, co if (ifp->ctx->options & DHCPCD_DUMPLEASE) elen = 2; else - elen = 13; + elen = 12; #define EMALLOC(i, l) if ((env[(i)] = malloc((l))) == NULL) goto eexit; /* Make our env + space for profile, wireless and debug */ @@ -374,12 +375,6 @@ make_env(const struct interface *ifp, co env[11] = strdup("if_oneup=false"); if (env[11] == NULL) goto eexit; - if (dhcpcd_ipwaited(ifp->ctx)) - env[12] = strdup("if_ipwaited=true"); - else - env[12] = strdup("if_ipwaited=false"); - if (env[12] == NULL) - goto eexit; if (ifo->options & DHCPCD_DEBUG) { e = strlen("syslog_debug=true") + 1; EMALLOC(elen, e); Index: src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf diff -u src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.6 src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.7 --- src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.6 Fri Nov 7 20:51:03 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf Sat May 16 23:31:32 2015 @@ -1,4 +1,4 @@ -# $NetBSD: 20-resolv.conf,v 1.6 2014/11/07 20:51:03 roy Exp $ +# $NetBSD: 20-resolv.conf,v 1.7 2015/05/16 23:31:32 roy Exp $ # Generate /etc/resolv.conf # Support resolvconf(8) if available @@ -70,17 +70,54 @@ build_resolv_conf() rm -f "$cf" } +# Extract any ND DNS options from the RA +# For now, we ignore the lifetime of the DNS options unless they +# are absent or zero. +# In this case they are removed from consideration. +# See draft-gont-6man-slaac-dns-config-issues-01 for issues +# regarding DNS option lifetime in ND messages. +eval_nd_dns() +{ + + eval ltime=\$nd${i}_rdnss${j}_lifetime + if [ -z "$ltime" -o "$ltime" = 0 ]; then + rdnss= + else + eval rdnss=\$nd${i}_rdnss${j}_servers + fi + eval ltime=\$nd${i}_dnssl${j}_lifetime + if [ -z "$ltime" -o "$ltime" = 0 ]; then + dnssl= + else + eval dnssl=\$nd${i}_dnssl${j}_search + fi + + [ -z "$rdnss" -a -z "$dnssl" ] && return 1 + + new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss" + new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl" + j=$(($j + 1)) + return 0 +} + add_resolv_conf() { - local x= conf="$signature$NL" i=${ra_count:-0} ra= warn=true + local x= conf="$signature$NL" warn=true + local i j ltime rdnss dnssl new_rdnss new_dnssl - while [ $i -ne 0 ]; do - eval ra=\$ra${i}_rdnss - new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$ra" - eval ra=\$ra${i}_dnssl - new_domain_search="$new_domain_search${new_domain_search:+ }$ra" - i=$(($i - 1)) + # Loop to extract the ND DNS options using our indexed shell values + i=1 + j=1 + while true; do + while true; do + eval_nd_dns || break + done + i=$(($i + 1)) + j=1 + eval_nd_dns || break done + new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss" + new_domain_search="$new_domain_search${new_domain_search:+ }$new_dnssl" # If we don't have any configuration, remove it if [ -z "$new_domain_name_servers" -a \