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