diff --git a/external/bsd/dhcpcd/dist/src/dhcp.c b/external/bsd/dhcpcd/dist/src/dhcp.c index 1bad22ca98a9..b309b01c4ce9 100644 --- a/external/bsd/dhcpcd/dist/src/dhcp.c +++ b/external/bsd/dhcpcd/dist/src/dhcp.c @@ -1034,7 +1034,7 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type) 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, const struct interface *ifp, uint8_t type) #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 char *reason) #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 *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/external/bsd/dhcpcd/dist/src/dhcp6.c b/external/bsd/dhcpcd/dist/src/dhcp6.c index 84c4b41ee657..0e7743e366b5 100644 --- a/external/bsd/dhcpcd/dist/src/dhcp6.c +++ b/external/bsd/dhcpcd/dist/src/dhcp6.c @@ -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, struct dhcp6_message *m, size_t len) 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 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 @@ -3319,7 +3319,7 @@ dhcp6_recvif(struct interface *ifp, const char *sfrom, 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, struct msghdr *msg, struct ipv6_addr *ia) } 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, struct msghdr *msg, struct ipv6_addr *ia) len = (size_t)tlen; #endif +recvif: dhcp6_recvif(ifp, sfrom, r, len); } @@ -4041,6 +4039,19 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason) } 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 diff --git a/external/bsd/dhcpcd/dist/src/dhcpcd.8.in b/external/bsd/dhcpcd/dist/src/dhcpcd.8.in index 59f01166bb14..8704e2454389 100644 --- a/external/bsd/dhcpcd/dist/src/dhcpcd.8.in +++ b/external/bsd/dhcpcd/dist/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/external/bsd/dhcpcd/dist/src/dhcpcd.c b/external/bsd/dhcpcd/dist/src/dhcpcd.c index 63615ef1cc44..1363b3c7f379 100644 --- a/external/bsd/dhcpcd/dist/src/dhcpcd.c +++ b/external/bsd/dhcpcd/dist/src/dhcpcd.c @@ -29,6 +29,7 @@ const char dhcpcd_copyright[] = "Copyright (c) 2006-2020 Roy Marples"; #include +#include #include #include #include @@ -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 *ctx, unsigned long long opts) 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]); diff --git a/external/bsd/dhcpcd/dist/src/if-bsd.c b/external/bsd/dhcpcd/dist/src/if-bsd.c index 7bc1d7321c34..78735c7b9fd8 100644 --- a/external/bsd/dhcpcd/dist/src/if-bsd.c +++ b/external/bsd/dhcpcd/dist/src/if-bsd.c @@ -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 diff --git a/external/bsd/dhcpcd/dist/src/privsep.c b/external/bsd/dhcpcd/dist/src/privsep.c index ce4f05651081..fbfb99d37fdc 100644 --- a/external/bsd/dhcpcd/dist/src/privsep.c +++ b/external/bsd/dhcpcd/dist/src/privsep.c @@ -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 + + /* 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; - -#ifdef PRIVSEP_DEBUG - logdebugx("%s: status %d", __func__, status); -#endif - - return status; + return err; } int @@ -507,7 +508,8 @@ ps_sendpsmmsg(struct dhcpcd_ctx *ctx, int fd, #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 rfd, uint16_t cmd, int wfd) #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 rfd, uint16_t cmd, int wfd) #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 fd, logdebugx("%s: %zd", __func__, len); #endif - if (len == -1 && (errno == ECONNRESET || errno == EBADF)) - len = 0; if (len == -1 || len == 0) stop = true; else { diff --git a/external/bsd/dhcpcd/dist/src/script.c b/external/bsd/dhcpcd/dist/src/script.c index d14a8f79da02..282b5ac2a830 100644 --- a/external/bsd/dhcpcd/dist/src/script.c +++ b/external/bsd/dhcpcd/dist/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;