Module Name:    src
Committed By:   roy
Date:           Thu Jun  4 13:08:13 UTC 2020

Modified Files:
        src/external/bsd/dhcpcd/dist/src: dhcp.c dhcp6.c dhcpcd.8.in dhcpcd.c
            if-bsd.c privsep.c script.c

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.37 -r1.38 src/external/bsd/dhcpcd/dist/src/dhcp.c \
    src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.19 -r1.20 src/external/bsd/dhcpcd/dist/src/dhcp6.c
cvs rdiff -u -r1.6 -r1.7 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in \
    src/external/bsd/dhcpcd/dist/src/script.c
cvs rdiff -u -r1.20 -r1.21 src/external/bsd/dhcpcd/dist/src/if-bsd.c
cvs rdiff -u -r1.3 -r1.4 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.37 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.38
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.37	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c	Thu Jun  4 13:08:13 2020
@@ -1034,7 +1034,7 @@ make_message(struct bootp **bootpm, cons
 	auth = NULL;	/* appease GCC */
 	auth_len = 0;
 	if (ifo->auth.options & DHCPCD_AUTH_SEND) {
-		ssize_t alen = dhcp_auth_encode(&ifo->auth,
+		ssize_t alen = dhcp_auth_encode(ifp->ctx, &ifo->auth,
 		    state->auth.token,
 		    NULL, 0, 4, type, NULL, 0);
 		if (alen != -1 && alen > UINT8_MAX) {
@@ -1129,7 +1129,7 @@ make_message(struct bootp **bootpm, cons
 
 #ifdef AUTH
 	if (ifo->auth.options & DHCPCD_AUTH_SEND && auth_len != 0)
-		dhcp_auth_encode(&ifo->auth, state->auth.token,
+		dhcp_auth_encode(ifp->ctx, &ifo->auth, state->auth.token,
 		    (uint8_t *)bootp, len, 4, type, auth, auth_len);
 #endif
 
@@ -2747,6 +2747,18 @@ dhcp_drop(struct interface *ifp, const c
 #endif
 		}
 	}
+#ifdef AUTH
+	else if (state->auth.reconf != NULL) {
+		/*
+		 * Drop the lease as the token may only be present
+		 * in the initial reply message and not subsequent
+		 * renewals.
+		 * If dhcpcd is restarted, the token is lost.
+		 * XXX persist this in another file?
+		 */
+		dhcp_unlink(ifp->ctx, state->leasefile);
+	}
+#endif
 
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 #ifdef AUTH
@@ -4176,3 +4188,24 @@ dhcp_handleifa(int cmd, struct ipv4_addr
 
 	return ia;
 }
+
+#ifndef SMALL
+int
+dhcp_dump(struct interface *ifp)
+{
+	struct dhcp_state *state;
+
+	ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state));
+	if (state == NULL) {
+		logerr(__func__);
+		return -1;
+	}
+	state->new_len = read_lease(ifp, &state->new);
+	if (state->new == NULL) {
+		logerr("read_lease");
+		return -1;
+	}
+	state->reason = "DUMP";
+	return script_runreason(ifp, state->reason);
+}
+#endif
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.37 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.38
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.37	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Thu Jun  4 13:08:13 2020
@@ -29,6 +29,7 @@
 const char dhcpcd_copyright[] = "Copyright (c) 2006-2020 Roy Marples";
 
 #include <sys/file.h>
+#include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -86,6 +87,7 @@ const int dhcpcd_signals[] = {
 	SIGHUP,
 	SIGUSR1,
 	SIGUSR2,
+	SIGCHLD,
 };
 const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals);
 
@@ -1340,6 +1342,9 @@ stop_all_interfaces(struct dhcpcd_ctx *c
 	struct interface *ifp;
 
 	ctx->options |= DHCPCD_EXITING;
+	if (ctx->ifaces == NULL)
+		return;
+
 	/* Drop the last interface first */
 	TAILQ_FOREACH_REVERSE(ifp, ctx->ifaces, if_head, next) {
 		if (!ifp->active)
@@ -1395,7 +1400,7 @@ dhcpcd_signal_cb(int sig, void *arg)
 	unsigned long long opts;
 	int exit_code;
 
-	if (ctx->options & DHCPCD_FORKED) {
+	if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) {
 		pid_t pid = pidfile_read(ctx->pidfile);
 		if (pid == -1) {
 			if (errno != ENOENT)
@@ -1441,6 +1446,10 @@ dhcpcd_signal_cb(int sig, void *arg)
 		if (logopen(ctx->logfile) == -1)
 			logerr(__func__);
 		return;
+	case SIGCHLD:
+		while (waitpid(-1, NULL, WNOHANG) > 0)
+			;
+		return;
 	default:
 		logerrx("received signal %d but don't know what to do with it",
 		    sig);
@@ -1663,20 +1672,13 @@ dumperr:
 	return 0;
 }
 
-static const char *dumpskip[] = {
-	"PATH=",
-	"pid=",
-	"chroot=",
-};
-
 static int
 dhcpcd_readdump(struct dhcpcd_ctx *ctx)
 {
 	int error = 0;
-	size_t nifaces, buflen = 0, dlen, i;
+	size_t nifaces, buflen = 0, dlen;
 	ssize_t len;
-	char *buf = NULL, *dp, *de;
-	const char *skip;
+	char *buf = NULL;
 
 again1:
 	len = read(ctx->control_fd, &nifaces, sizeof(nifaces));
@@ -1723,26 +1725,7 @@ again3:
 			error = -1;
 			goto out;
 		}
-		dp = buf;
-		de = dp + dlen;
-		if (*(de - 1) != '\0') {
-			errno = EINVAL;
-			error = -1;
-			goto out;
-		}
-		while (dp < de) {
-			for (i = 0; i < __arraycount(dumpskip); i++) {
-				skip = dumpskip[i];
-				if (strncmp(dp, skip, strlen(skip)) == 0)
-					break;
-			}
-			if (i == __arraycount(dumpskip)) {
-				if (strncmp(dp, "new_", 4) == 0)
-					dp += 4;
-				printf("%s\n", dp);
-			}
-			dp += strlen(dp) + 1;
-		}
+		script_dump(buf, dlen);
 		fflush(stdout);
 		if (nifaces != 1)
 			putchar('\n');
@@ -2061,13 +2044,9 @@ printpidfile:
 		signal(dhcpcd_signals_ignore[si], SIG_IGN);
 
 	/* Save signal mask, block and redirect signals to our handler */
-	if (eloop_signal_set_cb(ctx.eloop,
+	eloop_signal_set_cb(ctx.eloop,
 	    dhcpcd_signals, dhcpcd_signals_len,
-	    dhcpcd_signal_cb, &ctx) == -1)
-	{
-		logerr("%s: eloop_signal_set_cb", __func__);
-		goto exit_failure;
-	}
+	    dhcpcd_signal_cb, &ctx);
 	if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) {
 		logerr("%s: eloop_signal_mask", __func__);
 		goto exit_failure;
@@ -2107,6 +2086,45 @@ printpidfile:
 	}
 #endif
 
+#ifndef SMALL
+	if (ctx.options & DHCPCD_DUMPLEASE &&
+	    ioctl(fileno(stdin), FIONREAD, &i, sizeof(i)) == 0 &&
+	    i > 0)
+	{
+		ifp = calloc(1, sizeof(*ifp));
+		if (ifp == NULL) {
+			logerr(__func__);
+			goto exit_failure;
+		}
+		ifp->ctx = &ctx;
+		ifp->options = ifo;
+		switch (family) {
+		case AF_INET:
+#ifdef INET
+			if (dhcp_dump(ifp) == -1)
+				goto exit_failure;
+			break;
+#else
+			logerrx("No DHCP support");
+			goto exit_failure;
+#endif
+		case AF_INET6:
+#ifdef DHCP6
+			if (dhcp6_dump(ifp) == -1)
+				goto exit_failure;
+			break;
+#else
+			logerrx("No DHCP6 support");
+			goto exit_failure;
+#endif
+		default:
+			logerrx("Family not specified. Please use -4 or -6.");
+			goto exit_failure;
+		}
+		goto exit_success;
+	}
+#endif
+
 	/* Test against siga instead of sig to avoid gcc
 	 * warning about a bogus potential signed overflow.
 	 * The end result will be the same. */
@@ -2194,7 +2212,6 @@ printpidfile:
 			logerr("fork");
 			goto exit_failure;
 		case 0:
-			eloop_requeue(ctx.eloop);
 			break;
 		default:
 			ctx.options |= DHCPCD_FORKED; /* A lie */
@@ -2203,7 +2220,6 @@ printpidfile:
 		}
 		break;
 	default:
-		waitpid(pid, &i, 0);
 		ctx.options |= DHCPCD_FORKED; /* A lie */
 		ctx.fork_fd = sigpipe[0];
 		close(sigpipe[1]);

Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.19 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.20
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.19	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c	Thu Jun  4 13:08:13 2020
@@ -881,7 +881,7 @@ dhcp6_makemessage(struct interface *ifp)
 #ifdef AUTH
 	auth_len = 0;
 	if (ifo->auth.options & DHCPCD_AUTH_SEND) {
-		ssize_t alen = dhcp_auth_encode(&ifo->auth,
+		ssize_t alen = dhcp_auth_encode(ifp->ctx, &ifo->auth,
 		    state->auth.token, NULL, 0, 6, type, NULL, 0);
 		if (alen != -1 && alen > UINT16_MAX) {
 			errno = ERANGE;
@@ -1196,9 +1196,9 @@ dhcp6_update_auth(struct interface *ifp,
 		return -1;
 
 	state = D6_STATE(ifp);
-	return dhcp_auth_encode(&ifp->options->auth, state->auth.token,
-	    (uint8_t *)state->send, state->send_len,
-	    6, state->send->type, opt, opt_len);
+	return dhcp_auth_encode(ifp->ctx, &ifp->options->auth,
+	    state->auth.token, (uint8_t *)state->send, state->send_len, 6,
+	    state->send->type, opt, opt_len);
 }
 #endif
 
@@ -1483,7 +1483,7 @@ void dhcp6_renew(struct interface *ifp)
 	dhcp6_startrenew(ifp);
 }
 
-int
+bool
 dhcp6_dadcompleted(const struct interface *ifp)
 {
 	const struct dhcp6_state *state;
@@ -1493,9 +1493,9 @@ dhcp6_dadcompleted(const struct interfac
 	TAILQ_FOREACH(ap, &state->addrs, next) {
 		if (ap->flags & IPV6_AF_ADDED &&
 		    !(ap->flags & IPV6_AF_DADCOMPLETED))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -3319,7 +3319,7 @@ dhcp6_recvif(struct interface *ifp, cons
 			loginfox("%s: accepted reconfigure key", ifp->name);
 	} else if (ifo->auth.options & DHCPCD_AUTH_SEND) {
 		if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
-			logerr("%s: no authentication from %s",
+			logerrx("%s: no authentication from %s",
 			    ifp->name, sfrom);
 			return;
 		}
@@ -3595,15 +3595,12 @@ dhcp6_recvmsg(struct dhcpcd_ctx *ctx, st
 	}
 
 	if (r->type == DHCP6_RECONFIGURE) {
-		logdebugx("%s: RECONFIGURE6 recv from %s,"
-		    " sending to all interfaces",
-		    ifp->name, sfrom);
-		TAILQ_FOREACH(ifp, ctx->ifaces, next) {
-			state = D6_CSTATE(ifp);
-			if (state != NULL && state->send != NULL)
-				dhcp6_recvif(ifp, sfrom, r, len);
+		if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
+			logerrx("%s: RECONFIGURE6 recv from %s, not LL",
+			    ifp->name, sfrom);
+			return;
 		}
-		return;
+		goto recvif;
 	}
 
 	state = D6_CSTATE(ifp);
@@ -3679,6 +3676,7 @@ dhcp6_recvmsg(struct dhcpcd_ctx *ctx, st
 	len = (size_t)tlen;
 #endif
 
+recvif:
 	dhcp6_recvif(ifp, sfrom, r, len);
 }
 
@@ -4041,6 +4039,19 @@ dhcp6_freedrop(struct interface *ifp, in
 			}
 			dhcp_unlink(ifp->ctx, state->leasefile);
 		}
+#ifdef AUTH
+		else if (state->auth.reconf != NULL) {
+			/*
+			 * Drop the lease as the token may only be present
+			 * in the initial reply message and not subsequent
+			 * renewals.
+			 * If dhcpcd is restarted, the token is lost.
+			 * XXX persist this in another file?
+			 */
+			dhcp_unlink(ifp->ctx, state->leasefile);
+		}
+#endif
+
 		dhcp6_freedrop_addrs(ifp, drop, NULL);
 		free(state->old);
 		state->old = state->new;
@@ -4293,3 +4304,24 @@ delegated:
 	return 1;
 }
 #endif
+
+#ifndef SMALL
+int
+dhcp6_dump(struct interface *ifp)
+{
+	struct dhcp6_state *state;
+
+	ifp->if_data[IF_DATA_DHCP6] = state = calloc(1, sizeof(*state));
+	if (state == NULL) {
+		logerr(__func__);
+		return -1;
+	}
+	TAILQ_INIT(&state->addrs);
+	if (dhcp6_readlease(ifp, 0) == -1) {
+		logerr("dhcp6_readlease");
+		return -1;
+	}
+	state->reason = "DUMP6";
+	return script_runreason(ifp, state->reason);
+}
+#endif

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.6 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.7
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.6	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in	Thu Jun  4 13:08:13 2020
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 21, 2020
+.Dd May 31, 2020
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -72,7 +72,7 @@
 .Op interface
 .Nm
 .Fl U , Fl Fl dumplease
-.Ar interface
+.Op Ar interface
 .Nm
 .Fl Fl version
 .Nm
@@ -685,15 +685,20 @@ option is not sent in TEST mode so that 
 To test INFORM the interface needs to be configured with the desired address
 before starting
 .Nm .
-.It Fl U , Fl Fl dumplease Ar interface
+.It Fl U , Fl Fl dumplease Op Ar interface
 Dumps the current lease for the
 .Ar interface
 to stdout.
+If no
+.Ar interface
+is given then all interfaces are dumped.
 Use the
 .Fl 4
 or
 .Fl 6
 flags to specify an address family.
+If a lease is piped in via standard input then that is dumped.
+In this case, specifying an address family is mandatory.
 .It Fl V , Fl Fl variables
 Display a list of option codes, the associated variable and encoding for use in
 .Xr dhcpcd-run-hooks 8 .
Index: src/external/bsd/dhcpcd/dist/src/script.c
diff -u src/external/bsd/dhcpcd/dist/src/script.c:1.6 src/external/bsd/dhcpcd/dist/src/script.c:1.7
--- src/external/bsd/dhcpcd/dist/src/script.c:1.6	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/script.c	Thu Jun  4 13:08:13 2020
@@ -1,4 +1,4 @@
-/* stSPDX-License-Identifier: BSD-2-Clause */
+/* SPDX-License-Identifier: BSD-2-Clause */
 /*
  * dhcpcd - DHCP client daemon
  * Copyright (c) 2006-2020 Roy Marples <r...@marples.name>
@@ -193,6 +193,8 @@ script_buftoenv(struct dhcpcd_ctx *ctx, 
 		}
 	}
 	assert(*(bufp - 1) == '\0');
+	if (nenv == 0)
+		return NULL;
 
 	if (ctx->script_envlen < nenv) {
 		env = reallocarray(ctx->script_env, nenv + 1, sizeof(*env));
@@ -235,6 +237,7 @@ make_env(struct dhcpcd_ctx *ctx, const s
 #ifdef DHCP6
 	const struct dhcp6_state *d6_state;
 #endif
+	bool is_stdin = ifp->name[0] == '\0';
 
 #ifdef HAVE_OPEN_MEMSTREAM
 	if (ctx->script_fp == NULL) {
@@ -264,23 +267,19 @@ make_env(struct dhcpcd_ctx *ctx, const s
 	}
 #endif
 
-	/* Needed for scripts */
-	path = getenv("PATH");
-	if (efprintf(fp, "PATH=%s", path == NULL ? DEFAULT_PATH:path) == -1)
-		goto eexit;
-	if (efprintf(fp, "reason=%s", reason) == -1)
-		goto eexit;
-	if (efprintf(fp, "pid=%d", getpid()) == -1)
-		goto eexit;
-
-#ifdef PRIVSEP
-	if (ctx->options & DHCPCD_PRIVSEP && ctx->ps_user != NULL) {
-		if (efprintf(fp, "chroot=%s", ctx->ps_user->pw_dir) == -1)
+	if (!(ifp->ctx->options & DHCPCD_DUMPLEASE)) {
+		/* Needed for scripts */
+		path = getenv("PATH");
+		if (efprintf(fp, "PATH=%s",
+		    path == NULL ? DEFAULT_PATH : path) == -1)
+			goto eexit;
+		if (efprintf(fp, "pid=%d", getpid()) == -1)
+			goto eexit;
+	}
+	if (!is_stdin) {
+		if (efprintf(fp, "reason=%s", reason) == -1)
 			goto eexit;
 	}
-	if (strcmp(reason, "CHROOT") == 0)
-		goto make;
-#endif
 
 	ifo = ifp->options;
 #ifdef INET
@@ -340,9 +339,10 @@ make_env(struct dhcpcd_ctx *ctx, const s
 		protocol = PROTO_DHCP;
 #endif
 
-
-	if (efprintf(fp, "interface=%s", ifp->name) == -1)
-		goto eexit;
+	if (!is_stdin) {
+		if (efprintf(fp, "interface=%s", ifp->name) == -1)
+			goto eexit;
+	}
 	if (ifp->ctx->options & DHCPCD_DUMPLEASE)
 		goto dumplease;
 	if (efprintf(fp, "ifcarrier=%s",
@@ -508,9 +508,6 @@ dumplease:
 				goto eexit;
 	}
 
-#ifdef PRIVSEP
-make:
-#endif
 	/* Convert buffer to argv */
 	fflush(fp);
 
@@ -536,6 +533,9 @@ make:
 	fp = NULL;
 #endif
 
+	if (is_stdin)
+		return buf_pos;
+
 	if (script_buftoenv(ctx, ctx->script_buf, (size_t)buf_pos) == NULL)
 		goto eexit;
 
@@ -686,23 +686,48 @@ script_run(struct dhcpcd_ctx *ctx, char 
 }
 
 int
+script_dump(const char *env, size_t len)
+{
+	const char *ep = env + len;
+
+	if (len == 0)
+		return 0;
+
+	if (*(ep - 1) != '\0') {
+		errno = EINVAL;
+		return -1;
+	}
+
+	for (; env < ep; env += strlen(env) + 1) {
+		if (strncmp(env, "new_", 4) == 0)
+			env += 4;
+		printf("%s\n", env);
+	}
+	return 0;
+}
+
+int
 script_runreason(const struct interface *ifp, const char *reason)
 {
 	struct dhcpcd_ctx *ctx = ifp->ctx;
 	char *argv[2];
 	int status = 0;
 	struct fd_list *fd;
+	long buflen;
 
 	if (ctx->script == NULL &&
 	    TAILQ_FIRST(&ifp->ctx->control_fds) == NULL)
 		return 0;
 
 	/* Make our env */
-	if (make_env(ifp->ctx, ifp, reason) == -1) {
+	if ((buflen = make_env(ifp->ctx, ifp, reason)) == -1) {
 		logerr(__func__);
 		return -1;
 	}
 
+	if (strncmp(reason, "DUMP", 4) == 0)
+		return script_dump(ctx->script_buf, (size_t)buflen);
+
 	if (ctx->script == NULL)
 		goto send_listeners;
 

Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.20 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.21
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.20	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c	Thu Jun  4 13:08:13 2020
@@ -100,10 +100,12 @@
 #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
 #endif
 
-/* Ignore these interface names which look like ethernet but are virtual. */
+/* Ignore these interface names which look like ethernet but are virtual or
+ * just won't work without explicit configuration. */
 static const char * const ifnames_ignore[] = {
 	"bridge",
 	"fwe",		/* Firewire */
+	"fwip",		/* Firewire */
 	"tap",
 	"xvif",		/* XEN DOM0 -> guest interface */
 	NULL

Index: src/external/bsd/dhcpcd/dist/src/privsep.c
diff -u src/external/bsd/dhcpcd/dist/src/privsep.c:1.3 src/external/bsd/dhcpcd/dist/src/privsep.c:1.4
--- src/external/bsd/dhcpcd/dist/src/privsep.c:1.3	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/privsep.c	Thu Jun  4 13:08:13 2020
@@ -131,6 +131,41 @@ ps_dropprivs(struct dhcpcd_ctx *ctx)
 	return 0;
 }
 
+static int
+ps_setbuf0(int fd, int ctl, int minlen)
+{
+	int len;
+	socklen_t slen;
+
+	slen = sizeof(len);
+	if (getsockopt(fd, SOL_SOCKET, ctl, &len, &slen) == -1)
+		return -1;
+
+#ifdef __linux__
+	len /= 2;
+#endif
+	if (len >= minlen)
+		return 0;
+
+	return setsockopt(fd, SOL_SOCKET, ctl, &minlen, sizeof(minlen));
+}
+
+static int
+ps_setbuf(int fd)
+{
+	/* Ensure we can receive a fully sized privsep message.
+	 * Double the send buffer. */
+	int minlen = (int)sizeof(struct ps_msg);
+
+	if (ps_setbuf0(fd, SO_RCVBUF, minlen) == -1 ||
+	    ps_setbuf0(fd, SO_SNDBUF, minlen * 2) == -1)
+	{
+		logerr(__func__);
+		return -1;
+	}
+	return 0;
+}
+
 pid_t
 ps_dostart(struct dhcpcd_ctx *ctx,
     pid_t *priv_pid, int *priv_fd,
@@ -160,11 +195,13 @@ ps_dostart(struct dhcpcd_ctx *ctx,
 	case 0:
 		*priv_fd = fd[1];
 		close(fd[0]);
+		ps_setbuf(*priv_fd);
 		break;
 	default:
 		*priv_pid = pid;
 		*priv_fd = fd[0];
 		close(fd[1]);
+		ps_setbuf(*priv_fd);
 		if (recv_unpriv_msg == NULL)
 			;
 #ifdef HAVE_CAPSICUM
@@ -206,12 +243,8 @@ ps_dostart(struct dhcpcd_ctx *ctx,
 		ctx->ps_inet_fd = -1;
 	}
 
-	if (eloop_signal_set_cb(ctx->eloop,
-	    dhcpcd_signals, dhcpcd_signals_len, signal_cb, ctx) == -1)
-	{
-		logerr("%s: eloop_signal_set_cb", __func__);
-		goto errexit;
-	}
+	eloop_signal_set_cb(ctx->eloop,
+	    dhcpcd_signals, dhcpcd_signals_len, signal_cb, ctx);
 
 	/* ctx->sigset aready has the initial sigmask set in main() */
 	if (eloop_signal_mask(ctx->eloop, NULL) == -1) {
@@ -251,67 +284,35 @@ errexit:
 		(void)ps_sendcmd(ctx, *priv_fd, PS_STOP, 0, NULL, 0);
 	shutdown(*priv_fd, SHUT_RDWR);
 	*priv_fd = -1;
+	eloop_exit(ctx->eloop, EXIT_FAILURE);
 	return -1;
 }
 
 int
 ps_dostop(struct dhcpcd_ctx *ctx, pid_t *pid, int *fd)
 {
-	int status;
+	int err = 0;
 
 #ifdef PRIVSEP_DEBUG
 	logdebugx("%s: pid %d fd %d", __func__, *pid, *fd);
 #endif
-	if (*pid == 0)
-		return 0;
-	eloop_event_delete(ctx->eloop, *fd);
-	if (ps_sendcmd(ctx, *fd, PS_STOP, 0, NULL, 0) == -1 &&
-	    errno != ECONNRESET)
-		logerr(__func__);
-	if (shutdown(*fd, SHUT_RDWR) == -1 && errno != ENOTCONN)
-		logerr(__func__);
-	close(*fd);
-	*fd = -1;
-	/* We won't have permission for all processes .... */
-#if 0
-	if (kill(*pid, SIGTERM) == -1)
-		logerr(__func__);
-#endif
-	status = 0;
-
-#ifdef HAVE_CAPSICUM
-	unsigned int cap_mode = 0;
-	int cap_err = cap_getmode(&cap_mode);
 
-	if (cap_err == -1) {
-		if (errno != ENOSYS)
-			logerr("%s: cap_getmode", __func__);
-	} else if (cap_mode != 0)
-		goto nowait;
-#endif
-
-	/* Wait for the process to finish */
-	while (waitpid(*pid, &status, 0) == -1) {
-		if (errno != EINTR) {
-			logerr("%s: waitpid", __func__);
-			status = 0;
-			break;
+	if (*fd != -1) {
+		eloop_event_delete(ctx->eloop, *fd);
+		if (ps_sendcmd(ctx, *fd, PS_STOP, 0, NULL, 0) == -1 ||
+		    shutdown(*fd, SHUT_RDWR) == -1)
+		{
+			logerr(__func__);
+			err = -1;
 		}
-#ifdef PRIVSEP_DEBUG
-		else
-			logerr("%s: waitpid ", __func__);
-#endif
+		close(*fd);
+		*fd = -1;
 	}
-#ifdef HAVE_CAPSICUM
-nowait:
-#endif
-	*pid = 0;
-
-#ifdef PRIVSEP_DEBUG
-	logdebugx("%s: status %d", __func__, status);
-#endif
 
-	return status;
+	/* Don't wait for the process as it may not respond to the shutdown
+	 * request. We'll reap the process on receipt of SIGCHLD. */
+	*pid = 0;
+	return err;
 }
 
 int
@@ -507,7 +508,8 @@ ps_sendpsmmsg(struct dhcpcd_ctx *ctx, in
 #ifdef PRIVSEP_DEBUG
 	logdebugx("%s: %zd", __func__, len);
 #endif
-	if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED)
+	if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED &&
+	    !(ctx->options & DHCPCD_PRIVSEPROOT))
 		eloop_exit(ctx->eloop, len == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 	return len;
 }
@@ -650,8 +652,12 @@ ps_recvmsg(struct dhcpcd_ctx *ctx, int r
 #ifdef PRIVSEP_DEBUG
 	logdebugx("%s: recv fd %d, %zd bytes", __func__, rfd, len);
 #endif
-	if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED) {
-		eloop_exit(ctx->eloop, len == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+
+	if (len == -1 || len == 0) {
+		if (ctx->options & DHCPCD_FORKED &&
+		    !(ctx->options & DHCPCD_PRIVSEPROOT))
+			eloop_exit(ctx->eloop,
+			    len == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 		return len;
 	}
 
@@ -660,7 +666,8 @@ ps_recvmsg(struct dhcpcd_ctx *ctx, int r
 #ifdef PRIVSEP_DEBUG
 	logdebugx("%s: send fd %d, %zu bytes", __func__, wfd, len);
 #endif
-	if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED)
+	if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED &&
+	    !(ctx->options & DHCPCD_PRIVSEPROOT))
 		eloop_exit(ctx->eloop, len == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 	return len;
 }
@@ -682,8 +689,6 @@ ps_recvpsmsg(struct dhcpcd_ctx *ctx, int
 	logdebugx("%s: %zd", __func__, len);
 #endif
 
-	if (len == -1 && (errno == ECONNRESET || errno == EBADF))
-		len = 0;
 	if (len == -1 || len == 0)
 		stop = true;
 	else {

Reply via email to