1 /* $OpenBSD: engine.c,v 1.31 2024/12/24 17:40:06 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2017, 2021, 2024 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 #include <sys/mbuf.h> 28 29 #include <net/if.h> 30 #include <net/route.h> 31 #include <arpa/inet.h> 32 #include <netinet/in.h> 33 #include <netinet/ip.h> 34 35 #include <errno.h> 36 #include <event.h> 37 #include <imsg.h> 38 #include <pwd.h> 39 #include <signal.h> 40 #include <stddef.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <time.h> 45 #include <unistd.h> 46 #include <vis.h> 47 48 #include "log.h" 49 #include "dhcp6leased.h" 50 #include "engine.h" 51 52 /* 53 * RFC 2131 4.1 p23 has "SHOULD be 4 seconds", we are a bit more aggressive, 54 * networks are faster these days. 55 */ 56 #define START_EXP_BACKOFF 1 57 #define MAX_EXP_BACKOFF_SLOW 64 /* RFC 2131 4.1 p23 */ 58 #define MAX_EXP_BACKOFF_FAST 2 59 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 60 61 enum if_state { 62 IF_DOWN, 63 IF_INIT, 64 /* IF_SELECTING, */ 65 IF_REQUESTING, 66 IF_BOUND, 67 IF_RENEWING, 68 IF_REBINDING, 69 /* IF_INIT_REBOOT, */ 70 IF_REBOOTING, 71 }; 72 73 const char* if_state_name[] = { 74 "Down", 75 "Init", 76 /* "Selecting", */ 77 "Requesting", 78 "Bound", 79 "Renewing", 80 "Rebinding", 81 /* "Init-Reboot", */ 82 "Rebooting", 83 "IPv6 only", 84 }; 85 86 enum reconfigure_action { 87 CONFIGURE, 88 DECONFIGURE, 89 }; 90 91 const char* reconfigure_action_name[] = { 92 "configure", 93 "deconfigure", 94 }; 95 96 struct dhcp6leased_iface { 97 LIST_ENTRY(dhcp6leased_iface) entries; 98 enum if_state state; 99 struct event timer; 100 struct timeval timo; 101 uint32_t if_index; 102 int rdomain; 103 int running; 104 int link_state; 105 uint8_t xid[XID_SIZE]; 106 int serverid_len; 107 uint8_t serverid[SERVERID_SIZE]; 108 struct prefix pds[MAX_IA]; 109 struct prefix new_pds[MAX_IA]; 110 struct timespec request_time; 111 struct timespec elapsed_time_start; 112 uint32_t lease_time; 113 uint32_t t1; 114 uint32_t t2; 115 }; 116 117 LIST_HEAD(, dhcp6leased_iface) dhcp6leased_interfaces; 118 119 __dead void engine_shutdown(void); 120 void engine_sig_handler(int sig, short, void *); 121 void engine_dispatch_frontend(int, short, void *); 122 void engine_dispatch_main(int, short, void *); 123 void send_interface_info(struct dhcp6leased_iface *, pid_t); 124 void engine_showinfo_ctl(struct imsg *, uint32_t); 125 void engine_update_iface(struct imsg_ifinfo *); 126 struct dhcp6leased_iface *get_dhcp6leased_iface_by_id(uint32_t); 127 void remove_dhcp6leased_iface(uint32_t); 128 void parse_dhcp(struct dhcp6leased_iface *, 129 struct imsg_dhcp *); 130 int parse_ia_pd_options(uint8_t *, size_t, struct prefix *); 131 void state_transition(struct dhcp6leased_iface *, enum 132 if_state); 133 void iface_timeout(int, short, void *); 134 void request_dhcp_discover(struct dhcp6leased_iface *); 135 void request_dhcp_request(struct dhcp6leased_iface *); 136 void configure_interfaces(struct dhcp6leased_iface *); 137 void deconfigure_interfaces(struct dhcp6leased_iface *); 138 void deprecate_interfaces(struct dhcp6leased_iface *); 139 int prefixcmp(struct prefix *, struct prefix *, int); 140 void send_reconfigure_interface(struct iface_pd_conf *, 141 struct prefix *, enum reconfigure_action); 142 int engine_imsg_compose_main(int, pid_t, void *, uint16_t); 143 const char *dhcp_option_type2str(int); 144 const char *dhcp_duid2str(int, uint8_t *); 145 const char *dhcp_status2str(int); 146 void in6_prefixlen2mask(struct in6_addr *, int len); 147 148 struct dhcp6leased_conf *engine_conf; 149 150 static struct imsgev *iev_frontend; 151 static struct imsgev *iev_main; 152 int64_t proposal_id; 153 static struct dhcp_duid duid; 154 155 void 156 engine_sig_handler(int sig, short event, void *arg) 157 { 158 /* 159 * Normal signal handler rules don't apply because libevent 160 * decouples for us. 161 */ 162 163 switch (sig) { 164 case SIGINT: 165 case SIGTERM: 166 engine_shutdown(); 167 default: 168 fatalx("unexpected signal"); 169 } 170 } 171 172 void 173 engine(int debug, int verbose) 174 { 175 struct event ev_sigint, ev_sigterm; 176 struct passwd *pw; 177 178 engine_conf = config_new_empty(); 179 180 log_init(debug, LOG_DAEMON); 181 log_setverbose(verbose); 182 183 if ((pw = getpwnam(DHCP6LEASED_USER)) == NULL) 184 fatal("getpwnam"); 185 186 if (chdir("/") == -1) 187 fatal("chdir(\"/\")"); 188 189 if (unveil("/", "") == -1) 190 fatal("unveil /"); 191 if (unveil(NULL, NULL) == -1) 192 fatal("unveil"); 193 194 setproctitle("%s", "engine"); 195 log_procinit("engine"); 196 197 if (setgroups(1, &pw->pw_gid) || 198 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 199 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 200 fatal("can't drop privileges"); 201 202 if (pledge("stdio recvfd", NULL) == -1) 203 fatal("pledge"); 204 205 event_init(); 206 207 /* Setup signal handler(s). */ 208 signal_set(&ev_sigint, SIGINT, engine_sig_handler, NULL); 209 signal_set(&ev_sigterm, SIGTERM, engine_sig_handler, NULL); 210 signal_add(&ev_sigint, NULL); 211 signal_add(&ev_sigterm, NULL); 212 signal(SIGPIPE, SIG_IGN); 213 signal(SIGHUP, SIG_IGN); 214 215 /* Setup pipe and event handler to the main process. */ 216 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 217 fatal(NULL); 218 219 if (imsgbuf_init(&iev_main->ibuf, 3) == -1) 220 fatal(NULL); 221 imsgbuf_allow_fdpass(&iev_main->ibuf); 222 iev_main->handler = engine_dispatch_main; 223 224 /* Setup event handlers. */ 225 iev_main->events = EV_READ; 226 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 227 iev_main->handler, iev_main); 228 event_add(&iev_main->ev, NULL); 229 230 LIST_INIT(&dhcp6leased_interfaces); 231 232 event_dispatch(); 233 234 engine_shutdown(); 235 } 236 237 __dead void 238 engine_shutdown(void) 239 { 240 /* Close pipes. */ 241 imsgbuf_clear(&iev_frontend->ibuf); 242 close(iev_frontend->ibuf.fd); 243 imsgbuf_clear(&iev_main->ibuf); 244 close(iev_main->ibuf.fd); 245 246 free(iev_frontend); 247 free(iev_main); 248 249 log_info("engine exiting"); 250 exit(0); 251 } 252 253 int 254 engine_imsg_compose_frontend(int type, pid_t pid, void *data, 255 uint16_t datalen) 256 { 257 return (imsg_compose_event(iev_frontend, type, 0, pid, -1, 258 data, datalen)); 259 } 260 261 int 262 engine_imsg_compose_main(int type, pid_t pid, void *data, 263 uint16_t datalen) 264 { 265 return (imsg_compose_event(iev_main, type, 0, pid, -1, 266 data, datalen)); 267 } 268 269 void 270 engine_dispatch_frontend(int fd, short event, void *bula) 271 { 272 struct imsgev *iev = bula; 273 struct imsgbuf *ibuf = &iev->ibuf; 274 struct imsg imsg; 275 struct dhcp6leased_iface *iface; 276 ssize_t n; 277 int shut = 0; 278 int verbose; 279 uint32_t if_index; 280 281 if (event & EV_READ) { 282 if ((n = imsgbuf_read(ibuf)) == -1) 283 fatal("imsgbuf_read error"); 284 if (n == 0) /* Connection closed. */ 285 shut = 1; 286 } 287 if (event & EV_WRITE) { 288 if (imsgbuf_write(ibuf) == -1) { 289 if (errno == EPIPE) /* Connection closed. */ 290 shut = 1; 291 else 292 fatal("imsgbuf_write"); 293 } 294 } 295 296 for (;;) { 297 if ((n = imsg_get(ibuf, &imsg)) == -1) 298 fatal("%s: imsg_get error", __func__); 299 if (n == 0) /* No more messages. */ 300 break; 301 302 switch (imsg.hdr.type) { 303 case IMSG_CTL_LOG_VERBOSE: 304 if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 305 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 306 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 307 memcpy(&verbose, imsg.data, sizeof(verbose)); 308 log_setverbose(verbose); 309 break; 310 case IMSG_CTL_SHOW_INTERFACE_INFO: 311 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 312 fatalx("%s: IMSG_CTL_SHOW_INTERFACE_INFO wrong " 313 "length: %lu", __func__, 314 IMSG_DATA_SIZE(imsg)); 315 memcpy(&if_index, imsg.data, sizeof(if_index)); 316 engine_showinfo_ctl(&imsg, if_index); 317 break; 318 case IMSG_REQUEST_REBOOT: 319 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 320 fatalx("%s: IMSG_CTL_SEND_DISCOVER wrong " 321 "length: %lu", __func__, 322 IMSG_DATA_SIZE(imsg)); 323 memcpy(&if_index, imsg.data, sizeof(if_index)); 324 iface = get_dhcp6leased_iface_by_id(if_index); 325 if (iface != NULL) { 326 switch (iface->state) { 327 case IF_DOWN: 328 break; 329 case IF_INIT: 330 case IF_REQUESTING: 331 state_transition(iface, iface->state); 332 break; 333 case IF_RENEWING: 334 case IF_REBINDING: 335 case IF_REBOOTING: 336 case IF_BOUND: 337 state_transition(iface, IF_REBOOTING); 338 break; 339 } 340 } 341 break; 342 case IMSG_REMOVE_IF: 343 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 344 fatalx("%s: IMSG_REMOVE_IF wrong length: %lu", 345 __func__, IMSG_DATA_SIZE(imsg)); 346 memcpy(&if_index, imsg.data, sizeof(if_index)); 347 remove_dhcp6leased_iface(if_index); 348 break; 349 case IMSG_DHCP: { 350 struct imsg_dhcp imsg_dhcp; 351 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_dhcp)) 352 fatalx("%s: IMSG_DHCP wrong length: %lu", 353 __func__, IMSG_DATA_SIZE(imsg)); 354 memcpy(&imsg_dhcp, imsg.data, sizeof(imsg_dhcp)); 355 iface = get_dhcp6leased_iface_by_id(imsg_dhcp.if_index); 356 if (iface != NULL) 357 parse_dhcp(iface, &imsg_dhcp); 358 break; 359 } 360 default: 361 log_debug("%s: unexpected imsg %d", __func__, 362 imsg.hdr.type); 363 break; 364 } 365 imsg_free(&imsg); 366 } 367 if (!shut) 368 imsg_event_add(iev); 369 else { 370 /* This pipe is dead. Remove its event handler. */ 371 event_del(&iev->ev); 372 event_loopexit(NULL); 373 } 374 } 375 376 void 377 engine_dispatch_main(int fd, short event, void *bula) 378 { 379 static struct dhcp6leased_conf *nconf; 380 static struct iface_conf *iface_conf; 381 static struct iface_ia_conf *iface_ia_conf; 382 struct iface_pd_conf *iface_pd_conf; 383 struct imsg imsg; 384 struct imsgev *iev = bula; 385 struct imsgbuf *ibuf = &iev->ibuf; 386 struct imsg_ifinfo imsg_ifinfo; 387 ssize_t n; 388 int shut = 0; 389 390 if (event & EV_READ) { 391 if ((n = imsgbuf_read(ibuf)) == -1) 392 fatal("imsgbuf_read error"); 393 if (n == 0) /* Connection closed. */ 394 shut = 1; 395 } 396 if (event & EV_WRITE) { 397 if (imsgbuf_write(ibuf) == -1) { 398 if (errno == EPIPE) /* Connection closed. */ 399 shut = 1; 400 else 401 fatal("imsgbuf_write"); 402 } 403 } 404 405 for (;;) { 406 if ((n = imsg_get(ibuf, &imsg)) == -1) 407 fatal("%s: imsg_get error", __func__); 408 if (n == 0) /* No more messages. */ 409 break; 410 411 switch (imsg.hdr.type) { 412 case IMSG_SOCKET_IPC: 413 /* 414 * Setup pipe and event handler to the frontend 415 * process. 416 */ 417 if (iev_frontend) 418 fatalx("%s: received unexpected imsg fd " 419 "to engine", __func__); 420 421 if ((fd = imsg_get_fd(&imsg)) == -1) 422 fatalx("%s: expected to receive imsg fd to " 423 "engine but didn't receive any", __func__); 424 425 iev_frontend = malloc(sizeof(struct imsgev)); 426 if (iev_frontend == NULL) 427 fatal(NULL); 428 429 if (imsgbuf_init(&iev_frontend->ibuf, fd) == -1) 430 fatal(NULL); 431 iev_frontend->handler = engine_dispatch_frontend; 432 iev_frontend->events = EV_READ; 433 434 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 435 iev_frontend->events, iev_frontend->handler, 436 iev_frontend); 437 event_add(&iev_frontend->ev, NULL); 438 439 if (pledge("stdio", NULL) == -1) 440 fatal("pledge"); 441 442 break; 443 case IMSG_UUID: 444 if (IMSG_DATA_SIZE(imsg) != sizeof(duid.uuid)) 445 fatalx("%s: IMSG_UUID wrong length: " 446 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 447 duid.type = htons(DUID_UUID_TYPE); 448 memcpy(duid.uuid, imsg.data, sizeof(duid.uuid)); 449 break; 450 case IMSG_UPDATE_IF: 451 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_ifinfo)) 452 fatalx("%s: IMSG_UPDATE_IF wrong length: %lu", 453 __func__, IMSG_DATA_SIZE(imsg)); 454 memcpy(&imsg_ifinfo, imsg.data, sizeof(imsg_ifinfo)); 455 engine_update_iface(&imsg_ifinfo); 456 break; 457 case IMSG_RECONF_CONF: 458 if (nconf != NULL) 459 fatalx("%s: IMSG_RECONF_CONF already in " 460 "progress", __func__); 461 if (IMSG_DATA_SIZE(imsg) != 462 sizeof(struct dhcp6leased_conf)) 463 fatalx("%s: IMSG_RECONF_CONF wrong length: %lu", 464 __func__, IMSG_DATA_SIZE(imsg)); 465 if ((nconf = malloc(sizeof(struct dhcp6leased_conf))) == 466 NULL) 467 fatal(NULL); 468 memcpy(nconf, imsg.data, 469 sizeof(struct dhcp6leased_conf)); 470 SIMPLEQ_INIT(&nconf->iface_list); 471 break; 472 case IMSG_RECONF_IFACE: 473 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 474 iface_conf)) 475 fatalx("%s: IMSG_RECONF_IFACE wrong length: " 476 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 477 if ((iface_conf = malloc(sizeof(struct iface_conf))) 478 == NULL) 479 fatal(NULL); 480 memcpy(iface_conf, imsg.data, sizeof(struct 481 iface_conf)); 482 SIMPLEQ_INIT(&iface_conf->iface_ia_list); 483 SIMPLEQ_INSERT_TAIL(&nconf->iface_list, 484 iface_conf, entry); 485 iface_conf->ia_count = 0; 486 break; 487 case IMSG_RECONF_IFACE_IA: 488 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 489 iface_ia_conf)) 490 fatalx("%s: IMSG_RECONF_IFACE_IA wrong " 491 "length: %lu", __func__, 492 IMSG_DATA_SIZE(imsg)); 493 if ((iface_ia_conf = 494 malloc(sizeof(struct iface_ia_conf))) == NULL) 495 fatal(NULL); 496 memcpy(iface_ia_conf, imsg.data, sizeof(struct 497 iface_ia_conf)); 498 SIMPLEQ_INIT(&iface_ia_conf->iface_pd_list); 499 SIMPLEQ_INSERT_TAIL(&iface_conf->iface_ia_list, 500 iface_ia_conf, entry); 501 iface_ia_conf->id = iface_conf->ia_count++; 502 if (iface_conf->ia_count > MAX_IA) 503 fatalx("Too many prefix delegation requests."); 504 break; 505 case IMSG_RECONF_IFACE_PD: 506 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 507 iface_pd_conf)) 508 fatalx("%s: IMSG_RECONF_IFACE_PD wrong length: " 509 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 510 if ((iface_pd_conf = 511 malloc(sizeof(struct iface_pd_conf))) == NULL) 512 fatal(NULL); 513 memcpy(iface_pd_conf, imsg.data, sizeof(struct 514 iface_pd_conf)); 515 SIMPLEQ_INSERT_TAIL(&iface_ia_conf->iface_pd_list, 516 iface_pd_conf, entry); 517 break; 518 case IMSG_RECONF_IFACE_IA_END: 519 iface_ia_conf = NULL; 520 break; 521 case IMSG_RECONF_IFACE_END: 522 iface_conf = NULL; 523 break; 524 case IMSG_RECONF_END: { 525 struct dhcp6leased_iface *iface; 526 int *ifaces; 527 int i, if_index; 528 char *if_name; 529 char ifnamebuf[IF_NAMESIZE]; 530 531 if (nconf == NULL) 532 fatalx("%s: IMSG_RECONF_END without " 533 "IMSG_RECONF_CONF", __func__); 534 ifaces = changed_ifaces(engine_conf, nconf); 535 merge_config(engine_conf, nconf); 536 nconf = NULL; 537 for (i = 0; ifaces[i] != 0; i++) { 538 if_index = ifaces[i]; 539 if_name = if_indextoname(if_index, ifnamebuf); 540 iface = get_dhcp6leased_iface_by_id(if_index); 541 if (if_name == NULL || iface == NULL) 542 continue; 543 iface_conf = find_iface_conf( 544 &engine_conf->iface_list, if_name); 545 if (iface_conf == NULL) 546 continue; 547 } 548 free(ifaces); 549 break; 550 } 551 default: 552 log_debug("%s: unexpected imsg %d", __func__, 553 imsg.hdr.type); 554 break; 555 } 556 imsg_free(&imsg); 557 } 558 if (!shut) 559 imsg_event_add(iev); 560 else { 561 /* This pipe is dead. Remove its event handler. */ 562 event_del(&iev->ev); 563 event_loopexit(NULL); 564 } 565 } 566 567 void 568 send_interface_info(struct dhcp6leased_iface *iface, pid_t pid) 569 { 570 struct ctl_engine_info cei; 571 572 memset(&cei, 0, sizeof(cei)); 573 cei.if_index = iface->if_index; 574 cei.running = iface->running; 575 cei.link_state = iface->link_state; 576 strlcpy(cei.state, if_state_name[iface->state], sizeof(cei.state)); 577 memcpy(&cei.request_time, &iface->request_time, 578 sizeof(cei.request_time)); 579 cei.lease_time = iface->lease_time; 580 cei.t1 = iface->t1; 581 cei.t2 = iface->t2; 582 memcpy(&cei.pds, &iface->pds, sizeof(cei.pds)); 583 engine_imsg_compose_frontend(IMSG_CTL_SHOW_INTERFACE_INFO, pid, &cei, 584 sizeof(cei)); 585 } 586 587 void 588 engine_showinfo_ctl(struct imsg *imsg, uint32_t if_index) 589 { 590 struct dhcp6leased_iface *iface; 591 592 switch (imsg->hdr.type) { 593 case IMSG_CTL_SHOW_INTERFACE_INFO: 594 if ((iface = get_dhcp6leased_iface_by_id(if_index)) != NULL) 595 send_interface_info(iface, imsg->hdr.pid); 596 else 597 engine_imsg_compose_frontend(IMSG_CTL_END, 598 imsg->hdr.pid, NULL, 0); 599 break; 600 default: 601 log_debug("%s: error handling imsg", __func__); 602 break; 603 } 604 } 605 606 void 607 engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) 608 { 609 struct dhcp6leased_iface *iface; 610 struct iface_conf *iface_conf; 611 int need_refresh = 0; 612 char ifnamebuf[IF_NAMESIZE], *if_name; 613 614 iface = get_dhcp6leased_iface_by_id(imsg_ifinfo->if_index); 615 616 if (iface == NULL) { 617 if ((iface = calloc(1, sizeof(*iface))) == NULL) 618 fatal("calloc"); 619 iface->state = IF_DOWN; 620 arc4random_buf(iface->xid, sizeof(iface->xid)); 621 iface->timo.tv_usec = arc4random_uniform(1000000); 622 evtimer_set(&iface->timer, iface_timeout, iface); 623 iface->if_index = imsg_ifinfo->if_index; 624 iface->rdomain = imsg_ifinfo->rdomain; 625 iface->running = imsg_ifinfo->running; 626 iface->link_state = imsg_ifinfo->link_state; 627 LIST_INSERT_HEAD(&dhcp6leased_interfaces, iface, entries); 628 need_refresh = 1; 629 } else { 630 if (imsg_ifinfo->rdomain != iface->rdomain) { 631 iface->rdomain = imsg_ifinfo->rdomain; 632 need_refresh = 1; 633 } 634 if (imsg_ifinfo->running != iface->running) { 635 iface->running = imsg_ifinfo->running; 636 need_refresh = 1; 637 } 638 639 if (imsg_ifinfo->link_state != iface->link_state) { 640 iface->link_state = imsg_ifinfo->link_state; 641 need_refresh = 1; 642 } 643 } 644 645 if (!need_refresh) 646 return; 647 648 if ((if_name = if_indextoname(iface->if_index, ifnamebuf)) == NULL) { 649 log_debug("%s: unknown interface %d", __func__, 650 iface->if_index); 651 return; 652 } 653 654 if ((iface_conf = find_iface_conf(&engine_conf->iface_list, if_name)) 655 == NULL) { 656 log_debug("%s: no interface configuration for %d", __func__, 657 iface->if_index); 658 return; 659 } 660 661 if (iface->running && LINK_STATE_IS_UP(iface->link_state)) { 662 uint32_t i; 663 int got_lease; 664 665 if (iface->pds[0].prefix_len == 0) 666 memcpy(iface->pds, imsg_ifinfo->pds, 667 sizeof(iface->pds)); 668 669 got_lease = 0; 670 for (i = 0; i < iface_conf->ia_count; i++) { 671 if (iface->pds[i].prefix_len > 0) { 672 got_lease = 1; 673 break; 674 } 675 } 676 if (got_lease) 677 state_transition(iface, IF_REBOOTING); 678 else 679 state_transition(iface, IF_INIT); 680 } else 681 state_transition(iface, IF_DOWN); 682 } 683 struct dhcp6leased_iface* 684 get_dhcp6leased_iface_by_id(uint32_t if_index) 685 { 686 struct dhcp6leased_iface *iface; 687 LIST_FOREACH (iface, &dhcp6leased_interfaces, entries) { 688 if (iface->if_index == if_index) 689 return (iface); 690 } 691 692 return (NULL); 693 } 694 695 void 696 remove_dhcp6leased_iface(uint32_t if_index) 697 { 698 struct dhcp6leased_iface *iface; 699 700 iface = get_dhcp6leased_iface_by_id(if_index); 701 702 if (iface == NULL) 703 return; 704 705 deconfigure_interfaces(iface); 706 LIST_REMOVE(iface, entries); 707 evtimer_del(&iface->timer); 708 free(iface); 709 } 710 711 void 712 parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp) 713 { 714 struct iface_conf *iface_conf; 715 struct iface_ia_conf *ia_conf; 716 struct dhcp_hdr hdr; 717 struct dhcp_option_hdr opt_hdr; 718 struct dhcp_iapd iapd; 719 size_t rem; 720 uint32_t t1, t2, lease_time; 721 int serverid_len, rapid_commit = 0; 722 uint8_t serverid[SERVERID_SIZE]; 723 uint8_t *p; 724 char ifnamebuf[IF_NAMESIZE], *if_name; 725 char ntopbuf[INET6_ADDRSTRLEN]; 726 727 if ((if_name = if_indextoname(iface->if_index, ifnamebuf)) == NULL) { 728 log_debug("%s: unknown interface %d", __func__, 729 iface->if_index); 730 goto out; 731 } 732 if ((iface_conf = find_iface_conf(&engine_conf->iface_list, if_name)) 733 == NULL) { 734 log_debug("%s: no interface configuration for %d", __func__, 735 iface->if_index); 736 goto out; 737 } 738 739 log_debug("%s: %s ia_count: %d", __func__, if_name, 740 iface_conf->ia_count); 741 742 serverid_len = t1 = t2 = lease_time = 0; 743 memset(iface->new_pds, 0, sizeof(iface->new_pds)); 744 745 p = dhcp->packet; 746 rem = dhcp->len; 747 748 if (rem < sizeof(struct dhcp_hdr)) { 749 log_warnx("%s: message too short", __func__); 750 goto out; 751 } 752 memcpy(&hdr, p, sizeof(struct dhcp_hdr)); 753 p += sizeof(struct dhcp_hdr); 754 rem -= sizeof(struct dhcp_hdr); 755 756 if (log_getverbose() > 1) 757 log_debug("%s: %s, xid: 0x%02x%02x%02x", __func__, 758 dhcp_message_type2str(hdr.msg_type), hdr.xid[0], hdr.xid[1], 759 hdr.xid[2]); 760 761 while (rem >= sizeof(struct dhcp_option_hdr)) { 762 memcpy(&opt_hdr, p, sizeof(struct dhcp_option_hdr)); 763 opt_hdr.code = ntohs(opt_hdr.code); 764 opt_hdr.len = ntohs(opt_hdr.len); 765 p += sizeof(struct dhcp_option_hdr); 766 rem -= sizeof(struct dhcp_option_hdr); 767 if (log_getverbose() > 1) 768 log_debug("%s: %s, len: %u", __func__, 769 dhcp_option_type2str(opt_hdr.code), opt_hdr.len); 770 771 if (rem < opt_hdr.len) { 772 log_warnx("%s: malformed packet, ignoring", __func__); 773 goto out; 774 } 775 776 switch (opt_hdr.code) { 777 case DHO_CLIENTID: 778 if (opt_hdr.len != sizeof(struct dhcp_duid) || 779 memcmp(&duid, p, sizeof(struct dhcp_duid)) != 0) { 780 log_debug("%s: message not for us", __func__); 781 goto out; 782 } 783 break; 784 case DHO_SERVERID: 785 /* 786 * RFC 8415, 11.1: 787 * The length of the DUID (not including the type code) 788 * is at least 1 octet and at most 128 octets. 789 */ 790 if (opt_hdr.len < 2 + 1) { 791 log_warnx("%s: SERVERID too short", __func__); 792 goto out; 793 } 794 if (opt_hdr.len > SERVERID_SIZE) { 795 log_warnx("%s: SERVERID too long", __func__); 796 goto out; 797 } 798 log_debug("%s: SERVERID: %s", __func__, 799 dhcp_duid2str(opt_hdr.len, p)); 800 if (serverid_len != 0) { 801 log_warnx("%s: duplicate SERVERID option", 802 __func__); 803 goto out; 804 } 805 serverid_len = opt_hdr.len; 806 memcpy(serverid, p, serverid_len); 807 break; 808 case DHO_IA_PD: 809 if (opt_hdr.len < sizeof(struct dhcp_iapd)) { 810 log_warnx("%s: IA_PD too short", __func__); 811 goto out; 812 } 813 memcpy(&iapd, p, sizeof(struct dhcp_iapd)); 814 815 if (t1 == 0 || t1 > ntohl(iapd.t1)) 816 t1 = ntohl(iapd.t1); 817 if (t2 == 0 || t2 > ntohl(iapd.t2)) 818 t2 = ntohl(iapd.t2); 819 820 log_debug("%s: IA_PD, IAID: %08x, T1: %u, T2: %u", 821 __func__, ntohl(iapd.iaid), ntohl(iapd.t1), 822 ntohl(iapd.t2)); 823 if (ntohl(iapd.iaid) < iface_conf->ia_count) { 824 int status_code; 825 status_code = parse_ia_pd_options(p + 826 sizeof(struct dhcp_iapd), opt_hdr.len - 827 sizeof(struct dhcp_iapd), 828 &iface->new_pds[ntohl(iapd.iaid)]); 829 830 if (status_code != DHCP_STATUS_SUCCESS && 831 iface->state == IF_RENEWING) { 832 state_transition(iface, IF_REBINDING); 833 goto out; 834 } 835 } 836 break; 837 case DHO_RAPID_COMMIT: 838 if (opt_hdr.len != 0) { 839 log_warnx("%s: invalid rapid commit option", 840 __func__); 841 goto out; 842 } 843 rapid_commit = 1; 844 break; 845 default: 846 log_debug("unhandled option: %u", opt_hdr.code); 847 break; 848 } 849 850 p += opt_hdr.len; 851 rem -= opt_hdr.len; 852 } 853 854 /* check that we got all the information we need */ 855 if (serverid_len == 0) { 856 log_warnx("%s: Did not receive server identifier", __func__); 857 goto out; 858 } 859 860 861 SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) { 862 struct prefix *pd = &iface->new_pds[ia_conf->id]; 863 864 if (pd->prefix_len == 0) { 865 log_warnx("%s: no IA for IAID %d found", __func__, 866 ia_conf->id); 867 goto out; 868 } 869 if (pd->prefix_len > ia_conf->prefix_len) { 870 log_warnx("%s: prefix for IAID %d too small: %d > %d", 871 __func__, ia_conf->id, pd->prefix_len, 872 ia_conf->prefix_len); 873 goto out; 874 } 875 876 if (lease_time < pd->vltime) 877 lease_time = pd->vltime; 878 879 log_debug("%s: pltime: %u, vltime: %u, prefix: %s/%u", 880 __func__, pd->pltime, pd->vltime, inet_ntop(AF_INET6, 881 &pd->prefix, ntopbuf, INET6_ADDRSTRLEN), pd->prefix_len); 882 } 883 884 switch (hdr.msg_type) { 885 case DHCPSOLICIT: 886 case DHCPREQUEST: 887 case DHCPCONFIRM: 888 case DHCPRENEW: 889 case DHCPREBIND: 890 case DHCPRELEASE: 891 case DHCPDECLINE: 892 case DHCPINFORMATIONREQUEST: 893 log_warnx("%s: Ignoring client-only message (%s) from server", 894 __func__, dhcp_message_type2str(hdr.msg_type)); 895 goto out; 896 case DHCPRELAYFORW: 897 case DHCPRELAYREPL: 898 log_warnx("%s: Ignoring relay-agent-only message (%s) from " 899 "server", __func__, dhcp_message_type2str(hdr.msg_type)); 900 goto out; 901 case DHCPADVERTISE: 902 if (iface->state != IF_INIT) { 903 log_debug("%s: ignoring unexpected %s", __func__, 904 dhcp_message_type2str(hdr.msg_type)); 905 goto out; 906 } 907 iface->serverid_len = serverid_len; 908 memcpy(iface->serverid, serverid, SERVERID_SIZE); 909 memcpy(iface->pds, iface->new_pds, sizeof(iface->pds)); 910 state_transition(iface, IF_REQUESTING); 911 break; 912 case DHCPREPLY: 913 switch (iface->state) { 914 case IF_REQUESTING: 915 case IF_RENEWING: 916 case IF_REBINDING: 917 case IF_REBOOTING: 918 break; 919 case IF_INIT: 920 if (rapid_commit && engine_conf->rapid_commit) 921 break; 922 /* fall through */ 923 default: 924 log_debug("%s: ignoring unexpected %s", __func__, 925 dhcp_message_type2str(hdr.msg_type)); 926 goto out; 927 } 928 iface->serverid_len = serverid_len; 929 memcpy(iface->serverid, serverid, SERVERID_SIZE); 930 931 /* XXX handle t1 = 0 or t2 = 0 */ 932 iface->t1 = t1; 933 iface->t2 = t2; 934 iface->lease_time = lease_time; 935 clock_gettime(CLOCK_MONOTONIC, &iface->request_time); 936 state_transition(iface, IF_BOUND); 937 break; 938 case DHCPRECONFIGURE: 939 log_warnx("%s: Ignoring %s from server", 940 __func__, dhcp_message_type2str(hdr.msg_type)); 941 goto out; 942 default: 943 fatalx("%s: %s unhandled", 944 __func__, dhcp_message_type2str(hdr.msg_type)); 945 break; 946 } 947 out: 948 return; 949 } 950 951 int 952 parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix) 953 { 954 struct dhcp_option_hdr opt_hdr; 955 struct dhcp_iaprefix iaprefix; 956 struct in6_addr mask; 957 int i; 958 uint16_t status_code = DHCP_STATUS_SUCCESS; 959 char ntopbuf[INET6_ADDRSTRLEN], *visbuf; 960 961 while (len >= sizeof(struct dhcp_option_hdr)) { 962 memcpy(&opt_hdr, p, sizeof(struct dhcp_option_hdr)); 963 opt_hdr.code = ntohs(opt_hdr.code); 964 opt_hdr.len = ntohs(opt_hdr.len); 965 p += sizeof(struct dhcp_option_hdr); 966 len -= sizeof(struct dhcp_option_hdr); 967 if (log_getverbose() > 1) 968 log_debug("%s: %s, len: %u", __func__, 969 dhcp_option_type2str(opt_hdr.code), opt_hdr.len); 970 if (len < opt_hdr.len) { 971 log_warnx("%s: malformed packet, ignoring", __func__); 972 return DHCP_STATUS_UNSPECFAIL; 973 } 974 975 switch (opt_hdr.code) { 976 case DHO_IA_PREFIX: 977 if (len < sizeof(struct dhcp_iaprefix)) { 978 log_warnx("%s: malformed packet, ignoring", 979 __func__); 980 return DHCP_STATUS_UNSPECFAIL; 981 } 982 983 memcpy(&iaprefix, p, sizeof(struct dhcp_iaprefix)); 984 log_debug("%s: pltime: %u, vltime: %u, prefix: %s/%u", 985 __func__, ntohl(iaprefix.pltime), 986 ntohl(iaprefix.vltime), inet_ntop(AF_INET6, 987 &iaprefix.prefix, ntopbuf, INET6_ADDRSTRLEN), 988 iaprefix.prefix_len); 989 990 if (ntohl(iaprefix.vltime) < ntohl(iaprefix.pltime)) { 991 log_warnx("%s: vltime < pltime, ignoring IA_PD", 992 __func__); 993 break; 994 } 995 996 if (ntohl(iaprefix.vltime) == 0) { 997 log_debug("%s: vltime == 0, ignoring IA_PD", 998 __func__); 999 break; 1000 } 1001 1002 prefix->prefix = iaprefix.prefix; 1003 prefix->prefix_len = iaprefix.prefix_len; 1004 prefix->vltime = ntohl(iaprefix.vltime); 1005 prefix->pltime = ntohl(iaprefix.pltime); 1006 1007 /* make sure prefix is masked correctly */ 1008 memset(&mask, 0, sizeof(mask)); 1009 in6_prefixlen2mask(&mask, prefix->prefix_len); 1010 for (i = 0; i < 16; i++) 1011 prefix->prefix.s6_addr[i] &= mask.s6_addr[i]; 1012 1013 break; 1014 case DHO_STATUS_CODE: 1015 /* XXX STATUS_CODE can also appear outside of options */ 1016 if (len < 2) { 1017 log_warnx("%s: malformed packet, ignoring", 1018 __func__); 1019 return DHCP_STATUS_UNSPECFAIL; 1020 } 1021 memcpy(&status_code, p, sizeof(uint16_t)); 1022 status_code = ntohs(status_code); 1023 /* must be at least 4 * srclen + 1 long */ 1024 visbuf = calloc(4, opt_hdr.len - 2 + 1); 1025 if (visbuf == NULL) { 1026 log_warn("%s", __func__); 1027 break; 1028 } 1029 strvisx(visbuf, p + 2, opt_hdr.len - 2, VIS_SAFE); 1030 log_debug("%s: %s - %s", __func__, 1031 dhcp_status2str(status_code), visbuf); 1032 break; 1033 default: 1034 log_debug("unhandled option: %u", opt_hdr.code); 1035 } 1036 p += opt_hdr.len; 1037 len -= opt_hdr.len; 1038 } 1039 return status_code; 1040 } 1041 1042 /* XXX check valid transitions */ 1043 void 1044 state_transition(struct dhcp6leased_iface *iface, enum if_state new_state) 1045 { 1046 enum if_state old_state = iface->state; 1047 char ifnamebuf[IF_NAMESIZE], *if_name; 1048 1049 iface->state = new_state; 1050 1051 switch (new_state) { 1052 case IF_DOWN: 1053 switch (old_state) { 1054 case IF_RENEWING: 1055 case IF_REBINDING: 1056 case IF_REBOOTING: 1057 case IF_BOUND: 1058 deprecate_interfaces(iface); 1059 break; 1060 default: 1061 break; 1062 } 1063 /* 1064 * Nothing else to do until iface comes up. 1065 * IP addresses will expire. 1066 */ 1067 iface->timo.tv_sec = -1; 1068 break; 1069 case IF_INIT: 1070 switch (old_state) { 1071 case IF_INIT: 1072 if (iface->timo.tv_sec < MAX_EXP_BACKOFF_SLOW) 1073 iface->timo.tv_sec *= 2; 1074 break; 1075 case IF_REQUESTING: 1076 case IF_RENEWING: 1077 case IF_REBINDING: 1078 case IF_REBOOTING: 1079 /* lease expired, got DHCPNAK or timeout: delete IP */ 1080 deconfigure_interfaces(iface); 1081 /* fall through */ 1082 case IF_DOWN: 1083 iface->timo.tv_sec = START_EXP_BACKOFF; 1084 clock_gettime(CLOCK_MONOTONIC, 1085 &iface->elapsed_time_start); 1086 break; 1087 case IF_BOUND: 1088 fatal("invalid transition Bound -> Init"); 1089 break; 1090 } 1091 request_dhcp_discover(iface); 1092 break; 1093 case IF_REBOOTING: 1094 if (old_state == IF_REBOOTING) 1095 iface->timo.tv_sec *= 2; 1096 else { 1097 iface->timo.tv_sec = START_EXP_BACKOFF; 1098 arc4random_buf(iface->xid, sizeof(iface->xid)); 1099 } 1100 request_dhcp_request(iface); 1101 break; 1102 case IF_REQUESTING: 1103 if (old_state == IF_REQUESTING) 1104 iface->timo.tv_sec *= 2; 1105 else { 1106 iface->timo.tv_sec = START_EXP_BACKOFF; 1107 clock_gettime(CLOCK_MONOTONIC, 1108 &iface->elapsed_time_start); 1109 } 1110 request_dhcp_request(iface); 1111 break; 1112 case IF_BOUND: 1113 iface->timo.tv_sec = iface->t1; 1114 switch (old_state) { 1115 case IF_REQUESTING: 1116 case IF_RENEWING: 1117 case IF_REBINDING: 1118 case IF_REBOOTING: 1119 configure_interfaces(iface); 1120 break; 1121 case IF_INIT: 1122 if (engine_conf->rapid_commit) 1123 configure_interfaces(iface); 1124 else 1125 fatal("invalid transition Init -> Bound"); 1126 break; 1127 default: 1128 break; 1129 } 1130 break; 1131 case IF_RENEWING: 1132 if (old_state == IF_BOUND) { 1133 iface->timo.tv_sec = (iface->t2 - 1134 iface->t1) / 2; /* RFC 2131 4.4.5 */ 1135 arc4random_buf(iface->xid, sizeof(iface->xid)); 1136 } else 1137 iface->timo.tv_sec /= 2; 1138 1139 if (iface->timo.tv_sec < 60) 1140 iface->timo.tv_sec = 60; 1141 request_dhcp_request(iface); 1142 break; 1143 case IF_REBINDING: 1144 if (old_state == IF_RENEWING) { 1145 iface->timo.tv_sec = (iface->lease_time - 1146 iface->t2) / 2; /* RFC 2131 4.4.5 */ 1147 } else 1148 iface->timo.tv_sec /= 2; 1149 request_dhcp_request(iface); 1150 break; 1151 } 1152 1153 if_name = if_indextoname(iface->if_index, ifnamebuf); 1154 log_debug("%s[%s] %s -> %s, timo: %lld", __func__, if_name == NULL ? 1155 "?" : if_name, if_state_name[old_state], if_state_name[new_state], 1156 iface->timo.tv_sec); 1157 1158 if (iface->timo.tv_sec == -1) { 1159 if (evtimer_pending(&iface->timer, NULL)) 1160 evtimer_del(&iface->timer); 1161 } else 1162 evtimer_add(&iface->timer, &iface->timo); 1163 } 1164 1165 void 1166 iface_timeout(int fd, short events, void *arg) 1167 { 1168 struct dhcp6leased_iface *iface = (struct dhcp6leased_iface *)arg; 1169 struct timespec now, res; 1170 1171 log_debug("%s[%d]: %s", __func__, iface->if_index, 1172 if_state_name[iface->state]); 1173 1174 switch (iface->state) { 1175 case IF_DOWN: 1176 state_transition(iface, IF_DOWN); 1177 break; 1178 case IF_INIT: 1179 state_transition(iface, IF_INIT); 1180 break; 1181 case IF_REBOOTING: 1182 if (iface->timo.tv_sec >= MAX_EXP_BACKOFF_FAST) 1183 state_transition(iface, IF_INIT); 1184 else 1185 state_transition(iface, IF_REBOOTING); 1186 break; 1187 case IF_REQUESTING: 1188 if (iface->timo.tv_sec >= MAX_EXP_BACKOFF_SLOW) 1189 state_transition(iface, IF_INIT); 1190 else 1191 state_transition(iface, IF_REQUESTING); 1192 break; 1193 case IF_BOUND: 1194 state_transition(iface, IF_RENEWING); 1195 break; 1196 case IF_RENEWING: 1197 clock_gettime(CLOCK_MONOTONIC, &now); 1198 timespecsub(&now, &iface->request_time, &res); 1199 log_debug("%s: res.tv_sec: %lld, t2: %u", __func__, 1200 res.tv_sec, iface->t2); 1201 if (res.tv_sec >= iface->t2) 1202 state_transition(iface, IF_REBINDING); 1203 else 1204 state_transition(iface, IF_RENEWING); 1205 break; 1206 case IF_REBINDING: 1207 clock_gettime(CLOCK_MONOTONIC, &now); 1208 timespecsub(&now, &iface->request_time, &res); 1209 log_debug("%s: res.tv_sec: %lld, lease_time: %u", __func__, 1210 res.tv_sec, iface->lease_time); 1211 if (res.tv_sec > iface->lease_time) 1212 state_transition(iface, IF_INIT); 1213 else 1214 state_transition(iface, IF_REBINDING); 1215 break; 1216 } 1217 } 1218 1219 /* XXX can this be merged into dhcp_request()? */ 1220 void 1221 request_dhcp_discover(struct dhcp6leased_iface *iface) 1222 { 1223 struct imsg_req_dhcp imsg; 1224 struct timespec now, res; 1225 1226 memset(&imsg, 0, sizeof(imsg)); 1227 imsg.if_index = iface->if_index; 1228 memcpy(imsg.xid, iface->xid, sizeof(imsg.xid)); 1229 clock_gettime(CLOCK_MONOTONIC, &now); 1230 timespecsub(&now, &iface->elapsed_time_start, &res); 1231 if (res.tv_sec * 100 > 0xffff) 1232 imsg.elapsed_time = 0xffff; 1233 else 1234 imsg.elapsed_time = res.tv_sec * 100; 1235 engine_imsg_compose_frontend(IMSG_SEND_SOLICIT, 0, &imsg, sizeof(imsg)); 1236 } 1237 1238 void 1239 request_dhcp_request(struct dhcp6leased_iface *iface) 1240 { 1241 struct imsg_req_dhcp imsg; 1242 struct timespec now, res; 1243 1244 memset(&imsg, 0, sizeof(imsg)); 1245 imsg.if_index = iface->if_index; 1246 memcpy(imsg.xid, iface->xid, sizeof(imsg.xid)); 1247 1248 clock_gettime(CLOCK_MONOTONIC, &now); 1249 timespecsub(&now, &iface->elapsed_time_start, &res); 1250 if (res.tv_sec * 100 > 0xffff) 1251 imsg.elapsed_time = 0xffff; 1252 else 1253 imsg.elapsed_time = res.tv_sec * 100; 1254 1255 switch (iface->state) { 1256 case IF_DOWN: 1257 fatalx("invalid state IF_DOWN in %s", __func__); 1258 break; 1259 case IF_INIT: 1260 fatalx("invalid state IF_INIT in %s", __func__); 1261 break; 1262 case IF_BOUND: 1263 fatalx("invalid state IF_BOUND in %s", __func__); 1264 break; 1265 case IF_REBOOTING: 1266 case IF_REQUESTING: 1267 case IF_RENEWING: 1268 case IF_REBINDING: 1269 imsg.serverid_len = iface->serverid_len; 1270 memcpy(imsg.serverid, iface->serverid, SERVERID_SIZE); 1271 memcpy(imsg.pds, iface->pds, sizeof(iface->pds)); 1272 break; 1273 } 1274 switch (iface->state) { 1275 case IF_REQUESTING: 1276 engine_imsg_compose_frontend(IMSG_SEND_REQUEST, 0, &imsg, 1277 sizeof(imsg)); 1278 break; 1279 case IF_RENEWING: 1280 engine_imsg_compose_frontend(IMSG_SEND_RENEW, 0, &imsg, 1281 sizeof(imsg)); 1282 break; 1283 case IF_REBOOTING: 1284 case IF_REBINDING: 1285 engine_imsg_compose_frontend(IMSG_SEND_REBIND, 0, &imsg, 1286 sizeof(imsg)); 1287 break; 1288 default: 1289 fatalx("%s: wrong state", __func__); 1290 } 1291 } 1292 1293 /* XXX we need to install a reject route for the delegated prefix */ 1294 void 1295 configure_interfaces(struct dhcp6leased_iface *iface) 1296 { 1297 struct iface_conf *iface_conf; 1298 struct iface_ia_conf *ia_conf; 1299 struct iface_pd_conf *pd_conf; 1300 struct imsg_lease_info imsg_lease_info; 1301 uint32_t i; 1302 char ntopbuf[INET6_ADDRSTRLEN]; 1303 char ifnamebuf[IF_NAMESIZE], *if_name; 1304 1305 if ((if_name = if_indextoname(iface->if_index, ifnamebuf)) == NULL) { 1306 log_debug("%s: unknown interface %d", __func__, 1307 iface->if_index); 1308 return; 1309 } 1310 if ((iface_conf = find_iface_conf(&engine_conf->iface_list, if_name)) 1311 == NULL) { 1312 log_debug("%s: no interface configuration for %d", __func__, 1313 iface->if_index); 1314 return; 1315 } 1316 1317 for (i = 0; i < iface_conf->ia_count; i++) { 1318 struct prefix *pd = &iface->new_pds[i]; 1319 1320 log_info("prefix delegation #%d %s/%d received on %s from " 1321 "server %s", i, inet_ntop(AF_INET6, &pd->prefix, ntopbuf, 1322 INET6_ADDRSTRLEN), pd->prefix_len, if_name, 1323 dhcp_duid2str(iface->serverid_len, iface->serverid)); 1324 } 1325 1326 SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) { 1327 struct prefix *pd = &iface->new_pds[ia_conf->id]; 1328 1329 SIMPLEQ_FOREACH(pd_conf, &ia_conf->iface_pd_list, entry) { 1330 send_reconfigure_interface(pd_conf, pd, CONFIGURE); 1331 } 1332 } 1333 1334 if (prefixcmp(iface->pds, iface->new_pds, iface_conf->ia_count) != 0) { 1335 log_info("Prefix delegations on %s from server %s changed", 1336 if_name, dhcp_duid2str(iface->serverid_len, 1337 iface->serverid)); 1338 for (i = 0; i < iface_conf->ia_count; i++) { 1339 log_debug("%s: iface->pds [%d]: %s/%d", __func__, i, 1340 inet_ntop(AF_INET6, &iface->pds[i].prefix, ntopbuf, 1341 INET6_ADDRSTRLEN), iface->pds[i].prefix_len); 1342 log_debug("%s: pds [%d]: %s/%d", __func__, i, 1343 inet_ntop(AF_INET6, &iface->new_pds[i].prefix, 1344 ntopbuf, INET6_ADDRSTRLEN), 1345 iface->new_pds[i].prefix_len); 1346 } 1347 deconfigure_interfaces(iface); 1348 } 1349 1350 memcpy(iface->pds, iface->new_pds, sizeof(iface->pds)); 1351 memset(iface->new_pds, 0, sizeof(iface->new_pds)); 1352 1353 memset(&imsg_lease_info, 0, sizeof(imsg_lease_info)); 1354 imsg_lease_info.if_index = iface->if_index; 1355 memcpy(imsg_lease_info.pds, iface->pds, sizeof(iface->pds)); 1356 engine_imsg_compose_main(IMSG_WRITE_LEASE, 0, &imsg_lease_info, 1357 sizeof(imsg_lease_info)); 1358 } 1359 1360 void 1361 deconfigure_interfaces(struct dhcp6leased_iface *iface) 1362 { 1363 struct iface_conf *iface_conf; 1364 struct iface_ia_conf *ia_conf; 1365 struct iface_pd_conf *pd_conf; 1366 uint32_t i; 1367 char ntopbuf[INET6_ADDRSTRLEN]; 1368 char ifnamebuf[IF_NAMESIZE], *if_name; 1369 1370 1371 if ((if_name = if_indextoname(iface->if_index, ifnamebuf)) == NULL) { 1372 log_debug("%s: unknown interface %d", __func__, 1373 iface->if_index); 1374 return; 1375 } 1376 if ((iface_conf = find_iface_conf(&engine_conf->iface_list, if_name)) 1377 == NULL) { 1378 log_debug("%s: no interface configuration for %d", __func__, 1379 iface->if_index); 1380 return; 1381 } 1382 1383 for (i = 0; i < iface_conf->ia_count; i++) { 1384 struct prefix *pd = &iface->pds[i]; 1385 1386 log_info("Prefix delegation #%d %s/%d expired on %s from " 1387 "server %s", i, inet_ntop(AF_INET6, &pd->prefix, ntopbuf, 1388 INET6_ADDRSTRLEN), pd->prefix_len, if_name, 1389 dhcp_duid2str(iface->serverid_len, iface->serverid)); 1390 } 1391 1392 SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) { 1393 struct prefix *pd = &iface->pds[ia_conf->id]; 1394 1395 SIMPLEQ_FOREACH(pd_conf, &ia_conf->iface_pd_list, entry) { 1396 send_reconfigure_interface(pd_conf, pd, DECONFIGURE); 1397 } 1398 } 1399 memset(iface->pds, 0, sizeof(iface->pds)); 1400 } 1401 1402 void 1403 deprecate_interfaces(struct dhcp6leased_iface *iface) 1404 { 1405 struct iface_conf *iface_conf; 1406 struct iface_ia_conf *ia_conf; 1407 struct iface_pd_conf *pd_conf; 1408 struct timespec now, diff; 1409 uint32_t i; 1410 char ntopbuf[INET6_ADDRSTRLEN]; 1411 char ifnamebuf[IF_NAMESIZE], *if_name; 1412 1413 1414 if ((if_name = if_indextoname(iface->if_index, ifnamebuf)) == NULL) { 1415 log_debug("%s: unknown interface %d", __func__, 1416 iface->if_index); 1417 return; 1418 } 1419 if ((iface_conf = find_iface_conf(&engine_conf->iface_list, if_name)) 1420 == NULL) { 1421 log_debug("%s: no interface configuration for %d", __func__, 1422 iface->if_index); 1423 return; 1424 } 1425 1426 for (i = 0; i < iface_conf->ia_count; i++) { 1427 struct prefix *pd = &iface->pds[i]; 1428 1429 log_info("%s went down, deprecating prefix delegation #%d %s/%d" 1430 " from server %s", if_name, i, inet_ntop(AF_INET6, 1431 &pd->prefix, ntopbuf, INET6_ADDRSTRLEN), pd->prefix_len, 1432 dhcp_duid2str(iface->serverid_len, iface->serverid)); 1433 } 1434 1435 clock_gettime(CLOCK_MONOTONIC, &now); 1436 timespecsub(&now, &iface->request_time, &diff); 1437 1438 SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) { 1439 struct prefix *pd = &iface->pds[ia_conf->id]; 1440 1441 if (pd->vltime > diff.tv_sec) 1442 pd->vltime -= diff.tv_sec; 1443 else 1444 pd->vltime = 0; 1445 1446 pd->pltime = 0; 1447 1448 SIMPLEQ_FOREACH(pd_conf, &ia_conf->iface_pd_list, entry) { 1449 send_reconfigure_interface(pd_conf, pd, CONFIGURE); 1450 } 1451 } 1452 } 1453 1454 int 1455 prefixcmp(struct prefix *a, struct prefix *b, int count) 1456 { 1457 int i; 1458 1459 for (i = 0; i < count; i++) { 1460 if (a[i].prefix_len != b[i].prefix_len) 1461 return 1; 1462 if (memcmp(&a[i].prefix, &b[i].prefix, 1463 sizeof(struct in6_addr)) != 0) 1464 return 1; 1465 } 1466 return 0; 1467 } 1468 1469 void 1470 send_reconfigure_interface(struct iface_pd_conf *pd_conf, struct prefix *pd, 1471 enum reconfigure_action action) 1472 { 1473 struct imsg_configure_address address; 1474 uint32_t if_index; 1475 int i; 1476 char ntopbuf[INET6_ADDRSTRLEN]; 1477 1478 if (pd->prefix_len == 0) 1479 return; 1480 1481 if (strcmp(pd_conf->name, "reserve") == 0) 1482 return; 1483 1484 if ((if_index = if_nametoindex(pd_conf->name)) == 0) 1485 return; 1486 1487 memset(&address, 0, sizeof(address)); 1488 1489 address.if_index = if_index; 1490 address.addr.sin6_family = AF_INET6; 1491 address.addr.sin6_len = sizeof(address.addr); 1492 address.addr.sin6_addr = pd->prefix; 1493 1494 for (i = 0; i < 16; i++) 1495 address.addr.sin6_addr.s6_addr[i] |= 1496 pd_conf->prefix_mask.s6_addr[i]; 1497 1498 /* XXX make this configurable & use SOII */ 1499 address.addr.sin6_addr.s6_addr[15] |= 1; 1500 1501 in6_prefixlen2mask(&address.mask, pd_conf->prefix_len); 1502 1503 log_debug("%s: %s %s: %s/%d", __func__, pd_conf->name, 1504 reconfigure_action_name[action], inet_ntop(AF_INET6, 1505 &address.addr.sin6_addr, ntopbuf, INET6_ADDRSTRLEN), 1506 pd_conf->prefix_len); 1507 1508 address.vltime = pd->vltime; 1509 address.pltime = pd->pltime; 1510 1511 if (action == CONFIGURE) 1512 engine_imsg_compose_main(IMSG_CONFIGURE_ADDRESS, 0, &address, 1513 sizeof(address)); 1514 else 1515 engine_imsg_compose_main(IMSG_DECONFIGURE_ADDRESS, 0, &address, 1516 sizeof(address)); 1517 } 1518 1519 const char * 1520 dhcp_message_type2str(int type) 1521 { 1522 static char buf[sizeof("Unknown [255]")]; 1523 1524 switch (type) { 1525 case DHCPSOLICIT: 1526 return "DHCPSOLICIT"; 1527 case DHCPADVERTISE: 1528 return "DHCPADVERTISE"; 1529 case DHCPREQUEST: 1530 return "DHCPREQUEST"; 1531 case DHCPCONFIRM: 1532 return "DHCPCONFIRM"; 1533 case DHCPRENEW: 1534 return "DHCPRENEW"; 1535 case DHCPREBIND: 1536 return "DHCPREBIND"; 1537 case DHCPREPLY: 1538 return "DHCPREPLY"; 1539 case DHCPRELEASE: 1540 return "DHCPRELEASE"; 1541 case DHCPDECLINE: 1542 return "DHCPDECLINE"; 1543 case DHCPRECONFIGURE: 1544 return "DHCPRECONFIGURE"; 1545 case DHCPINFORMATIONREQUEST: 1546 return "DHCPINFORMATIONREQUEST"; 1547 case DHCPRELAYFORW: 1548 return "DHCPRELAYFORW"; 1549 case DHCPRELAYREPL: 1550 return "DHCPRELAYREPL"; 1551 default: 1552 snprintf(buf, sizeof(buf), "Unknown [%u]", type & 0xff); 1553 return buf; 1554 } 1555 } 1556 1557 const char * 1558 dhcp_option_type2str(int code) 1559 { 1560 static char buf[sizeof("Unknown [65535]")]; 1561 switch (code) { 1562 case DHO_CLIENTID: 1563 return "DHO_CLIENTID"; 1564 case DHO_SERVERID: 1565 return "DHO_SERVERID"; 1566 case DHO_ORO: 1567 return "DHO_ORO"; 1568 case DHO_ELAPSED_TIME: 1569 return "DHO_ELAPSED_TIME"; 1570 case DHO_STATUS_CODE: 1571 return "DHO_STATUS_CODE"; 1572 case DHO_RAPID_COMMIT: 1573 return "DHO_RAPID_COMMIT"; 1574 case DHO_VENDOR_CLASS: 1575 return "DHO_VENDOR_CLASS"; 1576 case DHO_IA_PD: 1577 return "DHO_IA_PD"; 1578 case DHO_IA_PREFIX: 1579 return "DHO_IA_PREFIX"; 1580 case DHO_SOL_MAX_RT: 1581 return "DHO_SOL_MAX_RT"; 1582 case DHO_INF_MAX_RT: 1583 return "DHO_INF_MAX_RT"; 1584 default: 1585 snprintf(buf, sizeof(buf), "Unknown [%u]", code &0xffff); 1586 return buf; 1587 } 1588 } 1589 1590 const char* 1591 dhcp_duid2str(int len, uint8_t *p) 1592 { 1593 static char buf[2 * 130]; 1594 int i, rem; 1595 char *pbuf; 1596 1597 if (len > 130) 1598 return "invalid"; 1599 1600 pbuf = buf; 1601 rem = sizeof(buf); 1602 for (i = 0; i < len && rem > 0; i++, pbuf += 2, rem -=2) 1603 snprintf(pbuf, rem, "%02x", p[i]); 1604 1605 return buf; 1606 } 1607 1608 const char* 1609 dhcp_status2str(int status) 1610 { 1611 static char buf[sizeof("Unknown [255]")]; 1612 1613 switch (status) { 1614 case DHCP_STATUS_SUCCESS: 1615 return "Success"; 1616 case DHCP_STATUS_UNSPECFAIL: 1617 return "UnspecFail"; 1618 case DHCP_STATUS_NOADDRSAVAIL: 1619 return "NoAddrsAvail"; 1620 case DHCP_STATUS_NOBINDING: 1621 return "NoBinding"; 1622 case DHCP_STATUS_NOTONLINK: 1623 return "NotOnLink"; 1624 case DHCP_STATUS_USEMULTICAST: 1625 return "UseMulticast"; 1626 case DHCP_STATUS_NOPREFIXAVAIL: 1627 return "NoPrefixAvail"; 1628 default: 1629 snprintf(buf, sizeof(buf), "Unknown [%u]", status & 0xff); 1630 return buf; 1631 } 1632 } 1633 1634 /* from sys/netinet6/in6.c */ 1635 /* 1636 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 1637 * All rights reserved. 1638 * 1639 * Redistribution and use in source and binary forms, with or without 1640 * modification, are permitted provided that the following conditions 1641 * are met: 1642 * 1. Redistributions of source code must retain the above copyright 1643 * notice, this list of conditions and the following disclaimer. 1644 * 2. Redistributions in binary form must reproduce the above copyright 1645 * notice, this list of conditions and the following disclaimer in the 1646 * documentation and/or other materials provided with the distribution. 1647 * 3. Neither the name of the project nor the names of its contributors 1648 * may be used to endorse or promote products derived from this software 1649 * without specific prior written permission. 1650 * 1651 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1652 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1653 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1654 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 1655 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1656 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1657 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1658 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1659 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1660 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1661 * SUCH DAMAGE. 1662 */ 1663 void 1664 in6_prefixlen2mask(struct in6_addr *maskp, int len) 1665 { 1666 u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; 1667 int bytelen, bitlen, i; 1668 1669 if (0 > len || len > 128) 1670 fatalx("%s: invalid prefix length(%d)\n", __func__, len); 1671 1672 bzero(maskp, sizeof(*maskp)); 1673 bytelen = len / 8; 1674 bitlen = len % 8; 1675 for (i = 0; i < bytelen; i++) 1676 maskp->s6_addr[i] = 0xff; 1677 /* len == 128 is ok because bitlen == 0 then */ 1678 if (bitlen) 1679 maskp->s6_addr[bytelen] = maskarray[bitlen - 1]; 1680 } 1681