From 413652c1b372b0eddcb1c03ba9a89e202266f7aa Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 12 Sep 2013 15:43:20 +0000 Subject: [PATCH] Instead of linking directly to libudev, create a plugin system for /dev management. This allows dhcpcd to work even if udev removed and adds the ability to change from udev to something else in the future. --- .gitignore | 2 + Makefile | 16 ++++- Makefile.inc | 2 + README | 9 +++ configure | 30 ++++++---- defs.h | 3 + dev.c | 136 ++++++++++++++++++++++++++++++++++++++++++ dev/udev.h => dev.h | 30 ++++++++-- dev/Makefile | 42 +++++++++++++ dev/udev.c | 57 +++++++++++------- dhcpcd-hooks/Makefile | 6 +- dhcpcd.8.in | 39 +++++++----- dhcpcd.c | 7 +++ dhcpcd.conf.5.in | 13 +++- if-linux.c | 31 +++------- if-options.c | 19 +++++- if-options.h | 2 + net.c | 9 +-- 18 files changed, 364 insertions(+), 89 deletions(-) create mode 100644 dev.c rename dev/udev.h => dev.h (75%) create mode 100644 dev/Makefile diff --git a/.gitignore b/.gitignore index 89c1bd0e..7d6ba580 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ .depend *.o +*.So +*.so *.bz2 config.h config.mk diff --git a/Makefile b/Makefile index 0669cfbb..31da4f16 100644 --- 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 diff --git a/Makefile.inc b/Makefile.inc index fd7ead44..98c55d12 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -1,5 +1,7 @@ # System definitions +PICFLAG?= -fPIC + BINMODE?= 0555 NONBINMODE?= 0444 MANMODE?= ${NONBINMODE} diff --git a/README b/README index 467107cf..028d64f9 100644 --- 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. diff --git a/configure b/configure index a2c817e0..40ce65c6 100755 --- 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 <_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 a5dcf824..194f354c 100644 --- 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 index 00000000..e181dbb2 --- /dev/null +++ b/dev.c @@ -0,0 +1,136 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2013 Roy Marples + * + * 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 +#include +#include +#include +#include +#include + +#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; +} diff --git a/dev/udev.h b/dev.h similarity index 75% rename from dev/udev.h rename to dev.h index 0d785726..f56209d4 100644 --- a/dev/udev.h +++ b/dev.h @@ -24,12 +24,30 @@ * 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 index 00000000..e6b3a2cf --- /dev/null +++ b/dev/Makefile @@ -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} diff --git a/dev/udev.c b/dev/udev.c index 1eaa510c..4376b9fc 100644 --- a/dev/udev.c +++ b/dev/udev.c @@ -27,20 +27,21 @@ #define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE #include -#include #include #include #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; +} diff --git a/dhcpcd-hooks/Makefile b/dhcpcd-hooks/Makefile index c3ae1887..5982f1b7 100644 --- a/dhcpcd-hooks/Makefile +++ b/dhcpcd-hooks/Makefile @@ -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 \ diff --git a/dhcpcd.8.in b/dhcpcd.8.in index d8b6781f..0bdbc3ff 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -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 diff --git a/dhcpcd.c b/dhcpcd.c index f94b2d4f..54fab9a3 100644 --- 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. diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index 08404125..9f6e083e 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -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 diff --git a/if-linux.c b/if-linux.c index ddbfc0ed..4fad0a72 100644 --- a/if-linux.c +++ b/if-linux.c @@ -57,13 +57,11 @@ #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; } diff --git a/if-options.c b/if-options.c index 858fad96..97d1e12e 100644 --- a/if-options.c +++ b/if-options.c @@ -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; diff --git a/if-options.h b/if-options.h index 69c7200a..80bb5902 100644 --- a/if-options.h +++ b/if-options.h @@ -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 cbdde113..c3191f5c 100644 --- a/net.c +++ b/net.c @@ -67,15 +67,13 @@ #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. */ -- 2.47.3