Module Name:    src
Committed By:   roy
Date:           Sun Sep  6 14:55:34 UTC 2020

Modified Files:
        src/external/bsd/dhcpcd/dist/src: dhcp.c dhcpcd.8.in dhcpcd.c
            if-options.c ipv6.c ipv6nd.c logerr.c privsep.c

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/external/bsd/dhcpcd/dist/src/dhcp.c
cvs rdiff -u -r1.7 -r1.8 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in \
    src/external/bsd/dhcpcd/dist/src/logerr.c
cvs rdiff -u -r1.41 -r1.42 src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.26 -r1.27 src/external/bsd/dhcpcd/dist/src/if-options.c
cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/src/ipv6.c
cvs rdiff -u -r1.22 -r1.23 src/external/bsd/dhcpcd/dist/src/ipv6nd.c
cvs rdiff -u -r1.6 -r1.7 src/external/bsd/dhcpcd/dist/src/privsep.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/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.38 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.39
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.38	Thu Jun  4 13:08:13 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c	Sun Sep  6 14:55:34 2020
@@ -777,7 +777,7 @@ make_message(struct bootp **bootpm, cons
 	    (type == DHCP_REQUEST &&
 	    state->addr->mask.s_addr == lease->mask.s_addr &&
 	    (state->new == NULL || IS_DHCP(state->new)) &&
-	    !(state->added & STATE_FAKE))))
+	    !(state->added & (STATE_FAKE | STATE_EXPIRED)))))
 		bootp->ciaddr = state->addr->addr.s_addr;
 
 	bootp->op = BOOTREQUEST;
