aboutsummaryrefslogtreecommitdiffstats
path: root/control.c
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2011-01-24 16:27:51 -0800
committerDmitry Shmidt <dimitrysh@google.com>2011-01-24 16:27:51 -0800
commite86eee143ed21592f88a46623a81f71002430459 (patch)
treee0be4ce113729bce176fd5054aeaf51a88b2e169 /control.c
parent6bcc301d166624837871fd601b4d3b5d43551e6b (diff)
downloadexternal_dhcpcd-e86eee143ed21592f88a46623a81f71002430459.zip
external_dhcpcd-e86eee143ed21592f88a46623a81f71002430459.tar.gz
external_dhcpcd-e86eee143ed21592f88a46623a81f71002430459.tar.bz2
dhcpcd: Update to Version 5.2.10
Change-Id: I949331c7aad91b125decd51da4041983d3a352bc Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'control.c')
-rw-r--r--control.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/control.c b/control.c
new file mode 100644
index 0000000..24fb354
--- /dev/null
+++ b/control.c
@@ -0,0 +1,208 @@
+/*
+ * dhcpcd - DHCP client daemon
+ * Copyright (c) 2006-2009 Roy Marples <roy@marples.name>
+ * All rights reserved
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <linux/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "common.h"
+#include "dhcpcd.h"
+#include "control.h"
+#include "eloop.h"
+
+static int fd = -1;
+static char buffer[1024];
+static char *argvp[255];
+
+struct sockaddr_un sun;
+struct fd_list *fds = NULL;
+
+static void
+remove_control_data(void *arg)
+{
+ 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;
+ char *e, *p;
+ char **ap;
+
+ bytes = read(l->fd, buffer, sizeof(buffer) - 1);
+ if (bytes == -1 || bytes == 0) {
+ remove_control_data(l);
+ return;
+ }
+ buffer[bytes] = '\0';
+ 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 */
+static void
+handle_control(_unused void *arg)
+{
+ struct sockaddr_un run;
+ socklen_t len;
+ struct fd_list *l;
+ int f;
+
+ len = sizeof(run);
+ if ((f = accept(fd, (struct sockaddr *)&run, &len)) == -1)
+ return;
+ 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
+make_sock(void)
+{
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ return -1;
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strlcpy(sun.sun_path, CONTROLSOCKET, sizeof(sun.sun_path));
+ return sizeof(sun.sun_family) + strlen(sun.sun_path) + 1;
+}
+
+int
+start_control(void)
+{
+ int len;
+
+ if ((len = make_sock()) == -1)
+ return -1;
+ unlink(CONTROLSOCKET);
+ if (bind(fd, (struct sockaddr *)&sun, len) == -1 ||
+ chmod(CONTROLSOCKET,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1 ||
+ set_cloexec(fd) == -1 ||
+ set_nonblock(fd) == -1 ||
+ listen(fd, sizeof(fds)) == -1)
+ {
+ close(fd);
+ return -1;
+ }
+ add_event(fd, handle_control, NULL);
+ return fd;
+}
+
+int
+stop_control(void)
+{
+ int retval = 0;
+ struct fd_list *l, *ll;
+
+ delete_event(fd);
+ if (shutdown(fd, SHUT_RDWR) == -1)
+ retval = 1;
+ fd = -1;
+ if (unlink(CONTROLSOCKET) == -1)
+ retval = -1;
+
+ l = fds;
+ while (l != NULL) {
+ ll = l->next;
+ delete_event(l->fd);
+ shutdown(l->fd, SHUT_RDWR);
+ free(l);
+ l = ll;
+ }
+
+ return retval;
+}
+
+int
+open_control(void)
+{
+ int len;
+
+ if ((len = make_sock()) == -1)
+ return -1;
+ return connect(fd, (struct sockaddr *)&sun, len);
+}
+
+int
+send_control(int argc, char * const *argv)
+{
+ char *p = buffer;
+ int i;
+ size_t len;
+
+ if (argc > 255) {
+ errno = ENOBUFS;
+ return -1;
+ }
+ for (i = 0; i < argc; i++) {
+ len = strlen(argv[i]) + 1;
+ if ((p - buffer) + len > sizeof(buffer)) {
+ errno = ENOBUFS;
+ return -1;
+ }
+ memcpy(p, argv[i], len);
+ p += len;
+ }
+ return write(fd, buffer, p - buffer);
+}