1 /* SPDX-License-Identifier: BSD-2-Clause */
3 * Privilege Separation for dhcpcd, privileged proxy
4 * Copyright (c) 2006-2021 Roy Marples <roy@marples.name>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
33 #include <sys/types.h>
59 __CTASSERT(sizeof(ioctl_request_t) <= sizeof(unsigned long));
65 char psr_pad[sizeof(ssize_t) - sizeof(int)];
70 struct dhcpcd_ctx *psr_ctx;
71 struct psr_error psr_error;
77 ps_root_readerrorcb(void *arg)
79 struct psr_ctx *psr_ctx = arg;
80 struct dhcpcd_ctx *ctx = psr_ctx->psr_ctx;
81 struct psr_error *psr_error = &psr_ctx->psr_error;
82 struct iovec iov[] = {
83 { .iov_base = psr_error, .iov_len = sizeof(*psr_error) },
84 { .iov_base = psr_ctx->psr_data,
85 .iov_len = psr_ctx->psr_datalen },
88 int exit_code = EXIT_FAILURE;
90 #define PSR_ERROR(e) \
92 psr_error->psr_result = -1; \
93 psr_error->psr_errno = (e); \
95 } while (0 /* CONSTCOND */)
97 len = readv(ctx->ps_root_fd, iov, __arraycount(iov));
100 else if ((size_t)len < sizeof(*psr_error))
102 exit_code = EXIT_SUCCESS;
105 eloop_exit(ctx->ps_eloop, exit_code);
109 ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len)
111 struct psr_ctx psr_ctx = {
113 .psr_data = data, .psr_datalen = len,
116 if (eloop_event_add(ctx->ps_eloop, ctx->ps_root_fd,
117 ps_root_readerrorcb, &psr_ctx) == -1)
120 eloop_enter(ctx->ps_eloop);
121 eloop_start(ctx->ps_eloop, &ctx->sigset);
123 errno = psr_ctx.psr_error.psr_errno;
124 return psr_ctx.psr_error.psr_result;
127 #ifdef PRIVSEP_GETIFADDRS
129 ps_root_mreaderrorcb(void *arg)
131 struct psr_ctx *psr_ctx = arg;
132 struct dhcpcd_ctx *ctx = psr_ctx->psr_ctx;
133 struct psr_error *psr_error = &psr_ctx->psr_error;
134 struct iovec iov[] = {
135 { .iov_base = psr_error, .iov_len = sizeof(*psr_error) },
136 { .iov_base = NULL, .iov_len = 0 },
139 int exit_code = EXIT_FAILURE;
141 len = recv(ctx->ps_root_fd, psr_error, sizeof(*psr_error), MSG_PEEK);
144 else if ((size_t)len < sizeof(*psr_error))
147 if (psr_error->psr_datalen > SSIZE_MAX)
149 else if (psr_error->psr_datalen != 0) {
150 psr_ctx->psr_data = malloc(psr_error->psr_datalen);
151 if (psr_ctx->psr_data == NULL)
153 psr_ctx->psr_datalen = psr_error->psr_datalen;
154 iov[1].iov_base = psr_ctx->psr_data;
155 iov[1].iov_len = psr_ctx->psr_datalen;
158 len = readv(ctx->ps_root_fd, iov, __arraycount(iov));
161 else if ((size_t)len != sizeof(*psr_error) + psr_ctx->psr_datalen)
163 exit_code = EXIT_SUCCESS;
166 eloop_exit(ctx->ps_eloop, exit_code);
170 ps_root_mreaderror(struct dhcpcd_ctx *ctx, void **data, size_t *len)
172 struct psr_ctx psr_ctx = {
176 if (eloop_event_add(ctx->ps_eloop, ctx->ps_root_fd,
177 ps_root_mreaderrorcb, &psr_ctx) == -1)
180 eloop_enter(ctx->ps_eloop);
181 eloop_start(ctx->ps_eloop, &ctx->sigset);
183 errno = psr_ctx.psr_error.psr_errno;
184 *data = psr_ctx.psr_data;
185 *len = psr_ctx.psr_datalen;
186 return psr_ctx.psr_error.psr_result;
191 ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t result,
192 void *data, size_t len)
194 struct psr_error psr = {
195 .psr_result = result,
199 struct iovec iov[] = {
200 { .iov_base = &psr, .iov_len = sizeof(psr) },
201 { .iov_base = data, .iov_len = len },
205 logdebugx("%s: result %zd errno %d", __func__, result, errno);
208 return writev(ctx->ps_root_fd, iov, __arraycount(iov));
212 ps_root_doioctl(unsigned long req, void *data, size_t len)
216 /* Only allow these ioctls */
219 case SIOCAIFADDR: /* FALLTHROUGH */
220 case SIOCDIFADDR: /* FALLTHROUGH */
223 case SIOCSIFHWADDR: /* FALLTHROUGH */
225 #ifdef SIOCGIFPRIORITY
226 case SIOCGIFPRIORITY: /* FALLTHROUGH */
228 case SIOCSIFFLAGS: /* FALLTHROUGH */
229 case SIOCGIFMTU: /* FALLTHROUGH */
237 s = socket(PF_INET, SOCK_DGRAM, 0);
239 #ifdef IOCTL_REQUEST_TYPE
241 ioctl_request_t reqt;
243 memcpy(&reqt, &req, sizeof(reqt));
244 err = ioctl(s, reqt, data, len);
247 err = ioctl(s, req, data, len);
257 ps_root_run_script(struct dhcpcd_ctx *ctx, const void *data, size_t len)
259 const char *envbuf = data;
260 char * const argv[] = { ctx->script, NULL };
267 if (script_buftoenv(ctx, UNCONST(envbuf), len) == NULL)
270 pid = script_exec(argv, ctx->script_env);
273 /* Wait for the script to finish */
274 while (waitpid(pid, &status, 0) == -1) {
275 if (errno != EINTR) {
285 ps_root_validpath(const struct dhcpcd_ctx *ctx, uint16_t cmd, const char *path)
288 /* Avoid a previous directory attack to avoid /proc/../
289 * dhcpcd should never use a path with double dots. */
290 if (strstr(path, "..") != NULL)
293 if (cmd == PS_READFILE) {
294 #ifdef EMBEDDED_CONFIG
295 if (strcmp(ctx->cffile, EMBEDDED_CONFIG) == 0)
298 if (strcmp(ctx->cffile, path) == 0)
301 if (strncmp(DBDIR, path, strlen(DBDIR)) == 0)
303 if (strncmp(RUNDIR, path, strlen(RUNDIR)) == 0)
307 if (strncmp("/proc/net/", path, strlen("/proc/net/")) == 0 ||
308 strncmp("/proc/sys/net/", path, strlen("/proc/sys/net/")) == 0 ||
309 strncmp("/sys/class/net/", path, strlen("/sys/class/net/")) == 0)
318 ps_root_dowritefile(const struct dhcpcd_ctx *ctx,
319 mode_t mode, void *data, size_t len)
321 char *file = data, *nc;
323 nc = memchr(file, '\0', len);
329 if (!ps_root_validpath(ctx, PS_WRITEFILE, file))
332 return writefile(file, mode, nc, len - (size_t)(nc - file));
337 ps_root_monordm(uint64_t *rdm, size_t len)
340 if (len != sizeof(*rdm)) {
344 return auth_get_rdm_monotonic(rdm);
348 #ifdef PRIVSEP_GETIFADDRS
351 ps_root_dogetifaddrs(void **rdata, size_t *rlen)
353 struct ifaddrs *ifaddrs, *ifa;
358 if (getifaddrs(&ifaddrs) == -1)
360 if (ifaddrs == NULL) {
366 /* Work out the buffer length required.
367 * Ensure everything is aligned correctly, which does
368 * create a larger buffer than what is needed to send,
369 * but makes creating the same structure in the client
372 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
373 len += ALIGN(sizeof(*ifa));
374 len += ALIGN(IFNAMSIZ);
375 len += ALIGN(sizeof(salen) * IFA_NADDRS);
376 if (ifa->ifa_addr != NULL)
377 len += ALIGN(sa_len(ifa->ifa_addr));
378 if (ifa->ifa_netmask != NULL)
379 len += ALIGN(sa_len(ifa->ifa_netmask));
380 if (ifa->ifa_broadaddr != NULL)
381 len += ALIGN(sa_len(ifa->ifa_broadaddr));
384 * On BSD we need to carry ifa_data so we can access
385 * if_data->ifi_link_state
387 if (ifa->ifa_addr != NULL &&
388 ifa->ifa_addr->sa_family == AF_LINK)
389 len += ALIGN(sizeof(struct if_data));
393 /* Use calloc to set everything to zero.
394 * This satisfies memory sanitizers because don't write
395 * where we don't need to. */
396 buf = calloc(1, len);
398 freeifaddrs(ifaddrs);
404 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
405 memcpy(buf, ifa, sizeof(*ifa));
406 buf += ALIGN(sizeof(*ifa));
408 strlcpy((char *)buf, ifa->ifa_name, IFNAMSIZ);
409 buf += ALIGN(IFNAMSIZ);
411 buf += ALIGN(sizeof(salen) * IFA_NADDRS);
413 #define COPYINSA(addr) \
415 if ((addr) != NULL) \
416 salen = sa_len((addr)); \
420 memcpy(sap, &salen, sizeof(salen)); \
421 memcpy(buf, (addr), salen); \
422 buf += ALIGN(salen); \
424 sap += sizeof(salen); \
425 } while (0 /*CONSTCOND */)
427 COPYINSA(ifa->ifa_addr);
428 COPYINSA(ifa->ifa_netmask);
429 COPYINSA(ifa->ifa_broadaddr);
432 if (ifa->ifa_addr != NULL &&
433 ifa->ifa_addr->sa_family == AF_LINK)
435 salen = (socklen_t)sizeof(struct if_data);
436 memcpy(buf, ifa->ifa_data, salen);
441 memcpy(sap, &salen, sizeof(salen));
444 freeifaddrs(ifaddrs);
450 ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
452 struct dhcpcd_ctx *ctx = arg;
454 struct ps_process *psp;
455 struct iovec *iov = msg->msg_iov;
456 void *data = iov->iov_base, *rdata = NULL;
457 size_t len = iov->iov_len, rlen = 0;
458 uint8_t buf[PS_BUFLEN];
461 bool free_rdata = false;
463 cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
464 psp = ps_findprocess(ctx, &psm->ps_id);
467 logerrx("%s: IN cmd %x, psp %p", __func__, psm->ps_cmd, psp);
471 if (psm->ps_cmd & PS_STOP) {
472 int ret = ps_dostop(ctx, &psp->psp_pid, &psp->psp_fd);
476 } else if (psm->ps_cmd & PS_START) {
477 /* Process has already started .... */
481 err = ps_sendpsmmsg(ctx, psp->psp_fd, psm, msg);
483 logerr("%s: failed to send message to pid %d",
484 __func__, psp->psp_pid);
485 shutdown(psp->psp_fd, SHUT_RDWR);
493 if (psm->ps_cmd & PS_STOP && psp == NULL)
499 case PS_BPF_ARP: /* FALLTHROUGH */
502 return ps_bpf_cmd(ctx, psm, msg);
506 return ps_inet_cmd(ctx, psm, msg);
510 case PS_DHCP6: /* FALLTHROUGH */
513 return ps_inet_cmd(ctx, psm, msg);
519 assert(msg->msg_iovlen == 0 || msg->msg_iovlen == 1);
524 switch (psm->ps_cmd) {
526 err = ps_root_doioctl(psm->ps_flags, data, len);
533 err = ps_root_run_script(ctx, data, len);
536 if (!ps_root_validpath(ctx, psm->ps_cmd, data)) {
543 if (!ps_root_validpath(ctx, psm->ps_cmd, data)) {
547 err = readfile(data, buf, sizeof(buf));
554 err = ps_root_dowritefile(ctx, (mode_t)psm->ps_flags,
558 err = filemtime(data, &mtime);
561 rlen = sizeof(mtime);
565 err = logopen(ctx->logfile);
568 case PS_AUTH_MONORDM:
569 err = ps_root_monordm(data, len);
576 #ifdef PRIVSEP_GETIFADDRS
578 err = ps_root_dogetifaddrs(&rdata, &rlen);
582 #if defined(INET6) && (defined(__linux__) || defined(HAVE_PLEDGE))
583 case PS_IP6FORWARDING:
584 err = ip6_forwarding(data);
589 err = dev_initialised(ctx, data);
591 case PS_DEV_LISTENING:
592 err = dev_listening(ctx);
596 err = ps_root_os(psm, msg, &rdata, &rlen);
600 err = ps_root_writeerror(ctx, err, rlen != 0 ? rdata : 0, rlen);
606 /* Receive from state engine, do an action. */
608 ps_root_recvmsg(void *arg)
610 struct dhcpcd_ctx *ctx = arg;
612 if (ps_recvpsmsg(ctx, ctx->ps_root_fd, ps_root_recvmsgcb, ctx) == -1)
618 ps_root_handleinterface(void *arg, int action, const char *ifname)
620 struct dhcpcd_ctx *ctx = arg;
624 flag = PS_DEV_IFADDED;
625 else if (action == -1)
626 flag = PS_DEV_IFREMOVED;
627 else if (action == 0)
628 flag = PS_DEV_IFUPDATED;
634 return (int)ps_sendcmd(ctx, ctx->ps_data_fd, PS_DEV_IFCMD, flag,
635 ifname, strlen(ifname) + 1);
640 ps_root_startcb(void *arg)
642 struct dhcpcd_ctx *ctx = arg;
644 if (ctx->options & DHCPCD_MANAGER)
645 setproctitle("[privileged proxy]");
647 setproctitle("[privileged proxy] %s%s%s",
649 ctx->options & DHCPCD_IPV4 ? " [ip4]" : "",
650 ctx->options & DHCPCD_IPV6 ? " [ip6]" : "");
651 ctx->ps_root_pid = getpid();
652 ctx->options |= DHCPCD_PRIVSEPROOT;
654 /* Open network sockets for sending.
655 * This is a small bit wasteful for non sandboxed OS's
656 * but makes life very easy for unicasting DHCPv6 in non manager
657 * mode as we no longer care about address selection.
658 * We can't call shutdown SHUT_RD on the socket because it's
659 * not connectd. All we can do is try and set a zero sized
660 * receive buffer and just let it overflow.
661 * Reading from it just to drain it is a waste of CPU time. */
663 if (ctx->options & DHCPCD_IPV4) {
666 ctx->udp_wfd = xsocket(PF_INET,
667 SOCK_RAW | SOCK_CXNB, IPPROTO_UDP);
668 if (ctx->udp_wfd == -1)
669 logerr("%s: dhcp_openraw", __func__);
670 else if (setsockopt(ctx->udp_wfd, SOL_SOCKET, SO_RCVBUF,
671 &buflen, sizeof(buflen)) == -1)
672 logerr("%s: setsockopt SO_RCVBUF DHCP", __func__);
676 if (ctx->options & DHCPCD_IPV6) {
679 ctx->nd_fd = ipv6nd_open(false);
680 if (ctx->nd_fd == -1)
681 logerr("%s: ipv6nd_open", __func__);
682 else if (setsockopt(ctx->nd_fd, SOL_SOCKET, SO_RCVBUF,
683 &buflen, sizeof(buflen)) == -1)
684 logerr("%s: setsockopt SO_RCVBUF ND", __func__);
688 if (ctx->options & DHCPCD_IPV6) {
691 ctx->dhcp6_wfd = dhcp6_openraw();
692 if (ctx->dhcp6_wfd == -1)
693 logerr("%s: dhcp6_openraw", __func__);
694 else if (setsockopt(ctx->dhcp6_wfd, SOL_SOCKET, SO_RCVBUF,
695 &buflen, sizeof(buflen)) == -1)
696 logerr("%s: setsockopt SO_RCVBUF DHCP6", __func__);
701 /* Start any dev listening plugin which may want to
702 * change the interface name provided by the kernel */
703 if ((ctx->options & (DHCPCD_MANAGER | DHCPCD_DEV)) ==
704 (DHCPCD_MANAGER | DHCPCD_DEV))
705 dev_start(ctx, ps_root_handleinterface);
712 ps_root_signalcb(int sig, __unused void *arg)
715 if (sig == SIGCHLD) {
716 while (waitpid(-1, NULL, WNOHANG) > 0)
722 int (*handle_interface)(void *, int, const char *);
726 ps_root_devcb(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
729 struct iovec *iov = msg->msg_iov;
731 if (msg->msg_iovlen != 1) {
736 switch(psm->ps_flags) {
740 case PS_DEV_IFREMOVED:
743 case PS_DEV_IFUPDATED:
751 return dhcpcd_handleinterface(ctx, action, iov->iov_base);
756 ps_root_dispatchcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
758 struct dhcpcd_ctx *ctx = arg;
761 switch(psm->ps_cmd) {
764 err = ps_root_devcb(ctx, psm, msg);
769 err = ps_bpf_dispatch(ctx, psm, msg);
770 if (err == -1 && errno == ENOTSUP)
772 err = ps_inet_dispatch(ctx, psm, msg);
778 ps_root_dispatch(void *arg)
780 struct dhcpcd_ctx *ctx = arg;
782 if (ps_recvpsmsg(ctx, ctx->ps_data_fd, ps_root_dispatchcb, ctx) == -1)
787 ps_root_log(void *arg)
789 struct dhcpcd_ctx *ctx = arg;
791 if (logreadfd(ctx->ps_log_fd) == -1)
796 ps_root_start(struct dhcpcd_ctx *ctx)
798 int logfd[2], datafd[2];
801 if (xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, logfd) == -1)
803 #ifdef PRIVSEP_RIGHTS
804 if (ps_rights_limit_fdpair(logfd) == -1)
808 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, datafd) == -1)
810 if (ps_setbuf_fdpair(datafd) == -1)
812 #ifdef PRIVSEP_RIGHTS
813 if (ps_rights_limit_fdpair(datafd) == -1)
817 pid = ps_dostart(ctx, &ctx->ps_root_pid, &ctx->ps_root_fd,
818 ps_root_recvmsg, NULL, ctx,
819 ps_root_startcb, ps_root_signalcb, 0);
822 ctx->ps_log_fd = logfd[1];
823 if (eloop_event_add(ctx->eloop, ctx->ps_log_fd,
824 ps_root_log, ctx) == -1)
827 ctx->ps_data_fd = datafd[1];
830 } else if (pid == -1)
836 ctx->ps_data_fd = datafd[0];
838 if (eloop_event_add(ctx->eloop, ctx->ps_data_fd,
839 ps_root_dispatch, ctx) == -1)
842 if ((ctx->ps_eloop = eloop_new()) == NULL)
845 eloop_signal_set_cb(ctx->ps_eloop,
846 dhcpcd_signals, dhcpcd_signals_len,
847 ps_root_signalcb, ctx);
853 ps_root_stop(struct dhcpcd_ctx *ctx)
856 return ps_dostop(ctx, &ctx->ps_root_pid, &ctx->ps_root_fd);
860 ps_root_script(struct dhcpcd_ctx *ctx, const void *data, size_t len)
863 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_SCRIPT, 0, data, len) == -1)
865 return ps_root_readerror(ctx, NULL, 0);
869 ps_root_ioctl(struct dhcpcd_ctx *ctx, ioctl_request_t req, void *data,
872 #ifdef IOCTL_REQUEST_TYPE
873 unsigned long ulreq = 0;
875 memcpy(&ulreq, &req, sizeof(req));
876 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_IOCTL, ulreq, data, len) == -1)
879 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_IOCTL, req, data, len) == -1)
882 return ps_root_readerror(ctx, data, len);
886 ps_root_unlink(struct dhcpcd_ctx *ctx, const char *file)
889 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_UNLINK, 0,
890 file, strlen(file) + 1) == -1)
892 return ps_root_readerror(ctx, NULL, 0);
896 ps_root_readfile(struct dhcpcd_ctx *ctx, const char *file,
897 void *data, size_t len)
899 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_READFILE, 0,
900 file, strlen(file) + 1) == -1)
902 return ps_root_readerror(ctx, data, len);
906 ps_root_writefile(struct dhcpcd_ctx *ctx, const char *file, mode_t mode,
907 const void *data, size_t len)
912 flen = strlcpy(buf, file, sizeof(buf));
914 if (flen > sizeof(buf) || flen + len > sizeof(buf)) {
918 memcpy(buf + flen, data, len);
920 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_WRITEFILE, mode,
921 buf, flen + len) == -1)
923 return ps_root_readerror(ctx, NULL, 0);
927 ps_root_filemtime(struct dhcpcd_ctx *ctx, const char *file, time_t *time)
930 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_FILEMTIME, 0,
931 file, strlen(file) + 1) == -1)
933 return ps_root_readerror(ctx, time, sizeof(*time));
937 ps_root_logreopen(struct dhcpcd_ctx *ctx)
940 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_LOGREOPEN, 0, NULL, 0) == -1)
942 return ps_root_readerror(ctx, NULL, 0);
945 #ifdef PRIVSEP_GETIFADDRS
947 ps_root_getifaddrs(struct dhcpcd_ctx *ctx, struct ifaddrs **ifahead)
956 if (ps_sendcmd(ctx, ctx->ps_root_fd,
957 PS_GETIFADDRS, 0, NULL, 0) == -1)
959 err = ps_root_mreaderror(ctx, &buf, &len);
964 /* Should be impossible - lo0 will always exist. */
971 *ifahead = (struct ifaddrs *)(void *)bp;
972 for (ifa = *ifahead; ifa != NULL; ifa = ifa->ifa_next) {
973 if (len < ALIGN(sizeof(*ifa)) +
974 ALIGN(IFNAMSIZ) + ALIGN(sizeof(salen) * IFA_NADDRS))
976 bp += ALIGN(sizeof(*ifa));
978 bp += ALIGN(IFNAMSIZ);
980 bp += ALIGN(sizeof(salen) * IFA_NADDRS);
981 len -= ALIGN(sizeof(*ifa)) +
982 ALIGN(IFNAMSIZ) + ALIGN(sizeof(salen) * IFA_NADDRS);
984 #define COPYOUTSA(addr) \
986 memcpy(&salen, sap, sizeof(salen)); \
990 (addr) = (struct sockaddr *)bp; \
991 bp += ALIGN(salen); \
992 len -= ALIGN(salen); \
994 sap += sizeof(salen); \
995 } while (0 /* CONSTCOND */)
997 COPYOUTSA(ifa->ifa_addr);
998 COPYOUTSA(ifa->ifa_netmask);
999 COPYOUTSA(ifa->ifa_broadaddr);
1001 memcpy(&salen, sap, sizeof(salen));
1007 len -= ALIGN(salen);
1009 ifa->ifa_data = NULL;
1012 ifa->ifa_next = (struct ifaddrs *)(void *)bp;
1014 ifa->ifa_next = NULL;
1026 #if defined(__linux__) || defined(HAVE_PLEDGE)
1028 ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname)
1031 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_IP6FORWARDING, 0,
1032 ifname, ifname != NULL ? strlen(ifname) + 1 : 0) == -1)
1034 return ps_root_readerror(ctx, NULL, 0);
1040 ps_root_getauthrdm(struct dhcpcd_ctx *ctx, uint64_t *rdm)
1043 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_AUTH_MONORDM, 0,
1044 rdm, sizeof(*rdm))== -1)
1046 return (int)ps_root_readerror(ctx, rdm, sizeof(*rdm));
1052 ps_root_dev_initialised(struct dhcpcd_ctx *ctx, const char *ifname)
1055 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_INITTED, 0,
1056 ifname, strlen(ifname) + 1)== -1)
1058 return (int)ps_root_readerror(ctx, NULL, 0);
1062 ps_root_dev_listening(struct dhcpcd_ctx * ctx)
1065 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_LISTENING, 0, NULL, 0)== -1)
1067 return (int)ps_root_readerror(ctx, NULL, 0);