1 /* $OpenBSD: frontend.c,v 1.23 2021/10/20 07:04:49 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2017, 2021 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 #include <sys/types.h> 22 #include <sys/ioctl.h> 23 #include <sys/queue.h> 24 #include <sys/socket.h> 25 #include <sys/syslog.h> 26 #include <sys/uio.h> 27 28 #include <net/bpf.h> 29 #include <net/if.h> 30 #include <net/if_dl.h> 31 #include <net/if_types.h> 32 #include <net/route.h> 33 34 #include <netinet/in.h> 35 #include <netinet/if_ether.h> 36 #include <netinet/ip.h> 37 #include <netinet/udp.h> 38 39 #include <arpa/inet.h> 40 41 #include <errno.h> 42 #include <event.h> 43 #include <ifaddrs.h> 44 #include <imsg.h> 45 #include <pwd.h> 46 #include <signal.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 52 #include "bpf.h" 53 #include "log.h" 54 #include "dhcpleased.h" 55 #include "frontend.h" 56 #include "control.h" 57 #include "checksum.h" 58 59 #define ROUTE_SOCKET_BUF_SIZE 16384 60 #define BOOTP_MIN_LEN 300 /* fixed bootp packet adds up to 300 */ 61 62 struct bpf_ev { 63 struct event ev; 64 uint8_t buf[BPFLEN]; 65 }; 66 67 struct iface { 68 LIST_ENTRY(iface) entries; 69 struct bpf_ev bpfev; 70 struct imsg_ifinfo ifinfo; 71 int send_discover; 72 uint32_t xid; 73 struct in_addr requested_ip; 74 struct in_addr server_identifier; 75 struct in_addr dhcp_server; 76 int udpsock; 77 }; 78 79 __dead void frontend_shutdown(void); 80 void frontend_sig_handler(int, short, void *); 81 void update_iface(struct if_msghdr *, struct sockaddr_dl *); 82 void frontend_startup(void); 83 void init_ifaces(void); 84 void route_receive(int, short, void *); 85 void handle_route_message(struct rt_msghdr *, struct sockaddr **); 86 void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 87 void bpf_receive(int, short, void *); 88 int get_flags(char *); 89 int get_xflags(char *); 90 struct iface *get_iface_by_id(uint32_t); 91 void remove_iface(uint32_t); 92 void set_bpfsock(int, uint32_t); 93 ssize_t build_packet(uint8_t, char *, uint32_t, struct ether_addr *, 94 struct in_addr *, struct in_addr *); 95 void send_discover(struct iface *); 96 void send_request(struct iface *); 97 void bpf_send_packet(struct iface *, uint8_t *, ssize_t); 98 int udp_send_packet(struct iface *, uint8_t *, ssize_t); 99 #ifndef SMALL 100 int iface_conf_cmp(struct iface_conf *, struct iface_conf *); 101 #endif /* SMALL */ 102 103 LIST_HEAD(, iface) interfaces; 104 struct dhcpleased_conf *frontend_conf; 105 static struct imsgev *iev_main; 106 static struct imsgev *iev_engine; 107 struct event ev_route; 108 int ioctlsock; 109 110 uint8_t dhcp_packet[1500]; 111 112 void 113 frontend_sig_handler(int sig, short event, void *bula) 114 { 115 /* 116 * Normal signal handler rules don't apply because libevent 117 * decouples for us. 118 */ 119 120 switch (sig) { 121 case SIGINT: 122 case SIGTERM: 123 frontend_shutdown(); 124 default: 125 fatalx("unexpected signal"); 126 } 127 } 128 129 void 130 frontend(int debug, int verbose) 131 { 132 struct event ev_sigint, ev_sigterm; 133 struct passwd *pw; 134 135 #ifndef SMALL 136 frontend_conf = config_new_empty(); 137 #endif /* SMALL */ 138 139 log_init(debug, LOG_DAEMON); 140 log_setverbose(verbose); 141 142 if ((pw = getpwnam(DHCPLEASED_USER)) == NULL) 143 fatal("getpwnam"); 144 145 if (chdir("/") == -1) 146 fatal("chdir(\"/\")"); 147 148 if (unveil("/", "") == -1) 149 fatal("unveil /"); 150 if (unveil(NULL, NULL) == -1) 151 fatal("unveil"); 152 153 setproctitle("%s", "frontend"); 154 log_procinit("frontend"); 155 156 if ((ioctlsock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)) == -1) 157 fatal("socket"); 158 159 if (setgroups(1, &pw->pw_gid) || 160 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 161 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 162 fatal("can't drop privileges"); 163 164 if (pledge("stdio unix recvfd route", NULL) == -1) 165 fatal("pledge"); 166 event_init(); 167 168 /* Setup signal handler. */ 169 signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL); 170 signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL); 171 signal_add(&ev_sigint, NULL); 172 signal_add(&ev_sigterm, NULL); 173 signal(SIGPIPE, SIG_IGN); 174 signal(SIGHUP, SIG_IGN); 175 176 /* Setup pipe and event handler to the parent process. */ 177 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 178 fatal(NULL); 179 imsg_init(&iev_main->ibuf, 3); 180 iev_main->handler = frontend_dispatch_main; 181 iev_main->events = EV_READ; 182 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 183 iev_main->handler, iev_main); 184 event_add(&iev_main->ev, NULL); 185 186 LIST_INIT(&interfaces); 187 event_dispatch(); 188 189 frontend_shutdown(); 190 } 191 192 __dead void 193 frontend_shutdown(void) 194 { 195 /* Close pipes. */ 196 msgbuf_write(&iev_engine->ibuf.w); 197 msgbuf_clear(&iev_engine->ibuf.w); 198 close(iev_engine->ibuf.fd); 199 msgbuf_write(&iev_main->ibuf.w); 200 msgbuf_clear(&iev_main->ibuf.w); 201 close(iev_main->ibuf.fd); 202 203 #ifndef SMALL 204 config_clear(frontend_conf); 205 #endif /* SMALL */ 206 207 free(iev_engine); 208 free(iev_main); 209 210 log_info("frontend exiting"); 211 exit(0); 212 } 213 214 int 215 frontend_imsg_compose_main(int type, pid_t pid, void *data, 216 uint16_t datalen) 217 { 218 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, 219 datalen)); 220 } 221 222 int 223 frontend_imsg_compose_engine(int type, uint32_t peerid, pid_t pid, 224 void *data, uint16_t datalen) 225 { 226 return (imsg_compose_event(iev_engine, type, peerid, pid, -1, 227 data, datalen)); 228 } 229 230 void 231 frontend_dispatch_main(int fd, short event, void *bula) 232 { 233 static struct dhcpleased_conf *nconf; 234 static struct iface_conf *iface_conf; 235 struct imsg imsg; 236 struct imsgev *iev = bula; 237 struct imsgbuf *ibuf = &iev->ibuf; 238 struct iface *iface; 239 ssize_t n; 240 int shut = 0, bpfsock, if_index, udpsock; 241 242 if (event & EV_READ) { 243 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 244 fatal("imsg_read error"); 245 if (n == 0) /* Connection closed. */ 246 shut = 1; 247 } 248 if (event & EV_WRITE) { 249 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 250 fatal("msgbuf_write"); 251 if (n == 0) /* Connection closed. */ 252 shut = 1; 253 } 254 255 for (;;) { 256 if ((n = imsg_get(ibuf, &imsg)) == -1) 257 fatal("%s: imsg_get error", __func__); 258 if (n == 0) /* No more messages. */ 259 break; 260 261 switch (imsg.hdr.type) { 262 case IMSG_SOCKET_IPC: 263 /* 264 * Setup pipe and event handler to the engine 265 * process. 266 */ 267 if (iev_engine) 268 fatalx("%s: received unexpected imsg fd " 269 "to frontend", __func__); 270 271 if ((fd = imsg.fd) == -1) 272 fatalx("%s: expected to receive imsg fd to " 273 "frontend but didn't receive any", 274 __func__); 275 276 iev_engine = malloc(sizeof(struct imsgev)); 277 if (iev_engine == NULL) 278 fatal(NULL); 279 280 imsg_init(&iev_engine->ibuf, fd); 281 iev_engine->handler = frontend_dispatch_engine; 282 iev_engine->events = EV_READ; 283 284 event_set(&iev_engine->ev, iev_engine->ibuf.fd, 285 iev_engine->events, iev_engine->handler, iev_engine); 286 event_add(&iev_engine->ev, NULL); 287 break; 288 case IMSG_BPFSOCK: 289 if ((bpfsock = imsg.fd) == -1) 290 fatalx("%s: expected to receive imsg " 291 "bpf fd but didn't receive any", 292 __func__); 293 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 294 fatalx("%s: IMSG_BPFSOCK wrong length: " 295 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 296 memcpy(&if_index, imsg.data, sizeof(if_index)); 297 set_bpfsock(bpfsock, if_index); 298 break; 299 case IMSG_UDPSOCK: 300 if ((udpsock = imsg.fd) == -1) 301 fatalx("%s: expected to receive imsg " 302 "udpsocket fd but didn't receive any", 303 __func__); 304 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 305 fatalx("%s: IMSG_UDPSOCK wrong length: " 306 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 307 memcpy(&if_index, imsg.data, sizeof(if_index)); 308 if ((iface = get_iface_by_id(if_index)) == NULL) { 309 close(fd); 310 break; 311 } 312 if (iface->udpsock != -1) 313 fatalx("%s: received unexpected udpsocket", 314 __func__); 315 iface->udpsock = udpsock; 316 break; 317 case IMSG_CLOSE_UDPSOCK: 318 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 319 fatalx("%s: IMSG_UDPSOCK wrong length: " 320 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 321 memcpy(&if_index, imsg.data, sizeof(if_index)); 322 if ((iface = get_iface_by_id(if_index)) != NULL && 323 iface->udpsock != -1) { 324 close(iface->udpsock); 325 iface->udpsock = -1; 326 } 327 break; 328 case IMSG_ROUTESOCK: 329 if ((fd = imsg.fd) == -1) 330 fatalx("%s: expected to receive imsg " 331 "routesocket fd but didn't receive any", 332 __func__); 333 event_set(&ev_route, fd, EV_READ | EV_PERSIST, 334 route_receive, NULL); 335 break; 336 case IMSG_STARTUP: 337 frontend_startup(); 338 break; 339 #ifndef SMALL 340 case IMSG_RECONF_CONF: 341 if (nconf != NULL) 342 fatalx("%s: IMSG_RECONF_CONF already in " 343 "progress", __func__); 344 if ((nconf = malloc(sizeof(struct dhcpleased_conf))) == 345 NULL) 346 fatal(NULL); 347 SIMPLEQ_INIT(&nconf->iface_list); 348 break; 349 case IMSG_RECONF_IFACE: 350 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 351 iface_conf)) 352 fatalx("%s: IMSG_RECONF_IFACE wrong length: " 353 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 354 if ((iface_conf = malloc(sizeof(struct iface_conf))) 355 == NULL) 356 fatal(NULL); 357 memcpy(iface_conf, imsg.data, sizeof(struct 358 iface_conf)); 359 iface_conf->vc_id = NULL; 360 iface_conf->vc_id_len = 0; 361 iface_conf->c_id = NULL; 362 iface_conf->c_id_len = 0; 363 SIMPLEQ_INSERT_TAIL(&nconf->iface_list, 364 iface_conf, entry); 365 break; 366 case IMSG_RECONF_VC_ID: 367 if (iface_conf == NULL) 368 fatal("IMSG_RECONF_VC_ID without " 369 "IMSG_RECONF_IFACE"); 370 if (IMSG_DATA_SIZE(imsg) > 255 + 2) 371 fatalx("%s: IMSG_RECONF_VC_ID wrong length: " 372 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 373 if ((iface_conf->vc_id = malloc(IMSG_DATA_SIZE(imsg))) 374 == NULL) 375 fatal(NULL); 376 memcpy(iface_conf->vc_id, imsg.data, 377 IMSG_DATA_SIZE(imsg)); 378 iface_conf->vc_id_len = IMSG_DATA_SIZE(imsg); 379 break; 380 case IMSG_RECONF_C_ID: 381 if (iface_conf == NULL) 382 fatal("IMSG_RECONF_C_ID without " 383 "IMSG_RECONF_IFACE"); 384 if (IMSG_DATA_SIZE(imsg) > 255 + 2) 385 fatalx("%s: IMSG_RECONF_C_ID wrong length: " 386 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 387 if ((iface_conf->c_id = malloc(IMSG_DATA_SIZE(imsg))) 388 == NULL) 389 fatal(NULL); 390 memcpy(iface_conf->c_id, imsg.data, 391 IMSG_DATA_SIZE(imsg)); 392 iface_conf->c_id_len = IMSG_DATA_SIZE(imsg); 393 break; 394 case IMSG_RECONF_END: { 395 int i; 396 int *ifaces; 397 char ifnamebuf[IF_NAMESIZE], *if_name; 398 399 if (nconf == NULL) 400 fatalx("%s: IMSG_RECONF_END without " 401 "IMSG_RECONF_CONF", __func__); 402 403 ifaces = changed_ifaces(frontend_conf, nconf); 404 merge_config(frontend_conf, nconf); 405 nconf = NULL; 406 for (i = 0; ifaces[i] != 0; i++) { 407 if_index = ifaces[i]; 408 if_name = if_indextoname(if_index, ifnamebuf); 409 log_debug("changed iface: %s[%d]", if_name != 410 NULL ? if_name : "<unknown>", if_index); 411 frontend_imsg_compose_engine( 412 IMSG_REQUEST_REBOOT, 0, 0, &if_index, 413 sizeof(if_index)); 414 } 415 free(ifaces); 416 break; 417 } 418 case IMSG_CONTROLFD: 419 if ((fd = imsg.fd) == -1) 420 fatalx("%s: expected to receive imsg " 421 "control fd but didn't receive any", 422 __func__); 423 /* Listen on control socket. */ 424 control_listen(fd); 425 break; 426 case IMSG_CTL_END: 427 control_imsg_relay(&imsg); 428 break; 429 #endif /* SMALL */ 430 default: 431 log_debug("%s: error handling imsg %d", __func__, 432 imsg.hdr.type); 433 break; 434 } 435 imsg_free(&imsg); 436 } 437 if (!shut) 438 imsg_event_add(iev); 439 else { 440 /* This pipe is dead. Remove its event handler. */ 441 event_del(&iev->ev); 442 event_loopexit(NULL); 443 } 444 } 445 446 void 447 frontend_dispatch_engine(int fd, short event, void *bula) 448 { 449 struct imsgev *iev = bula; 450 struct imsgbuf *ibuf = &iev->ibuf; 451 struct imsg imsg; 452 struct iface *iface; 453 ssize_t n; 454 int shut = 0; 455 456 if (event & EV_READ) { 457 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 458 fatal("imsg_read error"); 459 if (n == 0) /* Connection closed. */ 460 shut = 1; 461 } 462 if (event & EV_WRITE) { 463 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 464 fatal("msgbuf_write"); 465 if (n == 0) /* Connection closed. */ 466 shut = 1; 467 } 468 469 for (;;) { 470 if ((n = imsg_get(ibuf, &imsg)) == -1) 471 fatal("%s: imsg_get error", __func__); 472 if (n == 0) /* No more messages. */ 473 break; 474 475 switch (imsg.hdr.type) { 476 #ifndef SMALL 477 case IMSG_CTL_END: 478 case IMSG_CTL_SHOW_INTERFACE_INFO: 479 control_imsg_relay(&imsg); 480 break; 481 #endif /* SMALL */ 482 case IMSG_SEND_DISCOVER: { 483 struct imsg_req_discover imsg_req_discover; 484 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_req_discover)) 485 fatalx("%s: IMSG_SEND_DISCOVER wrong " 486 "length: %lu", __func__, 487 IMSG_DATA_SIZE(imsg)); 488 memcpy(&imsg_req_discover, imsg.data, 489 sizeof(imsg_req_discover)); 490 iface = get_iface_by_id(imsg_req_discover.if_index); 491 if (iface != NULL) { 492 iface->xid = imsg_req_discover.xid; 493 send_discover(iface); 494 } 495 break; 496 } 497 case IMSG_SEND_REQUEST: { 498 struct imsg_req_request imsg_req_request; 499 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_req_request)) 500 fatalx("%s: IMSG_SEND_REQUEST wrong " 501 "length: %lu", __func__, 502 IMSG_DATA_SIZE(imsg)); 503 memcpy(&imsg_req_request, imsg.data, 504 sizeof(imsg_req_request)); 505 iface = get_iface_by_id(imsg_req_request.if_index); 506 if (iface != NULL) { 507 iface->xid = imsg_req_request.xid; 508 iface->requested_ip.s_addr = 509 imsg_req_request.requested_ip.s_addr; 510 iface->server_identifier.s_addr = 511 imsg_req_request.server_identifier.s_addr; 512 iface->dhcp_server.s_addr = 513 imsg_req_request.dhcp_server.s_addr; 514 send_request(iface); 515 } 516 break; 517 } 518 default: 519 log_debug("%s: error handling imsg %d", __func__, 520 imsg.hdr.type); 521 break; 522 } 523 imsg_free(&imsg); 524 } 525 if (!shut) 526 imsg_event_add(iev); 527 else { 528 /* This pipe is dead. Remove its event handler. */ 529 event_del(&iev->ev); 530 event_loopexit(NULL); 531 } 532 } 533 534 int 535 get_flags(char *if_name) 536 { 537 struct ifreq ifr; 538 539 strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 540 if (ioctl(ioctlsock, SIOCGIFFLAGS, (caddr_t)&ifr) == -1) { 541 log_warn("SIOCGIFFLAGS"); 542 return -1; 543 } 544 return ifr.ifr_flags; 545 } 546 547 int 548 get_xflags(char *if_name) 549 { 550 struct ifreq ifr; 551 552 strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 553 if (ioctl(ioctlsock, SIOCGIFXFLAGS, (caddr_t)&ifr) == -1) { 554 log_warn("SIOCGIFXFLAGS"); 555 return -1; 556 } 557 return ifr.ifr_flags; 558 } 559 560 void 561 update_iface(struct if_msghdr *ifm, struct sockaddr_dl *sdl) 562 { 563 struct iface *iface; 564 struct imsg_ifinfo ifinfo; 565 uint32_t if_index; 566 int flags, xflags; 567 char ifnamebuf[IF_NAMESIZE], *if_name; 568 569 if_index = ifm->ifm_index; 570 571 flags = ifm->ifm_flags; 572 xflags = ifm->ifm_xflags; 573 574 iface = get_iface_by_id(if_index); 575 if_name = if_indextoname(if_index, ifnamebuf); 576 577 if (if_name == NULL) { 578 if (iface != NULL) { 579 log_debug("interface with idx %d removed", if_index); 580 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 581 &if_index, sizeof(if_index)); 582 remove_iface(if_index); 583 } 584 return; 585 } 586 587 if (!(xflags & IFXF_AUTOCONF4)) { 588 if (iface != NULL) { 589 log_info("Removed autoconf flag from %s", if_name); 590 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 591 &if_index, sizeof(if_index)); 592 remove_iface(if_index); 593 } 594 return; 595 } 596 597 memset(&ifinfo, 0, sizeof(ifinfo)); 598 ifinfo.if_index = if_index; 599 ifinfo.link_state = ifm->ifm_data.ifi_link_state; 600 ifinfo.rdomain = ifm->ifm_tableid; 601 ifinfo.running = (flags & (IFF_UP | IFF_RUNNING)) == 602 (IFF_UP | IFF_RUNNING); 603 604 if (sdl != NULL && (sdl->sdl_type == IFT_ETHER || 605 sdl->sdl_type == IFT_CARP) && sdl->sdl_alen == ETHER_ADDR_LEN) 606 memcpy(ifinfo.hw_address.ether_addr_octet, LLADDR(sdl), 607 ETHER_ADDR_LEN); 608 else if (iface == NULL) { 609 log_warnx("Could not find AF_LINK address for %s.", if_name); 610 return; 611 } 612 613 if (iface == NULL) { 614 if ((iface = calloc(1, sizeof(*iface))) == NULL) 615 fatal("calloc"); 616 iface->udpsock = -1; 617 LIST_INSERT_HEAD(&interfaces, iface, entries); 618 frontend_imsg_compose_main(IMSG_OPEN_BPFSOCK, 0, 619 &if_index, sizeof(if_index)); 620 } else { 621 if (iface->ifinfo.rdomain != ifinfo.rdomain && 622 iface->udpsock != -1) { 623 close(iface->udpsock); 624 iface->udpsock = -1; 625 } 626 } 627 628 if (memcmp(&iface->ifinfo, &ifinfo, sizeof(iface->ifinfo)) != 0) { 629 memcpy(&iface->ifinfo, &ifinfo, sizeof(iface->ifinfo)); 630 frontend_imsg_compose_main(IMSG_UPDATE_IF, 0, &iface->ifinfo, 631 sizeof(iface->ifinfo)); 632 } 633 } 634 635 void 636 frontend_startup(void) 637 { 638 if (!event_initialized(&ev_route)) 639 fatalx("%s: did not receive a route socket from the main " 640 "process", __func__); 641 642 init_ifaces(); 643 if (pledge("stdio unix recvfd", NULL) == -1) 644 fatal("pledge"); 645 event_add(&ev_route, NULL); 646 } 647 648 void 649 init_ifaces(void) 650 { 651 struct iface *iface; 652 struct imsg_ifinfo ifinfo; 653 struct if_nameindex *ifnidxp, *ifnidx; 654 struct ifaddrs *ifap, *ifa; 655 uint32_t if_index; 656 int flags, xflags; 657 char *if_name; 658 659 if ((ifnidxp = if_nameindex()) == NULL) 660 fatalx("if_nameindex"); 661 662 if (getifaddrs(&ifap) != 0) 663 fatal("getifaddrs"); 664 665 for (ifnidx = ifnidxp; ifnidx->if_index != 0 && ifnidx->if_name != NULL; 666 ifnidx++) { 667 if_index = ifnidx->if_index; 668 if_name = ifnidx->if_name; 669 if ((flags = get_flags(if_name)) == -1) 670 continue; 671 if ((xflags = get_xflags(if_name)) == -1) 672 continue; 673 if (!(xflags & IFXF_AUTOCONF4)) 674 continue; 675 676 memset(&ifinfo, 0, sizeof(ifinfo)); 677 ifinfo.if_index = if_index; 678 ifinfo.link_state = -1; 679 ifinfo.running = (flags & (IFF_UP | IFF_RUNNING)) == 680 (IFF_UP | IFF_RUNNING); 681 682 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 683 if (strcmp(if_name, ifa->ifa_name) != 0) 684 continue; 685 if (ifa->ifa_addr == NULL) 686 continue; 687 688 switch (ifa->ifa_addr->sa_family) { 689 case AF_LINK: { 690 struct if_data *if_data; 691 struct sockaddr_dl *sdl; 692 693 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 694 if ((sdl->sdl_type != IFT_ETHER && 695 sdl->sdl_type != IFT_CARP) || 696 sdl->sdl_alen != ETHER_ADDR_LEN) 697 continue; 698 memcpy(ifinfo.hw_address.ether_addr_octet, 699 LLADDR(sdl), ETHER_ADDR_LEN); 700 701 if_data = (struct if_data *)ifa->ifa_data; 702 ifinfo.link_state = if_data->ifi_link_state; 703 ifinfo.rdomain = if_data->ifi_rdomain; 704 goto out; 705 } 706 default: 707 break; 708 } 709 } 710 out: 711 if (ifinfo.link_state == -1) 712 /* no AF_LINK found */ 713 continue; 714 715 if ((iface = calloc(1, sizeof(*iface))) == NULL) 716 fatal("calloc"); 717 iface->udpsock = -1; 718 memcpy(&iface->ifinfo, &ifinfo, sizeof(iface->ifinfo)); 719 LIST_INSERT_HEAD(&interfaces, iface, entries); 720 frontend_imsg_compose_main(IMSG_OPEN_BPFSOCK, 0, 721 &if_index, sizeof(if_index)); 722 frontend_imsg_compose_main(IMSG_UPDATE_IF, 0, &iface->ifinfo, 723 sizeof(iface->ifinfo)); 724 } 725 726 freeifaddrs(ifap); 727 if_freenameindex(ifnidxp); 728 } 729 730 void 731 route_receive(int fd, short events, void *arg) 732 { 733 static uint8_t *buf; 734 735 struct rt_msghdr *rtm; 736 struct sockaddr *sa, *rti_info[RTAX_MAX]; 737 ssize_t n; 738 739 if (buf == NULL) { 740 buf = malloc(ROUTE_SOCKET_BUF_SIZE); 741 if (buf == NULL) 742 fatal("malloc"); 743 } 744 rtm = (struct rt_msghdr *)buf; 745 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) { 746 if (errno == EAGAIN || errno == EINTR) 747 return; 748 log_warn("dispatch_rtmsg: read error"); 749 return; 750 } 751 752 if (n == 0) 753 fatal("routing socket closed"); 754 755 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) { 756 log_warnx("partial rtm of %zd in buffer", n); 757 return; 758 } 759 760 if (rtm->rtm_version != RTM_VERSION) 761 return; 762 763 sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen); 764 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 765 766 handle_route_message(rtm, rti_info); 767 } 768 769 void 770 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) 771 { 772 struct sockaddr_dl *sdl = NULL; 773 struct if_announcemsghdr *ifan; 774 uint32_t if_index; 775 776 switch (rtm->rtm_type) { 777 case RTM_IFINFO: 778 if (rtm->rtm_addrs & RTA_IFP && rti_info[RTAX_IFP]->sa_family 779 == AF_LINK) 780 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; 781 update_iface((struct if_msghdr *)rtm, sdl); 782 break; 783 case RTM_IFANNOUNCE: 784 ifan = (struct if_announcemsghdr *)rtm; 785 if_index = ifan->ifan_index; 786 if (ifan->ifan_what == IFAN_DEPARTURE) { 787 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 788 &if_index, sizeof(if_index)); 789 remove_iface(if_index); 790 } 791 break; 792 case RTM_PROPOSAL: 793 if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) { 794 log_debug("RTP_PROPOSAL_SOLICIT"); 795 frontend_imsg_compose_engine(IMSG_REPROPOSE_RDNS, 796 0, 0, NULL, 0); 797 } 798 #ifndef SMALL 799 else if (rtm->rtm_flags & RTF_PROTO3) { 800 char ifnamebuf[IF_NAMESIZE], *if_name; 801 802 if_index = rtm->rtm_index; 803 if_name = if_indextoname(if_index, ifnamebuf); 804 log_warnx("\"dhclient %s\" ran, requesting new lease", 805 if_name != NULL ? if_name : "(unknown)"); 806 frontend_imsg_compose_engine(IMSG_REQUEST_REBOOT, 807 0, 0, &if_index, sizeof(if_index)); 808 } 809 #endif /* SMALL */ 810 break; 811 default: 812 log_debug("unexpected RTM: %d", rtm->rtm_type); 813 break; 814 } 815 } 816 817 #define ROUNDUP(a) \ 818 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 819 820 void 821 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 822 { 823 int i; 824 825 for (i = 0; i < RTAX_MAX; i++) { 826 if (addrs & (1 << i)) { 827 rti_info[i] = sa; 828 sa = (struct sockaddr *)((char *)(sa) + 829 ROUNDUP(sa->sa_len)); 830 } else 831 rti_info[i] = NULL; 832 } 833 } 834 835 void 836 bpf_receive(int fd, short events, void *arg) 837 { 838 struct bpf_hdr *hdr; 839 struct imsg_dhcp imsg_dhcp; 840 struct iface *iface; 841 ssize_t len, rem; 842 uint8_t *p; 843 844 iface = (struct iface *)arg; 845 846 if ((len = read(fd, iface->bpfev.buf, BPFLEN)) == -1) { 847 log_warn("%s: read", __func__); 848 return; 849 } 850 851 if (len == 0) 852 fatal("%s len == 0", __func__); 853 854 memset(&imsg_dhcp, 0, sizeof(imsg_dhcp)); 855 imsg_dhcp.if_index = iface->ifinfo.if_index; 856 857 rem = len; 858 p = iface->bpfev.buf; 859 860 while (rem > 0) { 861 if ((size_t)rem < sizeof(*hdr)) { 862 log_warnx("packet too short"); 863 return; 864 } 865 hdr = (struct bpf_hdr *)p; 866 if (hdr->bh_caplen != hdr->bh_datalen) { 867 log_warnx("skipping truncated packet"); 868 goto cont; 869 } 870 if (rem < hdr->bh_hdrlen + hdr->bh_caplen) 871 /* we are done */ 872 break; 873 if (hdr->bh_caplen > sizeof(imsg_dhcp.packet)) { 874 log_warn("packet too big"); 875 goto cont; 876 } 877 memcpy(&imsg_dhcp.packet, p + hdr->bh_hdrlen, hdr->bh_caplen); 878 imsg_dhcp.len = hdr->bh_caplen; 879 frontend_imsg_compose_engine(IMSG_DHCP, 0, 0, &imsg_dhcp, 880 sizeof(imsg_dhcp)); 881 cont: 882 p += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); 883 rem -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); 884 885 } 886 } 887 888 ssize_t 889 build_packet(uint8_t message_type, char *if_name, uint32_t xid, 890 struct ether_addr *hw_address, struct in_addr *requested_ip, 891 struct in_addr *server_identifier) 892 { 893 static uint8_t dhcp_cookie[] = DHCP_COOKIE; 894 static uint8_t dhcp_message_type[] = {DHO_DHCP_MESSAGE_TYPE, 1, 895 DHCPDISCOVER}; 896 static uint8_t dhcp_hostname[255] = {DHO_HOST_NAME, 0 /*, ... */}; 897 static uint8_t dhcp_client_id[] = {DHO_DHCP_CLIENT_IDENTIFIER, 7, 898 HTYPE_ETHER, 0, 0, 0, 0, 0, 0}; 899 static uint8_t dhcp_req_list[] = {DHO_DHCP_PARAMETER_REQUEST_LIST, 900 8, DHO_SUBNET_MASK, DHO_ROUTERS, DHO_DOMAIN_NAME_SERVERS, 901 DHO_HOST_NAME, DHO_DOMAIN_NAME, DHO_BROADCAST_ADDRESS, 902 DHO_DOMAIN_SEARCH, DHO_CLASSLESS_STATIC_ROUTES}; 903 static uint8_t dhcp_requested_address[] = {DHO_DHCP_REQUESTED_ADDRESS, 904 4, 0, 0, 0, 0}; 905 static uint8_t dhcp_server_identifier[] = {DHO_DHCP_SERVER_IDENTIFIER, 906 4, 0, 0, 0, 0}; 907 #ifndef SMALL 908 struct iface_conf *iface_conf; 909 #endif /* SMALL */ 910 struct dhcp_hdr *hdr; 911 ssize_t len; 912 uint8_t *p; 913 char *c; 914 915 #ifndef SMALL 916 iface_conf = find_iface_conf(&frontend_conf->iface_list, if_name); 917 #endif /* SMALL */ 918 919 memset(dhcp_packet, 0, sizeof(dhcp_packet)); 920 dhcp_message_type[2] = message_type; 921 p = dhcp_packet; 922 hdr = (struct dhcp_hdr *)p; 923 hdr->op = DHCP_BOOTREQUEST; 924 hdr->htype = HTYPE_ETHER; 925 hdr->hlen = 6; 926 hdr->hops = 0; 927 hdr->xid = xid; 928 hdr->secs = 0; 929 memcpy(hdr->chaddr, hw_address, sizeof(*hw_address)); 930 p += sizeof(struct dhcp_hdr); 931 memcpy(p, dhcp_cookie, sizeof(dhcp_cookie)); 932 p += sizeof(dhcp_cookie); 933 memcpy(p, dhcp_message_type, sizeof(dhcp_message_type)); 934 p += sizeof(dhcp_message_type); 935 if (gethostname(dhcp_hostname + 2, sizeof(dhcp_hostname) - 2) == 0) { 936 if ((c = strchr(dhcp_hostname + 2, '.')) != NULL) 937 *c = '\0'; 938 dhcp_hostname[1] = strlen(dhcp_hostname + 2); 939 memcpy(p, dhcp_hostname, dhcp_hostname[1] + 2); 940 p += dhcp_hostname[1] + 2; 941 } 942 943 #ifndef SMALL 944 if (iface_conf != NULL) { 945 if (iface_conf->c_id_len > 0) { 946 /* XXX check space */ 947 memcpy(p, iface_conf->c_id, iface_conf->c_id_len); 948 p += iface_conf->c_id_len; 949 } 950 if (iface_conf->vc_id_len > 0) { 951 /* XXX check space */ 952 memcpy(p, iface_conf->vc_id, iface_conf->vc_id_len); 953 p += iface_conf->vc_id_len; 954 } 955 } else 956 #endif /* SMALL */ 957 { 958 memcpy(dhcp_client_id + 3, hw_address, sizeof(*hw_address)); 959 memcpy(p, dhcp_client_id, sizeof(dhcp_client_id)); 960 p += sizeof(dhcp_client_id); 961 } 962 memcpy(p, dhcp_req_list, sizeof(dhcp_req_list)); 963 p += sizeof(dhcp_req_list); 964 965 if (message_type == DHCPREQUEST) { 966 memcpy(dhcp_requested_address + 2, requested_ip, 967 sizeof(*requested_ip)); 968 memcpy(p, dhcp_requested_address, 969 sizeof(dhcp_requested_address)); 970 p += sizeof(dhcp_requested_address); 971 972 if (server_identifier->s_addr != INADDR_ANY) { 973 memcpy(dhcp_server_identifier + 2, server_identifier, 974 sizeof(*server_identifier)); 975 memcpy(p, dhcp_server_identifier, 976 sizeof(dhcp_server_identifier)); 977 p += sizeof(dhcp_server_identifier); 978 } 979 } 980 981 *p = DHO_END; 982 p += 1; 983 984 len = p - dhcp_packet; 985 986 /* dhcp_packet is initialized with DHO_PADs */ 987 if (len < BOOTP_MIN_LEN) 988 len = BOOTP_MIN_LEN; 989 990 return (len); 991 } 992 993 void 994 send_discover(struct iface *iface) 995 { 996 ssize_t pkt_len; 997 char ifnamebuf[IF_NAMESIZE], *if_name; 998 999 if (!event_initialized(&iface->bpfev.ev)) { 1000 iface->send_discover = 1; 1001 return; 1002 } 1003 iface->send_discover = 0; 1004 1005 if_name = if_indextoname(iface->ifinfo.if_index, ifnamebuf); 1006 log_debug("DHCPDISCOVER on %s", if_name == NULL ? "?" : if_name); 1007 1008 pkt_len = build_packet(DHCPDISCOVER, if_name, iface->xid, 1009 &iface->ifinfo.hw_address, &iface->requested_ip, NULL); 1010 bpf_send_packet(iface, dhcp_packet, pkt_len); 1011 } 1012 1013 void 1014 send_request(struct iface *iface) 1015 { 1016 ssize_t pkt_len; 1017 char ifnamebuf[IF_NAMESIZE], *if_name; 1018 1019 if_name = if_indextoname(iface->ifinfo.if_index, ifnamebuf); 1020 log_debug("DHCPREQUEST on %s", if_name == NULL ? "?" : if_name); 1021 1022 pkt_len = build_packet(DHCPREQUEST, if_name, iface->xid, 1023 &iface->ifinfo.hw_address, &iface->requested_ip, 1024 &iface->server_identifier); 1025 if (iface->dhcp_server.s_addr != INADDR_ANY) { 1026 if (udp_send_packet(iface, dhcp_packet, pkt_len) == -1) 1027 bpf_send_packet(iface, dhcp_packet, pkt_len); 1028 } else 1029 bpf_send_packet(iface, dhcp_packet, pkt_len); 1030 } 1031 1032 int 1033 udp_send_packet(struct iface *iface, uint8_t *packet, ssize_t len) 1034 { 1035 struct sockaddr_in to; 1036 1037 memset(&to, 0, sizeof(to)); 1038 to.sin_family = AF_INET; 1039 to.sin_len = sizeof(to); 1040 to.sin_addr.s_addr = iface->dhcp_server.s_addr; 1041 to.sin_port = ntohs(SERVER_PORT); 1042 1043 if (sendto(iface->udpsock, packet, len, 0, (struct sockaddr *)&to, 1044 sizeof(to)) == -1) { 1045 log_warn("sendto"); 1046 return -1; 1047 } 1048 return 0; 1049 } 1050 void 1051 bpf_send_packet(struct iface *iface, uint8_t *packet, ssize_t len) 1052 { 1053 struct iovec iov[4]; 1054 struct ether_header eh; 1055 struct ip ip; 1056 struct udphdr udp; 1057 ssize_t total, result; 1058 int iovcnt = 0, i; 1059 1060 memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost)); 1061 memcpy(eh.ether_shost, &iface->ifinfo.hw_address, 1062 sizeof(eh.ether_dhost)); 1063 eh.ether_type = htons(ETHERTYPE_IP); 1064 iov[0].iov_base = &eh; 1065 iov[0].iov_len = sizeof(eh); 1066 iovcnt++; 1067 1068 ip.ip_v = 4; 1069 ip.ip_hl = 5; 1070 ip.ip_tos = IPTOS_LOWDELAY; 1071 ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len); 1072 ip.ip_id = 0; 1073 ip.ip_off = 0; 1074 ip.ip_ttl = 128; 1075 ip.ip_p = IPPROTO_UDP; 1076 ip.ip_sum = 0; 1077 ip.ip_src.s_addr = 0; 1078 ip.ip_dst.s_addr = INADDR_BROADCAST; 1079 ip.ip_sum = wrapsum(checksum((unsigned char *)&ip, sizeof(ip), 0)); 1080 iov[iovcnt].iov_base = &ip; 1081 iov[iovcnt].iov_len = sizeof(ip); 1082 iovcnt++; 1083 1084 udp.uh_sport = htons(CLIENT_PORT); 1085 udp.uh_dport = htons(SERVER_PORT); 1086 udp.uh_ulen = htons(sizeof(udp) + len); 1087 udp.uh_sum = 0; 1088 udp.uh_sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp), 1089 checksum((unsigned char *)packet, len, 1090 checksum((unsigned char *)&ip.ip_src, 1091 2 * sizeof(ip.ip_src), 1092 IPPROTO_UDP + (uint32_t)ntohs(udp.uh_ulen))))); 1093 iov[iovcnt].iov_base = &udp; 1094 iov[iovcnt].iov_len = sizeof(udp); 1095 iovcnt++; 1096 1097 iov[iovcnt].iov_base = packet; 1098 iov[iovcnt].iov_len = len; 1099 iovcnt++; 1100 1101 total = 0; 1102 for (i = 0; i < iovcnt; i++) 1103 total += iov[i].iov_len; 1104 1105 result = writev(EVENT_FD(&iface->bpfev.ev), iov, iovcnt); 1106 if (result == -1) 1107 log_warn("%s: writev", __func__); 1108 else if (result < total) { 1109 log_warnx("%s, writev: %zd of %zd bytes", __func__, result, 1110 total); 1111 } 1112 } 1113 1114 struct iface* 1115 get_iface_by_id(uint32_t if_index) 1116 { 1117 struct iface *iface; 1118 1119 LIST_FOREACH (iface, &interfaces, entries) { 1120 if (iface->ifinfo.if_index == if_index) 1121 return (iface); 1122 } 1123 1124 return (NULL); 1125 } 1126 1127 void 1128 remove_iface(uint32_t if_index) 1129 { 1130 struct iface *iface; 1131 1132 iface = get_iface_by_id(if_index); 1133 1134 if (iface == NULL) 1135 return; 1136 1137 LIST_REMOVE(iface, entries); 1138 event_del(&iface->bpfev.ev); 1139 close(EVENT_FD(&iface->bpfev.ev)); 1140 if (iface->udpsock != -1) 1141 close(iface->udpsock); 1142 free(iface); 1143 } 1144 1145 void 1146 set_bpfsock(int bpfsock, uint32_t if_index) 1147 { 1148 struct iface *iface; 1149 1150 if ((iface = get_iface_by_id(if_index)) == NULL) { 1151 /* 1152 * The interface disappeared while we were waiting for the 1153 * parent process to open the raw socket. 1154 */ 1155 close(bpfsock); 1156 } else { 1157 event_set(&iface->bpfev.ev, bpfsock, EV_READ | 1158 EV_PERSIST, bpf_receive, iface); 1159 event_add(&iface->bpfev.ev, NULL); 1160 if (iface->send_discover) 1161 send_discover(iface); 1162 } 1163 } 1164 1165 #ifndef SMALL 1166 struct iface_conf* 1167 find_iface_conf(struct iface_conf_head *head, char *if_name) 1168 { 1169 struct iface_conf *iface_conf; 1170 1171 if (if_name == NULL) 1172 return (NULL); 1173 1174 SIMPLEQ_FOREACH(iface_conf, head, entry) { 1175 if (strcmp(iface_conf->name, if_name) == 0) 1176 return iface_conf; 1177 } 1178 return (NULL); 1179 } 1180 1181 int* 1182 changed_ifaces(struct dhcpleased_conf *oconf, struct dhcpleased_conf *nconf) 1183 { 1184 struct iface_conf *iface_conf, *oiface_conf; 1185 int *ret, if_index, count = 0, i = 0; 1186 1187 /* 1188 * Worst case: All old interfaces replaced with new interfaces. 1189 * This should still be a small number 1190 */ 1191 SIMPLEQ_FOREACH(iface_conf, &oconf->iface_list, entry) 1192 count++; 1193 SIMPLEQ_FOREACH(iface_conf, &nconf->iface_list, entry) 1194 count++; 1195 1196 ret = calloc(count + 1, sizeof(int)); 1197 1198 SIMPLEQ_FOREACH(iface_conf, &nconf->iface_list, entry) { 1199 if ((if_index = if_nametoindex(iface_conf->name)) == 0) 1200 continue; 1201 oiface_conf = find_iface_conf(&oconf->iface_list, 1202 iface_conf->name); 1203 if (oiface_conf == NULL) { 1204 /* new interface added to config */ 1205 ret[i++] = if_index; 1206 } else if (iface_conf_cmp(iface_conf, oiface_conf) != 0) { 1207 /* interface conf changed */ 1208 ret[i++] = if_index; 1209 } 1210 } 1211 SIMPLEQ_FOREACH(oiface_conf, &oconf->iface_list, entry) { 1212 if ((if_index = if_nametoindex(oiface_conf->name)) == 0) 1213 continue; 1214 if (find_iface_conf(&nconf->iface_list, oiface_conf->name) == 1215 NULL) { 1216 /* interface removed from config */ 1217 ret[i++] = if_index; 1218 } 1219 } 1220 return ret; 1221 } 1222 1223 int 1224 iface_conf_cmp(struct iface_conf *a, struct iface_conf *b) 1225 { 1226 if (a->vc_id_len != b->vc_id_len) 1227 return 1; 1228 if (memcmp(a->vc_id, b->vc_id, a->vc_id_len) != 0) 1229 return 1; 1230 if (a->c_id_len != b->c_id_len) 1231 return 1; 1232 if (memcmp(a->c_id, b->c_id, a->c_id_len) != 0) 1233 return 1; 1234 if (a->ignore != b->ignore) 1235 return 1; 1236 if (a->ignore_servers_len != b->ignore_servers_len) 1237 return 1; 1238 if (memcmp(a->ignore_servers, b->ignore_servers, 1239 a->ignore_servers_len * sizeof (struct in_addr)) != 0) 1240 return 1; 1241 return 0; 1242 } 1243 #endif /* SMALL */ 1244