From: Roy Marples Date: Sun, 31 May 2020 20:06:32 +0000 (+0100) Subject: Restore dumping a lease from stdin X-Git-Tag: v9.1.1~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80ecaa1cb50bb8508ec44a4b8a9b29c19218892e;p=thirdparty%2Fdhcpcd.git Restore dumping a lease from stdin --- diff --git a/src/Makefile b/src/Makefile index a63b8246..28fb6e35 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,7 +43,6 @@ CLEANFILES+= *.tar.xz ${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} diff --git a/src/dhcp.c b/src/dhcp.c index 1bad22ca..4970cc7a 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -4176,3 +4176,24 @@ dhcp_handleifa(int cmd, struct ipv4_addr *ia, pid_t pid) 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 diff --git a/src/dhcp.h b/src/dhcp.h index d15e10be..497e2888 100644 --- a/src/dhcp.h +++ b/src/dhcp.h @@ -276,6 +276,7 @@ void dhcp_bind(struct interface *); 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 */ diff --git a/src/dhcp6.c b/src/dhcp6.c index 84c4b41e..e6e12e30 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -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 interface *ifp) 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 @@ 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 diff --git a/src/dhcp6.h b/src/dhcp6.h index 329b515a..31e80452 100644 --- a/src/dhcp6.h +++ b/src/dhcp6.h @@ -243,9 +243,10 @@ ssize_t dhcp6_env(FILE *, const char *, const struct interface *, 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 */ diff --git a/src/dhcpcd.8.in b/src/dhcpcd.8.in index 59f01166..8704e245 100644 --- a/src/dhcpcd.8.in +++ b/src/dhcpcd.8.in @@ -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 the server does not lease an address. 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 . diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 63615ef1..a5fd7412 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -29,6 +29,7 @@ const char dhcpcd_copyright[] = "Copyright (c) 2006-2020 Roy Marples"; #include +#include #include #include #include @@ -1663,20 +1664,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 +1717,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'); @@ -2107,6 +2082,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. */ diff --git a/src/script.c b/src/script.c index d14a8f79..282b5ac2 100644 --- a/src/script.c +++ b/src/script.c @@ -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 @@ -193,6 +193,8 @@ script_buftoenv(struct dhcpcd_ctx *ctx, char *buf, size_t len) } } 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 struct interface *ifp, #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 struct interface *ifp, } #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 struct interface *ifp, 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; @@ -685,6 +685,27 @@ script_run(struct dhcpcd_ctx *ctx, char **argv) return WEXITSTATUS(status); } +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) { @@ -692,17 +713,21 @@ script_runreason(const struct interface *ifp, const char *reason) 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; diff --git a/src/script.h b/src/script.h index e9ad1117..9bcd3350 100644 --- a/src/script.h +++ b/src/script.h @@ -36,5 +36,6 @@ void if_printoptions(void); 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