1 /* $OpenBSD: engine.c,v 1.85 2023/04/30 13:08:40 phessler Exp $ */ 2 3 /* 4 * Copyright (c) 2017 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 /* 23 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 24 * All rights reserved. 25 * 26 * Redistribution and use in source and binary forms, with or without 27 * modification, are permitted provided that the following conditions 28 * are met: 29 * 1. Redistributions of source code must retain the above copyright 30 * notice, this list of conditions and the following disclaimer. 31 * 2. Redistributions in binary form must reproduce the above copyright 32 * notice, this list of conditions and the following disclaimer in the 33 * documentation and/or other materials provided with the distribution. 34 * 3. Neither the name of the project nor the names of its contributors 35 * may be used to endorse or promote products derived from this software 36 * without specific prior written permission. 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 41 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 */ 50 51 #include <sys/types.h> 52 #include <sys/queue.h> 53 #include <sys/socket.h> 54 #include <sys/syslog.h> 55 #include <sys/uio.h> 56 57 #include <net/if.h> 58 #include <net/route.h> 59 #include <arpa/inet.h> 60 #include <netinet/in.h> 61 #include <netinet/if_ether.h> 62 #include <netinet/ip6.h> 63 #include <netinet6/ip6_var.h> 64 #include <netinet6/nd6.h> 65 #include <netinet/icmp6.h> 66 67 #include <crypto/sha2.h> 68 69 #include <errno.h> 70 #include <event.h> 71 #include <imsg.h> 72 #include <pwd.h> 73 #include <signal.h> 74 #include <stddef.h> 75 #include <stdlib.h> 76 #include <string.h> 77 #include <time.h> 78 #include <unistd.h> 79 80 #include "log.h" 81 #include "slaacd.h" 82 #include "engine.h" 83 84 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 85 86 #define MAX_RTR_SOLICITATION_DELAY 1 87 #define MAX_RTR_SOLICITATION_DELAY_USEC MAX_RTR_SOLICITATION_DELAY * 1000000 88 #define RTR_SOLICITATION_INTERVAL 4 89 #define MAX_RTR_SOLICITATIONS 3 90 91 /* 92 * Constants for RFC 8981 temporary address extensions 93 * 94 * PRIV_PREFERRED_LIFETIME > (PRIV_MAX_DESYNC_FACTOR + PRIV_REGEN_ADVANCE) 95 */ 96 #define PRIV_VALID_LIFETIME 172800 /* 2 days */ 97 #define PRIV_PREFERRED_LIFETIME 86400 /* 1 day */ 98 #define PRIV_MAX_DESYNC_FACTOR 34560 /* PRIV_PREFERRED_LIFETIME * 0.4 */ 99 #define PRIV_REGEN_ADVANCE 5 /* 5 seconds */ 100 101 enum if_state { 102 IF_DOWN, 103 IF_INIT, 104 IF_BOUND, 105 }; 106 107 enum proposal_state { 108 PROPOSAL_IF_DOWN, 109 PROPOSAL_NOT_CONFIGURED, 110 PROPOSAL_CONFIGURED, 111 PROPOSAL_NEARLY_EXPIRED, 112 PROPOSAL_WITHDRAWN, 113 PROPOSAL_DUPLICATED, 114 PROPOSAL_STALE, 115 }; 116 117 const char* rpref_name[] = { 118 "Low", 119 "Medium", 120 "High", 121 }; 122 123 struct radv_prefix { 124 LIST_ENTRY(radv_prefix) entries; 125 struct in6_addr prefix; 126 uint8_t prefix_len; /*XXX int */ 127 int onlink; 128 int autonomous; 129 uint32_t vltime; 130 uint32_t pltime; 131 int dad_counter; 132 }; 133 134 struct radv_rdns { 135 LIST_ENTRY(radv_rdns) entries; 136 struct in6_addr rdns; 137 }; 138 139 struct radv { 140 LIST_ENTRY(radv) entries; 141 struct sockaddr_in6 from; 142 struct timespec when; 143 struct timespec uptime; 144 struct event timer; 145 uint32_t min_lifetime; 146 uint8_t curhoplimit; 147 int managed; 148 int other; 149 enum rpref rpref; 150 uint16_t router_lifetime; /* in seconds */ 151 uint32_t reachable_time; /* in milliseconds */ 152 uint32_t retrans_time; /* in milliseconds */ 153 LIST_HEAD(, radv_prefix) prefixes; 154 uint32_t rdns_lifetime; 155 LIST_HEAD(, radv_rdns) rdns_servers; 156 uint32_t mtu; 157 }; 158 159 struct address_proposal { 160 LIST_ENTRY(address_proposal) entries; 161 struct event timer; 162 int64_t id; 163 enum proposal_state state; 164 struct timeval timo; 165 struct timespec created; 166 struct timespec when; 167 struct timespec uptime; 168 uint32_t if_index; 169 struct ether_addr hw_address; 170 struct sockaddr_in6 from; 171 struct sockaddr_in6 addr; 172 struct in6_addr mask; 173 struct in6_addr prefix; 174 int temporary; 175 uint8_t prefix_len; 176 uint32_t vltime; 177 uint32_t pltime; 178 uint32_t desync_factor; 179 uint8_t soiikey[SLAACD_SOIIKEY_LEN]; 180 uint32_t mtu; 181 }; 182 183 struct dfr_proposal { 184 LIST_ENTRY(dfr_proposal) entries; 185 struct event timer; 186 int64_t id; 187 enum proposal_state state; 188 struct timeval timo; 189 struct timespec when; 190 struct timespec uptime; 191 uint32_t if_index; 192 int rdomain; 193 struct sockaddr_in6 addr; 194 uint32_t router_lifetime; 195 enum rpref rpref; 196 }; 197 198 struct rdns_proposal { 199 LIST_ENTRY(rdns_proposal) entries; 200 struct event timer; 201 int64_t id; 202 enum proposal_state state; 203 struct timeval timo; 204 struct timespec when; 205 struct timespec uptime; 206 uint32_t if_index; 207 int rdomain; 208 struct sockaddr_in6 from; 209 int rdns_count; 210 struct in6_addr rdns[MAX_RDNS_COUNT]; 211 uint32_t rdns_lifetime; 212 }; 213 214 struct slaacd_iface { 215 LIST_ENTRY(slaacd_iface) entries; 216 enum if_state state; 217 struct event timer; 218 struct timeval timo; 219 struct timespec last_sol; 220 int probes; 221 uint32_t if_index; 222 uint32_t rdomain; 223 int running; 224 int autoconf; 225 int temporary; 226 int soii; 227 struct ether_addr hw_address; 228 struct sockaddr_in6 ll_address; 229 uint8_t soiikey[SLAACD_SOIIKEY_LEN]; 230 int link_state; 231 uint32_t cur_mtu; 232 LIST_HEAD(, radv) radvs; 233 LIST_HEAD(, address_proposal) addr_proposals; 234 LIST_HEAD(, dfr_proposal) dfr_proposals; 235 LIST_HEAD(, rdns_proposal) rdns_proposals; 236 }; 237 238 LIST_HEAD(, slaacd_iface) slaacd_interfaces; 239 240 __dead void engine_shutdown(void); 241 void engine_sig_handler(int sig, short, void *); 242 void engine_dispatch_frontend(int, short, void *); 243 void engine_dispatch_main(int, short, void *); 244 #ifndef SMALL 245 void send_interface_info(struct slaacd_iface *, pid_t); 246 void engine_showinfo_ctl(struct imsg *, uint32_t); 247 void debug_log_ra(struct imsg_ra *); 248 int in6_mask2prefixlen(struct in6_addr *); 249 #endif /* SMALL */ 250 struct slaacd_iface *get_slaacd_iface_by_id(uint32_t); 251 void remove_slaacd_iface(uint32_t); 252 void free_ra(struct radv *); 253 void iface_state_transition(struct slaacd_iface *, enum 254 if_state); 255 void addr_proposal_state_transition(struct 256 address_proposal *, enum proposal_state); 257 void dfr_proposal_state_transition(struct dfr_proposal *, 258 enum proposal_state); 259 void rdns_proposal_state_transition(struct rdns_proposal *, 260 enum proposal_state); 261 void engine_update_iface(struct imsg_ifinfo *); 262 void request_solicitation(struct slaacd_iface *); 263 void parse_ra(struct slaacd_iface *, struct imsg_ra *); 264 void gen_addr(struct slaacd_iface *, struct radv_prefix *, 265 struct address_proposal *, int); 266 void gen_address_proposal(struct slaacd_iface *, struct 267 radv *, struct radv_prefix *, int); 268 void free_address_proposal(struct address_proposal *); 269 void withdraw_addr(struct address_proposal *); 270 void configure_address(struct address_proposal *); 271 void in6_prefixlen2mask(struct in6_addr *, int len); 272 void gen_dfr_proposal(struct slaacd_iface *, struct 273 radv *); 274 void configure_dfr(struct dfr_proposal *); 275 void free_dfr_proposal(struct dfr_proposal *); 276 void withdraw_dfr(struct dfr_proposal *); 277 void update_iface_ra_rdns(struct slaacd_iface *, 278 struct radv *); 279 void gen_rdns_proposal(struct slaacd_iface *, struct 280 radv *); 281 void free_rdns_proposal(struct rdns_proposal *); 282 void withdraw_rdns(struct rdns_proposal *); 283 void compose_rdns_proposal(uint32_t, int); 284 void update_iface_ra(struct slaacd_iface *, struct radv *); 285 void update_iface_ra_dfr(struct slaacd_iface *, 286 struct radv *); 287 void update_iface_ra_prefix(struct slaacd_iface *, 288 struct radv *, struct radv_prefix *prefix); 289 void address_proposal_timeout(int, short, void *); 290 void dfr_proposal_timeout(int, short, void *); 291 void rdns_proposal_timeout(int, short, void *); 292 void iface_timeout(int, short, void *); 293 struct radv *find_ra(struct slaacd_iface *, struct sockaddr_in6 *); 294 struct address_proposal *find_address_proposal_by_addr(struct slaacd_iface *, 295 struct sockaddr_in6 *); 296 struct dfr_proposal *find_dfr_proposal_by_gw(struct slaacd_iface *, 297 struct sockaddr_in6 *); 298 struct rdns_proposal *find_rdns_proposal_by_gw(struct slaacd_iface *, 299 struct sockaddr_in6 *); 300 struct radv_prefix *find_prefix(struct radv *, struct in6_addr *, uint8_t); 301 int engine_imsg_compose_main(int, pid_t, void *, uint16_t); 302 uint32_t real_lifetime(struct timespec *, uint32_t); 303 void merge_dad_couters(struct radv *, struct radv *); 304 305 static struct imsgev *iev_frontend; 306 static struct imsgev *iev_main; 307 int64_t proposal_id; 308 309 310 #define CASE(x) case x : return #x 311 312 #ifndef SMALL 313 static const char* 314 if_state_name(enum if_state ifs) 315 { 316 switch (ifs) { 317 CASE(IF_DOWN); 318 CASE(IF_INIT); 319 CASE(IF_BOUND); 320 } 321 } 322 323 static const char* 324 proposal_state_name(enum proposal_state ps) 325 { 326 switch (ps) { 327 CASE(PROPOSAL_IF_DOWN); 328 CASE(PROPOSAL_NOT_CONFIGURED); 329 CASE(PROPOSAL_CONFIGURED); 330 CASE(PROPOSAL_NEARLY_EXPIRED); 331 CASE(PROPOSAL_WITHDRAWN); 332 CASE(PROPOSAL_DUPLICATED); 333 CASE(PROPOSAL_STALE); 334 } 335 } 336 #endif 337 338 void 339 engine_sig_handler(int sig, short event, void *arg) 340 { 341 /* 342 * Normal signal handler rules don't apply because libevent 343 * decouples for us. 344 */ 345 346 switch (sig) { 347 case SIGINT: 348 case SIGTERM: 349 engine_shutdown(); 350 default: 351 fatalx("unexpected signal"); 352 } 353 } 354 355 void 356 engine(int debug, int verbose) 357 { 358 struct event ev_sigint, ev_sigterm; 359 struct passwd *pw; 360 361 log_init(debug, LOG_DAEMON); 362 log_setverbose(verbose); 363 364 if ((pw = getpwnam(SLAACD_USER)) == NULL) 365 fatal("getpwnam"); 366 367 if (chdir("/") == -1) 368 fatal("chdir(\"/\")"); 369 370 if (unveil("/", "") == -1) 371 fatal("unveil /"); 372 if (unveil(NULL, NULL) == -1) 373 fatal("unveil"); 374 375 setproctitle("%s", "engine"); 376 log_procinit("engine"); 377 378 if (setgroups(1, &pw->pw_gid) || 379 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 380 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 381 fatal("can't drop privileges"); 382 383 if (pledge("stdio recvfd", NULL) == -1) 384 fatal("pledge"); 385 386 event_init(); 387 388 /* Setup signal handler(s). */ 389 signal_set(&ev_sigint, SIGINT, engine_sig_handler, NULL); 390 signal_set(&ev_sigterm, SIGTERM, engine_sig_handler, NULL); 391 signal_add(&ev_sigint, NULL); 392 signal_add(&ev_sigterm, NULL); 393 signal(SIGPIPE, SIG_IGN); 394 signal(SIGHUP, SIG_IGN); 395 396 /* Setup pipe and event handler to the main process. */ 397 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 398 fatal(NULL); 399 400 imsg_init(&iev_main->ibuf, 3); 401 iev_main->handler = engine_dispatch_main; 402 403 /* Setup event handlers. */ 404 iev_main->events = EV_READ; 405 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 406 iev_main->handler, iev_main); 407 event_add(&iev_main->ev, NULL); 408 409 LIST_INIT(&slaacd_interfaces); 410 411 event_dispatch(); 412 413 engine_shutdown(); 414 } 415 416 __dead void 417 engine_shutdown(void) 418 { 419 /* Close pipes. */ 420 msgbuf_clear(&iev_frontend->ibuf.w); 421 close(iev_frontend->ibuf.fd); 422 msgbuf_clear(&iev_main->ibuf.w); 423 close(iev_main->ibuf.fd); 424 425 free(iev_frontend); 426 free(iev_main); 427 428 log_info("engine exiting"); 429 exit(0); 430 } 431 432 int 433 engine_imsg_compose_frontend(int type, pid_t pid, void *data, 434 uint16_t datalen) 435 { 436 return (imsg_compose_event(iev_frontend, type, 0, pid, -1, 437 data, datalen)); 438 } 439 440 int 441 engine_imsg_compose_main(int type, pid_t pid, void *data, 442 uint16_t datalen) 443 { 444 return (imsg_compose_event(iev_main, type, 0, pid, -1, 445 data, datalen)); 446 } 447 448 void 449 engine_dispatch_frontend(int fd, short event, void *bula) 450 { 451 struct imsgev *iev = bula; 452 struct imsgbuf *ibuf = &iev->ibuf; 453 struct imsg imsg; 454 struct slaacd_iface *iface; 455 struct imsg_ra ra; 456 struct address_proposal *addr_proposal = NULL; 457 struct dfr_proposal *dfr_proposal = NULL; 458 struct imsg_del_addr del_addr; 459 struct imsg_del_route del_route; 460 struct imsg_dup_addr dup_addr; 461 ssize_t n; 462 int shut = 0; 463 #ifndef SMALL 464 int verbose; 465 #endif /* SMALL */ 466 uint32_t if_index; 467 468 if (event & EV_READ) { 469 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 470 fatal("imsg_read error"); 471 if (n == 0) /* Connection closed. */ 472 shut = 1; 473 } 474 if (event & EV_WRITE) { 475 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 476 fatal("msgbuf_write"); 477 if (n == 0) /* Connection closed. */ 478 shut = 1; 479 } 480 481 for (;;) { 482 if ((n = imsg_get(ibuf, &imsg)) == -1) 483 fatal("%s: imsg_get error", __func__); 484 if (n == 0) /* No more messages. */ 485 break; 486 487 switch (imsg.hdr.type) { 488 #ifndef SMALL 489 case IMSG_CTL_LOG_VERBOSE: 490 if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 491 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 492 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 493 memcpy(&verbose, imsg.data, sizeof(verbose)); 494 log_setverbose(verbose); 495 break; 496 case IMSG_CTL_SHOW_INTERFACE_INFO: 497 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 498 fatalx("%s: IMSG_CTL_SHOW_INTERFACE_INFO wrong " 499 "length: %lu", __func__, 500 IMSG_DATA_SIZE(imsg)); 501 memcpy(&if_index, imsg.data, sizeof(if_index)); 502 engine_showinfo_ctl(&imsg, if_index); 503 break; 504 #endif /* SMALL */ 505 case IMSG_REMOVE_IF: 506 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 507 fatalx("%s: IMSG_REMOVE_IF wrong length: %lu", 508 __func__, IMSG_DATA_SIZE(imsg)); 509 memcpy(&if_index, imsg.data, sizeof(if_index)); 510 remove_slaacd_iface(if_index); 511 break; 512 case IMSG_RA: 513 if (IMSG_DATA_SIZE(imsg) != sizeof(ra)) 514 fatalx("%s: IMSG_RA wrong length: %lu", 515 __func__, IMSG_DATA_SIZE(imsg)); 516 memcpy(&ra, imsg.data, sizeof(ra)); 517 iface = get_slaacd_iface_by_id(ra.if_index); 518 519 /* 520 * Ignore unsolicitated router advertisements 521 * if we think the interface is still down. 522 * Otherwise we confuse the state machine. 523 */ 524 if (iface != NULL && iface->state != IF_DOWN) 525 parse_ra(iface, &ra); 526 break; 527 case IMSG_CTL_SEND_SOLICITATION: 528 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 529 fatalx("%s: IMSG_CTL_SEND_SOLICITATION wrong " 530 "length: %lu", __func__, 531 IMSG_DATA_SIZE(imsg)); 532 memcpy(&if_index, imsg.data, sizeof(if_index)); 533 iface = get_slaacd_iface_by_id(if_index); 534 if (iface == NULL) 535 log_warnx("requested to send solicitation on " 536 "non-autoconf interface: %u", if_index); 537 else { 538 iface->last_sol.tv_sec = 0; /* no rate limit */ 539 request_solicitation(iface); 540 } 541 break; 542 case IMSG_DEL_ADDRESS: 543 if (IMSG_DATA_SIZE(imsg) != sizeof(del_addr)) 544 fatalx("%s: IMSG_DEL_ADDRESS wrong length: %lu", 545 __func__, IMSG_DATA_SIZE(imsg)); 546 memcpy(&del_addr, imsg.data, sizeof(del_addr)); 547 iface = get_slaacd_iface_by_id(del_addr.if_index); 548 if (iface == NULL) { 549 log_debug("IMSG_DEL_ADDRESS: unknown interface" 550 ", ignoring"); 551 break; 552 } 553 554 addr_proposal = find_address_proposal_by_addr(iface, 555 &del_addr.addr); 556 /* 557 * If it's in state PROPOSAL_WITHDRAWN we just 558 * deleted it ourself but want to keep it around 559 * so we can renew it 560 */ 561 if (addr_proposal && addr_proposal->state != 562 PROPOSAL_WITHDRAWN) 563 free_address_proposal(addr_proposal); 564 break; 565 case IMSG_DEL_ROUTE: 566 if (IMSG_DATA_SIZE(imsg) != sizeof(del_route)) 567 fatalx("%s: IMSG_DEL_ROUTE wrong length: %lu", 568 __func__, IMSG_DATA_SIZE(imsg)); 569 memcpy(&del_route, imsg.data, sizeof(del_route)); 570 iface = get_slaacd_iface_by_id(del_route.if_index); 571 if (iface == NULL) { 572 log_debug("IMSG_DEL_ROUTE: unknown interface" 573 ", ignoring"); 574 break; 575 } 576 577 dfr_proposal = find_dfr_proposal_by_gw(iface, 578 &del_route.gw); 579 580 if (dfr_proposal) { 581 dfr_proposal->state = PROPOSAL_WITHDRAWN; 582 free_dfr_proposal(dfr_proposal); 583 } 584 break; 585 case IMSG_DUP_ADDRESS: 586 if (IMSG_DATA_SIZE(imsg) != sizeof(dup_addr)) 587 fatalx("%s: IMSG_DUP_ADDRESS wrong length: %lu", 588 __func__, IMSG_DATA_SIZE(imsg)); 589 memcpy(&dup_addr, imsg.data, sizeof(dup_addr)); 590 iface = get_slaacd_iface_by_id(dup_addr.if_index); 591 if (iface == NULL) { 592 log_debug("IMSG_DUP_ADDRESS: unknown interface" 593 ", ignoring"); 594 break; 595 } 596 597 addr_proposal = find_address_proposal_by_addr(iface, 598 &dup_addr.addr); 599 600 if (addr_proposal) 601 addr_proposal_state_transition(addr_proposal, 602 PROPOSAL_DUPLICATED); 603 break; 604 case IMSG_REPROPOSE_RDNS: 605 LIST_FOREACH (iface, &slaacd_interfaces, entries) 606 compose_rdns_proposal(iface->if_index, 607 iface->rdomain); 608 break; 609 default: 610 log_debug("%s: unexpected imsg %d", __func__, 611 imsg.hdr.type); 612 break; 613 } 614 imsg_free(&imsg); 615 } 616 if (!shut) 617 imsg_event_add(iev); 618 else { 619 /* This pipe is dead. Remove its event handler. */ 620 event_del(&iev->ev); 621 event_loopexit(NULL); 622 } 623 } 624 625 void 626 engine_dispatch_main(int fd, short event, void *bula) 627 { 628 struct imsg imsg; 629 struct imsgev *iev = bula; 630 struct imsgbuf *ibuf = &iev->ibuf; 631 struct imsg_ifinfo imsg_ifinfo; 632 ssize_t n; 633 int shut = 0; 634 635 if (event & EV_READ) { 636 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 637 fatal("imsg_read error"); 638 if (n == 0) /* Connection closed. */ 639 shut = 1; 640 } 641 if (event & EV_WRITE) { 642 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 643 fatal("msgbuf_write"); 644 if (n == 0) /* Connection closed. */ 645 shut = 1; 646 } 647 648 for (;;) { 649 if ((n = imsg_get(ibuf, &imsg)) == -1) 650 fatal("%s: imsg_get error", __func__); 651 if (n == 0) /* No more messages. */ 652 break; 653 654 switch (imsg.hdr.type) { 655 case IMSG_SOCKET_IPC: 656 /* 657 * Setup pipe and event handler to the frontend 658 * process. 659 */ 660 if (iev_frontend) 661 fatalx("%s: received unexpected imsg fd " 662 "to engine", __func__); 663 664 if ((fd = imsg.fd) == -1) 665 fatalx("%s: expected to receive imsg fd to " 666 "engine but didn't receive any", __func__); 667 668 iev_frontend = malloc(sizeof(struct imsgev)); 669 if (iev_frontend == NULL) 670 fatal(NULL); 671 672 imsg_init(&iev_frontend->ibuf, fd); 673 iev_frontend->handler = engine_dispatch_frontend; 674 iev_frontend->events = EV_READ; 675 676 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 677 iev_frontend->events, iev_frontend->handler, 678 iev_frontend); 679 event_add(&iev_frontend->ev, NULL); 680 681 if (pledge("stdio", NULL) == -1) 682 fatal("pledge"); 683 break; 684 case IMSG_UPDATE_IF: 685 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_ifinfo)) 686 fatalx("%s: IMSG_UPDATE_IF wrong length: %lu", 687 __func__, IMSG_DATA_SIZE(imsg)); 688 memcpy(&imsg_ifinfo, imsg.data, sizeof(imsg_ifinfo)); 689 engine_update_iface(&imsg_ifinfo); 690 break; 691 default: 692 log_debug("%s: unexpected imsg %d", __func__, 693 imsg.hdr.type); 694 break; 695 } 696 imsg_free(&imsg); 697 } 698 if (!shut) 699 imsg_event_add(iev); 700 else { 701 /* This pipe is dead. Remove its event handler. */ 702 event_del(&iev->ev); 703 event_loopexit(NULL); 704 } 705 } 706 707 #ifndef SMALL 708 void 709 send_interface_info(struct slaacd_iface *iface, pid_t pid) 710 { 711 struct ctl_engine_info cei; 712 struct ctl_engine_info_ra cei_ra; 713 struct ctl_engine_info_ra_prefix cei_ra_prefix; 714 struct ctl_engine_info_ra_rdns cei_ra_rdns; 715 struct ctl_engine_info_address_proposal cei_addr_proposal; 716 struct ctl_engine_info_dfr_proposal cei_dfr_proposal; 717 struct ctl_engine_info_rdns_proposal cei_rdns_proposal; 718 struct radv *ra; 719 struct radv_prefix *prefix; 720 struct radv_rdns *rdns; 721 struct address_proposal *addr_proposal; 722 struct dfr_proposal *dfr_proposal; 723 struct rdns_proposal *rdns_proposal; 724 725 memset(&cei, 0, sizeof(cei)); 726 cei.if_index = iface->if_index; 727 cei.running = iface->running; 728 cei.autoconf = iface->autoconf; 729 cei.temporary = iface->temporary; 730 cei.soii = iface->soii; 731 memcpy(&cei.hw_address, &iface->hw_address, sizeof(struct ether_addr)); 732 memcpy(&cei.ll_address, &iface->ll_address, 733 sizeof(struct sockaddr_in6)); 734 engine_imsg_compose_frontend(IMSG_CTL_SHOW_INTERFACE_INFO, pid, &cei, 735 sizeof(cei)); 736 LIST_FOREACH(ra, &iface->radvs, entries) { 737 memset(&cei_ra, 0, sizeof(cei_ra)); 738 memcpy(&cei_ra.from, &ra->from, sizeof(cei_ra.from)); 739 memcpy(&cei_ra.when, &ra->when, sizeof(cei_ra.when)); 740 memcpy(&cei_ra.uptime, &ra->uptime, sizeof(cei_ra.uptime)); 741 cei_ra.curhoplimit = ra->curhoplimit; 742 cei_ra.managed = ra->managed; 743 cei_ra.other = ra->other; 744 if (strlcpy(cei_ra.rpref, rpref_name[ra->rpref], sizeof( 745 cei_ra.rpref)) >= sizeof(cei_ra.rpref)) 746 log_warnx("truncated router preference"); 747 cei_ra.router_lifetime = ra->router_lifetime; 748 cei_ra.reachable_time = ra->reachable_time; 749 cei_ra.retrans_time = ra->retrans_time; 750 cei_ra.mtu = ra->mtu; 751 engine_imsg_compose_frontend(IMSG_CTL_SHOW_INTERFACE_INFO_RA, 752 pid, &cei_ra, sizeof(cei_ra)); 753 754 LIST_FOREACH(prefix, &ra->prefixes, entries) { 755 memset(&cei_ra_prefix, 0, sizeof(cei_ra_prefix)); 756 757 cei_ra_prefix.prefix = prefix->prefix; 758 cei_ra_prefix.prefix_len = prefix->prefix_len; 759 cei_ra_prefix.onlink = prefix->onlink; 760 cei_ra_prefix.autonomous = prefix->autonomous; 761 cei_ra_prefix.vltime = prefix->vltime; 762 cei_ra_prefix.pltime = prefix->pltime; 763 engine_imsg_compose_frontend( 764 IMSG_CTL_SHOW_INTERFACE_INFO_RA_PREFIX, pid, 765 &cei_ra_prefix, sizeof(cei_ra_prefix)); 766 } 767 768 LIST_FOREACH(rdns, &ra->rdns_servers, entries) { 769 memset(&cei_ra_rdns, 0, sizeof(cei_ra_rdns)); 770 memcpy(&cei_ra_rdns.rdns, &rdns->rdns, 771 sizeof(cei_ra_rdns.rdns)); 772 cei_ra_rdns.lifetime = ra->rdns_lifetime; 773 engine_imsg_compose_frontend( 774 IMSG_CTL_SHOW_INTERFACE_INFO_RA_RDNS, pid, 775 &cei_ra_rdns, sizeof(cei_ra_rdns)); 776 } 777 } 778 779 if (!LIST_EMPTY(&iface->addr_proposals)) 780 engine_imsg_compose_frontend( 781 IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSALS, pid, NULL, 0); 782 783 LIST_FOREACH(addr_proposal, &iface->addr_proposals, entries) { 784 memset(&cei_addr_proposal, 0, sizeof(cei_addr_proposal)); 785 cei_addr_proposal.id = addr_proposal->id; 786 if(strlcpy(cei_addr_proposal.state, 787 proposal_state_name(addr_proposal->state), 788 sizeof(cei_addr_proposal.state)) >= 789 sizeof(cei_addr_proposal.state)) 790 log_warnx("truncated state name"); 791 cei_addr_proposal.next_timeout = addr_proposal->timo.tv_sec; 792 cei_addr_proposal.when = addr_proposal->when; 793 cei_addr_proposal.uptime = addr_proposal->uptime; 794 memcpy(&cei_addr_proposal.addr, &addr_proposal->addr, sizeof( 795 cei_addr_proposal.addr)); 796 memcpy(&cei_addr_proposal.prefix, &addr_proposal->prefix, 797 sizeof(cei_addr_proposal.prefix)); 798 cei_addr_proposal.prefix_len = addr_proposal->prefix_len; 799 cei_addr_proposal.temporary = addr_proposal->temporary; 800 cei_addr_proposal.vltime = addr_proposal->vltime; 801 cei_addr_proposal.pltime = addr_proposal->pltime; 802 803 engine_imsg_compose_frontend( 804 IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSAL, pid, 805 &cei_addr_proposal, sizeof(cei_addr_proposal)); 806 } 807 808 if (!LIST_EMPTY(&iface->dfr_proposals)) 809 engine_imsg_compose_frontend( 810 IMSG_CTL_SHOW_INTERFACE_INFO_DFR_PROPOSALS, pid, NULL, 0); 811 812 LIST_FOREACH(dfr_proposal, &iface->dfr_proposals, entries) { 813 memset(&cei_dfr_proposal, 0, sizeof(cei_dfr_proposal)); 814 cei_dfr_proposal.id = dfr_proposal->id; 815 if(strlcpy(cei_dfr_proposal.state, 816 proposal_state_name(dfr_proposal->state), 817 sizeof(cei_dfr_proposal.state)) >= 818 sizeof(cei_dfr_proposal.state)) 819 log_warnx("truncated state name"); 820 cei_dfr_proposal.next_timeout = dfr_proposal->timo.tv_sec; 821 cei_dfr_proposal.when = dfr_proposal->when; 822 cei_dfr_proposal.uptime = dfr_proposal->uptime; 823 memcpy(&cei_dfr_proposal.addr, &dfr_proposal->addr, sizeof( 824 cei_dfr_proposal.addr)); 825 cei_dfr_proposal.router_lifetime = 826 dfr_proposal->router_lifetime; 827 if(strlcpy(cei_dfr_proposal.rpref, 828 rpref_name[dfr_proposal->rpref], 829 sizeof(cei_dfr_proposal.rpref)) >= 830 sizeof(cei_dfr_proposal.rpref)) 831 log_warnx("truncated router preference"); 832 engine_imsg_compose_frontend( 833 IMSG_CTL_SHOW_INTERFACE_INFO_DFR_PROPOSAL, pid, 834 &cei_dfr_proposal, sizeof(cei_dfr_proposal)); 835 } 836 837 if (!LIST_EMPTY(&iface->rdns_proposals)) 838 engine_imsg_compose_frontend( 839 IMSG_CTL_SHOW_INTERFACE_INFO_RDNS_PROPOSALS, pid, NULL, 0); 840 841 LIST_FOREACH(rdns_proposal, &iface->rdns_proposals, entries) { 842 memset(&cei_rdns_proposal, 0, sizeof(cei_rdns_proposal)); 843 cei_rdns_proposal.id = rdns_proposal->id; 844 if(strlcpy(cei_rdns_proposal.state, 845 proposal_state_name(rdns_proposal->state), 846 sizeof(cei_rdns_proposal.state)) >= 847 sizeof(cei_rdns_proposal.state)) 848 log_warnx("truncated state name"); 849 cei_rdns_proposal.next_timeout = rdns_proposal->timo.tv_sec; 850 cei_rdns_proposal.when = rdns_proposal->when; 851 cei_rdns_proposal.uptime = rdns_proposal->uptime; 852 memcpy(&cei_rdns_proposal.from, &rdns_proposal->from, sizeof( 853 cei_rdns_proposal.from)); 854 cei_rdns_proposal.rdns_count = rdns_proposal->rdns_count; 855 memcpy(&cei_rdns_proposal.rdns, 856 &rdns_proposal->rdns, sizeof(cei_rdns_proposal.rdns)); 857 cei_rdns_proposal.rdns_lifetime = 858 rdns_proposal->rdns_lifetime; 859 engine_imsg_compose_frontend( 860 IMSG_CTL_SHOW_INTERFACE_INFO_RDNS_PROPOSAL, pid, 861 &cei_rdns_proposal, sizeof(cei_rdns_proposal)); 862 } 863 } 864 865 void 866 engine_showinfo_ctl(struct imsg *imsg, uint32_t if_index) 867 { 868 struct slaacd_iface *iface; 869 870 switch (imsg->hdr.type) { 871 case IMSG_CTL_SHOW_INTERFACE_INFO: 872 if (if_index == 0) { 873 LIST_FOREACH (iface, &slaacd_interfaces, entries) 874 send_interface_info(iface, imsg->hdr.pid); 875 } else { 876 if ((iface = get_slaacd_iface_by_id(if_index)) != NULL) 877 send_interface_info(iface, imsg->hdr.pid); 878 } 879 engine_imsg_compose_frontend(IMSG_CTL_END, imsg->hdr.pid, NULL, 880 0); 881 break; 882 default: 883 log_debug("%s: error handling imsg", __func__); 884 break; 885 } 886 } 887 888 #endif /* SMALL */ 889 890 struct slaacd_iface* 891 get_slaacd_iface_by_id(uint32_t if_index) 892 { 893 struct slaacd_iface *iface; 894 LIST_FOREACH (iface, &slaacd_interfaces, entries) { 895 if (iface->if_index == if_index) 896 return (iface); 897 } 898 899 return (NULL); 900 } 901 902 void 903 remove_slaacd_iface(uint32_t if_index) 904 { 905 struct slaacd_iface *iface; 906 struct radv *ra; 907 struct address_proposal *addr_proposal; 908 struct dfr_proposal *dfr_proposal; 909 struct rdns_proposal *rdns_proposal; 910 911 iface = get_slaacd_iface_by_id(if_index); 912 913 if (iface == NULL) 914 return; 915 916 LIST_REMOVE(iface, entries); 917 while(!LIST_EMPTY(&iface->radvs)) { 918 ra = LIST_FIRST(&iface->radvs); 919 LIST_REMOVE(ra, entries); 920 free_ra(ra); 921 } 922 while(!LIST_EMPTY(&iface->addr_proposals)) { 923 addr_proposal = LIST_FIRST(&iface->addr_proposals); 924 free_address_proposal(addr_proposal); 925 } 926 while(!LIST_EMPTY(&iface->dfr_proposals)) { 927 dfr_proposal = LIST_FIRST(&iface->dfr_proposals); 928 free_dfr_proposal(dfr_proposal); 929 } 930 while(!LIST_EMPTY(&iface->rdns_proposals)) { 931 rdns_proposal = LIST_FIRST(&iface->rdns_proposals); 932 free_rdns_proposal(rdns_proposal); 933 } 934 compose_rdns_proposal(iface->if_index, iface->rdomain); 935 evtimer_del(&iface->timer); 936 free(iface); 937 } 938 939 void 940 free_ra(struct radv *ra) 941 { 942 struct radv_prefix *prefix; 943 struct radv_rdns *rdns; 944 945 if (ra == NULL) 946 return; 947 948 evtimer_del(&ra->timer); 949 950 while (!LIST_EMPTY(&ra->prefixes)) { 951 prefix = LIST_FIRST(&ra->prefixes); 952 LIST_REMOVE(prefix, entries); 953 free(prefix); 954 } 955 956 while (!LIST_EMPTY(&ra->rdns_servers)) { 957 rdns = LIST_FIRST(&ra->rdns_servers); 958 LIST_REMOVE(rdns, entries); 959 free(rdns); 960 } 961 962 free(ra); 963 } 964 965 void 966 iface_state_transition(struct slaacd_iface *iface, enum if_state new_state) 967 { 968 enum if_state old_state = iface->state; 969 struct address_proposal *addr_proposal; 970 struct dfr_proposal *dfr_proposal; 971 struct rdns_proposal *rdns_proposal; 972 char ifnamebuf[IF_NAMESIZE], *if_name; 973 974 iface->state = new_state; 975 976 switch (new_state) { 977 case IF_DOWN: 978 if (old_state != IF_DOWN) { 979 LIST_FOREACH (addr_proposal, &iface->addr_proposals, 980 entries) 981 addr_proposal_state_transition(addr_proposal, 982 PROPOSAL_IF_DOWN); 983 LIST_FOREACH (dfr_proposal, &iface->dfr_proposals, 984 entries) 985 dfr_proposal_state_transition(dfr_proposal, 986 PROPOSAL_IF_DOWN); 987 LIST_FOREACH (rdns_proposal, &iface->rdns_proposals, 988 entries) 989 rdns_proposal_state_transition(rdns_proposal, 990 PROPOSAL_IF_DOWN); 991 } 992 993 /* nothing else to do until interface comes back up */ 994 iface->timo.tv_sec = -1; 995 break; 996 case IF_INIT: 997 switch (old_state) { 998 case IF_INIT: 999 iface->probes++; 1000 break; 1001 case IF_DOWN: 1002 LIST_FOREACH (addr_proposal, &iface->addr_proposals, 1003 entries) 1004 addr_proposal_state_transition(addr_proposal, 1005 PROPOSAL_WITHDRAWN); 1006 LIST_FOREACH (dfr_proposal, &iface->dfr_proposals, 1007 entries) 1008 dfr_proposal_state_transition(dfr_proposal, 1009 PROPOSAL_WITHDRAWN); 1010 LIST_FOREACH (rdns_proposal, &iface->rdns_proposals, 1011 entries) 1012 rdns_proposal_state_transition(rdns_proposal, 1013 PROPOSAL_WITHDRAWN); 1014 default: 1015 iface->probes = 0; 1016 } 1017 if (iface->probes < MAX_RTR_SOLICITATIONS) { 1018 iface->timo.tv_sec = RTR_SOLICITATION_INTERVAL; 1019 request_solicitation(iface); 1020 } else 1021 /* no router available, stop probing */ 1022 iface->timo.tv_sec = -1; 1023 break; 1024 case IF_BOUND: 1025 iface->timo.tv_sec = -1; 1026 break; 1027 } 1028 1029 if_name = if_indextoname(iface->if_index, ifnamebuf); 1030 log_debug("%s[%s] %s -> %s, timo: %lld", __func__, if_name == NULL ? 1031 "?" : if_name, if_state_name(old_state), if_state_name(new_state), 1032 iface->timo.tv_sec); 1033 1034 if (iface->timo.tv_sec == -1) { 1035 if (evtimer_pending(&iface->timer, NULL)) 1036 evtimer_del(&iface->timer); 1037 } else 1038 evtimer_add(&iface->timer, &iface->timo); 1039 } 1040 1041 void addr_proposal_state_transition(struct address_proposal *addr_proposal, 1042 enum proposal_state new_state) 1043 { 1044 enum proposal_state old_state = addr_proposal->state; 1045 struct slaacd_iface *iface; 1046 uint32_t lifetime; 1047 char ifnamebuf[IF_NAMESIZE], *if_name; 1048 1049 addr_proposal->state = new_state; 1050 1051 if ((iface = get_slaacd_iface_by_id(addr_proposal->if_index)) == NULL) 1052 return; 1053 1054 switch (addr_proposal->state) { 1055 case PROPOSAL_IF_DOWN: 1056 if (old_state == PROPOSAL_IF_DOWN) { 1057 withdraw_addr(addr_proposal); 1058 addr_proposal->timo.tv_sec = -1; 1059 } else { 1060 addr_proposal->timo.tv_sec = 1061 real_lifetime(&addr_proposal->uptime, 1062 addr_proposal->vltime); 1063 } 1064 break; 1065 case PROPOSAL_NOT_CONFIGURED: 1066 break; 1067 case PROPOSAL_CONFIGURED: 1068 lifetime = real_lifetime(&addr_proposal->uptime, 1069 addr_proposal->pltime); 1070 if (lifetime == 0) 1071 lifetime = real_lifetime(&addr_proposal->uptime, 1072 addr_proposal->vltime); 1073 if (lifetime > MAX_RTR_SOLICITATIONS * 1074 (RTR_SOLICITATION_INTERVAL + 1)) 1075 addr_proposal->timo.tv_sec = lifetime - 1076 MAX_RTR_SOLICITATIONS * RTR_SOLICITATION_INTERVAL; 1077 else 1078 addr_proposal->timo.tv_sec = RTR_SOLICITATION_INTERVAL; 1079 break; 1080 case PROPOSAL_NEARLY_EXPIRED: 1081 lifetime = real_lifetime(&addr_proposal->uptime, 1082 addr_proposal->pltime); 1083 if (lifetime == 0) 1084 lifetime = real_lifetime(&addr_proposal->uptime, 1085 addr_proposal->vltime); 1086 if (lifetime > MAX_RTR_SOLICITATIONS * 1087 (RTR_SOLICITATION_INTERVAL + 1)) 1088 addr_proposal->timo.tv_sec = lifetime - 1089 MAX_RTR_SOLICITATIONS * RTR_SOLICITATION_INTERVAL; 1090 else 1091 addr_proposal->timo.tv_sec = RTR_SOLICITATION_INTERVAL; 1092 request_solicitation(iface); 1093 break; 1094 case PROPOSAL_WITHDRAWN: 1095 withdraw_addr(addr_proposal); 1096 addr_proposal->timo.tv_sec = MAX_RTR_SOLICITATIONS * 1097 RTR_SOLICITATION_INTERVAL; 1098 break; 1099 case PROPOSAL_DUPLICATED: 1100 addr_proposal->timo.tv_sec = 0; 1101 break; 1102 case PROPOSAL_STALE: 1103 addr_proposal->timo.tv_sec = 0; /* remove immediately */ 1104 break; 1105 } 1106 1107 if_name = if_indextoname(addr_proposal->if_index, ifnamebuf); 1108 log_debug("%s[%s] %s -> %s, timo: %lld", __func__, if_name == NULL ? 1109 "?" : if_name, proposal_state_name(old_state), 1110 proposal_state_name(new_state), 1111 addr_proposal->timo.tv_sec); 1112 1113 if (addr_proposal->timo.tv_sec == -1) { 1114 if (evtimer_pending(&addr_proposal->timer, NULL)) 1115 evtimer_del(&addr_proposal->timer); 1116 } else 1117 evtimer_add(&addr_proposal->timer, &addr_proposal->timo); 1118 } 1119 1120 void dfr_proposal_state_transition(struct dfr_proposal *dfr_proposal, 1121 enum proposal_state new_state) 1122 { 1123 enum proposal_state old_state = dfr_proposal->state; 1124 struct slaacd_iface *iface; 1125 uint32_t lifetime; 1126 char ifnamebuf[IF_NAMESIZE], *if_name; 1127 1128 dfr_proposal->state = new_state; 1129 1130 if ((iface = get_slaacd_iface_by_id(dfr_proposal->if_index)) == NULL) 1131 return; 1132 1133 switch (dfr_proposal->state) { 1134 case PROPOSAL_IF_DOWN: 1135 if (old_state == PROPOSAL_IF_DOWN) { 1136 withdraw_dfr(dfr_proposal); 1137 dfr_proposal->timo.tv_sec = -1; 1138 } else { 1139 dfr_proposal->timo.tv_sec = 1140 real_lifetime(&dfr_proposal->uptime, 1141 dfr_proposal->router_lifetime); 1142 } 1143 break; 1144 case PROPOSAL_NOT_CONFIGURED: 1145 break; 1146 case PROPOSAL_CONFIGURED: 1147 lifetime = real_lifetime(&dfr_proposal->uptime, 1148 dfr_proposal->router_lifetime); 1149 if (lifetime > MAX_RTR_SOLICITATIONS * 1150 (RTR_SOLICITATION_INTERVAL + 1)) 1151 dfr_proposal->timo.tv_sec = lifetime - 1152 MAX_RTR_SOLICITATIONS * RTR_SOLICITATION_INTERVAL; 1153 else 1154 dfr_proposal->timo.tv_sec = RTR_SOLICITATION_INTERVAL; 1155 break; 1156 case PROPOSAL_NEARLY_EXPIRED: 1157 lifetime = real_lifetime(&dfr_proposal->uptime, 1158 dfr_proposal->router_lifetime); 1159 if (lifetime > MAX_RTR_SOLICITATIONS * 1160 (RTR_SOLICITATION_INTERVAL + 1)) 1161 dfr_proposal->timo.tv_sec = lifetime - 1162 MAX_RTR_SOLICITATIONS * RTR_SOLICITATION_INTERVAL; 1163 else 1164 dfr_proposal->timo.tv_sec = RTR_SOLICITATION_INTERVAL; 1165 request_solicitation(iface); 1166 break; 1167 case PROPOSAL_WITHDRAWN: 1168 withdraw_dfr(dfr_proposal); 1169 dfr_proposal->timo.tv_sec = MAX_RTR_SOLICITATIONS * 1170 RTR_SOLICITATION_INTERVAL; 1171 break; 1172 case PROPOSAL_STALE: 1173 dfr_proposal->timo.tv_sec = 0; /* remove immediately */ 1174 break; 1175 case PROPOSAL_DUPLICATED: 1176 fatalx("invalid dfr state: PROPOSAL_DUPLICATED"); 1177 break; 1178 } 1179 1180 if_name = if_indextoname(dfr_proposal->if_index, ifnamebuf); 1181 log_debug("%s[%s] %s -> %s, timo: %lld", __func__, if_name == NULL ? 1182 "?" : if_name, proposal_state_name(old_state), 1183 proposal_state_name(new_state), 1184 dfr_proposal->timo.tv_sec); 1185 1186 if (dfr_proposal->timo.tv_sec == -1) { 1187 if (evtimer_pending(&dfr_proposal->timer, NULL)) 1188 evtimer_del(&dfr_proposal->timer); 1189 } else 1190 evtimer_add(&dfr_proposal->timer, &dfr_proposal->timo); 1191 1192 } 1193 1194 void rdns_proposal_state_transition(struct rdns_proposal *rdns_proposal, 1195 enum proposal_state new_state) 1196 { 1197 enum proposal_state old_state = rdns_proposal->state; 1198 struct slaacd_iface *iface; 1199 uint32_t lifetime; 1200 char ifnamebuf[IF_NAMESIZE], *if_name; 1201 1202 rdns_proposal->state = new_state; 1203 1204 if ((iface = get_slaacd_iface_by_id(rdns_proposal->if_index)) == NULL) 1205 return; 1206 1207 switch (rdns_proposal->state) { 1208 case PROPOSAL_IF_DOWN: 1209 if (old_state == PROPOSAL_IF_DOWN) { 1210 withdraw_rdns(rdns_proposal); 1211 rdns_proposal->timo.tv_sec = -1; 1212 } else { 1213 rdns_proposal->timo.tv_sec = 1214 real_lifetime(&rdns_proposal->uptime, 1215 rdns_proposal->rdns_lifetime); 1216 } 1217 break; 1218 case PROPOSAL_NOT_CONFIGURED: 1219 break; 1220 case PROPOSAL_CONFIGURED: 1221 lifetime = real_lifetime(&rdns_proposal->uptime, 1222 rdns_proposal->rdns_lifetime); 1223 if (lifetime > MAX_RTR_SOLICITATIONS * 1224 (RTR_SOLICITATION_INTERVAL + 1)) 1225 rdns_proposal->timo.tv_sec = lifetime - 1226 MAX_RTR_SOLICITATIONS * RTR_SOLICITATION_INTERVAL; 1227 else 1228 rdns_proposal->timo.tv_sec = RTR_SOLICITATION_INTERVAL; 1229 break; 1230 case PROPOSAL_NEARLY_EXPIRED: 1231 lifetime = real_lifetime(&rdns_proposal->uptime, 1232 rdns_proposal->rdns_lifetime); 1233 if (lifetime > MAX_RTR_SOLICITATIONS * 1234 (RTR_SOLICITATION_INTERVAL + 1)) 1235 rdns_proposal->timo.tv_sec = lifetime - 1236 MAX_RTR_SOLICITATIONS * RTR_SOLICITATION_INTERVAL; 1237 else 1238 rdns_proposal->timo.tv_sec = RTR_SOLICITATION_INTERVAL; 1239 request_solicitation(iface); 1240 break; 1241 case PROPOSAL_WITHDRAWN: 1242 withdraw_rdns(rdns_proposal); 1243 rdns_proposal->timo.tv_sec = MAX_RTR_SOLICITATIONS * 1244 RTR_SOLICITATION_INTERVAL; 1245 break; 1246 case PROPOSAL_STALE: 1247 rdns_proposal->timo.tv_sec = 0; /* remove immediately */ 1248 break; 1249 case PROPOSAL_DUPLICATED: 1250 fatalx("invalid rdns state: PROPOSAL_DUPLICATED"); 1251 break; 1252 } 1253 1254 if_name = if_indextoname(rdns_proposal->if_index, ifnamebuf); 1255 log_debug("%s[%s] %s -> %s, timo: %lld", __func__, if_name == NULL ? 1256 "?" : if_name, proposal_state_name(old_state), 1257 proposal_state_name(new_state), 1258 rdns_proposal->timo.tv_sec); 1259 1260 if (rdns_proposal->timo.tv_sec == -1) { 1261 if (evtimer_pending(&rdns_proposal->timer, NULL)) 1262 evtimer_del(&rdns_proposal->timer); 1263 } else 1264 evtimer_add(&rdns_proposal->timer, &rdns_proposal->timo); 1265 } 1266 1267 void 1268 request_solicitation(struct slaacd_iface *iface) 1269 { 1270 struct timespec now, diff, sol_delay = {RTR_SOLICITATION_INTERVAL, 0}; 1271 1272 clock_gettime(CLOCK_MONOTONIC, &now); 1273 timespecsub(&now, &iface->last_sol, &diff); 1274 if (timespeccmp(&diff, &sol_delay, <)) { 1275 log_warnx("last solicitation less then %d seconds ago", 1276 RTR_SOLICITATION_INTERVAL); 1277 return; 1278 } 1279 1280 iface->last_sol = now; 1281 engine_imsg_compose_frontend(IMSG_CTL_SEND_SOLICITATION, 0, 1282 &iface->if_index, sizeof(iface->if_index)); 1283 } 1284 1285 void 1286 engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) 1287 { 1288 struct slaacd_iface *iface; 1289 int need_refresh = 0; 1290 1291 iface = get_slaacd_iface_by_id(imsg_ifinfo->if_index); 1292 if (iface == NULL) { 1293 if ((iface = calloc(1, sizeof(*iface))) == NULL) 1294 fatal("calloc"); 1295 iface->state = IF_DOWN; 1296 iface->timo.tv_usec = arc4random_uniform(1000000); 1297 evtimer_set(&iface->timer, iface_timeout, iface); 1298 iface->if_index = imsg_ifinfo->if_index; 1299 iface->rdomain = imsg_ifinfo->rdomain; 1300 iface->running = imsg_ifinfo->running; 1301 iface->link_state = imsg_ifinfo->link_state; 1302 iface->autoconf = imsg_ifinfo->autoconf; 1303 iface->temporary = imsg_ifinfo->temporary; 1304 iface->soii = imsg_ifinfo->soii; 1305 memcpy(&iface->hw_address, &imsg_ifinfo->hw_address, 1306 sizeof(struct ether_addr)); 1307 memcpy(&iface->ll_address, &imsg_ifinfo->ll_address, 1308 sizeof(struct sockaddr_in6)); 1309 memcpy(iface->soiikey, imsg_ifinfo->soiikey, 1310 sizeof(iface->soiikey)); 1311 LIST_INIT(&iface->radvs); 1312 LIST_INSERT_HEAD(&slaacd_interfaces, iface, entries); 1313 LIST_INIT(&iface->addr_proposals); 1314 LIST_INIT(&iface->dfr_proposals); 1315 LIST_INIT(&iface->rdns_proposals); 1316 need_refresh = 1; 1317 } else { 1318 memcpy(&iface->ll_address, &imsg_ifinfo->ll_address, 1319 sizeof(struct sockaddr_in6)); 1320 1321 if (iface->autoconf != imsg_ifinfo->autoconf) { 1322 iface->autoconf = imsg_ifinfo->autoconf; 1323 need_refresh = 1; 1324 } 1325 1326 if (iface->temporary != imsg_ifinfo->temporary) { 1327 iface->temporary = imsg_ifinfo->temporary; 1328 need_refresh = 1; 1329 } 1330 1331 if (iface->soii != imsg_ifinfo->soii) { 1332 iface->soii = imsg_ifinfo->soii; 1333 need_refresh = 1; 1334 } 1335 1336 if (memcmp(&iface->hw_address, &imsg_ifinfo->hw_address, 1337 sizeof(struct ether_addr)) != 0) { 1338 memcpy(&iface->hw_address, &imsg_ifinfo->hw_address, 1339 sizeof(struct ether_addr)); 1340 need_refresh = 1; 1341 } 1342 1343 if (memcmp(iface->soiikey, imsg_ifinfo->soiikey, 1344 sizeof(iface->soiikey)) != 0) { 1345 memcpy(iface->soiikey, imsg_ifinfo->soiikey, 1346 sizeof(iface->soiikey)); 1347 need_refresh = 1; 1348 } 1349 1350 if (imsg_ifinfo->running != iface->running) { 1351 iface->running = imsg_ifinfo->running; 1352 need_refresh = 1; 1353 } 1354 if (imsg_ifinfo->link_state != iface->link_state) { 1355 iface->link_state = imsg_ifinfo->link_state; 1356 need_refresh = 1; 1357 } 1358 } 1359 1360 if (!need_refresh) 1361 return; 1362 1363 if (iface->running && LINK_STATE_IS_UP(iface->link_state)) 1364 iface_state_transition(iface, IF_INIT); 1365 1366 else 1367 iface_state_transition(iface, IF_DOWN); 1368 } 1369 1370 void 1371 parse_ra(struct slaacd_iface *iface, struct imsg_ra *ra) 1372 { 1373 struct icmp6_hdr *icmp6_hdr; 1374 struct nd_router_advert *nd_ra; 1375 struct radv *radv; 1376 struct radv_prefix *prefix; 1377 struct radv_rdns *rdns; 1378 ssize_t len = ra->len; 1379 const char *hbuf; 1380 uint8_t *p; 1381 1382 #ifndef SMALL 1383 if (log_getverbose() > 1) 1384 debug_log_ra(ra); 1385 #endif /* SMALL */ 1386 1387 hbuf = sin6_to_str(&ra->from); 1388 if ((size_t)len < sizeof(struct icmp6_hdr)) { 1389 log_warnx("received too short message (%ld) from %s", len, 1390 hbuf); 1391 return; 1392 } 1393 1394 p = ra->packet; 1395 icmp6_hdr = (struct icmp6_hdr *)p; 1396 if (icmp6_hdr->icmp6_type != ND_ROUTER_ADVERT) 1397 return; 1398 1399 if (!IN6_IS_ADDR_LINKLOCAL(&ra->from.sin6_addr)) { 1400 log_debug("RA from non link local address %s", hbuf); 1401 return; 1402 } 1403 1404 if ((size_t)len < sizeof(struct nd_router_advert)) { 1405 log_warnx("received too short message (%ld) from %s", len, 1406 hbuf); 1407 return; 1408 } 1409 1410 if ((radv = calloc(1, sizeof(*radv))) == NULL) 1411 fatal("calloc"); 1412 1413 LIST_INIT(&radv->prefixes); 1414 LIST_INIT(&radv->rdns_servers); 1415 1416 radv->min_lifetime = UINT32_MAX; 1417 1418 nd_ra = (struct nd_router_advert *)p; 1419 len -= sizeof(struct nd_router_advert); 1420 p += sizeof(struct nd_router_advert); 1421 1422 log_debug("ICMPv6 type(%d), code(%d) from %s of length %ld", 1423 nd_ra->nd_ra_type, nd_ra->nd_ra_code, hbuf, len); 1424 1425 if (nd_ra->nd_ra_code != 0) { 1426 log_warnx("invalid ICMPv6 code (%d) from %s", nd_ra->nd_ra_code, 1427 hbuf); 1428 goto err; 1429 } 1430 1431 memcpy(&radv->from, &ra->from, sizeof(ra->from)); 1432 1433 if (clock_gettime(CLOCK_REALTIME, &radv->when)) 1434 fatal("clock_gettime"); 1435 if (clock_gettime(CLOCK_MONOTONIC, &radv->uptime)) 1436 fatal("clock_gettime"); 1437 1438 radv->curhoplimit = nd_ra->nd_ra_curhoplimit; 1439 radv->managed = nd_ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED; 1440 radv->other = nd_ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER; 1441 1442 switch (nd_ra->nd_ra_flags_reserved & ND_RA_FLAG_RTPREF_MASK) { 1443 case ND_RA_FLAG_RTPREF_HIGH: 1444 radv->rpref=HIGH; 1445 break; 1446 case ND_RA_FLAG_RTPREF_LOW: 1447 radv->rpref=LOW; 1448 break; 1449 case ND_RA_FLAG_RTPREF_MEDIUM: 1450 /* fallthrough */ 1451 default: 1452 radv->rpref=MEDIUM; 1453 break; 1454 } 1455 radv->router_lifetime = ntohs(nd_ra->nd_ra_router_lifetime); 1456 if (radv->router_lifetime != 0) 1457 radv->min_lifetime = radv->router_lifetime; 1458 radv->reachable_time = ntohl(nd_ra->nd_ra_reachable); 1459 radv->retrans_time = ntohl(nd_ra->nd_ra_retransmit); 1460 1461 while ((size_t)len >= sizeof(struct nd_opt_hdr)) { 1462 struct nd_opt_hdr *nd_opt_hdr = (struct nd_opt_hdr *)p; 1463 struct nd_opt_prefix_info *prf; 1464 struct nd_opt_rdnss *rdnss; 1465 struct nd_opt_mtu *mtu; 1466 struct in6_addr *in6; 1467 int i; 1468 1469 len -= sizeof(struct nd_opt_hdr); 1470 p += sizeof(struct nd_opt_hdr); 1471 1472 if (nd_opt_hdr->nd_opt_len * 8 - 2 > len) { 1473 log_warnx("invalid option len: %u > %ld", 1474 nd_opt_hdr->nd_opt_len, len); 1475 goto err; 1476 } 1477 1478 switch (nd_opt_hdr->nd_opt_type) { 1479 case ND_OPT_PREFIX_INFORMATION: 1480 if (nd_opt_hdr->nd_opt_len != 4) { 1481 log_warnx("invalid ND_OPT_PREFIX_INFORMATION: " 1482 "len != 4"); 1483 goto err; 1484 } 1485 1486 if ((prefix = calloc(1, sizeof(*prefix))) == NULL) 1487 fatal("calloc"); 1488 1489 prf = (struct nd_opt_prefix_info*) nd_opt_hdr; 1490 prefix->prefix = prf->nd_opt_pi_prefix; 1491 prefix->prefix_len = prf->nd_opt_pi_prefix_len; 1492 prefix->onlink = prf->nd_opt_pi_flags_reserved & 1493 ND_OPT_PI_FLAG_ONLINK; 1494 prefix->autonomous = prf->nd_opt_pi_flags_reserved & 1495 ND_OPT_PI_FLAG_AUTO; 1496 prefix->vltime = ntohl(prf->nd_opt_pi_valid_time); 1497 prefix->pltime = ntohl(prf->nd_opt_pi_preferred_time); 1498 if (radv->min_lifetime > prefix->pltime) 1499 radv->min_lifetime = prefix->pltime; 1500 1501 LIST_INSERT_HEAD(&radv->prefixes, prefix, entries); 1502 1503 break; 1504 1505 case ND_OPT_RDNSS: 1506 if (nd_opt_hdr->nd_opt_len < 3) { 1507 log_warnx("invalid ND_OPT_RDNSS: len < 24"); 1508 goto err; 1509 } 1510 1511 if ((nd_opt_hdr->nd_opt_len - 1) % 2 != 0) { 1512 log_warnx("invalid ND_OPT_RDNSS: length with" 1513 "out header is not multiply of 16: %d", 1514 (nd_opt_hdr->nd_opt_len - 1) * 8); 1515 goto err; 1516 } 1517 1518 rdnss = (struct nd_opt_rdnss*) nd_opt_hdr; 1519 1520 radv->rdns_lifetime = ntohl( 1521 rdnss->nd_opt_rdnss_lifetime); 1522 if (radv->min_lifetime > radv->rdns_lifetime) 1523 radv->min_lifetime = radv->rdns_lifetime; 1524 1525 in6 = (struct in6_addr*) (p + 6); 1526 for (i=0; i < (nd_opt_hdr->nd_opt_len - 1)/2; i++, 1527 in6++) { 1528 if((rdns = calloc(1, sizeof(*rdns))) == NULL) 1529 fatal("calloc"); 1530 memcpy(&rdns->rdns, in6, sizeof(rdns->rdns)); 1531 LIST_INSERT_HEAD(&radv->rdns_servers, rdns, 1532 entries); 1533 } 1534 break; 1535 case ND_OPT_MTU: 1536 if (nd_opt_hdr->nd_opt_len != 1) { 1537 log_warnx("invalid ND_OPT_MTU: len != 1"); 1538 goto err; 1539 } 1540 mtu = (struct nd_opt_mtu*) nd_opt_hdr; 1541 radv->mtu = ntohl(mtu->nd_opt_mtu_mtu); 1542 1543 /* path MTU cannot be less than IPV6_MMTU */ 1544 if (radv->mtu < IPV6_MMTU) { 1545 radv->mtu = 0; 1546 log_warnx("invalid advertised MTU"); 1547 } 1548 1549 break; 1550 case ND_OPT_DNSSL: 1551 case ND_OPT_REDIRECTED_HEADER: 1552 case ND_OPT_SOURCE_LINKADDR: 1553 case ND_OPT_TARGET_LINKADDR: 1554 case ND_OPT_ROUTE_INFO: 1555 #if 0 1556 log_debug("\tOption: %u (len: %u) not implemented", 1557 nd_opt_hdr->nd_opt_type, nd_opt_hdr->nd_opt_len * 1558 8); 1559 #endif 1560 break; 1561 default: 1562 log_debug("\t\tUNKNOWN: %d", nd_opt_hdr->nd_opt_type); 1563 break; 1564 1565 } 1566 len -= nd_opt_hdr->nd_opt_len * 8 - 2; 1567 p += nd_opt_hdr->nd_opt_len * 8 - 2; 1568 } 1569 update_iface_ra(iface, radv); 1570 return; 1571 1572 err: 1573 free_ra(radv); 1574 } 1575 1576 void 1577 gen_addr(struct slaacd_iface *iface, struct radv_prefix *prefix, struct 1578 address_proposal *addr_proposal, int temporary) 1579 { 1580 SHA2_CTX ctx; 1581 struct in6_addr iid; 1582 int i; 1583 u_int8_t digest[SHA512_DIGEST_LENGTH]; 1584 1585 memset(&iid, 0, sizeof(iid)); 1586 1587 /* from in6_ifadd() in nd6_rtr.c */ 1588 /* XXX from in6.h, guarded by #ifdef _KERNEL XXX nonstandard */ 1589 #define s6_addr32 __u6_addr.__u6_addr32 1590 1591 in6_prefixlen2mask(&addr_proposal->mask, addr_proposal->prefix_len); 1592 1593 memset(&addr_proposal->addr, 0, sizeof(addr_proposal->addr)); 1594 1595 addr_proposal->addr.sin6_family = AF_INET6; 1596 addr_proposal->addr.sin6_len = sizeof(addr_proposal->addr); 1597 1598 memcpy(&addr_proposal->addr.sin6_addr, &prefix->prefix, 1599 sizeof(addr_proposal->addr.sin6_addr)); 1600 1601 for (i = 0; i < 4; i++) 1602 addr_proposal->addr.sin6_addr.s6_addr32[i] &= 1603 addr_proposal->mask.s6_addr32[i]; 1604 1605 if (temporary) { 1606 arc4random_buf(&iid.s6_addr, sizeof(iid.s6_addr)); 1607 } else if (iface->soii) { 1608 SHA512Init(&ctx); 1609 SHA512Update(&ctx, &prefix->prefix, 1610 sizeof(prefix->prefix)); 1611 SHA512Update(&ctx, &iface->hw_address, 1612 sizeof(iface->hw_address)); 1613 SHA512Update(&ctx, &prefix->dad_counter, 1614 sizeof(prefix->dad_counter)); 1615 SHA512Update(&ctx, addr_proposal->soiikey, 1616 sizeof(addr_proposal->soiikey)); 1617 SHA512Final(digest, &ctx); 1618 1619 memcpy(&iid.s6_addr, digest + (sizeof(digest) - 1620 sizeof(iid.s6_addr)), sizeof(iid.s6_addr)); 1621 } else { 1622 /* This is safe, because we have a 64 prefix len */ 1623 memcpy(&iid.s6_addr, &iface->ll_address.sin6_addr, 1624 sizeof(iid.s6_addr)); 1625 } 1626 1627 for (i = 0; i < 4; i++) 1628 addr_proposal->addr.sin6_addr.s6_addr32[i] |= 1629 (iid.s6_addr32[i] & ~addr_proposal->mask.s6_addr32[i]); 1630 #undef s6_addr32 1631 } 1632 1633 /* from sys/netinet6/in6.c */ 1634 void 1635 in6_prefixlen2mask(struct in6_addr *maskp, int len) 1636 { 1637 u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; 1638 int bytelen, bitlen, i; 1639 1640 if (0 > len || len > 128) 1641 fatalx("%s: invalid prefix length(%d)\n", __func__, len); 1642 1643 bzero(maskp, sizeof(*maskp)); 1644 bytelen = len / 8; 1645 bitlen = len % 8; 1646 for (i = 0; i < bytelen; i++) 1647 maskp->s6_addr[i] = 0xff; 1648 /* len == 128 is ok because bitlen == 0 then */ 1649 if (bitlen) 1650 maskp->s6_addr[bytelen] = maskarray[bitlen - 1]; 1651 } 1652 1653 #ifndef SMALL 1654 /* from kame via ifconfig, where it's called prefix() */ 1655 int 1656 in6_mask2prefixlen(struct in6_addr *in6) 1657 { 1658 u_char *nam = (u_char *)in6; 1659 int byte, bit, plen = 0, size = sizeof(struct in6_addr); 1660 1661 for (byte = 0; byte < size; byte++, plen += 8) 1662 if (nam[byte] != 0xff) 1663 break; 1664 if (byte == size) 1665 return (plen); 1666 for (bit = 7; bit != 0; bit--, plen++) 1667 if (!(nam[byte] & (1 << bit))) 1668 break; 1669 for (; bit != 0; bit--) 1670 if (nam[byte] & (1 << bit)) 1671 return (0); 1672 byte++; 1673 for (; byte < size; byte++) 1674 if (nam[byte]) 1675 return (0); 1676 return (plen); 1677 } 1678 1679 void 1680 debug_log_ra(struct imsg_ra *ra) 1681 { 1682 struct nd_router_advert *nd_ra; 1683 ssize_t len = ra->len; 1684 char ntopbuf[INET6_ADDRSTRLEN]; 1685 const char *hbuf; 1686 uint8_t *p; 1687 1688 hbuf = sin6_to_str(&ra->from); 1689 1690 if (!IN6_IS_ADDR_LINKLOCAL(&ra->from.sin6_addr)) { 1691 log_warnx("RA from non link local address %s", hbuf); 1692 return; 1693 } 1694 1695 if ((size_t)len < sizeof(struct nd_router_advert)) { 1696 log_warnx("received too short message (%ld) from %s", len, 1697 hbuf); 1698 return; 1699 } 1700 1701 p = ra->packet; 1702 nd_ra = (struct nd_router_advert *)p; 1703 len -= sizeof(struct nd_router_advert); 1704 p += sizeof(struct nd_router_advert); 1705 1706 log_debug("ICMPv6 type(%d), code(%d) from %s of length %ld", 1707 nd_ra->nd_ra_type, nd_ra->nd_ra_code, hbuf, len); 1708 1709 if (nd_ra->nd_ra_type != ND_ROUTER_ADVERT) { 1710 log_warnx("invalid ICMPv6 type (%d) from %s", nd_ra->nd_ra_type, 1711 hbuf); 1712 return; 1713 } 1714 1715 if (nd_ra->nd_ra_code != 0) { 1716 log_warnx("invalid ICMPv6 code (%d) from %s", nd_ra->nd_ra_code, 1717 hbuf); 1718 return; 1719 } 1720 1721 log_debug("---"); 1722 log_debug("RA from %s", hbuf); 1723 log_debug("\tCur Hop Limit: %u", nd_ra->nd_ra_curhoplimit); 1724 log_debug("\tManaged address configuration: %d", 1725 (nd_ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) ? 1 : 0); 1726 log_debug("\tOther configuration: %d", 1727 (nd_ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) ? 1 : 0); 1728 switch (nd_ra->nd_ra_flags_reserved & ND_RA_FLAG_RTPREF_MASK) { 1729 case ND_RA_FLAG_RTPREF_HIGH: 1730 log_debug("\tRouter Preference: high"); 1731 break; 1732 case ND_RA_FLAG_RTPREF_MEDIUM: 1733 log_debug("\tRouter Preference: medium"); 1734 break; 1735 case ND_RA_FLAG_RTPREF_LOW: 1736 log_debug("\tRouter Preference: low"); 1737 break; 1738 case ND_RA_FLAG_RTPREF_RSV: 1739 log_debug("\tRouter Preference: reserved"); 1740 break; 1741 } 1742 log_debug("\tRouter Lifetime: %hds", 1743 ntohs(nd_ra->nd_ra_router_lifetime)); 1744 log_debug("\tReachable Time: %ums", ntohl(nd_ra->nd_ra_reachable)); 1745 log_debug("\tRetrans Timer: %ums", ntohl(nd_ra->nd_ra_retransmit)); 1746 1747 while ((size_t)len >= sizeof(struct nd_opt_hdr)) { 1748 struct nd_opt_hdr *nd_opt_hdr = (struct nd_opt_hdr *)p; 1749 struct nd_opt_mtu *mtu; 1750 struct nd_opt_prefix_info *prf; 1751 struct nd_opt_rdnss *rdnss; 1752 struct in6_addr *in6; 1753 int i; 1754 1755 len -= sizeof(struct nd_opt_hdr); 1756 p += sizeof(struct nd_opt_hdr); 1757 if (nd_opt_hdr->nd_opt_len * 8 - 2 > len) { 1758 log_warnx("invalid option len: %u > %ld", 1759 nd_opt_hdr->nd_opt_len, len); 1760 return; 1761 } 1762 log_debug("\tOption: %u (len: %u)", nd_opt_hdr->nd_opt_type, 1763 nd_opt_hdr->nd_opt_len * 8); 1764 switch (nd_opt_hdr->nd_opt_type) { 1765 case ND_OPT_SOURCE_LINKADDR: 1766 if (nd_opt_hdr->nd_opt_len == 1) 1767 log_debug("\t\tND_OPT_SOURCE_LINKADDR: " 1768 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 1769 p[0], p[1], p[2], p[3], p[4], p[5], p[6], 1770 p[7]); 1771 else 1772 log_debug("\t\tND_OPT_SOURCE_LINKADDR"); 1773 break; 1774 case ND_OPT_TARGET_LINKADDR: 1775 if (nd_opt_hdr->nd_opt_len == 1) 1776 log_debug("\t\tND_OPT_TARGET_LINKADDR: " 1777 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 1778 p[0], p[1], p[2], p[3], p[4], p[5], p[6], 1779 p[7]); 1780 else 1781 log_debug("\t\tND_OPT_TARGET_LINKADDR"); 1782 break; 1783 case ND_OPT_PREFIX_INFORMATION: 1784 if (nd_opt_hdr->nd_opt_len != 4) { 1785 log_warnx("invalid ND_OPT_PREFIX_INFORMATION: " 1786 "len != 4"); 1787 return; 1788 } 1789 prf = (struct nd_opt_prefix_info*) nd_opt_hdr; 1790 1791 log_debug("\t\tND_OPT_PREFIX_INFORMATION: %s/%u", 1792 inet_ntop(AF_INET6, &prf->nd_opt_pi_prefix, 1793 ntopbuf, INET6_ADDRSTRLEN), 1794 prf->nd_opt_pi_prefix_len); 1795 log_debug("\t\t\tOn-link: %d", 1796 prf->nd_opt_pi_flags_reserved & 1797 ND_OPT_PI_FLAG_ONLINK ? 1:0); 1798 log_debug("\t\t\tAutonomous address-configuration: %d", 1799 prf->nd_opt_pi_flags_reserved & 1800 ND_OPT_PI_FLAG_AUTO ? 1 : 0); 1801 log_debug("\t\t\tvltime: %u", 1802 ntohl(prf->nd_opt_pi_valid_time)); 1803 log_debug("\t\t\tpltime: %u", 1804 ntohl(prf->nd_opt_pi_preferred_time)); 1805 break; 1806 case ND_OPT_REDIRECTED_HEADER: 1807 log_debug("\t\tND_OPT_REDIRECTED_HEADER"); 1808 break; 1809 case ND_OPT_MTU: 1810 if (nd_opt_hdr->nd_opt_len != 1) { 1811 log_warnx("invalid ND_OPT_MTU: len != 1"); 1812 return; 1813 } 1814 mtu = (struct nd_opt_mtu*) nd_opt_hdr; 1815 log_debug("\t\tND_OPT_MTU: %u", 1816 ntohl(mtu->nd_opt_mtu_mtu)); 1817 break; 1818 case ND_OPT_ROUTE_INFO: 1819 log_debug("\t\tND_OPT_ROUTE_INFO"); 1820 break; 1821 case ND_OPT_RDNSS: 1822 if (nd_opt_hdr->nd_opt_len < 3) { 1823 log_warnx("invalid ND_OPT_RDNSS: len < 24"); 1824 return; 1825 } 1826 if ((nd_opt_hdr->nd_opt_len - 1) % 2 != 0) { 1827 log_warnx("invalid ND_OPT_RDNSS: length with" 1828 "out header is not multiply of 16: %d", 1829 (nd_opt_hdr->nd_opt_len - 1) * 8); 1830 return; 1831 } 1832 rdnss = (struct nd_opt_rdnss*) nd_opt_hdr; 1833 log_debug("\t\tND_OPT_RDNSS: lifetime: %u", ntohl( 1834 rdnss->nd_opt_rdnss_lifetime)); 1835 in6 = (struct in6_addr*) (p + 6); 1836 for (i=0; i < (nd_opt_hdr->nd_opt_len - 1)/2; i++, 1837 in6++) { 1838 log_debug("\t\t\t%s", inet_ntop(AF_INET6, in6, 1839 ntopbuf, INET6_ADDRSTRLEN)); 1840 } 1841 break; 1842 default: 1843 log_debug("\t\tUNKNOWN: %d", nd_opt_hdr->nd_opt_type); 1844 break; 1845 1846 } 1847 len -= nd_opt_hdr->nd_opt_len * 8 - 2; 1848 p += nd_opt_hdr->nd_opt_len * 8 - 2; 1849 } 1850 } 1851 #endif /* SMALL */ 1852 1853 void update_iface_ra(struct slaacd_iface *iface, struct radv *ra) 1854 { 1855 struct radv *old_ra; 1856 struct radv_prefix *prefix; 1857 1858 if ((old_ra = find_ra(iface, &ra->from)) == NULL) 1859 LIST_INSERT_HEAD(&iface->radvs, ra, entries); 1860 else { 1861 LIST_REPLACE(old_ra, ra, entries); 1862 merge_dad_couters(old_ra, ra); 1863 free_ra(old_ra); 1864 } 1865 1866 update_iface_ra_dfr(iface, ra); 1867 1868 LIST_FOREACH(prefix, &ra->prefixes, entries) { 1869 if (!prefix->autonomous || prefix->vltime == 0 || 1870 prefix->pltime > prefix->vltime || 1871 IN6_IS_ADDR_LINKLOCAL(&prefix->prefix)) 1872 continue; 1873 update_iface_ra_prefix(iface, ra, prefix); 1874 } 1875 1876 update_iface_ra_rdns(iface, ra); 1877 } 1878 1879 void 1880 update_iface_ra_dfr(struct slaacd_iface *iface, struct radv *ra) 1881 { 1882 struct dfr_proposal *dfr_proposal; 1883 1884 dfr_proposal = find_dfr_proposal_by_gw(iface, &ra->from); 1885 1886 if (ra->router_lifetime == 0) { 1887 free_dfr_proposal(dfr_proposal); 1888 return; 1889 } 1890 1891 if (!dfr_proposal) { 1892 /* new proposal */ 1893 gen_dfr_proposal(iface, ra); 1894 return; 1895 } 1896 1897 dfr_proposal->when = ra->when; 1898 dfr_proposal->uptime = ra->uptime; 1899 dfr_proposal->router_lifetime = ra->router_lifetime; 1900 1901 log_debug("%s, dfr state: %s, rl: %d", __func__, 1902 proposal_state_name(dfr_proposal->state), 1903 real_lifetime(&dfr_proposal->uptime, 1904 dfr_proposal->router_lifetime)); 1905 1906 switch (dfr_proposal->state) { 1907 case PROPOSAL_CONFIGURED: 1908 case PROPOSAL_NEARLY_EXPIRED: 1909 /* routes do not expire in the kernel, update timeout */ 1910 dfr_proposal_state_transition(dfr_proposal, 1911 PROPOSAL_CONFIGURED); 1912 break; 1913 case PROPOSAL_IF_DOWN: 1914 case PROPOSAL_WITHDRAWN: 1915 log_debug("updating dfr"); 1916 configure_dfr(dfr_proposal); 1917 break; 1918 default: 1919 log_debug("%s: iface %d: %s", __func__, iface->if_index, 1920 sin6_to_str(&dfr_proposal->addr)); 1921 break; 1922 } 1923 } 1924 1925 void 1926 update_iface_ra_prefix(struct slaacd_iface *iface, struct radv *ra, 1927 struct radv_prefix *prefix) 1928 { 1929 struct address_proposal *addr_proposal; 1930 uint32_t pltime, vltime; 1931 int found, found_temporary, duplicate_found; 1932 1933 found = found_temporary = duplicate_found = 0; 1934 1935 if (!!iface->autoconf != !!iface->temporary) { 1936 struct address_proposal *tmp; 1937 /* 1938 * If only the autoconf or temporary flag is set, check if we 1939 * have the "other kind" of address configured and delete it. 1940 */ 1941 LIST_FOREACH_SAFE (addr_proposal, &iface->addr_proposals, 1942 entries, tmp) { 1943 if ((!addr_proposal->temporary && !iface->autoconf) || 1944 (addr_proposal->temporary && !iface->temporary)) 1945 free_address_proposal(addr_proposal); 1946 } 1947 } 1948 1949 LIST_FOREACH(addr_proposal, &iface->addr_proposals, entries) { 1950 if (prefix->prefix_len == addr_proposal-> prefix_len && 1951 memcmp(&prefix->prefix, &addr_proposal->prefix, 1952 sizeof(struct in6_addr)) != 0) 1953 continue; 1954 1955 if (memcmp(&addr_proposal->hw_address, 1956 &iface->hw_address, 1957 sizeof(addr_proposal->hw_address)) != 0) 1958 continue; 1959 1960 if (memcmp(&addr_proposal->soiikey, &iface->soiikey, 1961 sizeof(addr_proposal->soiikey)) != 0) 1962 continue; 1963 1964 if (addr_proposal->state == PROPOSAL_DUPLICATED) { 1965 duplicate_found = 1; 1966 continue; 1967 } 1968 1969 vltime = prefix->vltime; 1970 1971 if (addr_proposal->temporary) { 1972 struct timespec now; 1973 int64_t ltime, mtime; 1974 1975 if (clock_gettime(CLOCK_MONOTONIC, &now)) 1976 fatal("clock_gettime"); 1977 1978 mtime = addr_proposal->created.tv_sec + 1979 PRIV_PREFERRED_LIFETIME - 1980 addr_proposal->desync_factor; 1981 1982 ltime = MINIMUM(mtime, now.tv_sec + prefix->pltime) - 1983 now.tv_sec; 1984 1985 pltime = ltime > 0 ? ltime : 0; 1986 1987 ltime = MINIMUM(addr_proposal->created.tv_sec + 1988 PRIV_VALID_LIFETIME, now.tv_sec + vltime) - 1989 now.tv_sec; 1990 vltime = ltime > 0 ? ltime : 0; 1991 1992 if ((mtime - now.tv_sec) > PRIV_REGEN_ADVANCE) 1993 found_temporary = 1; 1994 } else { 1995 pltime = prefix->pltime; 1996 found = 1; 1997 } 1998 1999 addr_proposal->from = ra->from; 2000 addr_proposal->when = ra->when; 2001 addr_proposal->uptime = ra->uptime; 2002 2003 addr_proposal->vltime = vltime; 2004 addr_proposal->pltime = pltime; 2005 2006 if (ra->mtu == iface->cur_mtu) 2007 addr_proposal->mtu = 0; 2008 else { 2009 addr_proposal->mtu = ra->mtu; 2010 iface->cur_mtu = ra->mtu; 2011 } 2012 2013 log_debug("%s, addr state: %s", __func__, 2014 proposal_state_name(addr_proposal->state)); 2015 2016 switch (addr_proposal->state) { 2017 case PROPOSAL_CONFIGURED: 2018 case PROPOSAL_NEARLY_EXPIRED: 2019 case PROPOSAL_IF_DOWN: 2020 case PROPOSAL_WITHDRAWN: 2021 log_debug("updating address"); 2022 configure_address(addr_proposal); 2023 break; 2024 default: 2025 log_debug("%s: iface %d: %s", __func__, iface->if_index, 2026 sin6_to_str(&addr_proposal->addr)); 2027 break; 2028 } 2029 } 2030 2031 if (!found && iface->autoconf && duplicate_found && iface->soii) { 2032 prefix->dad_counter++; 2033 log_debug("%s dad_counter: %d", __func__, prefix->dad_counter); 2034 gen_address_proposal(iface, ra, prefix, 0); 2035 } else if (!found && iface->autoconf && (iface->soii || 2036 prefix->prefix_len <= 64)) 2037 /* new proposal */ 2038 gen_address_proposal(iface, ra, prefix, 0); 2039 2040 /* temporary addresses do not depend on eui64 */ 2041 if (!found_temporary && iface->temporary) { 2042 if (prefix->pltime >= PRIV_REGEN_ADVANCE) { 2043 /* new temporary proposal */ 2044 gen_address_proposal(iface, ra, prefix, 1); 2045 } else if (prefix->pltime > 0) { 2046 log_warnx("%s: pltime from %s is too small: %d < %d; " 2047 "not generating temporary address", __func__, 2048 sin6_to_str(&ra->from), prefix->pltime, 2049 PRIV_REGEN_ADVANCE); 2050 } 2051 } 2052 } 2053 2054 void 2055 update_iface_ra_rdns(struct slaacd_iface *iface, struct radv *ra) 2056 { 2057 struct rdns_proposal *rdns_proposal; 2058 struct radv_rdns *radv_rdns; 2059 struct in6_addr rdns[MAX_RDNS_COUNT]; 2060 int rdns_count; 2061 2062 rdns_proposal = find_rdns_proposal_by_gw(iface, &ra->from); 2063 2064 if (!rdns_proposal) { 2065 /* new proposal */ 2066 if (!LIST_EMPTY(&ra->rdns_servers)) 2067 gen_rdns_proposal(iface, ra); 2068 return; 2069 } 2070 2071 rdns_count = 0; 2072 memset(&rdns, 0, sizeof(rdns)); 2073 LIST_FOREACH(radv_rdns, &ra->rdns_servers, entries) { 2074 memcpy(&rdns[rdns_count++], 2075 &radv_rdns->rdns, sizeof(struct in6_addr)); 2076 if (rdns_proposal->rdns_count == MAX_RDNS_COUNT) 2077 break; 2078 } 2079 2080 if (rdns_count == 0) { 2081 free_rdns_proposal(rdns_proposal); 2082 return; 2083 } 2084 2085 if (rdns_proposal->rdns_count != rdns_count || 2086 memcmp(&rdns_proposal->rdns, &rdns, sizeof(rdns)) != 0) { 2087 memcpy(&rdns_proposal->rdns, &rdns, sizeof(rdns)); 2088 rdns_proposal->rdns_count = rdns_count; 2089 rdns_proposal->state = PROPOSAL_NOT_CONFIGURED; 2090 } 2091 rdns_proposal->when = ra->when; 2092 rdns_proposal->uptime = ra->uptime; 2093 rdns_proposal->rdns_lifetime = ra->rdns_lifetime; 2094 2095 log_debug("%s, rdns state: %s, rl: %d", __func__, 2096 proposal_state_name(rdns_proposal->state), 2097 real_lifetime(&rdns_proposal->uptime, 2098 rdns_proposal->rdns_lifetime)); 2099 2100 switch (rdns_proposal->state) { 2101 case PROPOSAL_CONFIGURED: 2102 case PROPOSAL_NEARLY_EXPIRED: 2103 /* rdns are not expired by the kernel, update timeout */ 2104 rdns_proposal_state_transition(rdns_proposal, 2105 PROPOSAL_CONFIGURED); 2106 break; 2107 case PROPOSAL_IF_DOWN: 2108 case PROPOSAL_WITHDRAWN: 2109 case PROPOSAL_NOT_CONFIGURED: 2110 log_debug("updating rdns"); 2111 rdns_proposal_state_transition(rdns_proposal, 2112 PROPOSAL_CONFIGURED); 2113 compose_rdns_proposal(rdns_proposal->if_index, 2114 rdns_proposal->rdomain); 2115 break; 2116 default: 2117 log_debug("%s: iface %d: %s", __func__, iface->if_index, 2118 sin6_to_str(&rdns_proposal->from)); 2119 break; 2120 } 2121 } 2122 2123 2124 void 2125 configure_address(struct address_proposal *addr_proposal) 2126 { 2127 struct imsg_configure_address address; 2128 struct slaacd_iface *iface; 2129 2130 log_debug("%s: %d", __func__, addr_proposal->if_index); 2131 2132 address.if_index = addr_proposal->if_index; 2133 memcpy(&address.addr, &addr_proposal->addr, sizeof(address.addr)); 2134 memcpy(&address.mask, &addr_proposal->mask, sizeof(address.mask)); 2135 address.vltime = addr_proposal->vltime; 2136 address.pltime = addr_proposal->pltime; 2137 address.temporary = addr_proposal->temporary; 2138 address.mtu = addr_proposal->mtu; 2139 2140 engine_imsg_compose_main(IMSG_CONFIGURE_ADDRESS, 0, &address, 2141 sizeof(address)); 2142 2143 if ((iface = get_slaacd_iface_by_id(addr_proposal->if_index)) != NULL) 2144 iface_state_transition(iface, IF_BOUND); 2145 addr_proposal_state_transition(addr_proposal, PROPOSAL_CONFIGURED); 2146 } 2147 2148 void 2149 gen_address_proposal(struct slaacd_iface *iface, struct radv *ra, struct 2150 radv_prefix *prefix, int temporary) 2151 { 2152 struct address_proposal *addr_proposal; 2153 const char *hbuf; 2154 2155 if ((addr_proposal = calloc(1, sizeof(*addr_proposal))) == NULL) 2156 fatal("calloc"); 2157 addr_proposal->id = ++proposal_id; 2158 evtimer_set(&addr_proposal->timer, address_proposal_timeout, 2159 addr_proposal); 2160 addr_proposal->timo.tv_sec = 1; 2161 addr_proposal->timo.tv_usec = arc4random_uniform(1000000); 2162 addr_proposal->state = PROPOSAL_NOT_CONFIGURED; 2163 if (clock_gettime(CLOCK_MONOTONIC, &addr_proposal->created)) 2164 fatal("clock_gettime"); 2165 addr_proposal->when = ra->when; 2166 addr_proposal->uptime = ra->uptime; 2167 addr_proposal->if_index = iface->if_index; 2168 memcpy(&addr_proposal->from, &ra->from, 2169 sizeof(addr_proposal->from)); 2170 memcpy(&addr_proposal->hw_address, &iface->hw_address, 2171 sizeof(addr_proposal->hw_address)); 2172 memcpy(&addr_proposal->soiikey, &iface->soiikey, 2173 sizeof(addr_proposal->soiikey)); 2174 addr_proposal->temporary = temporary; 2175 memcpy(&addr_proposal->prefix, &prefix->prefix, 2176 sizeof(addr_proposal->prefix)); 2177 addr_proposal->prefix_len = prefix->prefix_len; 2178 2179 if (temporary) { 2180 addr_proposal->vltime = MINIMUM(prefix->vltime, 2181 PRIV_VALID_LIFETIME); 2182 addr_proposal->desync_factor = 2183 arc4random_uniform(PRIV_MAX_DESYNC_FACTOR); 2184 2185 addr_proposal->pltime = MINIMUM(prefix->pltime, 2186 PRIV_PREFERRED_LIFETIME - addr_proposal->desync_factor); 2187 } else { 2188 addr_proposal->vltime = prefix->vltime; 2189 addr_proposal->pltime = prefix->pltime; 2190 } 2191 2192 if (ra->mtu == iface->cur_mtu) 2193 addr_proposal->mtu = 0; 2194 else { 2195 addr_proposal->mtu = ra->mtu; 2196 iface->cur_mtu = ra->mtu; 2197 } 2198 2199 gen_addr(iface, prefix, addr_proposal, temporary); 2200 2201 LIST_INSERT_HEAD(&iface->addr_proposals, addr_proposal, entries); 2202 configure_address(addr_proposal); 2203 2204 hbuf = sin6_to_str(&addr_proposal->addr); 2205 log_debug("%s: iface %d: %s", __func__, iface->if_index, hbuf); 2206 } 2207 2208 void 2209 free_address_proposal(struct address_proposal *addr_proposal) 2210 { 2211 if (addr_proposal == NULL) 2212 return; 2213 2214 LIST_REMOVE(addr_proposal, entries); 2215 evtimer_del(&addr_proposal->timer); 2216 switch (addr_proposal->state) { 2217 case PROPOSAL_CONFIGURED: 2218 case PROPOSAL_NEARLY_EXPIRED: 2219 case PROPOSAL_STALE: 2220 withdraw_addr(addr_proposal); 2221 break; 2222 default: 2223 break; 2224 } 2225 free(addr_proposal); 2226 } 2227 2228 void 2229 withdraw_addr(struct address_proposal *addr_proposal) 2230 { 2231 struct imsg_configure_address address; 2232 2233 log_debug("%s: %d", __func__, addr_proposal->if_index); 2234 memset(&address, 0, sizeof(address)); 2235 address.if_index = addr_proposal->if_index; 2236 memcpy(&address.addr, &addr_proposal->addr, sizeof(address.addr)); 2237 2238 engine_imsg_compose_main(IMSG_WITHDRAW_ADDRESS, 0, &address, 2239 sizeof(address)); 2240 } 2241 2242 void 2243 gen_dfr_proposal(struct slaacd_iface *iface, struct radv *ra) 2244 { 2245 struct dfr_proposal *dfr_proposal; 2246 const char *hbuf; 2247 2248 if ((dfr_proposal = calloc(1, sizeof(*dfr_proposal))) == NULL) 2249 fatal("calloc"); 2250 dfr_proposal->id = ++proposal_id; 2251 evtimer_set(&dfr_proposal->timer, dfr_proposal_timeout, 2252 dfr_proposal); 2253 dfr_proposal->timo.tv_sec = 1; 2254 dfr_proposal->timo.tv_usec = arc4random_uniform(1000000); 2255 dfr_proposal->state = PROPOSAL_NOT_CONFIGURED; 2256 dfr_proposal->when = ra->when; 2257 dfr_proposal->uptime = ra->uptime; 2258 dfr_proposal->if_index = iface->if_index; 2259 dfr_proposal->rdomain = iface->rdomain; 2260 memcpy(&dfr_proposal->addr, &ra->from, 2261 sizeof(dfr_proposal->addr)); 2262 dfr_proposal->router_lifetime = ra->router_lifetime; 2263 dfr_proposal->rpref = ra->rpref; 2264 2265 LIST_INSERT_HEAD(&iface->dfr_proposals, dfr_proposal, entries); 2266 configure_dfr(dfr_proposal); 2267 2268 hbuf = sin6_to_str(&dfr_proposal->addr); 2269 log_debug("%s: iface %d: %s", __func__, iface->if_index, hbuf); 2270 } 2271 2272 void 2273 configure_dfr(struct dfr_proposal *dfr_proposal) 2274 { 2275 struct imsg_configure_dfr dfr; 2276 2277 log_debug("%s: %d", __func__, dfr_proposal->if_index); 2278 2279 dfr.if_index = dfr_proposal->if_index; 2280 dfr.rdomain = dfr_proposal->rdomain; 2281 memcpy(&dfr.addr, &dfr_proposal->addr, sizeof(dfr.addr)); 2282 dfr.router_lifetime = dfr_proposal->router_lifetime; 2283 2284 engine_imsg_compose_main(IMSG_CONFIGURE_DFR, 0, &dfr, sizeof(dfr)); 2285 2286 dfr_proposal_state_transition(dfr_proposal, PROPOSAL_CONFIGURED); 2287 } 2288 2289 void 2290 withdraw_dfr(struct dfr_proposal *dfr_proposal) 2291 { 2292 struct imsg_configure_dfr dfr; 2293 2294 log_debug("%s: %d", __func__, dfr_proposal->if_index); 2295 2296 dfr.if_index = dfr_proposal->if_index; 2297 dfr.rdomain = dfr_proposal->rdomain; 2298 memcpy(&dfr.addr, &dfr_proposal->addr, sizeof(dfr.addr)); 2299 dfr.router_lifetime = dfr_proposal->router_lifetime; 2300 2301 engine_imsg_compose_main(IMSG_WITHDRAW_DFR, 0, &dfr, sizeof(dfr)); 2302 } 2303 2304 void 2305 free_dfr_proposal(struct dfr_proposal *dfr_proposal) 2306 { 2307 if (dfr_proposal == NULL) 2308 return; 2309 2310 LIST_REMOVE(dfr_proposal, entries); 2311 evtimer_del(&dfr_proposal->timer); 2312 switch (dfr_proposal->state) { 2313 case PROPOSAL_CONFIGURED: 2314 case PROPOSAL_NEARLY_EXPIRED: 2315 case PROPOSAL_STALE: 2316 withdraw_dfr(dfr_proposal); 2317 break; 2318 default: 2319 break; 2320 } 2321 free(dfr_proposal); 2322 } 2323 2324 void 2325 gen_rdns_proposal(struct slaacd_iface *iface, struct radv *ra) 2326 { 2327 struct rdns_proposal *rdns_proposal; 2328 struct radv_rdns *rdns; 2329 const char *hbuf; 2330 2331 if ((rdns_proposal = calloc(1, sizeof(*rdns_proposal))) == NULL) 2332 fatal("calloc"); 2333 rdns_proposal->id = ++proposal_id; 2334 evtimer_set(&rdns_proposal->timer, rdns_proposal_timeout, 2335 rdns_proposal); 2336 rdns_proposal->timo.tv_sec = 1; 2337 rdns_proposal->timo.tv_usec = arc4random_uniform(1000000); 2338 rdns_proposal->state = PROPOSAL_NOT_CONFIGURED; 2339 rdns_proposal->when = ra->when; 2340 rdns_proposal->uptime = ra->uptime; 2341 rdns_proposal->if_index = iface->if_index; 2342 rdns_proposal->rdomain = iface->rdomain; 2343 memcpy(&rdns_proposal->from, &ra->from, 2344 sizeof(rdns_proposal->from)); 2345 rdns_proposal->rdns_lifetime = ra->rdns_lifetime; 2346 LIST_FOREACH(rdns, &ra->rdns_servers, entries) { 2347 memcpy(&rdns_proposal->rdns[rdns_proposal->rdns_count++], 2348 &rdns->rdns, sizeof(struct in6_addr)); 2349 if (rdns_proposal->rdns_count == MAX_RDNS_COUNT) 2350 break; 2351 } 2352 2353 LIST_INSERT_HEAD(&iface->rdns_proposals, rdns_proposal, entries); 2354 compose_rdns_proposal(iface->if_index, iface->rdomain); 2355 2356 hbuf = sin6_to_str(&rdns_proposal->from); 2357 log_debug("%s: iface %d: %s", __func__, iface->if_index, hbuf); 2358 } 2359 2360 void 2361 compose_rdns_proposal(uint32_t if_index, int rdomain) 2362 { 2363 struct imsg_propose_rdns rdns; 2364 struct slaacd_iface *iface; 2365 struct rdns_proposal *rdns_proposal; 2366 int i; 2367 2368 memset(&rdns, 0, sizeof(rdns)); 2369 rdns.if_index = if_index; 2370 rdns.rdomain = rdomain; 2371 2372 if ((iface = get_slaacd_iface_by_id(if_index)) != NULL) { 2373 LIST_FOREACH(rdns_proposal, &iface->rdns_proposals, entries) { 2374 if (rdns_proposal->state == PROPOSAL_WITHDRAWN || 2375 rdns_proposal->state == PROPOSAL_STALE) 2376 continue; 2377 rdns_proposal_state_transition(rdns_proposal, 2378 PROPOSAL_CONFIGURED); 2379 for (i = 0; i < rdns_proposal->rdns_count && 2380 rdns.rdns_count < MAX_RDNS_COUNT; i++) { 2381 rdns.rdns[rdns.rdns_count++] = 2382 rdns_proposal->rdns[i]; 2383 } 2384 } 2385 } 2386 2387 engine_imsg_compose_main(IMSG_PROPOSE_RDNS, 0, &rdns, sizeof(rdns)); 2388 } 2389 2390 void 2391 free_rdns_proposal(struct rdns_proposal *rdns_proposal) 2392 { 2393 if (rdns_proposal == NULL) 2394 return; 2395 2396 LIST_REMOVE(rdns_proposal, entries); 2397 evtimer_del(&rdns_proposal->timer); 2398 switch (rdns_proposal->state) { 2399 case PROPOSAL_CONFIGURED: 2400 case PROPOSAL_NEARLY_EXPIRED: 2401 case PROPOSAL_STALE: 2402 withdraw_rdns(rdns_proposal); 2403 break; 2404 default: 2405 break; 2406 } 2407 free(rdns_proposal); 2408 } 2409 2410 void 2411 withdraw_rdns(struct rdns_proposal *rdns_proposal) 2412 { 2413 log_debug("%s: %d", __func__, rdns_proposal->if_index); 2414 2415 rdns_proposal->state = PROPOSAL_WITHDRAWN; 2416 2417 /* we have to re-propose all rdns servers, minus one */ 2418 compose_rdns_proposal(rdns_proposal->if_index, rdns_proposal->rdomain); 2419 } 2420 2421 void 2422 address_proposal_timeout(int fd, short events, void *arg) 2423 { 2424 struct address_proposal *addr_proposal; 2425 struct slaacd_iface *iface = NULL; 2426 struct radv *ra = NULL; 2427 struct radv_prefix *prefix = NULL; 2428 const char *hbuf; 2429 2430 addr_proposal = (struct address_proposal *)arg; 2431 2432 hbuf = sin6_to_str(&addr_proposal->addr); 2433 log_debug("%s: iface %d: %s [%s], priv: %s", __func__, 2434 addr_proposal->if_index, hbuf, 2435 proposal_state_name(addr_proposal->state), 2436 addr_proposal->temporary ? "y" : "n"); 2437 2438 switch (addr_proposal->state) { 2439 case PROPOSAL_IF_DOWN: 2440 addr_proposal_state_transition(addr_proposal, PROPOSAL_STALE); 2441 break; 2442 case PROPOSAL_CONFIGURED: 2443 addr_proposal_state_transition(addr_proposal, 2444 PROPOSAL_NEARLY_EXPIRED); 2445 break; 2446 case PROPOSAL_NEARLY_EXPIRED: 2447 if (real_lifetime(&addr_proposal->uptime, 2448 addr_proposal->vltime) > 0) 2449 addr_proposal_state_transition(addr_proposal, 2450 PROPOSAL_NEARLY_EXPIRED); 2451 else 2452 addr_proposal_state_transition(addr_proposal, 2453 PROPOSAL_STALE); 2454 break; 2455 case PROPOSAL_DUPLICATED: 2456 iface = get_slaacd_iface_by_id(addr_proposal->if_index); 2457 if (iface != NULL) 2458 ra = find_ra(iface, &addr_proposal->from); 2459 if (ra != NULL) 2460 prefix = find_prefix(ra, &addr_proposal->prefix, 2461 addr_proposal->prefix_len); 2462 if (prefix != NULL) { 2463 if (!addr_proposal->temporary) { 2464 prefix->dad_counter++; 2465 gen_address_proposal(iface, ra, prefix, 0); 2466 } else 2467 gen_address_proposal(iface, ra, prefix, 1); 2468 } 2469 addr_proposal_state_transition(addr_proposal, PROPOSAL_STALE); 2470 break; 2471 case PROPOSAL_STALE: 2472 free_address_proposal(addr_proposal); 2473 addr_proposal = NULL; 2474 break; 2475 case PROPOSAL_WITHDRAWN: 2476 free_address_proposal(addr_proposal); 2477 addr_proposal = NULL; 2478 break; 2479 default: 2480 log_debug("%s: unhandled state: %s", __func__, 2481 proposal_state_name(addr_proposal->state)); 2482 } 2483 } 2484 2485 void 2486 dfr_proposal_timeout(int fd, short events, void *arg) 2487 { 2488 struct dfr_proposal *dfr_proposal; 2489 const char *hbuf; 2490 2491 dfr_proposal = (struct dfr_proposal *)arg; 2492 2493 hbuf = sin6_to_str(&dfr_proposal->addr); 2494 log_debug("%s: iface %d: %s [%s]", __func__, dfr_proposal->if_index, 2495 hbuf, proposal_state_name(dfr_proposal->state)); 2496 2497 switch (dfr_proposal->state) { 2498 case PROPOSAL_IF_DOWN: 2499 dfr_proposal_state_transition(dfr_proposal, PROPOSAL_STALE); 2500 break; 2501 case PROPOSAL_CONFIGURED: 2502 dfr_proposal_state_transition(dfr_proposal, 2503 PROPOSAL_NEARLY_EXPIRED); 2504 break; 2505 case PROPOSAL_NEARLY_EXPIRED: 2506 if (real_lifetime(&dfr_proposal->uptime, 2507 dfr_proposal->router_lifetime) > 0) 2508 dfr_proposal_state_transition(dfr_proposal, 2509 PROPOSAL_NEARLY_EXPIRED); 2510 else 2511 dfr_proposal_state_transition(dfr_proposal, 2512 PROPOSAL_STALE); 2513 break; 2514 case PROPOSAL_STALE: 2515 free_dfr_proposal(dfr_proposal); 2516 dfr_proposal = NULL; 2517 break; 2518 case PROPOSAL_WITHDRAWN: 2519 free_dfr_proposal(dfr_proposal); 2520 dfr_proposal = NULL; 2521 break; 2522 2523 default: 2524 log_debug("%s: unhandled state: %s", __func__, 2525 proposal_state_name(dfr_proposal->state)); 2526 } 2527 } 2528 2529 void 2530 rdns_proposal_timeout(int fd, short events, void *arg) 2531 { 2532 struct rdns_proposal *rdns_proposal; 2533 const char *hbuf; 2534 2535 rdns_proposal = (struct rdns_proposal *)arg; 2536 2537 hbuf = sin6_to_str(&rdns_proposal->from); 2538 log_debug("%s: iface %d: %s [%s]", __func__, rdns_proposal->if_index, 2539 hbuf, proposal_state_name(rdns_proposal->state)); 2540 2541 switch (rdns_proposal->state) { 2542 case PROPOSAL_IF_DOWN: 2543 rdns_proposal_state_transition(rdns_proposal, PROPOSAL_STALE); 2544 break; 2545 case PROPOSAL_CONFIGURED: 2546 rdns_proposal_state_transition(rdns_proposal, 2547 PROPOSAL_NEARLY_EXPIRED); 2548 break; 2549 case PROPOSAL_NEARLY_EXPIRED: 2550 if (real_lifetime(&rdns_proposal->uptime, 2551 rdns_proposal->rdns_lifetime) > 0) 2552 rdns_proposal_state_transition(rdns_proposal, 2553 PROPOSAL_NEARLY_EXPIRED); 2554 else 2555 rdns_proposal_state_transition(rdns_proposal, 2556 PROPOSAL_STALE); 2557 break; 2558 case PROPOSAL_STALE: 2559 free_rdns_proposal(rdns_proposal); 2560 rdns_proposal = NULL; 2561 break; 2562 case PROPOSAL_WITHDRAWN: 2563 free_rdns_proposal(rdns_proposal); 2564 rdns_proposal = NULL; 2565 break; 2566 2567 default: 2568 log_debug("%s: unhandled state: %s", __func__, 2569 proposal_state_name(rdns_proposal->state)); 2570 } 2571 } 2572 2573 void 2574 iface_timeout(int fd, short events, void *arg) 2575 { 2576 struct slaacd_iface *iface = (struct slaacd_iface *)arg; 2577 2578 log_debug("%s[%d]: %s", __func__, iface->if_index, 2579 if_state_name(iface->state)); 2580 2581 switch (iface->state) { 2582 case IF_DOWN: 2583 fatalx("%s: timeout in wrong state IF_DOWN", __func__); 2584 break; 2585 case IF_INIT: 2586 iface_state_transition(iface, IF_INIT); 2587 break; 2588 default: 2589 break; 2590 } 2591 } 2592 2593 struct radv* 2594 find_ra(struct slaacd_iface *iface, struct sockaddr_in6 *from) 2595 { 2596 struct radv *ra; 2597 2598 LIST_FOREACH (ra, &iface->radvs, entries) { 2599 if (memcmp(&ra->from.sin6_addr, &from->sin6_addr, 2600 sizeof(from->sin6_addr)) == 0) 2601 return (ra); 2602 } 2603 2604 return (NULL); 2605 } 2606 2607 struct address_proposal* 2608 find_address_proposal_by_addr(struct slaacd_iface *iface, struct sockaddr_in6 2609 *addr) 2610 { 2611 struct address_proposal *addr_proposal; 2612 2613 LIST_FOREACH (addr_proposal, &iface->addr_proposals, entries) { 2614 if (memcmp(&addr_proposal->addr, addr, sizeof(*addr)) == 0) 2615 return (addr_proposal); 2616 } 2617 2618 return (NULL); 2619 } 2620 2621 struct dfr_proposal* 2622 find_dfr_proposal_by_gw(struct slaacd_iface *iface, struct sockaddr_in6 2623 *addr) 2624 { 2625 struct dfr_proposal *dfr_proposal; 2626 2627 LIST_FOREACH (dfr_proposal, &iface->dfr_proposals, entries) { 2628 if (memcmp(&dfr_proposal->addr, addr, sizeof(*addr)) == 0) 2629 return (dfr_proposal); 2630 } 2631 2632 return (NULL); 2633 } 2634 2635 struct rdns_proposal* 2636 find_rdns_proposal_by_gw(struct slaacd_iface *iface, struct sockaddr_in6 2637 *from) 2638 { 2639 struct rdns_proposal *rdns_proposal; 2640 2641 LIST_FOREACH (rdns_proposal, &iface->rdns_proposals, entries) { 2642 if (memcmp(&rdns_proposal->from, from, sizeof(*from)) == 0) 2643 return (rdns_proposal); 2644 } 2645 2646 return (NULL); 2647 } 2648 2649 struct radv_prefix * 2650 find_prefix(struct radv *ra, struct in6_addr *prefix, uint8_t prefix_len) 2651 { 2652 struct radv_prefix *result; 2653 2654 2655 LIST_FOREACH(result, &ra->prefixes, entries) { 2656 if (memcmp(&result->prefix, prefix, 2657 sizeof(result->prefix)) == 0 && result->prefix_len == 2658 prefix_len) 2659 return (result); 2660 } 2661 return (NULL); 2662 } 2663 2664 uint32_t 2665 real_lifetime(struct timespec *received_uptime, uint32_t ltime) 2666 { 2667 struct timespec now, diff; 2668 int64_t remaining; 2669 2670 if (clock_gettime(CLOCK_MONOTONIC, &now)) 2671 fatal("clock_gettime"); 2672 2673 timespecsub(&now, received_uptime, &diff); 2674 2675 remaining = ((int64_t)ltime) - diff.tv_sec; 2676 2677 if (remaining < 0) 2678 remaining = 0; 2679 2680 return (remaining); 2681 } 2682 2683 void 2684 merge_dad_couters(struct radv *old_ra, struct radv *new_ra) 2685 { 2686 2687 struct radv_prefix *old_prefix, *new_prefix; 2688 2689 LIST_FOREACH(old_prefix, &old_ra->prefixes, entries) { 2690 if (!old_prefix->dad_counter) 2691 continue; 2692 if ((new_prefix = find_prefix(new_ra, &old_prefix->prefix, 2693 old_prefix->prefix_len)) != NULL) 2694 new_prefix->dad_counter = old_prefix->dad_counter; 2695 } 2696 } 2697