1*b2501eadSflorian /* $OpenBSD: unwind.c,v 1.10 2019/02/03 12:02:30 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> 24018cebfbSflorian #include <sys/syslog.h> 25018cebfbSflorian #include <sys/wait.h> 26018cebfbSflorian 27018cebfbSflorian #include <net/if.h> 28018cebfbSflorian #include <net/route.h> 29018cebfbSflorian 30018cebfbSflorian #include <err.h> 31018cebfbSflorian #include <errno.h> 32018cebfbSflorian #include <event.h> 33018cebfbSflorian #include <fcntl.h> 34018cebfbSflorian #include <imsg.h> 35018cebfbSflorian #include <netdb.h> 36018cebfbSflorian #include <pwd.h> 37018cebfbSflorian #include <stdio.h> 38018cebfbSflorian #include <stdlib.h> 39018cebfbSflorian #include <string.h> 40018cebfbSflorian #include <signal.h> 41018cebfbSflorian #include <unistd.h> 42018cebfbSflorian 43018cebfbSflorian #include "uw_log.h" 44018cebfbSflorian #include "unwind.h" 45018cebfbSflorian #include "frontend.h" 46018cebfbSflorian #include "resolver.h" 47018cebfbSflorian #include "control.h" 48*b2501eadSflorian #include "captiveportal.h" 49018cebfbSflorian 50018cebfbSflorian __dead void usage(void); 51018cebfbSflorian __dead void main_shutdown(void); 52018cebfbSflorian 53018cebfbSflorian void main_sig_handler(int, short, void *); 54018cebfbSflorian 55018cebfbSflorian static pid_t start_child(int, char *, int, int, int); 56018cebfbSflorian 57018cebfbSflorian void main_dispatch_frontend(int, short, void *); 58018cebfbSflorian void main_dispatch_resolver(int, short, void *); 59*b2501eadSflorian void main_dispatch_captiveportal(int, short, void *); 60018cebfbSflorian 61*b2501eadSflorian static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *, 62*b2501eadSflorian struct imsgbuf *); 63018cebfbSflorian static int main_imsg_send_config(struct unwind_conf *); 64018cebfbSflorian 65018cebfbSflorian int main_reload(void); 66*b2501eadSflorian int main_sendall(enum imsg_type, void *, uint16_t); 67018cebfbSflorian void open_dhcp_lease(int); 68d265a5d3Sflorian void open_ports(void); 69018cebfbSflorian 70018cebfbSflorian struct unwind_conf *main_conf; 71018cebfbSflorian struct imsgev *iev_frontend; 72018cebfbSflorian struct imsgev *iev_resolver; 73*b2501eadSflorian struct imsgev *iev_captiveportal; 74018cebfbSflorian char *conffile; 75018cebfbSflorian 76018cebfbSflorian pid_t frontend_pid; 77018cebfbSflorian pid_t resolver_pid; 78*b2501eadSflorian pid_t captiveportal_pid; 79018cebfbSflorian 80018cebfbSflorian uint32_t cmd_opts; 81018cebfbSflorian 82018cebfbSflorian void 83018cebfbSflorian main_sig_handler(int sig, short event, void *arg) 84018cebfbSflorian { 85018cebfbSflorian /* 86018cebfbSflorian * Normal signal handler rules don't apply because libevent 87018cebfbSflorian * decouples for us. 88018cebfbSflorian */ 89018cebfbSflorian 90018cebfbSflorian switch (sig) { 91018cebfbSflorian case SIGTERM: 92018cebfbSflorian case SIGINT: 935472663aSflorian main_shutdown(); 94018cebfbSflorian break; 95018cebfbSflorian case SIGHUP: 96018cebfbSflorian if (main_reload() == -1) 97018cebfbSflorian log_warnx("configuration reload failed"); 98018cebfbSflorian else 99018cebfbSflorian log_debug("configuration reloaded"); 100018cebfbSflorian break; 101018cebfbSflorian default: 102018cebfbSflorian fatalx("unexpected signal"); 103018cebfbSflorian } 104018cebfbSflorian } 105018cebfbSflorian 106018cebfbSflorian __dead void 107018cebfbSflorian usage(void) 108018cebfbSflorian { 109018cebfbSflorian extern char *__progname; 110018cebfbSflorian 111018cebfbSflorian fprintf(stderr, "usage: %s [-dnv] [-f file] [-s socket]\n", 112018cebfbSflorian __progname); 113018cebfbSflorian exit(1); 114018cebfbSflorian } 115018cebfbSflorian 116018cebfbSflorian int 117018cebfbSflorian main(int argc, char *argv[]) 118018cebfbSflorian { 119018cebfbSflorian struct event ev_sigint, ev_sigterm, ev_sighup; 120018cebfbSflorian int ch; 121*b2501eadSflorian int debug = 0, resolver_flag = 0; 122*b2501eadSflorian int frontend_flag = 0, captiveportal_flag = 0; 123018cebfbSflorian char *saved_argv0; 124018cebfbSflorian int pipe_main2frontend[2]; 125018cebfbSflorian int pipe_main2resolver[2]; 126*b2501eadSflorian int pipe_main2captiveportal[2]; 127018cebfbSflorian int frontend_routesock, rtfilter; 128018cebfbSflorian int control_fd; 129018cebfbSflorian char *csock; 130018cebfbSflorian 131018cebfbSflorian conffile = CONF_FILE; 132018cebfbSflorian csock = UNWIND_SOCKET; 133018cebfbSflorian 134018cebfbSflorian log_init(1, LOG_DAEMON); /* Log to stderr until daemonized. */ 135018cebfbSflorian log_setverbose(1); 136018cebfbSflorian 137018cebfbSflorian saved_argv0 = argv[0]; 138018cebfbSflorian if (saved_argv0 == NULL) 139018cebfbSflorian saved_argv0 = "unwind"; 140018cebfbSflorian 141*b2501eadSflorian while ((ch = getopt(argc, argv, "CdEFf:ns:v")) != -1) { 142018cebfbSflorian switch (ch) { 143*b2501eadSflorian case 'C': 144*b2501eadSflorian captiveportal_flag = 1; 145*b2501eadSflorian break; 146018cebfbSflorian case 'd': 147018cebfbSflorian debug = 1; 148018cebfbSflorian break; 149018cebfbSflorian case 'E': 150018cebfbSflorian resolver_flag = 1; 151018cebfbSflorian break; 152018cebfbSflorian case 'F': 153018cebfbSflorian frontend_flag = 1; 154018cebfbSflorian break; 155018cebfbSflorian case 'f': 156018cebfbSflorian conffile = optarg; 157018cebfbSflorian break; 158018cebfbSflorian case 'n': 159018cebfbSflorian cmd_opts |= OPT_NOACTION; 160018cebfbSflorian break; 161018cebfbSflorian case 's': 162018cebfbSflorian csock = optarg; 163018cebfbSflorian break; 164018cebfbSflorian case 'v': 165018cebfbSflorian if (cmd_opts & OPT_VERBOSE) 166018cebfbSflorian cmd_opts |= OPT_VERBOSE2; 167018cebfbSflorian cmd_opts |= OPT_VERBOSE; 168018cebfbSflorian break; 169018cebfbSflorian default: 170018cebfbSflorian usage(); 171018cebfbSflorian } 172018cebfbSflorian } 173018cebfbSflorian 174018cebfbSflorian argc -= optind; 175018cebfbSflorian argv += optind; 176*b2501eadSflorian if (argc > 0 || (resolver_flag && frontend_flag && captiveportal_flag)) 177018cebfbSflorian usage(); 178018cebfbSflorian 179018cebfbSflorian if (resolver_flag) 180018cebfbSflorian resolver(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 181018cebfbSflorian else if (frontend_flag) 182018cebfbSflorian frontend(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 183*b2501eadSflorian else if (captiveportal_flag) 184*b2501eadSflorian captiveportal(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2)); 185018cebfbSflorian 186588e8263Sflorian if ((main_conf = parse_config(conffile)) == NULL) 187018cebfbSflorian exit(1); 188018cebfbSflorian 189018cebfbSflorian if (cmd_opts & OPT_NOACTION) { 190018cebfbSflorian if (cmd_opts & OPT_VERBOSE) 191018cebfbSflorian print_config(main_conf); 192018cebfbSflorian else 193018cebfbSflorian fprintf(stderr, "configuration OK\n"); 194018cebfbSflorian exit(0); 195018cebfbSflorian } 196018cebfbSflorian 197018cebfbSflorian /* Check for root privileges. */ 198018cebfbSflorian if (geteuid()) 199018cebfbSflorian errx(1, "need root privileges"); 200018cebfbSflorian 201018cebfbSflorian /* Check for assigned daemon user */ 202018cebfbSflorian if (getpwnam(UNWIND_USER) == NULL) 203018cebfbSflorian errx(1, "unknown user %s", UNWIND_USER); 204018cebfbSflorian 205018cebfbSflorian log_init(debug, LOG_DAEMON); 206018cebfbSflorian log_setverbose(cmd_opts & OPT_VERBOSE); 207018cebfbSflorian 208018cebfbSflorian if (!debug) 209018cebfbSflorian daemon(1, 0); 210018cebfbSflorian 211018cebfbSflorian log_info("startup"); 212018cebfbSflorian 213018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 214018cebfbSflorian PF_UNSPEC, pipe_main2frontend) == -1) 215018cebfbSflorian fatal("main2frontend socketpair"); 216018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 217018cebfbSflorian PF_UNSPEC, pipe_main2resolver) == -1) 218018cebfbSflorian fatal("main2resolver socketpair"); 219*b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 220*b2501eadSflorian PF_UNSPEC, pipe_main2captiveportal) == -1) 221*b2501eadSflorian fatal("main2captiveportal socketpair"); 222018cebfbSflorian 223018cebfbSflorian /* Start children. */ 224018cebfbSflorian resolver_pid = start_child(PROC_RESOLVER, saved_argv0, 225018cebfbSflorian pipe_main2resolver[1], debug, cmd_opts & (OPT_VERBOSE | 226018cebfbSflorian OPT_VERBOSE2)); 227018cebfbSflorian frontend_pid = start_child(PROC_FRONTEND, saved_argv0, 228018cebfbSflorian pipe_main2frontend[1], debug, cmd_opts & (OPT_VERBOSE | 229018cebfbSflorian OPT_VERBOSE2)); 230*b2501eadSflorian captiveportal_pid = start_child(PROC_CAPTIVEPORTAL, saved_argv0, 231*b2501eadSflorian pipe_main2captiveportal[1], debug, cmd_opts & (OPT_VERBOSE | 232*b2501eadSflorian OPT_VERBOSE2)); 233018cebfbSflorian 234018cebfbSflorian unwind_process = PROC_MAIN; 235018cebfbSflorian log_procinit(log_procnames[unwind_process]); 236018cebfbSflorian 237018cebfbSflorian event_init(); 238018cebfbSflorian 239018cebfbSflorian /* Setup signal handler. */ 240018cebfbSflorian signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 241018cebfbSflorian signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 242018cebfbSflorian signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 243018cebfbSflorian signal_add(&ev_sigint, NULL); 244018cebfbSflorian signal_add(&ev_sigterm, NULL); 245018cebfbSflorian signal_add(&ev_sighup, NULL); 246018cebfbSflorian signal(SIGPIPE, SIG_IGN); 247018cebfbSflorian 248018cebfbSflorian /* Setup pipes to children. */ 249018cebfbSflorian 250018cebfbSflorian if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL || 251*b2501eadSflorian (iev_captiveportal = malloc(sizeof(struct imsgev))) == NULL || 252018cebfbSflorian (iev_resolver = malloc(sizeof(struct imsgev))) == NULL) 253018cebfbSflorian fatal(NULL); 254018cebfbSflorian imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]); 255018cebfbSflorian iev_frontend->handler = main_dispatch_frontend; 256018cebfbSflorian imsg_init(&iev_resolver->ibuf, pipe_main2resolver[0]); 257018cebfbSflorian iev_resolver->handler = main_dispatch_resolver; 258*b2501eadSflorian imsg_init(&iev_captiveportal->ibuf, pipe_main2captiveportal[0]); 259*b2501eadSflorian iev_captiveportal->handler = main_dispatch_captiveportal; 260018cebfbSflorian 261*b2501eadSflorian /* Setup event handlers for pipes. */ 262018cebfbSflorian iev_frontend->events = EV_READ; 263018cebfbSflorian event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 264018cebfbSflorian iev_frontend->events, iev_frontend->handler, iev_frontend); 265018cebfbSflorian event_add(&iev_frontend->ev, NULL); 266018cebfbSflorian 267018cebfbSflorian iev_resolver->events = EV_READ; 268018cebfbSflorian event_set(&iev_resolver->ev, iev_resolver->ibuf.fd, iev_resolver->events, 269018cebfbSflorian iev_resolver->handler, iev_resolver); 270018cebfbSflorian event_add(&iev_resolver->ev, NULL); 271018cebfbSflorian 272*b2501eadSflorian iev_captiveportal->events = EV_READ; 273*b2501eadSflorian event_set(&iev_captiveportal->ev, iev_captiveportal->ibuf.fd, 274*b2501eadSflorian iev_captiveportal->events, iev_captiveportal->handler, 275*b2501eadSflorian iev_captiveportal); 276*b2501eadSflorian event_add(&iev_captiveportal->ev, NULL); 277*b2501eadSflorian 278*b2501eadSflorian if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, 279*b2501eadSflorian &iev_resolver->ibuf, &iev_captiveportal->ibuf)) 280018cebfbSflorian fatal("could not establish imsg links"); 281018cebfbSflorian 282018cebfbSflorian if ((control_fd = control_init(csock)) == -1) 283018cebfbSflorian fatalx("control socket setup failed"); 284018cebfbSflorian 2859e627e00Sflorian if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 286018cebfbSflorian AF_INET)) < 0) 287018cebfbSflorian fatal("route socket"); 288018cebfbSflorian 289018cebfbSflorian rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_PROPOSAL) | 290018cebfbSflorian ROUTE_FILTER(RTM_GET); 2919e627e00Sflorian if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER, 292018cebfbSflorian &rtfilter, sizeof(rtfilter)) < 0) 293018cebfbSflorian fatal("setsockopt(ROUTE_MSGFILTER)"); 294018cebfbSflorian 295018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd); 296018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock); 297018cebfbSflorian main_imsg_send_config(main_conf); 298018cebfbSflorian 299d265a5d3Sflorian if (pledge("stdio inet rpath sendfd", NULL) == -1) 300018cebfbSflorian fatal("pledge"); 301018cebfbSflorian 302018cebfbSflorian main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0); 303018cebfbSflorian 304018cebfbSflorian event_dispatch(); 305018cebfbSflorian 306018cebfbSflorian main_shutdown(); 307018cebfbSflorian return (0); 308018cebfbSflorian } 309018cebfbSflorian 310018cebfbSflorian __dead void 311018cebfbSflorian main_shutdown(void) 312018cebfbSflorian { 313018cebfbSflorian pid_t pid; 314018cebfbSflorian int status; 315018cebfbSflorian 316018cebfbSflorian /* Close pipes. */ 317018cebfbSflorian msgbuf_clear(&iev_frontend->ibuf.w); 318018cebfbSflorian close(iev_frontend->ibuf.fd); 319018cebfbSflorian msgbuf_clear(&iev_resolver->ibuf.w); 320018cebfbSflorian close(iev_resolver->ibuf.fd); 321*b2501eadSflorian msgbuf_clear(&iev_captiveportal->ibuf.w); 322*b2501eadSflorian close(iev_captiveportal->ibuf.fd); 323018cebfbSflorian 324018cebfbSflorian config_clear(main_conf); 325018cebfbSflorian 326018cebfbSflorian log_debug("waiting for children to terminate"); 327018cebfbSflorian do { 328018cebfbSflorian pid = wait(&status); 329018cebfbSflorian if (pid == -1) { 330018cebfbSflorian if (errno != EINTR && errno != ECHILD) 331018cebfbSflorian fatal("wait"); 332018cebfbSflorian } else if (WIFSIGNALED(status)) 333018cebfbSflorian log_warnx("%s terminated; signal %d", 334018cebfbSflorian (pid == resolver_pid) ? "resolver" : 335018cebfbSflorian "frontend", WTERMSIG(status)); 336018cebfbSflorian } while (pid != -1 || (pid == -1 && errno == EINTR)); 337018cebfbSflorian 338018cebfbSflorian free(iev_frontend); 339018cebfbSflorian free(iev_resolver); 340*b2501eadSflorian free(iev_captiveportal); 341018cebfbSflorian 342018cebfbSflorian log_info("terminating"); 343018cebfbSflorian exit(0); 344018cebfbSflorian } 345018cebfbSflorian 346018cebfbSflorian static pid_t 347018cebfbSflorian start_child(int p, char *argv0, int fd, int debug, int verbose) 348018cebfbSflorian { 349018cebfbSflorian char *argv[7]; 350018cebfbSflorian int argc = 0; 351018cebfbSflorian pid_t pid; 352018cebfbSflorian 353018cebfbSflorian switch (pid = fork()) { 354018cebfbSflorian case -1: 355018cebfbSflorian fatal("cannot fork"); 356018cebfbSflorian case 0: 357018cebfbSflorian break; 358018cebfbSflorian default: 359018cebfbSflorian close(fd); 360018cebfbSflorian return (pid); 361018cebfbSflorian } 362018cebfbSflorian 363018cebfbSflorian if (dup2(fd, 3) == -1) 364018cebfbSflorian fatal("cannot setup imsg fd"); 365018cebfbSflorian 366018cebfbSflorian argv[argc++] = argv0; 367018cebfbSflorian switch (p) { 368018cebfbSflorian case PROC_MAIN: 369018cebfbSflorian fatalx("Can not start main process"); 370018cebfbSflorian case PROC_RESOLVER: 371018cebfbSflorian argv[argc++] = "-E"; 372018cebfbSflorian break; 373018cebfbSflorian case PROC_FRONTEND: 374018cebfbSflorian argv[argc++] = "-F"; 375018cebfbSflorian break; 376*b2501eadSflorian case PROC_CAPTIVEPORTAL: 377*b2501eadSflorian argv[argc++] = "-C"; 378*b2501eadSflorian break; 379018cebfbSflorian } 380018cebfbSflorian if (debug) 381018cebfbSflorian argv[argc++] = "-d"; 382018cebfbSflorian if (verbose & OPT_VERBOSE) 383018cebfbSflorian argv[argc++] = "-v"; 384018cebfbSflorian if (verbose & OPT_VERBOSE2) 385018cebfbSflorian argv[argc++] = "-v"; 386018cebfbSflorian argv[argc++] = NULL; 387018cebfbSflorian 388018cebfbSflorian execvp(argv0, argv); 389018cebfbSflorian fatal("execvp"); 390018cebfbSflorian } 391018cebfbSflorian 392018cebfbSflorian void 393018cebfbSflorian main_dispatch_frontend(int fd, short event, void *bula) 394018cebfbSflorian { 395018cebfbSflorian struct imsgev *iev = bula; 396018cebfbSflorian struct imsgbuf *ibuf; 397018cebfbSflorian struct imsg imsg; 398018cebfbSflorian ssize_t n; 399018cebfbSflorian int shut = 0, verbose; 400018cebfbSflorian u_short rtm_index; 401018cebfbSflorian 402018cebfbSflorian ibuf = &iev->ibuf; 403018cebfbSflorian 404018cebfbSflorian if (event & EV_READ) { 405018cebfbSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 406018cebfbSflorian fatal("imsg_read error"); 407018cebfbSflorian if (n == 0) /* Connection closed. */ 408018cebfbSflorian shut = 1; 409018cebfbSflorian } 410018cebfbSflorian if (event & EV_WRITE) { 411018cebfbSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 412018cebfbSflorian fatal("msgbuf_write"); 413018cebfbSflorian if (n == 0) /* Connection closed. */ 414018cebfbSflorian shut = 1; 415018cebfbSflorian } 416018cebfbSflorian 417018cebfbSflorian for (;;) { 418018cebfbSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 419018cebfbSflorian fatal("imsg_get"); 420018cebfbSflorian if (n == 0) /* No more messages. */ 421018cebfbSflorian break; 422018cebfbSflorian 423018cebfbSflorian switch (imsg.hdr.type) { 424018cebfbSflorian case IMSG_STARTUP_DONE: 425018cebfbSflorian break; 426018cebfbSflorian case IMSG_CTL_RELOAD: 427018cebfbSflorian if (main_reload() == -1) 428018cebfbSflorian log_warnx("configuration reload failed"); 429018cebfbSflorian else 430018cebfbSflorian log_warnx("configuration reloaded"); 431018cebfbSflorian break; 432018cebfbSflorian case IMSG_CTL_LOG_VERBOSE: 4332b821978Sflorian if (imsg.hdr.len != IMSG_HEADER_SIZE + 4342b821978Sflorian sizeof(verbose)) 4352b821978Sflorian fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 4362b821978Sflorian "%d", __func__, imsg.hdr.len); 437018cebfbSflorian memcpy(&verbose, imsg.data, sizeof(verbose)); 438018cebfbSflorian log_setverbose(verbose); 439018cebfbSflorian break; 440018cebfbSflorian case IMSG_OPEN_DHCP_LEASE: 4412b821978Sflorian if (imsg.hdr.len != IMSG_HEADER_SIZE + 4422b821978Sflorian sizeof(rtm_index)) 4432b821978Sflorian fatalx("%s: IMSG_OPEN_DHCP_LEASE wrong length: " 4442b821978Sflorian "%d", __func__, imsg.hdr.len); 445018cebfbSflorian memcpy(&rtm_index, imsg.data, sizeof(rtm_index)); 446018cebfbSflorian open_dhcp_lease(rtm_index); 447018cebfbSflorian break; 448d265a5d3Sflorian case IMSG_OPEN_PORTS: 449d265a5d3Sflorian open_ports(); 450d265a5d3Sflorian break; 451018cebfbSflorian default: 452018cebfbSflorian log_debug("%s: error handling imsg %d", __func__, 453018cebfbSflorian imsg.hdr.type); 454018cebfbSflorian break; 455018cebfbSflorian } 456018cebfbSflorian imsg_free(&imsg); 457018cebfbSflorian } 458018cebfbSflorian if (!shut) 459018cebfbSflorian imsg_event_add(iev); 460018cebfbSflorian else { 461018cebfbSflorian /* This pipe is dead. Remove its event handler */ 462018cebfbSflorian event_del(&iev->ev); 463018cebfbSflorian event_loopexit(NULL); 464018cebfbSflorian } 465018cebfbSflorian } 466018cebfbSflorian 467018cebfbSflorian void 468018cebfbSflorian main_dispatch_resolver(int fd, short event, void *bula) 469018cebfbSflorian { 470018cebfbSflorian struct imsgev *iev = bula; 471018cebfbSflorian struct imsgbuf *ibuf; 472018cebfbSflorian struct imsg imsg; 473*b2501eadSflorian struct sockaddr_in sin; 474*b2501eadSflorian ssize_t n; 475*b2501eadSflorian int shut = 0, httpsock; 476*b2501eadSflorian 477*b2501eadSflorian ibuf = &iev->ibuf; 478*b2501eadSflorian 479*b2501eadSflorian if (event & EV_READ) { 480*b2501eadSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 481*b2501eadSflorian fatal("imsg_read error"); 482*b2501eadSflorian if (n == 0) /* Connection closed. */ 483*b2501eadSflorian shut = 1; 484*b2501eadSflorian } 485*b2501eadSflorian if (event & EV_WRITE) { 486*b2501eadSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 487*b2501eadSflorian fatal("msgbuf_write"); 488*b2501eadSflorian if (n == 0) /* Connection closed. */ 489*b2501eadSflorian shut = 1; 490*b2501eadSflorian } 491*b2501eadSflorian 492*b2501eadSflorian for (;;) { 493*b2501eadSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 494*b2501eadSflorian fatal("imsg_get"); 495*b2501eadSflorian if (n == 0) /* No more messages. */ 496*b2501eadSflorian break; 497*b2501eadSflorian 498*b2501eadSflorian switch (imsg.hdr.type) { 499*b2501eadSflorian case IMSG_OPEN_HTTP_PORT: 500*b2501eadSflorian if (imsg.hdr.len != IMSG_HEADER_SIZE + 501*b2501eadSflorian sizeof(sin)) 502*b2501eadSflorian fatalx("%s: IMSG_OPEN_HTTP_PORT wrong length: " 503*b2501eadSflorian "%d", __func__, imsg.hdr.len); 504*b2501eadSflorian memcpy(&sin, imsg.data, sizeof(sin)); 505*b2501eadSflorian 506*b2501eadSflorian if ((httpsock = socket(AF_INET, SOCK_STREAM | 507*b2501eadSflorian SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { 508*b2501eadSflorian log_warn("%s: socket", __func__); 509*b2501eadSflorian break; 510*b2501eadSflorian } 511*b2501eadSflorian if (connect(httpsock, (struct sockaddr *)&sin, 512*b2501eadSflorian sin.sin_len) == -1) { 513*b2501eadSflorian if (errno != EINPROGRESS) { 514*b2501eadSflorian log_warn("%s: connect", __func__); 515*b2501eadSflorian close(httpsock); 516*b2501eadSflorian break; 517*b2501eadSflorian } 518*b2501eadSflorian } 519*b2501eadSflorian main_imsg_compose_captiveportal_fd(IMSG_HTTPSOCK, 0, 520*b2501eadSflorian httpsock); 521*b2501eadSflorian break; 522*b2501eadSflorian default: 523*b2501eadSflorian log_debug("%s: error handling imsg %d", __func__, 524*b2501eadSflorian imsg.hdr.type); 525*b2501eadSflorian break; 526*b2501eadSflorian } 527*b2501eadSflorian imsg_free(&imsg); 528*b2501eadSflorian } 529*b2501eadSflorian if (!shut) 530*b2501eadSflorian imsg_event_add(iev); 531*b2501eadSflorian else { 532*b2501eadSflorian /* This pipe is dead. Remove its event handler. */ 533*b2501eadSflorian event_del(&iev->ev); 534*b2501eadSflorian event_loopexit(NULL); 535*b2501eadSflorian } 536*b2501eadSflorian } 537*b2501eadSflorian 538*b2501eadSflorian void 539*b2501eadSflorian main_dispatch_captiveportal(int fd, short event, void *bula) 540*b2501eadSflorian { 541*b2501eadSflorian struct imsgev *iev = bula; 542*b2501eadSflorian struct imsgbuf *ibuf; 543*b2501eadSflorian struct imsg imsg; 544018cebfbSflorian ssize_t n; 545018cebfbSflorian int shut = 0; 546018cebfbSflorian 547018cebfbSflorian ibuf = &iev->ibuf; 548018cebfbSflorian 549018cebfbSflorian if (event & EV_READ) { 550018cebfbSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 551018cebfbSflorian fatal("imsg_read error"); 552018cebfbSflorian if (n == 0) /* Connection closed. */ 553018cebfbSflorian shut = 1; 554018cebfbSflorian } 555018cebfbSflorian if (event & EV_WRITE) { 556018cebfbSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 557018cebfbSflorian fatal("msgbuf_write"); 558018cebfbSflorian if (n == 0) /* Connection closed. */ 559018cebfbSflorian shut = 1; 560018cebfbSflorian } 561018cebfbSflorian 562018cebfbSflorian for (;;) { 563018cebfbSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 564018cebfbSflorian fatal("imsg_get"); 565018cebfbSflorian if (n == 0) /* No more messages. */ 566018cebfbSflorian break; 567018cebfbSflorian 568018cebfbSflorian switch (imsg.hdr.type) { 569018cebfbSflorian default: 570018cebfbSflorian log_debug("%s: error handling imsg %d", __func__, 571018cebfbSflorian imsg.hdr.type); 572018cebfbSflorian break; 573018cebfbSflorian } 574018cebfbSflorian imsg_free(&imsg); 575018cebfbSflorian } 576018cebfbSflorian if (!shut) 577018cebfbSflorian imsg_event_add(iev); 578018cebfbSflorian else { 579018cebfbSflorian /* This pipe is dead. Remove its event handler. */ 580018cebfbSflorian event_del(&iev->ev); 581018cebfbSflorian event_loopexit(NULL); 582018cebfbSflorian } 583018cebfbSflorian } 584018cebfbSflorian 585018cebfbSflorian void 586018cebfbSflorian main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) 587018cebfbSflorian { 588018cebfbSflorian if (iev_frontend) 589018cebfbSflorian imsg_compose_event(iev_frontend, type, 0, pid, -1, data, 590018cebfbSflorian datalen); 591018cebfbSflorian } 592018cebfbSflorian 593018cebfbSflorian void 594018cebfbSflorian main_imsg_compose_frontend_fd(int type, pid_t pid, int fd) 595018cebfbSflorian { 596018cebfbSflorian if (iev_frontend) 597018cebfbSflorian imsg_compose_event(iev_frontend, type, 0, pid, fd, NULL, 0); 598018cebfbSflorian } 599018cebfbSflorian 600018cebfbSflorian void 601018cebfbSflorian main_imsg_compose_resolver(int type, pid_t pid, void *data, uint16_t datalen) 602018cebfbSflorian { 603018cebfbSflorian if (iev_resolver) 604018cebfbSflorian imsg_compose_event(iev_resolver, type, 0, pid, -1, data, 605018cebfbSflorian datalen); 606018cebfbSflorian } 607018cebfbSflorian 608018cebfbSflorian void 609*b2501eadSflorian main_imsg_compose_captiveportal(int type, pid_t pid, void *data, 610*b2501eadSflorian uint16_t datalen) 611*b2501eadSflorian { 612*b2501eadSflorian if (iev_captiveportal) 613*b2501eadSflorian imsg_compose_event(iev_captiveportal, type, 0, pid, -1, data, 614*b2501eadSflorian datalen); 615*b2501eadSflorian } 616*b2501eadSflorian 617*b2501eadSflorian void 618*b2501eadSflorian main_imsg_compose_captiveportal_fd(int type, pid_t pid, int fd) 619*b2501eadSflorian { 620*b2501eadSflorian if (iev_frontend) 621*b2501eadSflorian imsg_compose_event(iev_captiveportal, type, 0, pid, fd, NULL, 622*b2501eadSflorian 0); 623*b2501eadSflorian } 624*b2501eadSflorian 625*b2501eadSflorian void 626018cebfbSflorian imsg_event_add(struct imsgev *iev) 627018cebfbSflorian { 628018cebfbSflorian iev->events = EV_READ; 629018cebfbSflorian if (iev->ibuf.w.queued) 630018cebfbSflorian iev->events |= EV_WRITE; 631018cebfbSflorian 632018cebfbSflorian event_del(&iev->ev); 633018cebfbSflorian event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 634018cebfbSflorian event_add(&iev->ev, NULL); 635018cebfbSflorian } 636018cebfbSflorian 637018cebfbSflorian int 638018cebfbSflorian imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 639018cebfbSflorian pid_t pid, int fd, void *data, uint16_t datalen) 640018cebfbSflorian { 641018cebfbSflorian int ret; 642018cebfbSflorian 643018cebfbSflorian if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, 644018cebfbSflorian datalen)) != -1) 645018cebfbSflorian imsg_event_add(iev); 646018cebfbSflorian 647018cebfbSflorian return (ret); 648018cebfbSflorian } 649018cebfbSflorian 650018cebfbSflorian static int 651018cebfbSflorian main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf, 652*b2501eadSflorian struct imsgbuf *resolver_buf, struct imsgbuf *captiveportal_buf) 653018cebfbSflorian { 654018cebfbSflorian int pipe_frontend2resolver[2]; 655*b2501eadSflorian int pipe_frontend2captiveportal[2]; 656*b2501eadSflorian int pipe_resolver2captiveportal[2]; 657018cebfbSflorian 658018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 659018cebfbSflorian PF_UNSPEC, pipe_frontend2resolver) == -1) 660018cebfbSflorian return (-1); 661018cebfbSflorian 662*b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 663*b2501eadSflorian PF_UNSPEC, pipe_frontend2captiveportal) == -1) 664*b2501eadSflorian return (-1); 665*b2501eadSflorian 666*b2501eadSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 667*b2501eadSflorian PF_UNSPEC, pipe_resolver2captiveportal) == -1) 668*b2501eadSflorian return (-1); 669*b2501eadSflorian 670*b2501eadSflorian if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0, 671018cebfbSflorian pipe_frontend2resolver[0], NULL, 0) == -1) 672018cebfbSflorian return (-1); 673*b2501eadSflorian if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0, 674018cebfbSflorian pipe_frontend2resolver[1], NULL, 0) == -1) 675018cebfbSflorian return (-1); 676018cebfbSflorian 677*b2501eadSflorian if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_CAPTIVEPORTAL, 0, 0, 678*b2501eadSflorian pipe_frontend2captiveportal[0], NULL, 0) == -1) 679*b2501eadSflorian return (-1); 680*b2501eadSflorian if (imsg_compose(captiveportal_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0, 681*b2501eadSflorian pipe_frontend2captiveportal[1], NULL, 0) == -1) 682*b2501eadSflorian return (-1); 683*b2501eadSflorian 684*b2501eadSflorian if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_CAPTIVEPORTAL, 0, 0, 685*b2501eadSflorian pipe_resolver2captiveportal[0], NULL, 0) == -1) 686*b2501eadSflorian return (-1); 687*b2501eadSflorian if (imsg_compose(captiveportal_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0, 688*b2501eadSflorian pipe_resolver2captiveportal[1], NULL, 0) == -1) 689*b2501eadSflorian return (-1); 690*b2501eadSflorian 691018cebfbSflorian return (0); 692018cebfbSflorian } 693018cebfbSflorian 694018cebfbSflorian int 695018cebfbSflorian main_reload(void) 696018cebfbSflorian { 697018cebfbSflorian struct unwind_conf *xconf; 698018cebfbSflorian 699018cebfbSflorian if ((xconf = parse_config(conffile)) == NULL) 700018cebfbSflorian return (-1); 701018cebfbSflorian 702018cebfbSflorian if (main_imsg_send_config(xconf) == -1) 703018cebfbSflorian return (-1); 704018cebfbSflorian 705018cebfbSflorian merge_config(main_conf, xconf); 706018cebfbSflorian 707018cebfbSflorian return (0); 708018cebfbSflorian } 709018cebfbSflorian 710018cebfbSflorian int 711018cebfbSflorian main_imsg_send_config(struct unwind_conf *xconf) 712018cebfbSflorian { 713018cebfbSflorian struct unwind_forwarder *unwind_forwarder; 714018cebfbSflorian 715018cebfbSflorian /* Send fixed part of config to children. */ 716*b2501eadSflorian if (main_sendall(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 717018cebfbSflorian return (-1); 718*b2501eadSflorian if (xconf->captive_portal_host != NULL) { 719*b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_HOST, 720*b2501eadSflorian xconf->captive_portal_host, 721*b2501eadSflorian strlen(xconf->captive_portal_host) + 1) == -1) 722*b2501eadSflorian return (-1); 723*b2501eadSflorian } 724*b2501eadSflorian 725*b2501eadSflorian if (xconf->captive_portal_path != NULL) { 726*b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_PATH, 727*b2501eadSflorian xconf->captive_portal_path, 728*b2501eadSflorian strlen(xconf->captive_portal_path) + 1) == -1) 729*b2501eadSflorian return (-1); 730*b2501eadSflorian } 731*b2501eadSflorian 732*b2501eadSflorian if (xconf->captive_portal_expected_response != NULL) { 733*b2501eadSflorian if (main_sendall(IMSG_RECONF_CAPTIVE_PORTAL_EXPECTED_RESPONSE, 734*b2501eadSflorian xconf->captive_portal_expected_response, 735*b2501eadSflorian strlen(xconf->captive_portal_expected_response) + 1) 736*b2501eadSflorian == -1) 737*b2501eadSflorian return (-1); 738*b2501eadSflorian } 739018cebfbSflorian 7403570995aSflorian /* send static forwarders to children */ 741018cebfbSflorian SIMPLEQ_FOREACH(unwind_forwarder, &xconf->unwind_forwarder_list, entry) { 742*b2501eadSflorian if (main_sendall(IMSG_RECONF_FORWARDER, unwind_forwarder, 743018cebfbSflorian sizeof(*unwind_forwarder)) == -1) 744018cebfbSflorian return (-1); 745018cebfbSflorian } 746018cebfbSflorian 7473570995aSflorian /* send static DoT forwarders to children */ 7483570995aSflorian SIMPLEQ_FOREACH(unwind_forwarder, &xconf->unwind_dot_forwarder_list, 7493570995aSflorian entry) { 750*b2501eadSflorian if (main_sendall(IMSG_RECONF_DOT_FORWARDER, unwind_forwarder, 7513570995aSflorian sizeof(*unwind_forwarder)) == -1) 7523570995aSflorian return (-1); 7533570995aSflorian } 7543570995aSflorian 755018cebfbSflorian /* Tell children the revised config is now complete. */ 756*b2501eadSflorian if (main_sendall(IMSG_RECONF_END, NULL, 0) == -1) 757018cebfbSflorian return (-1); 758018cebfbSflorian 759018cebfbSflorian return (0); 760018cebfbSflorian } 761018cebfbSflorian 762018cebfbSflorian int 763*b2501eadSflorian main_sendall(enum imsg_type type, void *buf, uint16_t len) 764018cebfbSflorian { 765018cebfbSflorian if (imsg_compose_event(iev_frontend, type, 0, 0, -1, buf, len) == -1) 766018cebfbSflorian return (-1); 767018cebfbSflorian if (imsg_compose_event(iev_resolver, type, 0, 0, -1, buf, len) == -1) 768018cebfbSflorian return (-1); 769*b2501eadSflorian if (imsg_compose_event(iev_captiveportal, type, 0, 0, -1, buf, len) == 770*b2501eadSflorian -1) 771*b2501eadSflorian return (-1); 772018cebfbSflorian return (0); 773018cebfbSflorian } 774018cebfbSflorian 775018cebfbSflorian void 776018cebfbSflorian merge_config(struct unwind_conf *conf, struct unwind_conf *xconf) 777018cebfbSflorian { 778018cebfbSflorian struct unwind_forwarder *unwind_forwarder; 779018cebfbSflorian 780018cebfbSflorian /* Remove & discard existing forwarders. */ 781018cebfbSflorian while ((unwind_forwarder = 782018cebfbSflorian SIMPLEQ_FIRST(&conf->unwind_forwarder_list)) != NULL) { 783018cebfbSflorian SIMPLEQ_REMOVE_HEAD(&conf->unwind_forwarder_list, entry); 784018cebfbSflorian free(unwind_forwarder); 785018cebfbSflorian } 7863570995aSflorian while ((unwind_forwarder = 7873570995aSflorian SIMPLEQ_FIRST(&conf->unwind_dot_forwarder_list)) != NULL) { 7883570995aSflorian SIMPLEQ_REMOVE_HEAD(&conf->unwind_dot_forwarder_list, entry); 7893570995aSflorian free(unwind_forwarder); 7903570995aSflorian } 791018cebfbSflorian 792018cebfbSflorian conf->unwind_options = xconf->unwind_options; 793018cebfbSflorian 794*b2501eadSflorian free(conf->captive_portal_host); 795*b2501eadSflorian conf->captive_portal_host = xconf->captive_portal_host; 796*b2501eadSflorian 797*b2501eadSflorian free(conf->captive_portal_path); 798*b2501eadSflorian conf->captive_portal_path = xconf->captive_portal_path; 799*b2501eadSflorian 800*b2501eadSflorian free(conf->captive_portal_expected_response); 801*b2501eadSflorian conf->captive_portal_expected_response = 802*b2501eadSflorian xconf->captive_portal_expected_response; 803*b2501eadSflorian 804*b2501eadSflorian conf->captive_portal_expected_status = 805*b2501eadSflorian xconf->captive_portal_expected_status; 806*b2501eadSflorian 807*b2501eadSflorian conf->captive_portal_auto = xconf->captive_portal_auto; 808*b2501eadSflorian 809018cebfbSflorian /* Add new forwarders. */ 810018cebfbSflorian while ((unwind_forwarder = 811018cebfbSflorian SIMPLEQ_FIRST(&xconf->unwind_forwarder_list)) != NULL) { 812018cebfbSflorian SIMPLEQ_REMOVE_HEAD(&xconf->unwind_forwarder_list, entry); 813018cebfbSflorian SIMPLEQ_INSERT_TAIL(&conf->unwind_forwarder_list, 814018cebfbSflorian unwind_forwarder, entry); 815018cebfbSflorian } 8163570995aSflorian while ((unwind_forwarder = 8173570995aSflorian SIMPLEQ_FIRST(&xconf->unwind_dot_forwarder_list)) != NULL) { 8183570995aSflorian SIMPLEQ_REMOVE_HEAD(&xconf->unwind_dot_forwarder_list, entry); 8193570995aSflorian SIMPLEQ_INSERT_TAIL(&conf->unwind_dot_forwarder_list, 8203570995aSflorian unwind_forwarder, entry); 8213570995aSflorian } 822018cebfbSflorian 823018cebfbSflorian free(xconf); 824018cebfbSflorian } 825018cebfbSflorian 826018cebfbSflorian struct unwind_conf * 827018cebfbSflorian config_new_empty(void) 828018cebfbSflorian { 829018cebfbSflorian struct unwind_conf *xconf; 830018cebfbSflorian 831018cebfbSflorian xconf = calloc(1, sizeof(*xconf)); 832018cebfbSflorian if (xconf == NULL) 833018cebfbSflorian fatal(NULL); 834018cebfbSflorian 835018cebfbSflorian SIMPLEQ_INIT(&xconf->unwind_forwarder_list); 8363570995aSflorian SIMPLEQ_INIT(&xconf->unwind_dot_forwarder_list); 837018cebfbSflorian 838*b2501eadSflorian if ((xconf->captive_portal_expected_response = strdup("")) == NULL) 839*b2501eadSflorian fatal(NULL); 840*b2501eadSflorian xconf->captive_portal_expected_status = 200; 841*b2501eadSflorian xconf->captive_portal_auto = 1; 842*b2501eadSflorian 843018cebfbSflorian return (xconf); 844018cebfbSflorian } 845018cebfbSflorian 846018cebfbSflorian void 847018cebfbSflorian config_clear(struct unwind_conf *conf) 848018cebfbSflorian { 849018cebfbSflorian struct unwind_conf *xconf; 850018cebfbSflorian 851018cebfbSflorian /* Merge current config with an empty config. */ 852018cebfbSflorian xconf = config_new_empty(); 853018cebfbSflorian merge_config(conf, xconf); 854018cebfbSflorian 855018cebfbSflorian free(conf); 856018cebfbSflorian } 857018cebfbSflorian 858018cebfbSflorian 859018cebfbSflorian #define _PATH_LEASE_DB "/var/db/dhclient.leases." 860018cebfbSflorian 861018cebfbSflorian void 862018cebfbSflorian open_dhcp_lease(int if_idx) 863018cebfbSflorian { 864018cebfbSflorian static char lease_filename[sizeof(_PATH_LEASE_DB) + IF_NAMESIZE] = 865018cebfbSflorian _PATH_LEASE_DB; 866018cebfbSflorian 867018cebfbSflorian int fd; 868018cebfbSflorian char *bufp; 869018cebfbSflorian 870018cebfbSflorian bufp = lease_filename + sizeof(_PATH_LEASE_DB) - 1; 871018cebfbSflorian bufp = if_indextoname(if_idx, bufp); 872018cebfbSflorian 873018cebfbSflorian if (bufp == NULL) { 874018cebfbSflorian log_debug("cannot find interface %d", if_idx); 875018cebfbSflorian return; 876018cebfbSflorian } 877018cebfbSflorian 878018cebfbSflorian log_debug("lease file name: %s", lease_filename); 879018cebfbSflorian 880018cebfbSflorian if ((fd = open(lease_filename, O_RDONLY)) == -1) { 881018cebfbSflorian log_warn(NULL); 882018cebfbSflorian return; 883018cebfbSflorian } 884018cebfbSflorian 885018cebfbSflorian 886018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_LEASEFD, 0, fd); 887018cebfbSflorian } 888d265a5d3Sflorian 889d265a5d3Sflorian void 890d265a5d3Sflorian open_ports(void) 891d265a5d3Sflorian { 892d265a5d3Sflorian struct addrinfo hints, *res0; 893d265a5d3Sflorian int udp4sock = -1, udp6sock = -1, error; 894d265a5d3Sflorian 895d265a5d3Sflorian memset(&hints, 0, sizeof(hints)); 896d265a5d3Sflorian hints.ai_family = AF_INET; 897d265a5d3Sflorian hints.ai_socktype = SOCK_DGRAM; 898d265a5d3Sflorian hints.ai_flags = AI_PASSIVE; 899d265a5d3Sflorian 900d265a5d3Sflorian 901d265a5d3Sflorian error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); 902d265a5d3Sflorian if (!error && res0) { 903d265a5d3Sflorian if ((udp4sock = socket(res0->ai_family, res0->ai_socktype, 904d265a5d3Sflorian res0->ai_protocol)) != -1) { 905d265a5d3Sflorian if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen) 906d265a5d3Sflorian == -1) { 907d265a5d3Sflorian close(udp4sock); 908d265a5d3Sflorian udp4sock = -1; 909d265a5d3Sflorian } 910d265a5d3Sflorian } 911d265a5d3Sflorian } 912d265a5d3Sflorian freeaddrinfo(res0); 913d265a5d3Sflorian 914d265a5d3Sflorian hints.ai_family = AF_INET6; 915d265a5d3Sflorian error = getaddrinfo("::1", "domain", &hints, &res0); 916d265a5d3Sflorian if (!error && res0) { 917d265a5d3Sflorian if ((udp6sock = socket(res0->ai_family, res0->ai_socktype, 918d265a5d3Sflorian res0->ai_protocol)) != -1) { 919d265a5d3Sflorian if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen) 920d265a5d3Sflorian == -1) { 921d265a5d3Sflorian close(udp6sock); 922d265a5d3Sflorian udp6sock = -1; 923d265a5d3Sflorian } 924d265a5d3Sflorian } 925d265a5d3Sflorian } 926d265a5d3Sflorian freeaddrinfo(res0); 927d265a5d3Sflorian 928d265a5d3Sflorian if (udp4sock == -1 && udp6sock == -1) 929d265a5d3Sflorian fatal("could not bind to 127.0.0.1 or ::1 on port 53"); 930d265a5d3Sflorian 931b04dd19dSflorian if (udp4sock != -1) 932d265a5d3Sflorian main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock); 933b04dd19dSflorian if (udp6sock != -1) 934d265a5d3Sflorian main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock); 935d265a5d3Sflorian } 936