diff options
author | Roy Marples <roy@marples.name> | 2020-05-10 12:19:59 +0100 |
---|---|---|
committer | Roy Marples <roy@marples.name> | 2020-05-10 12:19:59 +0100 |
commit | 82d7c0bc10c09e0fb5ae4df1eeaede78377d1c8b (patch) | |
tree | cb279ed101c8eed6c078d41b1bdfe75b514c2aef | |
parent | 6c1e0dbd92be10ba63fac479e545c95dd983ea26 (diff) | |
download | dhcpcd-82d7c0bc10c09e0fb5ae4df1eeaede78377d1c8b.tar.xz |
privsep: Add function for indirect ioctl
-rw-r--r-- | src/privsep-bsd.c | 47 | ||||
-rw-r--r-- | src/privsep-root.h | 2 | ||||
-rw-r--r-- | src/privsep.h | 3 |
3 files changed, 45 insertions, 7 deletions
diff --git a/src/privsep-bsd.c b/src/privsep-bsd.c index b64040d6..1a105b63 100644 --- a/src/privsep-bsd.c +++ b/src/privsep-bsd.c @@ -29,6 +29,7 @@ #include <sys/ioctl.h> #include <errno.h> +#include <string.h> #include <unistd.h> #include "dhcpcd.h" @@ -41,12 +42,30 @@ ps_root_doioctldom(int domain, unsigned long req, void *data, size_t len) int s, err; s = socket(domain, SOCK_DGRAM, 0); - if (s != -1) - err = ioctl(s, req, data, len); - else - err = -1; - if (s != -1) - close(s); + if (s == -1) + return -1; + err = ioctl(s, req, data, len); + close(s); + return err; +} + +static ssize_t +ps_root_doindirectioctl(unsigned long req, void *data, size_t len) +{ + char *p = data; + struct ifreq ifr = { .ifr_flags = 0 }; + ssize_t err; + + if (len < IFNAMSIZ) { + errno = EINVAL; + return -1; + } + + strlcpy(ifr.ifr_name, p, IFNAMSIZ); + ifr.ifr_data = p + IFNAMSIZ; + err = ps_root_doioctldom(PF_INET, req, &ifr, sizeof(ifr)); + if (err != -1) + memmove(data, ifr.ifr_data, len - IFNAMSIZ); return err; } @@ -78,6 +97,8 @@ ps_root_os(struct ps_msghdr *psm, struct msghdr *msg) return ps_root_doioctldom(PF_LINK, psm->ps_flags, data, len); case PS_IOCTL6: return ps_root_doioctldom(PF_INET6, psm->ps_flags, data, len); + case PS_IOCTLINDIRECT: + return ps_root_doindirectioctl(psm->ps_flags, data, len); case PS_ROUTE: return ps_root_doroute(data, len); default: @@ -114,6 +135,20 @@ ps_root_ioctl6(struct dhcpcd_ctx *ctx, unsigned long request, } ssize_t +ps_root_indirectioctl(struct dhcpcd_ctx *ctx, unsigned long request, + const char *ifname, void *data, size_t len) +{ + char buf[PS_BUFLEN]; + + strlcpy(buf, ifname, IFNAMSIZ); + memcpy(buf + IFNAMSIZ, data, len); + if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_IOCTLINDIRECT, + request, buf, IFNAMSIZ + len) == -1) + return -1; + return ps_root_readerror(ctx, data, len); +} + +ssize_t ps_root_route(struct dhcpcd_ctx *ctx, void *data, size_t len) { diff --git a/src/privsep-root.h b/src/privsep-root.h index 46608792..27a481a6 100644 --- a/src/privsep-root.h +++ b/src/privsep-root.h @@ -44,6 +44,8 @@ ssize_t ps_root_os(struct ps_msghdr *, struct msghdr *); ssize_t ps_root_route(struct dhcpcd_ctx *, void *, size_t); ssize_t ps_root_ioctllink(struct dhcpcd_ctx *, unsigned long, void *, size_t); ssize_t ps_root_ioctl6(struct dhcpcd_ctx *, unsigned long, void *, size_t); +ssize_t ps_root_indirectioctl(struct dhcpcd_ctx *, unsigned long, const char *, + void *, size_t); #endif #ifdef __linux__ ssize_t ps_root_sendnetlink(struct dhcpcd_ctx *, int, struct msghdr *); diff --git a/src/privsep.h b/src/privsep.h index cb16ac1f..9d156e9e 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -52,9 +52,10 @@ /* BSD Commands */ #define PS_IOCTLLINK 0x15 #define PS_IOCTL6 0x16 +#define PS_IOCTLINDIRECT 0x17 /* Linux commands */ -#define PS_WRITEPATHUINT 0x17 +#define PS_WRITEPATHUINT 0x18 #define PS_DELETE 0x20 #define PS_START 0x40 |