changeset 5288:30958d539e6c draft

Restore dumping a lease from stdin
author Roy Marples <roy@marples.name>
date Sun, 31 May 2020 21:06:32 +0100
parents d31a4f016043
children b32000689362
files src/Makefile src/dhcp.c src/dhcp.h src/dhcp6.c src/dhcp6.h src/dhcpcd.8.in src/dhcpcd.c src/script.c src/script.h
diffstat 9 files changed, 148 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile	Sun May 31 12:14:28 2020 +0100
+++ b/src/Makefile	Sun May 31 21:06:32 2020 +0100
@@ -43,7 +43,6 @@
 		${SED_SYS} ${SED_SCRIPT} ${SED_DATADIR} \
 		${SED_SERVICEEXISTS} ${SED_SERVICECMD} ${SED_SERVICESTATUS} \
 		${SED_STATUSARG} \
-		${SED_CHROOT} ${SED_PRIVSEP_USER} \
 		$< > $@
 
 all: ${TOP}/config.h ${PROG} ${SCRIPTS} ${MAN5} ${MAN8}
--- a/src/dhcp.c	Sun May 31 12:14:28 2020 +0100
+++ b/src/dhcp.c	Sun May 31 21:06:32 2020 +0100
@@ -4176,3 +4176,24 @@
 
 	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
--- a/src/dhcp.h	Sun May 31 12:14:28 2020 +0100
+++ b/src/dhcp.h	Sun May 31 21:06:32 2020 +0100
@@ -276,6 +276,7 @@
 void dhcp_reboot_newopts(struct interface *, unsigned long long);
 void dhcp_close(struct interface *);
 void dhcp_free(struct interface *);
+int dhcp_dump(struct interface *);
 #endif /* INET */
 
 #endif /* DHCP_H */
--- a/src/dhcp6.c	Sun May 31 12:14:28 2020 +0100
+++ b/src/dhcp6.c	Sun May 31 21:06:32 2020 +0100
@@ -1483,7 +1483,7 @@
 	dhcp6_startrenew(ifp);
 }
 
-int
+bool
 dhcp6_dadcompleted(const struct interface *ifp)
 {
 	const struct dhcp6_state *state;
@@ -1493,9 +1493,9 @@
 	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
@@ -4293,3 +4293,24 @@
 	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
--- a/src/dhcp6.h	Sun May 31 12:14:28 2020 +0100
+++ b/src/dhcp6.h	Sun May 31 21:06:32 2020 +0100
@@ -243,9 +243,10 @@
     const struct dhcp6_message *, size_t);
 void dhcp6_free(struct interface *);
 void dhcp6_handleifa(int, struct ipv6_addr *, pid_t);
-int dhcp6_dadcompleted(const struct interface *);
+bool dhcp6_dadcompleted(const struct interface *);
 void dhcp6_abort(struct interface *);
 void dhcp6_drop(struct interface *, const char *);
+int dhcp6_dump(struct interface *);
 #endif /* DHCP6 */
 
 #endif /* DHCP6_H */
--- a/src/dhcpcd.8.in	Sun May 31 12:14:28 2020 +0100
+++ b/src/dhcpcd.8.in	Sun May 31 21:06:32 2020 +0100
@@ -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 @@
 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 .
--- a/src/dhcpcd.c	Sun May 31 12:14:28 2020 +0100
+++ b/src/dhcpcd.c	Sun May 31 21:06:32 2020 +0100
@@ -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>
@@ -1663,20 +1664,13 @@
 	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 +1717,7 @@
 			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');
@@ -2107,6 +2082,45 @@
 	}
 #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. */
--- a/src/script.c	Sun May 31 12:14:28 2020 +0100
+++ b/src/script.c	Sun May 31 21:06:32 2020 +0100
@@ -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 <roy@marples.name>
@@ -193,6 +193,8 @@
 		}
 	}
 	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 @@
 #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 @@
 	}
 #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 (strcmp(reason, "CHROOT") == 0)
-		goto make;
-#endif
+	if (!is_stdin) {
+		if (efprintf(fp, "reason=%s", reason) == -1)
+			goto eexit;
+	}
 
 	ifo = ifp->options;
 #ifdef INET
@@ -340,9 +339,10 @@
 		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 @@
 				goto eexit;
 	}
 
-#ifdef PRIVSEP
-make:
-#endif
 	/* Convert buffer to argv */
 	fflush(fp);
 
@@ -536,6 +533,9 @@
 	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 @@
 }
 
 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;
 
--- a/src/script.h	Sun May 31 12:14:28 2020 +0100
+++ b/src/script.h	Sun May 31 21:06:32 2020 +0100
@@ -36,5 +36,6 @@
 char ** script_buftoenv(struct dhcpcd_ctx *, char *, size_t);
 pid_t script_exec(char *const *, char *const *);
 int send_interface(struct fd_list *, const struct interface *, int);
+int script_dump(const char *, size_t);
 int script_runreason(const struct interface *, const char *);
 #endif