]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
dhcpcd: dumping lease uses control socket to get the lease
authorRoy Marples <roy@marples.name>
Fri, 27 Mar 2020 16:14:48 +0000 (16:14 +0000)
committerRoy Marples <roy@marples.name>
Fri, 27 Mar 2020 16:14:48 +0000 (16:14 +0000)
Thanks to privsep it's hard to know where the lease is now stored.
As such, the only true location is from the running dhcpcd process.
The ability to read a raw lease from stdin has been dropped.

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 e719337957772faf4fac1ca20d090492febc7018..758ad779a192acb3e4553d76153eeec0ef7fa716 100644 (file)
@@ -3690,31 +3690,6 @@ dhcp_openbpf(struct interface *ifp)
        return 0;
 }
 
-int
-dhcp_dump(struct interface *ifp)
-{
-       struct dhcp_state *state;
-
-       ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state));
-       if (state == NULL)
-               goto eexit;
-       state->bpf_fd = -1;
-       dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
-           AF_INET, ifp);
-       state->new_len = read_lease(ifp, &state->new);
-       if (state->new == NULL) {
-               logerr("%s: %s",
-                   *ifp->name ? ifp->name : state->leasefile, __func__);
-               return -1;
-       }
-       state->reason = "DUMP";
-       return script_runreason(ifp, state->reason);
-
-eexit:
-       logerr(__func__);
-       return -1;
-}
-
 void
 dhcp_free(struct interface *ifp)
 {
index 8f513454c57c3c5ee39fde197f51ed7490c4955e..5b01a52cb8fbbdb2555ec09c09ca895d423af7f6 100644 (file)
@@ -276,7 +276,6 @@ 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 4e44edcb4c1f6f1c270046d1dfed4b683ca65583..129d5f0eac1f4f1f7ce4af63ac66dfe0fbe479a2 100644 (file)
@@ -4182,26 +4182,4 @@ delegated:
 
        return 1;
 }
-
-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);
-       dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
-           AF_INET6, ifp);
-       if (dhcp6_readlease(ifp, 0) == -1) {
-               logerr("%s: %s", __func__,
-                   *ifp->name ? ifp->name : state->leasefile);
-               return -1;
-       }
-       state->reason = "DUMP6";
-       return script_runreason(ifp, state->reason);
-}
 #endif
index ac2c47a0e0f226a4f901ae7c9836a52fc16e281f..c7d118891f4a92739d7327be7e4edb19f2283c18 100644 (file)
@@ -241,7 +241,6 @@ void dhcp6_handleifa(int, struct ipv6_addr *, pid_t);
 int 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 d41bf40a2bf8a34bbb5318175b6b0a39afcbe548..4bd32f78c4caed7541de46223748d8b2878e5d40 100644 (file)
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd January 22, 2020
+.Dd March 27, 2020
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -684,10 +684,9 @@ To test INFORM the interface needs to be configured with the desired address
 before starting
 .Nm .
 .It Fl U , Fl Fl dumplease Ar interface
-Dumps the last lease for the
+Dumps the current lease for the
 .Ar interface
 to stdout.
-If omitted, standard input is used to read a DHCP wire formatted message.
 Use the
 .Fl 4
 or
index bd2556eaa04469f9ad4d7472b5d2af37bdf007c9..d70ff37b2f60296a9ed233d435a7bc5babaa7dc9 100644 (file)
@@ -1458,7 +1458,7 @@ dhcpcd_getinterfaces(void *arg)
        TAILQ_FOREACH(ifp, fd->ctx->ifaces, next) {
                if (!ifp->active)
                        continue;
-               if (send_interface(fd, ifp) == -1)
+               if (send_interface(fd, ifp, AF_UNSPEC) == -1)
                        logerr(__func__);
        }
 }
@@ -1469,7 +1469,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
 {
        struct interface *ifp;
        unsigned long long opts;
-       int opt, oi, do_reboot, do_renew;
+       int opt, oi, do_reboot, do_renew, af = AF_UNSPEC;
        size_t len, l;
        char *tmp, *p;
 
@@ -1492,12 +1492,6 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
                return 0;
        }
 
-       /* Only privileged users can control dhcpcd via the socket. */
-       if (fd->flags & FD_UNPRIV) {
-               errno = EPERM;
-               return -1;
-       }
-
        /* Log the command */
        len = 1;
        for (opt = 0; opt < argc; opt++)
@@ -1542,9 +1536,50 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
                case 'N':
                        do_renew = 1;
                        break;
