]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add the ability to dump DHCPv6 leases.
authorRoy Marples <roy@marples.name>
Sun, 22 Jun 2014 13:05:05 +0000 (13:05 +0000)
committerRoy Marples <roy@marples.name>
Sun, 22 Jun 2014 13:05:05 +0000 (13:05 +0000)
Control DHCPv4 vs DHCPv6 dumping via the family option.

dhcp.c
dhcp.h
dhcp6.c
dhcp6.h
dhcpcd-hooks/02-dump
dhcpcd.c

diff --git a/dhcp.c b/dhcp.c
index 2f046842bf55bb1788a313f35114b54269389dfc..4f4fbb98c78a0e1f0b6ae420340d36fd73f139fe 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -2733,40 +2733,23 @@ dhcp_open(struct interface *ifp)
 }
 
 int
-dhcp_dump(struct dhcpcd_ctx *ctx, const char *ifname)
+dhcp_dump(struct interface *ifp)
 {
-       struct interface *ifp;
        struct dhcp_state *state;
 
-       if (ctx->ifaces == NULL) {
-               ctx->ifaces = malloc(sizeof(*ctx->ifaces));
-               if (ctx->ifaces == NULL)
-                       return -1;
-               TAILQ_INIT(ctx->ifaces);
-       }
-       state = NULL;
-       ifp = calloc(1, sizeof(*ifp));
-       if (ifp == NULL)
-               goto eexit;
-       ifp->ctx = ctx;
-       TAILQ_INSERT_HEAD(ctx->ifaces, ifp, next);
        ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state));
        if (state == NULL)
                goto eexit;
-       ifp->options = calloc(1, sizeof(*ifp->options));
-       if (ifp->options == NULL)
-               goto eexit;
-       strlcpy(ifp->name, ifname, sizeof(ifp->name));
        snprintf(state->leasefile, sizeof(state->leasefile),
            LEASEFILE, ifp->name);
        state->new = read_lease(ifp);
        if (state->new == NULL && errno == ENOENT) {
-               strlcpy(state->leasefile, ifname, sizeof(state->leasefile));
+               strlcpy(state->leasefile, ifp->name, sizeof(state->leasefile));
                state->new = read_lease(ifp);
        }
        if (state->new == NULL) {
                if (errno == ENOENT)
-                       syslog(LOG_ERR, "%s: no lease to dump", ifname);
+                       syslog(LOG_ERR, "%s: no lease to dump", ifp->name);
                return -1;
        }
        state->reason = "DUMP";
diff --git a/dhcp.h b/dhcp.h
index b7338c128c3580d10e458e4e8aab23071e37e43a..6eabc4c667b208d05cef32ffaaf3d1f9661369d3 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -285,7 +285,7 @@ void dhcp_bind(void *);
 void dhcp_reboot_newopts(struct interface *, unsigned long long);
 void dhcp_close(struct interface *);
 void dhcp_free(struct interface *);
-int dhcp_dump(struct dhcpcd_ctx *, const char *);
+int dhcp_dump(struct interface *);
 #else
 #define dhcp_printoptions
 #define dhcp_drop(a, b)
@@ -294,7 +294,7 @@ int dhcp_dump(struct dhcpcd_ctx *, const char *);
 #define dhcp_reboot_newopts(a, b)
 #define dhcp_close(a)
 #define dhcp_free(a)
-#define dhcp_dump(a, b) -1
+#define dhcp_dump(a) -1
 #endif
 
 #endif
diff --git a/dhcp6.c b/dhcp6.c
index 6ef106ffa996d7b431d4a3f81358cb2a22f3e397..f9966fc698f8511fd4f51330b25ffd0a7fae337b 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -1665,6 +1665,7 @@ dhcp6_readlease(struct interface *ifp)
        if (stat(state->leasefile, &st) == -1) {
                if (errno == ENOENT)
                        return 0;
+               syslog(LOG_ERR, "%s: %s: %m", ifp->name, __func__);
                return -1;
        }
        syslog(LOG_DEBUG, "%s: reading lease `%s'",
@@ -1674,12 +1675,17 @@ dhcp6_readlease(struct interface *ifp)
                return -1;
        }
        state->new = malloc((size_t)st.st_size);
-       if (state->new == NULL)
+       if (state->new == NULL) {
+               syslog(LOG_ERR, "%s: %m", __func__);
                return -1;
+       }
        state->new_len = (size_t)st.st_size;
        fd = open(state->leasefile, O_RDONLY);
-       if (fd == -1)
+       if (fd == -1) {
+               syslog(LOG_ERR, "%s: %s: %s: %m", ifp->name, __func__,
+                   state->leasefile);
                return -1;
+       }
        bytes = read(fd, state->new, state->new_len);
        close(fd);
        if (bytes < (ssize_t)state->new_len) {
@@ -2978,3 +2984,35 @@ dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
 
        return (ssize_t)n;
 }