@@ -836,7 +836,7 @@ make_message(struct bootp **bootpm, cons
 		if (type == DHCP_DECLINE ||
 		    (type == DHCP_REQUEST &&
 		    (state->addr == NULL ||
-		    state->added & STATE_FAKE ||
+		    state->added & (STATE_FAKE | STATE_EXPIRED) ||
 		    lease->addr.s_addr != state->addr->addr.s_addr)))
 		{
 			putip = true;
@@ -1745,7 +1745,7 @@ send_message(struct interface *ifp, uint
 		goto fail;
 	len = (size_t)r;
 
-	if (!(state->added & STATE_FAKE) &&
+	if (!(state->added & (STATE_FAKE | STATE_EXPIRED)) &&
 	    state->addr != NULL &&
 	    ipv4_iffindaddr(ifp, &state->lease.addr, NULL) != NULL)
 		from.s_addr = state->lease.addr.s_addr;
@@ -1869,14 +1869,16 @@ dhcp_discover(void *arg)
 	state->state = DHS_DISCOVER;
 	dhcp_new_xid(ifp);
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
-	if (ifo->fallback)
-		eloop_timeout_add_sec(ifp->ctx->eloop,
-		    ifo->reboot, dhcp_fallback, ifp);
+	if (!(state->added & STATE_EXPIRED)) {
+		if (ifo->fallback)
+			eloop_timeout_add_sec(ifp->ctx->eloop,
+			    ifo->reboot, dhcp_fallback, ifp);
 #ifdef IPV4LL
-	else if (ifo->options & DHCPCD_IPV4LL)
-		eloop_timeout_add_sec(ifp->ctx->eloop,
-		    ifo->reboot, ipv4ll_start, ifp);
+		else if (ifo->options & DHCPCD_IPV4LL)
+			eloop_timeout_add_sec(ifp->ctx->eloop,
+			    ifo->reboot, ipv4ll_start, ifp);
 #endif
+	}
 	if (ifo->options & DHCPCD_REQUEST)
 		loginfox("%s: soliciting a DHCP lease (requesting %s)",
 		    ifp->name, inet_ntoa(ifo->req_addr));
@@ -1897,30 +1899,21 @@ dhcp_request(void *arg)
 }
 
 static void
-dhcp_expire1(struct interface *ifp)
-{
-	struct dhcp_state *state = D_STATE(ifp);
-
-	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
-	dhcp_drop(ifp, "EXPIRE");
-	dhcp_unlink(ifp->ctx, state->leasefile);
-	state->interval = 0;
-	if (!(ifp->options->options & DHCPCD_LINK) || ifp->carrier > LINK_DOWN)
-		dhcp_discover(ifp);
-}
-
-static void
 dhcp_expire(void *arg)
 {
 	struct interface *ifp = arg;
+	struct dhcp_state *state = D_STATE(ifp);
 
 	if (ifp->options->options & DHCPCD_LASTLEASE_EXTEND) {
 		logwarnx("%s: DHCP lease expired, extending lease", ifp->name);
-		return;
+		state->added |= STATE_EXPIRED;
+	} else {
+		logerrx("%s: DHCP lease expired", ifp->name);
+		dhcp_drop(ifp, "EXPIRE");
+		dhcp_unlink(ifp->ctx, state->leasefile);
 	}
-
-	logerrx("%s: DHCP lease expired", ifp->name);
-	dhcp_expire1(ifp);
+	state->interval = 0;
+	dhcp_discover(ifp);
 }
 
 #if defined(ARP) || defined(IN_IFF_DUPLICATED)
@@ -2291,7 +2284,9 @@ dhcp_bind(struct interface *ifp)
 		return;
 	}
 	if (state->reason == NULL) {
-		if (state->old && !(state->added & STATE_FAKE)) {
+		if (state->old &&
+		    !(state->added & (STATE_FAKE | STATE_EXPIRED)))
+		{
 			if (state->old->yiaddr == state->new->yiaddr &&
 			    lease->server.s_addr &&
 			    state->state != DHS_REBIND)
@@ -2364,19 +2359,6 @@ dhcp_bind(struct interface *ifp)
 	eloop_event_add(ctx->eloop, state->udp_rfd, dhcp_handleifudp, ifp);
 }
 
-static void
-dhcp_lastlease(void *arg)
-{
-	struct interface *ifp = arg;
-	struct dhcp_state *state = D_STATE(ifp);
-
-	loginfox("%s: timed out contacting a DHCP server, using last lease",
-	    ifp->name);
-	dhcp_bind(ifp);
-	state->interval = 0;
-	dhcp_discover(ifp);
-}
-
 static size_t
 dhcp_message_new(struct bootp **bootp,
     const struct in_addr *addr, const struct in_addr *mask)
@@ -2476,6 +2458,26 @@ dhcp_arp_bind(struct interface *ifp)
 #endif
 
 static void
+dhcp_lastlease(void *arg)
+{
+	struct interface *ifp = arg;
+	struct dhcp_state *state = D_STATE(ifp);
+
+	loginfox("%s: timed out contacting a DHCP server, using last lease",
+	    ifp->name);
+#if defined(ARP) || defined(KERNEL_RFC5227)
+	dhcp_arp_bind(ifp);
+#else
+	dhcp_bind(ifp);
+#endif
+	/* Set expired here because dhcp_bind() -> ipv4_addaddr() will reset
+	 * state */
+	state->added |= STATE_EXPIRED;
+	state->interval = 0;
+	dhcp_discover(ifp);
+}
+
+static void
 dhcp_static(struct interface *ifp)
 {
 	struct if_options *ifo;

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.7 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.8
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.7	Thu Jun  4 13:08:13 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in	Sun Sep  6 14:55:34 2020
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 31, 2020
+.Dd September 2, 2020
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -385,8 +385,10 @@ If no interfaces are left running,
 .Nm
 will exit.
 .It Fl l , Fl Fl leasetime Ar seconds
-Request a specific lease time in
+Request a lease time of
 .Ar seconds .
+.Ar -1
+represents an infinite lease time.
 By default
 .Nm
 does not request any lease time and leaves it in the hands of the
Index: src/external/bsd/dhcpcd/dist/src/logerr.c
diff -u src/external/bsd/dhcpcd/dist/src/logerr.c:1.7 src/external/bsd/dhcpcd/dist/src/logerr.c:1.8
--- src/external/bsd/dhcpcd/dist/src/logerr.c:1.7	Thu Jul  2 17:15:00 2020
+++ src/external/bsd/dhcpcd/dist/src/logerr.c	Sun Sep  6 14:55:34 2020
@@ -52,7 +52,6 @@
 struct logctx {
 	char		 log_buf[BUFSIZ];
 	unsigned int	 log_opts;
-	FILE		*log_err;
 #ifndef SMALL
 	FILE		*log_file;
 #ifdef LOGERR_TAG
@@ -120,14 +119,13 @@ vlogprintf_r(struct logctx *ctx, FILE *s
 	int len = 0, e;
 	va_list a;
 #ifndef SMALL
-	FILE *err = ctx->log_err == NULL ? stderr : ctx->log_err;
 	bool log_pid;
 #ifdef LOGERR_TAG
 	bool log_tag;
 #endif
 
-	if ((stream == err && ctx->log_opts & LOGERR_ERR_DATE) ||
-	    (stream != err && ctx->log_opts & LOGERR_LOG_DATE))
+	if ((stream == stderr && ctx->log_opts & LOGERR_ERR_DATE) ||
+	    (stream != stderr && ctx->log_opts & LOGERR_LOG_DATE))
 	{
 		if ((e = logprintdate(stream)) == -1)
 			return -1;
@@ -135,8 +133,8 @@ vlogprintf_r(struct logctx *ctx, FILE *s
 	}
 
 #ifdef LOGERR_TAG
-	log_tag = ((stream == err && ctx->log_opts & LOGERR_ERR_TAG) ||
-	    (stream != err && ctx->log_opts & LOGERR_LOG_TAG));
+	log_tag = ((stream == stderr && ctx->log_opts & LOGERR_ERR_TAG) ||
+	    (stream != stderr && ctx->log_opts & LOGERR_LOG_TAG));
 	if (log_tag) {
 		if (ctx->log_tag == NULL)
 			ctx->log_tag = getprogname();
@@ -146,8 +144,8 @@ vlogprintf_r(struct logctx *ctx, FILE *s
 	}
 #endif
 
-	log_pid = ((stream == err && ctx->log_opts & LOGERR_ERR_PID) ||
-	    (stream != err && ctx->log_opts & LOGERR_LOG_PID));
+	log_pid = ((stream == stderr && ctx->log_opts & LOGERR_ERR_PID) ||
+	    (stream != stderr && ctx->log_opts & LOGERR_LOG_PID));
 	if (log_pid) {
 		if ((e = fprintf(stream, "[%d]", getpid())) == -1)
 			return -1;
@@ -204,12 +202,7 @@ vlogmessage(int pri, const char *fmt, va
 	    (pri <= LOG_ERR ||
 	    (!(ctx->log_opts & LOGERR_QUIET) && pri <= LOG_INFO) ||
 	    (ctx->log_opts & LOGERR_DEBUG && pri <= LOG_DEBUG)))
-	{
-		FILE *err;
-
-		err = ctx->log_err == NULL ? stderr : ctx->log_err;
-		len = vlogprintf_r(ctx, err, fmt, args);
-	}
+		len = vlogprintf_r(ctx, stderr, fmt, args);
 
 	if (!(ctx->log_opts & LOGERR_LOG))
 		return len;
@@ -370,30 +363,6 @@ logsettag(const char *tag)
 #endif
 
 int
-loggeterrfd(void)
-{
-	struct logctx *ctx = &_logctx;
-	FILE *err = ctx->log_err == NULL ? stderr : ctx->log_err;
-
-	return fileno(err);
-}
-
-int
-logseterrfd(int fd)
-{
-	struct logctx *ctx = &_logctx;
-
-	if (ctx->log_err != NULL)
-		fclose(ctx->log_err);
-	if (fd == -1) {
-		ctx->log_err = NULL;
-		return 0;
-	}
-	ctx->log_err = fdopen(fd, "a");
-	return ctx->log_err == NULL ? -1 : 0;
-}
-
-int
 logopen(const char *path)
 {
 	struct logctx *ctx = &_logctx;

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.41 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.42
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.41	Fri Jul  3 10:46:45 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Sun Sep  6 14:55:34 2020
@@ -336,7 +336,7 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
 #ifdef THERE_IS_NO_FORK
 	eloop_timeout_delete(ctx->eloop, handle_exit_timeout, ctx);
 	errno = ENOSYS;
-	return 0;
+	return;
 #else
 	int i;
 	unsigned int logopts = loggetopts();
@@ -361,8 +361,8 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
 
 	/* Don't use loginfo because this makes no sense in a log. */
 	if (!(logopts & LOGERR_QUIET))
-		(void)fprintf(stderr, "forked to background, child pid %d\n",
-		    getpid());
+		(void)fprintf(stderr,
+		    "forked to background, child pid %d\n", getpid());
 	i = EXIT_SUCCESS;
 	if (write(ctx->fork_fd, &i, sizeof(i)) == -1)
 		logerr("write");
@@ -371,11 +371,18 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
 	close(ctx->fork_fd);
 	ctx->fork_fd = -1;
 
-	if (isatty(loggeterrfd())) {
-		logopts &= ~LOGERR_ERR;
-		logsetopts(logopts);
-		logseterrfd(-1);
-	}
+	/*
+	 * Stop writing to stderr.
+	 * On the happy path, only the master process writes to stderr,
+	 * so this just stops wasting fprintf calls to nowhere.
+	 * All other calls - ie errors in privsep processes or script output,
+	 * will error when printing.
+	 * If we *really* want to fix that, then we need to suck
+	 * stderr/stdout in the master process and either disacrd it or pass
+	 * it to the launcher process and then to stderr.
+	 */
+	logopts &= ~LOGERR_ERR;
+	logsetopts(logopts);
 #endif
 }
 
@@ -1153,6 +1160,15 @@ dhcpcd_setlinkrcvbuf(struct dhcpcd_ctx *
 }
 #endif
 
+static void
+dhcpcd_runprestartinterface(void *arg)
+{
+	struct interface *ifp = arg;
+
+	run_preinit(ifp);
+	dhcpcd_prestartinterface(ifp);
+}
+
 void
 dhcpcd_linkoverflow(struct dhcpcd_ctx *ctx)
 {
@@ -1215,9 +1231,11 @@ dhcpcd_linkoverflow(struct dhcpcd_ctx *c
 			continue;
 		}
 		TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
-		if (ifp->active)
+		if (ifp->active) {
+			dhcpcd_initstate(ifp, 0);
 			eloop_timeout_add_sec(ctx->eloop, 0,
-			    dhcpcd_prestartinterface, ifp);
+			    dhcpcd_runprestartinterface, ifp);
+		}
 	}
 	free(ifaces);
 
@@ -1765,6 +1783,24 @@ dhcpcd_fork_cb(void *arg)
 	eloop_exit(ctx->eloop, exit_code);
 }
 
+static void
+dhcpcd_stderr_cb(void *arg)
+{
+	struct dhcpcd_ctx *ctx = arg;
+	char log[BUFSIZ];
+	ssize_t len;
+
+	len = read(ctx->stderr_fd, log, sizeof(log));
+	if (len == -1) {
+		if (errno != ECONNRESET)
+			logerr(__func__);
+		return;
+	}
+
+	log[len] = '\0';
+	fprintf(stderr, "%s", log);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -1778,7 +1814,7 @@ main(int argc, char **argv)
 	ssize_t len;
 #if defined(USE_SIGNALS) || !defined(THERE_IS_NO_FORK)
 	pid_t pid;
-	int sigpipe[2];
+	int fork_fd[2], stderr_fd[2];
 #endif
 #ifdef USE_SIGNALS
 	int sig = 0;
@@ -2100,11 +2136,20 @@ printpidfile:
 	}
 #endif
 
+#ifdef PRIVSEP
+	ps_init(&ctx);
+#endif
+
 #ifndef SMALL
 	if (ctx.options & DHCPCD_DUMPLEASE &&
 	    ioctl(fileno(stdin), FIONREAD, &i, sizeof(i)) == 0 &&
 	    i > 0)
 	{
+		ctx.options |= DHCPCD_FORKED; /* pretend child process */
+#ifdef PRIVSEP
+		if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1)
+			goto exit_failure;
+#endif
 		ifp = calloc(1, sizeof(*ifp));
 		if (ifp == NULL) {
 			logerr(__func__);
@@ -2153,6 +2198,14 @@ printpidfile:
 			ctx.control_fd = control_open(NULL, AF_UNSPEC,
 			    ctx.options & DHCPCD_DUMPLEASE);
 		if (ctx.control_fd != -1) {
+#ifdef PRIVSEP
+			ctx.options &= ~DHCPCD_FORKED;
+			if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1) {
+				ctx.options |= DHCPCD_FORKED;
+				goto exit_failure;
+			}
+			ctx.options |= DHCPCD_FORKED;
+#endif
 			if (!(ctx.options & DHCPCD_DUMPLEASE))
 				loginfox("sending commands to dhcpcd process");
 			len = control_send(&ctx, argc, argv);
@@ -2206,29 +2259,40 @@ printpidfile:
 	if (freopen(_PATH_DEVNULL, "r", stdin) == NULL)
 		logerr("%s: freopen stdin", __func__);
 
-
-#ifdef PRIVSEP
-	ps_init(&ctx);
-#endif
-
-#ifdef USE_SIGNALS
-	if (pipe(sigpipe) == -1) {
-		logerr("pipe");
-		goto exit_failure;
-	}
-#ifdef HAVE_CAPSICUM
-	if (ps_rights_limit_fdpair(sigpipe) == -1) {
-		logerr("ps_rights_limit_fdpair");
+#if defined(USE_SIGNALS) && !defined(THERE_IS_NO_FORK)
+	if (xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, fork_fd) == -1 ||
+	    xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, stderr_fd) == -1)
+	{
+		logerr("socketpair");
 		goto exit_failure;
 	}
-#endif
 	switch (pid = fork()) {
 	case -1:
 		logerr("fork");
 		goto exit_failure;
 	case 0:
-		ctx.fork_fd = sigpipe[1];
-		close(sigpipe[0]);
+		ctx.fork_fd = fork_fd[1];
+		close(fork_fd[0]);
+#ifdef PRIVSEP_RIGHTS
+		if (ps_rights_limit_fd(fork_fd[1]) == -1) {
+			logerr("ps_rights_limit_fdpair");
+			goto exit_failure;
+		}
+#endif
+		/*
+		 * Redirect stderr to the stderr socketpair.
+		 * Redirect stdout as well.
+		 * dhcpcd doesn't output via stdout, but something in
+		 * a called script might.
+		 *
+		 * Do NOT rights limit this fd as it will affect scripts.
+		 * For example, cmp reports insufficient caps on FreeBSD.
+		 */
+		if (dup2(stderr_fd[1], STDERR_FILENO) == -1 ||
+		    dup2(stderr_fd[1], STDOUT_FILENO) == -1)
+			logerr("dup2");
+		close(stderr_fd[0]);
+		close(stderr_fd[1]);
 		if (setsid() == -1) {
 			logerr("%s: setsid", __func__);
 			goto exit_failure;
@@ -2248,10 +2312,22 @@ printpidfile:
 		break;
 	default:
 		ctx.options |= DHCPCD_FORKED; /* A lie */
-		ctx.fork_fd = sigpipe[0];
-		close(sigpipe[1]);
+		ctx.fork_fd = fork_fd[0];
+		close(fork_fd[1]);
+		ctx.stderr_fd = stderr_fd[0];
+		close(stderr_fd[1]);
+#ifdef PRIVSEP_RIGHTS
+		if (ps_rights_limit_fd(fork_fd[0]) == -1 ||
+		    ps_rights_limit_fd(stderr_fd[0]) == 1)
+		{
+			logerr("ps_rights_limit_fdpair");
+			goto exit_failure;
+		}
+#endif
 		setproctitle("[launcher]");
 		eloop_event_add(ctx.eloop, ctx.fork_fd, dhcpcd_fork_cb, &ctx);
+		eloop_event_add(ctx.eloop, ctx.stderr_fd, dhcpcd_stderr_cb,
+		    &ctx);
 		goto run_loop;
 	}
 
@@ -2270,22 +2346,6 @@ printpidfile:
 		if_disable_rtadv();
 #endif
 
-	if (isatty(STDOUT_FILENO) &&
-	    freopen(_PATH_DEVNULL, "r", stdout) == NULL)
-		logerr("%s: freopen stdout", __func__);
-	if (isatty(STDERR_FILENO)) {
-		int fd = dup(STDERR_FILENO);
-
-		if (fd == -1)
-			logerr("%s: dup", __func__);
-		else if (logseterrfd(fd) == -1)
-			logerr("%s: logseterrfd", __func__);
-		else if (freopen(_PATH_DEVNULL, "r", stderr) == NULL) {
-			logseterrfd(-1);
-			logerr("%s: freopen stderr", __func__);
-		}
-	}
-
 #ifdef PRIVSEP
 	if (IN_PRIVSEP(&ctx) && ps_start(&ctx) == -1) {
 		logerr("ps_start");

Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.26 src/external/bsd/dhcpcd/dist/src/if-options.c:1.27
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.26	Thu Jul  2 13:59:19 2020
+++ src/external/bsd/dhcpcd/dist/src/if-options.c	Sun Sep  6 14:55:34 2020
@@ -59,6 +59,8 @@
 #define	SET_CONFIG_BLOCK(ifo)	((ifo)->options |= DHCPCD_FORKED)
 #define	CLEAR_CONFIG_BLOCK(ifo)	((ifo)->options &= ~DHCPCD_FORKED)
 
+static unsigned long long default_options;
+
 const struct option cf_options[] = {
 	{"background",      no_argument,       NULL, 'b'},
 	{"script",          required_argument, NULL, 'c'},
@@ -759,6 +761,10 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		break;
 	case 'l':
 		ARG_REQUIRED;
+		if (strcmp(arg, "-1") == 0) {
+			ifo->leasetime = DHCP_INFINITE_LIFETIME;
+			break;
+		}
 		ifo->leasetime = (uint32_t)strtou(arg, NULL,
 		    0, 0, UINT32_MAX, &e);
 		if (e) {
@@ -1021,6 +1027,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		}
 		ifo->options |= DHCPCD_CLIENTID;
 		ifo->clientid[0] = (uint8_t)s;
+		ifo->options &= ~DHCPCD_DUID;
 		break;
 	case 'J':
 		ifo->options |= DHCPCD_BROADCAST;
@@ -1204,13 +1211,23 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		ifo->options |= DHCPCD_ONESHOT;
 		break;
 	case '4':
+#ifdef INET
 		ifo->options &= ~DHCPCD_IPV6;
 		ifo->options |= DHCPCD_IPV4;
 		break;
+#else
+		logerrx("INET has been compiled out");
+		return -1;
+#endif
 	case '6':
+#ifdef INET6
 		ifo->options &= ~DHCPCD_IPV4;
 		ifo->options |= DHCPCD_IPV6;
 		break;
+#else
+		logerrx("INET6 has been compiled out");
+		return -1;
+#endif
 	case O_IPV4:
 		ifo->options |= DHCPCD_IPV4;
 		break;
@@ -2090,6 +2107,12 @@ invalid_token:
 		break;
 	case O_CONTROLGRP:
 		ARG_REQUIRED;
+#ifdef PRIVSEP
+		/* Control group is already set by this point.
+		 * We don't need to pledge getpw either with this. */
+		if (IN_PRIVSEP(ctx))
+			break;
+#endif
 #ifdef _REENTRANT
 		l = sysconf(_SC_GETGR_R_SIZE_MAX);
 		if (l == -1)
@@ -2326,18 +2349,30 @@ read_config(struct dhcpcd_ctx *ctx,
 	/* Seed our default options */
 	if ((ifo = default_config(ctx)) == NULL)
 		return NULL;
-	ifo->options |= DHCPCD_DAEMONISE | DHCPCD_GATEWAY;
-#ifdef PLUGIN_DEV
-	ifo->options |= DHCPCD_DEV;
-#endif
+	if (default_options == 0) {
+		default_options |= DHCPCD_DAEMONISE | DHCPCD_GATEWAY;
 #ifdef INET
-	ifo->options |= DHCPCD_IPV4 | DHCPCD_ARP | DHCPCD_DHCP | DHCPCD_IPV4LL;
+		skip = socket(PF_INET, SOCK_DGRAM, 0);
+		if (skip != -1) {
+			close(skip);
+			default_options |= DHCPCD_IPV4 | DHCPCD_ARP |
+			    DHCPCD_DHCP | DHCPCD_IPV4LL;
+		}
 #endif
 #ifdef INET6
-	ifo->options |= DHCPCD_IPV6 | DHCPCD_IPV6RS;
-	ifo->options |= DHCPCD_IPV6RA_AUTOCONF | DHCPCD_IPV6RA_REQRDNSS;
-	ifo->options |= DHCPCD_DHCP6;
+		skip = socket(PF_INET6, SOCK_DGRAM, 0);
+		if (skip != -1) {
+			close(skip);
+			default_options |= DHCPCD_IPV6 | DHCPCD_IPV6RS |
+			    DHCPCD_IPV6RA_AUTOCONF | DHCPCD_IPV6RA_REQRDNSS |
+			    DHCPCD_DHCP6;
+		}
 #endif
+#ifdef PLUGIN_DEV
+		default_options |= DHCPCD_DEV;
+#endif
+	}
+	ifo->options |= default_options;
 
 	CLEAR_CONFIG_BLOCK(ifo);
 

Index: src/external/bsd/dhcpcd/dist/src/ipv6.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6.c:1.13 src/external/bsd/dhcpcd/dist/src/ipv6.c:1.14
--- src/external/bsd/dhcpcd/dist/src/ipv6.c:1.13	Thu Jul  2 13:59:19 2020
+++ src/external/bsd/dhcpcd/dist/src/ipv6.c	Sun Sep  6 14:55:34 2020
@@ -679,6 +679,14 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons
 	/* Adjust plftime and vltime based on acquired time */
 	pltime = ia->prefix_pltime;
 	vltime = ia->prefix_vltime;
+
+	if (ifp->options->options & DHCPCD_LASTLEASE_EXTEND) {
+		/* We don't want the kernel to expire the address.
+		 * The saved times will be re-applied to the ia
+		 * before exiting this function. */
+		ia->prefix_vltime = ia->prefix_pltime = ND6_INFINITE_LIFETIME;
+	}
+
 	if (timespecisset(&ia->acquired) &&
 	    (ia->prefix_pltime != ND6_INFINITE_LIFETIME ||
 	    ia->prefix_vltime != ND6_INFINITE_LIFETIME))
@@ -1092,33 +1100,22 @@ ipv6_anyglobal(struct interface *sifp)
 	struct interface *ifp;
 	struct ipv6_state *state;
 	struct ipv6_addr *ia;
-#ifdef BSD
 	bool forwarding;
 
-#if defined(PRIVSEP) && defined(HAVE_PLEDGE)
+	/* BSD forwarding is either on or off.
+	 * Linux forwarding is technically the same as it's
+	 * configured by the "all" interface.
+	 * Per interface only affects IsRouter of NA messages. */
+#if defined(PRIVSEP) && (defined(HAVE_PLEDGE) || defined(__linux__))
 	if (IN_PRIVSEP(sifp->ctx))
-		forwarding = ps_root_ip6forwarding(sifp->ctx, NULL) == 1;
+		forwarding = ps_root_ip6forwarding(sifp->ctx, NULL) != 0;
 	else
 #endif
-		forwarding = ip6_forwarding(NULL) == 1;
-#endif
-
+		forwarding = ip6_forwarding(NULL) != 0;
 
 	TAILQ_FOREACH(ifp, sifp->ctx->ifaces, next) {
-#ifdef BSD
 		if (ifp != sifp && !forwarding)
 			continue;
-#else
-#if defined(PRIVSEP) && defined(__linux__)
-	if (IN_PRIVSEP(sifp->ctx)) {
-		if (ifp != sifp &&
-		    ps_root_ip6forwarding(sifp->ctx, ifp->name) != 1)
-			continue;
-	} else
-#endif
-		if (ifp != sifp && ip6_forwarding(ifp->name) != 1)
-			continue;
-#endif
 
 		state = IPV6_STATE(ifp);
 		if (state == NULL)

Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.22 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.23
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.22	Thu Jul  2 13:59:19 2020
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c	Sun Sep  6 14:55:34 2020
@@ -544,11 +544,11 @@ ipv6nd_advertise(struct ipv6_addr *ia)
 	na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
 #if defined(PRIVSEP) && (defined(__linux__) || defined(HAVE_PLEDGE))
 	if (IN_PRIVSEP(ctx)) {
-		if (ps_root_ip6forwarding(ctx, ifp->name) == 1)
+		if (ps_root_ip6forwarding(ctx, ifp->name) != 0)
 			na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
 	} else
 #endif
-	if (ip6_forwarding(ifp->name) == 1)
+	if (ip6_forwarding(ifp->name) != 0)
 		na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
 	na->nd_na_target = ia->addr;
 

Index: src/external/bsd/dhcpcd/dist/src/privsep.c
diff -u src/external/bsd/dhcpcd/dist/src/privsep.c:1.6 src/external/bsd/dhcpcd/dist/src/privsep.c:1.7
--- src/external/bsd/dhcpcd/dist/src/privsep.c:1.6	Thu Jul  2 13:59:19 2020
+++ src/external/bsd/dhcpcd/dist/src/privsep.c	Sun Sep  6 14:55:34 2020
@@ -34,6 +34,7 @@
  * Spawn an unpriv process to send/receive common network data.
  * Then drop all privs and start running.
  * Every process aside from the privileged actioneer is chrooted.
+ * All privsep processes ignore signals - only the master process accepts them.
  *
  * dhcpcd will maintain the config file in the chroot, no need to handle
  * this in a script or something.
@@ -74,6 +75,8 @@
 
 #ifdef HAVE_CAPSICUM
 #include <sys/capsicum.h>
+#include <capsicum_helpers.h>
+#define ps_rights_limit_stdio caph_limit_stdio
 #endif
 #ifdef HAVE_UTIL_H
 #include <util.h>
@@ -109,7 +112,7 @@ ps_init(struct dhcpcd_ctx *ctx)
 	return 0;
 }
 
-int
+static int
 ps_dropprivs(struct dhcpcd_ctx *ctx)
 {
 	struct passwd *pw = ctx->ps_user;
@@ -121,9 +124,10 @@ ps_dropprivs(struct dhcpcd_ctx *ctx)
 	if (chdir("/") == -1)
 		logerr("%s: chdir `/'", __func__);
 
-	if (setgroups(1, &pw->pw_gid) == -1 ||
+	if ((setgroups(1, &pw->pw_gid) == -1 ||
 	     setgid(pw->pw_gid) == -1 ||
-	     setuid(pw->pw_uid) == -1)
+	     setuid(pw->pw_uid) == -1) &&
+	     (errno != EPERM || ctx->options & DHCPCD_FORKED))
 	{
 		logerr("failed to drop privileges");
 		return -1;
@@ -162,7 +166,7 @@ ps_dropprivs(struct dhcpcd_ctx *ctx)
 	/* Prohibit writing to files.
 	 * Obviously this won't work if we are using a logfile
 	 * or redirecting stderr to a file. */
-	if (ctx->logfile == NULL && isatty(loggeterrfd())) {
+	if (ctx->logfile == NULL) {
 		if (setrlimit(RLIMIT_FSIZE, &rzero) == -1)
 			logerr("setrlimit RLIMIT_FSIZE");
 	}
@@ -283,12 +287,10 @@ ps_dostart(struct dhcpcd_ctx *ctx,
     void *recv_ctx, int (*callback)(void *), void (*signal_cb)(int, void *),
     unsigned int flags)
 {
-	int stype;
 	int fd[2];
 	pid_t pid;
 
-	stype = SOCK_CLOEXEC | SOCK_NONBLOCK;
-	if (socketpair(AF_UNIX, SOCK_DGRAM | stype, 0, fd) == -1) {
+	if (xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, fd) == -1) {
 		logerr("%s: socketpair", __func__);
 		return -1;
 	}
@@ -341,6 +343,14 @@ ps_dostart(struct dhcpcd_ctx *ctx,
 			close(ctx->ps_root_fd);
 			ctx->ps_root_fd = -1;
 		}
+
+#ifdef PRIVSEP_RIGHTS
+		/* We cannot limit the root process in any way. */
+		if (ps_rights_limit_stdio() == -1) {
+			logerr("ps_rights_limit_stdio");
+			goto errexit;
+		}
+#endif
 	}
 
 	if (priv_fd != &ctx->ps_inet_fd && ctx->ps_inet_fd != -1) {
@@ -471,9 +481,10 @@ ps_mastersandbox(struct dhcpcd_ctx *ctx)
 	}
 
 #ifdef PRIVSEP_RIGHTS
-	if ((ps_rights_limit_ioctl(ctx->pf_inet_fd) == -1 ||
-	     ps_rights_limit_fd(ctx->link_fd) == -1) &&
-	    errno != ENOSYS)
+	if ((ctx->pf_inet_fd != -1 &&
+	    ps_rights_limit_ioctl(ctx->pf_inet_fd) == -1) ||
+	    (ctx->link_fd != -1 && ps_rights_limit_fd(ctx->link_fd) == -1) ||
+	     ps_rights_limit_stdio() == -1)
 	{
 		logerr("%s: cap_rights_limit", __func__);
 		return -1;
@@ -645,12 +656,12 @@ ps_sendpsmmsg(struct dhcpcd_ctx *ctx, in
 		iovlen = 1;
 
 	len = writev(fd, iov, iovlen);
-#ifdef PRIVSEP_DEBUG
-	logdebugx("%s: %zd", __func__, len);
-#endif
-	if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED &&
-	    !(ctx->options & DHCPCD_PRIVSEPROOT))
-		eloop_exit(ctx->eloop, len == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+	if (len == -1) {
+		logerr(__func__);
+		if (ctx->options & DHCPCD_FORKED &&
+		    !(ctx->options & DHCPCD_PRIVSEPROOT))
+			eloop_exit(ctx->eloop, EXIT_FAILURE);
+	}
 	return len;
 }
 
@@ -789,10 +800,9 @@ ps_recvmsg(struct dhcpcd_ctx *ctx, int r
 	};
 
 	ssize_t len = recvmsg(rfd, &msg, 0);
-#ifdef PRIVSEP_DEBUG
-	logdebugx("%s: recv fd %d, %zd bytes", __func__, rfd, len);
-#endif
 
+	if (len == -1)
+		logerr("%s: recvmsg", __func__);
 	if (len == -1 || len == 0) {
 		if (ctx->options & DHCPCD_FORKED &&
 		    !(ctx->options & DHCPCD_PRIVSEPROOT))
@@ -803,12 +813,12 @@ ps_recvmsg(struct dhcpcd_ctx *ctx, int r
 
 	iov[0].iov_len = (size_t)len;
 	len = ps_sendcmdmsg(wfd, cmd, &msg);
-#ifdef PRIVSEP_DEBUG
-	logdebugx("%s: send fd %d, %zu bytes", __func__, wfd, len);
-#endif
-	if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED &&
-	    !(ctx->options & DHCPCD_PRIVSEPROOT))
-		eloop_exit(ctx->eloop, len == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+	if (len == -1) {
+		logerr("ps_sendcmdmsg");
+		if (ctx->options & DHCPCD_FORKED &&
+		    !(ctx->options & DHCPCD_PRIVSEPROOT))
+			eloop_exit(ctx->eloop, EXIT_FAILURE);
+	}
 	return len;
 }
 

Reply via email to