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