+
+int
+dhcp6_dump(struct interface *ifp)
+{
+       struct dhcp6_state *state;
+       int r;
+
+       ifp->if_data[IF_DATA_DHCP6] = state = calloc(1, sizeof(*state));
+       if (state == NULL)
+               goto eexit;
+       TAILQ_INIT(&state->addrs);
+       snprintf(state->leasefile, sizeof(state->leasefile),
+           LEASEFILE6, ifp->name);
+       r = dhcp6_readlease(ifp);
+       if (r == -1 && errno == ENOENT) {
+               strlcpy(state->leasefile, ifp->name, sizeof(state->leasefile));
+               r = dhcp6_readlease(ifp);
+       }
+       if (r == -1) {
+               if (errno == ENOENT)
+                       syslog(LOG_ERR, "%s: no lease to dump", ifp->name);
+               else
+                       syslog(LOG_ERR, "%s: dhcp6_readlease: %m", ifp->name);
+               return -1;
+       }
+       state->reason = "DUMP6";
+       return script_runreason(ifp, state->reason);
+
+eexit:
+       syslog(LOG_ERR, "%s: %m", __func__);
+       return -1;
+}
diff --git a/dhcp6.h b/dhcp6.h
index 468c4f5f0e2a181789a2245431a6335194f89827..4d276bdfaa0d55a2939334e60fb1f4f14ff0c3f2 100644 (file)
--- a/dhcp6.h
+++ b/dhcp6.h
@@ -236,6 +236,7 @@ void dhcp6_free(struct interface *);
 void dhcp6_handleifa(struct dhcpcd_ctx *, int, const char *,
     const struct in6_addr *addr, int);
 void dhcp6_drop(struct interface *, const char *);
+int dhcp6_dump(struct interface *);
 #else
 #define dhcp6_printoptions()
 #define dhcp6_addrexists(a, b) (0)
@@ -245,6 +246,7 @@ void dhcp6_drop(struct interface *, const char *);
 #define dhcp6_env(a, b, c, d, e)
 #define dhcp6_free(a)
 #define dhcp6_drop(a, b)
+#define dhcp6_dump(a) -1
 #endif
 
 #endif
index 97eab7a5b7a103607251c3079233667688af3d85..0d515f78f3bbfb9169961ff86f965dfc8df8d42e 100644 (file)
@@ -1,6 +1,8 @@
 # Just echo our DHCP options we have
 
-if [ "$reason" = "DUMP" ]; then
+case "$reason" in
+DUMP|DUMP6)
        set | sed -ne 's/^new_//p' | sort
        exit 0
-fi
+       ;;
+esac
index 3e25523f69886dfa0d0d2c43366b8d87138ddf82..d950c354f4ac83509d8859ca9d49ac5d12d799d1 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1351,12 +1351,44 @@ main(int argc, char **argv)
        if (chdir("/") == -1)
                syslog(LOG_ERR, "chdir `/': %m");
 
+       /* Freeing allocated addresses from dumping leases can trigger
+        * eloop removals as well, so init here. */
+       ctx.eloop = eloop_init();
+       if (ctx.eloop == NULL) {
+               syslog(LOG_ERR, "%s: %m", __func__);
+               goto exit_failure;
+       }
+
        if (ctx.options & DHCPCD_DUMPLEASE) {
                if (optind != argc - 1) {
                        syslog(LOG_ERR, "dumplease requires an interface");
                        goto exit_failure;
                }
-               if (dhcp_dump(&ctx, argv[optind]) == -1)
+               i = 0;
+               if (ctx.ifaces == NULL) {
+                       ctx.ifaces = malloc(sizeof(*ctx.ifaces));
+                       if (ctx.ifaces == NULL) {
+                               syslog(LOG_ERR, "%s: %m", __func__);
+                               goto exit_failure;
+                       }
+                       TAILQ_INIT(ctx.ifaces);
+               }
+               ifp = calloc(1, sizeof(*ifp));
+               if (ifp == NULL)
+                       goto exit_failure;
+               strlcpy(ifp->name, argv[optind], sizeof(ifp->name));
+               ifp->ctx = &ctx;
+               TAILQ_INSERT_HEAD(ctx.ifaces, ifp, next);
+               configure_interface(ifp, 0, NULL);
+               if (family == 0 || family == AF_INET) {
+                       if (dhcp_dump(ifp) == -1)
+                               i = 1;
+               }
+               if (family == 0 || family == AF_INET6) {
+                       if (dhcp6_dump(ifp) == -1)
+                               i = 1;
+               }
+               if (i == -1)
                        goto exit_failure;
                goto exit_success;
        }
@@ -1396,12 +1428,6 @@ main(int argc, char **argv)
                syslog(LOG_WARNING,
                    PACKAGE " will not work correctly unless run as root");
 
-       ctx.eloop = eloop_init();
-       if (ctx.eloop == NULL) {
-               syslog(LOG_ERR, "%s: %m", __func__);
-               goto exit_failure;
-       }
-
 #ifdef USE_SIGNALS
        if (sig != 0) {
                pid = read_pid(pidfile);