1 /* $OpenBSD: engine.c,v 1.14 2021/05/01 11:51:59 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2017, 2021 Florian Obser <florian@openbsd.org> 5 * Copyright (c) 2004, 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 <net/if.h> 29 #include <net/route.h> 30 #include <arpa/inet.h> 31 #include <netinet/in.h> 32 #include <netinet/if_ether.h> 33 #include <netinet/ip.h> 34 #include <netinet/udp.h> 35 36 #include <errno.h> 37 #include <event.h> 38 #include <imsg.h> 39 #include <pwd.h> 40 #include <signal.h> 41 #include <stddef.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <time.h> 46 #include <unistd.h> 47 #include <vis.h> 48 49 #include "checksum.h" 50 #include "log.h" 51 #include "dhcpleased.h" 52 #include "engine.h" 53 54 /* 55 * RFC 2131 4.1 p23 has "SHOULD be 4 seconds", we are a bit more aggressive, 56 * networks are faster these days. 57 */ 58 #define START_EXP_BACKOFF 1 59 #define MAX_EXP_BACKOFF_SLOW 64 /* RFC 2131 4.1 p23 */ 60 #define MAX_EXP_BACKOFF_FAST 2 61 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 62 63 enum if_state { 64 IF_DOWN, 65 IF_INIT, 66 /* IF_SELECTING, */ 67 IF_REQUESTING, 68 IF_BOUND, 69 IF_RENEWING, 70 IF_REBINDING, 71 /* IF_INIT_REBOOT, */ 72 IF_REBOOTING, 73 }; 74 75 const char* if_state_name[] = { 76 "Down", 77 "Init", 78 /* "Selecting", */ 79 "Requesting", 80 "Bound", 81 "Renewing", 82 "Rebinding", 83 /* "Init-Reboot", */ 84 "Rebooting", 85 }; 86 87 struct dhcpleased_iface { 88 LIST_ENTRY(dhcpleased_iface) entries; 89 enum if_state state; 90 struct event timer; 91 struct timeval timo; 92 uint32_t if_index; 93 int rdomain; 94 int running; 95 struct ether_addr hw_address; 96 int link_state; 97 uint32_t cur_mtu; 98 uint32_t xid; 99 struct timespec request_time; 100 struct in_addr server_identifier; 101 struct in_addr dhcp_server; /* for unicast */ 102 struct in_addr requested_ip; 103 struct in_addr mask; 104 struct in_addr router; 105 struct in_addr nameservers[MAX_RDNS_COUNT]; 106 uint32_t lease_time; 107 uint32_t renewal_time; 108 uint32_t rebinding_time; 109 }; 110 111 LIST_HEAD(, dhcpleased_iface) dhcpleased_interfaces; 112 113 __dead void engine_shutdown(void); 114 void engine_sig_handler(int sig, short, void *); 115 void engine_dispatch_frontend(int, short, void *); 116 void engine_dispatch_main(int, short, void *); 117 #ifndef SMALL 118 void send_interface_info(struct dhcpleased_iface *, pid_t); 119 void engine_showinfo_ctl(struct imsg *, uint32_t); 120 #endif /* SMALL */ 121 void engine_update_iface(struct imsg_ifinfo *); 122 struct dhcpleased_iface *get_dhcpleased_iface_by_id(uint32_t); 123 void remove_dhcpleased_iface(uint32_t); 124 void parse_dhcp(struct dhcpleased_iface *, 125 struct imsg_dhcp *); 126 void state_transition(struct dhcpleased_iface *, enum 127 if_state); 128 void iface_timeout(int, short, void *); 129 void request_dhcp_discover(struct dhcpleased_iface *); 130 void request_dhcp_request(struct dhcpleased_iface *); 131 void log_lease(struct dhcpleased_iface *, int); 132 void log_rdns(struct dhcpleased_iface *, int); 133 void send_configure_interface(struct dhcpleased_iface *); 134 void send_rdns_proposal(struct dhcpleased_iface *); 135 void send_deconfigure_interface(struct dhcpleased_iface *); 136 void send_rdns_withdraw(struct dhcpleased_iface *); 137 void parse_lease(struct dhcpleased_iface *, 138 struct imsg_ifinfo *); 139 int engine_imsg_compose_main(int, pid_t, void *, uint16_t); 140 void log_dhcp_hdr(struct dhcp_hdr *); 141 const char *dhcp_message_type2str(uint8_t); 142 143 static struct imsgev *iev_frontend; 144 static struct imsgev *iev_main; 145 int64_t proposal_id; 146 147 void 148 engine_sig_handler(int sig, short event, void *arg) 149 { 150 /* 151 * Normal signal handler rules don't apply because libevent 152 * decouples for us. 153 */ 154 155 switch (sig) { 156 case SIGINT: 157 case SIGTERM: 158 engine_shutdown(); 159 default: 160 fatalx("unexpected signal"); 161 } 162 } 163 164 void 165 engine(int debug, int verbose) 166 { 167 struct event ev_sigint, ev_sigterm; 168 struct passwd *pw; 169 170 log_init(debug, LOG_DAEMON); 171 log_setverbose(verbose); 172 173 if ((pw = getpwnam(DHCPLEASED_USER)) == NULL) 174 fatal("getpwnam"); 175 176 if (chdir("/") == -1) 177 fatal("chdir(\"/\")"); 178 179 if (unveil("/", "") == -1) 180 fatal("unveil(\"/\", \"\")"); 181 if (unveil(NULL, NULL) == -1) 182 fatal("unveil(NULL, NULL)"); 183 184 setproctitle("%s", "engine"); 185 log_procinit("engine"); 186 187 if (setgroups(1, &pw->pw_gid) || 188 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 189 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 190 fatal("can't drop privileges"); 191 192 if (pledge("stdio recvfd", NULL) == -1) 193 fatal("pledge"); 194 195 event_init(); 196 197 /* Setup signal handler(s). */ 198 signal_set(&ev_sigint, SIGINT, engine_sig_handler, NULL); 199 signal_set(&ev_sigterm, SIGTERM, engine_sig_handler, NULL); 200 signal_add(&ev_sigint, NULL); 201 signal_add(&ev_sigterm, NULL); 202 signal(SIGPIPE, SIG_IGN); 203 signal(SIGHUP, SIG_IGN); 204 205 /* Setup pipe and event handler to the main process. */ 206 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 207 fatal(NULL); 208 209 imsg_init(&iev_main->ibuf, 3); 210 iev_main->handler = engine_dispatch_main; 211 212 /* Setup event handlers. */ 213 iev_main->events = EV_READ; 214 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 215 iev_main->handler, iev_main); 216 event_add(&iev_main->ev, NULL); 217 218 LIST_INIT(&dhcpleased_interfaces); 219 220 event_dispatch(); 221 222 engine_shutdown(); 223 } 224 225 __dead void 226 engine_shutdown(void) 227 { 228 /* Close pipes. */ 229 msgbuf_clear(&iev_frontend->ibuf.w); 230 close(iev_frontend->ibuf.fd); 231 msgbuf_clear(&iev_main->ibuf.w); 232 close(iev_main->ibuf.fd); 233 234 free(iev_frontend); 235 free(iev_main); 236 237 log_info("engine exiting"); 238 exit(0); 239 } 240 241 int 242 engine_imsg_compose_frontend(int type, pid_t pid, void *data, 243 uint16_t datalen) 244 { 245 return (imsg_compose_event(iev_frontend, type, 0, pid, -1, 246 data, datalen)); 247 } 248 249 int 250 engine_imsg_compose_main(int type, pid_t pid, void *data, 251 uint16_t datalen) 252 { 253 return (imsg_compose_event(iev_main, type, 0, pid, -1, 254 data, datalen)); 255 } 256 257 void 258 engine_dispatch_frontend(int fd, short event, void *bula) 259 { 260 struct imsgev *iev = bula; 261 struct imsgbuf *ibuf = &iev->ibuf; 262 struct imsg imsg; 263 struct dhcpleased_iface *iface; 264 ssize_t n; 265 int shut = 0; 266 #ifndef SMALL 267 int verbose; 268 #endif /* SMALL */ 269 uint32_t if_index; 270 271 if (event & EV_READ) { 272 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 273 fatal("imsg_read error"); 274 if (n == 0) /* Connection closed. */ 275 shut = 1; 276 } 277 if (event & EV_WRITE) { 278 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 279 fatal("msgbuf_write"); 280 if (n == 0) /* Connection closed. */ 281 shut = 1; 282 } 283 284 for (;;) { 285 if ((n = imsg_get(ibuf, &imsg)) == -1) 286 fatal("%s: imsg_get error", __func__); 287 if (n == 0) /* No more messages. */ 288 break; 289 290 switch (imsg.hdr.type) { 291 #ifndef SMALL 292 case IMSG_CTL_LOG_VERBOSE: 293 if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 294 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 295 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 296 memcpy(&verbose, imsg.data, sizeof(verbose)); 297 log_setverbose(verbose); 298 break; 299 case IMSG_CTL_SHOW_INTERFACE_INFO: 300 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 301 fatalx("%s: IMSG_CTL_SHOW_INTERFACE_INFO wrong " 302 "length: %lu", __func__, 303 IMSG_DATA_SIZE(imsg)); 304 memcpy(&if_index, imsg.data, sizeof(if_index)); 305 engine_showinfo_ctl(&imsg, if_index); 306 break; 307 case IMSG_CTL_SEND_REQUEST: 308 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 309 fatalx("%s: IMSG_CTL_SEND_DISCOVER wrong " 310 "length: %lu", __func__, 311 IMSG_DATA_SIZE(imsg)); 312 memcpy(&if_index, imsg.data, sizeof(if_index)); 313 iface = get_dhcpleased_iface_by_id(if_index); 314 if (iface != NULL) { 315 switch (iface->state) { 316 case IF_DOWN: 317 break; 318 case IF_INIT: 319 case IF_REQUESTING: 320 case IF_RENEWING: 321 case IF_REBINDING: 322 case IF_REBOOTING: 323 state_transition(iface, iface->state); 324 break; 325 case IF_BOUND: 326 state_transition(iface, IF_RENEWING); 327 break; 328 } 329 } 330 break; 331 #endif /* SMALL */ 332 case IMSG_REMOVE_IF: 333 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 334 fatalx("%s: IMSG_REMOVE_IF wrong length: %lu", 335 __func__, IMSG_DATA_SIZE(imsg)); 336 memcpy(&if_index, imsg.data, sizeof(if_index)); 337 remove_dhcpleased_iface(if_index); 338 break; 339 case IMSG_DHCP: { 340 struct imsg_dhcp imsg_dhcp; 341 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_dhcp)) 342 fatalx("%s: IMSG_DHCP wrong length: %lu", 343 __func__, IMSG_DATA_SIZE(imsg)); 344 memcpy(&imsg_dhcp, imsg.data, sizeof(imsg_dhcp)); 345 iface = get_dhcpleased_iface_by_id(imsg_dhcp.if_index); 346 if (iface != NULL) 347 parse_dhcp(iface, &imsg_dhcp); 348 break; 349 } 350 case IMSG_REPROPOSE_RDNS: 351 LIST_FOREACH (iface, &dhcpleased_interfaces, entries) 352 send_rdns_proposal(iface); 353 break; 354 default: 355 log_debug("%s: unexpected imsg %d", __func__, 356 imsg.hdr.type); 357 break; 358 } 359 imsg_free(&imsg); 360 } 361 if (!shut) 362 imsg_event_add(iev); 363 else { 364 /* This pipe is dead. Remove its event handler. */ 365 event_del(&iev->ev); 366 event_loopexit(NULL); 367 } 368 } 369 370 void 371 engine_dispatch_main(int fd, short event, void *bula) 372 { 373 struct imsg imsg; 374 struct imsgev *iev = bula; 375 struct imsgbuf *ibuf = &iev->ibuf; 376 struct imsg_ifinfo imsg_ifinfo; 377 ssize_t n; 378 int shut = 0; 379 380 if (event & EV_READ) { 381 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 382 fatal("imsg_read error"); 383 if (n == 0) /* Connection closed. */ 384 shut = 1; 385 } 386 if (event & EV_WRITE) { 387 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 388 fatal("msgbuf_write"); 389 if (n == 0) /* Connection closed. */ 390 shut = 1; 391 } 392 393 for (;;) { 394 if ((n = imsg_get(ibuf, &imsg)) == -1) 395 fatal("%s: imsg_get error", __func__); 396 if (n == 0) /* No more messages. */ 397 break; 398 399 switch (imsg.hdr.type) { 400 case IMSG_SOCKET_IPC: 401 /* 402 * Setup pipe and event handler to the frontend 403 * process. 404 */ 405 if (iev_frontend) 406 fatalx("%s: received unexpected imsg fd " 407 "to engine", __func__); 408 409 if ((fd = imsg.fd) == -1) 410 fatalx("%s: expected to receive imsg fd to " 411 "engine but didn't receive any", __func__); 412 413 iev_frontend = malloc(sizeof(struct imsgev)); 414 if (iev_frontend == NULL) 415 fatal(NULL); 416 417 imsg_init(&iev_frontend->ibuf, fd); 418 iev_frontend->handler = engine_dispatch_frontend; 419 iev_frontend->events = EV_READ; 420 421 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 422 iev_frontend->events, iev_frontend->handler, 423 iev_frontend); 424 event_add(&iev_frontend->ev, NULL); 425 426 if (pledge("stdio", NULL) == -1) 427 fatal("pledge"); 428 429 break; 430 case IMSG_UPDATE_IF: 431 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_ifinfo)) 432 fatalx("%s: IMSG_UPDATE_IF wrong length: %lu", 433 __func__, IMSG_DATA_SIZE(imsg)); 434 memcpy(&imsg_ifinfo, imsg.data, sizeof(imsg_ifinfo)); 435 engine_update_iface(&imsg_ifinfo); 436 break; 437 default: 438 log_debug("%s: unexpected imsg %d", __func__, 439 imsg.hdr.type); 440 break; 441 } 442 imsg_free(&imsg); 443 } 444 if (!shut) 445 imsg_event_add(iev); 446 else { 447 /* This pipe is dead. Remove its event handler. */ 448 event_del(&iev->ev); 449 event_loopexit(NULL); 450 } 451 } 452 453 #ifndef SMALL 454 void 455 send_interface_info(struct dhcpleased_iface *iface, pid_t pid) 456 { 457 struct ctl_engine_info cei; 458 459 memset(&cei, 0, sizeof(cei)); 460 cei.if_index = iface->if_index; 461 cei.running = iface->running; 462 cei.link_state = iface->link_state; 463 strlcpy(cei.state, if_state_name[iface->state], sizeof(cei.state)); 464 memcpy(&cei.request_time, &iface->request_time, 465 sizeof(cei.request_time)); 466 cei.server_identifier.s_addr = iface->server_identifier.s_addr; 467 cei.dhcp_server.s_addr = iface->dhcp_server.s_addr; 468 cei.requested_ip.s_addr = iface->requested_ip.s_addr; 469 cei.mask.s_addr = iface->mask.s_addr; 470 cei.router.s_addr = iface->router.s_addr; 471 memcpy(cei.nameservers, iface->nameservers, sizeof(cei.nameservers)); 472 cei.lease_time = iface->lease_time; 473 cei.renewal_time = iface->renewal_time; 474 cei.rebinding_time = iface->rebinding_time; 475 engine_imsg_compose_frontend(IMSG_CTL_SHOW_INTERFACE_INFO, pid, &cei, 476 sizeof(cei)); 477 } 478 479 void 480 engine_showinfo_ctl(struct imsg *imsg, uint32_t if_index) 481 { 482 struct dhcpleased_iface *iface; 483 484 switch (imsg->hdr.type) { 485 case IMSG_CTL_SHOW_INTERFACE_INFO: 486 if (if_index == 0) { 487 LIST_FOREACH (iface, &dhcpleased_interfaces, entries) 488 send_interface_info(iface, imsg->hdr.pid); 489 } else { 490 if ((iface = get_dhcpleased_iface_by_id(if_index)) != 491 NULL) 492 send_interface_info(iface, imsg->hdr.pid); 493 } 494 engine_imsg_compose_frontend(IMSG_CTL_END, imsg->hdr.pid, NULL, 495 0); 496 break; 497 default: 498 log_debug("%s: error handling imsg", __func__); 499 break; 500 } 501 } 502 #endif /* SMALL */ 503 504 void 505 engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) 506 { 507 struct dhcpleased_iface *iface; 508 int need_refresh = 0; 509 510 iface = get_dhcpleased_iface_by_id(imsg_ifinfo->if_index); 511 512 if (iface == NULL) { 513 if ((iface = calloc(1, sizeof(*iface))) == NULL) 514 fatal("calloc"); 515 iface->state = IF_DOWN; 516 iface->timo.tv_usec = arc4random_uniform(1000000); 517 evtimer_set(&iface->timer, iface_timeout, iface); 518 iface->if_index = imsg_ifinfo->if_index; 519 iface->rdomain = imsg_ifinfo->rdomain; 520 iface->running = imsg_ifinfo->running; 521 iface->link_state = imsg_ifinfo->link_state; 522 iface->requested_ip.s_addr = INADDR_ANY; 523 memcpy(&iface->hw_address, &imsg_ifinfo->hw_address, 524 sizeof(struct ether_addr)); 525 LIST_INSERT_HEAD(&dhcpleased_interfaces, iface, entries); 526 need_refresh = 1; 527 } else { 528 if (memcmp(&iface->hw_address, &imsg_ifinfo->hw_address, 529 sizeof(struct ether_addr)) != 0) { 530 memcpy(&iface->hw_address, &imsg_ifinfo->hw_address, 531 sizeof(struct ether_addr)); 532 need_refresh = 1; 533 } 534 if (imsg_ifinfo->rdomain != iface->rdomain) { 535 iface->rdomain = imsg_ifinfo->rdomain; 536 need_refresh = 1; 537 } 538 if (imsg_ifinfo->running != iface->running) { 539 iface->running = imsg_ifinfo->running; 540 need_refresh = 1; 541 } 542 543 if (imsg_ifinfo->link_state != iface->link_state) { 544 iface->link_state = imsg_ifinfo->link_state; 545 need_refresh = 1; 546 } 547 } 548 549 if (!need_refresh) 550 return; 551 552 if (iface->running && LINK_STATE_IS_UP(iface->link_state)) { 553 if (iface->requested_ip.s_addr == INADDR_ANY) 554 parse_lease(iface, imsg_ifinfo); 555 556 if (iface->requested_ip.s_addr == INADDR_ANY) 557 state_transition(iface, IF_INIT); 558 else 559 state_transition(iface, IF_REBOOTING); 560 } else 561 state_transition(iface, IF_DOWN); 562 } 563 struct dhcpleased_iface* 564 get_dhcpleased_iface_by_id(uint32_t if_index) 565 { 566 struct dhcpleased_iface *iface; 567 LIST_FOREACH (iface, &dhcpleased_interfaces, entries) { 568 if (iface->if_index == if_index) 569 return (iface); 570 } 571 572 return (NULL); 573 } 574 575 void 576 remove_dhcpleased_iface(uint32_t if_index) 577 { 578 struct dhcpleased_iface *iface; 579 580 iface = get_dhcpleased_iface_by_id(if_index); 581 582 if (iface == NULL) 583 return; 584 585 send_rdns_withdraw(iface); 586 send_deconfigure_interface(iface); 587 LIST_REMOVE(iface, entries); 588 evtimer_del(&iface->timer); 589 free(iface); 590 } 591 592 void 593 parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp *dhcp) 594 { 595 static uint8_t cookie[] = DHCP_COOKIE; 596 static struct ether_addr bcast_mac; 597 struct ether_header *eh; 598 struct ether_addr ether_src, ether_dst; 599 struct ip *ip; 600 struct udphdr *udp; 601 struct dhcp_hdr *dhcp_hdr; 602 struct in_addr server_identifier, subnet_mask, router; 603 struct in_addr nameservers[MAX_RDNS_COUNT]; 604 size_t rem, i; 605 uint32_t sum, usum, lease_time = 0, renewal_time = 0; 606 uint32_t rebinding_time = 0; 607 uint8_t *p, dho = DHO_PAD, dho_len; 608 uint8_t dhcp_message_type = 0; 609 char from[sizeof("xx:xx:xx:xx:xx:xx")]; 610 char to[sizeof("xx:xx:xx:xx:xx:xx")]; 611 char hbuf_src[INET_ADDRSTRLEN]; 612 char hbuf_dst[INET_ADDRSTRLEN]; 613 char hbuf[INET_ADDRSTRLEN]; 614 char vis_buf[4 * 255 + 1]; 615 char ifnamebuf[IF_NAMESIZE], *if_name; 616 617 if (bcast_mac.ether_addr_octet[0] == 0) 618 memset(bcast_mac.ether_addr_octet, 0xff, ETHER_ADDR_LEN); 619 620 memset(hbuf_src, 0, sizeof(hbuf_src)); 621 memset(hbuf_dst, 0, sizeof(hbuf_dst)); 622 623 p = dhcp->packet; 624 rem = dhcp->len; 625 626 if (rem < sizeof(*eh)) { 627 log_warnx("%s: message too short", __func__); 628 return; 629 } 630 eh = (struct ether_header *)p; 631 memcpy(ether_src.ether_addr_octet, eh->ether_shost, 632 sizeof(ether_src.ether_addr_octet)); 633 strlcpy(from, ether_ntoa(ðer_src), sizeof(from)); 634 memcpy(ether_dst.ether_addr_octet, eh->ether_dhost, 635 sizeof(ether_dst.ether_addr_octet)); 636 strlcpy(to, ether_ntoa(ðer_dst), sizeof(to)); 637 p += sizeof(*eh); 638 rem -= sizeof(*eh); 639 640 if (memcmp(ðer_dst, &iface->hw_address, sizeof(ether_dst)) != 0 && 641 memcmp(ðer_dst, &bcast_mac, sizeof(ether_dst)) != 0) 642 return ; /* silently ignore packet not for us */ 643 644 if (rem < sizeof(*ip)) 645 goto too_short; 646 647 if (log_getverbose() > 1) 648 log_debug("%s, from: %s, to: %s", __func__, from, to); 649 650 ip = (struct ip *)p; 651 652 if (rem < (size_t)ip->ip_hl << 2) 653 goto too_short; 654 655 if (wrapsum(checksum((uint8_t *)ip, ip->ip_hl << 2, 0)) != 0) { 656 log_warnx("%s: bad IP checksum", __func__); 657 return; 658 } 659 if (rem < ntohs(ip->ip_len)) 660 goto too_short; 661 662 p += ip->ip_hl << 2; 663 rem -= ip->ip_hl << 2; 664 665 if (inet_ntop(AF_INET, &ip->ip_src, hbuf_src, sizeof(hbuf_src)) == NULL) 666 hbuf_src[0] = '\0'; 667 if (inet_ntop(AF_INET, &ip->ip_dst, hbuf_dst, sizeof(hbuf_dst)) == NULL) 668 hbuf_dst[0] = '\0'; 669 670 if (rem < sizeof(*udp)) 671 goto too_short; 672 673 udp = (struct udphdr *)p; 674 if (rem < ntohs(udp->uh_ulen)) 675 goto too_short; 676 677 if (rem > ntohs(udp->uh_ulen)) { 678 if (log_getverbose() > 1) { 679 log_debug("%s: accepting packet with %lu bytes of data" 680 " after udp payload", __func__, rem - 681 ntohs(udp->uh_ulen)); 682 } 683 rem = ntohs(udp->uh_ulen); 684 } 685 686 p += sizeof(*udp); 687 rem -= sizeof(*udp); 688 689 usum = udp->uh_sum; 690 udp->uh_sum = 0; 691 692 sum = wrapsum(checksum((uint8_t *)udp, sizeof(*udp), checksum(p, rem, 693 checksum((uint8_t *)&ip->ip_src, 2 * sizeof(ip->ip_src), 694 IPPROTO_UDP + ntohs(udp->uh_ulen))))); 695 696 if (usum != 0 && usum != sum) { 697 log_warnx("%s: bad UDP checksum", __func__); 698 return; 699 } 700 701 if (log_getverbose() > 1) { 702 log_debug("%s: %s:%d -> %s:%d", __func__, hbuf_src, 703 ntohs(udp->uh_sport), hbuf_dst, ntohs(udp->uh_dport)); 704 } 705 706 if (ntohs(udp->uh_sport) != SERVER_PORT || 707 ntohs(udp->uh_dport) != CLIENT_PORT) { 708 log_warnx("%s: invalid ports used %s:%d -> %s:%d", __func__, 709 hbuf_src, ntohs(udp->uh_sport), 710 hbuf_dst, ntohs(udp->uh_dport)); 711 return; 712 } 713 if (rem < sizeof(*dhcp_hdr)) 714 goto too_short; 715 716 dhcp_hdr = (struct dhcp_hdr *)p; 717 p += sizeof(*dhcp_hdr); 718 rem -= sizeof(*dhcp_hdr); 719 720 dhcp_hdr->sname[DHCP_SNAME_LEN -1 ] = '\0'; /* ensure it's a string */ 721 dhcp_hdr->file[DHCP_FILE_LEN -1 ] = '\0'; /* ensure it's a string */ 722 723 if (log_getverbose() > 1) 724 log_dhcp_hdr(dhcp_hdr); 725 726 if (dhcp_hdr->op != DHCP_BOOTREPLY) { 727 log_warnx("%s: ignorning non-reply packet", __func__); 728 return; 729 } 730 731 if (dhcp_hdr->xid != iface->xid) 732 return; /* silently ignore wrong xid */ 733 734 if (rem < sizeof(cookie)) 735 goto too_short; 736 737 if (memcmp(p, cookie, sizeof(cookie)) != 0) { 738 log_warnx("%s: no dhcp cookie in packet from %s", __func__, 739 from); 740 return; 741 } 742 p += sizeof(cookie); 743 rem -= sizeof(cookie); 744 745 memset(&server_identifier, 0, sizeof(server_identifier)); 746 memset(&subnet_mask, 0, sizeof(subnet_mask)); 747 memset(&router, 0, sizeof(router)); 748 memset(&nameservers, 0, sizeof(nameservers)); 749 750 while (rem > 0 && dho != DHO_END) { 751 dho = *p; 752 p += 1; 753 rem -= 1; 754 /* only DHO_END and DHO_PAD are 1 byte long without length */ 755 if (dho == DHO_PAD || dho == DHO_END) 756 dho_len = 0; 757 else { 758 if (rem == 0) 759 goto too_short; /* missing option length */ 760 dho_len = *p; 761 p += 1; 762 rem -= 1; 763 if (rem < dho_len) 764 goto too_short; 765 } 766 767 switch (dho) { 768 case DHO_PAD: 769 if (log_getverbose() > 1) 770 log_debug("DHO_PAD"); 771 break; 772 case DHO_END: 773 if (log_getverbose() > 1) 774 log_debug("DHO_END"); 775 break; 776 case DHO_DHCP_MESSAGE_TYPE: 777 if (dho_len != 1) 778 goto wrong_length; 779 dhcp_message_type = *p; 780 if (log_getverbose() > 1) { 781 log_debug("DHO_DHCP_MESSAGE_TYPE: %s", 782 dhcp_message_type2str(dhcp_message_type)); 783 } 784 p += dho_len; 785 rem -= dho_len; 786 break; 787 case DHO_DHCP_SERVER_IDENTIFIER: 788 if (dho_len != sizeof(server_identifier)) 789 goto wrong_length; 790 memcpy(&server_identifier, p, 791 sizeof(server_identifier)); 792 if (log_getverbose() > 1) { 793 log_debug("DHO_DHCP_SERVER_IDENTIFIER: %s", 794 inet_ntop(AF_INET, &server_identifier, 795 hbuf, sizeof(hbuf))); 796 } 797 p += dho_len; 798 rem -= dho_len; 799 break; 800 case DHO_DHCP_LEASE_TIME: 801 if (dho_len != sizeof(lease_time)) 802 goto wrong_length; 803 memcpy(&lease_time, p, sizeof(lease_time)); 804 lease_time = ntohl(lease_time); 805 if (log_getverbose() > 1) { 806 log_debug("DHO_DHCP_LEASE_TIME %us", 807 lease_time); 808 } 809 p += dho_len; 810 rem -= dho_len; 811 break; 812 case DHO_SUBNET_MASK: 813 if (dho_len != sizeof(subnet_mask)) 814 goto wrong_length; 815 memcpy(&subnet_mask, p, sizeof(subnet_mask)); 816 if (log_getverbose() > 1) { 817 log_debug("DHO_SUBNET_MASK: %s", 818 inet_ntop(AF_INET, &subnet_mask, hbuf, 819 sizeof(hbuf))); 820 } 821 p += dho_len; 822 rem -= dho_len; 823 break; 824 case DHO_ROUTERS: 825 if (dho_len < sizeof(router)) 826 goto wrong_length; 827 if (dho_len % sizeof(router) != 0) 828 goto wrong_length; 829 /* we only use one router */ 830 memcpy(&router, p, sizeof(router)); 831 if (log_getverbose() > 1) { 832 log_debug("DHO_ROUTER: %s (1/%lu)", 833 inet_ntop(AF_INET, &router, hbuf, 834 sizeof(hbuf)), dho_len / sizeof(router)); 835 } 836 p += dho_len; 837 rem -= dho_len; 838 break; 839 case DHO_DOMAIN_NAME_SERVERS: 840 if (dho_len < sizeof(nameservers[0])) 841 goto wrong_length; 842 if (dho_len % sizeof(nameservers[0]) != 0) 843 goto wrong_length; 844 /* we limit ourself to 8 nameservers for proposals */ 845 memcpy(&nameservers, p, MINIMUM(sizeof(nameservers), 846 dho_len)); 847 if (log_getverbose() > 1) { 848 for (i = 0; i < MINIMUM(sizeof(nameservers), 849 dho_len / sizeof(nameservers[0])); i++) { 850 log_debug("DHO_DOMAIN_NAME_SERVERS: %s " 851 "(%lu/%lu)", inet_ntop(AF_INET, 852 &nameservers[i], hbuf, 853 sizeof(hbuf)), i + 1, 854 dho_len / sizeof(nameservers[0])); 855 } 856 } 857 p += dho_len; 858 rem -= dho_len; 859 break; 860 case DHO_DOMAIN_NAME: 861 if ( dho_len < 1) 862 goto wrong_length; 863 if (log_getverbose() > 1) { 864 strvisx(vis_buf, p, dho_len, VIS_SAFE); 865 log_debug("DHO_DOMAIN_NAME: %s", vis_buf); 866 } 867 p += dho_len; 868 rem -= dho_len; 869 break; 870 case DHO_DHCP_RENEWAL_TIME: 871 if (dho_len != sizeof(renewal_time)) 872 goto wrong_length; 873 memcpy(&renewal_time, p, sizeof(renewal_time)); 874 renewal_time = ntohl(renewal_time); 875 if (log_getverbose() > 1) { 876 log_debug("DHO_DHCP_RENEWAL_TIME %us", 877 renewal_time); 878 } 879 p += dho_len; 880 rem -= dho_len; 881 break; 882 case DHO_DHCP_REBINDING_TIME: 883 if (dho_len != sizeof(rebinding_time)) 884 goto wrong_length; 885 memcpy(&rebinding_time, p, sizeof(rebinding_time)); 886 rebinding_time = ntohl(rebinding_time); 887 if (log_getverbose() > 1) { 888 log_debug("DHO_DHCP_REBINDING_TIME %us", 889 rebinding_time); 890 } 891 p += dho_len; 892 rem -= dho_len; 893 break; 894 case DHO_DHCP_CLIENT_IDENTIFIER: 895 /* the server is supposed to echo this back to us */ 896 if (dho_len != 1 + sizeof(iface->hw_address)) 897 goto wrong_length; 898 if (*p != HTYPE_ETHER) { 899 log_warn("DHO_DHCP_CLIENT_IDENTIFIER: wrong " 900 "type"); 901 return; 902 } 903 if (memcmp(p + 1, &iface->hw_address, 904 sizeof(iface->hw_address)) != 0) { 905 log_warn("wrong DHO_DHCP_CLIENT_IDENTIFIER"); 906 return; 907 } 908 p += dho_len; 909 rem -= dho_len; 910 break; 911 default: 912 if (log_getverbose() > 1) 913 log_debug("DHO_%u, len: %u", dho, dho_len); 914 p += dho_len; 915 rem -= dho_len; 916 } 917 918 } 919 while (rem != 0) { 920 if (*p != DHO_PAD) 921 break; 922 p++; 923 rem--; 924 } 925 if (rem != 0) 926 log_warnx("%s: %lu bytes garbage data from %s", __func__, rem, 927 from); 928 929 if_name = if_indextoname(iface->if_index, ifnamebuf); 930 log_debug("%s on %s from %s/%s to %s/%s", 931 dhcp_message_type2str(dhcp_message_type), if_name == NULL ? "?" : 932 if_name, from, hbuf_src, to, hbuf_dst); 933 934 switch (dhcp_message_type) { 935 case DHCPOFFER: 936 if (iface->state != IF_INIT) { 937 log_debug("ignoring unexpected DHCPOFFER"); 938 return; 939 } 940 if (server_identifier.s_addr == INADDR_ANY && 941 dhcp_hdr->yiaddr.s_addr == INADDR_ANY) { 942 log_warnx("%s: did not receive server identifier or " 943 "offered IP address", __func__); 944 return; 945 } 946 iface->server_identifier.s_addr = server_identifier.s_addr; 947 iface->requested_ip.s_addr = dhcp_hdr->yiaddr.s_addr; 948 state_transition(iface, IF_REQUESTING); 949 break; 950 case DHCPACK: 951 switch (iface->state) { 952 case IF_REQUESTING: 953 case IF_RENEWING: 954 case IF_REBINDING: 955 case IF_REBOOTING: 956 break; 957 default: 958 log_debug("ignoring unexpected DHCPACK"); 959 return; 960 } 961 if (server_identifier.s_addr == INADDR_ANY && 962 dhcp_hdr->yiaddr.s_addr == INADDR_ANY) { 963 log_warnx("%s: did not receive server identifier or " 964 "offered IP address", __func__); 965 return; 966 } 967 if (lease_time == 0) { 968 log_warnx("%s no lease time from %s", __func__, from); 969 return; 970 } 971 if (subnet_mask.s_addr == INADDR_ANY) { 972 log_warnx("%s: no subnetmask received from %s", 973 __func__, from); 974 return; 975 } 976 977 /* RFC 2131 4.4.5 */ 978 /* Ignore invalid T1/T2 options */ 979 if (renewal_time >= rebinding_time) { 980 log_warnx("%s: renewal_time(%u) >= rebinding_time(%u) " 981 "from %s: using defaults", 982 __func__, renewal_time, rebinding_time, from); 983 renewal_time = rebinding_time = 0; 984 } else if (rebinding_time >= lease_time) { 985 log_warnx("%s: rebinding_time(%u) >= lease_time(%u) " 986 "from %s: using defaults", 987 __func__, rebinding_time, lease_time, from); 988 renewal_time = rebinding_time = 0; 989 } 990 991 if (renewal_time == 0) 992 renewal_time = lease_time / 2; 993 if (rebinding_time == 0) 994 rebinding_time = lease_time - (lease_time / 8); 995 996 clock_gettime(CLOCK_MONOTONIC, &iface->request_time); 997 iface->server_identifier.s_addr = server_identifier.s_addr; 998 iface->requested_ip.s_addr = dhcp_hdr->yiaddr.s_addr; 999 iface->mask.s_addr = subnet_mask.s_addr; 1000 iface->router.s_addr = router.s_addr; 1001 iface->lease_time = lease_time; 1002 iface->renewal_time = renewal_time; 1003 iface->rebinding_time = rebinding_time; 1004 memcpy(iface->nameservers, nameservers, 1005 sizeof(iface->nameservers)); 1006 state_transition(iface, IF_BOUND); 1007 break; 1008 case DHCPNAK: 1009 switch (iface->state) { 1010 case IF_REQUESTING: 1011 case IF_RENEWING: 1012 case IF_REBINDING: 1013 case IF_REBOOTING: 1014 break; 1015 default: 1016 log_debug("ignoring unexpected DHCPNAK"); 1017 return; 1018 } 1019 1020 state_transition(iface, IF_INIT); 1021 break; 1022 default: 1023 log_warnx("%s: unimplemented message type %d", __func__, 1024 dhcp_message_type); 1025 break; 1026 } 1027 return; 1028 too_short: 1029 log_warnx("%s: message from %s too short", __func__, from); 1030 return; 1031 wrong_length: 1032 log_warnx("%s: received option %d with wrong length: %d", __func__, 1033 dho, dho_len); 1034 return; 1035 } 1036 1037 /* XXX check valid transitions */ 1038 void 1039 state_transition(struct dhcpleased_iface *iface, enum if_state new_state) 1040 { 1041 enum if_state old_state = iface->state; 1042 struct timespec now, res; 1043 char ifnamebuf[IF_NAMESIZE], *if_name; 1044 1045 iface->state = new_state; 1046 switch (new_state) { 1047 case IF_DOWN: 1048 if (iface->requested_ip.s_addr == INADDR_ANY) { 1049 /* nothing to do until iface comes up */ 1050 iface->timo.tv_sec = -1; 1051 break; 1052 } 1053 if (old_state == IF_DOWN) { 1054 /* nameservers already withdrawn when if went down */ 1055 send_deconfigure_interface(iface); 1056 /* nothing more to do until iface comes back */ 1057 iface->timo.tv_sec = -1; 1058 } else { 1059 send_rdns_withdraw(iface); 1060 clock_gettime(CLOCK_MONOTONIC, &now); 1061 timespecsub(&now, &iface->request_time, &res); 1062 iface->timo.tv_sec = iface->lease_time - res.tv_sec; 1063 if (iface->timo.tv_sec < 0) 1064 iface->timo.tv_sec = 0; /* deconfigure now */ 1065 } 1066 break; 1067 case IF_INIT: 1068 switch (old_state) { 1069 case IF_INIT: 1070 if (iface->timo.tv_sec < MAX_EXP_BACKOFF_SLOW) 1071 iface->timo.tv_sec *= 2; 1072 break; 1073 case IF_REQUESTING: 1074 case IF_RENEWING: 1075 case IF_REBINDING: 1076 case IF_REBOOTING: 1077 /* lease expired, got DHCPNAK or timeout: delete IP */ 1078 send_rdns_withdraw(iface); 1079 send_deconfigure_interface(iface); 1080 /* fall through */ 1081 case IF_DOWN: 1082 iface->timo.tv_sec = START_EXP_BACKOFF; 1083 break; 1084 case IF_BOUND: 1085 fatal("invalid transition Bound -> Init"); 1086 break; 1087 } 1088 request_dhcp_discover(iface); 1089 break; 1090 case IF_REBOOTING: 1091 if (old_state == IF_REBOOTING) 1092 iface->timo.tv_sec *= 2; 1093 else { 1094 /* make sure we send broadcast */ 1095 iface->dhcp_server.s_addr = INADDR_ANY; 1096 iface->timo.tv_sec = START_EXP_BACKOFF; 1097 } 1098 request_dhcp_request(iface); 1099 break; 1100 case IF_REQUESTING: 1101 if (old_state == IF_REQUESTING) 1102 iface->timo.tv_sec *= 2; 1103 else 1104 iface->timo.tv_sec = START_EXP_BACKOFF; 1105 request_dhcp_request(iface); 1106 break; 1107 case IF_BOUND: 1108 iface->timo.tv_sec = iface->renewal_time; 1109 if (old_state == IF_REQUESTING || old_state == IF_REBOOTING) { 1110 send_configure_interface(iface); 1111 send_rdns_proposal(iface); 1112 } 1113 break; 1114 case IF_RENEWING: 1115 if (old_state == IF_BOUND) { 1116 iface->dhcp_server.s_addr = 1117 iface->server_identifier.s_addr; 1118 iface->server_identifier.s_addr = INADDR_ANY; 1119 1120 iface->timo.tv_sec = (iface->rebinding_time - 1121 iface->renewal_time) / 2; /* RFC 2131 4.4.5 */ 1122 } else 1123 iface->timo.tv_sec /= 2; 1124 1125 if (iface->timo.tv_sec < 60) 1126 iface->timo.tv_sec = 60; 1127 request_dhcp_request(iface); 1128 break; 1129 case IF_REBINDING: 1130 if (old_state == IF_RENEWING) { 1131 iface->dhcp_server.s_addr = INADDR_ANY; 1132 iface->timo.tv_sec = (iface->lease_time - 1133 iface->renewal_time) / 2; /* RFC 2131 4.4.5 */ 1134 } else 1135 iface->timo.tv_sec /= 2; 1136 request_dhcp_request(iface); 1137 break; 1138 } 1139 1140 if_name = if_indextoname(iface->if_index, ifnamebuf); 1141 log_debug("%s[%s] %s -> %s, timo: %lld", __func__, if_name == NULL ? 1142 "?" : if_name, if_state_name[old_state], if_state_name[new_state], 1143 iface->timo.tv_sec); 1144 1145 if (iface->timo.tv_sec == -1) { 1146 if (evtimer_pending(&iface->timer, NULL)) 1147 evtimer_del(&iface->timer); 1148 } else 1149 evtimer_add(&iface->timer, &iface->timo); 1150 } 1151 1152 void 1153 iface_timeout(int fd, short events, void *arg) 1154 { 1155 struct dhcpleased_iface *iface = (struct dhcpleased_iface *)arg; 1156 struct timespec now, res; 1157 1158 log_debug("%s[%d]: %s", __func__, iface->if_index, 1159 if_state_name[iface->state]); 1160 1161 switch (iface->state) { 1162 case IF_DOWN: 1163 state_transition(iface, IF_DOWN); 1164 break; 1165 case IF_INIT: 1166 state_transition(iface, IF_INIT); 1167 break; 1168 case IF_REBOOTING: 1169 if (iface->timo.tv_sec >= MAX_EXP_BACKOFF_FAST) 1170 state_transition(iface, IF_INIT); 1171 else 1172 state_transition(iface, IF_REBOOTING); 1173 break; 1174 case IF_REQUESTING: 1175 if (iface->timo.tv_sec >= MAX_EXP_BACKOFF_FAST) 1176 state_transition(iface, IF_INIT); 1177 else 1178 state_transition(iface, IF_REQUESTING); 1179 break; 1180 case IF_BOUND: 1181 state_transition(iface, IF_RENEWING); 1182 break; 1183 case IF_RENEWING: 1184 clock_gettime(CLOCK_MONOTONIC, &now); 1185 timespecsub(&now, &iface->request_time, &res); 1186 log_debug("%s: res.tv_sec: %lld, rebinding_time: %u", __func__, 1187 res.tv_sec, iface->rebinding_time); 1188 if (res.tv_sec > iface->rebinding_time) 1189 state_transition(iface, IF_REBINDING); 1190 else 1191 state_transition(iface, IF_RENEWING); 1192 break; 1193 case IF_REBINDING: 1194 clock_gettime(CLOCK_MONOTONIC, &now); 1195 timespecsub(&now, &iface->request_time, &res); 1196 log_debug("%s: res.tv_sec: %lld, lease_time: %u", __func__, 1197 res.tv_sec, iface->lease_time); 1198 if (res.tv_sec > iface->lease_time) 1199 state_transition(iface, IF_INIT); 1200 else 1201 state_transition(iface, IF_REBINDING); 1202 break; 1203 } 1204 } 1205 1206 void 1207 request_dhcp_discover(struct dhcpleased_iface *iface) 1208 { 1209 struct imsg_req_discover imsg_req_discover; 1210 1211 imsg_req_discover.if_index = iface->if_index; 1212 imsg_req_discover.xid = iface->xid = arc4random(); 1213 engine_imsg_compose_frontend(IMSG_SEND_DISCOVER, 0, &imsg_req_discover, 1214 sizeof(imsg_req_discover)); 1215 } 1216 1217 void 1218 request_dhcp_request(struct dhcpleased_iface *iface) 1219 { 1220 struct imsg_req_request imsg_req_request; 1221 1222 iface->xid = arc4random(); 1223 imsg_req_request.if_index = iface->if_index; 1224 imsg_req_request.xid = iface->xid; 1225 imsg_req_request.server_identifier.s_addr = 1226 iface->server_identifier.s_addr; 1227 imsg_req_request.requested_ip.s_addr = iface->requested_ip.s_addr; 1228 imsg_req_request.dhcp_server.s_addr = iface->dhcp_server.s_addr; 1229 engine_imsg_compose_frontend(IMSG_SEND_REQUEST, 0, &imsg_req_request, 1230 sizeof(imsg_req_request)); 1231 } 1232 1233 void 1234 log_lease(struct dhcpleased_iface *iface, int deconfigure) 1235 { 1236 char hbuf_lease[INET_ADDRSTRLEN], hbuf_server[INET_ADDRSTRLEN]; 1237 char ifnamebuf[IF_NAMESIZE], *if_name; 1238 1239 if_name = if_indextoname(iface->if_index, ifnamebuf); 1240 inet_ntop(AF_INET, &iface->requested_ip, hbuf_lease, 1241 sizeof(hbuf_lease)); 1242 inet_ntop(AF_INET, &iface->server_identifier, hbuf_server, 1243 sizeof(hbuf_server)); 1244 1245 1246 if (deconfigure) 1247 log_info("deleting %s from %s (lease from %s)", hbuf_lease, 1248 if_name == NULL ? "?" : if_name, hbuf_server); 1249 else 1250 log_info("adding %s to %s (lease from %s)", hbuf_lease, 1251 if_name == NULL ? "?" : if_name, hbuf_server); 1252 } 1253 1254 void 1255 send_configure_interface(struct dhcpleased_iface *iface) 1256 { 1257 struct imsg_configure_interface imsg; 1258 1259 log_lease(iface, 0); 1260 1261 imsg.if_index = iface->if_index; 1262 imsg.rdomain = iface->rdomain; 1263 imsg.addr.s_addr = iface->requested_ip.s_addr; 1264 imsg.mask.s_addr = iface->mask.s_addr; 1265 imsg.router.s_addr = iface->router.s_addr; 1266 engine_imsg_compose_main(IMSG_CONFIGURE_INTERFACE, 0, &imsg, 1267 sizeof(imsg)); 1268 } 1269 1270 void 1271 send_deconfigure_interface(struct dhcpleased_iface *iface) 1272 { 1273 struct imsg_configure_interface imsg; 1274 1275 if (iface->requested_ip.s_addr == INADDR_ANY) 1276 return; 1277 1278 log_lease(iface, 1); 1279 1280 imsg.if_index = iface->if_index; 1281 imsg.rdomain = iface->rdomain; 1282 imsg.addr.s_addr = iface->requested_ip.s_addr; 1283 imsg.mask.s_addr = iface->mask.s_addr; 1284 imsg.router.s_addr = iface->router.s_addr; 1285 engine_imsg_compose_main(IMSG_DECONFIGURE_INTERFACE, 0, &imsg, 1286 sizeof(imsg)); 1287 1288 iface->server_identifier.s_addr = INADDR_ANY; 1289 iface->dhcp_server.s_addr = INADDR_ANY; 1290 iface->requested_ip.s_addr = INADDR_ANY; 1291 iface->mask.s_addr = INADDR_ANY; 1292 iface->router.s_addr = INADDR_ANY; 1293 } 1294 1295 void 1296 log_rdns(struct dhcpleased_iface *iface, int withdraw) 1297 { 1298 int i; 1299 char hbuf_rdns[INET_ADDRSTRLEN], hbuf_server[INET_ADDRSTRLEN]; 1300 char ifnamebuf[IF_NAMESIZE], *if_name, *rdns_buf = NULL, *tmp_buf; 1301 1302 if_name = if_indextoname(iface->if_index, ifnamebuf); 1303 1304 inet_ntop(AF_INET, &iface->server_identifier, hbuf_server, 1305 sizeof(hbuf_server)); 1306 1307 for (i = 0; i < MAX_RDNS_COUNT && iface->nameservers[i].s_addr != 1308 INADDR_ANY; i++) { 1309 inet_ntop(AF_INET, &iface->nameservers[i], hbuf_rdns, 1310 sizeof(hbuf_rdns)); 1311 tmp_buf = rdns_buf; 1312 if (asprintf(&rdns_buf, "%s %s", tmp_buf ? tmp_buf : "", 1313 hbuf_rdns) < 0) { 1314 rdns_buf = NULL; 1315 break; 1316 } 1317 free(tmp_buf); 1318 } 1319 1320 if (rdns_buf != NULL) { 1321 if (withdraw) { 1322 log_info("deleting nameservers%s (lease from %s on %s)", 1323 rdns_buf, hbuf_server, if_name == NULL ? "?" : 1324 if_name); 1325 } else { 1326 log_info("adding nameservers%s (lease from %s on %s)", 1327 rdns_buf, hbuf_server, if_name == NULL ? "?" : 1328 if_name); 1329 } 1330 free(rdns_buf); 1331 } 1332 } 1333 1334 void 1335 send_rdns_proposal(struct dhcpleased_iface *iface) 1336 { 1337 struct imsg_propose_rdns imsg; 1338 1339 log_rdns(iface, 0); 1340 1341 memset(&imsg, 0, sizeof(imsg)); 1342 1343 imsg.if_index = iface->if_index; 1344 imsg.rdomain = iface->rdomain; 1345 for (imsg.rdns_count = 0; imsg.rdns_count < MAX_RDNS_COUNT && 1346 iface->nameservers[imsg.rdns_count].s_addr != INADDR_ANY; 1347 imsg.rdns_count++) 1348 ; 1349 memcpy(imsg.rdns, iface->nameservers, sizeof(imsg.rdns)); 1350 engine_imsg_compose_main(IMSG_PROPOSE_RDNS, 0, &imsg, sizeof(imsg)); 1351 } 1352 1353 void 1354 send_rdns_withdraw(struct dhcpleased_iface *iface) 1355 { 1356 struct imsg_propose_rdns imsg; 1357 1358 log_rdns(iface, 1); 1359 1360 memset(&imsg, 0, sizeof(imsg)); 1361 1362 imsg.if_index = iface->if_index; 1363 imsg.rdomain = iface->rdomain; 1364 engine_imsg_compose_main(IMSG_WITHDRAW_RDNS, 0, &imsg, sizeof(imsg)); 1365 memset(iface->nameservers, 0, sizeof(iface->nameservers)); 1366 } 1367 1368 void 1369 parse_lease(struct dhcpleased_iface *iface, struct imsg_ifinfo *imsg_ifinfo) 1370 { 1371 char *p, *p1; 1372 1373 /* make sure this is a string */ 1374 imsg_ifinfo->lease[sizeof(imsg_ifinfo->lease) - 1] = '\0'; 1375 1376 iface->requested_ip.s_addr = INADDR_ANY; 1377 1378 if ((p = strstr(imsg_ifinfo->lease, LEASE_PREFIX)) == NULL) 1379 return; 1380 1381 p += sizeof(LEASE_PREFIX) - 1; 1382 if ((p1 = strchr(p, '\n')) == NULL) 1383 return; 1384 *p1 = '\0'; 1385 1386 if (inet_pton(AF_INET, p, &iface->requested_ip) != 1) 1387 iface->requested_ip.s_addr = INADDR_ANY; 1388 } 1389 1390 void 1391 log_dhcp_hdr(struct dhcp_hdr *dhcp_hdr) 1392 { 1393 char hbuf[INET_ADDRSTRLEN]; 1394 1395 log_debug("dhcp_hdr op: %s (%d)", dhcp_hdr->op == DHCP_BOOTREQUEST ? 1396 "Boot Request" : dhcp_hdr->op == DHCP_BOOTREPLY ? "Boot Reply" : 1397 "Unknown", dhcp_hdr->op); 1398 log_debug("dhcp_hdr htype: %s (%d)", dhcp_hdr->htype == 1 ? "Ethernet": 1399 "Unknown", dhcp_hdr->htype); 1400 log_debug("dhcp_hdr hlen: %d", dhcp_hdr->hlen); 1401 log_debug("dhcp_hdr hops: %d", dhcp_hdr->hops); 1402 log_debug("dhcp_hdr xid: 0x%x", dhcp_hdr->xid); 1403 log_debug("dhcp_hdr secs: %u", dhcp_hdr->secs); 1404 log_debug("dhcp_hdr flags: 0x%x", dhcp_hdr->flags); 1405 log_debug("dhcp_hdr ciaddr: %s", inet_ntop(AF_INET, &dhcp_hdr->ciaddr, 1406 hbuf, sizeof(hbuf))); 1407 log_debug("dhcp_hdr yiaddr: %s", inet_ntop(AF_INET, &dhcp_hdr->yiaddr, 1408 hbuf, sizeof(hbuf))); 1409 log_debug("dhcp_hdr siaddr: %s", inet_ntop(AF_INET, &dhcp_hdr->siaddr, 1410 hbuf, sizeof(hbuf))); 1411 log_debug("dhcp_hdr giaddr: %s", inet_ntop(AF_INET, &dhcp_hdr->giaddr, 1412 hbuf, sizeof(hbuf))); 1413 log_debug("dhcp_hdr chaddr: %02x:%02x:%02x:%02x:%02x:%02x " 1414 "(%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x)", 1415 dhcp_hdr->chaddr[0], dhcp_hdr->chaddr[1], dhcp_hdr->chaddr[2], 1416 dhcp_hdr->chaddr[3], dhcp_hdr->chaddr[4], dhcp_hdr->chaddr[5], 1417 dhcp_hdr->chaddr[6], dhcp_hdr->chaddr[7], dhcp_hdr->chaddr[8], 1418 dhcp_hdr->chaddr[9], dhcp_hdr->chaddr[10], dhcp_hdr->chaddr[11], 1419 dhcp_hdr->chaddr[12], dhcp_hdr->chaddr[13], dhcp_hdr->chaddr[14], 1420 dhcp_hdr->chaddr[15]); 1421 /* ignore sname and file, if we ever print it use strvis(3) */ 1422 } 1423 1424 const char * 1425 dhcp_message_type2str(uint8_t dhcp_message_type) 1426 { 1427 switch (dhcp_message_type) { 1428 case DHCPDISCOVER: 1429 return "DHCPDISCOVER"; 1430 case DHCPOFFER: 1431 return "DHCPOFFER"; 1432 case DHCPREQUEST: 1433 return "DHCPREQUEST"; 1434 case DHCPDECLINE: 1435 return "DHCPDECLINE"; 1436 case DHCPACK: 1437 return "DHCPACK"; 1438 case DHCPNAK: 1439 return "DHCPNAK"; 1440 case DHCPRELEASE: 1441 return "DHCPRELEASE"; 1442 case DHCPINFORM: 1443 return "DHCPINFORM"; 1444 default: 1445 return "Unknown"; 1446 } 1447 } 1448