1*d51e05adSsthen /* $OpenBSD: iked.c,v 1.72 2024/12/26 18:24:54 sthen Exp $ */ 245ae9d61Sreyk 345ae9d61Sreyk /* 465c540d0Spatrick * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> 5fcebd35dSreyk * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> 645ae9d61Sreyk * 745ae9d61Sreyk * Permission to use, copy, modify, and distribute this software for any 845ae9d61Sreyk * purpose with or without fee is hereby granted, provided that the above 945ae9d61Sreyk * copyright notice and this permission notice appear in all copies. 1045ae9d61Sreyk * 1145ae9d61Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1245ae9d61Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1345ae9d61Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1445ae9d61Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1545ae9d61Sreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1645ae9d61Sreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1745ae9d61Sreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1845ae9d61Sreyk */ 1945ae9d61Sreyk 2045ae9d61Sreyk #include <sys/queue.h> 2145ae9d61Sreyk #include <sys/socket.h> 22fc7fd3e3Sreyk #include <sys/wait.h> 2345ae9d61Sreyk #include <sys/uio.h> 2445ae9d61Sreyk 2545ae9d61Sreyk #include <stdlib.h> 2645ae9d61Sreyk #include <stdio.h> 2745ae9d61Sreyk #include <unistd.h> 2845ae9d61Sreyk #include <string.h> 2945ae9d61Sreyk #include <getopt.h> 3045ae9d61Sreyk #include <signal.h> 310f12961aSreyk #include <syslog.h> 3245ae9d61Sreyk #include <errno.h> 3345ae9d61Sreyk #include <err.h> 3445ae9d61Sreyk #include <pwd.h> 3545ae9d61Sreyk #include <event.h> 3645ae9d61Sreyk 3745ae9d61Sreyk #include "iked.h" 3845ae9d61Sreyk #include "ikev2.h" 39c183a39cStobhe #include "version.h" 4045ae9d61Sreyk 4145ae9d61Sreyk __dead void usage(void); 4245ae9d61Sreyk 4345ae9d61Sreyk void parent_shutdown(struct iked *); 4445ae9d61Sreyk void parent_sig_handler(int, short, void *); 45f2f2a684Sreyk int parent_dispatch_ca(int, struct privsep_proc *, struct imsg *); 46ebfc3693Sreyk int parent_dispatch_control(int, struct privsep_proc *, struct imsg *); 47cd3f460fStobhe int parent_dispatch_ikev2(int, struct privsep_proc *, struct imsg *); 488e8f56e9Stobhe void parent_connected(struct privsep *); 4945ae9d61Sreyk int parent_configure(struct iked *); 5045ae9d61Sreyk 51e8e9d77fStobhe struct iked *iked_env; 52e8e9d77fStobhe 53f2f2a684Sreyk static struct privsep_proc procs[] = { 54ebfc3693Sreyk { "ca", PROC_CERT, parent_dispatch_ca, caproc, IKED_CA }, 55ebfc3693Sreyk { "control", PROC_CONTROL, parent_dispatch_control, control }, 56cd3f460fStobhe { "ikev2", PROC_IKEV2, parent_dispatch_ikev2, ikev2 } 5745ae9d61Sreyk }; 5845ae9d61Sreyk 5945ae9d61Sreyk __dead void 6045ae9d61Sreyk usage(void) 6145ae9d61Sreyk { 6245ae9d61Sreyk extern char *__progname; 6345ae9d61Sreyk 64b49e1847Sjmc fprintf(stderr, "usage: %s [-dnSTtVv] [-D macro=value] " 65791e0891Sjmc "[-f file] [-p udpencap_port] [-s socket]\n", __progname); 6645ae9d61Sreyk exit(1); 6745ae9d61Sreyk } 6845ae9d61Sreyk 6945ae9d61Sreyk int 7045ae9d61Sreyk main(int argc, char *argv[]) 7145ae9d61Sreyk { 7245ae9d61Sreyk int c; 7345ae9d61Sreyk int debug = 0, verbose = 0; 7445ae9d61Sreyk int opts = 0; 751ae9ce49Stobhe enum natt_mode natt_mode = NATT_DEFAULT; 7659c69d76Stobhe in_port_t port = IKED_NATT_PORT; 7745ae9d61Sreyk const char *conffile = IKED_CONFIG; 78fbc39eabStobhe const char *sock = IKED_SOCKET; 79a7dbf4aeStobhe const char *errstr, *title = NULL; 8045ae9d61Sreyk struct iked *env = NULL; 81701048fbSreyk struct privsep *ps; 82a7dbf4aeStobhe enum privsep_procid proc_id = PROC_PARENT; 83a7dbf4aeStobhe int proc_instance = 0; 84a7dbf4aeStobhe int argc0 = argc; 8545ae9d61Sreyk 860f12961aSreyk log_init(1, LOG_DAEMON); 8745ae9d61Sreyk 88a7dbf4aeStobhe while ((c = getopt(argc, argv, "6D:df:I:nP:p:Ss:TtvV")) != -1) { 8945ae9d61Sreyk switch (c) { 905342a326Sreyk case '6': 9133e50974Ssthen log_warnx("the -6 option is ignored and will be " 9253b41a44Stobhe "removed in the future."); 935342a326Sreyk break; 9445ae9d61Sreyk case 'D': 9545ae9d61Sreyk if (cmdline_symset(optarg) < 0) 9645ae9d61Sreyk log_warnx("could not parse macro definition %s", 9745ae9d61Sreyk optarg); 9845ae9d61Sreyk break; 99f767955eStobhe case 'd': 100f767955eStobhe debug++; 10145ae9d61Sreyk break; 10245ae9d61Sreyk case 'f': 10345ae9d61Sreyk conffile = optarg; 10445ae9d61Sreyk break; 105a7dbf4aeStobhe case 'I': 106a7dbf4aeStobhe proc_instance = strtonum(optarg, 0, 107a7dbf4aeStobhe PROC_MAX_INSTANCES, &errstr); 108a7dbf4aeStobhe if (errstr) 109a7dbf4aeStobhe fatalx("invalid process instance"); 110a7dbf4aeStobhe break; 111f767955eStobhe case 'n': 112f767955eStobhe debug = 1; 113f767955eStobhe opts |= IKED_OPT_NOACTION; 114fbc39eabStobhe break; 115a7dbf4aeStobhe case 'P': 116a7dbf4aeStobhe title = optarg; 117a7dbf4aeStobhe proc_id = proc_getid(procs, nitems(procs), title); 118a7dbf4aeStobhe if (proc_id == PROC_MAX) 119a7dbf4aeStobhe fatalx("invalid process name"); 120a7dbf4aeStobhe break; 121f767955eStobhe case 'p': 122f767955eStobhe if (natt_mode == NATT_DISABLE) 123f767955eStobhe errx(1, "-T and -p are mutually exclusive"); 124277a74a3Stobhe port = strtonum(optarg, 1, UINT16_MAX, &errstr); 125277a74a3Stobhe if (errstr != NULL) 126277a74a3Stobhe errx(1, "port is %s: %s", errstr, optarg); 127f767955eStobhe natt_mode = NATT_FORCE; 12845ae9d61Sreyk break; 1293372b54cSreyk case 'S': 1303372b54cSreyk opts |= IKED_OPT_PASSIVE; 1313372b54cSreyk break; 132f767955eStobhe case 's': 133f767955eStobhe sock = optarg; 134f767955eStobhe break; 13545ae9d61Sreyk case 'T': 1361ae9ce49Stobhe if (natt_mode == NATT_FORCE) 1371ae9ce49Stobhe errx(1, "-T and -t/-p are mutually exclusive"); 1381ae9ce49Stobhe natt_mode = NATT_DISABLE; 13945ae9d61Sreyk break; 14012c9fd31Sreyk case 't': 1411ae9ce49Stobhe if (natt_mode == NATT_DISABLE) 1421ae9ce49Stobhe errx(1, "-T and -t are mutually exclusive"); 1431ae9ce49Stobhe natt_mode = NATT_FORCE; 14412c9fd31Sreyk break; 145f767955eStobhe case 'v': 146f767955eStobhe verbose++; 147f767955eStobhe opts |= IKED_OPT_VERBOSE; 14859c69d76Stobhe break; 149c183a39cStobhe case 'V': 150c183a39cStobhe fprintf(stderr, "OpenIKED %s\n", IKED_VERSION); 151c183a39cStobhe return 0; 15245ae9d61Sreyk default: 15345ae9d61Sreyk usage(); 15445ae9d61Sreyk } 15545ae9d61Sreyk } 15645ae9d61Sreyk 157a7dbf4aeStobhe /* log to stderr until daemonized */ 158a7dbf4aeStobhe log_init(debug ? debug : 1, LOG_DAEMON); 159a7dbf4aeStobhe 1601a82444dSpatrick argc -= optind; 1611a82444dSpatrick if (argc > 0) 1621a82444dSpatrick usage(); 1631a82444dSpatrick 16445ae9d61Sreyk if ((env = calloc(1, sizeof(*env))) == NULL) 16545ae9d61Sreyk fatal("calloc: env"); 16645ae9d61Sreyk 167e8e9d77fStobhe iked_env = env; 16845ae9d61Sreyk env->sc_opts = opts; 1697e57f0c1Stobhe env->sc_nattmode = natt_mode; 17059c69d76Stobhe env->sc_nattport = port; 17145ae9d61Sreyk 172701048fbSreyk ps = &env->sc_ps; 173701048fbSreyk ps->ps_env = env; 174701048fbSreyk 175b9fc9a72Sderaadt if (strlcpy(env->sc_conffile, conffile, PATH_MAX) >= PATH_MAX) 176b9fc9a72Sderaadt errx(1, "config file exceeds PATH_MAX"); 17745ae9d61Sreyk 178a7dbf4aeStobhe group_init(); 17945ae9d61Sreyk policy_init(env); 18045ae9d61Sreyk 181701048fbSreyk if ((ps->ps_pw = getpwnam(IKED_USER)) == NULL) 18245ae9d61Sreyk errx(1, "unknown user %s", IKED_USER); 18345ae9d61Sreyk 18445ae9d61Sreyk /* Configure the control socket */ 185fbc39eabStobhe ps->ps_csock.cs_name = sock; 18645ae9d61Sreyk 1870f12961aSreyk log_init(debug, LOG_DAEMON); 188871fc12cSreyk log_setverbose(verbose); 18945ae9d61Sreyk 190ea9a120cSjsg if (opts & IKED_OPT_NOACTION) 191ea9a120cSjsg ps->ps_noaction = 1; 192*d51e05adSsthen else { 193*d51e05adSsthen /* check for root privileges */ 194*d51e05adSsthen if (geteuid()) 195*d51e05adSsthen errx(1, "need root privileges"); 196*d51e05adSsthen } 197ea9a120cSjsg 198a7dbf4aeStobhe ps->ps_instance = proc_instance; 199a7dbf4aeStobhe if (title != NULL) 200a7dbf4aeStobhe ps->ps_title[proc_id] = title; 20145ae9d61Sreyk 202a7dbf4aeStobhe /* only the parent returns */ 203a7dbf4aeStobhe proc_init(ps, procs, nitems(procs), debug, argc0, argv, proc_id); 20445ae9d61Sreyk 20545ae9d61Sreyk setproctitle("parent"); 2060f12961aSreyk log_procinit("parent"); 20745ae9d61Sreyk 20845ae9d61Sreyk event_init(); 20945ae9d61Sreyk 210701048fbSreyk signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps); 211701048fbSreyk signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps); 212701048fbSreyk signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps); 213701048fbSreyk signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps); 214701048fbSreyk signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps); 215d5fd2e4bSreyk signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps); 21645ae9d61Sreyk 217701048fbSreyk signal_add(&ps->ps_evsigint, NULL); 218701048fbSreyk signal_add(&ps->ps_evsigterm, NULL); 219701048fbSreyk signal_add(&ps->ps_evsigchld, NULL); 220701048fbSreyk signal_add(&ps->ps_evsighup, NULL); 221701048fbSreyk signal_add(&ps->ps_evsigpipe, NULL); 222d5fd2e4bSreyk signal_add(&ps->ps_evsigusr1, NULL); 22345ae9d61Sreyk 224264f8b22Stobhe vroute_init(env); 225264f8b22Stobhe 2268e8f56e9Stobhe proc_connect(ps, parent_connected); 22745ae9d61Sreyk 22845ae9d61Sreyk event_dispatch(); 22945ae9d61Sreyk 23045ae9d61Sreyk log_debug("%d parent exiting", getpid()); 23191e971e4Stobhe parent_shutdown(env); 23245ae9d61Sreyk 23345ae9d61Sreyk return (0); 23445ae9d61Sreyk } 23545ae9d61Sreyk 2368e8f56e9Stobhe void 2378e8f56e9Stobhe parent_connected(struct privsep *ps) 2388e8f56e9Stobhe { 2398e8f56e9Stobhe struct iked *env = ps->ps_env; 2408e8f56e9Stobhe 2418e8f56e9Stobhe if (parent_configure(env) == -1) 2428e8f56e9Stobhe fatalx("configuration failed"); 2438e8f56e9Stobhe } 2448e8f56e9Stobhe 24545ae9d61Sreyk int 24645ae9d61Sreyk parent_configure(struct iked *env) 24745ae9d61Sreyk { 24845ae9d61Sreyk struct sockaddr_storage ss; 24945ae9d61Sreyk 25045ae9d61Sreyk if (parse_config(env->sc_conffile, env) == -1) { 251fc7fd3e3Sreyk proc_kill(&env->sc_ps); 25245ae9d61Sreyk exit(1); 25345ae9d61Sreyk } 25445ae9d61Sreyk 25545ae9d61Sreyk if (env->sc_opts & IKED_OPT_NOACTION) { 25645ae9d61Sreyk fprintf(stderr, "configuration OK\n"); 257fc7fd3e3Sreyk proc_kill(&env->sc_ps); 25845ae9d61Sreyk exit(0); 25945ae9d61Sreyk } 26045ae9d61Sreyk 26145ae9d61Sreyk env->sc_pfkey = -1; 262ba38eea7Stobhe config_setpfkey(env); 26345ae9d61Sreyk 264e8b444cdSreyk /* Send private and public keys to cert after forking the children */ 265e8b444cdSreyk if (config_setkeys(env) == -1) 266e8b444cdSreyk fatalx("%s: failed to send keys", __func__); 267e8b444cdSreyk config_setreset(env, RESET_CA, PROC_CERT); 268e8b444cdSreyk 269e2015428Sreyk /* Now compile the policies and calculate skip steps */ 270e2015428Sreyk config_setcompile(env, PROC_IKEV2); 271e2015428Sreyk 27245ae9d61Sreyk bzero(&ss, sizeof(ss)); 27345ae9d61Sreyk ss.ss_family = AF_INET; 27445ae9d61Sreyk 2751ae9ce49Stobhe /* see comment on config_setsocket() */ 2767e57f0c1Stobhe if (env->sc_nattmode != NATT_FORCE) 2773a5a2baaStobhe config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2); 2787e57f0c1Stobhe if (env->sc_nattmode != NATT_DISABLE) 2793a5a2baaStobhe config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2); 28045ae9d61Sreyk 28145ae9d61Sreyk bzero(&ss, sizeof(ss)); 28245ae9d61Sreyk ss.ss_family = AF_INET6; 28345ae9d61Sreyk 2847e57f0c1Stobhe if (env->sc_nattmode != NATT_FORCE) 2853a5a2baaStobhe config_setsocket(env, &ss, htons(IKED_IKE_PORT), PROC_IKEV2); 2867e57f0c1Stobhe if (env->sc_nattmode != NATT_DISABLE) 2873a5a2baaStobhe config_setsocket(env, &ss, htons(env->sc_nattport), PROC_IKEV2); 28845ae9d61Sreyk 289ebfc3693Sreyk /* 290ebfc3693Sreyk * pledge in the parent process: 291ebfc3693Sreyk * It has to run fairly late to allow forking the processes and 292ebfc3693Sreyk * opening the PFKEY socket and the listening UDP sockets (once) 293ebfc3693Sreyk * that need the bypass ioctls that are never allowed by pledge. 294ebfc3693Sreyk * 295ebfc3693Sreyk * Other flags: 296ebfc3693Sreyk * stdio - for malloc and basic I/O including events. 297ebfc3693Sreyk * rpath - for reload to open and read the configuration files. 298ebfc3693Sreyk * proc - run kill to terminate its children safely. 299ebfc3693Sreyk * dns - for reload and ocsp connect. 300ebfc3693Sreyk * inet - for ocsp connect. 301ebfc3693Sreyk * route - for using interfaces in iked.conf (SIOCGIFGMEMB) 302264f8b22Stobhe * wroute - for adding and removing addresses (SIOCAIFGMEMB) 303ebfc3693Sreyk * sendfd - for ocsp sockets. 304ebfc3693Sreyk */ 305264f8b22Stobhe if (pledge("stdio rpath proc dns inet route wroute sendfd", NULL) == -1) 306ebfc3693Sreyk fatal("pledge"); 307ebfc3693Sreyk 308421819b6Stobhe config_setstatic(env); 309fc20f985Sreyk config_setcoupled(env, env->sc_decoupled ? 0 : 1); 3106d3b905bSmarkus config_setocsp(env); 311f36db9c4Syasuoka config_setradauth(env); 312f36db9c4Syasuoka config_setradacct(env); 313f9967a42Stobhe /* Must be last */ 314f9967a42Stobhe config_setmode(env, env->sc_passive ? 1 : 0); 315fc20f985Sreyk 31645ae9d61Sreyk return (0); 31745ae9d61Sreyk } 31845ae9d61Sreyk 31945ae9d61Sreyk void 32045ae9d61Sreyk parent_reload(struct iked *env, int reset, const char *filename) 32145ae9d61Sreyk { 32245ae9d61Sreyk /* Switch back to the default config file */ 32345ae9d61Sreyk if (filename == NULL || *filename == '\0') 32445ae9d61Sreyk filename = env->sc_conffile; 32545ae9d61Sreyk 32645ae9d61Sreyk log_debug("%s: level %d config file %s", __func__, reset, filename); 32745ae9d61Sreyk 32845ae9d61Sreyk if (reset == RESET_RELOAD) { 32945ae9d61Sreyk config_setreset(env, RESET_POLICY, PROC_IKEV2); 330f36db9c4Syasuoka config_setreset(env, RESET_RADIUS, PROC_IKEV2); 331e8b444cdSreyk if (config_setkeys(env) == -1) 332e8b444cdSreyk fatalx("%s: failed to send keys", __func__); 33345ae9d61Sreyk config_setreset(env, RESET_CA, PROC_CERT); 33445ae9d61Sreyk 33545ae9d61Sreyk if (parse_config(filename, env) == -1) { 33645ae9d61Sreyk log_debug("%s: failed to load config file %s", 33745ae9d61Sreyk __func__, filename); 33845ae9d61Sreyk } 339fc20f985Sreyk 340e2015428Sreyk /* Re-compile policies and skip steps */ 341e2015428Sreyk config_setcompile(env, PROC_IKEV2); 342e2015428Sreyk 343421819b6Stobhe config_setstatic(env); 344fc20f985Sreyk config_setcoupled(env, env->sc_decoupled ? 0 : 1); 3456d3b905bSmarkus config_setocsp(env); 346f9967a42Stobhe /* Must be last */ 347f9967a42Stobhe config_setmode(env, env->sc_passive ? 1 : 0); 34845ae9d61Sreyk } else { 34945ae9d61Sreyk config_setreset(env, reset, PROC_IKEV2); 35045ae9d61Sreyk config_setreset(env, reset, PROC_CERT); 35145ae9d61Sreyk } 35245ae9d61Sreyk } 35345ae9d61Sreyk 35445ae9d61Sreyk void 355701048fbSreyk parent_sig_handler(int sig, short event, void *arg) 35645ae9d61Sreyk { 357701048fbSreyk struct privsep *ps = arg; 35845ae9d61Sreyk int die = 0, status, fail, id; 35945ae9d61Sreyk pid_t pid; 36045ae9d61Sreyk char *cause; 36145ae9d61Sreyk 36245ae9d61Sreyk switch (sig) { 36345ae9d61Sreyk case SIGHUP: 36445ae9d61Sreyk log_info("%s: reload requested with SIGHUP", __func__); 36545ae9d61Sreyk 36645ae9d61Sreyk /* 36745ae9d61Sreyk * This is safe because libevent uses async signal handlers 36845ae9d61Sreyk * that run in the event loop and not in signal context. 36945ae9d61Sreyk */ 370701048fbSreyk parent_reload(ps->ps_env, 0, NULL); 37145ae9d61Sreyk break; 37245ae9d61Sreyk case SIGPIPE: 37345ae9d61Sreyk log_info("%s: ignoring SIGPIPE", __func__); 37445ae9d61Sreyk break; 375d5fd2e4bSreyk case SIGUSR1: 376d5fd2e4bSreyk log_info("%s: ignoring SIGUSR1", __func__); 377d5fd2e4bSreyk break; 37845ae9d61Sreyk case SIGTERM: 37945ae9d61Sreyk case SIGINT: 38091e971e4Stobhe die = 1; 38191e971e4Stobhe /* FALLTHROUGH */ 38245ae9d61Sreyk case SIGCHLD: 38345ae9d61Sreyk do { 3846acea849Stobhe int len = 0; 385aa48e8d1Smillert 38645ae9d61Sreyk pid = waitpid(-1, &status, WNOHANG); 38745ae9d61Sreyk if (pid <= 0) 38845ae9d61Sreyk continue; 38945ae9d61Sreyk 39045ae9d61Sreyk fail = 0; 39145ae9d61Sreyk if (WIFSIGNALED(status)) { 39245ae9d61Sreyk fail = 1; 393aa48e8d1Smillert len = asprintf(&cause, "terminated; signal %d", 39445ae9d61Sreyk WTERMSIG(status)); 39545ae9d61Sreyk } else if (WIFEXITED(status)) { 39645ae9d61Sreyk if (WEXITSTATUS(status) != 0) { 39745ae9d61Sreyk fail = 1; 398aa48e8d1Smillert len = asprintf(&cause, 399aa48e8d1Smillert "exited abnormally"); 40045ae9d61Sreyk } else 401aa48e8d1Smillert len = asprintf(&cause, "exited okay"); 40245ae9d61Sreyk } else 40345ae9d61Sreyk fatalx("unexpected cause of SIGCHLD"); 40445ae9d61Sreyk 405aa48e8d1Smillert if (len == -1) 406aa48e8d1Smillert fatal("asprintf"); 407aa48e8d1Smillert 40845ae9d61Sreyk die = 1; 40945ae9d61Sreyk 41045ae9d61Sreyk for (id = 0; id < PROC_MAX; id++) 411701048fbSreyk if (pid == ps->ps_pid[id]) { 412e08ac948Sreyk if (fail) 41345ae9d61Sreyk log_warnx("lost child: %s %s", 414701048fbSreyk ps->ps_title[id], cause); 41545ae9d61Sreyk break; 41645ae9d61Sreyk } 41745ae9d61Sreyk 41845ae9d61Sreyk free(cause); 41945ae9d61Sreyk } while (pid > 0 || (pid == -1 && errno == EINTR)); 42045ae9d61Sreyk 42145ae9d61Sreyk if (die) 422701048fbSreyk parent_shutdown(ps->ps_env); 42345ae9d61Sreyk break; 42445ae9d61Sreyk default: 42545ae9d61Sreyk fatalx("unexpected signal"); 42645ae9d61Sreyk } 42745ae9d61Sreyk } 42845ae9d61Sreyk 42945ae9d61Sreyk int 430ebfc3693Sreyk parent_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg) 43145ae9d61Sreyk { 432e8e9d77fStobhe struct iked *env = iked_env; 43345ae9d61Sreyk 434ebfc3693Sreyk switch (imsg->hdr.type) { 4353fdfc9aaStobhe case IMSG_CTL_ACTIVE: 4363fdfc9aaStobhe case IMSG_CTL_PASSIVE: 4373fdfc9aaStobhe proc_forward_imsg(&env->sc_ps, imsg, PROC_IKEV2, -1); 4383fdfc9aaStobhe break; 439ebfc3693Sreyk case IMSG_OCSP_FD: 4404f9da335Stobhe ocsp_connect(env, imsg); 441ebfc3693Sreyk break; 442ebfc3693Sreyk default: 44345ae9d61Sreyk return (-1); 44445ae9d61Sreyk } 44545ae9d61Sreyk 446ebfc3693Sreyk return (0); 447ebfc3693Sreyk } 448ebfc3693Sreyk 44945ae9d61Sreyk int 450ebfc3693Sreyk parent_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg) 45145ae9d61Sreyk { 452e8e9d77fStobhe struct iked *env = iked_env; 45345ae9d61Sreyk int v; 45445ae9d61Sreyk char *str = NULL; 455d09d3a7dSreyk unsigned int type = imsg->hdr.type; 45645ae9d61Sreyk 457fc20f985Sreyk switch (type) { 45845ae9d61Sreyk case IMSG_CTL_RESET: 45945ae9d61Sreyk IMSG_SIZE_CHECK(imsg, &v); 46045ae9d61Sreyk memcpy(&v, imsg->data, sizeof(v)); 46145ae9d61Sreyk parent_reload(env, v, NULL); 462484f668cSreyk break; 463fc20f985Sreyk case IMSG_CTL_COUPLE: 464fc20f985Sreyk case IMSG_CTL_DECOUPLE: 465fc20f985Sreyk case IMSG_CTL_ACTIVE: 466fc20f985Sreyk case IMSG_CTL_PASSIVE: 467c205e972Sreyk proc_compose(&env->sc_ps, PROC_IKEV2, type, NULL, 0); 468484f668cSreyk break; 46945ae9d61Sreyk case IMSG_CTL_RELOAD: 47045ae9d61Sreyk if (IMSG_DATA_SIZE(imsg) > 0) 47145ae9d61Sreyk str = get_string(imsg->data, IMSG_DATA_SIZE(imsg)); 47245ae9d61Sreyk parent_reload(env, 0, str); 47345ae9d61Sreyk free(str); 47445ae9d61Sreyk break; 4759a12c596Sreyk case IMSG_CTL_VERBOSE: 4769a12c596Sreyk proc_forward_imsg(&env->sc_ps, imsg, PROC_IKEV2, -1); 4779a12c596Sreyk proc_forward_imsg(&env->sc_ps, imsg, PROC_CERT, -1); 4789a12c596Sreyk 4799a12c596Sreyk /* return 1 to let proc.c handle it locally */ 4809a12c596Sreyk return (1); 481484f668cSreyk default: 482484f668cSreyk return (-1); 48345ae9d61Sreyk } 48445ae9d61Sreyk 485484f668cSreyk return (0); 48645ae9d61Sreyk } 48745ae9d61Sreyk 488cd3f460fStobhe int 489cd3f460fStobhe parent_dispatch_ikev2(int fd, struct privsep_proc *p, struct imsg *imsg) 490cd3f460fStobhe { 491e8e9d77fStobhe struct iked *env = iked_env; 492cd3f460fStobhe 493cd3f460fStobhe switch (imsg->hdr.type) { 494264f8b22Stobhe case IMSG_IF_ADDADDR: 495264f8b22Stobhe case IMSG_IF_DELADDR: 496264f8b22Stobhe return (vroute_getaddr(env, imsg)); 4979ef39cf4Stobhe case IMSG_VDNS_ADD: 4989ef39cf4Stobhe case IMSG_VDNS_DEL: 4999ef39cf4Stobhe return (vroute_getdns(env, imsg)); 500264f8b22Stobhe case IMSG_VROUTE_ADD: 501264f8b22Stobhe case IMSG_VROUTE_DEL: 502264f8b22Stobhe return (vroute_getroute(env, imsg)); 503264f8b22Stobhe case IMSG_VROUTE_CLONE: 504264f8b22Stobhe return (vroute_getcloneroute(env, imsg)); 505cd3f460fStobhe default: 506cd3f460fStobhe return (-1); 507cd3f460fStobhe } 508cd3f460fStobhe 509cd3f460fStobhe return (0); 510cd3f460fStobhe } 511cd3f460fStobhe 51245ae9d61Sreyk void 51345ae9d61Sreyk parent_shutdown(struct iked *env) 51445ae9d61Sreyk { 515fc7fd3e3Sreyk proc_kill(&env->sc_ps); 51645ae9d61Sreyk 51791e971e4Stobhe vroute_cleanup(env); 51847ed2a28Stobhe free(env->sc_vroute); 51945ae9d61Sreyk free(env); 52045ae9d61Sreyk 52145ae9d61Sreyk log_warnx("parent terminating"); 52245ae9d61Sreyk exit(0); 52345ae9d61Sreyk } 524