summaryrefslogtreecommitdiffstats
path: root/src/privsep-root.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-05-24 10:30:23 +0000
committerRoy Marples <roy@marples.name>2020-05-24 10:30:23 +0000
commitf643f08e35fad9e54777b0e327c8cf768f2d82b3 (patch)
treee7847afc494da9d0ed00c6fbce96bedeb40e8e50 /src/privsep-root.c
parenta4951704171655b11c683bacff6df58da5287aa2 (diff)
downloaddhcpcd-f643f08e35fad9e54777b0e327c8cf768f2d82b3.tar.xz
privsep: Allow dev plugins to work
For udev at least, it requires a /var/run to be available in the chroot which is poor. As such, give it a full IPC.
Diffstat (limited to 'src/privsep-root.c')
-rw-r--r--src/privsep-root.c104
1 files changed, 101 insertions, 3 deletions
diff --git a/src/privsep-root.c b/src/privsep-root.c
index b4216760..6a82fb6b 100644
--- a/src/privsep-root.c
+++ b/src/privsep-root.c
@@ -44,6 +44,7 @@
#include <unistd.h>
#include "common.h"
+#include "dev.h"
#include "dhcpcd.h"
#include "dhcp6.h"
#include "eloop.h"
@@ -525,6 +526,14 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
err = ip6_forwarding(data);
break;
#endif
+#ifdef PLUGIN_DEV
+ case PS_DEV_INITTED:
+ err = dev_initialized(ctx, data);
+ break;
+ case PS_DEV_LISTENING:
+ err = dev_listening(ctx);
+ break;
+#endif
default:
err = ps_root_os(psm, msg);
break;
@@ -548,6 +557,27 @@ ps_root_recvmsg(void *arg)
}
static int
+ps_root_handleinterface(void *arg, int action, const char *ifname)
+{
+ struct dhcpcd_ctx *ctx = arg;
+ unsigned long flag;
+
+ if (action == 1)
+ flag = PS_DEV_IFADDED;
+ else if (action == -1)
+ flag = PS_DEV_IFREMOVED;
+ else if (action == 0)
+ flag = PS_DEV_IFUPDATED;
+ else {
+ errno = EINVAL;
+ return -1;
+ }
+
+ return (int)ps_sendcmd(ctx, ctx->ps_data_fd, PS_DEV_IFCMD, flag,
+ ifname, strlen(ifname) + 1);
+}
+
+static int
ps_root_startcb(void *arg)
{
struct dhcpcd_ctx *ctx = arg;
@@ -582,6 +612,12 @@ ps_root_startcb(void *arg)
return -1;
#endif
+ /* Start any dev listening plugin which may want to
+ * change the interface name provided by the kernel */
+ if ((ctx->options & (DHCPCD_MASTER | DHCPCD_DEV)) ==
+ (DHCPCD_MASTER | DHCPCD_DEV))
+ dev_start(ctx, ps_root_handleinterface);
+
return 0;
}
@@ -603,17 +639,58 @@ ps_root_signalcb(int sig, void *arg)
eloop_exit(ctx->eloop, sig == SIGTERM ? EXIT_SUCCESS : EXIT_FAILURE);
}
+int (*handle_interface)(void *, int, const char *);
+
+#ifdef PLUGIN_DEV
+static ssize_t
+ps_root_devcb(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
+{
+ int action;
+ struct iovec *iov = msg->msg_iov;
+
+ if (msg->msg_iovlen != 1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ switch(psm->ps_flags) {
+ case PS_DEV_IFADDED:
+ action = 1;
+ break;
+ case PS_DEV_IFREMOVED:
+ action = -1;
+ break;
+ case PS_DEV_IFUPDATED:
+ action = 0;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return dhcpcd_handleinterface(ctx, action, iov->iov_base);
+}
+#endif
+
static ssize_t
ps_root_dispatchcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
{
struct dhcpcd_ctx *ctx = arg;
ssize_t err;
+ switch(psm->ps_cmd) {
+#ifdef PLUGIN_DEV
+ case PS_DEV_IFCMD:
+ err = ps_root_devcb(ctx, psm, msg);
+ break;
+#endif
+ default:
+ err = ps_bpf_dispatch(ctx, psm, msg);
#ifdef INET
- err = ps_bpf_dispatch(ctx, psm, msg);
- if (err == -1 && errno == ENOTSUP)
+ if (err == -1 && errno == ENOTSUP)
#endif
- err = ps_inet_dispatch(ctx, psm, msg);
+ err = ps_inet_dispatch(ctx, psm, msg);
+ }
return err;
}
@@ -826,3 +903,24 @@ ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname)
return ps_root_readerror(ctx, NULL, 0);
}
#endif
+
+#ifdef PLUGIN_DEV
+int
+ps_root_dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname)
+{
+
+ if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_INITTED, 0,
+ ifname, strlen(ifname) + 1)== -1)
+ return -1;
+ return (int)ps_root_readerror(ctx, NULL, 0);
+}
+
+int
+ps_root_dev_listening(struct dhcpcd_ctx * ctx)
+{
+
+ if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_LISTENING, 0, NULL, 0)== -1)
+ return -1;
+ return (int)ps_root_readerror(ctx, NULL, 0);
+}
+#endif