]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Instead of linking directly to libudev, create a plugin system for /dev
authorRoy Marples <roy@marples.name>
Thu, 12 Sep 2013 15:43:20 +0000 (15:43 +0000)
committerRoy Marples <roy@marples.name>
Thu, 12 Sep 2013 15:43:20 +0000 (15:43 +0000)
management. This allows dhcpcd to work even if udev removed and adds the
ability to change from udev to something else in the future.

18 files changed:
.gitignore
Makefile
Makefile.inc
README
configure
defs.h
dev.c [new file with mode: 0644]
dev.h [moved from dev/udev.h with 75% similarity]
dev/Makefile [new file with mode: 0644]
dev/udev.c
dhcpcd-hooks/Makefile
dhcpcd.8.in
dhcpcd.c
dhcpcd.conf.5.in
if-linux.c
if-options.c
if-options.h
net.c

index 89c1bd0e227450534caae48888bda56c06af2047..7d6ba580093b15bf012f06445bdb762a83ac8c9d 100644 (file)
@@ -1,5 +1,7 @@
 .depend
 *.o
+*.So
+*.so
 *.bz2
 config.h
 config.mk
index 0669cfbb747164aa72892da3b587101e6299ea0a..31da4f163fa01db01011096ec9e60f6b1ccc021a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -27,9 +27,10 @@ CLEANFILES+= .depend
 FILES=         dhcpcd.conf
 FILESDIR=      ${SYSCONFDIR}
 
-SUBDIRS=       dhcpcd-hooks
+SUBDIRS=       dhcpcd-hooks dev
 
 SED_DBDIR=             -e 's:@DBDIR@:${DBDIR}:g'
+SED_LIBDIR=            -e 's:@LIBDIR@:${LIBDIR}:g'
 SED_HOOKDIR=           -e 's:@HOOKDIR@:${HOOKDIR}:g'
 SED_SERVICEEXISTS=     -e 's:@SERVICEEXISTS@:${SERVICEEXISTS}:g'
 SED_SERVICECMD=                -e 's:@SERVICECMD@:${SERVICECMD}:g'
@@ -51,16 +52,21 @@ DISTFILE?=  ${DISTPREFIX}.tar.bz2
 
 CLEANFILES+=   *.tar.bz2
 
-.PHONY:                import import-bsd
+.PHONY:                import import-bsd dev
 
 .SUFFIXES:     .in
 
 .in:
-       ${SED} ${SED_DBDIR} ${SED_HOOKDIR} ${SED_SCRIPT} ${SED_SYS} \
+       ${SED} ${SED_DBDIR} ${SED_LIBDIR} ${SED_HOOKDIR} ${SED_SCRIPT} \
+               ${SED_SYS} \
                ${SED_SERVICEEXISTS} ${SED_SERVICECMD} ${SED_SERVICESTATUS} \
                $< > $@
 
 all: config.h ${PROG} ${SCRIPTS} ${MAN5} ${MAN8}
+       for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done
+
+dev:
+       cd dev && ${MAKE}
 
 .c.o:
        ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@
