${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}
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
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 */
dhcp6_startrenew(ifp);
}
-int
+bool
dhcp6_dadcompleted(const struct interface *ifp)
{
const struct dhcp6_state *state;
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
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
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 */
.\" 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
.Op interface
.Nm
.Fl U , Fl Fl dumplease
-.Ar interface
+.Op Ar interface
.Nm
.Fl Fl version
.Nm
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 .
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>
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));
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');
}
#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. */
-/* 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>
}
}
assert(*(bufp - 1) == '\0');
+ if (nenv == 0)
+ return NULL;
if (ctx->script_envlen < nenv) {
env = reallocarray(ctx->script_env, nenv + 1, sizeof(*env));
#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) {
}
#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
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",
goto eexit;
}
-#ifdef PRIVSEP
-make:
-#endif
/* Convert buffer to argv */
fflush(fp);
fp = NULL;
#endif
+ if (is_stdin)
+ return buf_pos;
+
if (script_buftoenv(ctx, ctx->script_buf, (size_t)buf_pos) == NULL)
goto eexit;
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)
{
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;
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