summaryrefslogtreecommitdiffstats
path: root/dhcpcd/dev.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-01-30 13:29:46 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-01-30 16:23:03 +0100
commitf2ed769880271654297a4be420f26ab94d39666b (patch)
tree4cbfc23184993e8ef11bb1d60b307cbb3644a259 /dhcpcd/dev.c
parentarphole: New test (diff)
downloadrtems-libbsd-f2ed769880271654297a4be420f26ab94d39666b.tar.bz2
DHCPCD(8): Import
Import DHCPCD(8) from: http://roy.marples.name/projects/dhcpcd/ The upstream sources can be obtained via: fossil clone http://roy.marples.name/projects/dhcpcd The imported version is 2014-01-29 19:46:44 [6b209507bb].
Diffstat (limited to 'dhcpcd/dev.c')
-rw-r--r--dhcpcd/dev.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/dhcpcd/dev.c b/dhcpcd/dev.c
new file mode 100644
index 00000000..b33a3e00
--- /dev/null
+++ b/dhcpcd/dev.c
@@ -0,0 +1,177 @@
+/*
+ * dhcpcd - DHCP client daemon
+ * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
+ *
+ * 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 <dirent.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "common.h"
+#include "dev.h"
+#include "eloop.h"
+#include "dhcpcd.h"
+
+static struct dev *dev;
+static void *handle;
+static int fd = -1;
+
+static struct dev_dhcpcd dev_dhcpcd = {
+ .handle_interface = &handle_interface
+};
+
+int
+dev_initialized(const char *ifname)
+{
+
+ if (dev == NULL)
+ return 1;
+ return dev->initialized(ifname);
+}
+
+int
+dev_listening(void)
+{
+
+ if (dev == NULL)
+ return 0;
+ return dev->listening();
+}
+
+void
+dev_stop(void)
+{
+
+ if (dev) {
+ syslog(LOG_DEBUG, "dev: unloaded %s", dev->name);
+ dev->stop();
+ free(dev);
+ dev = NULL;
+ }
+ if (handle) {
+ dlclose(handle);
+ handle = NULL;
+ }
+}
+
+static int
+dev_start2(const char *name)
+{
+ char file[PATH_MAX];
+ void *h;
+ void (*fptr)(struct dev *, const struct dev_dhcpcd *);
+ int r;
+
+ snprintf(file, sizeof(file), DEVDIR "/%s", name);
+ h = dlopen(file, RTLD_LAZY);
+ if (h == NULL) {
+ syslog(LOG_ERR, "dlopen: %s", dlerror());
+ return -1;
+ }
+ fptr = (void (*)(struct dev *, const struct dev_dhcpcd *))
+ dlsym(h, "dev_init");
+ if (fptr == NULL) {
+ syslog(LOG_ERR, "dlsym: %s", dlerror());
+ dlclose(h);
+ return -1;
+ }
+ dev = calloc(1, sizeof(*dev));
+ fptr(dev, &dev_dhcpcd);
+ if (dev->start == NULL || (r = dev->start()) == -1) {
+ free(dev);
+ dev = NULL;
+ dlclose(h);
+ return -1;
+ }
+ syslog(LOG_INFO, "dev: loaded %s", dev->name);
+ handle = h;
+ return r;
+}
+
+static int
+dev_start1(const char *plugin)
+{
+ DIR *dp;
+ struct dirent *d;
+ int r;
+
+ if (dev) {
+ syslog(LOG_ERR, "dev: already started %s", dev->name);
+ return -1;
+ }
+
+ if (plugin)
+ return dev_start2(plugin);
+
+ dp = opendir(DEVDIR);
+ if (dp == NULL) {
+ syslog(LOG_DEBUG, "dev: %s: %m", DEVDIR);
+ return 0;
+ }
+
+ r = 0;
+ while ((d = readdir(dp))) {
+ if (d->d_name[0] == '.')
+ continue;
+
+ r = dev_start2(d->d_name);
+ if (r != -1)
+ break;
+ }
+ closedir(dp);
+ return r;
+}
+
+static void
+dev_handle_data(__unused void *arg)
+{
+
+ if (dev->handle_device() == -1) {
+ /* XXX: an error occured. should we restart dev? */
+ }
+}
+
+int
+dev_start(const char *plugin)
+{
+
+ if (fd != -1) {
+ syslog(LOG_ERR, "%s: already started on fd %d", __func__, fd);
+ return fd;
+ }
+
+ fd = dev_start1(plugin);
+ if (fd != -1) {
+ if (eloop_event_add(fd, dev_handle_data, NULL) == -1) {
+ syslog(LOG_ERR, "%s: eloop_event_add: %m", __func__);
+ dev_stop();
+ return -1;
+ }
+ }
+
+ return fd;
+}