@@ -78,6 +84,9 @@ _proginstall: ${PROG}
        ${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${SBINDIR}
        ${INSTALL} -d ${DESTDIR}${DBDIR}
 
+proginstall: _proginstall
+       for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done
+
 _scriptsinstall: ${SCRIPTS}
        ${INSTALL} -d ${DESTDIR}${SCRIPTSDIR}
        ${INSTALL} -m ${BINMODE} ${SCRIPTS} ${DESTDIR}${SCRIPTSDIR}
@@ -98,6 +107,7 @@ install: _proginstall _scriptsinstall _maninstall _confinstall
 
 clean:
        rm -f ${OBJS} ${PROG} ${PROG}.core ${CLEANFILES}
+       for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done
 
 distclean: clean
        rm -f .depend config.h config.mk
index fd7ead443afa94235ae153912bdf1f6c50442e4b..98c55d1253d6ae67f89c253525615e7dd192410f 100644 (file)
@@ -1,5 +1,7 @@
 # System definitions
 
+PICFLAG?=      -fPIC
+
 BINMODE?=      0555
 NONBINMODE?=   0444
 MANMODE?=      ${NONBINMODE}
diff --git a/README b/README
index 467107cf1780a22ce3851de6ed80829f2e7747b4..028d64f96bd633b92d789440132c43381dec73a8 100644 (file)
--- a/README
+++ b/README
@@ -43,6 +43,15 @@ configure stage. If we cannot auto-detect how do to this, or it is wrong then
 you can change this by passing shell commands to --service-exists,
 --servicecmd and optionally --servicestatus.
 
+Some systems have /dev management systems and some of these like to rename
+interfaces. As this system would listen in the same way as dhcpcd to new
+interface arrivals, dhcpcd needs to listen to the /dev management sytem
+instead of the kernel. However, if the /dev management system breaks, stops
+working, or changes to a new one, dhcpcd should still try and continue to work.
+To facilitate this, dhcpcd allows a plugin to load to instruct dhcpcd when it
+can use an interface. As of the time of writing only udev support is included.
+You can disable this with --without-dev, or without-udev
+
 To prepare dhcpcd for import into a platform source tree (like NetBSD)
 you can use the make import target to create /tmp/dhcpcd-$version and
 populate it with all the source files and hooks needed.
index a2c817e0afae56691d3e800939a52c4d2adf5739..40ce65c6077e425d1c2106ccaa624a5d48ab9e74 100755 (executable)
--- a/configure
+++ b/configure
@@ -18,6 +18,7 @@ DEBUG=
 FORK=
 STATIC=
 INCLUDEDIR=
+DEVS=
 
 for x do
        opt=${x%%=*}
@@ -60,6 +61,7 @@ for x do
         --without-posix_spawn) POSIX_SPAWN=no;;
        --without-pollts) POLLTS=no;;
        --with-pollts) POLLTS=$var;;
+       --without-dev) DEV=no;;
        --without-udev) UDEV=no;;
        --serviceexists) SERVICEEXISTS=$var;;
        --servicecmd) SERVICECMD=$var;;
@@ -226,7 +228,7 @@ rm -f $CONFIG_H $CONFIG_MK
 echo "# $OS" >$CONFIG_MK
 echo "/* $OS */" >$CONFIG_H
 
-for x in SYSCONFDIR SBINDIR LIBEXECDIR DBDIR RUNDIR; do
+for x in SYSCONFDIR SBINDIR LIBDIR LIBEXECDIR DBDIR RUNDIR; do
        eval v=\$$x
        # Make files look nice for import
        l=$((10 - ${#x}))
@@ -316,7 +318,7 @@ linux)
        fi
        echo "SRCS+=            if-linux.c if-linux-wireless.c" >>$CONFIG_MK
        echo "SRCS+=            platform-linux.c" >>$CONFIG_MK
-       echo "LDADD+=           -lrt" >>$CONFIG_MK
+       echo "LDADD+=           -lrt -ldl" >>$CONFIG_MK
        ;;
 kfreebsd)
        echo "CPPFLAGS+=        -D_GNU_SOURCE" >>$CONFIG_MK
@@ -325,7 +327,7 @@ kfreebsd)
        fi
        echo "SRCS+=            if-bsd.c platform-bsd.c" >>$CONFIG_MK
        echo "COMPAT_SRCS+=     compat/linkaddr.c" >>$CONFIG_MK
-       echo "LDADD+=           -lrt" >>$CONFIG_MK
+       echo "LDADD+=           -lrt -ldl" >>$CONFIG_MK
        ;;
 *)
        if [ -z "$INET" -o "$INET" = yes ]; then
@@ -601,19 +603,19 @@ pselect)
        ;;
 esac
 
-if [ "$UDEV" != no ]; then
+if [ "$DEV" != no -a "$UDEV" != no ]; then
        printf "Checking for libudev ... "
        LIBUDEV_CFLAGS=$(pkg-config --cflags libudev 2>/dev/null)
        LIBUDEV_LIBS=$(pkg-config --libs libudev 2>/dev/null)
+       [ -z "$DEV" ] && DEV=yes
 fi
-if [ "$UDEV" != no -a -n "$LIBUDEV_LIBS" ]; then
+if [ "$DEV" != no -a "$UDEV" != no -a -n "$LIBUDEV_LIBS" ]; then
        echo "yes"
-       echo "SRCS+=    dev/udev.c" >>$CONFIG_MK
+       echo "DEV_PLUGINS+=     udev" >>$CONFIG_MK
        if [ -n "$LIBUDEV_CFLAGS" ]; then
