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