summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-09-19 14:40:50 +0100
committerRoy Marples <roy@marples.name>2020-09-19 14:40:50 +0100
commit1efd31813fde826b000fbc40234ea89979ef73a8 (patch)
treeff8f26cb8e5a13f34ebc319fe107e0ce4d77afbe
parent11963d2088a68a18ea61f27584a9339cd0292cac (diff)
downloaddhcpcd-1efd31813fde826b000fbc40234ea89979ef73a8.tar.xz
Linux: detect network namespace and deny udev in one
udev says whether an interface name is stable or not. In a network namespace, udev claims the interface does not exist. This makes sense because udev only operates in the root namespace. As such disable udev in a network namespace. While here correctly spell initialise.
-rw-r--r--src/dev.c6
-rw-r--r--src/dev.h4
-rw-r--r--src/dev/udev.c11
-rw-r--r--src/dhcpcd.h4
-rw-r--r--src/if-linux.c36
-rw-r--r--src/if.c5
-rw-r--r--src/if.h1
-rw-r--r--src/privsep-root.c4
-rw-r--r--src/privsep-root.h2
9 files changed, 61 insertions, 12 deletions
diff --git a/src/dev.c b/src/dev.c
index f7da67e4..8f14bf6b 100644
--- a/src/dev.c
+++ b/src/dev.c
@@ -39,18 +39,18 @@
#include "logerr.h"
int
-dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname)
+dev_initialised(struct dhcpcd_ctx *ctx, const char *ifname)
{
#ifdef PRIVSEP
if (ctx->options & DHCPCD_PRIVSEP &&
!(ctx->options & DHCPCD_PRIVSEPROOT))
- return ps_root_dev_initialized(ctx, ifname);
+ return ps_root_dev_initialised(ctx, ifname);
#endif
if (ctx->dev == NULL)
return 1;
- return ctx->dev->initialized(ifname);
+ return ctx->dev->initialised(ifname);
}
int
diff --git a/src/dev.h b/src/dev.h
index d51cbbec..3bfb5729 100644
--- a/src/dev.h
+++ b/src/dev.h
@@ -31,7 +31,7 @@
// dev plugin setup
struct dev {
const char *name;
- int (*initialized)(const char *);
+ int (*initialised)(const char *);
int (*listening)(void);
int (*handle_device)(void *);
int (*start)(void);
@@ -47,7 +47,7 @@ int dev_init(struct dev *, const struct dev_dhcpcd *);
// hooks for dhcpcd
#ifdef PLUGIN_DEV
#include "dhcpcd.h"
-int dev_initialized(struct dhcpcd_ctx *, const char *);
+int dev_initialised(struct dhcpcd_ctx *, const char *);
int dev_listening(struct dhcpcd_ctx *);
int dev_start(struct dhcpcd_ctx *, int (*)(void *, int, const char *));
void dev_stop(struct dhcpcd_ctx *);
diff --git a/src/dev/udev.c b/src/dev/udev.c
index 4fe7dde4..fefdefb2 100644
--- a/src/dev/udev.c
+++ b/src/dev/udev.c
@@ -39,6 +39,7 @@
#include "../common.h"
#include "../dev.h"
+#include "../if.h"
#include "../logerr.h"
static const char udev_name[] = "udev";
@@ -55,7 +56,7 @@ udev_listening(void)
}
static int
-udev_initialized(const char *ifname)
+udev_initialised(const char *ifname)
{
struct udev_device *device;
int r;
@@ -120,8 +121,14 @@ udev_stop(void)
static int
udev_start(void)
{
+ char netns[PATH_MAX];
int fd;
+ if (if_getnetworknamespace(netns, sizeof(netns)) != NULL) {
+ logdebugx("udev does not work in a network namespace");
+ return -1;
+ }
+
if (udev) {
logerrx("udev: already started");
return -1;
@@ -167,7 +174,7 @@ dev_init(struct dev *dev, const struct dev_dhcpcd *dev_dhcpcd)
{
dev->name = udev_name;
- dev->initialized = udev_initialized;
+ dev->initialised = udev_initialised;
dev->listening = udev_listening;
dev->handle_device = udev_handle_device;
dev->stop = udev_stop;
diff --git a/src/dhcpcd.h b/src/dhcpcd.h
index 03449e58..0cf774ce 100644
--- a/src/dhcpcd.h
+++ b/src/dhcpcd.h
@@ -254,6 +254,10 @@ struct dhcpcd_ctx {
struct dev *dev;
void *dev_handle;
#endif
+
+#ifdef __linux__
+ char netns[PATH_MAX];
+#endif
};
#ifdef USE_SIGNALS
diff --git a/src/if-linux.c b/src/if-linux.c
index 8d87d748..759b878e 100644
--- a/src/if-linux.c
+++ b/src/if-linux.c
@@ -60,6 +60,7 @@
#include <linux/if_arp.h>
#endif
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
@@ -144,6 +145,7 @@ struct priv {
int route_fd;
int generic_fd;
uint32_t route_pid;
+ char netns[PATH_MAX];
};
/* We need this to send a broadcast for InfiniBand.
@@ -383,6 +385,36 @@ if_linksocket(struct sockaddr_nl *nl, int protocol, int flags)
return fd;
}
+char *
+if_getnetworknamespace(char *buf, size_t len)
+{
+ struct stat sb_self, sb_netns;
+ DIR *dir;
+ struct dirent *de;
+ char file[PATH_MAX], *bufp = NULL;
+
+ if (stat("/proc/self/ns/net", &sb_self) == -1)
+ return NULL;
+
+ dir = opendir("/var/run/netns");
+ if (dir == NULL)
+ return NULL;
+
+ while ((de = readdir(dir)) != NULL) {
+ snprintf(file, sizeof(file), "/var/run/netns/%s", de->d_name);
+ if (stat(file, &sb_netns) == -1)
+ continue;
+ if (sb_self.st_dev != sb_netns.st_dev &&
+ sb_self.st_ino != sb_netns.st_ino)
+ continue;
+ strlcpy(buf, de->d_name, len);
+ bufp = buf;
+ break;
+ }
+ closedir(dir);
+ return bufp;
+}
+
int
if_opensockets_os(struct dhcpcd_ctx *ctx)
{
@@ -433,6 +465,9 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
if (priv->generic_fd == -1)
return -1;
+ if (if_getnetworknamespace(ctx->netns, sizeof(ctx->netns)) != NULL)
+ logdebugx("network namespace: %s", ctx->netns);
+
return 0;
}
@@ -1614,7 +1649,6 @@ if_initrt(struct dhcpcd_ctx *ctx, rb_tree_t *kroutes, int af)
&_if_initrt, kroutes);
}
-
#ifdef INET
/* Linux is a special snowflake when it comes to BPF. */
const char *bpf_name = "Packet Socket";
diff --git a/src/if.c b/src/if.c
index 40fdadcf..cb407e19 100644
--- a/src/if.c
+++ b/src/if.c
@@ -519,8 +519,11 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
#ifdef PLUGIN_DEV
/* Ensure that the interface name has settled */
- if (!dev_initialized(ctx, spec.devname))
+ if (!dev_initialised(ctx, spec.devname)) {
+ logdebugx("%s: waiting for interface to initialise",
+ spec.devname);
continue;
+ }
#endif
if (if_vimaster(ctx, spec.devname) == 1) {
diff --git a/src/if.h b/src/if.h
index e053fe5b..803f5818 100644
--- a/src/if.h
+++ b/src/if.h
@@ -191,6 +191,7 @@ int if_ignoregroup(int, const char *);
bool if_ignore(struct dhcpcd_ctx *, const char *);
int if_vimaster(struct dhcpcd_ctx *ctx, const char *);
unsigned short if_vlanid(const struct interface *);
+char * if_getnetworknamespace(char *, size_t);
int if_opensockets(struct dhcpcd_ctx *);
int if_opensockets_os(struct dhcpcd_ctx *);
void if_closesockets(struct dhcpcd_ctx *);
diff --git a/src/privsep-root.c b/src/privsep-root.c
index 1a438b67..92faec4c 100644
--- a/src/privsep-root.c
+++ b/src/privsep-root.c
@@ -570,7 +570,7 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
#endif
#ifdef PLUGIN_DEV
case PS_DEV_INITTED:
- err = dev_initialized(ctx, data);
+ err = dev_initialised(ctx, data);
break;
case PS_DEV_LISTENING:
err = dev_listening(ctx);
@@ -989,7 +989,7 @@ ps_root_getauthrdm(struct dhcpcd_ctx *ctx, uint64_t *rdm)
#ifdef PLUGIN_DEV
int
-ps_root_dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname)
+ps_root_dev_initialised(struct dhcpcd_ctx *ctx, const char *ifname)
{
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_INITTED, 0,
diff --git a/src/privsep-root.h b/src/privsep-root.h
index 5d6e1248..146622b1 100644
--- a/src/privsep-root.h
+++ b/src/privsep-root.h
@@ -67,7 +67,7 @@ ssize_t ps_root_sendnetlink(struct dhcpcd_ctx *, int, struct msghdr *);
#endif
#ifdef PLUGIN_DEV
-int ps_root_dev_initialized(struct dhcpcd_ctx *, const char *);
+int ps_root_dev_initialised(struct dhcpcd_ctx *, const char *);
int ps_root_dev_listening(struct dhcpcd_ctx *);
#endif