1*545b6e31Sclaudio /* $OpenBSD: monitor.c,v 1.24 2024/11/21 13:42:49 claudio Exp $ */ 294f5df21Sho 394f5df21Sho /* 494f5df21Sho * Copyright (c) 2005 H�kan Olsson. All rights reserved. 594f5df21Sho * 694f5df21Sho * Redistribution and use in source and binary forms, with or without 794f5df21Sho * modification, are permitted provided that the following conditions 894f5df21Sho * are met: 994f5df21Sho * 1094f5df21Sho * 1. Redistributions of source code must retain the above copyright 1194f5df21Sho * notice, this list of conditions and the following disclaimer. 1294f5df21Sho * 2. Redistributions in binary form must reproduce the above copyright 1394f5df21Sho * notice, this list of conditions and the following disclaimer in the 1494f5df21Sho * documentation and/or other materials provided with the distribution. 1594f5df21Sho * 1694f5df21Sho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1794f5df21Sho * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1894f5df21Sho * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1994f5df21Sho * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2094f5df21Sho * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2194f5df21Sho * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2294f5df21Sho * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2394f5df21Sho * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2494f5df21Sho * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2594f5df21Sho * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2694f5df21Sho */ 2794f5df21Sho 2894f5df21Sho #include <sys/types.h> 2994f5df21Sho #include <sys/ioctl.h> 3094f5df21Sho #include <sys/socket.h> 316ba6c827Smpf #include <sys/stat.h> 3294f5df21Sho #include <sys/sysctl.h> 338edcd8a8Sderaadt #include <sys/queue.h> 3494f5df21Sho #include <sys/wait.h> 35f3eaad2dSreyk #include <sys/un.h> 3694f5df21Sho #include <net/pfkeyv2.h> 3794f5df21Sho 3894f5df21Sho #include <errno.h> 396ba6c827Smpf #include <fcntl.h> 4094f5df21Sho #include <pwd.h> 4194f5df21Sho #include <signal.h> 4294f5df21Sho #include <string.h> 4394f5df21Sho #include <stdlib.h> 4494f5df21Sho #include <unistd.h> 45b9fc9a72Sderaadt #include <limits.h> 46f3eaad2dSreyk #include <imsg.h> 47f3eaad2dSreyk 48f3eaad2dSreyk #include "types.h" /* iked imsg types */ 4994f5df21Sho 506ba6c827Smpf #include "monitor.h" 5194f5df21Sho #include "sasyncd.h" 5294f5df21Sho 5394f5df21Sho struct m_state { 5494f5df21Sho pid_t pid; 5594f5df21Sho int s; 5694f5df21Sho } m_state; 5794f5df21Sho 5894f5df21Sho volatile sig_atomic_t sigchld = 0; 5994f5df21Sho 6094f5df21Sho static void got_sigchld(int); 6194f5df21Sho static void sig_to_child(int); 6294f5df21Sho static void m_priv_pfkey_snap(int); 63f3eaad2dSreyk static int m_priv_control_activate(void); 64f3eaad2dSreyk static int m_priv_control_passivate(void); 6510595a5dSmoritz static ssize_t m_write(int, void *, size_t); 6610595a5dSmoritz static ssize_t m_read(int, void *, size_t); 6794f5df21Sho 6894f5df21Sho pid_t 6994f5df21Sho monitor_init(void) 7094f5df21Sho { 7194f5df21Sho struct passwd *pw = getpwnam(SASYNCD_USER); 7294f5df21Sho extern char *__progname; 73b9fc9a72Sderaadt char root[PATH_MAX]; 7494f5df21Sho int p[2]; 7594f5df21Sho 7694f5df21Sho if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) != 0) { 7794f5df21Sho log_err("%s: socketpair failed - %s", __progname, 7894f5df21Sho strerror(errno)); 7994f5df21Sho exit(1); 8094f5df21Sho } 8194f5df21Sho 8294f5df21Sho if (!pw) { 8394f5df21Sho log_err("%s: getpwnam(\"%s\") failed", __progname, 8494f5df21Sho SASYNCD_USER); 8594f5df21Sho exit(1); 8694f5df21Sho } 8794f5df21Sho strlcpy(root, pw->pw_dir, sizeof root); 8894f5df21Sho endpwent(); 8994f5df21Sho 9094f5df21Sho signal(SIGCHLD, got_sigchld); 9194f5df21Sho signal(SIGTERM, sig_to_child); 9294f5df21Sho signal(SIGHUP, sig_to_child); 9394f5df21Sho signal(SIGINT, sig_to_child); 9494f5df21Sho 9594f5df21Sho m_state.pid = fork(); 9694f5df21Sho 9794f5df21Sho if (m_state.pid == -1) { 9894f5df21Sho log_err("%s: fork failed - %s", __progname, strerror(errno)); 9994f5df21Sho exit(1); 10094f5df21Sho } else if (m_state.pid == 0) { 10194f5df21Sho /* Child */ 10294f5df21Sho m_state.s = p[0]; 10394f5df21Sho close(p[1]); 10494f5df21Sho 105d89005d5Smpf if (chroot(pw->pw_dir) != 0 || chdir("/") != 0) { 106d89005d5Smpf log_err("%s: chroot failed", __progname); 107d89005d5Smpf exit(1); 108d89005d5Smpf } 109d89005d5Smpf 11094f5df21Sho if (setgroups(1, &pw->pw_gid) || 11194f5df21Sho setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 11294f5df21Sho setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) { 11394f5df21Sho log_err("%s: failed to drop privileges", __progname); 11494f5df21Sho exit(1); 11594f5df21Sho } 11694f5df21Sho } else { 11794f5df21Sho /* Parent */ 11894f5df21Sho setproctitle("[priv]"); 11994f5df21Sho m_state.s = p[1]; 12094f5df21Sho close(p[0]); 12194f5df21Sho } 12294f5df21Sho return m_state.pid; 12394f5df21Sho } 12494f5df21Sho 12594f5df21Sho static void 12694f5df21Sho got_sigchld(int s) 12794f5df21Sho { 12894f5df21Sho sigchld = 1; 12994f5df21Sho } 13094f5df21Sho 13194f5df21Sho static void 13294f5df21Sho sig_to_child(int s) 13394f5df21Sho { 13494f5df21Sho if (m_state.pid != -1) 13594f5df21Sho kill(m_state.pid, s); 13694f5df21Sho } 13794f5df21Sho 13874a71167Sho static void 13974a71167Sho monitor_drain_input(void) 14074a71167Sho { 14174a71167Sho int one = 1; 14274a71167Sho u_int8_t tmp; 14374a71167Sho 14474a71167Sho ioctl(m_state.s, FIONBIO, &one); 14510595a5dSmoritz while (m_read(m_state.s, &tmp, 1) > 0) 14674a71167Sho ; 14774a71167Sho ioctl(m_state.s, FIONBIO, 0); 14874a71167Sho } 14974a71167Sho 15094f5df21Sho /* We only use privsep to get in-kernel SADB and SPD snapshots via sysctl */ 15194f5df21Sho void 15294f5df21Sho monitor_loop(void) 15394f5df21Sho { 154f3eaad2dSreyk u_int32_t v, vn; 15574a71167Sho ssize_t r; 156f3eaad2dSreyk fd_set rfds; 157f3eaad2dSreyk int ret; 158f3eaad2dSreyk struct timeval *tvp, tv; 159f3eaad2dSreyk 160f3eaad2dSreyk FD_ZERO(&rfds); 161f3eaad2dSreyk tvp = NULL; 162f3eaad2dSreyk vn = 0; 16374a71167Sho 16474a71167Sho for (;;) { 165f3eaad2dSreyk ret = 0; 166f3eaad2dSreyk v = 0; 167f3eaad2dSreyk 16874a71167Sho if (sigchld) { 16994f5df21Sho pid_t pid; 17094f5df21Sho int status; 17194f5df21Sho do { 17294f5df21Sho pid = waitpid(m_state.pid, &status, WNOHANG); 17394f5df21Sho } while (pid == -1 && errno == EINTR); 17494f5df21Sho 17594f5df21Sho if (pid == m_state.pid && 17674a71167Sho (WIFEXITED(status) || WIFSIGNALED(status))) 17794f5df21Sho break; 17894f5df21Sho } 17994f5df21Sho 180f3eaad2dSreyk FD_SET(m_state.s, &rfds); 181f3eaad2dSreyk if (select(m_state.s + 1, &rfds, NULL, NULL, tvp) == -1) { 182f3eaad2dSreyk if (errno == EINTR || errno == EAGAIN) 183f3eaad2dSreyk continue; 1849b1b9aeeSokan log_err("monitor_loop: select()"); 185f3eaad2dSreyk break; 186f3eaad2dSreyk } 187f3eaad2dSreyk 1889945a12eSmcbride /* Wait for next task */ 189f3eaad2dSreyk if (FD_ISSET(m_state.s, &rfds)) { 19010595a5dSmoritz if ((r = m_read(m_state.s, &v, sizeof v)) < 1) { 19174a71167Sho if (r == -1) 1929b1b9aeeSokan log_err("monitor_loop: read()"); 19394f5df21Sho break; 19474a71167Sho } 195f3eaad2dSreyk } 196f3eaad2dSreyk 197f3eaad2dSreyk /* Retry after timeout */ 198f3eaad2dSreyk if (v == 0 && tvp != NULL) { 199f3eaad2dSreyk v = vn; 200f3eaad2dSreyk tvp = NULL; 201f3eaad2dSreyk vn = 0; 202f3eaad2dSreyk } 20394f5df21Sho 2049945a12eSmcbride switch (v) { 2059945a12eSmcbride case MONITOR_GETSNAP: 20694f5df21Sho /* Get the data. */ 20794f5df21Sho m_priv_pfkey_snap(m_state.s); 2089945a12eSmcbride break; 2099945a12eSmcbride case MONITOR_CARPINC: 2109945a12eSmcbride carp_demote(CARP_INC, 1); 2119945a12eSmcbride break; 2129945a12eSmcbride case MONITOR_CARPDEC: 2139945a12eSmcbride carp_demote(CARP_DEC, 1); 2149945a12eSmcbride break; 215f3eaad2dSreyk case MONITOR_CONTROL_ACTIVATE: 216f3eaad2dSreyk ret = m_priv_control_activate(); 2176ba6c827Smpf break; 218f3eaad2dSreyk case MONITOR_CONTROL_PASSIVATE: 219f3eaad2dSreyk ret = m_priv_control_passivate(); 2206ba6c827Smpf break; 22194f5df21Sho } 222f3eaad2dSreyk 223f3eaad2dSreyk if (ret == -1) { 224f3eaad2dSreyk /* Trigger retry after timeout */ 225f3eaad2dSreyk tv.tv_sec = MONITOR_RETRY_TIMEOUT; 226f3eaad2dSreyk tv.tv_usec = 0; 227f3eaad2dSreyk tvp = &tv; 228f3eaad2dSreyk vn = v; 229f3eaad2dSreyk } 2309945a12eSmcbride } 2319945a12eSmcbride 2329945a12eSmcbride monitor_carpundemote(NULL); 23394f5df21Sho 23474a71167Sho if (!sigchld) 23574a71167Sho log_msg(0, "monitor_loop: priv process exiting abnormally"); 23694f5df21Sho exit(0); 23794f5df21Sho } 23894f5df21Sho 2399945a12eSmcbride void 2409945a12eSmcbride monitor_carpundemote(void *v) 2419945a12eSmcbride { 2429945a12eSmcbride u_int32_t mtype = MONITOR_CARPDEC; 2439945a12eSmcbride if (!carp_demoted) 2449945a12eSmcbride return; 2459945a12eSmcbride if (m_write(m_state.s, &mtype, sizeof mtype) < 1) 2469945a12eSmcbride log_msg(1, "monitor_carpundemote: unable to write to monitor"); 2479945a12eSmcbride else 2489945a12eSmcbride carp_demoted = 0; 2499945a12eSmcbride } 2509945a12eSmcbride 2519945a12eSmcbride void 2529945a12eSmcbride monitor_carpdemote(void *v) 2539945a12eSmcbride { 2549945a12eSmcbride u_int32_t mtype = MONITOR_CARPINC; 2559945a12eSmcbride if (carp_demoted) 2569945a12eSmcbride return; 2579945a12eSmcbride if (m_write(m_state.s, &mtype, sizeof mtype) < 1) 2589945a12eSmcbride log_msg(1, "monitor_carpdemote: unable to write to monitor"); 2599945a12eSmcbride else 2609945a12eSmcbride carp_demoted = 1; 2619945a12eSmcbride } 2629945a12eSmcbride 26394f5df21Sho int 26494f5df21Sho monitor_get_pfkey_snap(u_int8_t **sadb, u_int32_t *sadbsize, u_int8_t **spd, 26594f5df21Sho u_int32_t *spdsize) 26694f5df21Sho { 2670dfd1698Smoritz u_int32_t v; 2680dfd1698Smoritz ssize_t rbytes; 26994f5df21Sho 2709945a12eSmcbride v = MONITOR_GETSNAP; 27110595a5dSmoritz if (m_write(m_state.s, &v, sizeof v) < 1) 27294f5df21Sho return -1; 27394f5df21Sho 27494f5df21Sho /* Read SADB data. */ 2759fdb5ecdSho *sadb = *spd = NULL; 2769fdb5ecdSho *spdsize = 0; 27710595a5dSmoritz if (m_read(m_state.s, sadbsize, sizeof *sadbsize) < 1) 27894f5df21Sho return -1; 2799fdb5ecdSho if (*sadbsize) { 28035de856eSderaadt *sadb = malloc(*sadbsize); 28194f5df21Sho if (!*sadb) { 28294f5df21Sho log_err("monitor_get_pfkey_snap: malloc()"); 28374a71167Sho monitor_drain_input(); 28494f5df21Sho return -1; 28594f5df21Sho } 28610595a5dSmoritz rbytes = m_read(m_state.s, *sadb, *sadbsize); 28710595a5dSmoritz if (rbytes < 1) { 28829b4e2eaSderaadt freezero(*sadb, *sadbsize); 28994f5df21Sho return -1; 29094f5df21Sho } 2919fdb5ecdSho } 29294f5df21Sho 29394f5df21Sho /* Read SPD data */ 29410595a5dSmoritz if (m_read(m_state.s, spdsize, sizeof *spdsize) < 1) { 29529b4e2eaSderaadt freezero(*sadb, *sadbsize); 29694f5df21Sho return -1; 29794f5df21Sho } 2989fdb5ecdSho if (*spdsize) { 29935de856eSderaadt *spd = malloc(*spdsize); 30094f5df21Sho if (!*spd) { 30194f5df21Sho log_err("monitor_get_pfkey_snap: malloc()"); 30274a71167Sho monitor_drain_input(); 30329b4e2eaSderaadt freezero(*sadb, *sadbsize); 30494f5df21Sho return -1; 30594f5df21Sho } 30610595a5dSmoritz rbytes = m_read(m_state.s, *spd, *spdsize); 30710595a5dSmoritz if (rbytes < 1) { 30829b4e2eaSderaadt freezero(*spd, *spdsize); 30929b4e2eaSderaadt freezero(*sadb, *sadbsize); 31094f5df21Sho return -1; 31194f5df21Sho } 3129fdb5ecdSho } 31394f5df21Sho 3149353ff65Skjell log_msg(2, "monitor_get_pfkey_snap: got %u bytes SADB, %u bytes SPD", 31594f5df21Sho *sadbsize, *spdsize); 31694f5df21Sho return 0; 31794f5df21Sho } 31894f5df21Sho 3196ba6c827Smpf int 320f3eaad2dSreyk monitor_control_active(int active) 3216ba6c827Smpf { 3226ba6c827Smpf u_int32_t cmd = 323f3eaad2dSreyk active ? MONITOR_CONTROL_ACTIVATE : MONITOR_CONTROL_PASSIVATE; 3246ba6c827Smpf if (write(m_state.s, &cmd, sizeof cmd) < 1) 3256ba6c827Smpf return -1; 3266ba6c827Smpf return 0; 3276ba6c827Smpf } 3286ba6c827Smpf 32994f5df21Sho /* Privileged */ 33094f5df21Sho static void 33194f5df21Sho m_priv_pfkey_snap(int s) 33294f5df21Sho { 333ce9c777cShaesbaert u_int8_t *sadb_buf = NULL, *spd_buf = NULL; 33494f5df21Sho size_t sadb_buflen = 0, spd_buflen = 0, sz; 33594f5df21Sho int mib[5]; 33694f5df21Sho u_int32_t v; 33794f5df21Sho 33894f5df21Sho mib[0] = CTL_NET; 33994f5df21Sho mib[1] = PF_KEY; 34094f5df21Sho mib[2] = PF_KEY_V2; 34194f5df21Sho mib[3] = NET_KEY_SADB_DUMP; 34294f5df21Sho mib[4] = 0; /* Unspec SA type */ 34394f5df21Sho 34494f5df21Sho /* First, fetch SADB data */ 345ce9c777cShaesbaert for (;;) { 346ce9c777cShaesbaert if (sysctl(mib, sizeof mib / sizeof mib[0], NULL, &sz, NULL, 0) 347ce9c777cShaesbaert == -1) 348ce9c777cShaesbaert break; 34994f5df21Sho 350ce9c777cShaesbaert if (!sz) 351ce9c777cShaesbaert break; 352ce9c777cShaesbaert 353ce9c777cShaesbaert /* Try to catch newly added data */ 354ce9c777cShaesbaert sz *= 2; 355ce9c777cShaesbaert 356ce9c777cShaesbaert if ((sadb_buf = malloc(sz)) == NULL) 357ce9c777cShaesbaert break; 35894f5df21Sho 35994f5df21Sho if (sysctl(mib, sizeof mib / sizeof mib[0], sadb_buf, &sz, NULL, 0) 36094f5df21Sho == -1) { 361ce9c777cShaesbaert free(sadb_buf); 362ce9c777cShaesbaert sadb_buf = NULL; 363ce9c777cShaesbaert /* 364ce9c777cShaesbaert * If new SAs were added meanwhile and the given buffer is 365ce9c777cShaesbaert * too small, retry. 366ce9c777cShaesbaert */ 367ce9c777cShaesbaert if (errno == ENOMEM) 368ce9c777cShaesbaert continue; 369ce9c777cShaesbaert break; 370ce9c777cShaesbaert } 371ce9c777cShaesbaert 372ce9c777cShaesbaert sadb_buflen = sz; 373ce9c777cShaesbaert break; 37494f5df21Sho } 37594f5df21Sho 37694f5df21Sho /* Next, fetch SPD data */ 37794f5df21Sho mib[3] = NET_KEY_SPD_DUMP; 37894f5df21Sho 379ce9c777cShaesbaert for (;;) { 380ce9c777cShaesbaert if (sysctl(mib, sizeof mib / sizeof mib[0], NULL, &sz, NULL, 0) 381ce9c777cShaesbaert == -1) 382ce9c777cShaesbaert break; 38394f5df21Sho 384ce9c777cShaesbaert if (!sz) 385ce9c777cShaesbaert break; 386ce9c777cShaesbaert 387ce9c777cShaesbaert /* Try to catch newly added data */ 388ce9c777cShaesbaert sz *= 2; 389ce9c777cShaesbaert 390ce9c777cShaesbaert if ((spd_buf = malloc(sz)) == NULL) 391ce9c777cShaesbaert break; 39294f5df21Sho 39394f5df21Sho if (sysctl(mib, sizeof mib / sizeof mib[0], spd_buf, &sz, NULL, 0) 39494f5df21Sho == -1) { 395ce9c777cShaesbaert free(spd_buf); 396ce9c777cShaesbaert spd_buf = NULL; 397ce9c777cShaesbaert /* 398ce9c777cShaesbaert * If new SPDs were added meanwhile and the given buffer is 399ce9c777cShaesbaert * too small, retry. 400ce9c777cShaesbaert */ 401ce9c777cShaesbaert if (errno == ENOMEM) 402ce9c777cShaesbaert continue; 403ce9c777cShaesbaert break; 40494f5df21Sho } 40594f5df21Sho 406ce9c777cShaesbaert spd_buflen = sz; 407ce9c777cShaesbaert break; 408ce9c777cShaesbaert } 409ce9c777cShaesbaert 41094f5df21Sho /* Return SADB data */ 41194f5df21Sho v = (u_int32_t)sadb_buflen; 41210595a5dSmoritz if (m_write(s, &v, sizeof v) == -1) { 41394f5df21Sho log_err("m_priv_pfkey_snap: write"); 4144eb95076Smillert goto cleanup; 41594f5df21Sho } 416ce9c777cShaesbaert if (m_write(s, sadb_buf, sadb_buflen) == -1) { 41794f5df21Sho log_err("m_priv_pfkey_snap: write"); 418ce9c777cShaesbaert goto cleanup; 419ce9c777cShaesbaert } 42094f5df21Sho 42194f5df21Sho /* Return SPD data */ 42294f5df21Sho v = (u_int32_t)spd_buflen; 42310595a5dSmoritz if (m_write(s, &v, sizeof v) == -1) { 42494f5df21Sho log_err("m_priv_pfkey_snap: write"); 4254eb95076Smillert goto cleanup; 42694f5df21Sho } 427ce9c777cShaesbaert if (m_write(s, spd_buf, spd_buflen) == -1) { 42894f5df21Sho log_err("m_priv_pfkey_snap: write"); 429ce9c777cShaesbaert goto cleanup; 430ce9c777cShaesbaert } 431ce9c777cShaesbaert 4324eb95076Smillert cleanup: 43329b4e2eaSderaadt freezero(sadb_buf, sadb_buflen); 43429b4e2eaSderaadt freezero(spd_buf, spd_buflen); 435ce9c777cShaesbaert } 43610595a5dSmoritz 437f3eaad2dSreyk static int 4386ba6c827Smpf m_priv_isakmpd_fifocmd(const char *cmd) 4396ba6c827Smpf { 4406ba6c827Smpf struct stat sb; 441f3eaad2dSreyk int fd = -1, ret = -1; 4426ba6c827Smpf 4436ba6c827Smpf if ((fd = open(ISAKMPD_FIFO, O_WRONLY)) == -1) { 4446ba6c827Smpf log_err("m_priv_isakmpd_fifocmd: open(%s)", ISAKMPD_FIFO); 4456ba6c827Smpf goto out; 4466ba6c827Smpf } 4476ba6c827Smpf if (fstat(fd, &sb) == -1) { 4486ba6c827Smpf log_err("m_priv_isakmpd_fifocmd: fstat(%s)", ISAKMPD_FIFO); 4496ba6c827Smpf goto out; 4506ba6c827Smpf } 4516ba6c827Smpf if (!S_ISFIFO(sb.st_mode)) { 4526ba6c827Smpf log_err("m_priv_isakmpd_fifocmd: %s not a fifo", ISAKMPD_FIFO); 4536ba6c827Smpf goto out; 4546ba6c827Smpf } 4556ba6c827Smpf 4566ba6c827Smpf if (write(fd, cmd, strlen(cmd)) == -1) { 4576ba6c827Smpf log_err("m_priv_isakmpd_fifocmd write"); 4586ba6c827Smpf goto out; 4596ba6c827Smpf } 460f3eaad2dSreyk 461f3eaad2dSreyk ret = 0; 4626ba6c827Smpf out: 4636ba6c827Smpf if (fd != -1) 4646ba6c827Smpf close(fd); 465f3eaad2dSreyk 466f3eaad2dSreyk return (ret); 4676ba6c827Smpf } 4686ba6c827Smpf 469f3eaad2dSreyk static int 470f3eaad2dSreyk m_priv_iked_imsg(u_int cmd) 4716ba6c827Smpf { 472f3eaad2dSreyk struct sockaddr_un sun; 473f3eaad2dSreyk int fd = -1, ret = -1; 474f3eaad2dSreyk struct imsgbuf ibuf; 475f3eaad2dSreyk 476f3eaad2dSreyk if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 477f3eaad2dSreyk log_err("m_priv_iked_imsg: socket"); 478f3eaad2dSreyk goto out; 4796ba6c827Smpf } 4806ba6c827Smpf 481f3eaad2dSreyk bzero(&sun, sizeof(sun)); 482f3eaad2dSreyk sun.sun_family = AF_UNIX; 483f3eaad2dSreyk strlcpy(sun.sun_path, IKED_SOCKET, sizeof(sun.sun_path)); 484f3eaad2dSreyk 485f3eaad2dSreyk if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 486f3eaad2dSreyk log_err("m_priv_iked_imsg: connect"); 487f3eaad2dSreyk goto out; 488f3eaad2dSreyk } 489f3eaad2dSreyk 490*545b6e31Sclaudio if (imsgbuf_init(&ibuf, fd) == -1) { 491*545b6e31Sclaudio log_err("m_priv_iked_imsg: imsgbuf_init"); 492*545b6e31Sclaudio goto out; 493*545b6e31Sclaudio } 494f3eaad2dSreyk if (imsg_compose(&ibuf, cmd, 0, 0, -1, NULL, 0) == -1) { 495f3eaad2dSreyk log_err("m_priv_iked_imsg: compose"); 496f3eaad2dSreyk goto err; 497f3eaad2dSreyk } 498dd7efffeSclaudio if (imsgbuf_flush(&ibuf) == -1) { 499f3eaad2dSreyk log_err("m_priv_iked_imsg: flush"); 500f3eaad2dSreyk goto err; 501f3eaad2dSreyk } 502f3eaad2dSreyk 503f3eaad2dSreyk ret = 0; 504f3eaad2dSreyk err: 505dd7efffeSclaudio imsgbuf_clear(&ibuf); 506f3eaad2dSreyk out: 507f3eaad2dSreyk if (fd != -1) 508f3eaad2dSreyk close(fd); 509f3eaad2dSreyk 510f3eaad2dSreyk return (ret); 511f3eaad2dSreyk } 512f3eaad2dSreyk 513f3eaad2dSreyk static int 514f3eaad2dSreyk m_priv_control_activate(void) 5156ba6c827Smpf { 516f3eaad2dSreyk if (cfgstate.flags & CTL_ISAKMPD) 517f3eaad2dSreyk if (m_priv_isakmpd_fifocmd("M active\n") == -1) 518f3eaad2dSreyk return (-1); 519f3eaad2dSreyk if (cfgstate.flags & CTL_IKED) 520f3eaad2dSreyk if (m_priv_iked_imsg(IMSG_CTL_ACTIVE) == -1) 521f3eaad2dSreyk return (-1); 522f3eaad2dSreyk return (0); 523f3eaad2dSreyk } 524f3eaad2dSreyk 525f3eaad2dSreyk static int 526f3eaad2dSreyk m_priv_control_passivate(void) 527f3eaad2dSreyk { 528f3eaad2dSreyk if (cfgstate.flags & CTL_ISAKMPD) 529f3eaad2dSreyk if (m_priv_isakmpd_fifocmd("M passive\n") == -1) 530f3eaad2dSreyk return (-1); 531f3eaad2dSreyk if (cfgstate.flags & CTL_IKED) 532f3eaad2dSreyk if (m_priv_iked_imsg(IMSG_CTL_PASSIVE) == -1) 533f3eaad2dSreyk return (-1); 534f3eaad2dSreyk return (0); 5356ba6c827Smpf } 5366ba6c827Smpf 53710595a5dSmoritz ssize_t 53810595a5dSmoritz m_write(int sock, void *buf, size_t len) 53910595a5dSmoritz { 54010595a5dSmoritz ssize_t n; 54110595a5dSmoritz size_t pos = 0; 54210595a5dSmoritz char *ptr = buf; 54310595a5dSmoritz 54410595a5dSmoritz while (len > pos) { 54510595a5dSmoritz switch (n = write(sock, ptr + pos, len - pos)) { 54610595a5dSmoritz case -1: 54710595a5dSmoritz if (errno == EINTR || errno == EAGAIN) 54810595a5dSmoritz continue; 54910595a5dSmoritz /* FALLTHROUGH */ 55010595a5dSmoritz case 0: 55110595a5dSmoritz return n; 55210595a5dSmoritz /* NOTREACHED */ 55310595a5dSmoritz default: 55410595a5dSmoritz pos += n; 55510595a5dSmoritz } 55610595a5dSmoritz } 55710595a5dSmoritz return pos; 55810595a5dSmoritz } 55910595a5dSmoritz 56010595a5dSmoritz ssize_t 56110595a5dSmoritz m_read(int sock, void *buf, size_t len) 56210595a5dSmoritz { 56310595a5dSmoritz ssize_t n; 56410595a5dSmoritz size_t pos = 0; 56510595a5dSmoritz char *ptr = buf; 56610595a5dSmoritz 56710595a5dSmoritz while (len > pos) { 56810595a5dSmoritz switch (n = read(sock, ptr + pos, len - pos)) { 56910595a5dSmoritz case -1: 57010595a5dSmoritz if (errno == EINTR || errno == EAGAIN) 57110595a5dSmoritz continue; 57210595a5dSmoritz /* FALLTHROUGH */ 57310595a5dSmoritz case 0: 57410595a5dSmoritz return n; 57510595a5dSmoritz /* NOTREACHED */ 57610595a5dSmoritz default: 57710595a5dSmoritz pos += n; 57810595a5dSmoritz } 57910595a5dSmoritz } 58010595a5dSmoritz return pos; 58110595a5dSmoritz } 582