Module Name: src Committed By: roy Date: Fri Mar 14 11:31:11 UTC 2014
Modified Files: src/external/bsd/dhcpcd/dist: dhcp.c dhcpcd.8.in dhcpcd.c if-bsd.c if-options.c ipv6nd.c net.c Log Message: Sync To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/external/bsd/dhcpcd/dist/dhcp.c cvs rdiff -u -r1.26 -r1.27 src/external/bsd/dhcpcd/dist/dhcpcd.8.in cvs rdiff -u -r1.3 -r1.4 src/external/bsd/dhcpcd/dist/dhcpcd.c cvs rdiff -u -r1.4 -r1.5 src/external/bsd/dhcpcd/dist/if-bsd.c cvs rdiff -u -r1.7 -r1.8 src/external/bsd/dhcpcd/dist/if-options.c cvs rdiff -u -r1.6 -r1.7 src/external/bsd/dhcpcd/dist/ipv6nd.c cvs rdiff -u -r1.5 -r1.6 src/external/bsd/dhcpcd/dist/net.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.11 src/external/bsd/dhcpcd/dist/dhcp.c:1.12 --- src/external/bsd/dhcpcd/dist/dhcp.c:1.11 Sat Mar 1 11:04:21 2014 +++ src/external/bsd/dhcpcd/dist/dhcp.c Fri Mar 14 11:31:11 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcp.c,v 1.11 2014/03/01 11:04:21 roy Exp $"); + __RCSID("$NetBSD: dhcp.c,v 1.12 2014/03/14 11:31:11 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -1064,8 +1064,12 @@ read_lease(struct interface *ifp) free(dhcp); return NULL; } - syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, - ifp->name, state->auth.token->secretid); + if (state->auth.token) + syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, + ifp->name, state->auth.token->secretid); + else + syslog(LOG_DEBUG, "%s: accepted reconfigure key", + ifp->name); } return dhcp; @@ -1347,7 +1351,7 @@ dhcp_close(struct interface *ifp) state->raw_fd = -1; } if (state->udp_fd != -1) { - /* we don't listen to events on the udp */ + eloop_event_delete(ifp->ctx->eloop, state->udp_fd); close(state->udp_fd); state->udp_fd = -1; } @@ -2200,8 +2204,12 @@ dhcp_handledhcp(struct interface *iface, iface, dhcp, from, 0); return; } - syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, - iface->name, state->auth.token->secretid); + if (state->auth.token) + syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, + iface->name, state->auth.token->secretid); + else + syslog(LOG_DEBUG, "%s: accepted reconfigure key", + iface->name); } else if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) { log_dhcp1(LOG_ERR, "no authentication", iface, dhcp, from, 0); return; @@ -2614,7 +2622,7 @@ dhcp_handleudp(void *arg) /* Just read what's in the UDP fd and discard it as we always read * from the raw fd */ - read(ctx->udp_fd, buffer, sizeof(buffer)); + (void)read(ctx->udp_fd, buffer, sizeof(buffer)); } static void @@ -2629,7 +2637,7 @@ dhcp_handleifudp(void *arg) /* Just read what's in the UDP fd and discard it as we always read * from the raw fd */ - read(state->udp_fd, buffer, sizeof(buffer)); + (void)read(state->udp_fd, buffer, sizeof(buffer)); } static int @@ -2673,25 +2681,23 @@ dhcp_open(struct interface *ifp) } int -dhcp_dump(const char *ifname) +dhcp_dump(struct dhcpcd_ctx *ctx, const char *ifname) { - struct dhcpcd_ctx ctx; struct interface *ifp; struct dhcp_state *state; - int r; - ifp = NULL; + if (ctx->ifaces == NULL) { + ctx->ifaces = malloc(sizeof(*ctx->ifaces)); + if (ctx->ifaces == NULL) + return -1; + TAILQ_INIT(ctx->ifaces); + } state = NULL; - memset(&ctx, 0, sizeof(ctx)); - ctx.ifaces = malloc(sizeof(*ctx.ifaces)); - if (ctx.ifaces == NULL) - goto eexit; - TAILQ_INIT(ctx.ifaces); ifp = calloc(1, sizeof(*ifp)); if (ifp == NULL) goto eexit; - ifp->ctx = &ctx; - TAILQ_INSERT_HEAD(ctx.ifaces, ifp, next); + 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; @@ -2701,7 +2707,6 @@ dhcp_dump(const char *ifname) strlcpy(ifp->name, ifname, sizeof(ifp->name)); snprintf(state->leasefile, sizeof(state->leasefile), LEASEFILE, ifp->name); - strlcpy(ifp->options->script, SCRIPT, sizeof(ifp->options->script)); state->new = read_lease(ifp); if (state->new == NULL && errno == ENOENT) { strlcpy(state->leasefile, ifname, sizeof(state->leasefile)); @@ -2710,28 +2715,14 @@ dhcp_dump(const char *ifname) if (state->new == NULL) { if (errno == ENOENT) syslog(LOG_ERR, "%s: no lease to dump", ifname); - r = -1; - goto cexit; + return -1; } state->reason = "DUMP"; - r = script_runreason(ifp, state->reason); - goto cexit; + return script_runreason(ifp, state->reason); eexit: syslog(LOG_ERR, "%s: %m", __func__); - r = -1; - -cexit: - if (state) { - free(state->new); - free(state); - } - if (ifp) { - free(ifp->options); - free(ifp); - } - free(ctx.ifaces); - return r; + return -1; } void Index: src/external/bsd/dhcpcd/dist/dhcpcd.8.in diff -u src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.26 src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.27 --- src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.26 Tue Feb 25 13:20:23 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.8.in Fri Mar 14 11:31:11 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: dhcpcd.8.in,v 1.26 2014/02/25 13:20:23 roy Exp $ +.\" $NetBSD: dhcpcd.8.in,v 1.27 2014/03/14 11:31:11 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 February 25, 2014 +.Dd March 7, 2014 .Dt DHCPCD 8 .Os .Sh NAME @@ -31,7 +31,7 @@ .Nd a DHCP client .Sh SYNOPSIS .Nm -.Op Fl 46ABbDdEGgHJKLpqTV +.Op Fl 46ABbDdEGgHJKLMpqTV .Op Fl C , Fl Fl nohook Ar hook .Op Fl c , Fl Fl script Ar script .Op Fl e , Fl Fl env Ar value @@ -327,6 +327,10 @@ By default .Nm does not request any lease time and leaves it in the hands of the DHCP server. +.It Fl M , Fl Fl master +Start +.Nm +in master mode even if only one interface specified on the command line. .It Fl m , Fl Fl metric Ar metric Metrics are used to prefer an interface over another one, lowest wins. .Nm @@ -639,11 +643,11 @@ lease and use the files mtime as when it Stores the monotonic counter used in the .Ar replay field in Authentication Options. -.It Pa @run...@dhcpcd.pid +.It Pa @RUNDIR@/dhcpcd.pid Stores the PID of .Nm running on all interfaces. -.It Pa @RUNDIR@dhcpcd\- Ns Ar interface Ns .pid +.It Pa @RUNDIR@/dhcpcd\- Ns Ar interface Ns .pid Stores the PID of .Nm running on the Index: src/external/bsd/dhcpcd/dist/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.3 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.4 --- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.3 Sat Mar 1 11:04:21 2014 +++ src/external/bsd/dhcpcd/dist/dhcpcd.c Fri Mar 14 11:31:11 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: dhcpcd.c,v 1.3 2014/03/01 11:04:21 roy Exp $"); + __RCSID("$NetBSD: dhcpcd.c,v 1.4 2014/03/14 11:31:11 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -300,9 +300,11 @@ find_interface(struct dhcpcd_ctx *ctx, c { struct interface *ifp; - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - if (strcmp(ifp->name, ifname) == 0) - return ifp; + if (ctx != NULL && ctx->ifaces != NULL) { + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + if (strcmp(ifp->name, ifname) == 0) + return ifp; + } } return NULL; } @@ -522,7 +524,8 @@ handle_carrier(struct dhcpcd_ctx *ctx, i * them as some OS's will remove, mark tentative or * do nothing. */ ipv6_free_ll_callbacks(ifp); - dhcp_drop(ifp, "NOCARRIER"); + dhcp_drop(ifp, "EXPIRE"); + script_runreason(ifp, "NOCARRIER"); } } else if (carrier == LINK_UP && ifp->flags & IFF_UP) { if (ifp->carrier != LINK_UP) { @@ -578,7 +581,8 @@ start_interface(void *arg) size_t i; char buf[DUID_LEN * 3]; - handle_carrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name); + if (ifp->carrier == LINK_UNKNOWN) + handle_carrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name); if (ifp->carrier == LINK_DOWN) { syslog(LOG_INFO, "%s: waiting for carrier", ifp->name); return; @@ -852,6 +856,7 @@ struct dhcpcd_siginfo { pid_t pid; } dhcpcd_siginfo; +#define sigmsg "received signal %s from PID %d, %s" static void handle_signal1(void *arg) { @@ -866,17 +871,17 @@ handle_signal1(void *arg) do_release = 0; switch (si->signo) { case SIGINT: - syslog(LOG_INFO, "received SIGINT from PID %d, stopping", - (int)si->pid); + syslog(LOG_INFO, sigmsg, "INT", (int)si->pid, "stopping"); break; case SIGTERM: - syslog(LOG_INFO, "received SIGTERM from PID %d, stopping", - (int)si->pid); + syslog(LOG_INFO, sigmsg, "TERM", (int)si->pid, "stopping"); break; case SIGALRM: - syslog(LOG_INFO, "received SIGALRM from PID %d, rebinding", - (int)si->pid); - + syslog(LOG_INFO, sigmsg, "ALRM", (int)si->pid, "releasing"); + do_release = 1; + break; + case SIGHUP: + syslog(LOG_INFO, sigmsg, "HUP", (int)si->pid, "rebinding"); free_globals(ctx); ifo = read_config(ctx, NULL, NULL, NULL); add_options(ctx, NULL, ifo, ctx->argc, ctx->argv); @@ -892,20 +897,14 @@ handle_signal1(void *arg) reconf_reboot(ctx, 1, ctx->argc, ctx->argv, ctx->argc - ctx->ifc); return; - case SIGHUP: - syslog(LOG_INFO, "received SIGHUP from PID %d, releasing", - (int)si->pid); - do_release = 1; - break; case SIGUSR1: - syslog(LOG_INFO, "received SIGUSR from PID %d, reconfiguring", - (int)si->pid); + syslog(LOG_INFO, sigmsg, "USR1", (int)si->pid, "reconfiguring"); TAILQ_FOREACH(ifp, ctx->ifaces, next) { ipv4_applyaddr(ifp); } return; case SIGPIPE: - syslog(LOG_WARNING, "received SIGPIPE"); + syslog(LOG_WARNING, "received signal PIPE"); return; default: syslog(LOG_ERR, @@ -921,14 +920,14 @@ handle_signal1(void *arg) } static void -handle_signal(__unused int sig, siginfo_t *siginfo, __unused void *context) +handle_signal(int sig, 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 = siginfo->si_signo; - dhcpcd_siginfo.pid = siginfo->si_pid; + dhcpcd_siginfo.signo = sig; + dhcpcd_siginfo.pid = siginfo ? siginfo->si_pid : 0; eloop_timeout_add_now(dhcpcd_ctx->eloop, handle_signal1, &dhcpcd_siginfo); } @@ -1118,6 +1117,7 @@ main(int argc, char **argv) #endif #ifdef USE_SIGNALS int sig; + const char *siga; #endif struct timespec ts; @@ -1125,6 +1125,7 @@ main(int argc, char **argv) #ifdef USE_SIGNALS dhcpcd_ctx = &ctx; sig = 0; + siga = NULL; #endif closefrom(3); openlog(PACKAGE, LOG_PERROR | LOG_PID, LOG_DAEMON); @@ -1166,15 +1167,19 @@ main(int argc, char **argv) #ifdef USE_SIGNALS case 'g': sig = SIGUSR1; + siga = "USR1"; break; case 'k': - sig = SIGHUP; + sig = SIGALRM; + siga = "ARLM"; break; case 'n': - sig = SIGALRM; + sig = SIGHUP; + siga = "HUP"; break; case 'x': sig = SIGTERM; + siga = "TERM";; break; #endif case 'T': @@ -1194,6 +1199,9 @@ main(int argc, char **argv) ctx.argv = argv; ctx.argc = argc; + ctx.ifc = argc - optind; + ctx.ifv = argv + optind; + ifo = read_config(&ctx, NULL, NULL, NULL); opt = add_options(&ctx, NULL, ifo, argc, argv); if (opt != 1) { @@ -1247,7 +1255,7 @@ main(int argc, char **argv) if (!(ctx.options & (DHCPCD_TEST | DHCPCD_DUMPLEASE))) { /* If we have any other args, we should run as a single dhcpcd * instance for that interface. */ - if (optind == argc - 1) { + if (optind == argc - 1 && !(ctx.options & DHCPCD_MASTER)) { if (strlen(argv[optind]) > IF_NAMESIZE) { syslog(LOG_ERR, "%s: interface name too long", argv[optind]); @@ -1270,13 +1278,15 @@ main(int argc, char **argv) syslog(LOG_ERR, "dumplease requires an interface"); goto exit_failure; } - if (dhcp_dump(argv[optind]) == -1) + if (dhcp_dump(&ctx, argv[optind]) == -1) goto exit_failure; goto exit_success; } #ifdef USE_SIGNALS - if (!(ctx.options & (DHCPCD_MASTER | DHCPCD_TEST))) { + if (!(ctx.options & DHCPCD_TEST) && + (sig == 0 || ctx.ifc != 0)) + { #endif if (ctx.options & DHCPCD_MASTER) i = -1; @@ -1318,20 +1328,20 @@ main(int argc, char **argv) if (sig != 0) { pid = read_pid(pidfile); if (pid != 0) - syslog(LOG_INFO, "sending signal %d to pid %d", - sig, pid); + syslog(LOG_INFO, "sending signal %s to pid %d", + siga, pid); if (pid == 0 || kill(pid, sig) != 0) { - if (sig != SIGALRM && errno != EPERM) + if (sig != SIGHUP && errno != EPERM) syslog(LOG_ERR, ""PACKAGE" not running"); if (pid != 0 && errno != ESRCH) { syslog(LOG_ERR, "kill: %m"); goto exit_failure; } unlink(pidfile); - if (sig != SIGALRM) + if (sig != SIGHUP) goto exit_failure; } else { - if (sig == SIGALRM || sig == SIGUSR1) + if (sig == SIGHUP || sig == SIGUSR1) goto exit_success; /* Spin until it exits */ syslog(LOG_INFO, "waiting for pid %d to exit", pid); @@ -1405,8 +1415,10 @@ main(int argc, char **argv) } #endif - ctx.ifc = argc - optind; - ctx.ifv = argv + optind; +#ifdef __FreeBSD__ + syslog(LOG_WARNING, "FreeBSD errors that are worked around:"); + syslog(LOG_WARNING, "IPv4 subnet routes cannot be deleted"); +#endif /* When running dhcpcd against a single interface, we need to retain * the old behaviour of waiting for an IP address */ Index: src/external/bsd/dhcpcd/dist/if-bsd.c diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.4 src/external/bsd/dhcpcd/dist/if-bsd.c:1.5 --- src/external/bsd/dhcpcd/dist/if-bsd.c:1.4 Tue Feb 25 13:20:23 2014 +++ src/external/bsd/dhcpcd/dist/if-bsd.c Fri Mar 14 11:31:11 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if-bsd.c,v 1.4 2014/02/25 13:20:23 roy Exp $"); + __RCSID("$NetBSD: if-bsd.c,v 1.5 2014/03/14 11:31:11 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -50,6 +50,7 @@ #elif __APPLE__ /* FIXME: Add apple includes so we can work out SSID */ #else +# include <net80211/ieee80211.h> # include <net80211/ieee80211_ioctl.h> #endif @@ -285,19 +286,24 @@ if_route(const struct rt *rt, int action memset(&rtm, 0, sizeof(rtm)); rtm.hdr.rtm_version = RTM_VERSION; rtm.hdr.rtm_seq = 1; + rtm.hdr.rtm_addrs = RTA_DST; if (action == 0) rtm.hdr.rtm_type = RTM_CHANGE; - else if (action > 0) + else if (action > 0) { rtm.hdr.rtm_type = RTM_ADD; - else + rtm.hdr.rtm_addrs |= RTA_GATEWAY; + } else rtm.hdr.rtm_type = RTM_DELETE; rtm.hdr.rtm_flags = RTF_UP; +#ifdef SIOCGIFPRIORITY + rtm.hdr.rtm_priority = rt->metric; +#endif + /* None interface subnet routes are static. */ if (rt->gate.s_addr != INADDR_ANY || rt->net.s_addr != state->net.s_addr || rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr)) rtm.hdr.rtm_flags |= RTF_STATIC; - rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; if (rt->dest.s_addr == rt->gate.s_addr && rt->net.s_addr == INADDR_BROADCAST) rtm.hdr.rtm_flags |= RTF_HOST; @@ -313,17 +319,19 @@ if_route(const struct rt *rt, int action } ADDADDR(&rt->dest); - if ((rtm.hdr.rtm_flags & RTF_HOST && - rt->gate.s_addr != htonl(INADDR_LOOPBACK)) || - !(rtm.hdr.rtm_flags & RTF_STATIC)) - { - /* Make us a link layer socket for the host gateway */ - memset(&su, 0, sizeof(su)); - su.sdl.sdl_len = sizeof(struct sockaddr_dl); - link_addr(rt->iface->name, &su.sdl); - ADDSU; - } else - ADDADDR(&rt->gate); + if (rtm.hdr.rtm_addrs & RTA_GATEWAY) { + if ((rtm.hdr.rtm_flags & RTF_HOST && + rt->gate.s_addr != htonl(INADDR_LOOPBACK)) || + !(rtm.hdr.rtm_flags & RTF_STATIC)) + { + /* Make us a link layer socket for the host gateway */ + memset(&su, 0, sizeof(su)); + su.sdl.sdl_len = sizeof(struct sockaddr_dl); + link_addr(rt->iface->name, &su.sdl); + ADDSU; + } else + ADDADDR(&rt->gate); + } if (rtm.hdr.rtm_addrs & RTA_NETMASK) ADDADDR(&rt->net); @@ -411,7 +419,7 @@ if_route6(const struct rt6 *rt, int acti char *bp = rtm.buffer; size_t l; int s, retval; - const struct ipv6_addr_l *lla; + const struct ipv6_addr *lla; if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) return -1; @@ -456,8 +464,11 @@ if_route6(const struct rt6 *rt, int acti rtm.hdr.rtm_type = RTM_ADD; else rtm.hdr.rtm_type = RTM_DELETE; - rtm.hdr.rtm_flags = RTF_UP; + rtm.hdr.rtm_addrs = RTA_DST | RTA_NETMASK; +#ifdef SIOCGIFPRIORITY + rtm.hdr.rtm_priority = rt->metric; +#endif /* None interface subnet routes are static. */ if (IN6_IS_ADDR_UNSPECIFIED(&rt->dest) && IN6_IS_ADDR_UNSPECIFIED(&rt->net)) @@ -467,19 +478,21 @@ if_route6(const struct rt6 *rt, int acti rtm.hdr.rtm_flags |= RTF_CLONING; #endif - rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; if (action >= 0) - rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA; + rtm.hdr.rtm_addrs |= RTA_GATEWAY | RTA_IFP | RTA_IFA; ADDADDR(&rt->dest); - if (!(rtm.hdr.rtm_flags & RTF_GATEWAY)) { - lla = ipv6_linklocal(rt->iface); - if (lla == NULL) /* unlikely as we need a LL to get here */ - return -1; - ADDADDRS(&lla->addr, rt->iface->index); - } else { - lla = NULL; - ADDADDRS(&rt->gate, rt->iface->index); + lla = NULL; + if (rtm.hdr.rtm_addrs & RTA_GATEWAY) { + if (!(rtm.hdr.rtm_flags & RTF_GATEWAY)) { + lla = ipv6_linklocal(rt->iface); + if (lla == NULL) /* unlikely */ + return -1; + ADDADDRS(&lla->addr, rt->iface->index); + } else { + lla = NULL; + ADDADDRS(&rt->gate, rt->iface->index); + } } if (rtm.hdr.rtm_addrs & RTA_NETMASK) { @@ -582,7 +595,7 @@ manage_link(struct dhcpcd_ctx *ctx) #ifdef INET struct rt rt; #endif -#if defined(INET6) && !defined(LISTEN_DAD) +#ifdef INET6 struct in6_addr ia6; struct sockaddr_in6 *sin6; int ifa_flags; @@ -701,7 +714,7 @@ manage_link(struct dhcpcd_ctx *ctx) &rt.dest, &rt.net, &rt.gate); break; #endif -#if defined(INET6) && !defined(LISTEN_DAD) +#ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6*)(void *) rti_info[RTAX_IFA]; Index: src/external/bsd/dhcpcd/dist/if-options.c diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.7 src/external/bsd/dhcpcd/dist/if-options.c:1.8 --- src/external/bsd/dhcpcd/dist/if-options.c:1.7 Sat Mar 1 11:04:21 2014 +++ src/external/bsd/dhcpcd/dist/if-options.c Fri Mar 14 11:31:11 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: if-options.c,v 1.7 2014/03/01 11:04:21 roy Exp $"); + __RCSID("$NetBSD: if-options.c,v 1.8 2014/03/14 11:31:11 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -127,6 +127,7 @@ const struct option cf_options[] = { {"broadcast", no_argument, NULL, 'J'}, {"nolink", no_argument, NULL, 'K'}, {"noipv4ll", no_argument, NULL, 'L'}, + {"master", no_argument, NULL, 'M'}, {"nooption", optional_argument, NULL, 'O'}, {"require", required_argument, NULL, 'Q'}, {"static", required_argument, NULL, 'S'}, @@ -929,6 +930,9 @@ parse_option(struct dhcpcd_ctx *ctx, con case 'L': ifo->options &= ~DHCPCD_IPV4LL; break; + case 'M': + ifo->options |= DHCPCD_MASTER; + break; case 'O': arg = set_option_space(ctx, arg, &d, &dl, ifo, &request, &require, &no); Index: src/external/bsd/dhcpcd/dist/ipv6nd.c diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.6 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.7 --- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.6 Sat Mar 1 11:04:21 2014 +++ src/external/bsd/dhcpcd/dist/ipv6nd.c Fri Mar 14 11:31:11 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: ipv6nd.c,v 1.6 2014/03/01 11:04:21 roy Exp $"); + __RCSID("$NetBSD: ipv6nd.c,v 1.7 2014/03/14 11:31:11 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -49,14 +49,6 @@ #include <syslog.h> #include <unistd.h> -/* Currently, no known kernel allows us to send from the unspecified address - * which is required for DAD to work. This isn't that much of a problem as - * the kernel will do DAD for us correctly, however we don't know the exact - * randomness the kernel applies to the timeouts. So we just follow the same - * logic and have a little faith. - * This define is purely for completeness */ -// #define IPV6_SEND_DAD - #define ELOOP_QUEUE 2 #include "common.h" #include "dhcpcd.h" @@ -66,11 +58,6 @@ #include "ipv6nd.h" #include "script.h" -#if defined(LISTEN_DAD) && defined(INET6) -# warning kernel does not report DAD results to userland -# warning listening to duplicated addresses on the wire -#endif - /* Debugging Router Solicitations is a lot of spam, so disable it */ //#define DEBUG_RS @@ -172,16 +159,10 @@ ipv6nd_open(struct dhcpcd_ctx *dctx) struct ipv6_ctx *ctx; int on; struct icmp6_filter filt; -#ifdef IPV6_SEND_DAD - union { - struct sockaddr sa; - struct sockaddr_in6 sin; - } su; -#endif ctx = dctx->ipv6; if (ctx->nd_fd != -1) - goto unspec; + return ctx->nd_fd; #ifdef SOCK_CLOEXEC ctx->nd_fd = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6); @@ -206,6 +187,12 @@ ipv6nd_open(struct dhcpcd_ctx *dctx) } #endif + /* RFC4861 4.1 */ + on = 255; + if (setsockopt(ctx->nd_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, + &on, sizeof(on)) == -1) + goto eexit; + on = 1; if (setsockopt(ctx->nd_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) == -1) @@ -224,62 +211,6 @@ ipv6nd_open(struct dhcpcd_ctx *dctx) goto eexit; eloop_event_add(dctx->eloop, ctx->nd_fd, ipv6nd_handledata, dctx); - -unspec: -#ifdef IPV6_SEND_DAD - if (ctx->unspec_fd != -1) - return ctx->nd_fd; - - ICMP6_FILTER_SETBLOCKALL(&filt); - - /* We send DAD requests from the unspecified address. */ -#ifdef SOCK_CLOEXEC - ctx->unspec_fd = socket(AF_INET6, - SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, - IPPROTO_ICMPV6); - if (ctx->unspec_fd == -1) - return -1; -#else - if ((ctx->unspec_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1) - return -1; - if ((on = fcntl(ctx->unspec_fd, F_GETFD, 0)) == -1 || - fcntl(ctx->unspec_fd, F_SETFD, on | FD_CLOEXEC) == -1) - { - close(ctx->unspec_fd); - ctx->unspec_fd = -1; - return -1; - } - if ((on = fcntl(ctx->unspec_fd, F_GETFL, 0)) == -1 || - fcntl(ctx->unspec_fd, F_SETFL, on | O_NONBLOCK) == -1) - { - close(ctx->unspec_fd); - ctx->unspec_fd = -1; - return -1; - } -#endif - - if (setsockopt(ctx->unspec_fd, IPPROTO_ICMPV6, ICMP6_FILTER, - &filt, sizeof(filt)) == -1) - goto eexit; - memset(&su, 0, sizeof(su)); - su.sin.sin6_family = AF_INET6; -#ifdef SIN6_LEN - su.sin.sin6_len = sizeof(su.sin); -#endif - if (bind(ctx->unspec_fd, &su.sa, sizeof(su.sin)) == -1) - goto eexit; -#endif - -#ifdef LISTEN_DAD - if (!ctx->dad_warned) { - syslog(LOG_WARNING, - "kernel does not report DAD results to userland"); - syslog(LOG_WARNING, - "warning listening to duplicated addresses on the wire"); - ctx->dad_warned = 1; - } -#endif - return ctx->nd_fd; eexit: @@ -288,12 +219,6 @@ eexit: close(ctx->nd_fd); ctx->nd_fd = -1; } -#ifdef IPV6_SEND_DAD - if (ctx->unpsec_fd != -1) { - close(ctx->unspec_fd); - ctx->unspec_fd = -1; - } -#endif return -1; } @@ -331,7 +256,6 @@ ipv6nd_sendrsprobe(void *arg) struct sockaddr_in6 dst; struct cmsghdr *cm; struct in6_pktinfo pi; - int hoplimit = HOPLIMIT; if (ipv6_linklocal(ifp) == NULL) { syslog(LOG_DEBUG, @@ -369,15 +293,6 @@ ipv6nd_sendrsprobe(void *arg) pi.ipi6_ifindex = ifp->index; memcpy(CMSG_DATA(cm), &pi, sizeof(pi)); - /* Hop limit */ - cm = CMSG_NXTHDR(&ctx->sndhdr, cm); - if (cm == NULL) /* unlikely */ - return; - cm->cmsg_level = IPPROTO_IPV6; - cm->cmsg_type = IPV6_HOPLIMIT; - cm->cmsg_len = CMSG_LEN(sizeof(hoplimit)); - memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit)); - syslog(LOG_DEBUG, "%s: sending Router Solicitation", ifp->name); if (sendmsg(ctx->nd_fd, &ctx->sndhdr, 0) == -1) { syslog(LOG_ERR, "%s: %s: sendmsg: %m", ifp->name, __func__); @@ -581,16 +496,11 @@ ipv6nd_dadcallback(void *arg) int wascompleted, found; wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED); - ipv6nd_cancelprobeaddr(ap); ap->flags |= IPV6_AF_DADCOMPLETED; if (ap->flags & IPV6_AF_DUPLICATED) /* No idea what how to try and make another address :( */ syslog(LOG_WARNING, "%s: DAD detected %s", ap->iface->name, ap->saddr); -#ifdef IPV6_SEND_DAD - else - ipv6_addaddr(ap); -#endif if (!wascompleted) { ifp = ap->iface; @@ -611,7 +521,7 @@ ipv6nd_dadcallback(void *arg) found = 1; } - if (wascompleted && found && rap->lifetime) { + if (wascompleted && found) { syslog(LOG_DEBUG, "%s: Router Advertisement DAD completed", rap->iface->name); @@ -687,11 +597,6 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st } nd_ra = (struct nd_router_advert *)icp; - /* Don't bother doing anything if we don't know about a router - * expiring */ - if ((rap == NULL || rap->lifetime == 0) - && nd_ra->nd_ra_router_lifetime == 0) - return; /* We don't want to spam the log with the fact we got an RA every * 30 seconds or so, so only spam the log if it's different. */ @@ -860,13 +765,13 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st ntohl(pi->nd_opt_pi_preferred_time); ap->nsprobes = 0; if (opt) { - l = strlen(opt); - tmp = realloc(opt, - l + strlen(ap->saddr) + 2); + l = strlen(opt) + 1; + m = strlen(ap->saddr) + 1; + tmp = realloc(opt, l + m); if (tmp) { opt = tmp; - opt[l] = ' '; - strcpy(opt + l + 1, ap->saddr); + opt[l - 1] = ' '; + strlcpy(opt + l, ap->saddr, m); } } else opt = strdup(ap->saddr); @@ -1001,14 +906,10 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st script_runreason(ifp, "TEST"); goto handle_flag; } - ipv6nd_probeaddrs(&rap->addrs); + ipv6_addaddrs(&rap->addrs); ipv6_buildroutes(ifp->ctx); - - /* We will get run by the expire function */ - if (rap->lifetime) { - if (ipv6nd_scriptrun(rap)) - return; - } + if (ipv6nd_scriptrun(rap)) + return; eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */ @@ -1025,15 +926,13 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st handle_flag: if (rap->flags & ND_RA_FLAG_MANAGED) { - if (rap->lifetime && new_data && - dhcp6_start(ifp, DH6S_INIT) == -1) + if (new_data && dhcp6_start(ifp, DH6S_INIT) == -1) syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name); } else if (rap->flags & ND_RA_FLAG_OTHER) { - if (rap->lifetime && new_data && - dhcp6_start(ifp, DH6S_INFORM) == -1) + if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1) syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name); } else { - if (rap->lifetime && new_data) + if (new_data) syslog(LOG_DEBUG, "%s: No DHCPv6 instruction in RA", ifp->name); if (ifp->ctx->options & DHCPCD_TEST) { @@ -1132,24 +1031,25 @@ ipv6nd_env(char **env, const char *prefi if (new) { **var = new; new = strchr(**var, '='); - if (new) - strcpy(new + 1, - rao->option); - else + if (new) { + len -= (new - **var); + strlcpy(new + 1, + rao->option, + len - 1); + } else syslog(LOG_ERR, "new is null"); } continue; } - new = realloc(**var, - strlen(**var) + 1 + - strlen(rao->option) + 1); + len = strlen(rao->option) + 1; + new = realloc(**var, strlen(**var) + 1 + len); if (new == NULL) return -1; **var = new; new += strlen(new); *new++ = ' '; - strcpy(new, rao->option); + strlcpy(new, rao->option, len); continue; } if (env) { @@ -1202,26 +1102,29 @@ ipv6nd_expirera(void *arg) TAILQ_FOREACH_SAFE(rap, ifp->ctx->ipv6->ra_routers, next, ran) { if (rap->iface != ifp) continue; - lt.tv_sec = rap->lifetime; - lt.tv_usec = 0; - timeradd(&rap->received, <, &expire); - if (rap->lifetime == 0 || timercmp(&now, &expire, >)) { - valid = 0; - if (!rap->expired) { - syslog(LOG_WARNING, - "%s: %s: router expired", - ifp->name, rap->sfrom); - rap->expired = expired = 1; - ipv6nd_cancelproberouter(rap); + valid = 0; + if (rap->lifetime) { + lt.tv_sec = rap->lifetime; + lt.tv_usec = 0; + timeradd(&rap->received, <, &expire); + if (rap->lifetime == 0 || timercmp(&now, &expire, >)) { + if (!rap->expired) { + syslog(LOG_WARNING, + "%s: %s: router expired", + ifp->name, rap->sfrom); + rap->expired = expired = 1; + ipv6nd_cancelproberouter(rap); + } + } else { + valid = 1; + timersub(&expire, &now, <); + if (!timerisset(&next) || + timercmp(&next, <, >)) + next = lt; } - } else { - valid = 1; - timersub(&expire, &now, <); - if (!timerisset(&next) || timercmp(&next, <, >)) - next = lt; } - /* Addresses are expired in ipv6ns_probeaddrs + /* 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) { @@ -1332,201 +1235,6 @@ ipv6nd_unreachable(void *arg) &tv, ipv6nd_proberouter, rap); } -#ifdef LISTEN_DAD -void -ipv6nd_cancelprobeaddr(struct ipv6_addr *ap) -{ - - eloop_timeout_delete(ap->iface->ctx->eloop, ipv6nd_probeaddr, ap); - if (ap->dadcallback) - eloop_timeout_delete(ap->iface->ctx->eloop, ap->dadcallback,ap); -} -#endif - -void -ipv6nd_probeaddr(void *arg) -{ - struct ipv6_addr *ap = arg; -#ifdef IPV6_SEND_DAD - struct nd_neighbor_solicit *ns; - struct nd_opt_hdr *nd; - struct sockaddr_in6 dst; - struct cmsghdr *cm; - struct in6_pktinfo pi; - int hoplimit = HOPLIMIT; -#else -#ifdef LISTEN_DAD - struct timeval tv, rtv; - struct timeval mtv; - int i; -#endif -#endif - - if (ap->dadcallback && - ((ap->flags & IPV6_AF_NEW) == 0 || - ap->nsprobes >= ap->iface->options->dadtransmits)) - { -#ifdef IPV6_SEND_DAD - ap->dadcallback(ap); -#else - if (!(ap->flags & IPV6_AF_AUTOCONF) || - ap->iface->options->options & DHCPCD_IPV6RA_OWN) - ipv6_addaddr(ap); -#endif - return; - } - - if (ipv6nd_open(ap->iface->ctx) == -1) { - syslog(LOG_ERR, "%s: ipv6nd_open: %m", __func__); - return; - } - - ap->flags &= ~IPV6_AF_DADCOMPLETED; - -#ifdef IPV6_SEND_DAD - if (!ap->ns) { - ap->nslen = sizeof(*ns) + ROUNDUP8(ap->iface->hwlen + 2); - ap->ns = calloc(1, ap->nslen); - if (ap->ns == NULL) { - syslog(LOG_ERR, "%s: %m", __func__); - return; - } - ns = (struct nd_neighbor_solicit *)(void *)ap->ns; - ns->nd_ns_type = ND_NEIGHBOR_SOLICIT; - //ns->nd_ns_cksum = 0; - //ns->nd_ns_code = 0; - //ns->nd_ns_reserved = 0; - ns->nd_ns_target = ap->addr; - nd = (struct nd_opt_hdr *)(ap->ns + sizeof(*ns)); - nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR; - nd->nd_opt_len = (ROUNDUP8(ap->iface->hwlen + 2)) >> 3; - memcpy(nd + 1, ap->iface->hwaddr, ap->iface->hwlen); - } - - memset(&dst, 0, sizeof(dst)); - dst.sin6_family = AF_INET6; -#ifdef SIN6_LEN - dst.sin6_len = sizeof(dst); -#endif - dst.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_MLL; - dst.sin6_addr.s6_addr16[1] = 0; - dst.sin6_addr.s6_addr32[1] = 0; - dst.sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_ONE; - dst.sin6_addr.s6_addr32[3] = ap->addr.s6_addr32[3]; - dst.sin6_addr.s6_addr[12] = 0xff; - - //memcpy(&dst.sin6_addr, &ap->addr, sizeof(dst.sin6_addr)); - dst.sin6_scope_id = ap->iface->index; - - ctx = ap->iface->ctx->ipv6; - ctx->sndhdr.msg_name = (caddr_t)&dst; - ctx->sndhdr.msg_iov[0].iov_base = ap->ns; - ctx->sndhdr.msg_iov[0].iov_len = ap->nslen; - - /* Set the outbound interface */ - cm = CMSG_FIRSTHDR(&ctx->sndhdr); - if (cm == NULL) /* unlikely */ - return; - cm->cmsg_level = IPPROTO_IPV6; - cm->cmsg_type = IPV6_PKTINFO; - cm->cmsg_len = CMSG_LEN(sizeof(pi)); - memset(&pi, 0, sizeof(pi)); - pi.ipi6_ifindex = ap->iface->index; - memcpy(CMSG_DATA(cm), &pi, sizeof(pi)); - - /* Hop limit */ - cm = CMSG_NXTHDR(&sndhdr, cm); - if (cm == NULL) /* unlikely */ - return; - cm->cmsg_level = IPPROTO_IPV6; - cm->cmsg_type = IPV6_HOPLIMIT; - cm->cmsg_len = CMSG_LEN(sizeof(hoplimit)); - memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit)); - -#ifdef DEBUG_NS - syslog(LOG_INFO, "%s: sending IPv6 NS for %s", - ap->iface->name, ap->saddr); - if (ap->dadcallback == NULL) - syslog(LOG_WARNING, "%s: no callback!", ap->iface->name); -#endif - if (sendmsg(unspec_sock, &sndhdr, 0) == -1) { - syslog(LOG_ERR, "%s: %s: sendmsg: %m", - ap->iface->name, __func__); - return; - } - - if (ap->dadcallback) { - ms_to_tv(&tv, RETRANS_TIMER); - ms_to_tv(&rtv, MIN_RANDOM_FACTOR); - timeradd(&tv, &rtv, &tv); - rtv.tv_sec = 0; - rtv.tv_usec = arc4random() % - (MAX_RANDOM_FACTOR_U - MIN_RANDOM_FACTOR_U); - timeradd(&tv, &rtv, &tv); - - eloop_timeout_add_tv(ap->iface->ctx->eloop, &tv, - ++(ap->nsprobes) < ap->iface->options->dadtransmits ? - ipv6nd_probeaddr : ap->dadcallback, - ap); - } -#else /* IPV6_SEND_DAD */ - - if (!(ap->flags & IPV6_AF_AUTOCONF) || - ap->iface->options->options & DHCPCD_IPV6RA_OWN) - ipv6_addaddr(ap); - -#ifdef LISTEN_DAD - /* Let the kernel handle DAD. - * We don't know the timings, so just wait for the max */ - if (ap->dadcallback) { - mtv.tv_sec = 0; - mtv.tv_usec = 0; - for (i = 0; i < ap->iface->options->dadtransmits; i++) { - ms_to_tv(&tv, RETRANS_TIMER); - ms_to_tv(&rtv, MAX_RANDOM_FACTOR); - timeradd(&tv, &rtv, &tv); - timeradd(&mtv, &tv, &mtv); - } - eloop_timeout_add_tv(ap->iface->ctx->eloop, - &mtv, ap->dadcallback, ap); - } -#endif -#endif /* IPV6_SEND_DAD */ -} - -ssize_t -ipv6nd_probeaddrs(struct ipv6_addrhead *addrs) -{ - struct ipv6_addr *ap, *apn; - ssize_t i; - - i = 0; - TAILQ_FOREACH_SAFE(ap, addrs, next, apn) { - if (ap->prefix_vltime == 0) { - TAILQ_REMOVE(addrs, ap, next); - if (ap->flags & IPV6_AF_ADDED) { - syslog(LOG_INFO, "%s: deleting address %s", - ap->iface->name, ap->saddr); - i++; - if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr) && - del_address6(ap) == -1 && - errno != EADDRNOTAVAIL && errno != ENXIO) - syslog(LOG_ERR, "del_address6 %m"); - } - if (ap->dadcallback) - eloop_q_timeout_delete(ap->iface->ctx->eloop, - 0, NULL, ap->dadcallback); - free(ap); - } else if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr)) { - ipv6nd_probeaddr(ap); - if (ap->flags & IPV6_AF_NEW) - i++; - } - } - - return i; -} - void ipv6nd_proberouter(void *arg) { @@ -1536,7 +1244,6 @@ ipv6nd_proberouter(void *arg) struct sockaddr_in6 dst; struct cmsghdr *cm; struct in6_pktinfo pi; - int hoplimit = HOPLIMIT; struct timeval tv, rtv; struct ipv6_ctx *ctx; @@ -1588,15 +1295,6 @@ ipv6nd_proberouter(void *arg) pi.ipi6_ifindex = rap->iface->index; memcpy(CMSG_DATA(cm), &pi, sizeof(pi)); - /* Hop limit */ - cm = CMSG_NXTHDR(&ctx->sndhdr, cm); - if (cm == NULL) /* unlikely */ - return; - cm->cmsg_level = IPPROTO_IPV6; - cm->cmsg_type = IPV6_HOPLIMIT; - cm->cmsg_len = CMSG_LEN(sizeof(hoplimit)); - memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit)); - #ifdef DEBUG_NS syslog(LOG_INFO, "%s: sending IPv6 NS for %s", rap->iface->name, rap->sfrom); @@ -1636,16 +1334,8 @@ ipv6nd_handlena(struct ipv6_ctx *ctx, st struct nd_neighbor_advert *nd_na; struct ra *rap; int is_router, is_solicited; -#ifdef DEBUG_NS - int found; -#endif struct timeval tv; -#ifdef LISTEN_DAD - struct dhcp6_state *d6state; - struct ipv6_addr *ap; -#endif - if ((size_t)len < sizeof(struct nd_neighbor_advert)) { syslog(LOG_ERR, "IPv6 NA packet too short from %s", ctx->sfrom); return; @@ -1669,55 +1359,16 @@ ipv6nd_handlena(struct ipv6_ctx *ctx, st return; } -#ifdef DEBUG_NS - found = 0; -#endif TAILQ_FOREACH(rap, ctx->ra_routers, next) { - if (rap->iface != ifp) - continue; - if (memcmp(rap->from.s6_addr, nd_na->nd_na_target.s6_addr, + if (rap->iface == ifp && + memcmp(rap->from.s6_addr, nd_na->nd_na_target.s6_addr, sizeof(rap->from.s6_addr)) == 0) break; -#ifdef LISTEN_DAD - TAILQ_FOREACH(ap, &rap->addrs, next) { - if (memcmp(ap->addr.s6_addr, - nd_na->nd_na_target.s6_addr, - sizeof(ap->addr.s6_addr)) == 0) - { - ap->flags |= IPV6_AF_DUPLICATED; - if (ap->dadcallback) - ap->dadcallback(ap); -#ifdef DEBUG_NS - found++; -#endif - } - } -#endif } if (rap == NULL) { -#ifdef LISTEN_DAD - d6state = D6_STATE(ifp); - if (d6state) { - TAILQ_FOREACH(ap, &d6state->addrs, next) { - if (memcmp(ap->addr.s6_addr, - nd_na->nd_na_target.s6_addr, - sizeof(ap->addr.s6_addr)) == 0) - { - ap->flags |= IPV6_AF_DUPLICATED; - if (ap->dadcallback) - ap->dadcallback(ap); -#ifdef DEBUG_NS - found++; -#endif - } - } - } -#endif - #ifdef DEBUG_NS - if (found == 0) - syslog(LOG_DEBUG, "%s: unexpected NA from %s", - ifp->name, ctx->sfrom); + syslog(LOG_DEBUG, "%s: unexpected NA from s", + ifp->name, ctx->sfrom); #endif return; } @@ -1774,6 +1425,8 @@ ipv6nd_handledata(void *arg) dhcpcd_ctx = arg; ctx = dhcpcd_ctx->ipv6; + ctx->rcvhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + + CMSG_SPACE(sizeof(int)); len = recvmsg(ctx->nd_fd, &ctx->rcvhdr, 0); if (len == -1) { syslog(LOG_ERR, "recvmsg: %m"); Index: src/external/bsd/dhcpcd/dist/net.c diff -u src/external/bsd/dhcpcd/dist/net.c:1.5 src/external/bsd/dhcpcd/dist/net.c:1.6 --- src/external/bsd/dhcpcd/dist/net.c:1.5 Tue Feb 25 13:20:23 2014 +++ src/external/bsd/dhcpcd/dist/net.c Fri Mar 14 11:31:11 2014 @@ -1,5 +1,5 @@ #include <sys/cdefs.h> - __RCSID("$NetBSD: net.c,v 1.5 2014/02/25 13:20:23 roy Exp $"); + __RCSID("$NetBSD: net.c,v 1.6 2014/03/14 11:31:11 roy Exp $"); /* * dhcpcd - DHCP client daemon @@ -253,13 +253,26 @@ discover_interfaces(struct dhcpcd_ctx *c #endif #ifdef AF_LINK const struct sockaddr_dl *sdl; +#ifdef SIOCGIFPRIORITY + struct ifreq ifr; + int s_inet; +#endif #ifdef IFLR_ACTIVE struct if_laddrreq iflr; - int socket_aflink; + int s_link; +#endif - socket_aflink = socket(AF_LINK, SOCK_DGRAM, 0); - if (socket_aflink == -1) +#ifdef SIOCGIFPRIORITY + if ((s_inet = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + return NULL; +#endif +#ifdef IFLR_ACTIVE + if ((s_link = socket(AF_LINK, SOCK_DGRAM, 0)) == -1) { +#ifdef SIOCGIFPRIORITY + close(s_inet); +#endif return NULL; + } memset(&iflr, 0, sizeof(iflr)); #endif #elif AF_PACKET @@ -268,7 +281,6 @@ discover_interfaces(struct dhcpcd_ctx *c if (getifaddrs(&ifaddrs) == -1) return NULL; - ifs = malloc(sizeof(*ifs)); if (ifs == NULL) return NULL; @@ -342,8 +354,10 @@ discover_interfaces(struct dhcpcd_ctx *c } ifp = calloc(1, sizeof(*ifp)); - if (ifp == NULL) - return NULL; + if (ifp == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + break; + } ifp->ctx = ctx; strlcpy(ifp->name, p, sizeof(ifp->name)); ifp->flags = ifa->ifa_flags; @@ -381,7 +395,7 @@ discover_interfaces(struct dhcpcd_ctx *c MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); iflr.flags = IFLR_PREFIX; iflr.prefixlen = sdl->sdl_alen * NBBY; - if (ioctl(socket_aflink, SIOCGLIFADDR, &iflr) == -1 || + if (ioctl(s_link, SIOCGLIFADDR, &iflr) == -1 || !(iflr.flags & IFLR_ACTIVE)) { free_interface(ifp); @@ -466,6 +480,13 @@ discover_interfaces(struct dhcpcd_ctx *c continue; } +#ifdef SIOCGIFPRIORITY + /* Respect the interface priority */ + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + if (ioctl(s_inet, SIOCGIFPRIORITY, &ifr) == 0) + ifp->metric = ifr.ifr_metric; +#else /* We reserve the 100 range for virtual interfaces, if and when * we can work them out. */ ifp->metric = 200 + ifp->index; @@ -473,6 +494,7 @@ discover_interfaces(struct dhcpcd_ctx *c ifp->wireless = 1; ifp->metric += 100; } +#endif TAILQ_INSERT_TAIL(ifs, ifp, next); } @@ -515,8 +537,11 @@ discover_interfaces(struct dhcpcd_ctx *c freeifaddrs(ifaddrs); +#ifdef SIOCGIFPRIORITY + close(s_inet); +#endif #ifdef IFLR_ACTIVE - close(socket_aflink); + close(s_link); #endif return ifs;