Send the dhcpcd-run-hooks enviornment to listeners on the control socket.
*/
#include <sys/stat.h>
+#include <sys/uio.h>
#include <sys/wait.h>
#include <netinet/in.h>
*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);
}
}
+ /* 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)
#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 */
{
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
close(fd);
return -1;
}
- memset(fds, -1, sizeof(fds));
add_event(fd, handle_control, NULL);
return fd;
}
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;
}
#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);
}
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;
}
}
#include <limits.h>
+#include "control.h"
#include "dhcp.h"
#include "if-options.h"
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 *);