]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Remove the limit for the number of connections to the control socket.
authorRoy Marples <roy@marples.name>
Mon, 12 Jan 2009 16:39:01 +0000 (16:39 +0000)
committerRoy Marples <roy@marples.name>
Mon, 12 Jan 2009 16:39:01 +0000 (16:39 +0000)
Send the dhcpcd-run-hooks enviornment to listeners on the control socket.

configure.c
control.c
control.h
dhcpcd.c
dhcpcd.h

index 917bd181cba0c564ef34a2da146c2cf5dcc4e396..24bec7601012124de191410bc6de04e659e63170 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <sys/stat.h>
+#include <sys/uio.h>
 #include <sys/wait.h>
 
 #include <netinet/in.h>
@@ -135,17 +136,41 @@ append_config(char ***env, ssize_t *len,
        *env = ne;
 }
 
+static size_t
+arraytostr(const char *const *argv, char **s)
+{
+       const char *const *ap;
+       char *p;
+       size_t len, l;
+
+       len = 0;
+       ap = argv;
+       while (*ap)
+               len += strlen(*ap++) + 1;
+       *s = p = xmalloc(len);
+       ap = argv;
+       while (*ap) {
+               l = strlen(*ap) + 1;
+               memcpy(p, *ap, l);
+               p += l;
+               ap++;
+       }
+       return len;
+}
+
 int
 run_script(const struct interface *iface, const char *reason)
 {
        char *const argv[2] = { UNCONST(iface->state->options->script), NULL };
        char **env = NULL, **ep;
-       char *path, *p;
+       char *path, *p, *bigenv;
        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);
@@ -236,6 +261,23 @@ run_script(const struct interface *iface, const char *reason)
                }
        }
 
+       /* Send to our listeners */
+       bigenv = NULL;
+       for (fd = fds; fd != NULL; fd = fd->next) {
+               if (fd->listener) {
+                       if (bigenv == NULL) {
+                               elen = arraytostr((const char *const *)env,
+                                               &bigenv);
+                               iov[0].iov_base = &elen;
+                               iov[0].iov_len = sizeof(size_t);
+                               iov[1].iov_base = bigenv;
+                               iov[1].iov_len = elen;
+                       }
+                       writev(fd->fd, iov, 2);
+               }
+       }
+       free(bigenv);
+
        /* Cleanup */
        ep = env;
        while (*ep)
index 185638ff5f777c878e9586b69b2ea4447f251ad4..751208260fe817d076e3bceaf390e68f9fa9b7ce 100644 (file)
--- a/control.c
+++ b/control.c
 
 #include "config.h"
 #include "common.h"
+#include "dhcpcd.h"
 #include "control.h"
 #include "eloop.h"
-#include "dhcpcd.h"
 
 static int fd = -1;
 struct sockaddr_un sun;
 static char buffer[1024];
 static char *argvp[255];
 
