From: Roy Marples Date: Tue, 13 Jan 2009 17:04:28 +0000 (+0000) Subject: Store the reason we run the script against the interface state. X-Git-Tag: v5.0.0~129 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1ba422363a3e1bbee4bbbee720dfeadfb7d82ee1;p=thirdparty%2Fdhcpcd.git Store the reason we run the script against the interface state. This enables us to query states via the control socket. --- diff --git a/bind.c b/bind.c index b692ab92..5d384f79 100644 --- a/bind.c +++ b/bind.c @@ -118,8 +118,8 @@ bind_interface(void *arg) struct if_options *ifo = state->options; struct dhcp_lease *lease = &state->lease; struct timeval tv; - const char *reason = NULL; + state->reason = NULL; delete_timeout(handle_exit_timeout, NULL); if (clock_monotonic) get_monotonic(&lease->boundtime); @@ -134,12 +134,12 @@ bind_interface(void *arg) iface->name, inet_ntoa(lease->addr)); lease->leasetime = ~0U; lease->net.s_addr = ifo->request_netmask.s_addr; - reason = "STATIC"; + state->reason = "STATIC"; } else if (IN_LINKLOCAL(htonl(state->new->yiaddr))) { syslog(LOG_INFO, "%s: using IPv4LL address %s", iface->name, inet_ntoa(lease->addr)); lease->leasetime = ~0U; - reason = "IPV4LL"; + state->reason = "IPV4LL"; } else if (ifo->options & DHCPCD_INFORM) { if (ifo->request_address.s_addr != 0) lease->addr.s_addr = ifo->request_address.s_addr; @@ -148,12 +148,12 @@ bind_interface(void *arg) syslog(LOG_INFO, "%s: received approval for %s", iface->name, inet_ntoa(lease->addr)); lease->leasetime = ~0U; - reason = "INFORM"; + state->reason = "INFORM"; } else { if (gettimeofday(&tv, NULL) == 0) lease->leasedfrom = tv.tv_sec; else if (lease->frominfo) - reason = "TIMEOUT"; + state->reason = "TIMEOUT"; if (lease->leasetime == ~0U) { lease->renewaltime = lease->rebindtime = lease->leasetime; syslog(LOG_INFO, "%s: leased %s for infinity", @@ -182,21 +182,22 @@ bind_interface(void *arg) inet_ntoa(lease->addr), lease->leasetime); } } - if (reason == NULL) { + if (options & DHCPCD_TEST) { + state->reason = "TEST"; + run_script(iface); + exit(EXIT_SUCCESS); + } + if (state->reason == NULL) { if (state->old) { if (state->old->yiaddr == state->new->yiaddr && lease->server.s_addr) - reason = "RENEW"; + state->reason = "RENEW"; else - reason = "REBIND"; + state->reason = "REBIND"; } else if (state->state == DHS_REBOOT) - reason = "REBOOT"; + state->reason = "REBOOT"; else - reason = "BOUND"; - } - if (options & DHCPCD_TEST) { - run_script(iface, "TEST"); - exit(EXIT_SUCCESS); + state->reason = "BOUND"; } if (lease->leasetime == ~0U) lease->renewaltime = lease->rebindtime = lease->leasetime; @@ -205,7 +206,7 @@ bind_interface(void *arg) add_timeout_sec(lease->rebindtime, start_rebind, iface); add_timeout_sec(lease->leasetime, start_expire, iface); } - configure(iface, reason); + configure(iface); daemonise(); state->state = DHS_BOUND; if (ifo->options & DHCPCD_ARP) { diff --git a/configure.c b/configure.c index 24bec760..60b1921a 100644 --- a/configure.c +++ b/configure.c @@ -158,48 +158,32 @@ arraytostr(const char *const *argv, char **s) return len; } -int -run_script(const struct interface *iface, const char *reason) +static ssize_t +make_env(const struct interface *iface, char ***argv) { - char *const argv[2] = { UNCONST(iface->state->options->script), NULL }; - char **env = NULL, **ep; - char *path, *p, *bigenv; + char **env, *p; ssize_t e, elen, l; - pid_t pid; - int status = 0; const struct if_options *ifo = iface->state->options; const struct interface *ifp; - const struct fd_list *fd; - struct iovec iov[2]; - - syslog(LOG_DEBUG, "%s: executing `%s', reason %s", - iface->name, argv[0], reason); /* Make our env */ - elen = 6; + elen = 5; env = xmalloc(sizeof(char *) * (elen + 1)); - path = getenv("PATH"); - if (path) { - e = strlen("PATH") + strlen(path) + 2; - env[0] = xmalloc(e); - snprintf(env[0], e, "PATH=%s", path); - } else - env[0] = xstrdup(DEFAULT_PATH); e = strlen("interface") + strlen(iface->name) + 2; + env[0] = xmalloc(e); + snprintf(env[0], e, "interface=%s", iface->name); + e = strlen("reason") + strlen(iface->state->reason) + 2; env[1] = xmalloc(e); - snprintf(env[1], e, "interface=%s", iface->name); - e = strlen("reason") + strlen(reason) + 2; - env[2] = xmalloc(e); - snprintf(env[2], e, "reason=%s", reason); + snprintf(env[1], e, "reason=%s", iface->state->reason); e = 20; + env[2] = xmalloc(e); + snprintf(env[2], e, "pid=%d", getpid()); env[3] = xmalloc(e); - snprintf(env[3], e, "pid=%d", getpid()); - env[4] = xmalloc(e); - snprintf(env[4], e, "metric=%d", iface->metric); + snprintf(env[3], e, "metric=%d", iface->metric); l = e = strlen("interface_order="); for (ifp = ifaces; ifp; ifp = ifp->next) e += strlen(ifp->name) + 1; - p = env[5] = xmalloc(e); + p = env[4] = xmalloc(e); strlcpy(p, "interface_order=", e); e -= l; p += l; @@ -247,6 +231,62 @@ run_script(const struct interface *iface, const char *reason) } env[elen] = '\0'; + *argv = env; + return elen; +} + +int +send_state(int fd, const struct interface *iface) +{ + char **env, **ep, *s; + ssize_t elen; + struct iovec iov[2]; + int retval; + + retval = 0; + make_env(iface, &env); + elen = arraytostr((const char *const *)env, &s); + iov[0].iov_base = &elen; + iov[0].iov_len = sizeof(ssize_t); + iov[1].iov_base = s; + iov[1].iov_len = elen; + retval = writev(fd, iov, 2); + ep = env; + while (*ep) + free(*ep++); + free(env); + free(s); + return retval; +} + +int +run_script(const struct interface *iface) +{ + char *const argv[2] = { UNCONST(iface->state->options->script), NULL }; + char **env = NULL, **ep; + char *path, *bigenv; + ssize_t e, elen = 0; + pid_t pid; + int status = 0; + const struct fd_list *fd; + struct iovec iov[2]; + + syslog(LOG_DEBUG, "%s: executing `%s', reason %s", + iface->name, argv[0], iface->state->reason); + + /* Make our env */ + elen = make_env(iface, &env); + env = xrealloc(env, sizeof(char *) * (elen + 2)); + /* Add path to it */ + path = getenv("PATH"); + if (path) { + e = strlen("PATH") + strlen(path) + 2; + env[elen] = xmalloc(e); + snprintf(env[elen], e, "PATH=%s", path); + } else + env[elen] = xstrdup(DEFAULT_PATH); + env[++elen] = '\0'; + pid = exec_script(argv, env); if (pid == -1) status = -1; @@ -269,7 +309,7 @@ run_script(const struct interface *iface, const char *reason) elen = arraytostr((const char *const *)env, &bigenv); iov[0].iov_base = &elen; - iov[0].iov_len = sizeof(size_t); + iov[0].iov_len = sizeof(ssize_t); iov[1].iov_base = bigenv; iov[1].iov_len = elen; } @@ -518,7 +558,7 @@ delete_address(struct interface *iface) } int -configure(struct interface *iface, const char *reason) +configure(struct interface *iface) { struct dhcp_message *dhcp = iface->state->new; struct dhcp_lease *lease = &iface->state->lease; @@ -533,7 +573,7 @@ configure(struct interface *iface, const char *reason) build_routes(); delete_address(iface); } - run_script(iface, reason); + run_script(iface); return 0; } @@ -578,6 +618,6 @@ configure(struct interface *iface, const char *reason) !(iface->state->options->options & DHCPCD_INFORM)) if (write_lease(iface, dhcp) == -1) syslog(LOG_ERR, "write_lease: %m"); - run_script(iface, reason); + run_script(iface); return 0; } diff --git a/configure.h b/configure.h index b5ffc7e0..3a4b6b93 100644 --- a/configure.h +++ b/configure.h @@ -30,7 +30,8 @@ #include "net.h" -int run_script(const struct interface *, const char *); -int configure(struct interface *, const char *); +int send_state(int, const struct interface *); +int run_script(const struct interface *); +int configure(struct interface *); #endif diff --git a/dhcpcd.c b/dhcpcd.c index d79ff973..61b9d5dc 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -188,7 +188,11 @@ drop_config(struct interface *iface, const char *reason) free(iface->state->old); iface->state->old = iface->state->new; iface->state->new = NULL; - configure(iface, reason); + if (reason == NULL) + iface->state->reason = "EXPIRE"; + else + iface->state->reason = reason; + configure(iface); } iface->state->lease.addr.s_addr = 0; } @@ -490,7 +494,8 @@ handle_dhcp(struct interface *iface, struct dhcp_message **dhcpp) state->old = state->new; state->new = state->offer; state->offer = NULL; - run_script(iface, "TEST"); + state->reason = "TEST"; + run_script(iface); exit(EXIT_SUCCESS); } delete_timeout(send_discover, iface); @@ -965,6 +970,7 @@ init_state(struct interface *iface, int argc, char **argv) ifs = iface->state = xzalloc(sizeof(*ifs)); ifs->state = DHS_INIT; + ifs->reason = "PREINIT"; ifs->nakoff = 1; configure_interface(iface, argc, argv); @@ -1010,7 +1016,7 @@ handle_new_interface(const char *ifname) if (ifn) continue; init_state(ifp, 2, UNCONST(argv)); - run_script(ifp, "PREINIT"); + run_script(ifp); start_interface(ifp); if (ifl) ifl->next = ifp; @@ -1103,13 +1109,15 @@ handle_args(struct fd_list *fd, int argc, char **argv) struct interface *ifs, *ifp, *ifl, *ifn, *ift; int do_exit = 0, do_release = 0, do_reboot = 0, opt, oi = 0; char *s, *p; - size_t l, len; + ssize_t l, len; + struct iovec iov[2]; if (fd != NULL) { + /* Special commands for our control socket */ if (strcmp(*argv, "--version") == 0) { write(fd->fd, VERSION, strlen(VERSION)); return 0; - } else if (strcmp(*argv, "--listinterfaces") == 0) { + } else if (strcmp(*argv, "--getinterfaces") == 0) { l = 0; for (ifp = ifaces; ifp; ifp = ifp->next) l += strlen(ifp->name) + 1; @@ -1121,9 +1129,21 @@ handle_args(struct fd_list *fd, int argc, char **argv) *p++ = ' '; } *--p = '\0'; - write(fd->fd, s, l); + iov[0].iov_base = &l; + iov[0].iov_len = sizeof(ssize_t); + iov[1].iov_base = s; + iov[1].iov_len = l; + writev(fd->fd, iov, 2); free(s); return 0; + } else if (strcmp(*argv, "--getstates") == 0) { + l = 0; + for (ifp = ifaces; ifp; ifp = ifp->next) + l++; + write(fd->fd, &l, sizeof(l)); + for (ifp = ifaces; ifp; ifp = ifp->next) + send_state(fd->fd, ifp); + return 0; } else if (strcmp(*argv, "--listen") == 0) { fd->listener = 1; return 0; @@ -1184,7 +1204,7 @@ handle_args(struct fd_list *fd, int argc, char **argv) } else { ifp->next = NULL; init_state(ifp, argc, argv); - run_script(ifp, "PREINIT"); + run_script(ifp); start_interface(ifp); if (ifl) ifl->next = ifp; @@ -1425,7 +1445,7 @@ main(int argc, char **argv) sort_interfaces(); for (iface = ifaces; iface; iface = iface->next) { if (!(options & DHCPCD_TEST)) - run_script(iface, "PREINIT"); + run_script(iface); start_interface(iface); } start_eloop(); diff --git a/dhcpcd.h b/dhcpcd.h index 61e552de..b5968e26 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -65,6 +65,7 @@ struct if_state { struct dhcp_message *new; struct dhcp_message *old; struct dhcp_lease lease; + const char *reason; time_t interval; time_t nakoff; uint32_t xid;