]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Store the reason we run the script against the interface state.
authorRoy Marples <roy@marples.name>
Tue, 13 Jan 2009 17:04:28 +0000 (17:04 +0000)
committerRoy Marples <roy@marples.name>
Tue, 13 Jan 2009 17:04:28 +0000 (17:04 +0000)
This enables us to query states via the control socket.

bind.c
configure.c
configure.h
dhcpcd.c
dhcpcd.h

diff --git a/bind.c b/bind.c
index b692ab92ef2b96bcbe6609c29b09cbe819888959..5d384f79e0a8d7d26373ef8a8d87f65ddba2b271 100644 (file)
--- 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) {
index 24bec7601012124de191410bc6de04e659e63170..60b1921ac1323b1141fc4fdda292832fd3cd19d2 100644 (file)
@@ -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;
 }
index b5ffc7e0210252b1e9c740568fa1f2cec04c432d..3a4b6b93d46f7de23319db6cd1784d8d58630146 100644 (file)
@@ -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
index d79ff973ba9bc9bc2ae748a04201bf4c607e021e..61b9d5dc6b2d91daf992235bc7863e75847d021f 100644 (file)
--- 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();
index 61e552de6d50428b440b4d9946056e2681bb997e..b5968e26926abe893a1aeb914305650d6f6aa550 100644 (file)
--- 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;