From: Roy Marples Date: Sun, 22 Jun 2014 13:05:05 +0000 (+0000) Subject: Add the ability to dump DHCPv6 leases. X-Git-Tag: v6.4.1~51 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bf7db9ecedcddc28ffa5eb4fa513195be8f14e29;p=thirdparty%2Fdhcpcd.git Add the ability to dump DHCPv6 leases. Control DHCPv4 vs DHCPv6 dumping via the family option. --- diff --git a/dhcp.c b/dhcp.c index 2f046842..4f4fbb98 100644 --- 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 b7338c12..6eabc4c6 100644 --- 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 6ef106ff..f9966fc6 100644 --- 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 468c4f5f..4d276bdf 100644 --- 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 diff --git a/dhcpcd-hooks/02-dump b/dhcpcd-hooks/02-dump index 97eab7a5..0d515f78 100644 --- a/dhcpcd-hooks/02-dump +++ b/dhcpcd-hooks/02-dump @@ -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 diff --git a/dhcpcd.c b/dhcpcd.c index 3e25523f..d950c354 100644 --- 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);