1 /* $OpenBSD: frontend.c,v 1.5 2019/01/27 12:40:54 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2018 Florian Obser <florian@openbsd.org> 5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/queue.h> 24 #include <sys/socket.h> 25 #include <sys/syslog.h> 26 #include <sys/uio.h> 27 28 #include <netinet/in.h> 29 #include <net/if.h> 30 #include <net/route.h> 31 32 #include <errno.h> 33 #include <event.h> 34 #include <imsg.h> 35 #include <netdb.h> 36 #include <pwd.h> 37 #include <signal.h> 38 #include <stdint.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <time.h> 43 #include <unistd.h> 44 45 #include "libunbound/config.h" 46 #include "libunbound/sldns/pkthdr.h" 47 #include "libunbound/sldns/sbuffer.h" 48 #include "libunbound/sldns/wire2str.h" 49 50 #include "uw_log.h" 51 #include "unwind.h" 52 #include "frontend.h" 53 #include "control.h" 54 55 #define ROUTE_SOCKET_BUF_SIZE 16384 56 57 struct udp_ev { 58 struct event ev; 59 uint8_t query[65536]; 60 struct msghdr rcvmhdr; 61 struct iovec rcviov[1]; 62 struct sockaddr_storage from; 63 } udp4ev, udp6ev; 64 65 struct pending_query { 66 TAILQ_ENTRY(pending_query) entry; 67 struct sockaddr_storage from; 68 uint8_t *query; 69 ssize_t len; 70 uint64_t imsg_id; 71 int fd; 72 int bogus; 73 }; 74 75 TAILQ_HEAD(, pending_query) pending_queries; 76 77 __dead void frontend_shutdown(void); 78 void frontend_sig_handler(int, short, void *); 79 void frontend_startup(void); 80 void udp_receive(int, short, void *); 81 void send_answer(struct pending_query *, uint8_t *, 82 ssize_t); 83 void route_receive(int, short, void *); 84 void handle_route_message(struct rt_msghdr *, 85 struct sockaddr **); 86 void get_rtaddrs(int, struct sockaddr *, 87 struct sockaddr **); 88 void rtmget_default(void); 89 char *ip_port(struct sockaddr *); 90 struct pending_query *find_pending_query(uint64_t); 91 void parse_dhcp_lease(int); 92 93 struct unwind_conf *frontend_conf; 94 struct imsgev *iev_main; 95 struct imsgev *iev_resolver; 96 struct event ev_route; 97 int udp4sock = -1, udp6sock = -1, routesock = -1; 98 99 void 100 frontend_sig_handler(int sig, short event, void *bula) 101 { 102 /* 103 * Normal signal handler rules don't apply because libevent 104 * decouples for us. 105 */ 106 107 switch (sig) { 108 case SIGINT: 109 case SIGTERM: 110 frontend_shutdown(); 111 default: 112 fatalx("unexpected signal"); 113 } 114 } 115 116 void 117 frontend(int debug, int verbose) 118 { 119 struct event ev_sigint, ev_sigterm; 120 struct passwd *pw; 121 size_t rcvcmsglen, sndcmsgbuflen; 122 uint8_t *rcvcmsgbuf; 123 uint8_t *sndcmsgbuf = NULL; 124 125 frontend_conf = config_new_empty(); 126 control_state.fd = -1; 127 128 log_init(debug, LOG_DAEMON); 129 log_setverbose(verbose); 130 131 if ((pw = getpwnam(UNWIND_USER)) == NULL) 132 fatal("getpwnam"); 133 134 if (chroot(pw->pw_dir) == -1) 135 fatal("chroot"); 136 if (chdir("/") == -1) 137 fatal("chdir(\"/\")"); 138 139 unwind_process = PROC_FRONTEND; 140 setproctitle("%s", log_procnames[unwind_process]); 141 log_procinit(log_procnames[unwind_process]); 142 143 if (setgroups(1, &pw->pw_gid) || 144 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 145 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 146 fatal("can't drop privileges"); 147 148 if (pledge("stdio unix recvfd", NULL) == -1) 149 fatal("pledge"); 150 151 event_init(); 152 153 /* Setup signal handler. */ 154 signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL); 155 signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL); 156 signal_add(&ev_sigint, NULL); 157 signal_add(&ev_sigterm, NULL); 158 signal(SIGPIPE, SIG_IGN); 159 signal(SIGHUP, SIG_IGN); 160 161 /* Setup pipe and event handler to the parent process. */ 162 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 163 fatal(NULL); 164 imsg_init(&iev_main->ibuf, 3); 165 iev_main->handler = frontend_dispatch_main; 166 iev_main->events = EV_READ; 167 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 168 iev_main->handler, iev_main); 169 event_add(&iev_main->ev, NULL); 170 171 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 172 CMSG_SPACE(sizeof(int)); 173 if((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) 174 fatal("malloc"); 175 176 udp4ev.rcviov[0].iov_base = (caddr_t)udp4ev.query; 177 udp4ev.rcviov[0].iov_len = sizeof(udp4ev.query); 178 udp4ev.rcvmhdr.msg_name = (caddr_t)&udp4ev.from; 179 udp4ev.rcvmhdr.msg_namelen = sizeof(udp4ev.from); 180 udp4ev.rcvmhdr.msg_iov = udp4ev.rcviov; 181 udp4ev.rcvmhdr.msg_iovlen = 1; 182 183 udp6ev.rcviov[0].iov_base = (caddr_t)udp6ev.query; 184 udp6ev.rcviov[0].iov_len = sizeof(udp6ev.query); 185 udp6ev.rcvmhdr.msg_name = (caddr_t)&udp6ev.from; 186 udp6ev.rcvmhdr.msg_namelen = sizeof(udp6ev.from); 187 udp6ev.rcvmhdr.msg_iov = udp6ev.rcviov; 188 udp6ev.rcvmhdr.msg_iovlen = 1; 189 190 sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 191 CMSG_SPACE(sizeof(int)); 192 if ((sndcmsgbuf = malloc(sndcmsgbuflen)) == NULL) 193 fatal("%s", __func__); 194 195 TAILQ_INIT(&pending_queries); 196 197 event_dispatch(); 198 199 frontend_shutdown(); 200 } 201 202 __dead void 203 frontend_shutdown(void) 204 { 205 /* Close pipes. */ 206 msgbuf_write(&iev_resolver->ibuf.w); 207 msgbuf_clear(&iev_resolver->ibuf.w); 208 close(iev_resolver->ibuf.fd); 209 msgbuf_write(&iev_main->ibuf.w); 210 msgbuf_clear(&iev_main->ibuf.w); 211 close(iev_main->ibuf.fd); 212 213 config_clear(frontend_conf); 214 215 free(iev_resolver); 216 free(iev_main); 217 218 log_info("frontend exiting"); 219 exit(0); 220 } 221 222 int 223 frontend_imsg_compose_main(int type, pid_t pid, void *data, uint16_t datalen) 224 { 225 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, 226 datalen)); 227 } 228 229 int 230 frontend_imsg_compose_resolver(int type, pid_t pid, void *data, uint16_t datalen) 231 { 232 return (imsg_compose_event(iev_resolver, type, 0, pid, -1, data, 233 datalen)); 234 } 235 236 void 237 frontend_dispatch_main(int fd, short event, void *bula) 238 { 239 static struct unwind_conf *nconf; 240 struct unwind_forwarder *unwind_forwarder; 241 struct imsg imsg; 242 struct imsgev *iev = bula; 243 struct imsgbuf *ibuf = &iev->ibuf; 244 int n, shut = 0; 245 246 if (event & EV_READ) { 247 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 248 fatal("imsg_read error"); 249 if (n == 0) /* Connection closed. */ 250 shut = 1; 251 } 252 if (event & EV_WRITE) { 253 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 254 fatal("msgbuf_write"); 255 if (n == 0) /* Connection closed. */ 256 shut = 1; 257 } 258 259 for (;;) { 260 if ((n = imsg_get(ibuf, &imsg)) == -1) 261 fatal("%s: imsg_get error", __func__); 262 if (n == 0) /* No more messages. */ 263 break; 264 265 switch (imsg.hdr.type) { 266 case IMSG_SOCKET_IPC: 267 /* 268 * Setup pipe and event handler to the resolver 269 * process. 270 */ 271 if (iev_resolver) { 272 log_warnx("%s: received unexpected imsg fd " 273 "to frontend", __func__); 274 break; 275 } 276 if ((fd = imsg.fd) == -1) { 277 log_warnx("%s: expected to receive imsg fd to " 278 "frontend but didn't receive any", 279 __func__); 280 break; 281 } 282 283 iev_resolver = malloc(sizeof(struct imsgev)); 284 if (iev_resolver == NULL) 285 fatal(NULL); 286 287 imsg_init(&iev_resolver->ibuf, fd); 288 iev_resolver->handler = frontend_dispatch_resolver; 289 iev_resolver->events = EV_READ; 290 291 event_set(&iev_resolver->ev, iev_resolver->ibuf.fd, 292 iev_resolver->events, iev_resolver->handler, iev_resolver); 293 event_add(&iev_resolver->ev, NULL); 294 break; 295 case IMSG_RECONF_CONF: 296 if ((nconf = malloc(sizeof(struct unwind_conf))) == 297 NULL) 298 fatal(NULL); 299 memcpy(nconf, imsg.data, sizeof(struct unwind_conf)); 300 SIMPLEQ_INIT(&nconf->unwind_forwarder_list); 301 SIMPLEQ_INIT(&nconf->unwind_dot_forwarder_list); 302 break; 303 case IMSG_RECONF_FORWARDER: 304 if ((unwind_forwarder = malloc(sizeof(struct 305 unwind_forwarder))) == NULL) 306 fatal(NULL); 307 memcpy(unwind_forwarder, imsg.data, sizeof(struct 308 unwind_forwarder)); 309 SIMPLEQ_INSERT_TAIL(&nconf->unwind_forwarder_list, 310 unwind_forwarder, entry); 311 break; 312 case IMSG_RECONF_DOT_FORWARDER: 313 if ((unwind_forwarder = malloc(sizeof(struct 314 unwind_forwarder))) == NULL) 315 fatal(NULL); 316 memcpy(unwind_forwarder, imsg.data, sizeof(struct 317 unwind_forwarder)); 318 SIMPLEQ_INSERT_TAIL(&nconf->unwind_dot_forwarder_list, 319 unwind_forwarder, entry); 320 break; 321 case IMSG_RECONF_END: 322 merge_config(frontend_conf, nconf); 323 nconf = NULL; 324 break; 325 case IMSG_UDP6SOCK: 326 if ((udp6sock = imsg.fd) == -1) 327 fatalx("%s: expected to receive imsg " 328 "UDP6 fd but didn't receive any", 329 __func__); 330 event_set(&udp6ev.ev, udp6sock, EV_READ | EV_PERSIST, 331 udp_receive, &udp6ev); 332 event_add(&udp6ev.ev, NULL); 333 break; 334 case IMSG_UDP4SOCK: 335 if ((udp4sock = imsg.fd) == -1) 336 fatalx("%s: expected to receive imsg " 337 "UDP4 fd but didn't receive any", 338 __func__); 339 event_set(&udp4ev.ev, udp4sock, EV_READ | EV_PERSIST, 340 udp_receive, &udp4ev); 341 event_add(&udp4ev.ev, NULL); 342 break; 343 case IMSG_ROUTESOCK: 344 if ((fd = imsg.fd) == -1) 345 fatalx("%s: expected to receive imsg " 346 "routesocket fd but didn't receive any", 347 __func__); 348 routesock = fd; 349 event_set(&ev_route, fd, EV_READ | EV_PERSIST, 350 route_receive, NULL); 351 break; 352 case IMSG_STARTUP: 353 frontend_startup(); 354 break; 355 case IMSG_CONTROLFD: 356 if ((fd = imsg.fd) == -1) 357 fatalx("%s: expected to receive imsg " 358 "control fd but didn't receive any", 359 __func__); 360 control_state.fd = fd; 361 /* Listen on control socket. */ 362 TAILQ_INIT(&ctl_conns); 363 control_listen(); 364 break; 365 case IMSG_LEASEFD: 366 if ((fd = imsg.fd) == -1) 367 fatalx("%s: expected to receive imsg " 368 "dhcp lease fd but didn't receive any", 369 __func__); 370 parse_dhcp_lease(fd); 371 break; 372 case IMSG_SHUTDOWN: 373 frontend_imsg_compose_resolver(IMSG_SHUTDOWN, 0, NULL, 0); 374 break; 375 default: 376 log_debug("%s: error handling imsg %d", __func__, 377 imsg.hdr.type); 378 break; 379 } 380 imsg_free(&imsg); 381 } 382 if (!shut) 383 imsg_event_add(iev); 384 else { 385 /* This pipe is dead. Remove its event handler. */ 386 event_del(&iev->ev); 387 event_loopexit(NULL); 388 } 389 } 390 391 void 392 frontend_dispatch_resolver(int fd, short event, void *bula) 393 { 394 static struct pending_query *pq; 395 struct imsgev *iev = bula; 396 struct imsgbuf *ibuf = &iev->ibuf; 397 struct imsg imsg; 398 struct query_imsg *query_imsg; 399 int n, shut = 0; 400 401 if (event & EV_READ) { 402 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 403 fatal("imsg_read error"); 404 if (n == 0) /* Connection closed. */ 405 shut = 1; 406 } 407 if (event & EV_WRITE) { 408 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 409 fatal("msgbuf_write"); 410 if (n == 0) /* Connection closed. */ 411 shut = 1; 412 } 413 414 for (;;) { 415 if ((n = imsg_get(ibuf, &imsg)) == -1) 416 fatal("%s: imsg_get error", __func__); 417 if (n == 0) /* No more messages. */ 418 break; 419 420 switch (imsg.hdr.type) { 421 case IMSG_SHUTDOWN: 422 frontend_imsg_compose_main(IMSG_SHUTDOWN, 0, NULL, 0); 423 break; 424 case IMSG_ANSWER_HEADER: 425 /* XX size */ 426 query_imsg = (struct query_imsg *)imsg.data; 427 if ((pq = find_pending_query(query_imsg->id)) == 428 NULL) { 429 log_warnx("cannot find pending query %llu", 430 query_imsg->id); 431 break; 432 } 433 if (query_imsg->err) { 434 send_answer(pq, NULL, 0); 435 pq = NULL; 436 break; 437 } 438 pq->bogus = query_imsg->bogus; 439 break; 440 case IMSG_ANSWER: 441 if (pq == NULL) 442 fatalx("IMSG_ANSWER without HEADER"); 443 send_answer(pq, imsg.data, imsg.hdr.len - 444 IMSG_HEADER_SIZE); 445 break; 446 case IMSG_RESOLVER_DOWN: 447 log_debug("%s: IMSG_RESOLVER_DOWN", __func__); 448 if (udp4sock != -1) { 449 event_del(&udp4ev.ev); 450 close(udp4sock); 451 udp4sock = -1; 452 } 453 if (udp6sock != -1) { 454 event_del(&udp6ev.ev); 455 close(udp6sock); 456 udp6sock = -1; 457 } 458 break; 459 case IMSG_RESOLVER_UP: 460 log_debug("%s: IMSG_RESOLVER_UP", __func__); 461 frontend_imsg_compose_main(IMSG_OPEN_PORTS, 0, NULL, 0); 462 break; 463 case IMSG_CTL_RESOLVER_INFO: 464 case IMSG_CTL_RESOLVER_WHY_BOGUS: 465 case IMSG_CTL_RESOLVER_HISTOGRAM: 466 case IMSG_CTL_END: 467 control_imsg_relay(&imsg); 468 break; 469 default: 470 log_debug("%s: error handling imsg %d", __func__, 471 imsg.hdr.type); 472 break; 473 } 474 imsg_free(&imsg); 475 } 476 if (!shut) 477 imsg_event_add(iev); 478 else { 479 /* This pipe is dead. Remove its event handler. */ 480 event_del(&iev->ev); 481 event_loopexit(NULL); 482 } 483 } 484 485 void 486 frontend_startup(void) 487 { 488 if (!event_initialized(&ev_route)) 489 fatalx("%s: did not receive a route socket from the main " 490 "process", __func__); 491 492 event_add(&ev_route, NULL); 493 494 frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0); 495 rtmget_default(); 496 } 497 498 void 499 udp_receive(int fd, short events, void *arg) 500 { 501 struct udp_ev *udpev = (struct udp_ev *)arg; 502 struct pending_query *pq; 503 struct query_imsg *query_imsg; 504 ssize_t len, rem_len, buf_len; 505 uint16_t qdcount, ancount, nscount, arcount, t, c; 506 uint8_t *queryp; 507 char *str_from, *str, buf[1024], *bufp; 508 509 if ((len = recvmsg(fd, &udpev->rcvmhdr, 0)) < 0) { 510 log_warn("recvmsg"); 511 return; 512 } 513 514 bufp = buf; 515 buf_len = sizeof(buf); 516 517 str_from = ip_port((struct sockaddr *)&udpev->from); 518 519 if (len < LDNS_HEADER_SIZE) { 520 log_warnx("bad query: too short, from: %s", str_from); 521 return; 522 } 523 524 qdcount = LDNS_QDCOUNT(udpev->query); 525 ancount = LDNS_ANCOUNT(udpev->query); 526 nscount = LDNS_NSCOUNT(udpev->query); 527 arcount = LDNS_ARCOUNT(udpev->query); 528 529 if (qdcount != 1 && ancount != 0 && nscount != 0 && arcount != 0) { 530 log_warnx("invalid query from %s, qdcount: %d, ancount: %d " 531 "nscount: %d, arcount: %d", str_from, qdcount, ancount, 532 nscount, arcount); 533 return; 534 } 535 536 log_debug("query from %s", str_from); 537 if ((str = sldns_wire2str_pkt(udpev->query, len)) != NULL) { 538 log_debug("%s", str); 539 free(str); 540 } 541 542 queryp = udpev->query; 543 rem_len = len; 544 545 queryp += LDNS_HEADER_SIZE; 546 rem_len -= LDNS_HEADER_SIZE; 547 548 sldns_wire2str_dname_scan(&queryp, &rem_len, &bufp, &buf_len, 549 udpev->query, len); 550 551 if (rem_len < 4) { 552 log_warnx("malformed query"); 553 return; 554 } 555 556 t = sldns_read_uint16(queryp); 557 c = sldns_read_uint16(queryp+2); 558 queryp += 4; 559 rem_len -= 4; 560 561 if ((pq = malloc(sizeof(*pq))) == NULL) { 562 log_warn(NULL); 563 return; 564 } 565 566 if ((pq->query = malloc(len)) == NULL) { 567 log_warn(NULL); 568 free(pq); 569 return; 570 } 571 572 do { 573 arc4random_buf(&pq->imsg_id, sizeof(pq->imsg_id)); 574 } while(find_pending_query(pq->imsg_id) != NULL); 575 576 memcpy(pq->query, udpev->query, len); 577 pq->len = len; 578 pq->from = udpev->from; 579 pq->fd = fd; 580 581 if ((query_imsg = calloc(1, sizeof(*query_imsg))) == NULL) { 582 log_warn(NULL); 583 return; 584 } 585 586 if (strlcpy(query_imsg->qname, buf, sizeof(query_imsg->qname)) >= 587 sizeof(buf)) { 588 log_warnx("qname too long"); 589 free(query_imsg); 590 /* XXX SERVFAIL */ 591 free(pq->query); 592 free(pq); 593 return; 594 } 595 query_imsg->id = pq->imsg_id; 596 query_imsg->t = t; 597 query_imsg->c = c; 598 599 if (frontend_imsg_compose_resolver(IMSG_QUERY, 0, query_imsg, 600 sizeof(*query_imsg)) != -1) { 601 TAILQ_INSERT_TAIL(&pending_queries, pq, entry); 602 } else { 603 free(query_imsg); 604 /* XXX SERVFAIL */ 605 free(pq->query); 606 free(pq); 607 } 608 609 } 610 611 void 612 send_answer(struct pending_query *pq, uint8_t *answer, ssize_t len) 613 { 614 log_debug("result for %s", 615 ip_port((struct sockaddr*)&pq->from)); 616 617 if (answer == NULL) { 618 answer = pq->query; 619 len = pq->len; 620 621 LDNS_QR_SET(answer); 622 LDNS_RA_SET(answer); 623 LDNS_RCODE_SET(answer, LDNS_RCODE_SERVFAIL); 624 } else { 625 if (pq->bogus) { 626 if(LDNS_CD_WIRE(pq->query)) { 627 LDNS_ID_SET(answer, LDNS_ID_WIRE(pq->query)); 628 LDNS_CD_SET(answer); 629 } else { 630 answer = pq->query; 631 len = pq->len; 632 633 LDNS_QR_SET(answer); 634 LDNS_RA_SET(answer); 635 LDNS_RCODE_SET(answer, LDNS_RCODE_SERVFAIL); 636 } 637 } else { 638 LDNS_ID_SET(answer, LDNS_ID_WIRE(pq->query)); 639 } 640 } 641 642 if(sendto(pq->fd, answer, len, 0, (struct sockaddr *) 643 &pq->from, pq->from.ss_len) == -1) 644 log_warn("sendto"); 645 646 TAILQ_REMOVE(&pending_queries, pq, entry); 647 free(pq->query); 648 free(pq); 649 } 650 651 char* 652 ip_port(struct sockaddr *sa) 653 { 654 static char hbuf[NI_MAXHOST], buf[NI_MAXHOST]; 655 656 if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 657 NI_NUMERICHOST) != 0) { 658 snprintf(buf, sizeof(buf), "%s", "(unknown)"); 659 return buf; 660 } 661 662 if (sa->sa_family == AF_INET6) 663 snprintf(buf, sizeof(buf), "[%s]:%d", hbuf, 664 ((struct sockaddr_in6 *)sa)->sin6_port); 665 if (sa->sa_family == AF_INET) 666 snprintf(buf, sizeof(buf), "[%s]:%d", hbuf, 667 ((struct sockaddr_in *)sa)->sin_port); 668 669 return buf; 670 } 671 672 struct pending_query* 673 find_pending_query(uint64_t id) 674 { 675 struct pending_query *pq; 676 677 TAILQ_FOREACH(pq, &pending_queries, entry) 678 if (pq->imsg_id == id) 679 return pq; 680 return NULL; 681 } 682 683 void 684 route_receive(int fd, short events, void *arg) 685 { 686 static uint8_t *buf; 687 688 struct rt_msghdr *rtm; 689 struct sockaddr *sa, *rti_info[RTAX_MAX]; 690 ssize_t n; 691 692 if (buf == NULL) { 693 buf = malloc(ROUTE_SOCKET_BUF_SIZE); 694 if (buf == NULL) 695 fatal("malloc"); 696 } 697 rtm = (struct rt_msghdr *)buf; 698 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) { 699 if (errno == EAGAIN || errno == EINTR) 700 return; 701 log_warn("dispatch_rtmsg: read error"); 702 return; 703 } 704 705 if (n == 0) 706 fatal("routing socket closed"); 707 708 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) { 709 log_warnx("partial rtm of %zd in buffer", n); 710 return; 711 } 712 713 if (rtm->rtm_version != RTM_VERSION) 714 return; 715 716 sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen); 717 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 718 719 handle_route_message(rtm, rti_info); 720 } 721 722 #define ROUNDUP(a) \ 723 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 724 725 void 726 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 727 { 728 int i; 729 730 for (i = 0; i < RTAX_MAX; i++) { 731 if (addrs & (1 << i)) { 732 rti_info[i] = sa; 733 sa = (struct sockaddr *)((char *)(sa) + 734 ROUNDUP(sa->sa_len)); 735 } else 736 rti_info[i] = NULL; 737 } 738 } 739 740 void 741 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) 742 { 743 char buf[IF_NAMESIZE], *bufp; 744 745 switch (rtm->rtm_type) { 746 case RTM_GET: 747 if (rtm->rtm_errno != 0) 748 break; 749 if (!(rtm->rtm_flags & RTF_UP)) 750 break; 751 if (!(rtm->rtm_addrs & RTA_DST)) 752 break; 753 if (rti_info[RTAX_DST]->sa_family != AF_INET) 754 break; 755 if (((struct sockaddr_in *)rti_info[RTAX_DST])->sin_addr. 756 s_addr != INADDR_ANY) 757 break; 758 if (!(rtm->rtm_addrs & RTA_NETMASK)) 759 break; 760 if (rti_info[RTAX_NETMASK]->sa_family != AF_INET) 761 break; 762 if (((struct sockaddr_in *)rti_info[RTAX_NETMASK])->sin_addr. 763 s_addr != INADDR_ANY) 764 break; 765 766 frontend_imsg_compose_main(IMSG_OPEN_DHCP_LEASE, 0, 767 &rtm->rtm_index, sizeof(rtm->rtm_index)); 768 769 bufp = if_indextoname(rtm->rtm_index, buf); 770 if (bufp) 771 log_debug("default route is on %s", buf); 772 773 break; 774 default: 775 break; 776 } 777 778 } 779 780 void 781 rtmget_default(void) 782 { 783 static int rtm_seq; 784 struct rt_msghdr rtm; 785 struct sockaddr_in sin; 786 struct iovec iov[5]; 787 long pad = 0; 788 int iovcnt = 0, padlen; 789 790 memset(&sin, 0, sizeof(sin)); 791 sin.sin_family = AF_INET; 792 sin.sin_len = sizeof(sin); 793 794 memset(&rtm, 0, sizeof(rtm)); 795 796 rtm.rtm_version = RTM_VERSION; 797 rtm.rtm_type = RTM_GET; 798 rtm.rtm_msglen = sizeof(rtm); 799 rtm.rtm_tableid = 0; /* XXX imsg->rdomain; */ 800 rtm.rtm_seq = ++rtm_seq; 801 rtm.rtm_addrs = RTA_DST | RTA_NETMASK; 802 803 iov[iovcnt].iov_base = &rtm; 804 iov[iovcnt++].iov_len = sizeof(rtm); 805 806 /* dst */ 807 iov[iovcnt].iov_base = &sin; 808 iov[iovcnt++].iov_len = sizeof(sin); 809 rtm.rtm_msglen += sizeof(sin); 810 padlen = ROUNDUP(sizeof(sin)) - sizeof(sin); 811 if (padlen > 0) { 812 iov[iovcnt].iov_base = &pad; 813 iov[iovcnt++].iov_len = padlen; 814 rtm.rtm_msglen += padlen; 815 } 816 817 /* mask */ 818 iov[iovcnt].iov_base = &sin; 819 iov[iovcnt++].iov_len = sizeof(sin); 820 rtm.rtm_msglen += sizeof(sin); 821 padlen = ROUNDUP(sizeof(sin)) - sizeof(sin); 822 if (padlen > 0) { 823 iov[iovcnt].iov_base = &pad; 824 iov[iovcnt++].iov_len = padlen; 825 rtm.rtm_msglen += padlen; 826 } 827 828 if (writev(routesock, iov, iovcnt) == -1) 829 log_warn("failed to send route message"); 830 } 831 832 void 833 parse_dhcp_lease(int fd) 834 { 835 FILE *f; 836 char *line = NULL, *cur_ns = NULL, *ns = NULL; 837 size_t linesize = 0; 838 ssize_t linelen; 839 time_t epoch, lease_time, now; 840 char **tok, *toks[4], *p; 841 842 if((f = fdopen(fd, "r")) == NULL) { 843 log_warn("cannot read dhcp lease"); 844 close(fd); 845 return; 846 } 847 848 now = time(NULL); 849 850 while ((linelen = getline(&line, &linesize, f)) != -1) { 851 for (tok = toks; tok < &toks[3] && (*tok = strsep(&line, " \t")) 852 != NULL;) { 853 if (**tok != '\0') 854 tok++; 855 } 856 *tok = NULL; 857 if (strcmp(toks[0], "option") == 0) { 858 if (strcmp(toks[1], "domain-name-servers") == 0) { 859 if((p = strchr(toks[2], ';')) != NULL) { 860 *p='\0'; 861 cur_ns = strdup(toks[2]); 862 } 863 } 864 if (strcmp(toks[1], "dhcp-lease-time") == 0) { 865 if((p = strchr(toks[2], ';')) != NULL) { 866 *p='\0'; 867 lease_time = strtonum(toks[2], 0, 868 INT64_MAX, NULL); 869 } 870 } 871 } else if (strcmp(toks[0], "epoch") == 0) { 872 if((p = strchr(toks[1], ';')) != NULL) { 873 *p='\0'; 874 epoch = strtonum(toks[1], 0, 875 INT64_MAX, NULL); 876 } 877 } 878 else if (*toks[0] == '}') { 879 if (epoch + lease_time > now ) { 880 free(ns); 881 ns = cur_ns; 882 //log_debug("ns: %s, lease_time: %lld, epoch: " 883 // "%lld\n", cur_ns, lease_time, epoch); 884 } else /* expired lease */ 885 free(cur_ns); 886 } 887 } 888 free(line); 889 890 if (ferror(f)) 891 log_warn("getline"); 892 fclose(f); 893 894 if (ns != NULL) { 895 log_debug("%s: ns: %s", __func__, ns); 896 frontend_imsg_compose_resolver(IMSG_FORWARDER, 0, ns, 897 strlen(ns) + 1); 898 } 899 } 900