-               echo "CFLAGS+=          $LIBUDEV_CFLAGS" >>$CONFIG_MK
+               echo "LIBUDEV_CFLAGS=           $LIBUDEV_CFLAGS" >>$CONFIG_MK
        fi
-       echo "CPPFLAGS+=        -DLIBUDEV" >>$CONFIG_MK
-       echo "LDADD+=           $LIBUDEV_LIBS" >>$CONFIG_MK
+       echo "LIBUDEV_LIBS=             $LIBUDEV_LIBS" >>$CONFIG_MK
 
        printf "Checking udev_monitor_filter_add_match_subsystem_devtype ..."
        cat <<EOF >_udev.c
@@ -627,16 +629,22 @@ int main(void) {
 EOF
        if $XCC $LIBUDEV_CFLAGS _udev.c -o _udev $LIBUDEV_LIBS 2>/dev/null
        then
-               echo "CPPFLAGS+=                -DLIBUDEV_FILTER" >>$CONFIG_MK
+               echo "LIBUDEV_CPPFLAGS+=        -DLIBUDEV_FILTER" >>$CONFIG_MK
                echo " yes"
        else
                echo " no"
        fi
        rm -f _udev.c _udev
-elif [ "$UDEV" != no ]; then
+elif [ "$DEV" != no -a "$UDEV" != no ]; then
        echo "no"
 fi
 
+if [ "$DEV" = yes ]; then
+       echo "SRCS+=            dev.c" >>$CONFIG_MK
+       echo "CPPFLAGS+=        -DPLUGIN_DEV" >>$CONFIG_MK
+       echo "LDFLAGS+=         -Wl,--export-dynamic" >>$CONFIG_MK
+fi
+
 if [ -z "$SERVICECMD" ]; then
        printf "Checking for OpenRC ... "
        if [ -x /sbin/rc-service ]; then
diff --git a/defs.h b/defs.h
index a5dcf824c77cad7f6e167f1aab9e4b4aeffcaf02..194f354c6529b7839abbc73ad0e5b03e023985e4 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -35,6 +35,9 @@
 #endif
 #ifndef SCRIPT
 # define SCRIPT                        LIBEXECDIR "/" PACKAGE "-run-hooks"
+#ifndef DEVDIR
+# define DEVDIR                        LIBDIR "/" PACKAGE "/dev"
+#endif
 #endif
 #ifndef DUID
 # define DUID                  SYSCONFDIR "/" PACKAGE ".duid"
diff --git a/dev.c b/dev.c
new file mode 100644 (file)
index 0000000..e181dbb
--- /dev/null
+++ b/dev.c
@@ -0,0 +1,136 @@
+/*
+ * 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"
+
+static struct dev *dev;
+static void *handle;
+
+int
+dev_settled(const char *ifname)
+{
+
+       if (dev == NULL)
+               return 1;
+       return dev->settled(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();
+               dev = NULL;
+       }
+       if (handle) {
+               dlclose(handle);
+               handle = NULL;
+       }
+}
+
+static int
+dev_start1(const char *name)
+{
+       char file[PATH_MAX];
+       void *h;
+       void (*fptr)(struct dev *);
+
+       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 *))dlsym(h, "dev_init");
+       if (fptr == NULL) {
+               syslog(LOG_ERR, "dlsym: %s", dlerror());
+               dlclose(h);
+               return -1;
+       }
+       dev = calloc(1, sizeof(*dev));
+       fptr(dev);
+       if (dev->start  == NULL || dev->start() == -1) {
+               free(dev);
+               dev = NULL;
+               dlclose(h);
+               return -1;
+       }
+       syslog(LOG_INFO, "dev: loaded %s", dev->name);
+       handle = h;
+       return 0;
+}
+
+int
+dev_start(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_start1(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_start1(d->d_name);
+               if (r != -1)
+                       break;
+       }
+       return r;
+}
similarity index 75%
rename from dev/udev.h
rename to dev.h
index 0d785726ab05c844b0140f329b83e5940e332434..f56209d44bb1d16d9bacb0eb36907bf7cc58e401 100644 (file)
+++ b/dev.h
  * SUCH DAMAGE.
  */
 
-#ifndef LIBUDEV_H
-#define LIBUDEV_H
+#ifndef DEV_H
+#define DEV_H
 
-int libudev_settled(const char *);
-int libudev_listening(void);
-int libudev_start(void);
-void libudev_stop(void);
+// dev plugin setup
+struct dev {
+       const char *name;
+       int (*settled)(const char *);
+       int (*listening)(void);
+       int (*start)(void);
+       void (*stop)(void);
+};
+int dev_init(struct dev *);
+
+// hooks for dhcpcd
+#ifdef PLUGIN_DEV
+int dev_settled(const char *);
+int dev_listening(void);
+int dev_start(const char *);
+void dev_stop(void);
+#else
+#define dev_settled(a) 1
+#define dev_listening() 0
+#define dev_start(a)
+#define dev_stop()
+#endif
 
 #endif
diff --git a/dev/Makefile b/dev/Makefile
new file mode 100644 (file)
index 0000000..e6b3a2c
--- /dev/null
@@ -0,0 +1,42 @@
+TOP?=  ../
+include ${TOP}/Makefile.inc
+include ${TOP}/config.mk
+
+CFLAGS?=       -O2
+CSTD?=         c99
+CFLAGS+=       -std=${CSTD}
+
+DEVDIR=                ${LIBDIR}/dhcpcd/dev
+DSRC=          ${DEV_PLUGINS:=.c}
+DOBJ=          ${DSRC:.c=.o}
+DSOBJ=         ${DOBJ:.o=.So}
+DPLUGS=                ${DEV_PLUGINS:=.so}
+
+CLEANFILES+=   ${DSOBJ} ${DPLUGS}
+
+.SUFFIXES:     .So .so
+
+.c.So:
+       ${CC} ${PICFLAG} -DPIC ${CPPFLAGS} ${CFLAGS} -c $< -o $@
+
+.So.so: ${DSOBJ}
+       ${CC} ${LDFLAGS} -shared -Wl,-x -o $@ -Wl,-soname,$@ \
+           $< ${LIBS}
+
+all: ${DPLUGS}
+
+udev.So:
+CFLAGS+=       ${LIBUDEV_CFLAGS}
+CPPFLAGS+=     ${LIBUDEV_CPPFLAGS}
+
+udev.so:
+LIBS+=         ${LIBUDEV_LIBS}
+
+proginstall: ${DPLUGS}
+       ${INSTALL} -d ${DESTDIR}${DEVDIR}
+       ${INSTALL} -m ${BINMODE} ${PROG} ${DPLUGS} ${DESTDIR}${DEVDIR}
+
+install: proginstall
+
+clean:
+       rm -f ${CLEANFILES}
index 1eaa510c5a81d635c672eb136e01cd1b3a6c85f2..4376b9fc6b4c49117ccbe022f6c7dac5554ae189 100644 (file)
 #define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
 
 #include <libudev.h>
-#include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
 
 #include "../common.h"
 #include "../dhcpcd.h"
 #include "../eloop.h"
-#include "udev.h"
+#include "../dev.h"
 
+static const char udev_name[]="udev";
 static struct udev *udev;
 static struct udev_monitor *monitor;
+static int monitor_fd = -1;
 
-int
-libudev_settled(const char *ifname)
+static int
+udev_settled(const char *ifname)
 {
        struct udev_device *device;
        int r;
@@ -55,7 +56,7 @@ libudev_settled(const char *ifname)
 }
 
 static void
-libudev_handledata(__unused void *arg)
+udev_handledata(__unused void *arg)
 {
        struct udev_device *device;
        const char *subsystem, *ifname, *action;
@@ -82,17 +83,22 @@ libudev_handledata(__unused void *arg)
        udev_device_unref(device);
 }
 
-int
-libudev_listening(void)
+static int
+udev_listening(void)
 {
 
        return monitor ? 1 : 0;
 }
 
-void
-libudev_stop(void)
+static void
+udev_stop(void)
 {
 
+       if (monitor_fd != -1) {
+               eloop_event_delete(monitor_fd);
+               monitor_fd = -1;
+       }
+
        if (monitor) {
                udev_monitor_unref(monitor);
                monitor = NULL;
@@ -104,17 +110,16 @@ libudev_stop(void)
        }
 }
 
-int
-libudev_start(void)
+static int
+udev_start(void)
 {
-       int fd;
 
        if (udev) {
-               syslog(LOG_ERR, "libudev: already started");
+               syslog(LOG_ERR, "udev: already started");
                return -1;
        }
 
-       syslog(LOG_DEBUG, "libudev: starting");
+       syslog(LOG_DEBUG, "udev: starting");
        udev = udev_new();
        if (udev == NULL) {
                syslog(LOG_ERR, "udev_new: %m");
@@ -138,21 +143,31 @@ libudev_start(void)
                syslog(LOG_ERR, "udev_monitor_enable_receiving: %m");
                goto bad;
        }
-       fd = udev_monitor_get_fd(monitor);
-       if (fd == -1) {
+       monitor_fd = udev_monitor_get_fd(monitor);
+       if (monitor_fd == -1) {
                syslog(LOG_ERR, "udev_monitor_get_fd: %m");
                goto bad;
        }
-       if (eloop_event_add(fd, libudev_handledata, NULL) == -1) {
+       if (eloop_event_add(monitor_fd, udev_handledata, NULL) == -1) {
                syslog(LOG_ERR, "%s: eloop_event_add: %m", __func__);
                goto bad;
        }
 
-       atexit(libudev_stop);
-
-       return fd;
+       return monitor_fd;
 bad:
 
-       libudev_stop();
+       udev_stop();
        return -1;
 }
+
+int
+dev_init(struct dev *dev)
+{
+
+       dev->name = udev_name;
+       dev->settled = udev_settled;
+       dev->listening = udev_listening;
+       dev->start = udev_start;
+       dev->stop = udev_stop;
+       return 0;
+}
index c3ae1887baa9d47efe1003fd51a2722bee3ebfc6..5982f1b7d0ffb563eca71a8ba792193f1a6abe77 100644 (file)
@@ -10,10 +10,14 @@ SCRIPTS+=   ${HOOKSCRIPTS}
 
 all:
 
-install:
+clean:
+
+proginstall:
        ${INSTALL} -d ${DESTDIR}${SCRIPTSDIR}
        ${INSTALL} -m ${NONBINMODE} ${SCRIPTS} ${DESTDIR}${SCRIPTSDIR}
 
+install: proginstall
+
 import:
        ${INSTALL} -d /tmp/${DISTPREFIX}/dhcpcd-hooks
        for x in ${SCRIPTS}; do \
index d8b6781f97f16abf64bb4ee2f242c7fb0c6304af..0bdbc3fffb36a9126c5c423ab83148149e0f610a 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 31, 2013
+.Dd September 12, 2013
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -383,6 +383,21 @@ If
 .Nm
 fails to contact a DHCP server then it returns a failure instead of falling
 back on IPv4LL.
+.It Fl S, Fl Fl static Ar value
+Configures a static
+.Ar value .
+If you set
+.Ic ip_address
+then
+.Nm
+will not attempt to obtain a lease and just use the value for the address with
+an infinite lease time.
+.Pp
+Here is an example which configures a static address, routes and dns.
+.D1 dhcpcd -S ip_address=192.168.0.10/24 \e
+.D1 -S routers=192.168.0.1 \e
+.D1 -S domain_name_servers=192.168.0.1 \e
+.D1 eth0
 .It Fl t , Fl Fl timeout Ar seconds
 Timeout after
 .Ar seconds ,
@@ -512,21 +527,6 @@ Quiet
 .Nm
 on the command line, only warnings and errors will be displayed.
 The messages are still logged though.
-.It Fl S, Fl Fl static Ar value
-Configures a static
-.Ar value .
-If you set
-.Ic ip_address
-then
-.Nm
-will not attempt to obtain a lease and just use the value for the address with
-an infinite lease time.
-.Pp
-Here is an example which configures a static address, routes and dns.
-.D1 dhcpcd -S ip_address=192.168.0.10/24 \e
-.D1 -S routers=192.168.0.1 \e
-.D1 -S domain_name_servers=192.168.0.1 \e
-.D1 eth0
 .It Fl T, Fl Fl test
 On receipt of DHCP messages just call
 .Pa @SCRIPT@
@@ -572,6 +572,10 @@ which is a space or comma separated list of patterns passed to
 If the same interface is matched in
 .Fl Z , Fl Fl denyinterfaces
 then it is still denied.
+.It Fl Fl nodev
+Don't load any
+.Pa /dev
+management modules.
 .El
 .Sh 3RDPARTY LINK MANAGEMENT
 Some interfaces require configuration by 3rd parties, such as PPP or VPN.
@@ -600,6 +604,9 @@ If you always use the same options, put them here.
 Text file that holds the DUID used to identify the host.
 .It Pa @SCRIPT@
 Bourne shell script that is run to configure or de-configure an interface.
+.It Pa @LIBDIR@/dhcpcd/dev
+.Pa /dev
+management modules.
 .It Pa @HOOKDIR@
 A directory containing bourne shell scripts that are run by the above script.
 Each script can be disabled by using the
index f94b2d4fc14dfcbdb502ef24c12c77552aded3f0..54fab9a39779e95399c4c3be8f17b60656e9d112 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -54,6 +54,7 @@ const char copyright[] = "Copyright (c) 2006-2013 Roy Marples";
 #include "config.h"
 #include "common.h"
 #include "control.h"
+#include "dev.h"
 #include "dhcpcd.h"
 #include "dhcp6.h"
 #include "eloop.h"
@@ -158,6 +159,7 @@ cleanup(void)
        free(ifdv);
 #endif
 
+       dev_stop();
        if (linkfd != -1)
                close(linkfd);
        if (pidfd > -1) {
@@ -1210,6 +1212,11 @@ main(int argc, char **argv)
        if (ifc == 1)
                options |= DHCPCD_WAITIP;
 
+       /* Start any dev listening plugin which may want to
+        * change the interface name provided by the kernel */
+       if (options & DHCPCD_DEV)
+               dev_start(dev_load);
+
        /* RTM_NEWADDR goes through the link socket as well which we
         * need for IPv6 DAD, so we check for DHCPCD_LINK in handle_carrier
         * instead.
index 08404125696d08be01c9d4030b27a22b5d659409..9f6e083ee705ad0564589b10647f319372fbbc0f 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd September 7, 2013
+.Dd September 12, 2013
 .Dt DHCPCD.CONF 5 SMM
 .Os
 .Sh NAME
@@ -90,6 +90,13 @@ such as FireWire and InfiniBand.
 In most cases,
 .Nm dhcpcd
 will set this automatically.
+.It Ic dev Ar value
+Load the
+.Ar value
+.Pa /dev
+management module.
+.Nm dhcpcd
+will load the first one found to work, if any.
 .It Ic env Ar value
 Push
 .Ar value
@@ -263,6 +270,10 @@ alongside.
 .It Ic noarp
 Don't send any ARP requests.
 This also disables IPv4LL.
+.It Ic nodev
+Don't load
+.Pa /dev
+management modules.
 .It Ic nogateway
 Don't install any default routes.
 .It Ic nohook Ar script
index ddbfc0edce53526e5ed6fa2fca8140ba1e40579a..4fad0a72f312c2f0f40b7460b5c7a2ca1285d075 100644 (file)
 
 #include "config.h"
 #include "common.h"
+#include "dev.h"
 #include "dhcp.h"
 #include "ipv4.h"
 #include "ipv6.h"
 #include "net.h"
-#ifdef LIBUDEV
-#include "dev/udev.h"
-#endif
 
 static int sock_fd;
 static struct sockaddr_nl sock_nl;
@@ -145,14 +143,6 @@ open_link_socket(void)
 {
        struct sockaddr_nl snl;
 
-#ifdef LIBUDEV
-       /* If we have libudev, we need to listen to it for interface
-        * arrivals and departures so we get the interface name udev wants
-        * to give it.
-        * If we fail to work, we fall back to listening to the kernel. */
-       libudev_start();
-#endif
-
        memset(&snl, 0, sizeof(snl));
        snl.nl_groups = RTMGRP_LINK;
 
@@ -423,12 +413,9 @@ handle_rename(unsigned int ifindex, const char *ifname)
        TAILQ_FOREACH(ifp, ifaces, next) {
                if (ifp->index == ifindex && strcmp(ifp->name, ifname)) {
                        handle_interface(-1, ifp->name);
-#ifdef LIBUDEV
-                       /* Let udev announce the interface for renaming */
-                       if (libudev_listening())
-                               return 1;
-#endif
-                       handle_interface(1, ifname);
+                       /* Let dev announce the interface for renaming */
+                       if (!dev_listening())
+                               handle_interface(1, ifname);
                        return 1;
                }
        }
@@ -505,12 +492,10 @@ link_netlink(struct nlmsghdr *nlm)
        /* Check for a new interface */
        ifp = find_interface(ifn);
        if (ifp == NULL) {
-#ifdef LIBUDEV
-               /* Let udev announce the interface for renaming */
-               if (libudev_listening())
-                       return 1;
-#endif
-               handle_interface(1, ifn);
+               /* If are listening to a dev manager, let that announce
+                * the interface rather than the kernel. */
+               if (dev_listening() < 1)
+                       handle_interface(1, ifn);
                return 1;
        }
 
index 858fad963740a96d5f422dc70d9ad62ffaeca690..97d1e12e7a459dff3923d8ab7fe6af3734f64f7b 100644 (file)
@@ -68,6 +68,10 @@ unsigned long long options = 0;
 #define O_IA_TA                        O_BASE + 11
 #define O_IA_PD                        O_BASE + 12
 #define O_HOSTNAME_SHORT       O_BASE + 13
+#define O_DEV                  O_BASE + 14
+#define O_NODEV                        O_BASE + 15
+
+char *dev_load;
 
 const struct option cf_options[] = {
        {"background",      no_argument,       NULL, 'b'},
@@ -130,6 +134,8 @@ const struct option cf_options[] = {
        {"ia_ta",           no_argument,       NULL, O_IA_TA},
        {"ia_pd",           no_argument,       NULL, O_IA_PD},
        {"hostname_short",  no_argument,       NULL, O_HOSTNAME_SHORT},
+       {"dev",             required_argument, NULL, O_DEV},
+       {"nodev",           no_argument,       NULL, O_NODEV},
        {NULL,              0,                 NULL, '\0'}
 };
 
@@ -1089,10 +1095,18 @@ got_iaid:
                        }
                }
                break;
+#endif
        case O_HOSTNAME_SHORT:
                ifo->options |= DHCPCD_HOSTNAME | DHCPCD_HOSTNAME_SHORT;
                break;
-#endif
+       case O_DEV:
+               if (dev_load)
+                       free(dev_load);
+               dev_load = strdup(arg);
+               break;
+       case O_NODEV:
+               ifo->options &= ~DHCPCD_DEV;
+               break;
        default:
                return 0;
        }
@@ -1184,6 +1198,9 @@ read_config(const char *file,
                return NULL;
        }
        ifo->options |= DHCPCD_DAEMONISE | DHCPCD_LINK;
+#ifdef PLUGIN_DEV
+       ifo->options |= DHCPCD_DEV;
+#endif
 #ifdef INET
        ifo->options |= DHCPCD_IPV4 | DHCPCD_IPV4LL;
        ifo->options |= DHCPCD_GATEWAY | DHCPCD_ARP;
index 69c7200a35df62dd977a30a768ba590c13e31bb5..80bb59021946374d7ec9571056ebf1c8ba4bcb20 100644 (file)
@@ -96,6 +96,7 @@
 #define DHCPCD_EXITING                 (1ULL << 44)
 #define DHCPCD_WAITIP4                 (1ULL << 45)
 #define DHCPCD_WAITIP6                 (1ULL << 46)
+#define DHCPCD_DEV                     (1ULL << 47)
 
 extern const struct option cf_options[];
 
@@ -158,6 +159,7 @@ struct if_options {
 };
 
 extern unsigned long long options;
+extern char *dev_load;
 
 struct if_options *read_config(const char *,
     const char *, const char *, const char *);
diff --git a/net.c b/net.c
index cbdde113c5ad718622e03600535c6c2f7943fe97..c3191f5cb11097f179029eb5b5f469362b1f9c12 100644 (file)
--- a/net.c
+++ b/net.c
 
 #include "config.h"
 #include "common.h"
+#include "dev.h"
 #include "dhcp.h"
 #include "dhcp6.h"
 #include "if-options.h"
 #include "ipv4.h"
 #include "ipv6nd.h"
 #include "net.h"
-#ifdef LIBUDEV
-#include "dev/udev.h"
-#endif
 
 int socket_afnet = -1;
 
@@ -270,10 +268,9 @@ discover_interfaces(int argc, char * const *argv)
 #endif
                }
 
-#ifdef LIBUDEV
-               if (!libudev_settled(ifa->ifa_name))
+               /* Ensure that the interface name has settled */
+               if (!dev_settled(ifa->ifa_name))
                        continue;
-#endif
 
                /* It's possible for an interface to have >1 AF_LINK.
                 * For our purposes, we use the first one. */