xref: /dflybsd-src/contrib/dhcpcd/src/privsep-bsd.c (revision 5422d4140b73a6e65966a6f40831066aa79c4714)
16e63cc1fSRoy Marples /* SPDX-License-Identifier: BSD-2-Clause */
26e63cc1fSRoy Marples /*
36e63cc1fSRoy Marples  * Privilege Separation for dhcpcd, BSD driver
480aa9461SRoy Marples  * Copyright (c) 2006-2023 Roy Marples <roy@marples.name>
56e63cc1fSRoy Marples  * All rights reserved
66e63cc1fSRoy Marples 
76e63cc1fSRoy Marples  * Redistribution and use in source and binary forms, with or without
86e63cc1fSRoy Marples  * modification, are permitted provided that the following conditions
96e63cc1fSRoy Marples  * are met:
106e63cc1fSRoy Marples  * 1. Redistributions of source code must retain the above copyright
116e63cc1fSRoy Marples  *    notice, this list of conditions and the following disclaimer.
126e63cc1fSRoy Marples  * 2. Redistributions in binary form must reproduce the above copyright
136e63cc1fSRoy Marples  *    notice, this list of conditions and the following disclaimer in the
146e63cc1fSRoy Marples  *    documentation and/or other materials provided with the distribution.
156e63cc1fSRoy Marples  *
166e63cc1fSRoy Marples  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
176e63cc1fSRoy Marples  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
186e63cc1fSRoy Marples  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
196e63cc1fSRoy Marples  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
206e63cc1fSRoy Marples  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
216e63cc1fSRoy Marples  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
226e63cc1fSRoy Marples  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
236e63cc1fSRoy Marples  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
246e63cc1fSRoy Marples  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
256e63cc1fSRoy Marples  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
266e63cc1fSRoy Marples  * SUCH DAMAGE.
276e63cc1fSRoy Marples  */
286e63cc1fSRoy Marples 
296e63cc1fSRoy Marples #include <sys/ioctl.h>
3080aa9461SRoy Marples #include <sys/types.h>
3180aa9461SRoy Marples #include <sys/sysctl.h>
326e63cc1fSRoy Marples 
33d4fb1e02SRoy Marples /* Need these for filtering the ioctls */
340a68f8d2SRoy Marples #include <arpa/inet.h>
35d4fb1e02SRoy Marples #include <net/if.h>
360a68f8d2SRoy Marples #include <netinet/if_ether.h>
37d4fb1e02SRoy Marples #include <netinet/in.h>
38d4fb1e02SRoy Marples #include <netinet6/in6_var.h>
39d4fb1e02SRoy Marples #include <netinet6/nd6.h>
400a68f8d2SRoy Marples #ifdef __NetBSD__
410a68f8d2SRoy Marples #include <netinet/if_ether.h>
420a68f8d2SRoy Marples #include <net/if_vlanvar.h> /* Needs netinet/if_ether.h */
430a68f8d2SRoy Marples #elif defined(__DragonFly__)
440a68f8d2SRoy Marples #include <net/vlan/if_vlan_var.h>
450a68f8d2SRoy Marples #else
460a68f8d2SRoy Marples #include <net/if_vlan_var.h>
470a68f8d2SRoy Marples #endif
48d4fb1e02SRoy Marples #ifdef __DragonFly__
49d4fb1e02SRoy Marples #  include <netproto/802_11/ieee80211_ioctl.h>
50d4fb1e02SRoy Marples #else
51d4fb1e02SRoy Marples #  include <net80211/ieee80211.h>
52d4fb1e02SRoy Marples #  include <net80211/ieee80211_ioctl.h>
53d4fb1e02SRoy Marples #endif
54d4fb1e02SRoy Marples 
556e63cc1fSRoy Marples #include <errno.h>
5680aa9461SRoy Marples #include <stdlib.h>
57d4fb1e02SRoy Marples #include <string.h>
586e63cc1fSRoy Marples #include <unistd.h>
596e63cc1fSRoy Marples 
606e63cc1fSRoy Marples #include "dhcpcd.h"
6180aa9461SRoy Marples #include "if.h"
626e63cc1fSRoy Marples #include "logerr.h"
636e63cc1fSRoy Marples #include "privsep.h"
646e63cc1fSRoy Marples 
656e63cc1fSRoy Marples static ssize_t
ps_root_doioctldom(struct dhcpcd_ctx * ctx,int domain,unsigned long req,void * data,size_t len)6680aa9461SRoy Marples ps_root_doioctldom(struct dhcpcd_ctx *ctx, int domain, unsigned long req, void *data, size_t len)
676e63cc1fSRoy Marples {
6880aa9461SRoy Marples #if defined(INET6) || (defined(SIOCALIFADDR) && defined(IFLR_ACTIVE))
6980aa9461SRoy Marples 	struct priv *priv = (struct priv *)ctx->priv;
7080aa9461SRoy Marples #endif
7180aa9461SRoy Marples 	int s;
7280aa9461SRoy Marples 
7380aa9461SRoy Marples 	switch(domain) {
7480aa9461SRoy Marples #ifdef INET
7580aa9461SRoy Marples 	case PF_INET:
7680aa9461SRoy Marples 		s = ctx->pf_inet_fd;
7780aa9461SRoy Marples 		break;
7880aa9461SRoy Marples #endif
7980aa9461SRoy Marples #ifdef INET6
8080aa9461SRoy Marples 	case PF_INET6:
8180aa9461SRoy Marples 		s = priv->pf_inet6_fd;
8280aa9461SRoy Marples 		break;
8380aa9461SRoy Marples #endif
8480aa9461SRoy Marples #if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */
8580aa9461SRoy Marples 	case PF_LINK:
8680aa9461SRoy Marples 		s = priv->pf_link_fd;
8780aa9461SRoy Marples 		break;
8880aa9461SRoy Marples #endif
8980aa9461SRoy Marples 	default:
9080aa9461SRoy Marples 		errno = EPFNOSUPPORT;
9180aa9461SRoy Marples 		return -1;
9280aa9461SRoy Marples 	}
936e63cc1fSRoy Marples 
94d4fb1e02SRoy Marples 	/* Only allow these ioctls */
95d4fb1e02SRoy Marples 	switch(req) {
96a0d9933aSRoy Marples #ifdef SIOCGIFDATA
97a0d9933aSRoy Marples 	case SIOCGIFDATA:	/* FALLTHROUGH */
98a0d9933aSRoy Marples #endif
99acd7a309SRoy Marples #ifdef SIOCG80211NWID
100acd7a309SRoy Marples 	case SIOCG80211NWID:	/* FALLTHROUGH */
101acd7a309SRoy Marples #endif
102acd7a309SRoy Marples #ifdef SIOCGETVLAN
103acd7a309SRoy Marples 	case SIOCGETVLAN:	/* FALLTHROUGH */
104acd7a309SRoy Marples #endif
105d4fb1e02SRoy Marples #ifdef SIOCIFAFATTACH
106d4fb1e02SRoy Marples 	case SIOCIFAFATTACH:	/* FALLTHROUGH */
107d4fb1e02SRoy Marples #endif
108d4fb1e02SRoy Marples #ifdef SIOCSIFXFLAGS
109d4fb1e02SRoy Marples 	case SIOCSIFXFLAGS:	/* FALLTHROUGH */
110d4fb1e02SRoy Marples #endif
111d4fb1e02SRoy Marples #ifdef SIOCSIFINFO_FLAGS
112d4fb1e02SRoy Marples 	case SIOCSIFINFO_FLAGS:	/* FALLTHROUGH */
113d4fb1e02SRoy Marples #endif
114d4fb1e02SRoy Marples #ifdef SIOCSRTRFLUSH_IN6
115d4fb1e02SRoy Marples 	case SIOCSRTRFLUSH_IN6:	/* FALLTHROUGH */
116d4fb1e02SRoy Marples 	case SIOCSPFXFLUSH_IN6: /* FALLTHROUGH */
117d4fb1e02SRoy Marples #endif
118d4fb1e02SRoy Marples #if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE)
119d4fb1e02SRoy Marples 	case SIOCALIFADDR:	/* FALLTHROUGH */
120d4fb1e02SRoy Marples 	case SIOCDLIFADDR:	/* FALLTHROUGH */
121d4fb1e02SRoy Marples #else
122d4fb1e02SRoy Marples 	case SIOCSIFLLADDR:	/* FALLTHROUGH */
123d4fb1e02SRoy Marples #endif
124d4fb1e02SRoy Marples #ifdef SIOCSIFINFO_IN6
125d4fb1e02SRoy Marples 	case SIOCSIFINFO_IN6:	/* FALLTHROUGH */
126d4fb1e02SRoy Marples #endif
127d4fb1e02SRoy Marples 	case SIOCAIFADDR_IN6:	/* FALLTHROUGH */
128acd7a309SRoy Marples 	case SIOCDIFADDR_IN6:
129d4fb1e02SRoy Marples 		break;
130d4fb1e02SRoy Marples 	default:
131d4fb1e02SRoy Marples 		errno = EPERM;
132d4fb1e02SRoy Marples 		return -1;
133d4fb1e02SRoy Marples 	}
134d4fb1e02SRoy Marples 
13580aa9461SRoy Marples 	return ioctl(s, req, data, len);
1366e63cc1fSRoy Marples }
1376e63cc1fSRoy Marples 
1386e63cc1fSRoy Marples static ssize_t
ps_root_doroute(struct dhcpcd_ctx * ctx,void * data,size_t len)13980aa9461SRoy Marples ps_root_doroute(struct dhcpcd_ctx *ctx, void *data, size_t len)
1406e63cc1fSRoy Marples {
1416e63cc1fSRoy Marples 
14280aa9461SRoy Marples 	return write(ctx->link_fd, data, len);
1436e63cc1fSRoy Marples }
1446e63cc1fSRoy Marples 
145a0d9933aSRoy Marples #if defined(HAVE_CAPSICUM) || defined(HAVE_PLEDGE)
146d4fb1e02SRoy Marples static ssize_t
ps_root_doindirectioctl(struct dhcpcd_ctx * ctx,unsigned long req,void * data,size_t len)14780aa9461SRoy Marples ps_root_doindirectioctl(struct dhcpcd_ctx *ctx,
14880aa9461SRoy Marples     unsigned long req, void *data, size_t len)
149d4fb1e02SRoy Marples {
150d4fb1e02SRoy Marples 	char *p = data;
151d4fb1e02SRoy Marples 	struct ifreq ifr = { .ifr_flags = 0 };
152d4fb1e02SRoy Marples 
153acd7a309SRoy Marples 	/* ioctl filtering is done in ps_root_doioctldom */
154d4fb1e02SRoy Marples 
155acd7a309SRoy Marples 	if (len < IFNAMSIZ + 1) {
156d4fb1e02SRoy Marples 		errno = EINVAL;
157d4fb1e02SRoy Marples 		return -1;
158d4fb1e02SRoy Marples 	}
159d4fb1e02SRoy Marples 
160d4fb1e02SRoy Marples 	strlcpy(ifr.ifr_name, p, IFNAMSIZ);
161acd7a309SRoy Marples 	len -= IFNAMSIZ;
162acd7a309SRoy Marples 	memmove(data, p + IFNAMSIZ, len);
163acd7a309SRoy Marples 	ifr.ifr_data = data;
164acd7a309SRoy Marples 
16580aa9461SRoy Marples 	return ps_root_doioctldom(ctx, PF_INET, req, &ifr, sizeof(ifr));
166d4fb1e02SRoy Marples }
167a0d9933aSRoy Marples #endif
1687f8103cdSRoy Marples 
169a0d9933aSRoy Marples #ifdef HAVE_PLEDGE
1707f8103cdSRoy Marples static ssize_t
ps_root_doifignoregroup(struct dhcpcd_ctx * ctx,void * data,size_t len)17180aa9461SRoy Marples ps_root_doifignoregroup(struct dhcpcd_ctx *ctx, void *data, size_t len)
1727f8103cdSRoy Marples {
1737f8103cdSRoy Marples 
1747f8103cdSRoy Marples 	if (len == 0 || ((const char *)data)[len - 1] != '\0') {
1757f8103cdSRoy Marples 		errno = EINVAL;
1767f8103cdSRoy Marples 		return -1;
1777f8103cdSRoy Marples 	}
1787f8103cdSRoy Marples 
17980aa9461SRoy Marples 	return if_ignoregroup(ctx->pf_inet_fd, data);
18080aa9461SRoy Marples }
18180aa9461SRoy Marples #endif
18280aa9461SRoy Marples 
18380aa9461SRoy Marples #ifdef HAVE_CAPSICUM
18480aa9461SRoy Marples static ssize_t
ps_root_dosysctl(unsigned long flags,void * data,size_t len,void ** rdata,size_t * rlen)18580aa9461SRoy Marples ps_root_dosysctl(unsigned long flags,
18680aa9461SRoy Marples     void *data, size_t len, void **rdata, size_t *rlen)
18780aa9461SRoy Marples {
18880aa9461SRoy Marples 	char *p = data, *e = p + len;
18980aa9461SRoy Marples 	int name[10];
19080aa9461SRoy Marples 	unsigned int namelen;
19180aa9461SRoy Marples 	void *oldp;
19280aa9461SRoy Marples 	size_t *oldlenp, oldlen, nlen;
19380aa9461SRoy Marples 	void *newp;
19480aa9461SRoy Marples 	size_t newlen;
19580aa9461SRoy Marples 	int err;
19680aa9461SRoy Marples 
19780aa9461SRoy Marples 	if (sizeof(namelen) >= len) {
19880aa9461SRoy Marples 		errno = EINVAL;
1997f8103cdSRoy Marples 		return -1;
20080aa9461SRoy Marples 	}
20180aa9461SRoy Marples 	memcpy(&namelen, p, sizeof(namelen));
20280aa9461SRoy Marples 	p += sizeof(namelen);
20380aa9461SRoy Marples 	nlen = sizeof(*name) * namelen;
20480aa9461SRoy Marples 	if (namelen > __arraycount(name)) {
20580aa9461SRoy Marples 		errno = ENOBUFS;
20680aa9461SRoy Marples 		return -1;
20780aa9461SRoy Marples 	}
20880aa9461SRoy Marples 	if (p + nlen > e) {
20980aa9461SRoy Marples 		errno = EINVAL;
21080aa9461SRoy Marples 		return -1;
21180aa9461SRoy Marples 	}
21280aa9461SRoy Marples 	memcpy(name, p, nlen);
21380aa9461SRoy Marples 	p += nlen;
21480aa9461SRoy Marples 	if (p + sizeof(oldlen) > e) {
21580aa9461SRoy Marples 		errno = EINVAL;
21680aa9461SRoy Marples 		return -1;
21780aa9461SRoy Marples 	}
21880aa9461SRoy Marples 	memcpy(&oldlen, p, sizeof(oldlen));
21980aa9461SRoy Marples 	p += sizeof(oldlen);
22080aa9461SRoy Marples 	if (p + sizeof(newlen) > e) {
22180aa9461SRoy Marples 		errno = EINVAL;
22280aa9461SRoy Marples 		return -1;
22380aa9461SRoy Marples 	}
22480aa9461SRoy Marples 	memcpy(&newlen, p, sizeof(newlen));
22580aa9461SRoy Marples 	p += sizeof(newlen);
22680aa9461SRoy Marples 	if (p + newlen > e) {
22780aa9461SRoy Marples 		errno = EINVAL;
22880aa9461SRoy Marples 		return -1;
22980aa9461SRoy Marples 	}
23080aa9461SRoy Marples 	newp = newlen ? p : NULL;
23180aa9461SRoy Marples 
23280aa9461SRoy Marples 	if (flags & PS_SYSCTL_OLEN) {
23380aa9461SRoy Marples 		*rlen = sizeof(oldlen) + oldlen;
23480aa9461SRoy Marples 		*rdata = malloc(*rlen);
23580aa9461SRoy Marples 		if (*rdata == NULL)
23680aa9461SRoy Marples 			return -1;
23780aa9461SRoy Marples 		oldlenp = (size_t *)*rdata;
23880aa9461SRoy Marples 		*oldlenp = oldlen;
23980aa9461SRoy Marples 		if (flags & PS_SYSCTL_ODATA)
24080aa9461SRoy Marples 			oldp = (char *)*rdata + sizeof(oldlen);
24180aa9461SRoy Marples 		else
24280aa9461SRoy Marples 			oldp = NULL;
24380aa9461SRoy Marples 	} else {
24480aa9461SRoy Marples 		oldlenp = NULL;
24580aa9461SRoy Marples 		oldp = NULL;
24680aa9461SRoy Marples 	}
24780aa9461SRoy Marples 
24880aa9461SRoy Marples 	err = sysctl(name, namelen, oldp, oldlenp, newp, newlen);
2497f8103cdSRoy Marples 	return err;
2507f8103cdSRoy Marples }
251d4fb1e02SRoy Marples #endif
252d4fb1e02SRoy Marples 
2536e63cc1fSRoy Marples ssize_t
ps_root_os(struct dhcpcd_ctx * ctx,struct ps_msghdr * psm,struct msghdr * msg,void ** rdata,size_t * rlen,bool * free_rdata)25480aa9461SRoy Marples ps_root_os(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg,
25580aa9461SRoy Marples     void **rdata, size_t *rlen, bool *free_rdata)
2566e63cc1fSRoy Marples {
2576e63cc1fSRoy Marples 	struct iovec *iov = msg->msg_iov;
2586e63cc1fSRoy Marples 	void *data = iov->iov_base;
2596e63cc1fSRoy Marples 	size_t len = iov->iov_len;
260acd7a309SRoy Marples 	ssize_t err;
2616e63cc1fSRoy Marples 
2626e63cc1fSRoy Marples 	switch (psm->ps_cmd) {
2636e63cc1fSRoy Marples 	case PS_IOCTLLINK:
26480aa9461SRoy Marples 		err = ps_root_doioctldom(ctx, PF_LINK, psm->ps_flags, data, len);
265acd7a309SRoy Marples 		break;
2666e63cc1fSRoy Marples 	case PS_IOCTL6:
26780aa9461SRoy Marples 		err = ps_root_doioctldom(ctx, PF_INET6, psm->ps_flags, data, len);
268acd7a309SRoy Marples 		break;
2696e63cc1fSRoy Marples 	case PS_ROUTE:
27080aa9461SRoy Marples 		return ps_root_doroute(ctx, data, len);
271a0d9933aSRoy Marples #if defined(HAVE_CAPSICUM) || defined(HAVE_PLEDGE)
272d4fb1e02SRoy Marples 	case PS_IOCTLINDIRECT:
27380aa9461SRoy Marples 		err = ps_root_doindirectioctl(ctx, psm->ps_flags, data, len);
274acd7a309SRoy Marples 		break;
275a0d9933aSRoy Marples #endif
276a0d9933aSRoy Marples #ifdef HAVE_PLEDGE
2777f8103cdSRoy Marples 	case PS_IFIGNOREGRP:
27880aa9461SRoy Marples 		return ps_root_doifignoregroup(ctx, data, len);
27980aa9461SRoy Marples #endif
28080aa9461SRoy Marples #ifdef HAVE_CAPSICUM
28180aa9461SRoy Marples 	case PS_SYSCTL:
28280aa9461SRoy Marples 		*free_rdata = true;
28380aa9461SRoy Marples 		return ps_root_dosysctl(psm->ps_flags, data, len, rdata, rlen);
28480aa9461SRoy Marples #else
28580aa9461SRoy Marples 	UNUSED(free_rdata);
286d4fb1e02SRoy Marples #endif
2876e63cc1fSRoy Marples 	default:
2886e63cc1fSRoy Marples 		errno = ENOTSUP;
2896e63cc1fSRoy Marples 		return -1;
2906e63cc1fSRoy Marples 	}
291acd7a309SRoy Marples 
292acd7a309SRoy Marples 	if (err != -1) {
293acd7a309SRoy Marples 		*rdata = data;
294acd7a309SRoy Marples 		*rlen = len;
295acd7a309SRoy Marples 	}
296acd7a309SRoy Marples 	return err;
2976e63cc1fSRoy Marples }
2986e63cc1fSRoy Marples 
2996e63cc1fSRoy Marples static ssize_t
ps_root_ioctldom(struct dhcpcd_ctx * ctx,uint16_t domain,unsigned long request,void * data,size_t len)300d4fb1e02SRoy Marples ps_root_ioctldom(struct dhcpcd_ctx *ctx, uint16_t domain, unsigned long request,
3016e63cc1fSRoy Marples     void *data, size_t len)
3026e63cc1fSRoy Marples {
3036e63cc1fSRoy Marples 
304*f3744ac9SRoy Marples 	if (ps_sendcmd(ctx, PS_ROOT_FD(ctx), domain,
3056e63cc1fSRoy Marples 	    request, data, len) == -1)
3066e63cc1fSRoy Marples 		return -1;
307d4fb1e02SRoy Marples 	return ps_root_readerror(ctx, data, len);
3086e63cc1fSRoy Marples }
3096e63cc1fSRoy Marples 
3106e63cc1fSRoy Marples ssize_t
ps_root_ioctllink(struct dhcpcd_ctx * ctx,unsigned long request,void * data,size_t len)3116e63cc1fSRoy Marples ps_root_ioctllink(struct dhcpcd_ctx *ctx, unsigned long request,
3126e63cc1fSRoy Marples     void *data, size_t len)
3136e63cc1fSRoy Marples {
3146e63cc1fSRoy Marples 
3156e63cc1fSRoy Marples 	return ps_root_ioctldom(ctx, PS_IOCTLLINK, request, data, len);
3166e63cc1fSRoy Marples }
3176e63cc1fSRoy Marples 
3186e63cc1fSRoy Marples ssize_t
ps_root_ioctl6(struct dhcpcd_ctx * ctx,unsigned long request,void * data,size_t len)3196e63cc1fSRoy Marples ps_root_ioctl6(struct dhcpcd_ctx *ctx, unsigned long request,
3206e63cc1fSRoy Marples     void *data, size_t len)
3216e63cc1fSRoy Marples {
3226e63cc1fSRoy Marples 
3236e63cc1fSRoy Marples 	return ps_root_ioctldom(ctx, PS_IOCTL6, request, data, len);
3246e63cc1fSRoy Marples }
3256e63cc1fSRoy Marples 
3266e63cc1fSRoy Marples ssize_t
ps_root_route(struct dhcpcd_ctx * ctx,void * data,size_t len)3276e63cc1fSRoy Marples ps_root_route(struct dhcpcd_ctx *ctx, void *data, size_t len)
3286e63cc1fSRoy Marples {
3296e63cc1fSRoy Marples 
330*f3744ac9SRoy Marples 	if (ps_sendcmd(ctx, PS_ROOT_FD(ctx), PS_ROUTE, 0, data, len) == -1)
3316e63cc1fSRoy Marples 		return -1;
332d4fb1e02SRoy Marples 	return ps_root_readerror(ctx, data, len);
3336e63cc1fSRoy Marples }
334d4fb1e02SRoy Marples 
335a0d9933aSRoy Marples #if defined(HAVE_CAPSICUM) || defined(HAVE_PLEDGE)
336d4fb1e02SRoy Marples ssize_t
ps_root_indirectioctl(struct dhcpcd_ctx * ctx,unsigned long request,const char * ifname,void * data,size_t len)337d4fb1e02SRoy Marples ps_root_indirectioctl(struct dhcpcd_ctx *ctx, unsigned long request,
338d4fb1e02SRoy Marples     const char *ifname, void *data, size_t len)
339d4fb1e02SRoy Marples {
340d4fb1e02SRoy Marples 	char buf[PS_BUFLEN];
341d4fb1e02SRoy Marples 
342acd7a309SRoy Marples 	if (IFNAMSIZ + len > sizeof(buf)) {
343acd7a309SRoy Marples 		errno = ENOBUFS;
344acd7a309SRoy Marples 		return -1;
345acd7a309SRoy Marples 	}
346acd7a309SRoy Marples 
347d4fb1e02SRoy Marples 	strlcpy(buf, ifname, IFNAMSIZ);
348d4fb1e02SRoy Marples 	memcpy(buf + IFNAMSIZ, data, len);
349*f3744ac9SRoy Marples 	if (ps_sendcmd(ctx, PS_ROOT_FD(ctx), PS_IOCTLINDIRECT,
350d4fb1e02SRoy Marples 	    request, buf, IFNAMSIZ + len) == -1)
351d4fb1e02SRoy Marples 		return -1;
352d4fb1e02SRoy Marples 	return ps_root_readerror(ctx, data, len);
353d4fb1e02SRoy Marples }
35480aa9461SRoy Marples #endif
3557f8103cdSRoy Marples 
35680aa9461SRoy Marples #ifdef HAVE_PLEDGE
3577f8103cdSRoy Marples ssize_t
ps_root_ifignoregroup(struct dhcpcd_ctx * ctx,const char * ifname)3587f8103cdSRoy Marples ps_root_ifignoregroup(struct dhcpcd_ctx *ctx, const char *ifname)
3597f8103cdSRoy Marples {
3607f8103cdSRoy Marples 
361*f3744ac9SRoy Marples 	if (ps_sendcmd(ctx, PS_ROOT_FD(ctx), PS_IFIGNOREGRP, 0,
3627f8103cdSRoy Marples 	    ifname, strlen(ifname) + 1) == -1)
3637f8103cdSRoy Marples 		return -1;
3647f8103cdSRoy Marples 	return ps_root_readerror(ctx, NULL, 0);
3657f8103cdSRoy Marples }
366d4fb1e02SRoy Marples #endif
36780aa9461SRoy Marples 
36880aa9461SRoy Marples #ifdef HAVE_CAPSICUM
36980aa9461SRoy Marples ssize_t
ps_root_sysctl(struct dhcpcd_ctx * ctx,const int * name,unsigned int namelen,void * oldp,size_t * oldlenp,const void * newp,size_t newlen)37080aa9461SRoy Marples ps_root_sysctl(struct dhcpcd_ctx *ctx,
37180aa9461SRoy Marples     const int *name, unsigned int namelen,
37280aa9461SRoy Marples     void *oldp, size_t *oldlenp, const void *newp, size_t newlen)
37380aa9461SRoy Marples {
37480aa9461SRoy Marples 	char buf[PS_BUFLEN], *p = buf;
37580aa9461SRoy Marples 	unsigned long flags = 0;
37680aa9461SRoy Marples 	size_t olen = (oldp && oldlenp) ? *oldlenp : 0, nolen;
37780aa9461SRoy Marples 
37880aa9461SRoy Marples 	if (sizeof(namelen) + (sizeof(*name) * namelen) +
37980aa9461SRoy Marples 	    sizeof(oldlenp) +
38080aa9461SRoy Marples 	    sizeof(newlen) + newlen > sizeof(buf))
38180aa9461SRoy Marples 	{
38280aa9461SRoy Marples 		errno = ENOBUFS;
38380aa9461SRoy Marples 		return -1;
38480aa9461SRoy Marples 	}
38580aa9461SRoy Marples 
38680aa9461SRoy Marples 	if (oldlenp)
38780aa9461SRoy Marples 		flags |= PS_SYSCTL_OLEN;
38880aa9461SRoy Marples 	if (oldp)
38980aa9461SRoy Marples 		flags |= PS_SYSCTL_ODATA;
39080aa9461SRoy Marples 	memcpy(p, &namelen, sizeof(namelen));
39180aa9461SRoy Marples 	p += sizeof(namelen);
39280aa9461SRoy Marples 	memcpy(p, name, sizeof(*name) * namelen);
39380aa9461SRoy Marples 	p += sizeof(*name) * namelen;
39480aa9461SRoy Marples 	memcpy(p, &olen, sizeof(olen));
39580aa9461SRoy Marples 	p += sizeof(olen);
39680aa9461SRoy Marples 	memcpy(p, &newlen, sizeof(newlen));
39780aa9461SRoy Marples 	p += sizeof(newlen);
39880aa9461SRoy Marples 	if (newlen) {
39980aa9461SRoy Marples 		memcpy(p, newp, newlen);
40080aa9461SRoy Marples 		p += newlen;
40180aa9461SRoy Marples 	}
40280aa9461SRoy Marples 
403*f3744ac9SRoy Marples 	if (ps_sendcmd(ctx, PS_ROOT_FD(ctx), PS_SYSCTL,
40480aa9461SRoy Marples 	    flags, buf, (size_t)(p - buf)) == -1)
40580aa9461SRoy Marples 		return -1;
40680aa9461SRoy Marples 
40780aa9461SRoy Marples 	if (ps_root_readerror(ctx, buf, sizeof(buf)) == -1)
40880aa9461SRoy Marples 		return -1;
40980aa9461SRoy Marples 
41080aa9461SRoy Marples 	p = buf;
41180aa9461SRoy Marples 	memcpy(&nolen, p, sizeof(nolen));
41280aa9461SRoy Marples 	p += sizeof(nolen);
41380aa9461SRoy Marples 	if (oldlenp) {
41480aa9461SRoy Marples 		*oldlenp = nolen;
41580aa9461SRoy Marples 		if (oldp && nolen <= olen)
41680aa9461SRoy Marples 			memcpy(oldp, p, nolen);
41780aa9461SRoy Marples 	}
41880aa9461SRoy Marples 
41980aa9461SRoy Marples 	return 0;
42080aa9461SRoy Marples }
42180aa9461SRoy Marples #endif
422