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