+               case 'U':
+                       opts |= DHCPCD_DUMPLEASE;
+                       break;
+               case '4':
+                       af = AF_INET;
+                       break;
+               case '6':
+                       af = AF_INET6;
+                       break;
                }
        }
 
+       if (opts & DHCPCD_DUMPLEASE) {
+               ctx->options |= DHCPCD_DUMPLEASE;
+               size_t nifaces = 0;
+
+               for (oi = optind; oi < argc; oi++) {
+                       if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL)
+                               continue;
+                       if (!ifp->active)
+                               continue;
+                       opt = send_interface(NULL, ifp, af);
+                       if (opt != -1)
+                               nifaces += (size_t)opt;
+               }
+               if (write(fd->fd, &nifaces, sizeof(nifaces)) != sizeof(nifaces))
+                       return -1;
+               for (oi = optind; oi < argc; oi++) {
+                       if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL)
+                               continue;
+                       if (!ifp->active)
+                               continue;
+                       send_interface(fd, ifp, af);
+               }
+               ctx->options &= ~DHCPCD_DUMPLEASE;
+               return 0;
+       }
+
+       /* Only privileged users can control dhcpcd via the socket. */
+       if (fd->flags & FD_UNPRIV) {
+               errno = EPERM;
+               return -1;
+       }
+
        if (opts & (DHCPCD_EXITING | DHCPCD_RELEASE)) {
                if (optind == argc) {
                        stop_all_interfaces(ctx, opts);
@@ -1583,6 +1618,86 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
        return 0;
 }
 
+static int
+dhcpcd_readdump(struct dhcpcd_ctx *ctx)
+{
+       int error = 0;
+       size_t nifaces, buflen = 0, dlen;
+       ssize_t len;
+       char *buf = NULL, *dp, *de;
+       bool print;
+
+again1:
+       len = read(ctx->control_fd, &nifaces, sizeof(nifaces));
+       if (len == -1) {
+               if (errno == EAGAIN)
+                       goto again1;
+               return -1;
+       }
+       if (len != sizeof(nifaces)) {
+               errno = EINVAL;
+               return -1;
+       }
+       for (; nifaces > 0; nifaces--) {
+again2:
+               len = read(ctx->control_fd, &dlen, sizeof(dlen));
+               if (len == -1) {
+                       if (errno == EAGAIN)
+                               goto again2;
+                       error = -1;
+                       goto out;
+               }
+               if (len != sizeof(dlen)) {
+                       errno = EINVAL;
+                       goto out;
+               }
+               if (dlen > buflen) {
+                       char *nbuf = realloc(buf, dlen);
+                       if (nbuf == NULL) {
+                               error = -1;
+                               goto out;
+                       }
+                       buf = nbuf;
+                       buflen = dlen;
+               }
+again3:
+               if (read(ctx->control_fd, buf, dlen) != (ssize_t)dlen) {
+                       if (errno == EAGAIN)
+                               goto again3;
+                       error = -1;
+                       goto out;
+               }
+               dp = buf;
+               de = dp + dlen;
+               while (dp < de) {
+                       if (dp + 6 >= de) /* _new and = something */
+                               break;
+                       if (dp[0] == 'n' && dp[3] == '_') {
+                               if (dp[1] == 'e' && dp[2] == 'w') {
+                                       print = true;
+                                       dp += 4;
+                               } else if (dp[1] == 'd' &&
+                                   isdigit((unsigned char)dp[2]))
+                                       print = true;
+                       } else
+                               print = false;
+                       while (dp < de && *dp != '\0') {
+                               if (print)
+                                       putchar(*dp);
+                               dp++;
+                       }
+                       if (print)
+                               putchar('\n');
+                       dp++;
+               }
+               fflush(stdout);
+       }
+
+out:
+       free(buf);
+       return error;
+}
+
 static void
 dhcpcd_fork_cb(void *arg)
 {
@@ -1891,74 +2006,7 @@ printpidfile:
                logerr("%s: eloop_signal_mask", __func__);
                goto exit_failure;
        }
-#endif
 
-       if (ctx.options & DHCPCD_DUMPLEASE) {
-               /* Open sockets so we can dump something about
-                * valid interfaces. */
-               if (if_opensockets(&ctx) == -1) {
-                       logerr("%s: if_opensockets", __func__);
-                       goto exit_failure;
-               }
-               if (optind != argc) {
-                       /* We need to try and find the interface so we can load
-                        * the hardware address to compare automated IAID */
-                       ctx.ifaces = if_discover(&ctx, &ifaddrs,
-                           argc - optind, argv + optind);
-               } else {
-                       if ((ctx.ifaces = malloc(sizeof(*ctx.ifaces))) != NULL)
-                               TAILQ_INIT(ctx.ifaces);
-               }
-               if (ctx.ifaces == NULL) {
-                       logerr("%s: if_discover", __func__);
-                       goto exit_failure;
-               }
-               ifp = if_find(ctx.ifaces, argv[optind]);
-               if (ifp == NULL) {
-                       ifp = calloc(1, sizeof(*ifp));
-                       if (ifp == NULL) {
-                               logerr(__func__);
-                               goto exit_failure;
-                       }
-                       if (optind != argc)
-                               strlcpy(ctx.pidfile, argv[optind],
-                                   sizeof(ctx.pidfile));
-                       ifp->ctx = &ctx;
-                       TAILQ_INSERT_HEAD(ctx.ifaces, ifp, next);
-                       if (family == 0) {
-                               if (ctx.pidfile[0] != '\0' &&
-                                   ctx.pidfile[strlen(ctx.pidfile) - 1] == '6')
-                                       family = AF_INET6;
-                               else
-                                       family = AF_INET;
-                       }
-               }
-               configure_interface(ifp, ctx.argc, ctx.argv, 0);
-               i = 0;
-               if (family == 0 || family == AF_INET) {
-#ifdef INET
-                       if (dhcp_dump(ifp) == -1)
-                               i = -1;
-#else
-                       if (family == AF_INET)
-                               logerrx("No INET support");
-#endif
-               }
-               if (family == 0 || family == AF_INET6) {
-#ifdef DHCP6
-                       if (dhcp6_dump(ifp) == -1)
-                               i = -1;
-#else
-                       if (family == AF_INET6)
-                               logerrx("No DHCP6 support");
-#endif
-               }
-               if (i == -1)
-                       goto exit_failure;
-               goto exit_success;
-       }
-
-#ifdef USE_SIGNALS
        /* Test against siga instead of sig to avoid gcc
         * warning about a bogus potential signed overflow.
         * The end result will be the same. */
@@ -1972,18 +2020,30 @@ printpidfile:
                if (ctx.control_fd == -1)
                        ctx.control_fd = control_open(NULL);
                if (ctx.control_fd != -1) {
-                       loginfox("sending commands to master dhcpcd process");
+                       if (!(ctx.options & DHCPCD_DUMPLEASE))
+                               loginfox("sending commands to dhcpcd process");
                        len = control_send(&ctx, argc, argv);
-                       if (len > 0) {
+                       if (len > 0)
                                logdebugx("send OK");
-                               goto exit_success;
-                       } else {
+                       else {
                                logerr("%s: control_send", __func__);
                                goto exit_failure;
                        }
+                       if (ctx.options & DHCPCD_DUMPLEASE) {
+                               if (dhcpcd_readdump(&ctx) == -1) {
+                                       logerr("%s: dhcpcd_readdump", __func__);
+                                       goto exit_failure;
+                               }
+                       }
+                       goto exit_success;
                } else {
                        if (errno != ENOENT)
                                logerr("%s: control_open", __func__);
+                       if (ctx.options & DHCPCD_DUMPLEASE) {
+                               if (errno == ENOENT)
+                                       logerrx("dhcpcd is not running");
+                               goto exit_failure;
+                       }
                }
                ctx.options &= ~DHCPCD_FORKED;
 #ifdef USE_SIGNALS
@@ -2312,7 +2372,6 @@ exit1:
        eloop_free(ctx.ps_eloop);
 #endif
        eloop_free(ctx.eloop);
-
        if (ctx.options & DHCPCD_STARTED && !(ctx.options & DHCPCD_FORKED))
                loginfox(PACKAGE " exited");
        logclose();
index 68aadff749b58d6aadda1baf1f99f1509e954cf0..04620ce104e22fed4afed250af6999256c232a03 100644 (file)
@@ -535,7 +535,7 @@ make:
        if (script_buftoenv(ctx, ctx->script_buf, (size_t)buf_pos) == NULL)
                goto eexit;
 
-       return buf_pos - 1;
+       return buf_pos;
 
 eexit:
        logerr(__func__);
@@ -556,13 +556,12 @@ send_interface1(struct fd_list *fd, const struct interface *ifp,
        len = make_env(ifp->ctx, ifp, reason);
        if (len == -1)
                return -1;
-       return control_queue(fd, ctx->script_buf,  (size_t)len, 1);
+       return control_queue(fd, ctx->script_buf, (size_t)len, 1);
 }
 
 int
-send_interface(struct fd_list *fd, const struct interface *ifp)
+send_interface(struct fd_list *fd, const struct interface *ifp, int af)
 {
-       const char *reason;
        int retval = 0;
 #ifdef INET
        const struct dhcp_state *d;
@@ -571,50 +570,78 @@ send_interface(struct fd_list *fd, const struct interface *ifp)
        const struct dhcp6_state *d6;
 #endif
 
-       switch (ifp->carrier) {
-       case LINK_UP:
-               reason = "CARRIER";
-               break;
-       case LINK_DOWN:
-       case LINK_DOWN_IFFUP:
-               reason = "NOCARRIER";
-               break;
-       default:
-               reason = "UNKNOWN";
-               break;
-       }
-       if (send_interface1(fd, ifp, reason) == -1)
-               retval = -1;
-#ifdef INET
-       if (D_STATE_RUNNING(ifp)) {
-               d = D_CSTATE(ifp);
-               if (send_interface1(fd, ifp, d->reason) == -1)
-                       retval = -1;
+       if (af == AF_UNSPEC || af == AF_LINK) {
+               const char *reason;
+
+               switch (ifp->carrier) {
+               case LINK_UP:
+                       reason = "CARRIER";
+                       break;
+               case LINK_DOWN:
+               case LINK_DOWN_IFFUP:
+                       reason = "NOCARRIER";
+                       break;
+               default:
+                       reason = "UNKNOWN";
+                       break;
+               }
+               if (fd != NULL) {
+                       if (send_interface1(fd, ifp, reason) == -1)
+                               retval = -1;
+               } else
+                       retval++;
        }
+
+#ifdef INET
+       if (af == AF_UNSPEC || af == AF_INET) {
+               if (D_STATE_RUNNING(ifp)) {
+                       d = D_CSTATE(ifp);
+                       if (fd != NULL) {
+                               if (send_interface1(fd, ifp, d->reason) == -1)
+                                       retval = -1;
+                       } else
+                               retval++;
+               }
 #ifdef IPV4LL
-       if (IPV4LL_STATE_RUNNING(ifp)) {
-               if (send_interface1(fd, ifp, "IPV4LL") == -1)
-                       retval = -1;
-       }
+               if (IPV4LL_STATE_RUNNING(ifp)) {
+                       if (fd != NULL) {
+                               if (send_interface1(fd, ifp, "IPV4LL") == -1)
+                                       retval = -1;
+                       } else
+                               retval++;
+               }
 #endif
+       }
 #endif
 
 #ifdef INET6
-       if (IPV6_STATE_RUNNING(ifp)) {
-               if (send_interface1(fd, ifp, "STATIC6") == -1)
-                       retval = -1;
-       }
-       if (RS_STATE_RUNNING(ifp)) {
-               if (send_interface1(fd, ifp, "ROUTERADVERT") == -1)
-                       retval = -1;
-       }
+       if (af == AF_UNSPEC || af == AF_INET6) {
+               if (IPV6_STATE_RUNNING(ifp)) {
+                       if (fd != NULL) {
+                               if (send_interface1(fd, ifp, "STATIC6") == -1)
+                                       retval = -1;
+                       } else
+                               retval++;
+               }
+               if (RS_STATE_RUNNING(ifp)) {
+                       if (fd != NULL) {
+                               if (send_interface1(fd, ifp,
+                                   "ROUTERADVERT") == -1)
+                                       retval = -1;
+                       } else
+                               retval++;
+               }
 #ifdef DHCP6
-       if (D6_STATE_RUNNING(ifp)) {
-               d6 = D6_CSTATE(ifp);
-               if (send_interface1(fd, ifp, d6->reason) == -1)
-                       retval = -1;
-       }
+               if (D6_STATE_RUNNING(ifp)) {
+                       d6 = D6_CSTATE(ifp);
+                       if (fd != NULL) {
+                               if (send_interface1(fd, ifp, d6->reason) == -1)
+                                       retval = -1;
+                       } else
+                               retval++;
+               }
 #endif
+       }
 #endif
 
        return retval;
index e35ca86d679982d46de0cd09c6ade22a95cf446a..0f20f9888c766aabde3de712157d53b04a83a830 100644 (file)
@@ -35,7 +35,7 @@ __printflike(2, 3) int efprintf(FILE *, const char *, ...);
 void if_printoptions(void);
 char ** script_buftoenv(struct dhcpcd_ctx *, char *, size_t);
 pid_t script_exec(const struct dhcpcd_ctx *, char *const *, char *const *);
-int send_interface(struct fd_list *, const struct interface *);
+int send_interface(struct fd_list *, const struct interface *, int);
 int script_runreason(const struct interface *, const char *);
 int script_runchroot(struct dhcpcd_ctx *, char *);
 #endif