xref: /dragonfly/contrib/dhcpcd/src/privsep-inet.c (revision 54175cef)
16e63cc1fSRoy Marples /* SPDX-License-Identifier: BSD-2-Clause */
26e63cc1fSRoy Marples /*
36e63cc1fSRoy Marples  * Privilege Separation for dhcpcd, network proxy
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/socket.h>
306e63cc1fSRoy Marples #include <sys/types.h>
316e63cc1fSRoy Marples 
32d4fb1e02SRoy Marples #include <netinet/in.h>
33d4fb1e02SRoy Marples #include <netinet/icmp6.h>
34d4fb1e02SRoy Marples 
356e63cc1fSRoy Marples #include <assert.h>
366e63cc1fSRoy Marples #include <errno.h>
376e63cc1fSRoy Marples #include <stdlib.h>
386e63cc1fSRoy Marples #include <string.h>
396e63cc1fSRoy Marples #include <unistd.h>
406e63cc1fSRoy Marples 
416e63cc1fSRoy Marples #include "arp.h"
426e63cc1fSRoy Marples #include "bpf.h"
436e63cc1fSRoy Marples #include "dhcp.h"
446e63cc1fSRoy Marples #include "dhcp6.h"
456e63cc1fSRoy Marples #include "eloop.h"
466e63cc1fSRoy Marples #include "ipv6nd.h"
476e63cc1fSRoy Marples #include "logerr.h"
486e63cc1fSRoy Marples #include "privsep.h"
496e63cc1fSRoy Marples 
50*54175cefSRoy Marples /* We expect to have open 2 SEQPACKET, 1 udp, 1 udp6 and 1 raw6 fds */
51*54175cefSRoy Marples 
526e63cc1fSRoy Marples #ifdef INET
536e63cc1fSRoy Marples static void
ps_inet_recvbootp(void * arg,unsigned short events)5480aa9461SRoy Marples ps_inet_recvbootp(void *arg, unsigned short events)
556e63cc1fSRoy Marples {
566e63cc1fSRoy Marples 	struct dhcpcd_ctx *ctx = arg;
576e63cc1fSRoy Marples 
58f3744ac9SRoy Marples 	if (ps_recvmsg(ctx->udp_rfd, events,
5980aa9461SRoy Marples 	    PS_BOOTP, ctx->ps_inet->psp_fd) == -1)
606e63cc1fSRoy Marples 		logerr(__func__);
616e63cc1fSRoy Marples }
626e63cc1fSRoy Marples #endif
636e63cc1fSRoy Marples 
646e63cc1fSRoy Marples #ifdef INET6
656e63cc1fSRoy Marples static void
ps_inet_recvra(void * arg,unsigned short events)6680aa9461SRoy Marples ps_inet_recvra(void *arg, unsigned short events)
676e63cc1fSRoy Marples {
686e63cc1fSRoy Marples #ifdef __sun
696e63cc1fSRoy Marples 	struct interface *ifp = arg;
706e63cc1fSRoy Marples 	struct rs_state *state = RS_STATE(ifp);
716e63cc1fSRoy Marples 	struct dhcpcd_ctx *ctx = ifp->ctx;
726e63cc1fSRoy Marples 
73f3744ac9SRoy Marples 	if (ps_recvmsg(state->nd_fd, events,
7480aa9461SRoy Marples 	    PS_ND, ctx->ps_inet->psp_fd) == -1)
756e63cc1fSRoy Marples 		logerr(__func__);
766e63cc1fSRoy Marples #else
776e63cc1fSRoy Marples 	struct dhcpcd_ctx *ctx = arg;
786e63cc1fSRoy Marples 
79f3744ac9SRoy Marples 	if (ps_recvmsg(ctx->nd_fd, events,
8080aa9461SRoy Marples 	    PS_ND, ctx->ps_inet->psp_fd) == -1)
816e63cc1fSRoy Marples 		logerr(__func__);
826e63cc1fSRoy Marples #endif
836e63cc1fSRoy Marples }
846e63cc1fSRoy Marples #endif
856e63cc1fSRoy Marples 
866e63cc1fSRoy Marples #ifdef DHCP6
876e63cc1fSRoy Marples static void
ps_inet_recvdhcp6(void * arg,unsigned short events)8880aa9461SRoy Marples ps_inet_recvdhcp6(void *arg, unsigned short events)
896e63cc1fSRoy Marples {
906e63cc1fSRoy Marples 	struct dhcpcd_ctx *ctx = arg;
916e63cc1fSRoy Marples 
92f3744ac9SRoy Marples 	if (ps_recvmsg(ctx->dhcp6_rfd, events,
9380aa9461SRoy Marples 	    PS_DHCP6, ctx->ps_inet->psp_fd) == -1)
946e63cc1fSRoy Marples 		logerr(__func__);
956e63cc1fSRoy Marples }
966e63cc1fSRoy Marples #endif
976e63cc1fSRoy Marples 
9893ddca5eSRoy Marples bool
ps_inet_canstart(const struct dhcpcd_ctx * ctx)9993ddca5eSRoy Marples ps_inet_canstart(const struct dhcpcd_ctx *ctx)
10093ddca5eSRoy Marples {
10193ddca5eSRoy Marples 
10293ddca5eSRoy Marples #ifdef INET
1030a68f8d2SRoy Marples 	if ((ctx->options & (DHCPCD_IPV4 | DHCPCD_MANAGER)) ==
1040a68f8d2SRoy Marples 	    (DHCPCD_IPV4 | DHCPCD_MANAGER))
10593ddca5eSRoy Marples 		return true;
10693ddca5eSRoy Marples #endif
10793ddca5eSRoy Marples #if defined(INET6) && !defined(__sun)
10893ddca5eSRoy Marples 	if (ctx->options & DHCPCD_IPV6)
10993ddca5eSRoy Marples 		return true;
11093ddca5eSRoy Marples #endif
11193ddca5eSRoy Marples #ifdef DHCP6
1120a68f8d2SRoy Marples 	if ((ctx->options & (DHCPCD_IPV6 | DHCPCD_MANAGER)) ==
1130a68f8d2SRoy Marples 	    (DHCPCD_IPV6 | DHCPCD_MANAGER))
11493ddca5eSRoy Marples 		return true;
11593ddca5eSRoy Marples #endif
11693ddca5eSRoy Marples 
11793ddca5eSRoy Marples 	return false;
11893ddca5eSRoy Marples }
11993ddca5eSRoy Marples 
1206e63cc1fSRoy Marples static int
ps_inet_startcb(struct ps_process * psp)12180aa9461SRoy Marples ps_inet_startcb(struct ps_process *psp)
1226e63cc1fSRoy Marples {
12380aa9461SRoy Marples 	struct dhcpcd_ctx *ctx = psp->psp_ctx;
1246e63cc1fSRoy Marples 	int ret = 0;
125d4fb1e02SRoy Marples 
1260a68f8d2SRoy Marples 	if (ctx->options & DHCPCD_MANAGER)
1276e63cc1fSRoy Marples 		setproctitle("[network proxy]");
128d4fb1e02SRoy Marples 	else
129d4fb1e02SRoy Marples 		setproctitle("[network proxy] %s%s%s",
13080aa9461SRoy Marples 		    ctx->ifc != 0 ? ctx->ifv[0] : "",
131d4fb1e02SRoy Marples 		    ctx->options & DHCPCD_IPV4 ? " [ip4]" : "",
132d4fb1e02SRoy Marples 		    ctx->options & DHCPCD_IPV6 ? " [ip6]" : "");
1336e63cc1fSRoy Marples 
1346e63cc1fSRoy Marples 	/* This end is the main engine, so it's useless for us. */
1356e63cc1fSRoy Marples 	close(ctx->ps_data_fd);
1366e63cc1fSRoy Marples 	ctx->ps_data_fd = -1;
1376e63cc1fSRoy Marples 
1387a0236bfSRoy Marples 	errno = 0;
1397a0236bfSRoy Marples 
1406e63cc1fSRoy Marples #ifdef INET
1410a68f8d2SRoy Marples 	if ((ctx->options & (DHCPCD_IPV4 | DHCPCD_MANAGER)) ==
1420a68f8d2SRoy Marples 	    (DHCPCD_IPV4 | DHCPCD_MANAGER))
1436e63cc1fSRoy Marples 	{
144d4fb1e02SRoy Marples 		ctx->udp_rfd = dhcp_openudp(NULL);
145d4fb1e02SRoy Marples 		if (ctx->udp_rfd == -1)
1466e63cc1fSRoy Marples 			logerr("%s: dhcp_open", __func__);
1477f8103cdSRoy Marples #ifdef PRIVSEP_RIGHTS
1487f8103cdSRoy Marples 		else if (ps_rights_limit_fd_rdonly(ctx->udp_rfd) == -1) {
1497f8103cdSRoy Marples 			logerr("%s: ps_rights_limit_fd_rdonly", __func__);
150d4fb1e02SRoy Marples 			close(ctx->udp_rfd);
151d4fb1e02SRoy Marples 			ctx->udp_rfd = -1;
152d4fb1e02SRoy Marples 		}
153d4fb1e02SRoy Marples #endif
15480aa9461SRoy Marples 		else if (eloop_event_add(ctx->eloop, ctx->udp_rfd, ELE_READ,
1556e63cc1fSRoy Marples 		    ps_inet_recvbootp, ctx) == -1)
1566e63cc1fSRoy Marples 		{
1576e63cc1fSRoy Marples 			logerr("%s: eloop_event_add DHCP", __func__);
158d4fb1e02SRoy Marples 			close(ctx->udp_rfd);
159d4fb1e02SRoy Marples 			ctx->udp_rfd = -1;
1607a0236bfSRoy Marples 		} else
1616e63cc1fSRoy Marples 			ret++;
1626e63cc1fSRoy Marples 	}
1636e63cc1fSRoy Marples #endif
1646e63cc1fSRoy Marples #if defined(INET6) && !defined(__sun)
1656e63cc1fSRoy Marples 	if (ctx->options & DHCPCD_IPV6) {
166d4fb1e02SRoy Marples 		ctx->nd_fd = ipv6nd_open(true);
167d4fb1e02SRoy Marples 		if (ctx->nd_fd == -1)
1686e63cc1fSRoy Marples 			logerr("%s: ipv6nd_open", __func__);
1697f8103cdSRoy Marples #ifdef PRIVSEP_RIGHTS
1707f8103cdSRoy Marples 		else if (ps_rights_limit_fd_rdonly(ctx->nd_fd) == -1) {
1717f8103cdSRoy Marples 			logerr("%s: ps_rights_limit_fd_rdonly", __func__);
172d4fb1e02SRoy Marples 			close(ctx->nd_fd);
173d4fb1e02SRoy Marples 			ctx->nd_fd = -1;
174d4fb1e02SRoy Marples 		}
175d4fb1e02SRoy Marples #endif
17680aa9461SRoy Marples 		else if (eloop_event_add(ctx->eloop, ctx->nd_fd, ELE_READ,
1776e63cc1fSRoy Marples 		    ps_inet_recvra, ctx) == -1)
1786e63cc1fSRoy Marples 		{
1796e63cc1fSRoy Marples 			logerr("%s: eloop_event_add RA", __func__);
1807a0236bfSRoy Marples 			close(ctx->nd_fd);
1817a0236bfSRoy Marples 			ctx->nd_fd = -1;
1827a0236bfSRoy Marples 		} else
1836e63cc1fSRoy Marples 			ret++;
1846e63cc1fSRoy Marples 	}
1856e63cc1fSRoy Marples #endif
1866e63cc1fSRoy Marples #ifdef DHCP6
1870a68f8d2SRoy Marples 	if ((ctx->options & (DHCPCD_IPV6 | DHCPCD_MANAGER)) ==
1880a68f8d2SRoy Marples 	    (DHCPCD_IPV6 | DHCPCD_MANAGER))
1896e63cc1fSRoy Marples 	{
190d4fb1e02SRoy Marples 		ctx->dhcp6_rfd = dhcp6_openudp(0, NULL);
191d4fb1e02SRoy Marples 		if (ctx->dhcp6_rfd == -1)
1926e63cc1fSRoy Marples 			logerr("%s: dhcp6_open", __func__);
1937f8103cdSRoy Marples #ifdef PRIVSEP_RIGHTS
1947f8103cdSRoy Marples 		else if (ps_rights_limit_fd_rdonly(ctx->dhcp6_rfd) == -1) {
1957f8103cdSRoy Marples 			logerr("%s: ps_rights_limit_fd_rdonly", __func__);
196d4fb1e02SRoy Marples 			close(ctx->dhcp6_rfd);
197d4fb1e02SRoy Marples 			ctx->dhcp6_rfd = -1;
198d4fb1e02SRoy Marples 		}
199d4fb1e02SRoy Marples #endif
20080aa9461SRoy Marples 		else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, ELE_READ,
2016e63cc1fSRoy Marples 		    ps_inet_recvdhcp6, ctx) == -1)
2026e63cc1fSRoy Marples 		{
2036e63cc1fSRoy Marples 			logerr("%s: eloop_event_add DHCP6", __func__);
204d4fb1e02SRoy Marples 			close(ctx->dhcp6_rfd);
205d4fb1e02SRoy Marples 			ctx->dhcp6_rfd = -1;
2067a0236bfSRoy Marples 		} else
2076e63cc1fSRoy Marples 			ret++;
2086e63cc1fSRoy Marples 	}
2096e63cc1fSRoy Marples #endif
2106e63cc1fSRoy Marples 
2117a0236bfSRoy Marples 	if (ret == 0 && errno == 0) {
2126e63cc1fSRoy Marples 		errno = ENXIO;
2136e63cc1fSRoy Marples 		return -1;
2146e63cc1fSRoy Marples 	}
2156e63cc1fSRoy Marples 	return ret;
2166e63cc1fSRoy Marples }
2176e63cc1fSRoy Marples 
218d4fb1e02SRoy Marples static bool
ps_inet_validudp(struct msghdr * msg,uint16_t sport,uint16_t dport)219d4fb1e02SRoy Marples ps_inet_validudp(struct msghdr *msg, uint16_t sport, uint16_t dport)
2206e63cc1fSRoy Marples {
221d4fb1e02SRoy Marples 	struct udphdr udp;
222d4fb1e02SRoy Marples 	struct iovec *iov = msg->msg_iov;
223d4fb1e02SRoy Marples 
224d4fb1e02SRoy Marples 	if (msg->msg_iovlen == 0 || iov->iov_len < sizeof(udp)) {
225d4fb1e02SRoy Marples 		errno = EINVAL;
226d4fb1e02SRoy Marples 		return false;
227d4fb1e02SRoy Marples 	}
228d4fb1e02SRoy Marples 
229d4fb1e02SRoy Marples 	memcpy(&udp, iov->iov_base, sizeof(udp));
230d4fb1e02SRoy Marples 	if (udp.uh_sport != htons(sport) || udp.uh_dport != htons(dport)) {
231d4fb1e02SRoy Marples 		errno = EPERM;
232d4fb1e02SRoy Marples 		return false;
233d4fb1e02SRoy Marples 	}
234d4fb1e02SRoy Marples 	return true;
235d4fb1e02SRoy Marples }
236d4fb1e02SRoy Marples 
237d4fb1e02SRoy Marples #ifdef INET6
238d4fb1e02SRoy Marples static bool
ps_inet_validnd(struct msghdr * msg)239d4fb1e02SRoy Marples ps_inet_validnd(struct msghdr *msg)
240d4fb1e02SRoy Marples {
241d4fb1e02SRoy Marples 	struct icmp6_hdr icmp6;
242d4fb1e02SRoy Marples 	struct iovec *iov = msg->msg_iov;
243d4fb1e02SRoy Marples 
244d4fb1e02SRoy Marples 	if (msg->msg_iovlen == 0 || iov->iov_len < sizeof(icmp6)) {
245d4fb1e02SRoy Marples 		errno = EINVAL;
246d4fb1e02SRoy Marples 		return false;
247d4fb1e02SRoy Marples 	}
248d4fb1e02SRoy Marples 
249d4fb1e02SRoy Marples 	memcpy(&icmp6, iov->iov_base, sizeof(icmp6));
250d4fb1e02SRoy Marples 	switch(icmp6.icmp6_type) {
251d4fb1e02SRoy Marples 	case ND_ROUTER_SOLICIT:
252d4fb1e02SRoy Marples 	case ND_NEIGHBOR_ADVERT:
253d4fb1e02SRoy Marples 		break;
254d4fb1e02SRoy Marples 	default:
255d4fb1e02SRoy Marples 		errno = EPERM;
256d4fb1e02SRoy Marples 		return false;
257d4fb1e02SRoy Marples 	}
258d4fb1e02SRoy Marples 
259d4fb1e02SRoy Marples 	return true;
260d4fb1e02SRoy Marples }
261d4fb1e02SRoy Marples #endif
262d4fb1e02SRoy Marples 
263d4fb1e02SRoy Marples static ssize_t
ps_inet_sendmsg(struct dhcpcd_ctx * ctx,struct ps_msghdr * psm,struct msghdr * msg)264d4fb1e02SRoy Marples ps_inet_sendmsg(struct dhcpcd_ctx *ctx,
265d4fb1e02SRoy Marples     struct ps_msghdr *psm, struct msghdr *msg)
266d4fb1e02SRoy Marples {
2676e63cc1fSRoy Marples 	struct ps_process *psp;
2686e63cc1fSRoy Marples 	int s;
2696e63cc1fSRoy Marples 
2706e63cc1fSRoy Marples 	psp = ps_findprocess(ctx, &psm->ps_id);
2716e63cc1fSRoy Marples 	if (psp != NULL) {
2726e63cc1fSRoy Marples 		s = psp->psp_work_fd;
2736e63cc1fSRoy Marples 		goto dosend;
2746e63cc1fSRoy Marples 	}
2756e63cc1fSRoy Marples 
2766e63cc1fSRoy Marples 	switch (psm->ps_cmd) {
2776e63cc1fSRoy Marples #ifdef INET
2786e63cc1fSRoy Marples 	case PS_BOOTP:
279d4fb1e02SRoy Marples 		if (!ps_inet_validudp(msg, BOOTPC, BOOTPS))
280d4fb1e02SRoy Marples 			return -1;
281d4fb1e02SRoy Marples 		s = ctx->udp_wfd;
2826e63cc1fSRoy Marples 		break;
2836e63cc1fSRoy Marples #endif
2846e63cc1fSRoy Marples #if defined(INET6) && !defined(__sun)
2856e63cc1fSRoy Marples 	case PS_ND:
286d4fb1e02SRoy Marples 		if (!ps_inet_validnd(msg))
287d4fb1e02SRoy Marples 			return -1;
2886e63cc1fSRoy Marples 		s = ctx->nd_fd;
2896e63cc1fSRoy Marples 		break;
2906e63cc1fSRoy Marples #endif
2916e63cc1fSRoy Marples #ifdef DHCP6
2926e63cc1fSRoy Marples 	case PS_DHCP6:
293d4fb1e02SRoy Marples 		if (!ps_inet_validudp(msg, DHCP6_CLIENT_PORT,DHCP6_SERVER_PORT))
294d4fb1e02SRoy Marples 			return -1;
295d4fb1e02SRoy Marples 		s = ctx->dhcp6_wfd;
2966e63cc1fSRoy Marples 		break;
2976e63cc1fSRoy Marples #endif
2986e63cc1fSRoy Marples 	default:
2996e63cc1fSRoy Marples 		errno = EINVAL;
3006e63cc1fSRoy Marples 		return -1;
3016e63cc1fSRoy Marples 	}
3026e63cc1fSRoy Marples 
3036e63cc1fSRoy Marples dosend:
3046e63cc1fSRoy Marples 	return sendmsg(s, msg, 0);
3056e63cc1fSRoy Marples }
3066e63cc1fSRoy Marples 
3076e63cc1fSRoy Marples static void
ps_inet_recvmsg(void * arg,unsigned short events)30880aa9461SRoy Marples ps_inet_recvmsg(void *arg, unsigned short events)
3096e63cc1fSRoy Marples {
31080aa9461SRoy Marples 	struct ps_process *psp = arg;
3116e63cc1fSRoy Marples 
312d4fb1e02SRoy Marples 	/* Receive shutdown */
31380aa9461SRoy Marples 	if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, NULL, NULL) == -1)
3146e63cc1fSRoy Marples 		logerr(__func__);
3156e63cc1fSRoy Marples }
3166e63cc1fSRoy Marples 
3176e63cc1fSRoy Marples ssize_t
ps_inet_dispatch(void * arg,struct ps_msghdr * psm,struct msghdr * msg)3186e63cc1fSRoy Marples ps_inet_dispatch(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
3196e63cc1fSRoy Marples {
3206e63cc1fSRoy Marples 	struct dhcpcd_ctx *ctx = arg;
3216e63cc1fSRoy Marples 
3226e63cc1fSRoy Marples 	switch (psm->ps_cmd) {
3236e63cc1fSRoy Marples #ifdef INET
3246e63cc1fSRoy Marples 	case PS_BOOTP:
3256e63cc1fSRoy Marples 		dhcp_recvmsg(ctx, msg);
3266e63cc1fSRoy Marples 		break;
3276e63cc1fSRoy Marples #endif
3286e63cc1fSRoy Marples #ifdef INET6
3296e63cc1fSRoy Marples 	case PS_ND:
3306e63cc1fSRoy Marples 		ipv6nd_recvmsg(ctx, msg);
3316e63cc1fSRoy Marples 		break;
3326e63cc1fSRoy Marples #endif
3336e63cc1fSRoy Marples #ifdef DHCP6
3346e63cc1fSRoy Marples 	case PS_DHCP6:
3356e63cc1fSRoy Marples 		dhcp6_recvmsg(ctx, msg, NULL);
3366e63cc1fSRoy Marples 		break;
3376e63cc1fSRoy Marples #endif
3386e63cc1fSRoy Marples 	default:
3396e63cc1fSRoy Marples 		errno = ENOTSUP;
3406e63cc1fSRoy Marples 		return -1;
3416e63cc1fSRoy Marples 	}
3426e63cc1fSRoy Marples 	return 1;
3436e63cc1fSRoy Marples }
3446e63cc1fSRoy Marples 
3456e63cc1fSRoy Marples static void
ps_inet_dodispatch(void * arg,unsigned short events)34680aa9461SRoy Marples ps_inet_dodispatch(void *arg, unsigned short events)
3476e63cc1fSRoy Marples {
34880aa9461SRoy Marples 	struct ps_process *psp = arg;
3496e63cc1fSRoy Marples 
35080aa9461SRoy Marples 	if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events,
35180aa9461SRoy Marples 	    ps_inet_dispatch, psp->psp_ctx) == -1)
3526e63cc1fSRoy Marples 		logerr(__func__);
3536e63cc1fSRoy Marples }
3546e63cc1fSRoy Marples 
3556e63cc1fSRoy Marples pid_t
ps_inet_start(struct dhcpcd_ctx * ctx)3566e63cc1fSRoy Marples ps_inet_start(struct dhcpcd_ctx *ctx)
3576e63cc1fSRoy Marples {
35880aa9461SRoy Marples 	struct ps_id id = {
35980aa9461SRoy Marples 		.psi_ifindex = 0,
36080aa9461SRoy Marples 		.psi_cmd = PS_INET,
36180aa9461SRoy Marples 	};
36280aa9461SRoy Marples 	struct ps_process *psp;
363d4fb1e02SRoy Marples 	pid_t pid;
3646e63cc1fSRoy Marples 
36580aa9461SRoy Marples 	psp = ctx->ps_inet = ps_newprocess(ctx, &id);
36680aa9461SRoy Marples 	if (psp == NULL)
36780aa9461SRoy Marples 		return -1;
36880aa9461SRoy Marples 
36980aa9461SRoy Marples 	strlcpy(psp->psp_name, "network proxy", sizeof(psp->psp_name));
37080aa9461SRoy Marples 	pid = ps_startprocess(psp, ps_inet_recvmsg, ps_inet_dodispatch,
37180aa9461SRoy Marples 	    ps_inet_startcb, NULL, PSF_DROPPRIVS);
372d4fb1e02SRoy Marples 
373a0d9933aSRoy Marples 	if (pid == 0)
374a0d9933aSRoy Marples 		ps_entersandbox("stdio", NULL);
375d4fb1e02SRoy Marples 
376d4fb1e02SRoy Marples 	return pid;
3776e63cc1fSRoy Marples }
3786e63cc1fSRoy Marples 
3796e63cc1fSRoy Marples int
ps_inet_stop(struct dhcpcd_ctx * ctx)3806e63cc1fSRoy Marples ps_inet_stop(struct dhcpcd_ctx *ctx)
3816e63cc1fSRoy Marples {
3826e63cc1fSRoy Marples 
38380aa9461SRoy Marples 	return ps_stopprocess(ctx->ps_inet);
3846e63cc1fSRoy Marples }
3856e63cc1fSRoy Marples 
3866e63cc1fSRoy Marples #ifdef INET
3876e63cc1fSRoy Marples static void
ps_inet_recvinbootp(void * arg,unsigned short events)38880aa9461SRoy Marples ps_inet_recvinbootp(void *arg, unsigned short events)
3896e63cc1fSRoy Marples {
3906e63cc1fSRoy Marples 	struct ps_process *psp = arg;
3916e63cc1fSRoy Marples 
392f3744ac9SRoy Marples 	if (ps_recvmsg(psp->psp_work_fd, events,
3936e63cc1fSRoy Marples 	    PS_BOOTP, psp->psp_ctx->ps_data_fd) == -1)
3946e63cc1fSRoy Marples 		logerr(__func__);
3956e63cc1fSRoy Marples }
3966e63cc1fSRoy Marples 
3976e63cc1fSRoy Marples static int
ps_inet_listenin(struct ps_process * psp)39880aa9461SRoy Marples ps_inet_listenin(struct ps_process *psp)
3996e63cc1fSRoy Marples {
4006e63cc1fSRoy Marples 	struct in_addr *ia = &psp->psp_id.psi_addr.psa_in_addr;
4016e63cc1fSRoy Marples 	char buf[INET_ADDRSTRLEN];
4026e63cc1fSRoy Marples 
4036e63cc1fSRoy Marples 	inet_ntop(AF_INET, ia, buf, sizeof(buf));
40480aa9461SRoy Marples 	setproctitle("[%s proxy] %s", psp->psp_protostr, buf);
4056e63cc1fSRoy Marples 
4066e63cc1fSRoy Marples 	psp->psp_work_fd = dhcp_openudp(ia);
4076e63cc1fSRoy Marples 	if (psp->psp_work_fd == -1) {
4086e63cc1fSRoy Marples 		logerr(__func__);
4096e63cc1fSRoy Marples 		return -1;
4106e63cc1fSRoy Marples 	}
4116e63cc1fSRoy Marples 
4127f8103cdSRoy Marples #ifdef PRIVSEP_RIGHTS
4137f8103cdSRoy Marples 	if (ps_rights_limit_fd_rdonly(psp->psp_work_fd) == -1) {
4147f8103cdSRoy Marples 		logerr("%s: ps_rights_limit_fd_rdonly", __func__);
415d4fb1e02SRoy Marples 		return -1;
416d4fb1e02SRoy Marples 	}
417d4fb1e02SRoy Marples #endif
418d4fb1e02SRoy Marples 
41980aa9461SRoy Marples 	if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ,
4206e63cc1fSRoy Marples 	    ps_inet_recvinbootp, psp) == -1)
4216e63cc1fSRoy Marples 	{
4226e63cc1fSRoy Marples 		logerr("%s: eloop_event_add DHCP", __func__);
4236e63cc1fSRoy Marples 		return -1;
4246e63cc1fSRoy Marples 	}
4256e63cc1fSRoy Marples 	return 0;
4266e63cc1fSRoy Marples }
4276e63cc1fSRoy Marples #endif
4286e63cc1fSRoy Marples 
4296e63cc1fSRoy Marples #if defined(INET6) && defined(__sun)
4306e63cc1fSRoy Marples static void
ps_inet_recvin6nd(void * arg)4316e63cc1fSRoy Marples ps_inet_recvin6nd(void *arg)
4326e63cc1fSRoy Marples {
4336e63cc1fSRoy Marples 	struct ps_process *psp = arg;
4346e63cc1fSRoy Marples 
435f3744ac9SRoy Marples 	if (ps_recvmsg(psp->psp_work_fd,
4366e63cc1fSRoy Marples 	    PS_ND, psp->psp_ctx->ps_data_fd) == -1)
4376e63cc1fSRoy Marples 		logerr(__func__);
4386e63cc1fSRoy Marples }
4396e63cc1fSRoy Marples 
4406e63cc1fSRoy Marples static int
ps_inet_listennd(struct ps_process * psp)44180aa9461SRoy Marples ps_inet_listennd(struct ps_process *psp)
4426e63cc1fSRoy Marples {
4436e63cc1fSRoy Marples 
4446e63cc1fSRoy Marples 	setproctitle("[ND network proxy]");
4456e63cc1fSRoy Marples 
4466e63cc1fSRoy Marples 	psp->psp_work_fd = ipv6nd_open(&psp->psp_ifp);
4476e63cc1fSRoy Marples 	if (psp->psp_work_fd == -1) {
4486e63cc1fSRoy Marples 		logerr(__func__);
4496e63cc1fSRoy Marples 		return -1;
4506e63cc1fSRoy Marples 	}
4516e63cc1fSRoy Marples 
4527f8103cdSRoy Marples #ifdef PRIVSEP_RIGHTS
4537f8103cdSRoy Marples 	if (ps_rights_limit_fd_rdonly(psp->psp_work_fd) == -1) {
4547f8103cdSRoy Marples 		logerr("%s: ps_rights_limit_fd_rdonly", __func__);
455d4fb1e02SRoy Marples 		return -1;
456d4fb1e02SRoy Marples 	}
457d4fb1e02SRoy Marples #endif
458d4fb1e02SRoy Marples 
4596e63cc1fSRoy Marples 	if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
4606e63cc1fSRoy Marples 	    ps_inet_recvin6nd, psp) == -1)
4616e63cc1fSRoy Marples 	{
4626e63cc1fSRoy Marples 		logerr(__func__);
4636e63cc1fSRoy Marples 		return -1;
4646e63cc1fSRoy Marples 	}
4656e63cc1fSRoy Marples 	return 0;
4666e63cc1fSRoy Marples }
4676e63cc1fSRoy Marples #endif
4686e63cc1fSRoy Marples 
4696e63cc1fSRoy Marples #ifdef DHCP6
4706e63cc1fSRoy Marples static void
ps_inet_recvin6dhcp6(void * arg,unsigned short events)47180aa9461SRoy Marples ps_inet_recvin6dhcp6(void *arg, unsigned short events)
4726e63cc1fSRoy Marples {
4736e63cc1fSRoy Marples 	struct ps_process *psp = arg;
4746e63cc1fSRoy Marples 
475f3744ac9SRoy Marples 	if (ps_recvmsg(psp->psp_work_fd, events,
4766e63cc1fSRoy Marples 	    PS_DHCP6, psp->psp_ctx->ps_data_fd) == -1)
4776e63cc1fSRoy Marples 		logerr(__func__);
4786e63cc1fSRoy Marples }
4796e63cc1fSRoy Marples 
4806e63cc1fSRoy Marples static int
ps_inet_listenin6(struct ps_process * psp)48180aa9461SRoy Marples ps_inet_listenin6(struct ps_process *psp)
4826e63cc1fSRoy Marples {
4836e63cc1fSRoy Marples 	struct in6_addr *ia = &psp->psp_id.psi_addr.psa_in6_addr;
4846e63cc1fSRoy Marples 	char buf[INET6_ADDRSTRLEN];
4856e63cc1fSRoy Marples 
4866e63cc1fSRoy Marples 	inet_ntop(AF_INET6, ia, buf, sizeof(buf));
48780aa9461SRoy Marples 	setproctitle("[%s proxy] %s", psp->psp_protostr, buf);
4886e63cc1fSRoy Marples 
4896e63cc1fSRoy Marples 	psp->psp_work_fd = dhcp6_openudp(psp->psp_id.psi_ifindex, ia);
4906e63cc1fSRoy Marples 	if (psp->psp_work_fd == -1) {
4916e63cc1fSRoy Marples 		logerr(__func__);
4926e63cc1fSRoy Marples 		return -1;
4936e63cc1fSRoy Marples 	}
4946e63cc1fSRoy Marples 
4957f8103cdSRoy Marples #ifdef PRIVSEP_RIGHTS
4967f8103cdSRoy Marples 	if (ps_rights_limit_fd_rdonly(psp->psp_work_fd) == -1) {
4977f8103cdSRoy Marples 		logerr("%s: ps_rights_limit_fd_rdonly", __func__);
498d4fb1e02SRoy Marples 		return -1;
499d4fb1e02SRoy Marples 	}
500d4fb1e02SRoy Marples #endif
501d4fb1e02SRoy Marples 
50280aa9461SRoy Marples 	if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ,
5036e63cc1fSRoy Marples 	    ps_inet_recvin6dhcp6, psp) == -1)
5046e63cc1fSRoy Marples 	{
5056e63cc1fSRoy Marples 		logerr("%s: eloop_event_add DHCP", __func__);
5066e63cc1fSRoy Marples 		return -1;
5076e63cc1fSRoy Marples 	}
5086e63cc1fSRoy Marples 	return 0;
5096e63cc1fSRoy Marples }
5106e63cc1fSRoy Marples #endif
5116e63cc1fSRoy Marples 
5126e63cc1fSRoy Marples static void
ps_inet_recvmsgpsp(void * arg,unsigned short events)51380aa9461SRoy Marples ps_inet_recvmsgpsp(void *arg, unsigned short events)
5146e63cc1fSRoy Marples {
5156e63cc1fSRoy Marples 	struct ps_process *psp = arg;
5166e63cc1fSRoy Marples 
517d4fb1e02SRoy Marples 	/* Receive shutdown. */
51880aa9461SRoy Marples 	if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, NULL, NULL) == -1)
5196e63cc1fSRoy Marples 		logerr(__func__);
5206e63cc1fSRoy Marples }
5216e63cc1fSRoy Marples 
5226e63cc1fSRoy Marples ssize_t
ps_inet_cmd(struct dhcpcd_ctx * ctx,struct ps_msghdr * psm,struct msghdr * msg)523d4fb1e02SRoy Marples ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
5246e63cc1fSRoy Marples {
525d4fb1e02SRoy Marples 	uint16_t cmd;
5266e63cc1fSRoy Marples 	struct ps_process *psp;
52780aa9461SRoy Marples 	int (*start_func)(struct ps_process *);
5286e63cc1fSRoy Marples 	pid_t start;
52980aa9461SRoy Marples 	struct ps_addr *psa = &psm->ps_id.psi_addr;
53080aa9461SRoy Marples 	void *ia;
53180aa9461SRoy Marples 	char buf[INET_MAX_ADDRSTRLEN];
5326e63cc1fSRoy Marples 
533d4fb1e02SRoy Marples 	cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
534d4fb1e02SRoy Marples 	if (cmd == psm->ps_cmd)
535d4fb1e02SRoy Marples 		return ps_inet_sendmsg(ctx, psm, msg);
536d4fb1e02SRoy Marples 
5376e63cc1fSRoy Marples 	psp = ps_findprocess(ctx, &psm->ps_id);
5386e63cc1fSRoy Marples 
5396e63cc1fSRoy Marples #ifdef PRIVSEP_DEBUG
5406e63cc1fSRoy Marples 	logerrx("%s: IN cmd %x, psp %p", __func__, psm->ps_cmd, psp);
5416e63cc1fSRoy Marples #endif
5426e63cc1fSRoy Marples 
5436e63cc1fSRoy Marples 	if (psm->ps_cmd & PS_STOP) {
5446e63cc1fSRoy Marples 		assert(psp == NULL);
5456e63cc1fSRoy Marples 		return 0;
5466e63cc1fSRoy Marples 	}
5476e63cc1fSRoy Marples 
5486e63cc1fSRoy Marples 	if (!(psm->ps_cmd & PS_START)) {
5496e63cc1fSRoy Marples 		errno = EINVAL;
5506e63cc1fSRoy Marples 		return -1;
5516e63cc1fSRoy Marples 	}
5526e63cc1fSRoy Marples 
5536e63cc1fSRoy Marples 	if (psp != NULL)
5546e63cc1fSRoy Marples 		return 1;
5556e63cc1fSRoy Marples 
5566e63cc1fSRoy Marples 	psp = ps_newprocess(ctx, &psm->ps_id);
5576e63cc1fSRoy Marples 	if (psp == NULL)
5586e63cc1fSRoy Marples 		return -1;
5596e63cc1fSRoy Marples 
56080aa9461SRoy Marples 
56180aa9461SRoy Marples 	switch (cmd) {
56280aa9461SRoy Marples #ifdef INET
56380aa9461SRoy Marples 	case PS_BOOTP:
56480aa9461SRoy Marples 		start_func = ps_inet_listenin;
56580aa9461SRoy Marples 		psp->psp_protostr = "BOOTP";
56680aa9461SRoy Marples 		ia = &psa->psa_in_addr;
56780aa9461SRoy Marples 		break;
56880aa9461SRoy Marples #endif
56980aa9461SRoy Marples #ifdef INET6
57080aa9461SRoy Marples #ifdef __sun
57180aa9461SRoy Marples 	case PS_ND:
57280aa9461SRoy Marples 		start_func = ps_inet_listennd;
57380aa9461SRoy Marples 		psp->psp_protostr = "ND";
57480aa9461SRoy Marples 		ia = &psa->psa_in6_addr;
57580aa9461SRoy Marples 		break;
57680aa9461SRoy Marples #endif
57780aa9461SRoy Marples #ifdef DHCP6
57880aa9461SRoy Marples 	case PS_DHCP6:
57980aa9461SRoy Marples 		start_func = ps_inet_listenin6;
58080aa9461SRoy Marples 		psp->psp_protostr = "DHCP6";
58180aa9461SRoy Marples 		ia = &psa->psa_in6_addr;
58280aa9461SRoy Marples 		break;
58380aa9461SRoy Marples #endif
58480aa9461SRoy Marples #endif
58580aa9461SRoy Marples 	default:
58680aa9461SRoy Marples 		logerrx("%s: unknown command %x", __func__, psm->ps_cmd);
58780aa9461SRoy Marples 		errno = ENOTSUP;
58880aa9461SRoy Marples 		return -1;
58980aa9461SRoy Marples 	}
59080aa9461SRoy Marples 
59180aa9461SRoy Marples 	snprintf(psp->psp_name, sizeof(psp->psp_name),
59280aa9461SRoy Marples 	    "%s proxy %s", psp->psp_protostr,
59380aa9461SRoy Marples 	    inet_ntop(psa->psa_family, ia, buf, sizeof(buf)));
59480aa9461SRoy Marples 	start = ps_startprocess(psp, ps_inet_recvmsgpsp, NULL,
59580aa9461SRoy Marples 	    start_func, NULL, PSF_DROPPRIVS);
5966e63cc1fSRoy Marples 	switch (start) {
5976e63cc1fSRoy Marples 	case -1:
5986e63cc1fSRoy Marples 		ps_freeprocess(psp);
5996e63cc1fSRoy Marples 		return -1;
6006e63cc1fSRoy Marples 	case 0:
601a0d9933aSRoy Marples 		ps_entersandbox("stdio", NULL);
6026e63cc1fSRoy Marples 		break;
6036e63cc1fSRoy Marples 	default:
60480aa9461SRoy Marples 		logdebugx("%s: spawned %s on PID %d",
60580aa9461SRoy Marples 		    psp->psp_ifname, psp->psp_name, psp->psp_pid);
6066e63cc1fSRoy Marples 		break;
6076e63cc1fSRoy Marples 	}
6086e63cc1fSRoy Marples 	return start;
6096e63cc1fSRoy Marples }
6106e63cc1fSRoy Marples 
6116e63cc1fSRoy Marples #ifdef INET
6126e63cc1fSRoy Marples static ssize_t
ps_inet_in_docmd(struct ipv4_addr * ia,uint16_t cmd,const struct msghdr * msg)613d4fb1e02SRoy Marples ps_inet_in_docmd(struct ipv4_addr *ia, uint16_t cmd, const struct msghdr *msg)
6146e63cc1fSRoy Marples {
6156e63cc1fSRoy Marples 	assert(ia != NULL);
6166e63cc1fSRoy Marples 	struct dhcpcd_ctx *ctx = ia->iface->ctx;
6176e63cc1fSRoy Marples 	struct ps_msghdr psm = {
6186e63cc1fSRoy Marples 		.ps_cmd = cmd,
6196e63cc1fSRoy Marples 		.ps_id = {
6206e63cc1fSRoy Marples 			.psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)),
6216e63cc1fSRoy Marples 			.psi_ifindex = ia->iface->index,
62280aa9461SRoy Marples 			.psi_addr.psa_family = AF_INET,
6236e63cc1fSRoy Marples 			.psi_addr.psa_in_addr = ia->addr,
6246e63cc1fSRoy Marples 		},
6256e63cc1fSRoy Marples 	};
6266e63cc1fSRoy Marples 
627f3744ac9SRoy Marples 	return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg);
6286e63cc1fSRoy Marples }
6296e63cc1fSRoy Marples 
6306e63cc1fSRoy Marples ssize_t
ps_inet_openbootp(struct ipv4_addr * ia)6316e63cc1fSRoy Marples ps_inet_openbootp(struct ipv4_addr *ia)
6326e63cc1fSRoy Marples {
6336e63cc1fSRoy Marples 
6346e63cc1fSRoy Marples 	return ps_inet_in_docmd(ia, PS_START | PS_BOOTP, NULL);
6356e63cc1fSRoy Marples }
6366e63cc1fSRoy Marples 
6376e63cc1fSRoy Marples ssize_t
ps_inet_closebootp(struct ipv4_addr * ia)6386e63cc1fSRoy Marples ps_inet_closebootp(struct ipv4_addr *ia)
6396e63cc1fSRoy Marples {
6406e63cc1fSRoy Marples 
6416e63cc1fSRoy Marples 	return ps_inet_in_docmd(ia, PS_STOP | PS_BOOTP, NULL);
6426e63cc1fSRoy Marples }
6436e63cc1fSRoy Marples 
6446e63cc1fSRoy Marples ssize_t
ps_inet_sendbootp(struct interface * ifp,const struct msghdr * msg)645d4fb1e02SRoy Marples ps_inet_sendbootp(struct interface *ifp, const struct msghdr *msg)
6466e63cc1fSRoy Marples {
64780aa9461SRoy Marples 	struct dhcpcd_ctx *ctx = ifp->ctx;
6486e63cc1fSRoy Marples 
649f3744ac9SRoy Marples 	return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_BOOTP, 0, msg);
6506e63cc1fSRoy Marples }
6516e63cc1fSRoy Marples #endif /* INET */
6526e63cc1fSRoy Marples 
6536e63cc1fSRoy Marples #ifdef INET6
6546e63cc1fSRoy Marples #ifdef __sun
6556e63cc1fSRoy Marples static ssize_t
ps_inet_ifp_docmd(struct interface * ifp,uint16_t cmd,const struct msghdr * msg)656d4fb1e02SRoy Marples ps_inet_ifp_docmd(struct interface *ifp, uint16_t cmd, const struct msghdr *msg)
6576e63cc1fSRoy Marples {
6586e63cc1fSRoy Marples 	struct dhcpcd_ctx *ctx = ifp->ctx;
6596e63cc1fSRoy Marples 	struct ps_msghdr psm = {
6606e63cc1fSRoy Marples 		.ps_cmd = cmd,
6616e63cc1fSRoy Marples 		.ps_id = {
6626e63cc1fSRoy Marples 			.psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)),
6636e63cc1fSRoy Marples 			.psi_ifindex = ifp->index,
66480aa9461SRoy Marples 			.psi_addr.psa_family = AF_INET6,
6656e63cc1fSRoy Marples 		},
6666e63cc1fSRoy Marples 	};
6676e63cc1fSRoy Marples 
668f3744ac9SRoy Marples 	return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg);
6696e63cc1fSRoy Marples }
6706e63cc1fSRoy Marples 
6716e63cc1fSRoy Marples ssize_t
ps_inet_opennd(struct interface * ifp)6726e63cc1fSRoy Marples ps_inet_opennd(struct interface *ifp)
6736e63cc1fSRoy Marples {
6746e63cc1fSRoy Marples 
6756e63cc1fSRoy Marples 	return ps_inet_ifp_docmd(ifp, PS_ND | PS_START, NULL);
6766e63cc1fSRoy Marples }
6776e63cc1fSRoy Marples 
6786e63cc1fSRoy Marples ssize_t
ps_inet_closend(struct interface * ifp)6796e63cc1fSRoy Marples ps_inet_closend(struct interface *ifp)
6806e63cc1fSRoy Marples {
6816e63cc1fSRoy Marples 
6826e63cc1fSRoy Marples 	return ps_inet_ifp_docmd(ifp, PS_ND | PS_STOP, NULL);
6836e63cc1fSRoy Marples }
6846e63cc1fSRoy Marples 
6856e63cc1fSRoy Marples ssize_t
ps_inet_sendnd(struct interface * ifp,const struct msghdr * msg)6866e63cc1fSRoy Marples ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg)
6876e63cc1fSRoy Marples {
6886e63cc1fSRoy Marples 
6896e63cc1fSRoy Marples 	return ps_inet_ifp_docmd(ifp, PS_ND, msg);
6906e63cc1fSRoy Marples }
6916e63cc1fSRoy Marples #else
6926e63cc1fSRoy Marples ssize_t
ps_inet_sendnd(struct interface * ifp,const struct msghdr * msg)6936e63cc1fSRoy Marples ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg)
6946e63cc1fSRoy Marples {
69580aa9461SRoy Marples 	struct dhcpcd_ctx *ctx = ifp->ctx;
6966e63cc1fSRoy Marples 
697f3744ac9SRoy Marples 	return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_ND, 0, msg);
6986e63cc1fSRoy Marples }
6996e63cc1fSRoy Marples #endif
7006e63cc1fSRoy Marples 
7016e63cc1fSRoy Marples #ifdef DHCP6
7026e63cc1fSRoy Marples static ssize_t
ps_inet_in6_docmd(struct ipv6_addr * ia,uint16_t cmd,const struct msghdr * msg)703d4fb1e02SRoy Marples ps_inet_in6_docmd(struct ipv6_addr *ia, uint16_t cmd, const struct msghdr *msg)
7046e63cc1fSRoy Marples {
7056e63cc1fSRoy Marples 	struct dhcpcd_ctx *ctx = ia->iface->ctx;
7066e63cc1fSRoy Marples 	struct ps_msghdr psm = {
7076e63cc1fSRoy Marples 		.ps_cmd = cmd,
7086e63cc1fSRoy Marples 		.ps_id = {
7096e63cc1fSRoy Marples 			.psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)),
7106e63cc1fSRoy Marples 			.psi_ifindex = ia->iface->index,
71180aa9461SRoy Marples 			.psi_addr.psa_family = AF_INET6,
7126e63cc1fSRoy Marples 			.psi_addr.psa_in6_addr = ia->addr,
7136e63cc1fSRoy Marples 		},
7146e63cc1fSRoy Marples 	};
7156e63cc1fSRoy Marples 
716f3744ac9SRoy Marples 	return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg);
7176e63cc1fSRoy Marples }
7186e63cc1fSRoy Marples 
7196e63cc1fSRoy Marples ssize_t
ps_inet_opendhcp6(struct ipv6_addr * ia)7206e63cc1fSRoy Marples ps_inet_opendhcp6(struct ipv6_addr *ia)
7216e63cc1fSRoy Marples {
7226e63cc1fSRoy Marples 
7236e63cc1fSRoy Marples 	return ps_inet_in6_docmd(ia, PS_DHCP6 | PS_START, NULL);
7246e63cc1fSRoy Marples }
7256e63cc1fSRoy Marples 
7266e63cc1fSRoy Marples ssize_t
ps_inet_closedhcp6(struct ipv6_addr * ia)7276e63cc1fSRoy Marples ps_inet_closedhcp6(struct ipv6_addr *ia)
7286e63cc1fSRoy Marples {
7296e63cc1fSRoy Marples 
7306e63cc1fSRoy Marples 	return ps_inet_in6_docmd(ia, PS_DHCP6 | PS_STOP, NULL);
7316e63cc1fSRoy Marples }
7326e63cc1fSRoy Marples 
7336e63cc1fSRoy Marples ssize_t
ps_inet_senddhcp6(struct interface * ifp,const struct msghdr * msg)734d4fb1e02SRoy Marples ps_inet_senddhcp6(struct interface *ifp, const struct msghdr *msg)
7356e63cc1fSRoy Marples {
73680aa9461SRoy Marples 	struct dhcpcd_ctx *ctx = ifp->ctx;
7376e63cc1fSRoy Marples 
738f3744ac9SRoy Marples 	return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_DHCP6, 0, msg);
7396e63cc1fSRoy Marples }
7406e63cc1fSRoy Marples #endif /* DHCP6 */
7416e63cc1fSRoy Marples #endif /* INET6 */
742