CLOSEFROM=
GETLINE=
STRLCPY=
+UDEV=
OS=
BUILD=
HOST=
--without-getline) GETLINE=no;;
--without-strlcpy) STRLCPY=no;;
--without-posix_spawn) POSIX_SPAWN=no;;
- --without-pollts) POLLTS=xno;;
+ --without-pollts) POLLTS=no;;
--with-pollts) POLLTS=$var;;
+ --without-udev) UDEV=no;;
--serviceexists) SERVICEEXISTS=$var;;
--servicecmd) SERVICECMD=$var;;
--servicestatus) SERVICESTATUS=$var;;
;;
esac
+if [ "$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)
+fi
+if [ "$UDEV" != no -a -n "$LIBUDEV_LIBS" ]; then
+ echo "yes"
+ echo "SRCS+= dev/udev.c" >>$CONFIG_MK
+ if [ -n "$LIBUDEV_CFLAGS" ]; then
+ echo "CFLAGS+= $LIBUDEV_CFLAGS" >>$CONFIG_MK
+ fi
+ echo "CPPFLAGS+= -DLIBUDEV" >>$CONFIG_MK
+ echo "LDADD+= $LIBUDEV_LIBS" >>$CONFIG_MK
+
+ printf "Checking udev_monitor_filter_add_match_subsystem_devtype ..."
+ cat <<EOF >_udev.c
+#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
+#include <libudev.h>
+#include <stdlib.h>
+int main(void) {
+ udev_monitor_filter_add_match_subsystem_devtype(NULL, NULL, NULL);
+ return 0;
+}
+EOF
+ if $XCC $LIBUDEV_CFLAGS _udev.c -o _udev $LIBUDEV_LIBS2 2>/dev/null
+ then
+ echo "CPPFLAGS+= -DLIBUDEV_FILTER" >>$CONFIG_MK
+ echo " yes"
+ else
+ echo " no"
+ fi
+ rm -f _udev.c _udev
+elif [ "$UDEV" != no ]; then
+ echo "no"
+fi
+
if [ -z "$SERVICECMD" ]; then
printf "Checking for OpenRC ... "
if [ -x /sbin/rc-service ]; then
--- /dev/null
+/*
+ * 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.
+ */
+
+#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"
+
+static struct udev_monitor *monitor;
+
+static void
+libudev_handledata(__unused void *arg)
+{
+ struct udev_device *device;
+ const char *ifname, *action;
+
+ device = udev_monitor_receive_device(monitor);
+ if (device == NULL) {
+ syslog(LOG_DEBUG, "libudev: received NULL device");
+ return;
+ }
+
+ /* udev filter documentation says "usually" so double check */
+ action = udev_device_get_subsystem(device);
+ if (strcmp(action, "net"))
+ return;
+
+ ifname = udev_device_get_sysname(device);
+ action = udev_device_get_action(device);
+ if (strcmp(action, "add") == 0)
+ handle_interface(1, ifname);
+ else if (strcmp(action, "remove") == 0)
+ handle_interface(-1, ifname);
+}
+
+int
+libudev_listening(void)
+{
+
+ return monitor == NULL ? 0 : 1;
+}
+
+void
+libudev_stop(void)
+{
+ struct udev *udev;
+
+ if (monitor) {
+ udev = udev_monitor_get_udev(monitor);
+ udev_unref(udev);
+ udev_monitor_unref(monitor);
+ monitor = NULL;
+ }
+}
+
+int
+libudev_start(void)
+{
+ struct udev *udev;
+ int fd;
+
+ syslog(LOG_DEBUG, "libudev: starting");
+ udev = udev_new();
+ if (udev == NULL) {
+ syslog(LOG_ERR, "udev_new: %m");
+ return -1;
+ }
+ monitor = udev_monitor_new_from_netlink(udev, "udev");
+ if (monitor == NULL) {
+ syslog(LOG_ERR, "udev_monitor_new_from_netlink: %m");
+ goto bad;
+ }
+#ifdef LIBUDEV_FILTER
+ if (udev_monitor_filter_add_match_subsystem_devtype(monitor,
+ "net", NULL) != 0)
+ {
+ syslog(LOG_ERR,
+ "udev_monitor_filter_add_match_subsystem_devtype: %m");
+ goto bad;
+ }
+#endif
+ if (udev_monitor_enable_receiving(monitor) != 0) {
+ syslog(LOG_ERR, "udev_monitor_enable_receiving: %m");
+ goto bad;
+ }
+ fd = udev_monitor_get_fd(monitor);
+ if (fd == -1) {
+ syslog(LOG_ERR, "udev_monitor_get_fd: %m");
+ goto bad;
+ }
+ if (eloop_event_add(fd, libudev_handledata, NULL) == -1) {
+ syslog(LOG_ERR, "%s: eloop_event_add: %m", __func__);
+ goto bad;
+ }
+
+ atexit(libudev_stop);
+
+ return fd;
+bad:
+
+ libudev_stop();
+ return -1;
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef LIBUDEV_H
+#define LIBUDEV_H
+
+int libudev_listening(void);
+int libudev_start(void);
+void libudev_stop(void);
+
+#endif
#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;
if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1)
return -1;
set_cloexec(fd);
+
return fd;
}
{
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;
struct ifinfomsg *ifi;
char ifn[IF_NAMESIZE + 1];
+#ifdef LIBUDEV
+ if (nlm->nlmsg_type == RTM_NEWLINK || nlm->nlmsg_type == RTM_DELLINK) {
+ if (libudev_listening())
+ return 1;
+ }
+#endif
+
len = link_route(nlm);
if (len != 0)
return len;