1*90d56d5fSflorian /* $OpenBSD: unwind.c,v 1.14 2019/02/11 13:38:53 florian Exp $ */ 2018cebfbSflorian 3018cebfbSflorian /* 4018cebfbSflorian * Copyright (c) 2018 Florian Obser <florian@openbsd.org> 5018cebfbSflorian * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6018cebfbSflorian * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 7018cebfbSflorian * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8018cebfbSflorian * 9018cebfbSflorian * Permission to use, copy, modify, and distribute this software for any 10018cebfbSflorian * purpose with or without fee is hereby granted, provided that the above 11018cebfbSflorian * copyright notice and this permission notice appear in all copies. 12018cebfbSflorian * 13018cebfbSflorian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14018cebfbSflorian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15018cebfbSflorian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16018cebfbSflorian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17018cebfbSflorian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18018cebfbSflorian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19018cebfbSflorian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20018cebfbSflorian */ 21018cebfbSflorian #include <sys/types.h> 22018cebfbSflorian #include <sys/queue.h> 23018cebfbSflorian #include <sys/socket.h> 24296cf316Sflorian #include <sys/stat.h> 25018cebfbSflorian #include <sys/syslog.h> 26018cebfbSflorian #include <sys/wait.h> 27018cebfbSflorian 28018cebfbSflorian #include <net/if.h> 29018cebfbSflorian #include <net/route.h> 30018cebfbSflorian 31018cebfbSflorian #include <err.h> 32018cebfbSflorian #include <errno.h> 33018cebfbSflorian #include <event.h> 34018cebfbSflorian #include <fcntl.h> 35018cebfbSflorian #include <imsg.h> 36018cebfbSflorian #include <netdb.h> 37018cebfbSflorian #include <pwd.h> 38018cebfbSflorian #include <stdio.h> 39018cebfbSflorian #include <stdlib.h> 40018cebfbSflorian #include <string.h> 41018cebfbSflorian #include <signal.h> 42018cebfbSflorian #include <unistd.h> 43018cebfbSflorian 44018cebfbSflorian #include "uw_log.h" 45018cebfbSflorian #include "unwind.h" 46018cebfbSflorian #include "frontend.h" 47018cebfbSflorian #include "resolver.h" 48018cebfbSflorian #include "control.h" 49b2501eadSflorian #include "captiveportal.h" 50018cebfbSflorian 51296cf316Sflorian #define LEASE_DB_DIR "/var/db/" 52296cf316Sflorian #define _PATH_LEASE_DB "/var/db/dhclient.leases." 53296cf316Sflorian 54*90d56d5fSflorian #define TRUST_ANCHOR_FILE "/var/db/unwind.key" 55296cf316Sflorian 56018cebfbSflorian __dead void usage(void); 57018cebfbSflorian __dead void main_shutdown(void); 58018cebfbSflorian 59018cebfbSflorian void main_sig_handler(int, short, void *); 60018cebfbSflorian 61018cebfbSflorian static pid_t start_child(int, char *, int, int, int); 62018cebfbSflorian 63018cebfbSflorian void main_dispatch_frontend(int, short, void *); 64018cebfbSflorian void main_dispatch_resolver(int, short, void *); 65b2501eadSflorian void main_dispatch_captiveportal(int, short, void *); 66018cebfbSflorian 67b2501eadSflorian static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *, 68b2501eadSflorian struct imsgbuf *); 69018cebfbSflorian static int main_imsg_send_config(struct unwind_conf *); 70018cebfbSflorian 71018cebfbSflorian int main_reload(void); 72b2501eadSflorian int main_sendall(enum imsg_type, void *, uint16_t); 73018cebfbSflorian void open_dhcp_lease(int); 74d265a5d3Sflorian void open_ports(void); 75018cebfbSflorian 76018cebfbSflorian struct unwind_conf *main_conf; 77018cebfbSflorian struct imsgev *iev_frontend; 78018cebfbSflorian struct imsgev *iev_resolver; 79b2501eadSflorian struct imsgev *iev_captiveportal; 80018cebfbSflorian char *conffile; 81018cebfbSflorian 82018cebfbSflorian pid_t frontend_pid; 83018cebfbSflorian pid_t resolver_pid; 84b2501eadSflorian pid_t captiveportal_pid; 85018cebfbSflorian 86018cebfbSflorian uint32_t cmd_opts; 87018cebfbSflorian 88018cebfbSflorian void 89018cebfbSflorian main_sig_handler(int sig, short event, void *arg) 90018cebfbSflorian { 91018cebfbSflorian /* 92018cebfbSflorian * Normal signal handler rules don't apply because libevent 93018cebfbSflorian * decouples for us. 94018cebfbSflorian */ 95018cebfbSflorian 96018cebfbSflorian switch (sig) { 97018cebfbSflorian case SIGTERM: 98018cebfbSflorian case SIGINT: 995472663aSflorian main_shutdown(); 100018cebfbSflorian break; 101018cebfbSflorian case SIGHUP: 102018cebfbSflorian if (main_reload() == -1) 103018cebfbSflorian log_warnx("configuration reload failed"); 104018cebfbSflorian else 105018cebfbSflorian log_debug("configuration reloaded"); 106018cebfbSflorian break; 107018cebfbSflorian default: 108018cebfbSflorian fatalx("unexpected signal"); 109018cebfbSflorian } 110018cebfbSflorian } 111018cebfbSflorian 112018cebfbSflorian __dead void 113018cebfbSflorian usage(void) 114018cebfbSflorian { 115018cebfbSflorian extern char *__progname; 116018cebfbSflorian 117018cebfbSflorian fprintf(stderr, "usage: %s [-dnv] [-f file] [-s socket]\n", 118018cebfbSflorian __progname); 119018cebfbSflorian exit(1); 120018cebfbSflorian } 121018cebfbSflorian 122018cebfbSflorian int 123018cebfbSflorian main(int argc, char *argv[]) 124018cebfbSflorian { 125018cebfbSflorian struct event ev_sigint, ev_sigterm, ev_sighup; 126018cebfbSflorian int ch; 127b2501eadSflorian int debug = 0, resolver_flag = 0; 128b2501eadSflorian int frontend_flag = 0, captiveportal_flag = 0; 129018cebfbSflorian char *saved_argv0; 130018cebfbSflorian int pipe_main2frontend[2]; 131018cebfbSflorian int pipe_main2resolver[2]; 132b2501eadSflorian int pipe_main2captiveportal[2]; 133018cebfbSflorian int frontend_routesock, rtfilter; 134d1b04a40Sflorian int control_fd, ta_fd; 135018cebfbSflorian char *csock; 136018cebfbSflorian 137018cebfbSflorian conffile = CONF_FILE; 138018cebfbSflorian csock = UNWIND_SOCKET; 139018cebfbSflorian 140018cebfbSflorian log_init(1, LOG_DAEMON); /* Log to stderr until daemonized. */ 141018cebfbSflorian log_setverbose(1); 142018cebfbSflorian 143018cebfbSflorian saved_argv0 = argv[0]; 144018cebfbSflorian if (saved_argv0 == NULL) 145018cebfbSflorian saved_argv0 = "unwind"; 146018cebfbSflorian 147b2501eadSflorian while ((ch = getopt(argc, argv, "CdEFf:ns:v")) != -1) { 148018cebfbSflorian switch (ch) { 149b2501eadSflorian case 'C': 150b2501eadSflorian captiveportal_flag = 1; 151b2501eadSflorian break; 152018cebfbSflorian case 'd': 153018cebfbSflorian debug = 1; 154018cebfbSflorian break; 155018cebfbSflorian case 'E': 156018cebfbSflorian resolver_flag = 1; 157018cebfbSflorian break; 158018cebfbSflorian case 'F': 159018cebfbSflorian frontend_flag = 1; 160018cebfbSflorian break; 161018cebfbSflorian case 'f': 162018cebfbSflorian conffile = optarg; 163018cebfbSflorian break; 164018cebfbSflorian case 'n': 165018cebfbSflorian cmd_opts |= OPT_NOACTION; 166018cebfbSflorian break; 167018cebfbSflorian case 's': 168018cebfbSflorian csock = optarg; 169018cebfbSflorian break; 170018cebfbSflorian case 'v': 171018cebfbSflorian if (cmd_opts & OPT_VERBOSE) 172018cebfbSflorian cmd_opts |= OPT_VERBOSE2; 173018cebfbSflorian cmd_opts |= OPT_VERBOSE; 174018cebfbSflorian break; 175018cebfbSflorian default: 176018cebfbSflorian usage(); 177018cebfbSflorian } 178018cebfbSflorian } 179018cebfbSflorian 180018cebfbSflorian argc -= optind; 181018cebfbSflorian argv += optind; 182b2501eadSflorian if (argc > 0 || (resolver_flag && frontend_flag && captiveportal_flag)) 183018cebfbSflorian usage(); 184018cebfbSflorian 185018cebfbSflorian if (resolver_flag) 186018cebfbSflorian resolver(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 187018cebfbSflorian else if (frontend_flag) 188018cebfbSflorian frontend(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 189b2501eadSflorian else if (captiveportal_flag) 190b2501eadSflorian captiveportal(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 191018cebfbSflorian 192588e8263Sflorian if ((main_conf = parse_config(conffile)) == NULL) 193018cebfbSflorian exit(1); 194018cebfbSflorian 195018cebfbSflorian if (cmd_opts & OPT_NOACTION) { 196018cebfbSflorian if (cmd_opts & OPT_VERBOSE) 197018cebfbSflorian print_config(main_conf); 198018cebfbSflorian else 199018cebfbSflorian fprintf(stderr, "configuration OK\n"); 200018cebfbSflorian exit(0); 201018cebfbSflorian } 202018cebfbSflorian 203018cebfbSflorian /* Check for root privileges. */ 204018cebfbSflorian if (geteuid()) 205018cebfbSflorian errx(1, "need root privileges"); 206018cebfbSflorian 207018cebfbSflorian /* Check for assigned daemon user */ 208018cebfbSflorian if (getpwnam(UNWIND_USER) == NULL) 209018cebfbSflorian errx(1, "unknown user %s", UNWIND_USER); 210018cebfbSflorian 211018cebfbSflorian log_init(debug, LOG_DAEMON); 212018cebfbSflorian log_setverbose(cmd_opts & OPT_VERBOSE); 213018cebfbSflorian 214018cebfbSflorian if (!debug) 215018cebfbSflorian daemon(1, 0); 216018cebfbSflorian 217018cebfbSflorian log_info("startup"); 218018cebfbSflorian 219018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 220018cebfbSflorian PF_UNSPEC, pipe_main2frontend) == -1) 221018cebfbSflorian fatal("main2frontend socketpair"); 222018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 223018cebfbSflorian PF_UNSPEC, pipe_main2resolver) == -1) 224018cebfbSflorian fatal("main2resolver socketpair"); 225b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 226b2501eadSflorian PF_UNSPEC, pipe_main2captiveportal) == -1) 227b2501eadSflorian fatal("main2captiveportal socketpair"); 228018cebfbSflorian 229018cebfbSflorian /* Start children. */ 230018cebfbSflorian resolver_pid = start_child(PROC_RESOLVER, saved_argv0, 231018cebfbSflorian pipe_main2resolver[1], debug, cmd_opts & (OPT_VERBOSE | 232018cebfbSflorian OPT_VERBOSE2)); 233018cebfbSflorian frontend_pid = start_child(PROC_FRONTEND, saved_argv0, 234018cebfbSflorian pipe_main2frontend[1], debug, cmd_opts & (OPT_VERBOSE | 235018cebfbSflorian OPT_VERBOSE2)); 236b2501eadSflorian captiveportal_pid = start_child(PROC_CAPTIVEPORTAL, saved_argv0, 237b2501eadSflorian pipe_main2captiveportal[1], debug, cmd_opts & (OPT_VERBOSE | 238b2501eadSflorian OPT_VERBOSE2)); 239018cebfbSflorian 240018cebfbSflorian unwind_process = PROC_MAIN; 241018cebfbSflorian log_procinit(log_procnames[unwind_process]); 242018cebfbSflorian 243018cebfbSflorian event_init(); 244018cebfbSflorian 245018cebfbSflorian /* Setup signal handler. */ 246018cebfbSflorian signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 247018cebfbSflorian signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 248018cebfbSflorian signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 249018cebfbSflorian signal_add(&ev_sigint, NULL); 250018cebfbSflorian signal_add(&ev_sigterm, NULL); 251018cebfbSflorian signal_add(&ev_sighup, NULL); 252018cebfbSflorian signal(SIGPIPE, SIG_IGN); 253018cebfbSflorian 254018cebfbSflorian /* Setup pipes to children. */ 255018cebfbSflorian 256018cebfbSflorian if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL || 257b2501eadSflorian (iev_captiveportal = malloc(sizeof(struct imsgev))) == NULL || 258018cebfbSflorian (iev_resolver = malloc(sizeof(struct imsgev))) == NULL) 259018cebfbSflorian fatal(NULL); 260018cebfbSflorian imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]); 261018cebfbSflorian iev_frontend->handler = main_dispatch_frontend; 262018cebfbSflorian imsg_init(&iev_resolver->ibuf, pipe_main2resolver[0]); 263018cebfbSflorian iev_resolver->handler = main_dispatch_resolver; 264b2501eadSflorian imsg_init(&iev_captiveportal->ibuf, pipe_main2captiveportal[0]); 265b2501eadSflorian iev_captiveportal->handler = main_dispatch_captiveportal; 266018cebfbSflorian 267b2501eadSflorian /* Setup event handlers for pipes. */ 268018cebfbSflorian iev_frontend->events = EV_READ; 269018cebfbSflorian event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 270018cebfbSflorian iev_frontend->events, iev_frontend->handler, iev_frontend); 271018cebfbSflorian event_add(&iev_frontend->ev, NULL); 272018cebfbSflorian 273018cebfbSflorian iev_resolver->events = EV_READ; 274018cebfbSflorian event_set(&iev_resolver->ev, iev_resolver->ibuf.fd, iev_resolver->events, 275018cebfbSflorian iev_resolver->handler, iev_resolver); 276018cebfbSflorian event_add(&iev_resolver->ev, NULL); 277018cebfbSflorian 278b2501eadSflorian iev_captiveportal->events = EV_READ; 279b2501eadSflorian event_set(&iev_captiveportal->ev, iev_captiveportal->ibuf.fd, 280b2501eadSflorian iev_captiveportal->events, iev_captiveportal->handler, 281b2501eadSflorian iev_captiveportal); 282b2501eadSflorian event_add(&iev_captiveportal->ev, NULL); 283b2501eadSflorian 284b2501eadSflorian if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, 285b2501eadSflorian &iev_resolver->ibuf, &iev_captiveportal->ibuf)) 286018cebfbSflorian fatal("could not establish imsg links"); 287018cebfbSflorian 288018cebfbSflorian if ((control_fd = control_init(csock)) == -1) 289018cebfbSflorian fatalx("control socket setup failed"); 290018cebfbSflorian 2919e627e00Sflorian if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 292018cebfbSflorian AF_INET)) < 0) 293018cebfbSflorian fatal("route socket"); 294018cebfbSflorian 295018cebfbSflorian rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_PROPOSAL) | 296018cebfbSflorian ROUTE_FILTER(RTM_GET); 2979e627e00Sflorian if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER, 298018cebfbSflorian &rtfilter, sizeof(rtfilter)) < 0) 299018cebfbSflorian fatal("setsockopt(ROUTE_MSGFILTER)"); 300018cebfbSflorian 301d1b04a40Sflorian if ((ta_fd = open(TRUST_ANCHOR_FILE, O_RDWR | O_CREAT, 0644)) == -1) 302d1b04a40Sflorian log_warn("%s", TRUST_ANCHOR_FILE); 303d1b04a40Sflorian 304d1b04a40Sflorian /* receiver handles failed open correctly */ 305d1b04a40Sflorian main_imsg_compose_frontend_fd(IMSG_TAFD, 0, ta_fd); 306d1b04a40Sflorian 307018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd); 308018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock); 309018cebfbSflorian main_imsg_send_config(main_conf); 310018cebfbSflorian 311296cf316Sflorian if (unveil(LEASE_DB_DIR, "r") == -1 && errno != ENOENT) 312296cf316Sflorian err(1, "unveil"); 313296cf316Sflorian 314d1b04a40Sflorian if (pledge("stdio inet dns rpath sendfd", NULL) == -1) 315018cebfbSflorian fatal("pledge"); 316018cebfbSflorian 317018cebfbSflorian main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0); 318296cf316Sflorian main_imsg_compose_resolver(IMSG_STARTUP, 0, NULL, 0); 319018cebfbSflorian 320018cebfbSflorian event_dispatch(); 321018cebfbSflorian 322018cebfbSflorian main_shutdown(); 323018cebfbSflorian return (0); 324018cebfbSflorian } 325018cebfbSflorian 326018cebfbSflorian __dead void 327018cebfbSflorian main_shutdown(void) 328018cebfbSflorian { 329018cebfbSflorian pid_t pid; 330018cebfbSflorian int status; 331018cebfbSflorian 332018cebfbSflorian /* Close pipes. */ 333018cebfbSflorian msgbuf_clear(&iev_frontend->ibuf.w); 334018cebfbSflorian close(iev_frontend->ibuf.fd); 335018cebfbSflorian msgbuf_clear(&iev_resolver->ibuf.w); 336018cebfbSflorian close(iev_resolver->ibuf.fd); 337b2501eadSflorian msgbuf_clear(&iev_captiveportal->ibuf.w); 338b2501eadSflorian close(iev_captiveportal->ibuf.fd); 339018cebfbSflorian 340018cebfbSflorian config_clear(main_conf); 341018cebfbSflorian 342018cebfbSflorian log_debug("waiting for children to terminate"); 343018cebfbSflorian do { 344018cebfbSflorian pid = wait(&status); 345018cebfbSflorian if (pid == -1) { 346018cebfbSflorian if (errno != EINTR && errno != ECHILD) 347018cebfbSflorian fatal("wait"); 348018cebfbSflorian } else if (WIFSIGNALED(status)) 349018cebfbSflorian log_warnx("%s terminated; signal %d", 350018cebfbSflorian (pid == resolver_pid) ? "resolver" : 351018cebfbSflorian "frontend", WTERMSIG(status)); 352018cebfbSflorian } while (pid != -1 || (pid == -1 && errno == EINTR)); 353018cebfbSflorian 354018cebfbSflorian free(iev_frontend); 355018cebfbSflorian free(iev_resolver); 356b2501eadSflorian free(iev_captiveportal); 357018cebfbSflorian 358018cebfbSflorian log_info("terminating"); 359018cebfbSflorian exit(0); 360018cebfbSflorian } 361018cebfbSflorian 362018cebfbSflorian static pid_t 363018cebfbSflorian start_child(int p, char *argv0, int fd, int debug, int verbose) 364018cebfbSflorian { 365018cebfbSflorian char *argv[7]; 366018cebfbSflorian int argc = 0; 367018cebfbSflorian pid_t pid; 368018cebfbSflorian 369018cebfbSflorian switch (pid = fork()) { 370018cebfbSflorian case -1: 371018cebfbSflorian fatal("cannot fork"); 372018cebfbSflorian case 0: 373018cebfbSflorian break; 374018cebfbSflorian default: 375018cebfbSflorian close(fd); 376018cebfbSflorian return (pid); 377018cebfbSflorian } 378018cebfbSflorian 379018cebfbSflorian if (dup2(fd, 3) == -1) 380018cebfbSflorian fatal("cannot setup imsg fd"); 381018cebfbSflorian 382018cebfbSflorian argv[argc++] = argv0; 383018cebfbSflorian switch (p) { 384018cebfbSflorian case PROC_MAIN: 385018cebfbSflorian fatalx("Can not start main process"); 386018cebfbSflorian case PROC_RESOLVER: 387018cebfbSflorian argv[argc++] = "-E"; 388018cebfbSflorian break; 389018cebfbSflorian case PROC_FRONTEND: 390018cebfbSflorian argv[argc++] = "-F"; 391018cebfbSflorian break; 392b2501eadSflorian case PROC_CAPTIVEPORTAL: 393b2501eadSflorian argv[argc++] = "-C"; 394b2501eadSflorian break; 395018cebfbSflorian } 396018cebfbSflorian if (debug) 397018cebfbSflorian argv[argc++] = "-d"; 398018cebfbSflorian if (verbose & OPT_VERBOSE) 399018cebfbSflorian argv[argc++] = "-v"; 400018cebfbSflorian if (verbose & OPT_VERBOSE2) 401018cebfbSflorian argv[argc++] = "-v"; 402018cebfbSflorian argv[argc++] = NULL; 403018cebfbSflorian 404018cebfbSflorian execvp(argv0, argv); 405018cebfbSflorian fatal("execvp"); 406018cebfbSflorian } 407018cebfbSflorian 408018cebfbSflorian void 409018cebfbSflorian main_dispatch_frontend(int fd, short event, void *bula) 410018cebfbSflorian { 411018cebfbSflorian struct imsgev *iev = bula; 412018cebfbSflorian struct imsgbuf *ibuf; 413018cebfbSflorian struct imsg imsg; 414018cebfbSflorian ssize_t n; 415018cebfbSflorian int shut = 0, verbose; 416018cebfbSflorian u_short rtm_index; 417018cebfbSflorian 418018cebfbSflorian ibuf = &iev->ibuf; 419018cebfbSflorian 420018cebfbSflorian if (event & EV_READ) { 421018cebfbSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 422018cebfbSflorian fatal("imsg_read error"); 423018cebfbSflorian if (n == 0) /* Connection closed. */ 424018cebfbSflorian shut = 1; 425018cebfbSflorian } 426018cebfbSflorian if (event & EV_WRITE) { 427018cebfbSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 428018cebfbSflorian fatal("msgbuf_write"); 429018cebfbSflorian if (n == 0) /* Connection closed. */ 430018cebfbSflorian shut = 1; 431018cebfbSflorian } 432018cebfbSflorian 433018cebfbSflorian for (;;) { 434018cebfbSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 435018cebfbSflorian fatal("imsg_get"); 436018cebfbSflorian if (n == 0) /* No more messages. */ 437018cebfbSflorian break; 438018cebfbSflorian 439018cebfbSflorian switch (imsg.hdr.type) { 440018cebfbSflorian case IMSG_STARTUP_DONE: 441018cebfbSflorian break; 442018cebfbSflorian case IMSG_CTL_RELOAD: 443018cebfbSflorian if (main_reload() == -1) 444018cebfbSflorian log_warnx("configuration reload failed"); 445018cebfbSflorian else 446018cebfbSflorian log_warnx("configuration reloaded"); 447018cebfbSflorian break; 448018cebfbSflorian case IMSG_CTL_LOG_VERBOSE: 4492b821978Sflorian if (imsg.hdr.len != IMSG_HEADER_SIZE + 4502b821978Sflorian sizeof(verbose)) 4512b821978Sflorian fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 4522b821978Sflorian "%d", __func__, imsg.hdr.len); 453018cebfbSflorian memcpy(&verbose, imsg.data, sizeof(verbose)); 454018cebfbSflorian log_setverbose(verbose); 455018cebfbSflorian break; 456018cebfbSflorian case IMSG_OPEN_DHCP_LEASE: 4572b821978Sflorian if (imsg.hdr.len != IMSG_HEADER_SIZE + 4582b821978Sflorian sizeof(rtm_index)) 4592b821978Sflorian fatalx("%s: IMSG_OPEN_DHCP_LEASE wrong length: " 4602b821978Sflorian "%d", __func__, imsg.hdr.len); 461018cebfbSflorian memcpy(&rtm_index, imsg.data, sizeof(rtm_index)); 462018cebfbSflorian open_dhcp_lease(rtm_index); 463018cebfbSflorian break; 464d265a5d3Sflorian case IMSG_OPEN_PORTS: 465d265a5d3Sflorian open_ports(); 466d265a5d3Sflorian break; 467018cebfbSflorian default: 468018cebfbSflorian log_debug("%s: error handling imsg %d", __func__, 469018cebfbSflorian imsg.hdr.type); 470018cebfbSflorian break; 471018cebfbSflorian } 472018cebfbSflorian imsg_free(&imsg); 473018cebfbSflorian } 474018cebfbSflorian if (!shut) 475018cebfbSflorian imsg_event_add(iev); 476018cebfbSflorian else { 477018cebfbSflorian /* This pipe is dead. Remove its event handler */ 478018cebfbSflorian event_del(&iev->ev); 479018cebfbSflorian event_loopexit(NULL); 480018cebfbSflorian } 481018cebfbSflorian } 482018cebfbSflorian 483018cebfbSflorian void 484018cebfbSflorian main_dispatch_resolver(int fd, short event, void *bula) 485018cebfbSflorian { 486018cebfbSflorian struct imsgev *iev = bula; 487018cebfbSflorian struct imsgbuf *ibuf; 488018cebfbSflorian struct imsg imsg; 489b2501eadSflorian struct sockaddr_in sin; 490b2501eadSflorian ssize_t n; 491b2501eadSflorian int shut = 0, httpsock; 492b2501eadSflorian 493b2501eadSflorian ibuf = &iev->ibuf; 494b2501eadSflorian 495b2501eadSflorian if (event & EV_READ) { 496b2501eadSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 497b2501eadSflorian fatal("imsg_read error"); 498b2501eadSflorian if (n == 0) /* Connection closed. */ 499b2501eadSflorian shut = 1; 500b2501eadSflorian } 501b2501eadSflorian if (event & EV_WRITE) { 502b2501eadSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 503b2501eadSflorian fatal("msgbuf_write"); 504b2501eadSflorian if (n == 0) /* Connection closed. */ 505b2501eadSflorian shut = 1; 506b2501eadSflorian } 507b2501eadSflorian 508b2501eadSflorian for (;;) { 509b2501eadSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 510b2501eadSflorian fatal("imsg_get"); 511b2501eadSflorian if (n == 0) /* No more messages. */ 512b2501eadSflorian break; 513b2501eadSflorian 514b2501eadSflorian switch (imsg.hdr.type) { 515b2501eadSflorian case IMSG_OPEN_HTTP_PORT: 516b2501eadSflorian if (imsg.hdr.len != IMSG_HEADER_SIZE + 517b2501eadSflorian sizeof(sin)) 518b2501eadSflorian fatalx("%s: IMSG_OPEN_HTTP_PORT wrong length: " 519b2501eadSflorian "%d", __func__, imsg.hdr.len); 520b2501eadSflorian memcpy(&sin, imsg.data, sizeof(sin)); 521b2501eadSflorian 522b2501eadSflorian if ((httpsock = socket(AF_INET, SOCK_STREAM | 523b2501eadSflorian SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { 524b2501eadSflorian log_warn("%s: socket", __func__); 525b2501eadSflorian break; 526b2501eadSflorian } 527b2501eadSflorian if (connect(httpsock, (struct sockaddr *)&sin, 528b2501eadSflorian sin.sin_len) == -1) { 529b2501eadSflorian if (errno != EINPROGRESS) { 530b2501eadSflorian log_warn("%s: connect", __func__); 531b2501eadSflorian close(httpsock); 532b2501eadSflorian break; 533b2501eadSflorian } 534b2501eadSflorian } 535b2501eadSflorian main_imsg_compose_captiveportal_fd(IMSG_HTTPSOCK, 0, 536b2501eadSflorian httpsock); 537b2501eadSflorian break; 538b2501eadSflorian default: 539b2501eadSflorian log_debug("%s: error handling imsg %d", __func__, 540b2501eadSflorian imsg.hdr.type); 541b2501eadSflorian break; 542b2501eadSflorian } 543b2501eadSflorian imsg_free(&imsg); 544b2501eadSflorian } 545b2501eadSflorian if (!shut) 546b2501eadSflorian imsg_event_add(iev); 547b2501eadSflorian else { 548b2501eadSflorian /* This pipe is dead. Remove its event handler. */ 549b2501eadSflorian event_del(&iev->ev); 550b2501eadSflorian event_loopexit(NULL); 551b2501eadSflorian } 552b2501eadSflorian } 553b2501eadSflorian 554b2501eadSflorian void 555b2501eadSflorian main_dispatch_captiveportal(int fd, short event, void *bula) 556b2501eadSflorian { 557b2501eadSflorian struct imsgev *iev = bula; 558b2501eadSflorian struct imsgbuf *ibuf; 559b2501eadSflorian struct imsg imsg; 560018cebfbSflorian ssize_t n; 561018cebfbSflorian int shut = 0; 562018cebfbSflorian 563018cebfbSflorian ibuf = &iev->ibuf; 564018cebfbSflorian 565018cebfbSflorian if (event & EV_READ) { 566018cebfbSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 567018cebfbSflorian fatal("imsg_read error"); 568018cebfbSflorian if (n == 0) /* Connection closed. */ 569018cebfbSflorian shut = 1; 570018cebfbSflorian } 571018cebfbSflorian if (event & EV_WRITE) { 572018cebfbSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 573018cebfbSflorian fatal("msgbuf_write"); 574018cebfbSflorian if (n == 0) /* Connection closed. */ 575018cebfbSflorian shut = 1; 576018cebfbSflorian } 577018cebfbSflorian 578018cebfbSflorian for (;;) { 579018cebfbSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 580018cebfbSflorian fatal("imsg_get"); 581018cebfbSflorian if (n == 0) /* No more messages. */ 582018cebfbSflorian break; 583018cebfbSflorian 584018cebfbSflorian switch (imsg.hdr.type) { 585018cebfbSflorian default: 586018cebfbSflorian log_debug("%s: error handling imsg %d", __func__, 587018cebfbSflorian imsg.hdr.type); 588018cebfbSflorian break; 589018cebfbSflorian } 590018cebfbSflorian imsg_free(&imsg); 591018cebfbSflorian } 592018cebfbSflorian if (!shut) 593018cebfbSflorian imsg_event_add(iev); 594018cebfbSflorian else { 595018cebfbSflorian /* This pipe is dead. Remove its event handler. */ 596018cebfbSflorian event_del(&iev->ev); 597018cebfbSflorian event_loopexit(NULL); 598018cebfbSflorian } 599018cebfbSflorian } 600018cebfbSflorian 601018cebfbSflorian void 602018cebfbSflorian main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) 603018cebfbSflorian { 604018cebfbSflorian if (iev_frontend) 605018cebfbSflorian imsg_compose_event(iev_frontend, type, 0, pid, -1, data, 606018cebfbSflorian datalen); 607018cebfbSflorian } 608018cebfbSflorian 609018cebfbSflorian void 610018cebfbSflorian main_imsg_compose_frontend_fd(int type, pid_t pid, int fd) 611018cebfbSflorian { 612018cebfbSflorian if (iev_frontend) 613018cebfbSflorian imsg_compose_event(iev_frontend, type, 0, pid, fd, NULL, 0); 614018cebfbSflorian } 615018cebfbSflorian 616018cebfbSflorian void 617018cebfbSflorian main_imsg_compose_resolver(int type, pid_t pid, void *data, uint16_t datalen) 618018cebfbSflorian { 619018cebfbSflorian if (iev_resolver) 620018cebfbSflorian imsg_compose_event(iev_resolver, type, 0, pid, -1, data, 621018cebfbSflorian datalen); 622018cebfbSflorian } 623018cebfbSflorian 624018cebfbSflorian void 625b2501eadSflorian main_imsg_compose_captiveportal(int type, pid_t pid, void *data, 626b2501eadSflorian uint16_t datalen) 627b2501eadSflorian { 628b2501eadSflorian if (iev_captiveportal) 629b2501eadSflorian imsg_compose_event(iev_captiveportal, type, 0, pid, -1, data, 630b2501eadSflorian datalen); 631b2501eadSflorian } 632b2501eadSflorian 633b2501eadSflorian void 634b2501eadSflorian main_imsg_compose_captiveportal_fd(int type, pid_t pid, int fd) 635b2501eadSflorian { 636b2501eadSflorian if (iev_frontend) 637b2501eadSflorian imsg_compose_event(iev_captiveportal, type, 0, pid, fd, NULL, 638b2501eadSflorian 0); 639b2501eadSflorian } 640b2501eadSflorian 641b2501eadSflorian void 642018cebfbSflorian imsg_event_add(struct imsgev *iev) 643018cebfbSflorian { 644018cebfbSflorian iev->events = EV_READ; 645018cebfbSflorian if (iev->ibuf.w.queued) 646018cebfbSflorian iev->events |= EV_WRITE; 647018cebfbSflorian 648018cebfbSflorian event_del(&iev->ev); 649018cebfbSflorian event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 650018cebfbSflorian event_add(&iev->ev, NULL); 651018cebfbSflorian } 652018cebfbSflorian 653018cebfbSflorian int 654018cebfbSflorian imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 655018cebfbSflorian pid_t pid, int fd, void *data, uint16_t datalen) 656018cebfbSflorian { 657018cebfbSflorian int ret; 658018cebfbSflorian 659018cebfbSflorian if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, 660018cebfbSflorian datalen)) != -1) 661018cebfbSflorian imsg_event_add(iev); 662018cebfbSflorian 663018cebfbSflorian return (ret); 664018cebfbSflorian } 665018cebfbSflorian 666018cebfbSflorian static int 667018cebfbSflorian main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf, 668b2501eadSflorian struct imsgbuf *resolver_buf, struct imsgbuf *captiveportal_buf) 669018cebfbSflorian { 670018cebfbSflorian int pipe_frontend2resolver[2]; 671b2501eadSflorian int pipe_frontend2captiveportal[2]; 672b2501eadSflorian int pipe_resolver2captiveportal[2]; 673018cebfbSflorian 674018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 675018cebfbSflorian PF_UNSPEC, pipe_frontend2resolver) == -1) 676018cebfbSflorian return (-1); 677018cebfbSflorian 678b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 679b2501eadSflorian PF_UNSPEC, pipe_frontend2captiveportal) == -1) 680b2501eadSflorian return (-1); 681b2501eadSflorian 682b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 683b2501eadSflorian PF_UNSPEC, pipe_resolver2captiveportal) == -1) 684b2501eadSflorian return (-1); 685b2501eadSflorian 686b2501eadSflorian if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0, 687018cebfbSflorian pipe_frontend2resolver[0], NULL, 0) == -1) 688018cebfbSflorian return (-1); 689b2501eadSflorian if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0, 690018cebfbSflorian pipe_frontend2resolver[1], NULL, 0) == -1) 691018cebfbSflorian return (-1); 692018cebfbSflorian 693b2501eadSflorian if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_CAPTIVEPORTAL, 0, 0, 694b2501eadSflorian pipe_frontend2captiveportal[0], NULL, 0) == -1) 695b2501eadSflorian return (-1); 696b2501eadSflorian if (imsg_compose(captiveportal_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0, 697b2501eadSflorian pipe_frontend2captiveportal[1], NULL, 0) == -1) 698b2501eadSflorian return (-1); 699b2501eadSflorian 700b2501eadSflorian if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_CAPTIVEPORTAL, 0, 0, 701b2501eadSflorian pipe_resolver2captiveportal[0], NULL, 0) == -1) 702b2501eadSflorian return (-1); 703b2501eadSflorian if (imsg_compose(captiveportal_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0, 704b2501eadSflorian pipe_resolver2captiveportal[1], NULL, 0) == -1) 705b2501eadSflorian return (-1); 706b2501eadSflorian 707018cebfbSflorian return (0); 708018cebfbSflorian } 709018cebfbSflorian 710018cebfbSflorian int 711018cebfbSflorian main_reload(void) 712018cebfbSflorian { 713018cebfbSflorian struct unwind_conf *xconf; 714018cebfbSflorian 715018cebfbSflorian if ((xconf = parse_config(conffile)) == NULL) 716018cebfbSflorian return (-1); 717018cebfbSflorian 718018cebfbSflorian if (main_imsg_send_config(xconf) == -1) 719018cebfbSflorian return (-1); 720018cebfbSflorian 721018cebfbSflorian merge_config(main_conf, xconf); 722018cebfbSflorian 723018cebfbSflorian return (0); 724018cebfbSflorian } 725018cebfbSflorian 726018cebfbSflorian int 727018cebfbSflorian main_imsg_send_config(struct unwind_conf *xconf) 728018cebfbSflorian { 729018cebfbSflorian struct unwind_forwarder *unwind_forwarder; 730018cebfbSflorian 731018cebfbSflorian /* Send fixed part of config to children. */ 732b2501eadSflorian if (main_sendall(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 733018cebfbSflorian return (-1); 734b2501eadSflorian if (xconf->captive_portal_host != NULL) { 735b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_HOST, 736b2501eadSflorian xconf->captive_portal_host, 737b2501eadSflorian strlen(xconf->captive_portal_host) + 1) == -1) 738b2501eadSflorian return (-1); 739b2501eadSflorian } 740b2501eadSflorian 741b2501eadSflorian if (xconf->captive_portal_path != NULL) { 742b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_PATH, 743b2501eadSflorian xconf->captive_portal_path, 744b2501eadSflorian strlen(xconf->captive_portal_path) + 1) == -1) 745b2501eadSflorian return (-1); 746b2501eadSflorian } 747b2501eadSflorian 748b2501eadSflorian if (xconf->captive_portal_expected_response != NULL) { 749b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_EXPECTED_RESPONSE, 750b2501eadSflorian xconf->captive_portal_expected_response, 751b2501eadSflorian strlen(xconf->captive_portal_expected_response) + 1) 752b2501eadSflorian == -1) 753b2501eadSflorian return (-1); 754b2501eadSflorian } 755018cebfbSflorian 7563570995aSflorian /* send static forwarders to children */ 757018cebfbSflorian SIMPLEQ_FOREACH(unwind_forwarder, &xconf->unwind_forwarder_list, entry) { 758b2501eadSflorian if (main_sendall(IMSG_RECONF_FORWARDER, unwind_forwarder, 759018cebfbSflorian sizeof(*unwind_forwarder)) == -1) 760018cebfbSflorian return (-1); 761018cebfbSflorian } 762018cebfbSflorian 7633570995aSflorian /* send static DoT forwarders to children */ 7643570995aSflorian SIMPLEQ_FOREACH(unwind_forwarder, &xconf->unwind_dot_forwarder_list, 7653570995aSflorian entry) { 766b2501eadSflorian if (main_sendall(IMSG_RECONF_DOT_FORWARDER, unwind_forwarder, 7673570995aSflorian sizeof(*unwind_forwarder)) == -1) 7683570995aSflorian return (-1); 7693570995aSflorian } 7703570995aSflorian 771018cebfbSflorian /* Tell children the revised config is now complete. */ 772b2501eadSflorian if (main_sendall(IMSG_RECONF_END, NULL, 0) == -1) 773018cebfbSflorian return (-1); 774018cebfbSflorian 775018cebfbSflorian return (0); 776018cebfbSflorian } 777018cebfbSflorian 778018cebfbSflorian int 779b2501eadSflorian main_sendall(enum imsg_type type, void *buf, uint16_t len) 780018cebfbSflorian { 781018cebfbSflorian if (imsg_compose_event(iev_frontend, type, 0, 0, -1, buf, len) == -1) 782018cebfbSflorian return (-1); 783018cebfbSflorian if (imsg_compose_event(iev_resolver, type, 0, 0, -1, buf, len) == -1) 784018cebfbSflorian return (-1); 785b2501eadSflorian if (imsg_compose_event(iev_captiveportal, type, 0, 0, -1, buf, len) == 786b2501eadSflorian -1) 787b2501eadSflorian return (-1); 788018cebfbSflorian return (0); 789018cebfbSflorian } 790018cebfbSflorian 791018cebfbSflorian void 792018cebfbSflorian merge_config(struct unwind_conf *conf, struct unwind_conf *xconf) 793018cebfbSflorian { 794018cebfbSflorian struct unwind_forwarder *unwind_forwarder; 795018cebfbSflorian 796018cebfbSflorian /* Remove & discard existing forwarders. */ 797018cebfbSflorian while ((unwind_forwarder = 798018cebfbSflorian SIMPLEQ_FIRST(&conf->unwind_forwarder_list)) != NULL) { 799018cebfbSflorian SIMPLEQ_REMOVE_HEAD(&conf->unwind_forwarder_list, entry); 800018cebfbSflorian free(unwind_forwarder); 801018cebfbSflorian } 8023570995aSflorian while ((unwind_forwarder = 8033570995aSflorian SIMPLEQ_FIRST(&conf->unwind_dot_forwarder_list)) != NULL) { 8043570995aSflorian SIMPLEQ_REMOVE_HEAD(&conf->unwind_dot_forwarder_list, entry); 8053570995aSflorian free(unwind_forwarder); 8063570995aSflorian } 807018cebfbSflorian 808018cebfbSflorian conf->unwind_options = xconf->unwind_options; 809018cebfbSflorian 810b2501eadSflorian free(conf->captive_portal_host); 811b2501eadSflorian conf->captive_portal_host = xconf->captive_portal_host; 812b2501eadSflorian 813b2501eadSflorian free(conf->captive_portal_path); 814b2501eadSflorian conf->captive_portal_path = xconf->captive_portal_path; 815b2501eadSflorian 816b2501eadSflorian free(conf->captive_portal_expected_response); 817b2501eadSflorian conf->captive_portal_expected_response = 818b2501eadSflorian xconf->captive_portal_expected_response; 819b2501eadSflorian 820b2501eadSflorian conf->captive_portal_expected_status = 821b2501eadSflorian xconf->captive_portal_expected_status; 822b2501eadSflorian 823b2501eadSflorian conf->captive_portal_auto = xconf->captive_portal_auto; 824b2501eadSflorian 825018cebfbSflorian /* Add new forwarders. */ 826018cebfbSflorian while ((unwind_forwarder = 827018cebfbSflorian SIMPLEQ_FIRST(&xconf->unwind_forwarder_list)) != NULL) { 828018cebfbSflorian SIMPLEQ_REMOVE_HEAD(&xconf->unwind_forwarder_list, entry); 829018cebfbSflorian SIMPLEQ_INSERT_TAIL(&conf->unwind_forwarder_list, 830018cebfbSflorian unwind_forwarder, entry); 831018cebfbSflorian } 8323570995aSflorian while ((unwind_forwarder = 8333570995aSflorian SIMPLEQ_FIRST(&xconf->unwind_dot_forwarder_list)) != NULL) { 8343570995aSflorian SIMPLEQ_REMOVE_HEAD(&xconf->unwind_dot_forwarder_list, entry); 8353570995aSflorian SIMPLEQ_INSERT_TAIL(&conf->unwind_dot_forwarder_list, 8363570995aSflorian unwind_forwarder, entry); 8373570995aSflorian } 838018cebfbSflorian 839018cebfbSflorian free(xconf); 840018cebfbSflorian } 841018cebfbSflorian 842018cebfbSflorian struct unwind_conf * 843018cebfbSflorian config_new_empty(void) 844018cebfbSflorian { 845018cebfbSflorian struct unwind_conf *xconf; 846018cebfbSflorian 847018cebfbSflorian xconf = calloc(1, sizeof(*xconf)); 848018cebfbSflorian if (xconf == NULL) 849018cebfbSflorian fatal(NULL); 850018cebfbSflorian 851018cebfbSflorian SIMPLEQ_INIT(&xconf->unwind_forwarder_list); 8523570995aSflorian SIMPLEQ_INIT(&xconf->unwind_dot_forwarder_list); 853018cebfbSflorian 854b2501eadSflorian if ((xconf->captive_portal_expected_response = strdup("")) == NULL) 855b2501eadSflorian fatal(NULL); 856b2501eadSflorian xconf->captive_portal_expected_status = 200; 857b2501eadSflorian xconf->captive_portal_auto = 1; 858b2501eadSflorian 859018cebfbSflorian return (xconf); 860018cebfbSflorian } 861018cebfbSflorian 862018cebfbSflorian void 863018cebfbSflorian config_clear(struct unwind_conf *conf) 864018cebfbSflorian { 865018cebfbSflorian struct unwind_conf *xconf; 866018cebfbSflorian 867018cebfbSflorian /* Merge current config with an empty config. */ 868018cebfbSflorian xconf = config_new_empty(); 869018cebfbSflorian merge_config(conf, xconf); 870018cebfbSflorian 871018cebfbSflorian free(conf); 872018cebfbSflorian } 873018cebfbSflorian 874018cebfbSflorian void 875018cebfbSflorian open_dhcp_lease(int if_idx) 876018cebfbSflorian { 877018cebfbSflorian static char lease_filename[sizeof(_PATH_LEASE_DB) + IF_NAMESIZE] = 878018cebfbSflorian _PATH_LEASE_DB; 879018cebfbSflorian 880018cebfbSflorian int fd; 881018cebfbSflorian char *bufp; 882018cebfbSflorian 883018cebfbSflorian bufp = lease_filename + sizeof(_PATH_LEASE_DB) - 1; 884018cebfbSflorian bufp = if_indextoname(if_idx, bufp); 885018cebfbSflorian 886018cebfbSflorian if (bufp == NULL) { 887018cebfbSflorian log_debug("cannot find interface %d", if_idx); 888018cebfbSflorian return; 889018cebfbSflorian } 890018cebfbSflorian 891018cebfbSflorian log_debug("lease file name: %s", lease_filename); 892018cebfbSflorian 893018cebfbSflorian if ((fd = open(lease_filename, O_RDONLY)) == -1) { 894018cebfbSflorian log_warn(NULL); 895018cebfbSflorian return; 896018cebfbSflorian } 897018cebfbSflorian 898018cebfbSflorian 899018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_LEASEFD, 0, fd); 900018cebfbSflorian } 901d265a5d3Sflorian 902d265a5d3Sflorian void 903d265a5d3Sflorian open_ports(void) 904d265a5d3Sflorian { 905d265a5d3Sflorian struct addrinfo hints, *res0; 906d265a5d3Sflorian int udp4sock = -1, udp6sock = -1, error; 907d265a5d3Sflorian 908d265a5d3Sflorian memset(&hints, 0, sizeof(hints)); 909d265a5d3Sflorian hints.ai_family = AF_INET; 910d265a5d3Sflorian hints.ai_socktype = SOCK_DGRAM; 911d265a5d3Sflorian hints.ai_flags = AI_PASSIVE; 912d265a5d3Sflorian 913d265a5d3Sflorian error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); 914d265a5d3Sflorian if (!error && res0) { 915d265a5d3Sflorian if ((udp4sock = socket(res0->ai_family, res0->ai_socktype, 916d265a5d3Sflorian res0->ai_protocol)) != -1) { 917d265a5d3Sflorian if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen) 918d265a5d3Sflorian == -1) { 919d265a5d3Sflorian close(udp4sock); 920d265a5d3Sflorian udp4sock = -1; 921d265a5d3Sflorian } 922d265a5d3Sflorian } 923d265a5d3Sflorian } 924296cf316Sflorian if (res0) 925d265a5d3Sflorian freeaddrinfo(res0); 926d265a5d3Sflorian 927d265a5d3Sflorian hints.ai_family = AF_INET6; 928d265a5d3Sflorian error = getaddrinfo("::1", "domain", &hints, &res0); 929d265a5d3Sflorian if (!error && res0) { 930d265a5d3Sflorian if ((udp6sock = socket(res0->ai_family, res0->ai_socktype, 931d265a5d3Sflorian res0->ai_protocol)) != -1) { 932d265a5d3Sflorian if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen) 933d265a5d3Sflorian == -1) { 934d265a5d3Sflorian close(udp6sock); 935d265a5d3Sflorian udp6sock = -1; 936d265a5d3Sflorian } 937d265a5d3Sflorian } 938d265a5d3Sflorian } 939296cf316Sflorian if (res0) 940d265a5d3Sflorian freeaddrinfo(res0); 941d265a5d3Sflorian 942d265a5d3Sflorian if (udp4sock == -1 && udp6sock == -1) 943d265a5d3Sflorian fatal("could not bind to 127.0.0.1 or ::1 on port 53"); 944d265a5d3Sflorian 945b04dd19dSflorian if (udp4sock != -1) 946d265a5d3Sflorian main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock); 947b04dd19dSflorian if (udp6sock != -1) 948d265a5d3Sflorian main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock); 949d265a5d3Sflorian } 950