]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Restore dumping a lease from stdin
authorRoy Marples <roy@marples.name>
Sun, 31 May 2020 20:06:32 +0000 (21:06 +0100)
committerRoy Marples <roy@marples.name>
Sun, 31 May 2020 20:06:32 +0000 (21:06 +0100)
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

index a63b824601b678a8667716d668dfa23859b71289..28fb6e35655502ca81d0d25df81c763a99ffee2a 100644 (file)
@@ -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}
index 1bad22ca98a996e28a9bb4f31d1b14baabeb865b..4970cc7adafdb3271fa91e4f313d5cd72f15cf08 100644 (file)
@@ -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
index d15e10be16bdb78dd179fae8c48ec81bd893845a..497e288813b5a9178e0cd2d022387b93da512c56 100644 (file)
@@ -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 */
index 84c4b41ee6572f1e74f3adaac52e94043139976f..e6e12e301aa6147fb3e7ba9617024cdc11414df3 100644 (file)
@@ -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
index 329b515aa0234737fc3cbf286778b3e2b1a15e1f..31e804524843e25968e0764073de69b9ceeed6a2 100644 (file)
@@ -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 */
index 59f01166bb1447f7dc2dfebde7a10f328689842f..8704e2454389b3150d36bfdaa68ca07bcbca0520 100644 (file)
@@ -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 .
index 63615ef1cc44ef68738a196b9eba66c21fe440ed..a5fd74123141e50eb156fcadad404b619291a0bf 100644 (file)
@@ -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 @@ 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. */
index d14a8f79da026ca85633d6369a762d613c5f53b1..282b5ac2a830a6b49a84f241389f26a382fcbf82 100644 (file)
@@ -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 @@ 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;
 
index e9ad111786f3883942a790ac86117be497eec7dd..9bcd3350d4b3870a9f0da9d55d378de312991c1f 100644 (file)
@@ -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