1*fd873f7fSflorian /* $OpenBSD: unwind.c,v 1.23 2019/04/02 07:47:23 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> 372f29e846Sflorian #include <asr.h> 38018cebfbSflorian #include <pwd.h> 39018cebfbSflorian #include <stdio.h> 40018cebfbSflorian #include <stdlib.h> 41018cebfbSflorian #include <string.h> 42018cebfbSflorian #include <signal.h> 43018cebfbSflorian #include <unistd.h> 44018cebfbSflorian 4558b5b9b8Sflorian #include "log.h" 46018cebfbSflorian #include "unwind.h" 47018cebfbSflorian #include "frontend.h" 48018cebfbSflorian #include "resolver.h" 49018cebfbSflorian #include "control.h" 50b2501eadSflorian #include "captiveportal.h" 51018cebfbSflorian 52296cf316Sflorian #define LEASE_DB_DIR "/var/db/" 53296cf316Sflorian #define _PATH_LEASE_DB "/var/db/dhclient.leases." 54296cf316Sflorian 5590d56d5fSflorian #define TRUST_ANCHOR_FILE "/var/db/unwind.key" 56296cf316Sflorian 57018cebfbSflorian __dead void usage(void); 58018cebfbSflorian __dead void main_shutdown(void); 59018cebfbSflorian 60018cebfbSflorian void main_sig_handler(int, short, void *); 61018cebfbSflorian 62018cebfbSflorian static pid_t start_child(int, char *, int, int, int); 63018cebfbSflorian 64018cebfbSflorian void main_dispatch_frontend(int, short, void *); 65018cebfbSflorian void main_dispatch_resolver(int, short, void *); 66b2501eadSflorian void main_dispatch_captiveportal(int, short, void *); 67018cebfbSflorian 68b2501eadSflorian static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *, 69b2501eadSflorian struct imsgbuf *); 70bb81f7e1Sflorian static int main_imsg_send_config(struct uw_conf *); 71018cebfbSflorian 72018cebfbSflorian int main_reload(void); 73b2501eadSflorian int main_sendall(enum imsg_type, void *, uint16_t); 74018cebfbSflorian void open_dhcp_lease(int); 75d265a5d3Sflorian void open_ports(void); 762f29e846Sflorian void resolve_captive_portal(void); 772f29e846Sflorian void resolve_captive_portal_done(struct asr_result *, void *); 78018cebfbSflorian 79bb81f7e1Sflorian struct uw_conf *main_conf; 80018cebfbSflorian struct imsgev *iev_frontend; 81018cebfbSflorian struct imsgev *iev_resolver; 82b2501eadSflorian struct imsgev *iev_captiveportal; 83018cebfbSflorian char *conffile; 84018cebfbSflorian 85018cebfbSflorian pid_t frontend_pid; 86018cebfbSflorian pid_t resolver_pid; 87b2501eadSflorian pid_t captiveportal_pid; 88018cebfbSflorian 89018cebfbSflorian uint32_t cmd_opts; 90018cebfbSflorian 91018cebfbSflorian void 92018cebfbSflorian main_sig_handler(int sig, short event, void *arg) 93018cebfbSflorian { 94018cebfbSflorian /* 95018cebfbSflorian * Normal signal handler rules don't apply because libevent 96018cebfbSflorian * decouples for us. 97018cebfbSflorian */ 98018cebfbSflorian 99018cebfbSflorian switch (sig) { 100018cebfbSflorian case SIGTERM: 101018cebfbSflorian case SIGINT: 1025472663aSflorian main_shutdown(); 103018cebfbSflorian break; 104018cebfbSflorian case SIGHUP: 105018cebfbSflorian if (main_reload() == -1) 106018cebfbSflorian log_warnx("configuration reload failed"); 107018cebfbSflorian else 108018cebfbSflorian log_debug("configuration reloaded"); 109018cebfbSflorian break; 110018cebfbSflorian default: 111018cebfbSflorian fatalx("unexpected signal"); 112018cebfbSflorian } 113018cebfbSflorian } 114018cebfbSflorian 115018cebfbSflorian __dead void 116018cebfbSflorian usage(void) 117018cebfbSflorian { 118018cebfbSflorian extern char *__progname; 119018cebfbSflorian 120018cebfbSflorian fprintf(stderr, "usage: %s [-dnv] [-f file] [-s socket]\n", 121018cebfbSflorian __progname); 122018cebfbSflorian exit(1); 123018cebfbSflorian } 124018cebfbSflorian 125018cebfbSflorian int 126018cebfbSflorian main(int argc, char *argv[]) 127018cebfbSflorian { 128018cebfbSflorian struct event ev_sigint, ev_sigterm, ev_sighup; 129bb81f7e1Sflorian int ch, debug = 0, resolver_flag = 0, frontend_flag = 0; 130bb81f7e1Sflorian int captiveportal_flag = 0, frontend_routesock, rtfilter; 131bb81f7e1Sflorian int pipe_main2frontend[2], pipe_main2resolver[2]; 132b2501eadSflorian int pipe_main2captiveportal[2]; 133d1b04a40Sflorian int control_fd, ta_fd; 134bb81f7e1Sflorian char *csock, *saved_argv0; 135018cebfbSflorian 136018cebfbSflorian conffile = CONF_FILE; 137018cebfbSflorian csock = UNWIND_SOCKET; 138018cebfbSflorian 139018cebfbSflorian log_init(1, LOG_DAEMON); /* Log to stderr until daemonized. */ 140018cebfbSflorian log_setverbose(1); 141018cebfbSflorian 142018cebfbSflorian saved_argv0 = argv[0]; 143018cebfbSflorian if (saved_argv0 == NULL) 144018cebfbSflorian saved_argv0 = "unwind"; 145018cebfbSflorian 146b2501eadSflorian while ((ch = getopt(argc, argv, "CdEFf:ns:v")) != -1) { 147018cebfbSflorian switch (ch) { 148b2501eadSflorian case 'C': 149b2501eadSflorian captiveportal_flag = 1; 150b2501eadSflorian break; 151018cebfbSflorian case 'd': 152018cebfbSflorian debug = 1; 153018cebfbSflorian break; 154018cebfbSflorian case 'E': 155018cebfbSflorian resolver_flag = 1; 156018cebfbSflorian break; 157018cebfbSflorian case 'F': 158018cebfbSflorian frontend_flag = 1; 159018cebfbSflorian break; 160018cebfbSflorian case 'f': 161018cebfbSflorian conffile = optarg; 162018cebfbSflorian break; 163018cebfbSflorian case 'n': 164018cebfbSflorian cmd_opts |= OPT_NOACTION; 165018cebfbSflorian break; 166018cebfbSflorian case 's': 167018cebfbSflorian csock = optarg; 168018cebfbSflorian break; 169018cebfbSflorian case 'v': 170018cebfbSflorian if (cmd_opts & OPT_VERBOSE) 171018cebfbSflorian cmd_opts |= OPT_VERBOSE2; 172018cebfbSflorian cmd_opts |= OPT_VERBOSE; 173018cebfbSflorian break; 174018cebfbSflorian default: 175018cebfbSflorian usage(); 176018cebfbSflorian } 177018cebfbSflorian } 178018cebfbSflorian 179018cebfbSflorian argc -= optind; 180018cebfbSflorian argv += optind; 181b2501eadSflorian if (argc > 0 || (resolver_flag && frontend_flag && captiveportal_flag)) 182018cebfbSflorian usage(); 183018cebfbSflorian 184018cebfbSflorian if (resolver_flag) 185018cebfbSflorian resolver(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 186018cebfbSflorian else if (frontend_flag) 187018cebfbSflorian frontend(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 188b2501eadSflorian else if (captiveportal_flag) 189b2501eadSflorian captiveportal(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 190018cebfbSflorian 191588e8263Sflorian if ((main_conf = parse_config(conffile)) == NULL) 192018cebfbSflorian exit(1); 193018cebfbSflorian 194018cebfbSflorian if (cmd_opts & OPT_NOACTION) { 195018cebfbSflorian if (cmd_opts & OPT_VERBOSE) 196018cebfbSflorian print_config(main_conf); 197018cebfbSflorian else 198018cebfbSflorian fprintf(stderr, "configuration OK\n"); 199018cebfbSflorian exit(0); 200018cebfbSflorian } 201018cebfbSflorian 202018cebfbSflorian /* Check for root privileges. */ 203018cebfbSflorian if (geteuid()) 204018cebfbSflorian errx(1, "need root privileges"); 205018cebfbSflorian 206018cebfbSflorian /* Check for assigned daemon user */ 207018cebfbSflorian if (getpwnam(UNWIND_USER) == NULL) 208018cebfbSflorian errx(1, "unknown user %s", UNWIND_USER); 209018cebfbSflorian 210018cebfbSflorian log_init(debug, LOG_DAEMON); 211018cebfbSflorian log_setverbose(cmd_opts & OPT_VERBOSE); 212018cebfbSflorian 213018cebfbSflorian if (!debug) 214018cebfbSflorian daemon(1, 0); 215018cebfbSflorian 216018cebfbSflorian log_info("startup"); 217018cebfbSflorian 218018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 219018cebfbSflorian PF_UNSPEC, pipe_main2frontend) == -1) 220018cebfbSflorian fatal("main2frontend socketpair"); 221018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 222018cebfbSflorian PF_UNSPEC, pipe_main2resolver) == -1) 223018cebfbSflorian fatal("main2resolver socketpair"); 224b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 225b2501eadSflorian PF_UNSPEC, pipe_main2captiveportal) == -1) 226b2501eadSflorian fatal("main2captiveportal socketpair"); 227018cebfbSflorian 228018cebfbSflorian /* Start children. */ 229018cebfbSflorian resolver_pid = start_child(PROC_RESOLVER, saved_argv0, 230018cebfbSflorian pipe_main2resolver[1], debug, cmd_opts & (OPT_VERBOSE | 231018cebfbSflorian OPT_VERBOSE2)); 232018cebfbSflorian frontend_pid = start_child(PROC_FRONTEND, saved_argv0, 233018cebfbSflorian pipe_main2frontend[1], debug, cmd_opts & (OPT_VERBOSE | 234018cebfbSflorian OPT_VERBOSE2)); 235b2501eadSflorian captiveportal_pid = start_child(PROC_CAPTIVEPORTAL, saved_argv0, 236b2501eadSflorian pipe_main2captiveportal[1], debug, cmd_opts & (OPT_VERBOSE | 237b2501eadSflorian OPT_VERBOSE2)); 238018cebfbSflorian 239bb81f7e1Sflorian uw_process = PROC_MAIN; 240bb81f7e1Sflorian log_procinit(log_procnames[uw_process]); 241018cebfbSflorian 242018cebfbSflorian event_init(); 243018cebfbSflorian 244018cebfbSflorian /* Setup signal handler. */ 245018cebfbSflorian signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 246018cebfbSflorian signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 247018cebfbSflorian signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 248018cebfbSflorian signal_add(&ev_sigint, NULL); 249018cebfbSflorian signal_add(&ev_sigterm, NULL); 250018cebfbSflorian signal_add(&ev_sighup, NULL); 251018cebfbSflorian signal(SIGPIPE, SIG_IGN); 252018cebfbSflorian 253018cebfbSflorian /* Setup pipes to children. */ 254018cebfbSflorian 255018cebfbSflorian if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL || 256b2501eadSflorian (iev_captiveportal = malloc(sizeof(struct imsgev))) == NULL || 257018cebfbSflorian (iev_resolver = malloc(sizeof(struct imsgev))) == NULL) 258018cebfbSflorian fatal(NULL); 259018cebfbSflorian imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]); 260018cebfbSflorian iev_frontend->handler = main_dispatch_frontend; 261018cebfbSflorian imsg_init(&iev_resolver->ibuf, pipe_main2resolver[0]); 262018cebfbSflorian iev_resolver->handler = main_dispatch_resolver; 263b2501eadSflorian imsg_init(&iev_captiveportal->ibuf, pipe_main2captiveportal[0]); 264b2501eadSflorian iev_captiveportal->handler = main_dispatch_captiveportal; 265018cebfbSflorian 266b2501eadSflorian /* Setup event handlers for pipes. */ 267018cebfbSflorian iev_frontend->events = EV_READ; 268018cebfbSflorian event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 269018cebfbSflorian iev_frontend->events, iev_frontend->handler, iev_frontend); 270018cebfbSflorian event_add(&iev_frontend->ev, NULL); 271018cebfbSflorian 272018cebfbSflorian iev_resolver->events = EV_READ; 273bb81f7e1Sflorian event_set(&iev_resolver->ev, iev_resolver->ibuf.fd, 274bb81f7e1Sflorian iev_resolver->events, iev_resolver->handler, iev_resolver); 275018cebfbSflorian event_add(&iev_resolver->ev, NULL); 276018cebfbSflorian 277b2501eadSflorian iev_captiveportal->events = EV_READ; 278b2501eadSflorian event_set(&iev_captiveportal->ev, iev_captiveportal->ibuf.fd, 279b2501eadSflorian iev_captiveportal->events, iev_captiveportal->handler, 280b2501eadSflorian iev_captiveportal); 281b2501eadSflorian event_add(&iev_captiveportal->ev, NULL); 282b2501eadSflorian 283b2501eadSflorian if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, 284b2501eadSflorian &iev_resolver->ibuf, &iev_captiveportal->ibuf)) 285018cebfbSflorian fatal("could not establish imsg links"); 286018cebfbSflorian 287018cebfbSflorian if ((control_fd = control_init(csock)) == -1) 288018cebfbSflorian fatalx("control socket setup failed"); 289018cebfbSflorian 2909e627e00Sflorian if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 291018cebfbSflorian AF_INET)) < 0) 292018cebfbSflorian fatal("route socket"); 293018cebfbSflorian 294018cebfbSflorian rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_PROPOSAL) | 295018cebfbSflorian ROUTE_FILTER(RTM_GET); 2969e627e00Sflorian if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER, 297018cebfbSflorian &rtfilter, sizeof(rtfilter)) < 0) 298018cebfbSflorian fatal("setsockopt(ROUTE_MSGFILTER)"); 299018cebfbSflorian 300d1b04a40Sflorian if ((ta_fd = open(TRUST_ANCHOR_FILE, O_RDWR | O_CREAT, 0644)) == -1) 301d1b04a40Sflorian log_warn("%s", TRUST_ANCHOR_FILE); 302d1b04a40Sflorian 303d1b04a40Sflorian /* receiver handles failed open correctly */ 304d1b04a40Sflorian main_imsg_compose_frontend_fd(IMSG_TAFD, 0, ta_fd); 305d1b04a40Sflorian 306018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd); 307018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock); 308018cebfbSflorian main_imsg_send_config(main_conf); 309018cebfbSflorian 310d1b04a40Sflorian if (pledge("stdio inet dns rpath sendfd", NULL) == -1) 311018cebfbSflorian fatal("pledge"); 312018cebfbSflorian 313018cebfbSflorian main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0); 314296cf316Sflorian main_imsg_compose_resolver(IMSG_STARTUP, 0, NULL, 0); 315018cebfbSflorian 316018cebfbSflorian event_dispatch(); 317018cebfbSflorian 318018cebfbSflorian main_shutdown(); 319018cebfbSflorian return (0); 320018cebfbSflorian } 321018cebfbSflorian 322018cebfbSflorian __dead void 323018cebfbSflorian main_shutdown(void) 324018cebfbSflorian { 325018cebfbSflorian pid_t pid; 326018cebfbSflorian int status; 327018cebfbSflorian 328018cebfbSflorian /* Close pipes. */ 329018cebfbSflorian msgbuf_clear(&iev_frontend->ibuf.w); 330018cebfbSflorian close(iev_frontend->ibuf.fd); 331018cebfbSflorian msgbuf_clear(&iev_resolver->ibuf.w); 332018cebfbSflorian close(iev_resolver->ibuf.fd); 333b2501eadSflorian msgbuf_clear(&iev_captiveportal->ibuf.w); 334b2501eadSflorian close(iev_captiveportal->ibuf.fd); 335018cebfbSflorian 336018cebfbSflorian config_clear(main_conf); 337018cebfbSflorian 338018cebfbSflorian log_debug("waiting for children to terminate"); 339018cebfbSflorian do { 340018cebfbSflorian pid = wait(&status); 341018cebfbSflorian if (pid == -1) { 342018cebfbSflorian if (errno != EINTR && errno != ECHILD) 343018cebfbSflorian fatal("wait"); 344018cebfbSflorian } else if (WIFSIGNALED(status)) 345018cebfbSflorian log_warnx("%s terminated; signal %d", 346018cebfbSflorian (pid == resolver_pid) ? "resolver" : 347018cebfbSflorian "frontend", WTERMSIG(status)); 348018cebfbSflorian } while (pid != -1 || (pid == -1 && errno == EINTR)); 349018cebfbSflorian 350018cebfbSflorian free(iev_frontend); 351018cebfbSflorian free(iev_resolver); 352b2501eadSflorian free(iev_captiveportal); 353018cebfbSflorian 354018cebfbSflorian log_info("terminating"); 355018cebfbSflorian exit(0); 356018cebfbSflorian } 357018cebfbSflorian 358018cebfbSflorian static pid_t 359018cebfbSflorian start_child(int p, char *argv0, int fd, int debug, int verbose) 360018cebfbSflorian { 361018cebfbSflorian char *argv[7]; 362018cebfbSflorian int argc = 0; 363018cebfbSflorian pid_t pid; 364018cebfbSflorian 365018cebfbSflorian switch (pid = fork()) { 366018cebfbSflorian case -1: 367018cebfbSflorian fatal("cannot fork"); 368018cebfbSflorian case 0: 369018cebfbSflorian break; 370018cebfbSflorian default: 371018cebfbSflorian close(fd); 372018cebfbSflorian return (pid); 373018cebfbSflorian } 374018cebfbSflorian 375ef4f5895Syasuoka if (fd != 3) { 376018cebfbSflorian if (dup2(fd, 3) == -1) 377018cebfbSflorian fatal("cannot setup imsg fd"); 378ef4f5895Syasuoka } else if (fcntl(fd, F_SETFD, 0) == -1) 379ef4f5895Syasuoka fatal("cannot setup imsg fd"); 380018cebfbSflorian 381018cebfbSflorian argv[argc++] = argv0; 382018cebfbSflorian switch (p) { 383018cebfbSflorian case PROC_MAIN: 384018cebfbSflorian fatalx("Can not start main process"); 385018cebfbSflorian case PROC_RESOLVER: 386018cebfbSflorian argv[argc++] = "-E"; 387018cebfbSflorian break; 388018cebfbSflorian case PROC_FRONTEND: 389018cebfbSflorian argv[argc++] = "-F"; 390018cebfbSflorian break; 391b2501eadSflorian case PROC_CAPTIVEPORTAL: 392b2501eadSflorian argv[argc++] = "-C"; 393b2501eadSflorian break; 394018cebfbSflorian } 395018cebfbSflorian if (debug) 396018cebfbSflorian argv[argc++] = "-d"; 397018cebfbSflorian if (verbose & OPT_VERBOSE) 398018cebfbSflorian argv[argc++] = "-v"; 399018cebfbSflorian if (verbose & OPT_VERBOSE2) 400018cebfbSflorian argv[argc++] = "-v"; 401018cebfbSflorian argv[argc++] = NULL; 402018cebfbSflorian 403018cebfbSflorian execvp(argv0, argv); 404018cebfbSflorian fatal("execvp"); 405018cebfbSflorian } 406018cebfbSflorian 407018cebfbSflorian void 408018cebfbSflorian main_dispatch_frontend(int fd, short event, void *bula) 409018cebfbSflorian { 410018cebfbSflorian struct imsgev *iev = bula; 411018cebfbSflorian struct imsgbuf *ibuf; 412018cebfbSflorian struct imsg imsg; 413018cebfbSflorian ssize_t n; 414018cebfbSflorian int shut = 0, verbose; 415018cebfbSflorian u_short rtm_index; 416018cebfbSflorian 417018cebfbSflorian ibuf = &iev->ibuf; 418018cebfbSflorian 419018cebfbSflorian if (event & EV_READ) { 420018cebfbSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 421018cebfbSflorian fatal("imsg_read error"); 422018cebfbSflorian if (n == 0) /* Connection closed. */ 423018cebfbSflorian shut = 1; 424018cebfbSflorian } 425018cebfbSflorian if (event & EV_WRITE) { 426018cebfbSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 427018cebfbSflorian fatal("msgbuf_write"); 428018cebfbSflorian if (n == 0) /* Connection closed. */ 429018cebfbSflorian shut = 1; 430018cebfbSflorian } 431018cebfbSflorian 432018cebfbSflorian for (;;) { 433018cebfbSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 434018cebfbSflorian fatal("imsg_get"); 435018cebfbSflorian if (n == 0) /* No more messages. */ 436018cebfbSflorian break; 437018cebfbSflorian 438018cebfbSflorian switch (imsg.hdr.type) { 439018cebfbSflorian case IMSG_STARTUP_DONE: 440018cebfbSflorian break; 441018cebfbSflorian case IMSG_CTL_RELOAD: 442018cebfbSflorian if (main_reload() == -1) 443018cebfbSflorian log_warnx("configuration reload failed"); 444018cebfbSflorian else 445018cebfbSflorian log_warnx("configuration reloaded"); 446018cebfbSflorian break; 447018cebfbSflorian case IMSG_CTL_LOG_VERBOSE: 448a9155f32Sflorian if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 4492b821978Sflorian fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 450a9155f32Sflorian "%lu", __func__, IMSG_DATA_SIZE(imsg)); 451018cebfbSflorian memcpy(&verbose, imsg.data, sizeof(verbose)); 452018cebfbSflorian log_setverbose(verbose); 453018cebfbSflorian break; 454018cebfbSflorian case IMSG_OPEN_DHCP_LEASE: 455a9155f32Sflorian if (IMSG_DATA_SIZE(imsg) != sizeof(rtm_index)) 4562b821978Sflorian fatalx("%s: IMSG_OPEN_DHCP_LEASE wrong length: " 457a9155f32Sflorian "%lu", __func__, IMSG_DATA_SIZE(imsg)); 458018cebfbSflorian memcpy(&rtm_index, imsg.data, sizeof(rtm_index)); 459018cebfbSflorian open_dhcp_lease(rtm_index); 460018cebfbSflorian break; 461d265a5d3Sflorian case IMSG_OPEN_PORTS: 462d265a5d3Sflorian open_ports(); 463d265a5d3Sflorian break; 464018cebfbSflorian default: 465018cebfbSflorian log_debug("%s: error handling imsg %d", __func__, 466018cebfbSflorian imsg.hdr.type); 467018cebfbSflorian break; 468018cebfbSflorian } 469018cebfbSflorian imsg_free(&imsg); 470018cebfbSflorian } 471018cebfbSflorian if (!shut) 472018cebfbSflorian imsg_event_add(iev); 473018cebfbSflorian else { 474018cebfbSflorian /* This pipe is dead. Remove its event handler */ 475018cebfbSflorian event_del(&iev->ev); 476018cebfbSflorian event_loopexit(NULL); 477018cebfbSflorian } 478018cebfbSflorian } 479018cebfbSflorian 480018cebfbSflorian void 481018cebfbSflorian main_dispatch_resolver(int fd, short event, void *bula) 482018cebfbSflorian { 483018cebfbSflorian struct imsgev *iev = bula; 484018cebfbSflorian struct imsgbuf *ibuf; 485018cebfbSflorian struct imsg imsg; 486b2501eadSflorian ssize_t n; 4872f29e846Sflorian int shut = 0; 488b2501eadSflorian 489b2501eadSflorian ibuf = &iev->ibuf; 490b2501eadSflorian 491b2501eadSflorian if (event & EV_READ) { 492b2501eadSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 493b2501eadSflorian fatal("imsg_read error"); 494b2501eadSflorian if (n == 0) /* Connection closed. */ 495b2501eadSflorian shut = 1; 496b2501eadSflorian } 497b2501eadSflorian if (event & EV_WRITE) { 498b2501eadSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 499b2501eadSflorian fatal("msgbuf_write"); 500b2501eadSflorian if (n == 0) /* Connection closed. */ 501b2501eadSflorian shut = 1; 502b2501eadSflorian } 503b2501eadSflorian 504b2501eadSflorian for (;;) { 505b2501eadSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 506b2501eadSflorian fatal("imsg_get"); 507b2501eadSflorian if (n == 0) /* No more messages. */ 508b2501eadSflorian break; 509b2501eadSflorian 510b2501eadSflorian switch (imsg.hdr.type) { 5112f29e846Sflorian case IMSG_RESOLVE_CAPTIVE_PORTAL: 5122f29e846Sflorian resolve_captive_portal(); 513b2501eadSflorian break; 514b2501eadSflorian default: 515b2501eadSflorian log_debug("%s: error handling imsg %d", __func__, 516b2501eadSflorian imsg.hdr.type); 517b2501eadSflorian break; 518b2501eadSflorian } 519b2501eadSflorian imsg_free(&imsg); 520b2501eadSflorian } 521b2501eadSflorian if (!shut) 522b2501eadSflorian imsg_event_add(iev); 523b2501eadSflorian else { 524b2501eadSflorian /* This pipe is dead. Remove its event handler. */ 525b2501eadSflorian event_del(&iev->ev); 526b2501eadSflorian event_loopexit(NULL); 527b2501eadSflorian } 528b2501eadSflorian } 529b2501eadSflorian 530b2501eadSflorian void 531b2501eadSflorian main_dispatch_captiveportal(int fd, short event, void *bula) 532b2501eadSflorian { 533b2501eadSflorian struct imsgev *iev = bula; 534b2501eadSflorian struct imsgbuf *ibuf; 535b2501eadSflorian struct imsg imsg; 536018cebfbSflorian ssize_t n; 537018cebfbSflorian int shut = 0; 538018cebfbSflorian 539018cebfbSflorian ibuf = &iev->ibuf; 540018cebfbSflorian 541018cebfbSflorian if (event & EV_READ) { 542018cebfbSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 543018cebfbSflorian fatal("imsg_read error"); 544018cebfbSflorian if (n == 0) /* Connection closed. */ 545018cebfbSflorian shut = 1; 546018cebfbSflorian } 547018cebfbSflorian if (event & EV_WRITE) { 548018cebfbSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 549018cebfbSflorian fatal("msgbuf_write"); 550018cebfbSflorian if (n == 0) /* Connection closed. */ 551018cebfbSflorian shut = 1; 552018cebfbSflorian } 553018cebfbSflorian 554018cebfbSflorian for (;;) { 555018cebfbSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 556018cebfbSflorian fatal("imsg_get"); 557018cebfbSflorian if (n == 0) /* No more messages. */ 558018cebfbSflorian break; 559018cebfbSflorian 560018cebfbSflorian switch (imsg.hdr.type) { 561018cebfbSflorian default: 562018cebfbSflorian log_debug("%s: error handling imsg %d", __func__, 563018cebfbSflorian imsg.hdr.type); 564018cebfbSflorian break; 565018cebfbSflorian } 566018cebfbSflorian imsg_free(&imsg); 567018cebfbSflorian } 568018cebfbSflorian if (!shut) 569018cebfbSflorian imsg_event_add(iev); 570018cebfbSflorian else { 571018cebfbSflorian /* This pipe is dead. Remove its event handler. */ 572018cebfbSflorian event_del(&iev->ev); 573018cebfbSflorian event_loopexit(NULL); 574018cebfbSflorian } 575018cebfbSflorian } 576018cebfbSflorian 577018cebfbSflorian void 578018cebfbSflorian main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) 579018cebfbSflorian { 580018cebfbSflorian if (iev_frontend) 581018cebfbSflorian imsg_compose_event(iev_frontend, type, 0, pid, -1, data, 582018cebfbSflorian datalen); 583018cebfbSflorian } 584018cebfbSflorian 585018cebfbSflorian void 586018cebfbSflorian main_imsg_compose_frontend_fd(int type, pid_t pid, int fd) 587018cebfbSflorian { 588018cebfbSflorian if (iev_frontend) 589018cebfbSflorian imsg_compose_event(iev_frontend, type, 0, pid, fd, NULL, 0); 590018cebfbSflorian } 591018cebfbSflorian 592018cebfbSflorian void 593018cebfbSflorian main_imsg_compose_resolver(int type, pid_t pid, void *data, uint16_t datalen) 594018cebfbSflorian { 595018cebfbSflorian if (iev_resolver) 596018cebfbSflorian imsg_compose_event(iev_resolver, type, 0, pid, -1, data, 597018cebfbSflorian datalen); 598018cebfbSflorian } 599018cebfbSflorian 600018cebfbSflorian void 601b2501eadSflorian main_imsg_compose_captiveportal(int type, pid_t pid, void *data, 602b2501eadSflorian uint16_t datalen) 603b2501eadSflorian { 604b2501eadSflorian if (iev_captiveportal) 605b2501eadSflorian imsg_compose_event(iev_captiveportal, type, 0, pid, -1, data, 606b2501eadSflorian datalen); 607b2501eadSflorian } 608b2501eadSflorian 609b2501eadSflorian void 610b2501eadSflorian main_imsg_compose_captiveportal_fd(int type, pid_t pid, int fd) 611b2501eadSflorian { 612b2501eadSflorian if (iev_frontend) 613b2501eadSflorian imsg_compose_event(iev_captiveportal, type, 0, pid, fd, NULL, 614b2501eadSflorian 0); 615b2501eadSflorian } 616b2501eadSflorian 617b2501eadSflorian void 618018cebfbSflorian imsg_event_add(struct imsgev *iev) 619018cebfbSflorian { 620018cebfbSflorian iev->events = EV_READ; 621018cebfbSflorian if (iev->ibuf.w.queued) 622018cebfbSflorian iev->events |= EV_WRITE; 623018cebfbSflorian 624018cebfbSflorian event_del(&iev->ev); 625018cebfbSflorian event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 626018cebfbSflorian event_add(&iev->ev, NULL); 627018cebfbSflorian } 628018cebfbSflorian 629018cebfbSflorian int 630018cebfbSflorian imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 631018cebfbSflorian pid_t pid, int fd, void *data, uint16_t datalen) 632018cebfbSflorian { 633018cebfbSflorian int ret; 634018cebfbSflorian 635018cebfbSflorian if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, 636018cebfbSflorian datalen)) != -1) 637018cebfbSflorian imsg_event_add(iev); 638018cebfbSflorian 639018cebfbSflorian return (ret); 640018cebfbSflorian } 641018cebfbSflorian 642018cebfbSflorian static int 643018cebfbSflorian main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf, 644b2501eadSflorian struct imsgbuf *resolver_buf, struct imsgbuf *captiveportal_buf) 645018cebfbSflorian { 646018cebfbSflorian int pipe_frontend2resolver[2]; 647b2501eadSflorian int pipe_frontend2captiveportal[2]; 648b2501eadSflorian int pipe_resolver2captiveportal[2]; 649018cebfbSflorian 650018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 651018cebfbSflorian PF_UNSPEC, pipe_frontend2resolver) == -1) 652018cebfbSflorian return (-1); 653018cebfbSflorian 654b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 655b2501eadSflorian PF_UNSPEC, pipe_frontend2captiveportal) == -1) 656b2501eadSflorian return (-1); 657b2501eadSflorian 658b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 659b2501eadSflorian PF_UNSPEC, pipe_resolver2captiveportal) == -1) 660b2501eadSflorian return (-1); 661b2501eadSflorian 662b2501eadSflorian if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0, 663018cebfbSflorian pipe_frontend2resolver[0], NULL, 0) == -1) 664018cebfbSflorian return (-1); 665b2501eadSflorian if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0, 666018cebfbSflorian pipe_frontend2resolver[1], NULL, 0) == -1) 667018cebfbSflorian return (-1); 668018cebfbSflorian 669b2501eadSflorian if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_CAPTIVEPORTAL, 0, 0, 670b2501eadSflorian pipe_frontend2captiveportal[0], NULL, 0) == -1) 671b2501eadSflorian return (-1); 672b2501eadSflorian if (imsg_compose(captiveportal_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0, 673b2501eadSflorian pipe_frontend2captiveportal[1], NULL, 0) == -1) 674b2501eadSflorian return (-1); 675b2501eadSflorian 676b2501eadSflorian if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_CAPTIVEPORTAL, 0, 0, 677b2501eadSflorian pipe_resolver2captiveportal[0], NULL, 0) == -1) 678b2501eadSflorian return (-1); 679b2501eadSflorian if (imsg_compose(captiveportal_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0, 680b2501eadSflorian pipe_resolver2captiveportal[1], NULL, 0) == -1) 681b2501eadSflorian return (-1); 682b2501eadSflorian 683018cebfbSflorian return (0); 684018cebfbSflorian } 685018cebfbSflorian 686018cebfbSflorian int 687018cebfbSflorian main_reload(void) 688018cebfbSflorian { 689bb81f7e1Sflorian struct uw_conf *xconf; 690018cebfbSflorian 691018cebfbSflorian if ((xconf = parse_config(conffile)) == NULL) 692018cebfbSflorian return (-1); 693018cebfbSflorian 694018cebfbSflorian if (main_imsg_send_config(xconf) == -1) 695018cebfbSflorian return (-1); 696018cebfbSflorian 697018cebfbSflorian merge_config(main_conf, xconf); 698018cebfbSflorian 699018cebfbSflorian return (0); 700018cebfbSflorian } 701018cebfbSflorian 702018cebfbSflorian int 703bb81f7e1Sflorian main_imsg_send_config(struct uw_conf *xconf) 704018cebfbSflorian { 705bb81f7e1Sflorian struct uw_forwarder *uw_forwarder; 706018cebfbSflorian 707018cebfbSflorian /* Send fixed part of config to children. */ 708b2501eadSflorian if (main_sendall(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 709018cebfbSflorian return (-1); 710b2501eadSflorian if (xconf->captive_portal_host != NULL) { 711b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_HOST, 712b2501eadSflorian xconf->captive_portal_host, 713b2501eadSflorian strlen(xconf->captive_portal_host) + 1) == -1) 714b2501eadSflorian return (-1); 715b2501eadSflorian } 716b2501eadSflorian 717b2501eadSflorian if (xconf->captive_portal_path != NULL) { 718b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_PATH, 719b2501eadSflorian xconf->captive_portal_path, 720b2501eadSflorian strlen(xconf->captive_portal_path) + 1) == -1) 721b2501eadSflorian return (-1); 722b2501eadSflorian } 723b2501eadSflorian 724b2501eadSflorian if (xconf->captive_portal_expected_response != NULL) { 725b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_EXPECTED_RESPONSE, 726b2501eadSflorian xconf->captive_portal_expected_response, 727b2501eadSflorian strlen(xconf->captive_portal_expected_response) + 1) 728b2501eadSflorian == -1) 729b2501eadSflorian return (-1); 730b2501eadSflorian } 731018cebfbSflorian 7323570995aSflorian /* send static forwarders to children */ 733bb81f7e1Sflorian SIMPLEQ_FOREACH(uw_forwarder, &xconf->uw_forwarder_list, entry) { 734bb81f7e1Sflorian if (main_sendall(IMSG_RECONF_FORWARDER, uw_forwarder, 735bb81f7e1Sflorian sizeof(*uw_forwarder)) == -1) 736018cebfbSflorian return (-1); 737018cebfbSflorian } 738018cebfbSflorian 7393570995aSflorian /* send static DoT forwarders to children */ 740bb81f7e1Sflorian SIMPLEQ_FOREACH(uw_forwarder, &xconf->uw_dot_forwarder_list, 7413570995aSflorian entry) { 742bb81f7e1Sflorian if (main_sendall(IMSG_RECONF_DOT_FORWARDER, uw_forwarder, 743bb81f7e1Sflorian sizeof(*uw_forwarder)) == -1) 7443570995aSflorian return (-1); 7453570995aSflorian } 7463570995aSflorian 747018cebfbSflorian /* Tell children the revised config is now complete. */ 748b2501eadSflorian if (main_sendall(IMSG_RECONF_END, NULL, 0) == -1) 749018cebfbSflorian return (-1); 750018cebfbSflorian 751018cebfbSflorian return (0); 752018cebfbSflorian } 753018cebfbSflorian 754018cebfbSflorian int 755b2501eadSflorian main_sendall(enum imsg_type type, void *buf, uint16_t len) 756018cebfbSflorian { 757018cebfbSflorian if (imsg_compose_event(iev_frontend, type, 0, 0, -1, buf, len) == -1) 758018cebfbSflorian return (-1); 759018cebfbSflorian if (imsg_compose_event(iev_resolver, type, 0, 0, -1, buf, len) == -1) 760018cebfbSflorian return (-1); 761b2501eadSflorian if (imsg_compose_event(iev_captiveportal, type, 0, 0, -1, buf, len) == 762b2501eadSflorian -1) 763b2501eadSflorian return (-1); 764018cebfbSflorian return (0); 765018cebfbSflorian } 766018cebfbSflorian 767018cebfbSflorian void 768bb81f7e1Sflorian merge_config(struct uw_conf *conf, struct uw_conf *xconf) 769018cebfbSflorian { 770bb81f7e1Sflorian struct uw_forwarder *uw_forwarder; 771018cebfbSflorian 772018cebfbSflorian /* Remove & discard existing forwarders. */ 773bb81f7e1Sflorian while ((uw_forwarder = SIMPLEQ_FIRST(&conf->uw_forwarder_list)) != 774bb81f7e1Sflorian NULL) { 775bb81f7e1Sflorian SIMPLEQ_REMOVE_HEAD(&conf->uw_forwarder_list, entry); 776bb81f7e1Sflorian free(uw_forwarder); 777018cebfbSflorian } 778bb81f7e1Sflorian while ((uw_forwarder = SIMPLEQ_FIRST(&conf->uw_dot_forwarder_list)) != 779bb81f7e1Sflorian NULL) { 780bb81f7e1Sflorian SIMPLEQ_REMOVE_HEAD(&conf->uw_dot_forwarder_list, entry); 781bb81f7e1Sflorian free(uw_forwarder); 7823570995aSflorian } 783018cebfbSflorian 784bb81f7e1Sflorian conf->uw_options = xconf->uw_options; 785*fd873f7fSflorian conf->res_pref_len = xconf->res_pref_len; 786*fd873f7fSflorian memcpy(&conf->res_pref, &xconf->res_pref, 787*fd873f7fSflorian sizeof(conf->res_pref)); 788018cebfbSflorian 789b2501eadSflorian free(conf->captive_portal_host); 790b2501eadSflorian conf->captive_portal_host = xconf->captive_portal_host; 791b2501eadSflorian 792b2501eadSflorian free(conf->captive_portal_path); 793b2501eadSflorian conf->captive_portal_path = xconf->captive_portal_path; 794b2501eadSflorian 795b2501eadSflorian free(conf->captive_portal_expected_response); 796b2501eadSflorian conf->captive_portal_expected_response = 797b2501eadSflorian xconf->captive_portal_expected_response; 798b2501eadSflorian 799b2501eadSflorian conf->captive_portal_expected_status = 800b2501eadSflorian xconf->captive_portal_expected_status; 801b2501eadSflorian 802b2501eadSflorian conf->captive_portal_auto = xconf->captive_portal_auto; 803b2501eadSflorian 804018cebfbSflorian /* Add new forwarders. */ 805bb81f7e1Sflorian while ((uw_forwarder = SIMPLEQ_FIRST(&xconf->uw_forwarder_list)) != 806bb81f7e1Sflorian NULL) { 807bb81f7e1Sflorian SIMPLEQ_REMOVE_HEAD(&xconf->uw_forwarder_list, entry); 808bb81f7e1Sflorian SIMPLEQ_INSERT_TAIL(&conf->uw_forwarder_list, 809bb81f7e1Sflorian uw_forwarder, entry); 810018cebfbSflorian } 811bb81f7e1Sflorian while ((uw_forwarder = SIMPLEQ_FIRST(&xconf->uw_dot_forwarder_list)) != 812bb81f7e1Sflorian NULL) { 813bb81f7e1Sflorian SIMPLEQ_REMOVE_HEAD(&xconf->uw_dot_forwarder_list, entry); 814bb81f7e1Sflorian SIMPLEQ_INSERT_TAIL(&conf->uw_dot_forwarder_list, 815bb81f7e1Sflorian uw_forwarder, entry); 8163570995aSflorian } 817018cebfbSflorian 818018cebfbSflorian free(xconf); 819018cebfbSflorian } 820018cebfbSflorian 821bb81f7e1Sflorian struct uw_conf * 822018cebfbSflorian config_new_empty(void) 823018cebfbSflorian { 824*fd873f7fSflorian static enum uw_resolver_type default_res_pref[] = { 825*fd873f7fSflorian UW_RES_DOT, 826*fd873f7fSflorian UW_RES_FORWARDER, 827*fd873f7fSflorian UW_RES_RECURSOR, 828*fd873f7fSflorian UW_RES_DHCP}; 829bb81f7e1Sflorian struct uw_conf *xconf; 830018cebfbSflorian 831018cebfbSflorian xconf = calloc(1, sizeof(*xconf)); 832018cebfbSflorian if (xconf == NULL) 833018cebfbSflorian fatal(NULL); 834018cebfbSflorian 835*fd873f7fSflorian memcpy(&xconf->res_pref, &default_res_pref, 836*fd873f7fSflorian sizeof(default_res_pref)); 837*fd873f7fSflorian xconf->res_pref_len = 4; 838*fd873f7fSflorian 839bb81f7e1Sflorian SIMPLEQ_INIT(&xconf->uw_forwarder_list); 840bb81f7e1Sflorian SIMPLEQ_INIT(&xconf->uw_dot_forwarder_list); 841018cebfbSflorian 842b2501eadSflorian if ((xconf->captive_portal_expected_response = strdup("")) == NULL) 843b2501eadSflorian fatal(NULL); 844bb81f7e1Sflorian 845b2501eadSflorian xconf->captive_portal_expected_status = 200; 846b2501eadSflorian xconf->captive_portal_auto = 1; 847b2501eadSflorian 848018cebfbSflorian return (xconf); 849018cebfbSflorian } 850018cebfbSflorian 851018cebfbSflorian void 852bb81f7e1Sflorian config_clear(struct uw_conf *conf) 853018cebfbSflorian { 854bb81f7e1Sflorian struct uw_conf *xconf; 855018cebfbSflorian 856018cebfbSflorian /* Merge current config with an empty config. */ 857018cebfbSflorian xconf = config_new_empty(); 858018cebfbSflorian merge_config(conf, xconf); 859018cebfbSflorian 860018cebfbSflorian free(conf); 861018cebfbSflorian } 862018cebfbSflorian 863018cebfbSflorian void 864018cebfbSflorian open_dhcp_lease(int if_idx) 865018cebfbSflorian { 866018cebfbSflorian static char lease_filename[sizeof(_PATH_LEASE_DB) + IF_NAMESIZE] = 867018cebfbSflorian _PATH_LEASE_DB; 868018cebfbSflorian 869018cebfbSflorian int fd; 870018cebfbSflorian char *bufp; 871018cebfbSflorian 872018cebfbSflorian bufp = lease_filename + sizeof(_PATH_LEASE_DB) - 1; 873018cebfbSflorian bufp = if_indextoname(if_idx, bufp); 874018cebfbSflorian 875018cebfbSflorian if (bufp == NULL) { 876018cebfbSflorian log_debug("cannot find interface %d", if_idx); 877018cebfbSflorian return; 878018cebfbSflorian } 879018cebfbSflorian 880018cebfbSflorian log_debug("lease file name: %s", lease_filename); 881018cebfbSflorian 882018cebfbSflorian if ((fd = open(lease_filename, O_RDONLY)) == -1) { 8834a26c82dSjca if (errno != ENOENT) 8844a26c82dSjca log_warn("cannot open lease file %s", lease_filename); 885018cebfbSflorian return; 886018cebfbSflorian } 887018cebfbSflorian 888018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_LEASEFD, 0, fd); 889018cebfbSflorian } 890d265a5d3Sflorian 891d265a5d3Sflorian void 892d265a5d3Sflorian open_ports(void) 893d265a5d3Sflorian { 894d265a5d3Sflorian struct addrinfo hints, *res0; 895d265a5d3Sflorian int udp4sock = -1, udp6sock = -1, error; 896d265a5d3Sflorian 897d265a5d3Sflorian memset(&hints, 0, sizeof(hints)); 898d265a5d3Sflorian hints.ai_family = AF_INET; 899d265a5d3Sflorian hints.ai_socktype = SOCK_DGRAM; 900cc4fd5c4Stedu hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE; 901d265a5d3Sflorian 902d265a5d3Sflorian error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); 903d265a5d3Sflorian if (!error && res0) { 904d265a5d3Sflorian if ((udp4sock = socket(res0->ai_family, res0->ai_socktype, 905d265a5d3Sflorian res0->ai_protocol)) != -1) { 906d265a5d3Sflorian if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen) 907d265a5d3Sflorian == -1) { 908d265a5d3Sflorian close(udp4sock); 909d265a5d3Sflorian udp4sock = -1; 910d265a5d3Sflorian } 911d265a5d3Sflorian } 912d265a5d3Sflorian } 913296cf316Sflorian if (res0) 914d265a5d3Sflorian freeaddrinfo(res0); 915d265a5d3Sflorian 916d265a5d3Sflorian hints.ai_family = AF_INET6; 917d265a5d3Sflorian error = getaddrinfo("::1", "domain", &hints, &res0); 918d265a5d3Sflorian if (!error && res0) { 919d265a5d3Sflorian if ((udp6sock = socket(res0->ai_family, res0->ai_socktype, 920d265a5d3Sflorian res0->ai_protocol)) != -1) { 921d265a5d3Sflorian if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen) 922d265a5d3Sflorian == -1) { 923d265a5d3Sflorian close(udp6sock); 924d265a5d3Sflorian udp6sock = -1; 925d265a5d3Sflorian } 926d265a5d3Sflorian } 927d265a5d3Sflorian } 928296cf316Sflorian if (res0) 929d265a5d3Sflorian freeaddrinfo(res0); 930d265a5d3Sflorian 931d265a5d3Sflorian if (udp4sock == -1 && udp6sock == -1) 932d265a5d3Sflorian fatal("could not bind to 127.0.0.1 or ::1 on port 53"); 933d265a5d3Sflorian 934b04dd19dSflorian if (udp4sock != -1) 935d265a5d3Sflorian main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock); 936b04dd19dSflorian if (udp6sock != -1) 937d265a5d3Sflorian main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock); 938d265a5d3Sflorian } 9392f29e846Sflorian 9402f29e846Sflorian void 9412f29e846Sflorian resolve_captive_portal(void) 9422f29e846Sflorian { 9432f29e846Sflorian struct addrinfo hints; 9442f29e846Sflorian void *as; 9452f29e846Sflorian 9462f29e846Sflorian if (main_conf->captive_portal_host == NULL) 9472f29e846Sflorian return; 9482f29e846Sflorian 9492f29e846Sflorian memset(&hints, 0, sizeof(hints)); 9502f29e846Sflorian hints.ai_family = PF_INET; 9512f29e846Sflorian hints.ai_socktype = SOCK_STREAM; 9522f29e846Sflorian 9532f29e846Sflorian log_debug("%s: %s", __func__, main_conf->captive_portal_host); 9542f29e846Sflorian 9552f29e846Sflorian if ((as = getaddrinfo_async(main_conf->captive_portal_host, "www", 9562f29e846Sflorian &hints, NULL)) != NULL) 9572f29e846Sflorian event_asr_run(as, resolve_captive_portal_done, NULL); 9582f29e846Sflorian else 9592f29e846Sflorian log_warn("%s: getaddrinfo_async", __func__); 9602f29e846Sflorian 9612f29e846Sflorian } 9622f29e846Sflorian 9632f29e846Sflorian void 9642f29e846Sflorian resolve_captive_portal_done(struct asr_result *ar, void *arg) 9652f29e846Sflorian { 9662f29e846Sflorian struct addrinfo *res; 9672f29e846Sflorian int httpsock; 9682f29e846Sflorian 9692f29e846Sflorian if (ar->ar_gai_errno) { 9702f29e846Sflorian log_warnx("%s: %s", __func__, gai_strerror(ar->ar_gai_errno)); 9712f29e846Sflorian return; 9722f29e846Sflorian } 9732f29e846Sflorian 9742f29e846Sflorian for (res = ar->ar_addrinfo; res; res = res->ai_next) { 9752f29e846Sflorian if (res->ai_family != PF_INET) 9762f29e846Sflorian continue; 9772f29e846Sflorian log_debug("%s: ip_port: %s", __func__, 9782f29e846Sflorian ip_port(res->ai_addr)); 9792f29e846Sflorian 9802f29e846Sflorian if ((httpsock = socket(AF_INET, SOCK_STREAM | 9812f29e846Sflorian SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { 9822f29e846Sflorian log_warn("%s: socket", __func__); 9832f29e846Sflorian break; 9842f29e846Sflorian } 9852f29e846Sflorian if (connect(httpsock, res->ai_addr, res->ai_addrlen) == -1) { 9862f29e846Sflorian if (errno != EINPROGRESS) { 9872f29e846Sflorian log_warn("%s: connect", __func__); 9882f29e846Sflorian close(httpsock); 9892f29e846Sflorian break; 9902f29e846Sflorian } 9912f29e846Sflorian } 9922f29e846Sflorian main_imsg_compose_captiveportal_fd(IMSG_HTTPSOCK, 0, 9932f29e846Sflorian httpsock); 9942f29e846Sflorian } 9952f29e846Sflorian 9962f29e846Sflorian freeaddrinfo(ar->ar_addrinfo); 9972f29e846Sflorian } 998