Sync trunk
authorroy <roy@NetBSD.org>
Fri, 14 Mar 2014 11:31:11 +0000
branchtrunk
changeset 225537 2f1325bd6b82
parent 225536 52a1e76c99b3
child 225538 cacc93d1ca48
Sync
external/bsd/dhcpcd/dist/dhcp.c
external/bsd/dhcpcd/dist/dhcpcd.8.in
external/bsd/dhcpcd/dist/dhcpcd.c
external/bsd/dhcpcd/dist/if-bsd.c
external/bsd/dhcpcd/dist/if-options.c
external/bsd/dhcpcd/dist/ipv6nd.c
external/bsd/dhcpcd/dist/net.c
--- a/external/bsd/dhcpcd/dist/dhcp.c	Fri Mar 14 11:29:44 2014 +0000
+++ b/external/bsd/dhcpcd/dist/dhcp.c	Fri Mar 14 11:31:11 2014 +0000
@@ -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 @@
 			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 @@
 		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 @@
 			    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 @@
 
 	/* 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 @@
 
 	/* 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 @@
 }
 
 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 @@
 	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 @@
 	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
--- a/external/bsd/dhcpcd/dist/dhcpcd.8.in	Fri Mar 14 11:29:44 2014 +0000
+++ b/external/bsd/dhcpcd/dist/dhcpcd.8.in	Fri Mar 14 11:31:11 2014 +0000
@@ -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 @@
 .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 @@
 Stores the monotonic counter used in the
 .Ar replay
 field in Authentication Options.
-.It Pa @RUNDIR@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
--- a/external/bsd/dhcpcd/dist/dhcpcd.c	Fri Mar 14 11:29:44 2014 +0000
+++ b/external/bsd/dhcpcd/dist/dhcpcd.c	Fri Mar 14 11:31:11 2014 +0000
@@ -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 @@
 {
 	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 @@
 			 * 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 @@
 	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 @@
 	pid_t pid;
 } dhcpcd_siginfo;
 
+#define sigmsg "received signal %s from PID %d, %s"
 static void
 handle_signal1(void *arg)
 {
@@ -866,17 +871,17 @@
 	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 @@
 		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 @@
 }
 
 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 @@
 #endif
 #ifdef USE_SIGNALS
 	int sig;
+	const char *siga;
 #endif
 	struct timespec ts;
 
@@ -1125,6 +1125,7 @@
 #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 @@
 #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 @@
 
 	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 @@
 	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 @@
 			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 @@
 	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 @@
 	}
 #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 */
--- a/external/bsd/dhcpcd/dist/if-bsd.c	Fri Mar 14 11:29:44 2014 +0000
+++ b/external/bsd/dhcpcd/dist/if-bsd.c	Fri Mar 14 11:31:11 2014 +0000
@@ -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 @@
 	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 @@
 	}
 
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 #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 @@
 					    &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];
--- a/external/bsd/dhcpcd/dist/if-options.c	Fri Mar 14 11:29:44 2014 +0000
+++ b/external/bsd/dhcpcd/dist/if-options.c	Fri Mar 14 11:31:11 2014 +0000
@@ -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 @@
 	{"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 @@
 	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);
--- a/external/bsd/dhcpcd/dist/ipv6nd.c	Fri Mar 14 11:29:44 2014 +0000
+++ b/external/bsd/dhcpcd/dist/ipv6nd.c	Fri Mar 14 11:31:11 2014 +0000
@@ -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 @@
 	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 @@
 	}
 #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 @@
 		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 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 					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 @@
 	}
 
 	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 @@
 			    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 @@
 		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 @@
 
 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 @@
 					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 @@
 	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, &lt, &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, &lt, &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, &lt);
+				if (!timerisset(&next) ||
+				    timercmp(&next, &lt, >))
+					next = lt;
 			}
-		} else {
-			valid = 1;
-			timersub(&expire, &now, &lt);
-			if (!timerisset(&next) || timercmp(&next, &lt, >))
-				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 @@
 	    &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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 
 	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");
--- a/external/bsd/dhcpcd/dist/net.c	Fri Mar 14 11:29:44 2014 +0000
+++ b/external/bsd/dhcpcd/dist/net.c	Fri Mar 14 11:31:11 2014 +0000
@@ -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 @@
 #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 @@
 
 	if (getifaddrs(&ifaddrs) == -1)
 		return NULL;
-
 	ifs = malloc(sizeof(*ifs));
 	if (ifs == NULL)
 		return NULL;
@@ -342,8 +354,10 @@
 		}
 
 		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 @@
 			    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 @@
 			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 @@
 			ifp->wireless = 1;
 			ifp->metric += 100;
 		}
+#endif
 
 		TAILQ_INSERT_TAIL(ifs, ifp, next);
 	}
@@ -515,8 +537,11 @@
 
 	freeifaddrs(ifaddrs);
 
+#ifdef SIOCGIFPRIORITY
+	close(s_inet);
+#endif
 #ifdef IFLR_ACTIVE
-	close(socket_aflink);
+	close(s_link);
 #endif
 
 	return ifs;