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