dev_initialized(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);
+#endif
+
if (ctx->dev == NULL)
return 1;
return ctx->dev->initialized(ifname);
dev_listening(struct dhcpcd_ctx *ctx)
{
+#ifdef PRIVSEP
+ if (ctx->options & DHCPCD_PRIVSEP &&
+ !(ctx->options & DHCPCD_PRIVSEPROOT))
+ return ps_root_dev_listening(ctx);
+#endif
+
if (ctx->dev == NULL)
return 0;
return ctx->dev->listening();
dev_stop(struct dhcpcd_ctx *ctx)
{
- dev_stop1(ctx,!(ctx->options & DHCPCD_FORKED));
+ dev_stop1(ctx, !(ctx->options & DHCPCD_FORKED));
}
static int
-dev_start2(struct dhcpcd_ctx *ctx, const char *name)
+dev_start2(struct dhcpcd_ctx *ctx, const struct dev_dhcpcd *dev_dhcpcd,
+ const char *name)
{
char file[PATH_MAX];
void *h;
void (*fptr)(struct dev *, const struct dev_dhcpcd *);
int r;
- struct dev_dhcpcd dev_dhcpcd;
snprintf(file, sizeof(file), DEVDIR "/%s", name);
h = dlopen(file, RTLD_LAZY);
dlclose(h);
return -1;
}
- dev_dhcpcd.handle_interface = &dhcpcd_handleinterface;
- fptr(ctx->dev, &dev_dhcpcd);
+ fptr(ctx->dev, dev_dhcpcd);
if (ctx->dev->start == NULL || (r = ctx->dev->start()) == -1) {
free(ctx->dev);
ctx->dev = NULL;
}
static int
-dev_start1(struct dhcpcd_ctx *ctx)
+dev_start1(struct dhcpcd_ctx *ctx, const struct dev_dhcpcd *dev_dhcpcd)
{
DIR *dp;
struct dirent *d;
}
if (ctx->dev_load)
- return dev_start2(ctx, ctx->dev_load);
+ return dev_start2(ctx, dev_dhcpcd, ctx->dev_load);
dp = opendir(DEVDIR);
if (dp == NULL) {
if (d->d_name[0] == '.')
continue;
- r = dev_start2(ctx, d->d_name);
+ r = dev_start2(ctx, dev_dhcpcd, d->d_name);
if (r != -1)
break;
}
}
int
-dev_start(struct dhcpcd_ctx *ctx)
+dev_start(struct dhcpcd_ctx *ctx, int (*handler)(void *, int, const char *))
{
+ struct dev_dhcpcd dev_dhcpcd = {
+ .handle_interface = handler,
+ };
if (ctx->dev_fd != -1) {
logerrx("%s: already started on fd %d", __func__, ctx->dev_fd);
return ctx->dev_fd;
}
- ctx->dev_fd = dev_start1(ctx);
+ ctx->dev_fd = dev_start1(ctx, &dev_dhcpcd);
if (ctx->dev_fd != -1) {
if (eloop_event_add(ctx->eloop, ctx->dev_fd,
dev_handle_data, ctx) == -1)
#include "dhcpcd.h"
int dev_initialized(struct dhcpcd_ctx *, const char *);
int dev_listening(struct dhcpcd_ctx *);
-int dev_start(struct dhcpcd_ctx *);
+int dev_start(struct dhcpcd_ctx *, int (*)(void *, int, const char *));
void dev_stop(struct dhcpcd_ctx *);
#else
#define dev_initialized(a, b) (1)
/* Start any dev listening plugin which may want to
* change the interface name provided by the kernel */
- if ((ctx.options & (DHCPCD_MASTER | DHCPCD_DEV)) ==
+ if (!IN_PRIVSEP(&ctx) &&
+ (ctx.options & (DHCPCD_MASTER | DHCPCD_DEV)) ==
(DHCPCD_MASTER | DHCPCD_DEV))
- dev_start(&ctx);
+ dev_start(&ctx, dhcpcd_handleinterface);
setproctitle("%s%s%s",
ctx.options & DHCPCD_MASTER ? "[master]" : argv[optind],
#include <unistd.h>
#include "common.h"
+#include "dev.h"
#include "dhcpcd.h"
#include "dhcp6.h"
#include "eloop.h"
case PS_IP6FORWARDING:
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);
logerr(__func__);
}
+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)
{
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;
}
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;
}
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
ssize_t ps_root_writepathuint(struct dhcpcd_ctx *, const char *, unsigned int);
#endif
+#ifdef PLUGIN_DEV
+int ps_root_dev_initialized(struct dhcpcd_ctx *, const char *);
+int ps_root_dev_listening(struct dhcpcd_ctx *);
+#endif
+
#endif
#include "arp.h"
#include "common.h"
#include "control.h"
+#include "dev.h"
#include "dhcp.h"
#include "dhcp6.h"
#include "eloop.h"
logdebugx("process %d stopping", getpid());
#endif
ps_free(ctx);
+ dev_stop(ctx);
eloop_exit(ctx->eloop, len != -1 ? EXIT_SUCCESS : EXIT_FAILURE);
return len;
}
#define PS_IP6FORWARDING 0x0104
#define PS_GETIFADDRS 0x0105
+/* Dev Commands */
+#define PS_DEV_LISTENING 0x0201
+#define PS_DEV_INITTED 0x0202
+#define PS_DEV_IFCMD 0x0203
+
+/* Dev Interface Commands (via flags) */
+#define PS_DEV_IFADDED 0x0001
+#define PS_DEV_IFREMOVED 0x0002
+#define PS_DEV_IFUPDATED 0x0003
+
/* Process commands */
#define PS_START 0x4000
#define PS_STOP 0x8000