Module Name: src Committed By: roy Date: Mon Jul 14 11:49:48 UTC 2014
Modified Files: src/external/bsd/dhcpcd/dist: dhcp.c dhcpcd.8.in dhcpcd.c dhcpcd.conf.5.in if-bsd.c if-options.c ipv6nd.c script.c Log Message: Sync To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/dhcp.c cvs rdiff -u -r1.28 -r1.29 src/external/bsd/dhcpcd/dist/dhcpcd.8.in cvs rdiff -u -r1.5 -r1.6 src/external/bsd/dhcpcd/dist/dhcpcd.c cvs rdiff -u -r1.8 -r1.9 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in \ src/external/bsd/dhcpcd/dist/ipv6nd.c cvs rdiff -u -r1.6 -r1.7 src/external/bsd/dhcpcd/dist/if-bsd.c \ src/external/bsd/dhcpcd/dist/script.c cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/if-options.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/dhcpcd/dist/dhcp.c diff -u src/external/bsd/dhcpcd/dist/dhcp.c:1.13 src/external/bsd/dhcpcd/dist/dhcp.c:1.14 --- src/external/bsd/dhcpcd/dist/dhcp.c:1.13 Sat Jun 14 20:55:37 2014 +++ src/external/bsd/dhcpcd/dist/dhcp.c Mon Jul 14 11:49:48 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcp.c,v 1.13 2014/06/14 20:55:37 roy Exp $"); + __RCSID("$NetBSD: dhcp.c,v 1.14 2014/07/14 11:49:48 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -128,16 +128,24 @@ static const size_t udp_dhcp_len = sizeo static int dhcp_open(struct interface *); void -dhcp_printoptions(const struct dhcpcd_ctx *ctx) +dhcp_printoptions(const struct dhcpcd_ctx *ctx, + const struct dhcp_opt *opts, size_t opts_len) { const char * const *p; - size_t i; - const struct dhcp_opt *opt; + size_t i, j; + const struct dhcp_opt *opt, *opt2; for (p = dhcp_params; *p; p++) printf(" %s\n", *p); - for (i = 0, opt = ctx->dhcp_opts; i < ctx->dhcp_opts_len; i++, opt++) + for (i = 0, opt = ctx->dhcp_opts; i < ctx->dhcp_opts_len; i++, opt++) { + for (j = 0, opt2 = opts; j < opts_len; j++, opt2++) + if (opt->option == opt2->option) + break; + if (j == opts_len) + printf("%03d %s\n", opt->option, opt->var); + } + for (i = 0, opt = opts; i < opts_len; i++, opt++) printf("%03d %s\n", opt->option, opt->var); } @@ -289,7 +297,7 @@ decode_rfc3442(char *out, size_t len, co errno = EINVAL; return -1; } - ocets = (cidr + 7) / 8; + ocets = (cidr + 7) / NBBY; if (!out) { p += 4 + ocets; bytes += ((4 * 4) * 2) + 4; @@ -360,7 +368,7 @@ decode_rfc3442_rt(const uint8_t *data, s } TAILQ_INSERT_TAIL(routes, rt, next); - ocets = (cidr + 7) / 8; + ocets = (cidr + 7) / NBBY; /* If we have ocets then we have a destination and netmask */ if (ocets > 0) { memcpy(&rt->dest.s_addr, p, ocets); @@ -946,6 +954,30 @@ make_message(struct dhcp_message **messa goto toobig; *p++ = (uint8_t)opt->option; } + for (i = 0, opt = ifo->dhcp_override; + i < ifo->dhcp_override_len; + i++, opt++) + { + /* Check if added above */ + for (lp = n_params + 1; lp < p; lp++) + if (*lp == (uint8_t)opt->option) + break; + if (lp < p) + continue; + if (!(opt->type & REQUEST || + has_option_mask(ifo->requestmask, opt->option))) + continue; + if (opt->type & NOREQ) + continue; + if (type == DHCP_INFORM && + (opt->option == DHO_RENEWALTIME || + opt->option == DHO_REBINDTIME)) + continue; + len = (size_t)((p - m) + 2); + if (len > sizeof(*dhcp)) + goto toobig; + *p++ = (uint8_t)opt->option; + } *n_params = (uint8_t)(p - n_params - 1); } @@ -2736,40 +2768,23 @@ dhcp_open(struct interface *ifp) } int -dhcp_dump(struct dhcpcd_ctx *ctx, const char *ifname) +dhcp_dump(struct interface *ifp) { - struct interface *ifp; struct dhcp_state *state; - if (ctx->ifaces == NULL) { - ctx->ifaces = malloc(sizeof(*ctx->ifaces)); - if (ctx->ifaces == NULL) - return -1; - TAILQ_INIT(ctx->ifaces); - } - state = NULL; - ifp = calloc(1, sizeof(*ifp)); - if (ifp == NULL) - goto eexit; - ifp->ctx = ctx; - TAILQ_INSERT_HEAD(ctx->ifaces, ifp, next); ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state)); if (state == NULL) goto eexit; - ifp->options = calloc(1, sizeof(*ifp->options)); - if (ifp->options == NULL) - goto eexit; - strlcpy(ifp->name, ifname, sizeof(ifp->name)); snprintf(state->leasefile, sizeof(state->leasefile), LEASEFILE, ifp->name); state->new = read_lease(ifp); if (state->new == NULL && errno == ENOENT) { - strlcpy(state->leasefile, ifname, sizeof(state->leasefile)); + strlcpy(state->leasefile, ifp->name, sizeof(state->leasefile)); state->new = read_lease(ifp); } if (state->new == NULL) { if (errno == ENOENT) - syslog(LOG_ERR, "%s: no lease to dump", ifname); + syslog(LOG_ERR, "%s: no lease to dump", ifp->name); return -1; } state->reason = "DUMP"; @@ -3018,13 +3033,22 @@ dhcp_start(struct interface *ifp) if (!(ifp->options->options & DHCPCD_IPV4)) return; - tv.tv_sec = DHCP_MIN_DELAY; - tv.tv_usec = (suseconds_t)arc4random_uniform( - (DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000); - timernorm(&tv); - syslog(LOG_DEBUG, - "%s: delaying DHCP for %0.1f seconds", - ifp->name, timeval_to_double(&tv)); + /* No point in delaying a static configuration */ + if (ifp->options->options & DHCPCD_STATIC && + !(ifp->options->options & DHCPCD_INFORM)) + { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = DHCP_MIN_DELAY; + tv.tv_usec = (suseconds_t)arc4random_uniform( + (DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000); + timernorm(&tv); + syslog(LOG_DEBUG, + "%s: delaying DHCP for %0.1f seconds", + ifp->name, timeval_to_double(&tv)); + } + eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_start1, ifp); } Index: src/external/bsd/dhcpcd/dist/dhcpcd.8.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.28 src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.29 --- src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.28 Sat Jun 14 20:55:37 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.8.in Mon Jul 14 11:49:48 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd.8.in,v 1.28 2014/06/14 20:55:37 roy Exp $ +.\" $NetBSD: dhcpcd.8.in,v 1.29 2014/07/14 11:49:48 roy Exp $ .\" Copyright (c) 2006-2014 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 June 2, 2014 +.Dd July 7, 2014 .Dt DHCPCD 8 .Os .Sh NAME @@ -76,7 +76,7 @@ .Sh DESCRIPTION .Nm is an implementation of the DHCP client specified in -.%R RFC 2131 . +.Li RFC 2131 . .Nm gets the host information .Po @@ -104,17 +104,17 @@ to renew early. .Pp .Nm is also an implementation of the BOOTP client specified in -.%R RFC 951 . +.Li RFC 951 . .Pp .Nm is also an implementation of the IPv6 Router Solicitor as specified in -.%R RFC 4861 +.Li RFC 4861 and -.%R RFC 6106 . +.Li RFC 6106 . .Pp .Nm is also an implemenation of the DHCPv6 client as specified in -.%R RFC 3315 . +.Li RFC 3315 . By default, .Nm only starts DHCPv6 when instructed to do so by an IPV6 Router Advertisement. @@ -212,7 +212,7 @@ instead of the default .Pa @SCRIPT@ . .It Fl D , Fl Fl duid Generate an -.%R RFC 4361 +.Li RFC 4361 compliant clientid. This requires persistent storage and not all DHCP servers work with it so it is not enabled by default. @@ -260,7 +260,7 @@ are disable, none, ptr and both. itself never does any DNS updates. .Nm encodes the FQDN hostname as specified in -.%R RFC1035 . +.Li RFC1035 . .It Fl f , Fl Fl config Ar file Specify a config to load instead of .Pa @SYSCONFDIR@/dhcpcd.conf . @@ -553,6 +553,14 @@ Dumps the last lease for the to stdout. .Ar interface could also be a path to a DHCP wire formatted file. +Use the +.Fl 4 +or +.Fl 6 +flags to specify an address family. +Pass a 2nd +.Fl U, Fl Fl dumplease option to dump a secondary lease, such as +DHCPv6 Prefix Delegation when not being mixed with another IA type. .It Fl V, Fl Fl variables Display a list of option codes and the associated variable for use in .Xr dhcpcd-run-hooks 8 . @@ -672,7 +680,8 @@ RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 213 RFC\ 3004, RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396, RFC\ 3397, RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075, RFC\ 4242, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833, -RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6704, RFC\ 7217. +RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6603, RFC\ 6704, +RFC\ 7217. .Sh AUTHORS .An Roy Marples Aq Mt r...@marples.name .Sh BUGS Index: src/external/bsd/dhcpcd/dist/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.5 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.6 --- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.5 Sat Jun 14 20:55:37 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.c Mon Jul 14 11:49:48 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcpcd.c,v 1.5 2014/06/14 20:55:37 roy Exp $"); + __RCSID("$NetBSD: dhcpcd.c,v 1.6 2014/07/14 11:49:48 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -142,14 +142,14 @@ free_globals(struct dhcpcd_ctx *ctx) struct dhcp_opt *opt; if (ctx->ifac) { - for (ctx->ifac--; ctx->ifac >= 0; ctx->ifac--) - free(ctx->ifav[ctx->ifac]); + for (; ctx->ifac > 0; ctx->ifac--) + free(ctx->ifav[ctx->ifac - 1]); free(ctx->ifav); ctx->ifav = NULL; } if (ctx->ifdc) { - for (ctx->ifdc--; ctx->ifdc >= 0; ctx->ifdc--) - free(ctx->ifdv[ctx->ifdc]); + for (; ctx->ifdc > 0; ctx->ifdc--) + free(ctx->ifdv[ctx->ifdc - 1]); free(ctx->ifdv); ctx->ifdv = NULL; } @@ -326,6 +326,9 @@ configure_interface1(struct interface *i { struct if_options *ifo = ifp->options; int ra_global, ra_iface; +#ifdef INET6 + size_t i; +#endif /* Do any platform specific configuration */ if_conf(ifp); @@ -342,7 +345,7 @@ configure_interface1(struct interface *i ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL); if (!(ifp->flags & (IFF_POINTOPOINT | IFF_LOOPBACK | IFF_MULTICAST))) ifo->options &= ~DHCPCD_IPV6RS; - if (ifo->options & DHCPCD_LINK && if_carrier(ifp) == LINK_UNKNOWN) + if (ifo->options & DHCPCD_LINK && ifp->carrier == LINK_UNKNOWN) ifo->options &= ~DHCPCD_LINK; if (ifo->metric != -1) @@ -434,17 +437,27 @@ configure_interface1(struct interface *i } #ifdef INET6 - if (ifo->ia == NULL && ifo->options & DHCPCD_IPV6) { - ifo->ia = malloc(sizeof(*ifo->ia)); - if (ifo->ia == NULL) - syslog(LOG_ERR, "%s: %m", __func__); - else { - if (ifo->ia_type == 0) - ifo->ia_type = D6_OPTION_IA_NA; - memcpy(ifo->ia->iaid, ifo->iaid, sizeof(ifo->iaid)); - ifo->ia_len = 1; - ifo->ia->sla = NULL; - ifo->ia->sla_len = 0; + if (ifo->options & DHCPCD_IPV6) { + if (ifo->ia == NULL) { + ifo->ia = malloc(sizeof(*ifo->ia)); + if (ifo->ia == NULL) + syslog(LOG_ERR, "%s: %m", __func__); + else { + ifo->ia_len = 1; + ifo->ia->ia_type = D6_OPTION_IA_NA; + memcpy(ifo->ia->iaid, ifo->iaid, + sizeof(ifo->iaid)); + memset(&ifo->ia->addr, 0, + sizeof(ifo->ia->addr)); + ifo->ia->sla = NULL; + ifo->ia->sla_len = 0; + } + } else { + for (i = 0; i < ifo->ia_len; i++) { + if (!ifo->ia[i].iaid_set) + memcpy(ifo->ia->iaid, ifo->iaid, + sizeof(ifo->iaid)); + } } } #endif @@ -496,10 +509,23 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx * if (ifp == NULL || !(ifp->options->options & DHCPCD_LINK)) return; - if (carrier == LINK_UNKNOWN) + switch(carrier) { + case LINK_UNKNOWN: carrier = if_carrier(ifp); /* will set ifp->flags */ - else + break; + case LINK_UP: + /* we have a carrier! however, we need to ignore the flags + * set in the kernel message as sometimes this message is + * reported before IFF_UP is set by the kernel even though + * dhcpcd has already set it. + * + * So we check the flags now. If IFF_UP is still not set + * then we should expect an accompanying link_down message */ + if_setflag(ifp, 0); /* will set ifp->flags */ + break; + default: ifp->flags = flags; + } if (carrier == LINK_UNKNOWN) syslog(LOG_ERR, "%s: carrier_status: %m", ifname); @@ -547,6 +573,8 @@ warn_iaid_conflict(struct interface *ifp TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) { if (ifn == ifp) continue; + if (ifn->options->options & DHCPCD_PFXDLGONLY) + continue; if (memcmp(ifn->options->iaid, iaid, sizeof(ifn->options->iaid)) == 0) break; @@ -558,38 +586,39 @@ warn_iaid_conflict(struct interface *ifp } /* This is only a problem if the interfaces are on the same network. */ - if (ifn) + if (ifn && strcmp(ifp->name, ifn->name)) syslog(LOG_ERR, "%s: IAID conflicts with one assigned to %s", ifp->name, ifn->name); } -void -dhcpcd_startinterface(void *arg) +static void +pre_start(struct interface *ifp) { - struct interface *ifp = arg; - struct if_options *ifo = ifp->options; - size_t i; - char buf[DUID_LEN * 3]; /* Add our link-local address before upping the interface * so our RFC7217 address beats the hwaddr based one. * This is also a safety check incase it was ripped out * from under us. */ - if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) { + if (ifp->options->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) { syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name); - ifo->options &= DHCPCD_IPV6; + ifp->options->options &= DHCPCD_IPV6; } +} - if (!(ifp->flags & IFF_UP) && if_carrier(ifp) != LINK_UNKNOWN) { - if (if_up(ifp) == -1) - syslog(LOG_ERR, "%s: if_up: %m", - ifp->name); - } +void +dhcpcd_startinterface(void *arg) +{ + struct interface *ifp = arg; + struct if_options *ifo = ifp->options; + size_t i; + char buf[DUID_LEN * 3]; + + pre_start(ifp); + if (if_up(ifp) == -1) + syslog(LOG_ERR, "%s: if_up: %m", ifp->name); - if (ifp->carrier == LINK_UNKNOWN) - dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name); - if (ifp->carrier == LINK_DOWN) { + if (ifp->carrier == LINK_DOWN && ifo->options & DHCPCD_LINK) { syslog(LOG_INFO, "%s: waiting for carrier", ifp->name); return; } @@ -599,11 +628,17 @@ dhcpcd_startinterface(void *arg) if (ifp->ctx->duid == NULL) { if (duid_init(ifp) == 0) return; - syslog(LOG_INFO, "DUID %s", - hwaddr_ntoa(ifp->ctx->duid, ifp->ctx->duid_len, - buf, sizeof(buf))); + if (!(ifo->options & DHCPCD_PFXDLGONLY)) + syslog(LOG_INFO, "DUID %s", + hwaddr_ntoa(ifp->ctx->duid, + ifp->ctx->duid_len, + buf, sizeof(buf))); } + } + if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6) && + !(ifo->options & DHCPCD_PFXDLGONLY)) + { /* Report IAIDs */ syslog(LOG_INFO, "%s: IAID %s", ifp->name, hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid), @@ -624,10 +659,12 @@ dhcpcd_startinterface(void *arg) if (ifo->options & DHCPCD_IPV6) { if (ifo->options & DHCPCD_IPV6RS && - !(ifo->options & DHCPCD_INFORM)) + !(ifo->options & (DHCPCD_INFORM | DHCPCD_PFXDLGONLY))) ipv6nd_startrs(ifp); - if (!(ifo->options & DHCPCD_IPV6RS)) { + if (!(ifo->options & DHCPCD_IPV6RS) || + ifo->options & DHCPCD_IA_FORCED) + { ssize_t nolease; if (ifo->options & DHCPCD_IA_FORCED) @@ -654,6 +691,8 @@ dhcpcd_startinterface(void *arg) "%s: dhcp6_start: %m", ifp->name); } } + if (ifo->options & DHCPCD_PFXDLGONLY) + return; if (ifo->options & DHCPCD_IPV4) dhcp_start(ifp); @@ -674,7 +713,7 @@ handle_link(void *arg) } static void -init_state(struct interface *ifp, int argc, char **argv) +dhcpcd_initstate1(struct interface *ifp, int argc, char **argv) { struct if_options *ifo; @@ -700,34 +739,27 @@ init_state(struct interface *ifp, int ar } } +void +dhcpcd_initstate(struct interface *ifp) +{ + + dhcpcd_initstate1(ifp, ifp->ctx->argc, ifp->ctx->argv); +} + static void run_preinit(struct interface *ifp) { - const char *reason; - reason = NULL; /* appease gcc */ - if (ifp->options->options & DHCPCD_LINK) { - switch (if_carrier(ifp)) { - case LINK_DOWN: - ifp->carrier = LINK_DOWN; - reason = "NOCARRIER"; - break; - case LINK_UP: - ifp->carrier = LINK_UP; - reason = "CARRIER"; - break; - default: - ifp->carrier = LINK_UNKNOWN; - return; - } - } else - ifp->carrier = LINK_UNKNOWN; + pre_start(ifp); + if (ifp->ctx->options & DHCPCD_TEST) + return; - if (!(ifp->ctx->options & DHCPCD_TEST)) - script_runreason(ifp, "PREINIT"); + script_runreason(ifp, "PREINIT"); - if (ifp->carrier != LINK_UNKNOWN && !(ifp->ctx->options & DHCPCD_TEST)) - script_runreason(ifp, reason); + if (ifp->carrier != LINK_UNKNOWN && + ifp->options->options & DHCPCD_LINK) + script_runreason(ifp, + ifp->carrier == LINK_UP ? "CARRIER" : "NOCARRIER"); } int @@ -735,7 +767,7 @@ dhcpcd_handleinterface(void *arg, int ac { struct dhcpcd_ctx *ctx; struct if_head *ifs; - struct interface *ifp, *ifn, *ifl = NULL; + struct interface *ifp, *iff, *ifn; const char * const argv[] = { ifname }; int i; @@ -746,6 +778,7 @@ dhcpcd_handleinterface(void *arg, int ac errno = ESRCH; return -1; } + syslog(LOG_DEBUG, "%s: interface departed", ifp->name); ifp->options->options |= DHCPCD_DEPARTED; stop_interface(ifp); return 0; @@ -767,22 +800,24 @@ dhcpcd_handleinterface(void *arg, int ac continue; i = 0; /* Check if we already have the interface */ - ifl = if_find(ctx, ifp->name); - if (ifl) { + iff = if_find(ctx, ifp->name); + if (iff) { + syslog(LOG_DEBUG, "%s: interface updated", iff->name); /* The flags and hwaddr could have changed */ - ifl->flags = ifp->flags; - ifl->hwlen = ifp->hwlen; + iff->flags = ifp->flags; + iff->hwlen = ifp->hwlen; if (ifp->hwlen != 0) - memcpy(ifl->hwaddr, ifp->hwaddr, ifl->hwlen); + memcpy(iff->hwaddr, ifp->hwaddr, iff->hwlen); } else { + syslog(LOG_DEBUG, "%s: interface added", ifp->name); TAILQ_REMOVE(ifs, ifp, next); TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next); - } - if (action > 0) { - init_state(ifp, ctx->argc, ctx->argv); + dhcpcd_initstate(ifp); run_preinit(ifp); - dhcpcd_startinterface(ifp); + iff = ifp; } + if (action > 0) + dhcpcd_startinterface(iff); } /* Free our discovered list */ @@ -857,7 +892,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, in if_free(ifp); } else { TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next); - init_state(ifp, argc, argv); + dhcpcd_initstate1(ifp, argc, argv); run_preinit(ifp); dhcpcd_startinterface(ifp); } @@ -870,7 +905,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, in static void stop_all_interfaces(struct dhcpcd_ctx *ctx, int do_release) { - struct interface *ifp; + struct interface *ifp, *ifpm; /* drop_dhcp could change the order, so we do it like this. */ for (;;) { @@ -878,6 +913,10 @@ stop_all_interfaces(struct dhcpcd_ctx *c ifp = TAILQ_LAST(ctx->ifaces, if_head); if (ifp == NULL) break; + /* Stop the master interface only */ + ifpm = if_find(ifp->ctx, ifp->name); + if (ifpm) + ifp = ifpm; if (do_release) { ifp->options->options |= DHCPCD_RELEASE; ifp->options->options &= ~DHCPCD_PERSISTENT; @@ -1250,10 +1289,13 @@ main(int argc, char **argv) i = 1; break; case 'U': - i = 2; + if (i == 3) + i = 4; + else if (i != 4) + i = 3; break; case 'V': - i = 3; + i = 2; break; case '?': usage(); @@ -1267,25 +1309,36 @@ main(int argc, char **argv) ctx.ifv = argv + optind; ifo = read_config(&ctx, NULL, NULL, NULL); + if (ifo == NULL) + goto exit_failure; opt = add_options(&ctx, NULL, ifo, argc, argv); if (opt != 1) { if (opt == 0) usage(); goto exit_failure; } - if (i == 3) { + if (i == 2) { printf("Interface options:\n"); + if (optind == argc - 1) { + free_options(ifo); + ifo = read_config(&ctx, argv[optind], NULL, NULL); + if (ifo == NULL) + goto exit_failure; + add_options(&ctx, NULL, ifo, argc, argv); + } if_printoptions(); #ifdef INET if (family == 0 || family == AF_INET) { printf("\nDHCPv4 options:\n"); - dhcp_printoptions(&ctx); + dhcp_printoptions(&ctx, + ifo->dhcp_override, ifo->dhcp_override_len); } #endif #ifdef INET6 if (family == 0 || family == AF_INET6) { printf("\nDHCPv6 options:\n"); - dhcp6_printoptions(&ctx); + dhcp6_printoptions(&ctx, + ifo->dhcp6_override, ifo->dhcp6_override_len); } #endif goto exit_success; @@ -1296,6 +1349,8 @@ main(int argc, char **argv) ctx.options |= DHCPCD_TEST; else ctx.options |= DHCPCD_DUMPLEASE; + if (i == 4) + ctx.options |= DHCPCD_PFXDLGONLY; ctx.options |= DHCPCD_PERSISTENT; ctx.options &= ~DHCPCD_DAEMONISE; } @@ -1344,8 +1399,7 @@ main(int argc, char **argv) } snprintf(pidfile, sizeof(pidfile), PIDFILE, "-", argv[optind], per); - } - else { + } else { snprintf(pidfile, sizeof(pidfile), PIDFILE, "", "", ""); ctx.options |= DHCPCD_MASTER; } @@ -1354,12 +1408,48 @@ main(int argc, char **argv) if (chdir("/") == -1) syslog(LOG_ERR, "chdir `/': %m"); + /* Freeing allocated addresses from dumping leases can trigger + * eloop removals as well, so init here. */ + ctx.eloop = eloop_init(); + if (ctx.eloop == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + goto exit_failure; + } + if (ctx.options & DHCPCD_DUMPLEASE) { if (optind != argc - 1) { syslog(LOG_ERR, "dumplease requires an interface"); goto exit_failure; } - if (dhcp_dump(&ctx, argv[optind]) == -1) + i = 0; + /* We need to try and find the interface so we can + * load the hardware address to compare automated IAID */ + ctx.ifaces = if_discover(&ctx, 1, argv + optind); + if (ctx.ifaces == NULL) + goto exit_failure; + ifp = TAILQ_FIRST(ctx.ifaces); + if (ifp == NULL) { + ifp = calloc(1, sizeof(*ifp)); + if (ifp == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + goto exit_failure; + } + strlcpy(ifp->name, argv[optind], sizeof(ifp->name)); + ifp->ctx = &ctx; + TAILQ_INSERT_HEAD(ctx.ifaces, ifp, next); + } + configure_interface(ifp, ctx.argc, ctx.argv); + if (ctx.options & DHCPCD_PFXDLGONLY) + ifp->options->options |= DHCPCD_PFXDLGONLY; + if (family == 0 || family == AF_INET) { + if (dhcp_dump(ifp) == -1) + i = 1; + } + if (family == 0 || family == AF_INET6) { + if (dhcp6_dump(ifp) == -1) + i = 1; + } + if (i == -1) goto exit_failure; goto exit_success; } @@ -1399,12 +1489,6 @@ main(int argc, char **argv) syslog(LOG_WARNING, PACKAGE " will not work correctly unless run as root"); - ctx.eloop = eloop_init(); - if (ctx.eloop == NULL) { - syslog(LOG_ERR, "%s: %m", __func__); - goto exit_failure; - } - #ifdef USE_SIGNALS if (sig != 0) { pid = read_pid(pidfile); @@ -1556,7 +1640,7 @@ main(int argc, char **argv) } TAILQ_FOREACH(ifp, ctx.ifaces, next) { - init_state(ifp, argc, argv); + dhcpcd_initstate1(ifp, argc, argv); } if (ctx.options & DHCPCD_BACKGROUND && dhcpcd_daemonise(&ctx)) @@ -1625,7 +1709,6 @@ exit1: free_options(ifo); free_globals(&ctx); - if_rarestore(&ctx); ipv4_ctxfree(&ctx); ipv6_ctxfree(&ctx); dev_stop(&ctx, !(ctx.options & DHCPCD_FORKED)); Index: src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.8 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.9 --- src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.8 Sat Jun 14 20:55:37 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in Mon Jul 14 11:49:48 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd.conf.5.in,v 1.8 2014/06/14 20:55:37 roy Exp $ +.\" $NetBSD: dhcpcd.conf.5.in,v 1.9 2014/07/14 11:49:48 roy Exp $ .\" Copyright (c) 2006-2014 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 June 6, 2014 +.Dd July 7, 2014 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -215,7 +215,7 @@ DNS if the domain part does not match th Also, see the .Ic env option above to control how the hostname is set on the host. -.It Ic ia_na Op Ar iaid +.It Ic ia_na Op Ar iaid Op / address Request a DHCPv6 Normal Address for .Ar iaid . .Ar iaid @@ -231,7 +231,7 @@ Request a DHCPv6 Temporary Address for You can request more than one ia_ta by specifying a unique .Ar iaid for each one. -.It Ic ia_pd Op Ar iaid Op Ar interface Op / Ar sla_id Op / Ar prefix_len +.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len Request a DHCPv6 Delegated Prefix for .Ar iaid . This option must be used in an @@ -251,7 +251,10 @@ Otherwise addresses are only assigned fo and .Ar sla_id . Each assigned address will have a suffix of 1. -You cannot assign a prefix to the requesting interface. +You cannot assign a prefix to the requesting interface unless the +DHCPv6 server supports +.Li RFC6603 +Prefix Exclude Option. .Nm dhcpcd has to be running for all the interfaces it is delegating to. A default @@ -291,6 +294,18 @@ IPv6RS should be disabled globally when .D1 interface eth1 .D1 ipv4 .D1 ipv6rs +.It Ic ia_pd_mix +To be RFC compliant, +.Nm dhcpcd +cannot mix Prefix Delegation with other DHCPv6 address types in the same +session. +This has a number of issues: additional DHCP traffic and potential collisions +between options. +.Ic ia_pd_mix +enables +.Li draft-ietf-dhc-dhcpv6-stateful-issues-06 +support so that Prefix Delegation can be mixed with other address types in +the same session. .It Ic ipv4only Only configure IPv4. .It Ic ipv6only @@ -458,6 +473,9 @@ Subsequent options are only parsed for t .Ar ssid . .It Ic slaac Op Ar hwaddr | Ar private Selects the interface identifier used for SLAAC generated IPv6 addresses. +If +.Ar private +is used, a RFC7217 address is generated. .It Ic static Ar value Configures a static .Ar value . @@ -740,11 +758,5 @@ Same as .Sh AUTHORS .An Roy Marples Aq Mt r...@marples.name .Sh BUGS -When configuring DHCPv6 you can only select one IA type. -I can't think of a use case where you would want different types, -so if you have one then please bring it up for discussion on the -.Aq Mt dhcpcd-disc...@marples.name -mailing list. -.Pp Please report them to .Lk http://roy.marples.name/projects/dhcpcd Index: src/external/bsd/dhcpcd/dist/ipv6nd.c diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.8 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.9 --- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.8 Sat Jun 14 20:55:37 2014 +++ src/external/bsd/dhcpcd/dist/ipv6nd.c Mon Jul 14 11:49:48 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv6nd.c,v 1.8 2014/06/14 20:55:37 roy Exp $"); + __RCSID("$NetBSD: ipv6nd.c,v 1.9 2014/07/14 11:49:48 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -282,7 +282,7 @@ ipv6nd_sendrsprobe(void *arg) dst.sin6_len = sizeof(dst); #endif dst.sin6_scope_id = ifp->index; - if (inet_pton(AF_INET6, ALLROUTERS, &dst.sin6_addr.s6_addr) != 1) { + if (inet_pton(AF_INET6, ALLROUTERS, &dst.sin6_addr) != 1) { syslog(LOG_ERR, "%s: %m", __func__); return; } @@ -627,8 +627,7 @@ ipv6nd_dadcallback(void *arg) ap->dadcounter = dadcounter; ap->flags &= ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED); ap->flags |= IPV6_AF_NEW; - p = inet_ntop(AF_INET6, ap->addr.s6_addr, - buf, sizeof(buf)); + p = inet_ntop(AF_INET6, &ap->addr, buf, sizeof(buf)); if (p) snprintf(ap->saddr, sizeof(ap->saddr), @@ -734,8 +733,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st TAILQ_FOREACH(rap, ctx->ra_routers, next) { if (ifp == rap->iface && - memcmp(rap->from.s6_addr, ctx->from.sin6_addr.s6_addr, - sizeof(rap->from.s6_addr)) == 0) + IN6_ARE_ADDR_EQUAL(&rap->from, &ctx->from.sin6_addr)) break; } @@ -764,8 +762,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st return; } rap->iface = ifp; - memcpy(rap->from.s6_addr, ctx->from.sin6_addr.s6_addr, - sizeof(rap->from.s6_addr)); + rap->from = ctx->from.sin6_addr; strlcpy(rap->sfrom, ctx->sfrom, sizeof(rap->sfrom)); TAILQ_INIT(&rap->addrs); TAILQ_INIT(&rap->options); @@ -852,9 +849,8 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st } TAILQ_FOREACH(ap, &rap->addrs, next) if (ap->prefix_len ==pi->nd_opt_pi_prefix_len && - memcmp(ap->prefix.s6_addr, - pi->nd_opt_pi_prefix.s6_addr, - sizeof(ap->prefix.s6_addr)) == 0) + IN6_ARE_ADDR_EQUAL(&ap->prefix, + &pi->nd_opt_pi_prefix)) break; if (ap == NULL) { if (!(pi->nd_opt_pi_flags_reserved & @@ -868,9 +864,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st ap->iface = rap->iface; ap->flags = IPV6_AF_NEW; ap->prefix_len = pi->nd_opt_pi_prefix_len; - memcpy(ap->prefix.s6_addr, - pi->nd_opt_pi_prefix.s6_addr, - sizeof(ap->prefix.s6_addr)); + ap->prefix = pi->nd_opt_pi_prefix; if (pi->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) { @@ -884,7 +878,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st break; } cbp = inet_ntop(AF_INET6, - ap->addr.s6_addr, + &ap->addr, buf, sizeof(buf)); if (cbp) snprintf(ap->saddr, @@ -947,7 +941,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st op += sizeof(rdnss->nd_opt_rdnss_lifetime); l = 0; for (n = ndo->nd_opt_len - 1; n > 1; n -= 2, - op += sizeof(addr.s6_addr)) + op += sizeof(addr)) { r = ipv6_printaddr(NULL, 0, op, ifp->name); if (r != -1) @@ -961,7 +955,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st if (opt == NULL) continue; for (n = ndo->nd_opt_len - 1; n > 1; n -= 2, - op += sizeof(addr.s6_addr)) + op += sizeof(addr)) { r = ipv6_printaddr(tmp, l, op, ifp->name); @@ -1401,8 +1395,7 @@ ipv6nd_handlena(struct ipv6_ctx *ctx, st TAILQ_FOREACH(rap, ctx->ra_routers, next) { if (rap->iface == ifp && - memcmp(rap->from.s6_addr, nd_na->nd_na_target.s6_addr, - sizeof(rap->from.s6_addr)) == 0) + IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na->nd_na_target)) break; } if (rap == NULL) { Index: src/external/bsd/dhcpcd/dist/if-bsd.c diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.6 src/external/bsd/dhcpcd/dist/if-bsd.c:1.7 --- src/external/bsd/dhcpcd/dist/if-bsd.c:1.6 Sat Jun 14 20:55:37 2014 +++ src/external/bsd/dhcpcd/dist/if-bsd.c Mon Jul 14 11:49:48 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if-bsd.c,v 1.6 2014/06/14 20:55:37 roy Exp $"); + __RCSID("$NetBSD: if-bsd.c,v 1.7 2014/07/14 11:49:48 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -891,9 +891,7 @@ if_managelink(struct dhcpcd_ctx *ctx) case AF_INET6: sin6 = (struct sockaddr_in6*)(void *) rti_info[RTAX_IFA]; - memcpy(ia6.s6_addr, - sin6->sin6_addr.s6_addr, - sizeof(ia6.s6_addr)); + ia6 = sin6->sin6_addr; if (rtm->rtm_type == RTM_NEWADDR) { ifa_flags = if_addrflags6(ifname, &ia6); if (ifa_flags == -1) @@ -1022,45 +1020,6 @@ if_nd6reachable(const char *ifname, stru return flags; } -void -if_rarestore(struct dhcpcd_ctx *ctx) -{ - - if (ctx->options & DHCPCD_FORKED) - return; - - for (; ctx->ra_restore_len > 0; ctx->ra_restore_len--) { -#ifdef ND6_IFF_ACCEPT_RTADV - if (!(ctx->options & DHCPCD_FORKED)) { - syslog(LOG_DEBUG, - "%s: restoring kernel IPv6 RA support", - ctx->ra_restore[ctx->ra_restore_len - 1]); - if (set_if_nd6_flag( - ctx->ra_restore[ctx->ra_restore_len -1], - ND6_IFF_ACCEPT_RTADV) == -1) - syslog(LOG_ERR, "%s: set_if_nd6_flag: %m", - ctx->ra_restore[ctx->ra_restore_len - 1]); -#ifdef ND6_IFF_OVERRIDE_RTADV - if (ctx->ra_kernel_set == 0 && del_if_nd6_flag( - ctx->ra_restore[ctx->ra_restore_len -1], - ND6_IFF_OVERRIDE_RTADV) == -1) - syslog(LOG_ERR, "%s: del_if_nd6_flag: %m", - ctx->ra_restore[ctx->ra_restore_len - 1]); -#endif - } -#endif - free(ctx->ra_restore[ctx->ra_restore_len - 1]); - } - free(ctx->ra_restore); - ctx->ra_restore = NULL; - - if (ctx->ra_kernel_set) { - syslog(LOG_DEBUG, "restoring kernel IPv6 RA support"); - if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 1) == -1) - syslog(LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m"); - } -} - static int if_raflush(void) { @@ -1088,10 +1047,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, con #ifdef ND6_IFF_OVERRIDE_RTADV int override; #endif -#ifdef ND6_IFF_ACCEPT_RTADV - size_t i; - char *p, **nrest; -#endif #ifdef ND6_IFF_IFDISABLED if (del_if_nd6_flag(ifname, ND6_IFF_IFDISABLED) == -1) { @@ -1169,7 +1124,7 @@ if_checkipv6(struct dhcpcd_ctx *ctx, con return ra; } #ifdef ND6_IFF_OVERRIDE_RTADV - if (override == 0 && ctx->ra_kernel_set == 0 && + if (override == 0 && set_if_nd6_flag(ifname, ND6_IFF_OVERRIDE_RTADV) == -1) { @@ -1180,25 +1135,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, con return ra; } #endif - for (i = 0; i < ctx->ra_restore_len; i++) - if (strcmp(ctx->ra_restore[i], ifname) == 0) - break; - if (i == ctx->ra_restore_len) { - p = strdup(ifname); - if (p == NULL) { - syslog(LOG_ERR, "%s: %m", __func__); - return 0; - } - nrest = realloc(ctx->ra_restore, - (ctx->ra_restore_len + 1) * sizeof(char *)); - if (nrest == NULL) { - syslog(LOG_ERR, "%s: %m", __func__); - free(p); - return 0; - } - ctx->ra_restore = nrest; - ctx->ra_restore[ctx->ra_restore_len++] = p; - } return 0; } return ra; @@ -1220,7 +1156,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, con return ra; } ra = 0; - ctx->ra_kernel_set = 1; /* Flush the kernel knowledge of advertised routers * and prefixes so the kernel does not expire prefixes Index: src/external/bsd/dhcpcd/dist/script.c diff -u src/external/bsd/dhcpcd/dist/script.c:1.6 src/external/bsd/dhcpcd/dist/script.c:1.7 --- src/external/bsd/dhcpcd/dist/script.c:1.6 Sat Jun 14 20:55:37 2014 +++ src/external/bsd/dhcpcd/dist/script.c Mon Jul 14 11:49:48 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: script.c,v 1.6 2014/06/14 20:55:37 roy Exp $"); + __RCSID("$NetBSD: script.c,v 1.7 2014/07/14 11:49:48 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -315,7 +315,8 @@ make_env(const struct interface *ifp, co snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp->name)); l = e = strlen("interface_order="); TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) { - e += strlen(ifp2->name) + 1; + if (!(ifp2->options->options & DHCPCD_PFXDLGONLY)) + e += strlen(ifp2->name) + 1; } EMALLOC(8, e); p = env[8]; @@ -323,11 +324,13 @@ make_env(const struct interface *ifp, co e -= l; p += l; TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) { - l = strlcpy(p, ifp2->name, e); - p += l; - e -= l; - *p++ = ' '; - e--; + if (!(ifp2->options->options & DHCPCD_PFXDLGONLY)) { + l = strlcpy(p, ifp2->name, e); + p += l; + e -= l; + *p++ = ' '; + e--; + } } *--p = '\0'; if (strcmp(reason, "TEST") == 0) { @@ -396,6 +399,16 @@ make_env(const struct interface *ifp, co } #endif #ifdef INET6 + if (dhcp6 && d6_state && ifo->options & DHCPCD_PFXDLGONLY) { + nenv = realloc(env, sizeof(char *) * (elen + 2)); + if (nenv == NULL) + goto eexit; + env = nenv; + env[elen] = strdup("ifclass=pd"); + if (env[elen] == NULL) + goto eexit; + elen++; + } if (dhcp6 && d6_state && d6_state->old) { n = dhcp6_env(NULL, NULL, ifp, d6_state->old, d6_state->old_len); Index: src/external/bsd/dhcpcd/dist/if-options.c diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.9 src/external/bsd/dhcpcd/dist/if-options.c:1.10 --- src/external/bsd/dhcpcd/dist/if-options.c:1.9 Sat Jun 14 20:55:37 2014 +++ src/external/bsd/dhcpcd/dist/if-options.c Mon Jul 14 11:49:48 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if-options.c,v 1.9 2014/06/14 20:55:37 roy Exp $"); + __RCSID("$NetBSD: if-options.c,v 1.10 2014/07/14 11:49:48 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -96,6 +96,7 @@ #define O_CONTROLGRP O_BASE + 34 #define O_SLAAC O_BASE + 35 #define O_GATEWAY O_BASE + 36 +#define O_PFXDLGMIX O_BASE + 37 const struct option cf_options[] = { {"background", no_argument, NULL, 'b'}, @@ -182,6 +183,7 @@ const struct option cf_options[] = { {"controlgroup", required_argument, NULL, O_CONTROLGRP}, {"slaac", required_argument, NULL, O_SLAAC}, {"gateway", no_argument, NULL, O_GATEWAY}, + {"ia_pd_mix", no_argument, NULL, O_PFXDLGMIX}, {NULL, 0, NULL, '\0'} }; @@ -521,7 +523,9 @@ parse_addr(__unused struct in_addr *addr static const char * set_option_space(struct dhcpcd_ctx *ctx, - const char *arg, const struct dhcp_opt **d, size_t *dl, + const char *arg, + const struct dhcp_opt **d, size_t *dl, + const struct dhcp_opt **od, size_t *odl, struct if_options *ifo, uint8_t *request[], uint8_t *require[], uint8_t *no[]) { @@ -530,6 +534,8 @@ set_option_space(struct dhcpcd_ctx *ctx, if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) { *d = ctx->dhcp6_opts; *dl = ctx->dhcp6_opts_len; + *od = ifo->dhcp6_override; + *odl = ifo->dhcp6_override_len; *request = ifo->requestmask6; *require = ifo->requiremask6; *no = ifo->nomask6; @@ -540,9 +546,13 @@ set_option_space(struct dhcpcd_ctx *ctx, #ifdef INET *d = ctx->dhcp_opts; *dl = ctx->dhcp_opts_len; + *od = ifo->dhcp_override; + *odl = ifo->dhcp_override_len; #else *d = NULL; *dl = 0; + *od = NULL; + *odl = 0; #endif *request = ifo->requestmask; *require = ifo->requiremask; @@ -633,15 +643,14 @@ parse_option(struct dhcpcd_ctx *ctx, con struct in_addr addr, addr2; in_addr_t *naddr; struct rt *rt; - const struct dhcp_opt *d; + const struct dhcp_opt *d, *od; uint8_t *request, *require, *no; struct dhcp_opt **dop, *ndop; - size_t *dop_len, dl; + size_t *dop_len, dl, odl; struct vivco *vivco; struct token *token; struct group *grp; #ifdef _REENTRANT -#error foo struct group grpbuf; #endif #ifdef INET6 @@ -736,10 +745,10 @@ parse_option(struct dhcpcd_ctx *ctx, con } break; case 'o': - arg = set_option_space(ctx, arg, &d, &dl, ifo, + arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, &request, &require, &no); - if (make_option_mask(d, dl, request, arg, 1) != 0 || - make_option_mask(d, dl, no, arg, -1) != 0) + if (make_option_mask(d, dl, od, odl, request, arg, 1) != 0 || + make_option_mask(d, dl, od, odl, no, arg, -1) != 0) { syslog(LOG_ERR, "unknown option `%s'", arg); return -1; @@ -955,22 +964,22 @@ parse_option(struct dhcpcd_ctx *ctx, con ifo->options |= DHCPCD_MASTER; break; case 'O': - arg = set_option_space(ctx, arg, &d, &dl, ifo, + arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, &request, &require, &no); - if (make_option_mask(d, dl, request, arg, -1) != 0 || - make_option_mask(d, dl, require, arg, -1) != 0 || - make_option_mask(d, dl, no, arg, 1) != 0) + if (make_option_mask(d, dl, od, odl, request, arg, -1) != 0 || + make_option_mask(d, dl, od, odl, require, arg, -1) != 0 || + make_option_mask(d, dl, od, odl, no, arg, 1) != 0) { syslog(LOG_ERR, "unknown option `%s'", arg); return -1; } break; case 'Q': - arg = set_option_space(ctx, arg, &d, &dl, ifo, + arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, &request, &require, &no); - if (make_option_mask(d, dl, require, arg, 1) != 0 || - make_option_mask(d, dl, request, arg, 1) != 0 || - make_option_mask(d, dl, no, arg, -1) != 0) + if (make_option_mask(d, dl, od, odl, require, arg, 1) != 0 || + make_option_mask(d, dl, od, odl, request, arg, 1) != 0 || + make_option_mask(d, dl, od, odl, no, arg, -1) != 0) { syslog(LOG_ERR, "unknown option `%s'", arg); return -1; @@ -1159,8 +1168,11 @@ parse_option(struct dhcpcd_ctx *ctx, con } break; case O_DESTINATION: - if (make_option_mask(ctx->dhcp_opts, ctx->dhcp_opts_len, - ifo->dstmask, arg, 2) != 0) { + arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo, + &request, &require, &no); + if (make_option_mask(d, dl, od, odl, + ifo->dstmask, arg, 2) != 0) + { if (errno == EINVAL) syslog(LOG_ERR, "option `%s' does not take" " an IPv4 address", arg); @@ -1223,35 +1235,41 @@ parse_option(struct dhcpcd_ctx *ctx, con } i = D6_OPTION_IA_PD; } - if (arg != NULL && ifname == NULL) { + if (ifname == NULL && arg) { syslog(LOG_ERR, "IA with IAID must belong in an interface block"); return -1; } ifo->options |= DHCPCD_IA_FORCED; - if (ifo->ia_type != 0 && ifo->ia_type != i) { - syslog(LOG_ERR, "cannot specify a different IA type"); - return -1; - } - ifo->ia_type = (uint16_t)i; - if (arg == NULL) - break; fp = strwhite(arg); - if (fp) + if (fp) { *fp++ = '\0'; - if (parse_iaid(iaid, arg, sizeof(iaid)) == -1) - return -1; + fp = strskipwhite(fp); + } + if (arg) { + p = strchr(arg, '/'); + if (p) + *p++ = '\0'; + if (parse_iaid(iaid, arg, sizeof(iaid)) == -1) + return -1; + } ia = NULL; for (sl = 0; sl < ifo->ia_len; sl++) { - if (ifo->ia[sl].iaid[0] == iaid[0] && + if ((arg == NULL && !ifo->ia[sl].iaid_set) || + (ifo->ia[sl].iaid_set && + ifo->ia[sl].iaid[0] == iaid[0] && ifo->ia[sl].iaid[1] == iaid[1] && ifo->ia[sl].iaid[2] == iaid[2] && - ifo->ia[sl].iaid[3] == iaid[3]) + ifo->ia[sl].iaid[3] == iaid[3])) { ia = &ifo->ia[sl]; break; } } + if (ia && ia->ia_type != (uint16_t)i) { + syslog(LOG_ERR, "Cannot mix IA for the same IAID"); + break; + } if (ia == NULL) { ia = realloc(ifo->ia, sizeof(*ifo->ia) * (ifo->ia_len + 1)); @@ -1261,14 +1279,47 @@ parse_option(struct dhcpcd_ctx *ctx, con } ifo->ia = ia; ia = &ifo->ia[ifo->ia_len++]; - ia->iaid[0] = iaid[0]; - ia->iaid[1] = iaid[1]; - ia->iaid[2] = iaid[2]; - ia->iaid[3] = iaid[3]; - ia->sla = NULL; + ia->ia_type = (uint16_t)i; + if (arg) { + ia->iaid[0] = iaid[0]; + ia->iaid[1] = iaid[1]; + ia->iaid[2] = iaid[2]; + ia->iaid[3] = iaid[3]; + ia->iaid_set = 1; + } else + ia->iaid_set = 0; + if (!ia->iaid_set || + p == NULL || + ia->ia_type == D6_OPTION_IA_TA) + { + memset(&ia->addr, 0, sizeof(ia->addr)); + ia->prefix_len = 0; + } else { + arg = p; + p = strchr(arg, '/'); + if (p) + *p++ = '\0'; + if (inet_pton(AF_INET6, arg, &ia->addr) == -1) { + syslog(LOG_ERR, "%s: %m", arg); + memset(&ia->addr, 0, sizeof(ia->addr)); + } + if (p && ia->ia_type == D6_OPTION_IA_PD) { + i = atoint(p); + if (i != -1 && (i < 8 || i > 120)) { + errno = EINVAL; + i = -1; + } + if (i == -1) { + syslog(LOG_ERR, "%s: %m", p); + ia->prefix_len = 0; + } else + ia->prefix_len = (uint8_t)i; + } + } ia->sla_len = 0; + ia->sla = NULL; } - if (ifo->ia_type != D6_OPTION_IA_PD) + if (ia->ia_type != D6_OPTION_IA_PD) break; for (p = fp; p; p = fp) { fp = strwhite(p); @@ -1287,12 +1338,6 @@ parse_option(struct dhcpcd_ctx *ctx, con np = strchr(p, '/'); if (np) *np++ = '\0'; - if (strcmp(ifname, p) == 0) { - syslog(LOG_ERR, - "%s: cannot assign IA_PD to itself", - ifname); - goto err_sla; - } if (strlcpy(sla->ifname, p, sizeof(sla->ifname)) >= sizeof(sla->ifname)) { @@ -1856,6 +1901,9 @@ err_sla: else ifo->options &= ~DHCPCD_SLAACPRIVATE; break; + case O_PFXDLGMIX: + ifo->options |= DHCPCD_PFXDLGMIX; + break; default: return 0; } @@ -2127,6 +2175,10 @@ read_config(struct dhcpcd_ctx *ctx, skip = 1; continue; } + /* Skip arping if we have selected a profile but not parsing + * one. */ + if (profile && !have_profile && strcmp(option, "arping") == 0) + continue; if (skip) continue; parse_config_line(ctx, ifname, ifo, option, line, &ldop, &edop);