-static int fds[5];
+struct fd_list *fds = NULL;
 
 static void
 remove_control_data(void *arg)
 {
-       size_t i;
-
-       for (i = 0; i < sizeof(fds); i++) {
-               if (&fds[i] == arg) {
-                       close(fds[i]);
-                       delete_event(fds[i]);
-                       fds[i] = -1;
+       struct fd_list *l, *last = NULL;
+
+       for (l = fds; l != NULL; l = l->next) {
+               if (l == arg) {
+                       close(l->fd);
+                       delete_event(l->fd);
+                       if (last == NULL)
+                               fds = l->next;
+                       else
+                               last->next = l->next;
+                       free(l);
+                       break;
                }
+               last = l;
        }
 }
 
 static void
 handle_control_data(void *arg)
 {
+       struct fd_list *l = arg;
        ssize_t bytes;
-       int argc, *s = arg;
+       int argc;
        char *e, *p;
        char **ap;
 
-       for (;;) {
-               bytes = read(*s, buffer, sizeof(buffer));
-               if (bytes == -1 || bytes == 0) {
-                       remove_control_data(arg);
-                       return;
-               }
-               p = buffer;
-               e = buffer + bytes;
-               argc = 0;
-               ap = argvp;
-               while (p < e && (size_t)argc < sizeof(argvp)) {
-                       argc++;
-                       *ap++ = p;
-                       p += strlen(p) + 1;
-               }
-               handle_args(*s, argc, argvp);
+       bytes = read(l->fd, buffer, sizeof(buffer));
+       if (bytes == -1 || bytes == 0) {
+               remove_control_data(l);
+               return;
        }
+       p = buffer;
+       e = buffer + bytes;
+       argc = 0;
+       ap = argvp;
+       while (p < e && (size_t)argc < sizeof(argvp)) {
+               argc++;
+               *ap++ = p;
+               p += strlen(p) + 1;
+       }
+       handle_args(l, argc, argvp);
 }
 
 /* ARGSUSED */
@@ -94,21 +99,18 @@ handle_control(_unused void *arg)
 {
        struct sockaddr_un run;
        socklen_t len;
-       size_t i;
-
-       for (i = 0; i < sizeof(fds); i++) {
-               if (fds[i] == -1)
-                       break;
-       }
-       if (i >= sizeof(fds))
-               return;
+       struct fd_list *l;
+       int f;
 
        len = sizeof(run);
-       if ((fds[i] = accept(fd, (struct sockaddr *)&run, &len)) == -1)
+       if ((f = accept(fd, (struct sockaddr *)&run, &len)) == -1)
                return;
-       add_event(fds[i], handle_control_data, &fds[i]);
-       /* Timeout the connection after 5 minutes - should be plenty */
-       add_timeout_sec(300, remove_control_data, &fds[i]);
+       l = xmalloc(sizeof(*l));
+       l->fd = f;
+       l->listener = 0;
+       l->next = fds;
+       fds = l;
+       add_event(l->fd, handle_control_data, l);
 }
 
 static int
@@ -139,7 +141,6 @@ start_control(void)
                close(fd);
                return -1;
        }
-       memset(fds, -1, sizeof(fds));
        add_event(fd, handle_control, NULL);
        return fd;
 }
@@ -148,10 +149,22 @@ int
 stop_control(void)
 {
        int retval = 0;
+       struct fd_list *l, *ll;
+
+       delete_event(fd);
        if (close(fd) == -1)
                retval = 1;
+       fd = -1;
        if (unlink(CONTROLSOCKET) == -1)
                retval = -1;
+       l = fds;
+       while (l != NULL) {
+               ll = l->next;
+               delete_event(l->fd);
+               close(l->fd);
+               free(l);
+               l = ll;
+       }
        return retval;
 }
 
index 4440690202572657218633209a8b18c4ee53276f..04d7aa1de0e72dd55f3dc3f7110164ab9139b980 100644 (file)
--- a/control.h
+++ b/control.h
 
 #include "dhcpcd.h"
 
+struct fd_list {
+       int fd;
+       int listener;
+       struct fd_list *next;
+};
+extern struct fd_list *fds;
+
 int start_control(void);
 int stop_control(void);
 int open_control(void);
index 325e4fd0e38ecfb927369e54583ae2bdaed4cc5a..d79ff973ba9bc9bc2ae748a04201bf4c607e021e 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1098,14 +1098,34 @@ handle_signal(_unused void *arg)
 }
 
 int
-handle_args(int fd, int argc, char **argv)
+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;
 
-       if (strcmp(*argv, "--version") == 0) {
-               if (fd != -1) {
-                       write(fd, VERSION, strlen(VERSION));
+       if (fd != NULL) {
+               if (strcmp(*argv, "--version") == 0) {
+                       write(fd->fd, VERSION, strlen(VERSION));
+                       return 0;
+               } else if (strcmp(*argv, "--listinterfaces") == 0) {
+                       l = 0;
+                       for (ifp = ifaces; ifp; ifp = ifp->next)
+                               l += strlen(ifp->name) + 1;
+                       s = p = xmalloc(l);
+                       for (ifp = ifaces; ifp; ifp = ifp->next) {
+                               len = strlen(ifp->name);
+                               memcpy(p, ifp->name, len);
+                               p += len;
+                               *p++ = ' ';
+                       }
+                       *--p = '\0';
+                       write(fd->fd, s, l);
+                       free(s);
+                       return 0;
+               } else if (strcmp(*argv, "--listen") == 0) {
+                       fd->listener = 1;
                        return 0;
                }
        }
index 21a3f4c20b95caa63ab1de0aa7c29cd84c825660..61e552de6d50428b440b4d9946056e2681bb997e 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
@@ -33,6 +33,7 @@
 
 #include <limits.h>
 
+#include "control.h"
 #include "dhcp.h"
 #include "if-options.h"
 
@@ -113,7 +114,7 @@ extern int ifdc;
 extern char **ifdv;
 extern struct interface *ifaces;
 
-int handle_args(int, int, char **);
+int handle_args(struct fd_list *, int, char **);
 void handle_exit_timeout(void *);
 void start_interface(void *);
 void start_discover(void *);