1 /* $OpenBSD: engine.c,v 1.21 2022/10/15 13:26:15 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2018 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 #include <sys/types.h> 23 #include <sys/queue.h> 24 #include <sys/socket.h> 25 #include <sys/syslog.h> 26 #include <sys/time.h> 27 #include <sys/uio.h> 28 29 #include <netinet/in.h> 30 #include <net/if.h> 31 #include <arpa/inet.h> 32 #include <netinet/icmp6.h> 33 34 #include <errno.h> 35 #include <event.h> 36 #include <imsg.h> 37 #include <pwd.h> 38 #include <signal.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <time.h> 42 #include <unistd.h> 43 44 #include "log.h" 45 #include "rad.h" 46 #include "engine.h" 47 48 struct engine_iface { 49 TAILQ_ENTRY(engine_iface) entry; 50 struct event timer; 51 struct timespec last_ra; 52 uint32_t if_index; 53 int ras_delayed; 54 }; 55 56 TAILQ_HEAD(, engine_iface) engine_interfaces; 57 58 59 __dead void engine_shutdown(void); 60 void engine_sig_handler(int sig, short, void *); 61 void engine_dispatch_frontend(int, short, void *); 62 void engine_dispatch_main(int, short, void *); 63 void parse_ra_rs(struct imsg_ra_rs *); 64 void parse_ra(struct imsg_ra_rs *); 65 void parse_rs(struct imsg_ra_rs *); 66 void update_iface(uint32_t); 67 void remove_iface(uint32_t); 68 struct engine_iface *find_engine_iface_by_id(uint32_t); 69 void iface_timeout(int, short, void *); 70 71 struct rad_conf *engine_conf; 72 static struct imsgev *iev_frontend; 73 static struct imsgev *iev_main; 74 struct sockaddr_in6 all_nodes; 75 76 void 77 engine_sig_handler(int sig, short event, void *arg) 78 { 79 /* 80 * Normal signal handler rules don't apply because libevent 81 * decouples for us. 82 */ 83 84 switch (sig) { 85 case SIGINT: 86 case SIGTERM: 87 engine_shutdown(); 88 default: 89 fatalx("unexpected signal"); 90 } 91 } 92 93 void 94 engine(int debug, int verbose) 95 { 96 struct event ev_sigint, ev_sigterm; 97 struct passwd *pw; 98 99 engine_conf = config_new_empty(); 100 101 log_init(debug, LOG_DAEMON); 102 log_setverbose(verbose); 103 104 if ((pw = getpwnam(RAD_USER)) == NULL) 105 fatal("getpwnam"); 106 107 if (chroot(pw->pw_dir) == -1) 108 fatal("chroot"); 109 if (chdir("/") == -1) 110 fatal("chdir(\"/\")"); 111 112 setproctitle("%s", "engine"); 113 log_procinit("engine"); 114 115 if (setgroups(1, &pw->pw_gid) || 116 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 117 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 118 fatal("can't drop privileges"); 119 120 if (pledge("stdio recvfd", NULL) == -1) 121 fatal("pledge"); 122 123 event_init(); 124 125 /* Setup signal handler(s). */ 126 signal_set(&ev_sigint, SIGINT, engine_sig_handler, NULL); 127 signal_set(&ev_sigterm, SIGTERM, engine_sig_handler, NULL); 128 signal_add(&ev_sigint, NULL); 129 signal_add(&ev_sigterm, NULL); 130 signal(SIGPIPE, SIG_IGN); 131 signal(SIGHUP, SIG_IGN); 132 133 /* Setup pipe and event handler to the main process. */ 134 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 135 fatal(NULL); 136 137 imsg_init(&iev_main->ibuf, 3); 138 iev_main->handler = engine_dispatch_main; 139 140 /* Setup event handlers. */ 141 iev_main->events = EV_READ; 142 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 143 iev_main->handler, iev_main); 144 event_add(&iev_main->ev, NULL); 145 146 all_nodes.sin6_len = sizeof(all_nodes); 147 all_nodes.sin6_family = AF_INET6; 148 if (inet_pton(AF_INET6, "ff02::1", &all_nodes.sin6_addr) != 1) 149 fatal("inet_pton"); 150 151 TAILQ_INIT(&engine_interfaces); 152 153 event_dispatch(); 154 155 engine_shutdown(); 156 } 157 158 __dead void 159 engine_shutdown(void) 160 { 161 /* Close pipes. */ 162 msgbuf_clear(&iev_frontend->ibuf.w); 163 close(iev_frontend->ibuf.fd); 164 msgbuf_clear(&iev_main->ibuf.w); 165 close(iev_main->ibuf.fd); 166 167 config_clear(engine_conf); 168 169 free(iev_frontend); 170 free(iev_main); 171 172 log_info("engine exiting"); 173 exit(0); 174 } 175 176 int 177 engine_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) 178 { 179 return (imsg_compose_event(iev_frontend, type, 0, pid, -1, 180 data, datalen)); 181 } 182 183 void 184 engine_dispatch_frontend(int fd, short event, void *bula) 185 { 186 struct imsgev *iev = bula; 187 struct imsgbuf *ibuf; 188 struct imsg imsg; 189 struct imsg_ra_rs ra_rs; 190 ssize_t n; 191 uint32_t if_index; 192 int shut = 0, verbose; 193 194 ibuf = &iev->ibuf; 195 196 if (event & EV_READ) { 197 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 198 fatal("imsg_read error"); 199 if (n == 0) /* Connection closed. */ 200 shut = 1; 201 } 202 if (event & EV_WRITE) { 203 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 204 fatal("msgbuf_write"); 205 if (n == 0) /* Connection closed. */ 206 shut = 1; 207 } 208 209 for (;;) { 210 if ((n = imsg_get(ibuf, &imsg)) == -1) 211 fatal("%s: imsg_get error", __func__); 212 if (n == 0) /* No more messages. */ 213 break; 214 215 switch (imsg.hdr.type) { 216 case IMSG_RA_RS: 217 if (IMSG_DATA_SIZE(imsg) != sizeof(ra_rs)) 218 fatalx("%s: IMSG_RA_RS wrong length: %lu", 219 __func__, IMSG_DATA_SIZE(imsg)); 220 memcpy(&ra_rs, imsg.data, sizeof(ra_rs)); 221 parse_ra_rs(&ra_rs); 222 break; 223 case IMSG_UPDATE_IF: 224 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 225 fatalx("%s: IMSG_UPDATE_IF wrong length: %lu", 226 __func__, IMSG_DATA_SIZE(imsg)); 227 memcpy(&if_index, imsg.data, sizeof(if_index)); 228 update_iface(if_index); 229 break; 230 case IMSG_REMOVE_IF: 231 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 232 fatalx("%s: IMSG_REMOVE_IF wrong length: %lu", 233 __func__, IMSG_DATA_SIZE(imsg)); 234 memcpy(&if_index, imsg.data, sizeof(if_index)); 235 remove_iface(if_index); 236 break; 237 case IMSG_CTL_LOG_VERBOSE: 238 if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 239 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 240 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 241 memcpy(&verbose, imsg.data, sizeof(verbose)); 242 log_setverbose(verbose); 243 break; 244 default: 245 log_debug("%s: unexpected imsg %d", __func__, 246 imsg.hdr.type); 247 break; 248 } 249 imsg_free(&imsg); 250 } 251 if (!shut) 252 imsg_event_add(iev); 253 else { 254 /* This pipe is dead. Remove its event handler. */ 255 event_del(&iev->ev); 256 event_loopexit(NULL); 257 } 258 } 259 260 void 261 engine_dispatch_main(int fd, short event, void *bula) 262 { 263 static struct rad_conf *nconf; 264 static struct ra_iface_conf *ra_iface_conf; 265 static struct ra_options_conf *ra_options; 266 struct imsg imsg; 267 struct imsgev *iev = bula; 268 struct imsgbuf *ibuf; 269 struct ra_prefix_conf *ra_prefix_conf; 270 struct ra_rdnss_conf *ra_rdnss_conf; 271 struct ra_dnssl_conf *ra_dnssl_conf; 272 struct ra_pref64_conf *pref64; 273 ssize_t n; 274 int shut = 0; 275 276 ibuf = &iev->ibuf; 277 278 if (event & EV_READ) { 279 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 280 fatal("imsg_read error"); 281 if (n == 0) /* Connection closed. */ 282 shut = 1; 283 } 284 if (event & EV_WRITE) { 285 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 286 fatal("msgbuf_write"); 287 if (n == 0) /* Connection closed. */ 288 shut = 1; 289 } 290 291 for (;;) { 292 if ((n = imsg_get(ibuf, &imsg)) == -1) 293 fatal("%s: imsg_get error", __func__); 294 if (n == 0) /* No more messages. */ 295 break; 296 297 switch (imsg.hdr.type) { 298 case IMSG_SOCKET_IPC: 299 /* 300 * Setup pipe and event handler to the frontend 301 * process. 302 */ 303 if (iev_frontend) 304 fatalx("%s: received unexpected imsg fd " 305 "to engine", __func__); 306 307 if ((fd = imsg.fd) == -1) 308 fatalx("%s: expected to receive imsg fd to " 309 "engine but didn't receive any", __func__); 310 311 iev_frontend = malloc(sizeof(struct imsgev)); 312 if (iev_frontend == NULL) 313 fatal(NULL); 314 315 imsg_init(&iev_frontend->ibuf, fd); 316 iev_frontend->handler = engine_dispatch_frontend; 317 iev_frontend->events = EV_READ; 318 319 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 320 iev_frontend->events, iev_frontend->handler, 321 iev_frontend); 322 event_add(&iev_frontend->ev, NULL); 323 break; 324 case IMSG_RECONF_CONF: 325 if (nconf != NULL) 326 fatalx("%s: IMSG_RECONF_CONF already in " 327 "progress", __func__); 328 if (IMSG_DATA_SIZE(imsg) != sizeof(struct rad_conf)) 329 fatalx("%s: IMSG_RECONF_CONF wrong length: %lu", 330 __func__, IMSG_DATA_SIZE(imsg)); 331 if ((nconf = malloc(sizeof(struct rad_conf))) == NULL) 332 fatal(NULL); 333 memcpy(nconf, imsg.data, sizeof(struct rad_conf)); 334 SIMPLEQ_INIT(&nconf->ra_iface_list); 335 SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list); 336 SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list); 337 SIMPLEQ_INIT(&nconf->ra_options.ra_pref64_list); 338 ra_options = &nconf->ra_options; 339 break; 340 case IMSG_RECONF_RA_IFACE: 341 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 342 ra_iface_conf)) 343 fatalx("%s: IMSG_RECONF_RA_IFACE wrong length: " 344 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 345 if ((ra_iface_conf = malloc(sizeof(struct 346 ra_iface_conf))) == NULL) 347 fatal(NULL); 348 memcpy(ra_iface_conf, imsg.data, 349 sizeof(struct ra_iface_conf)); 350 ra_iface_conf->autoprefix = NULL; 351 SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list); 352 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list); 353 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list); 354 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_pref64_list); 355 SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list, 356 ra_iface_conf, entry); 357 ra_options = &ra_iface_conf->ra_options; 358 break; 359 case IMSG_RECONF_RA_AUTOPREFIX: 360 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 361 ra_prefix_conf)) 362 fatalx("%s: IMSG_RECONF_RA_AUTOPREFIX wrong " 363 "length: %lu", __func__, 364 IMSG_DATA_SIZE(imsg)); 365 if ((ra_iface_conf->autoprefix = malloc(sizeof(struct 366 ra_prefix_conf))) == NULL) 367 fatal(NULL); 368 memcpy(ra_iface_conf->autoprefix, imsg.data, 369 sizeof(struct ra_prefix_conf)); 370 break; 371 case IMSG_RECONF_RA_PREFIX: 372 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 373 ra_prefix_conf)) 374 fatalx("%s: IMSG_RECONF_RA_PREFIX wrong " 375 "length: %lu", __func__, 376 IMSG_DATA_SIZE(imsg)); 377 if ((ra_prefix_conf = malloc(sizeof(struct 378 ra_prefix_conf))) == NULL) 379 fatal(NULL); 380 memcpy(ra_prefix_conf, imsg.data, sizeof(struct 381 ra_prefix_conf)); 382 SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_prefix_list, 383 ra_prefix_conf, entry); 384 break; 385 case IMSG_RECONF_RA_RDNSS: 386 if(IMSG_DATA_SIZE(imsg) != sizeof(struct 387 ra_rdnss_conf)) 388 fatalx("%s: IMSG_RECONF_RA_RDNSS wrong length: " 389 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 390 if ((ra_rdnss_conf = malloc(sizeof(struct 391 ra_rdnss_conf))) == NULL) 392 fatal(NULL); 393 memcpy(ra_rdnss_conf, imsg.data, sizeof(struct 394 ra_rdnss_conf)); 395 SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list, 396 ra_rdnss_conf, entry); 397 break; 398 case IMSG_RECONF_RA_DNSSL: 399 if(IMSG_DATA_SIZE(imsg) != sizeof(struct 400 ra_dnssl_conf)) 401 fatalx("%s: IMSG_RECONF_RA_DNSSL wrong length: " 402 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 403 if ((ra_dnssl_conf = malloc(sizeof(struct 404 ra_dnssl_conf))) == NULL) 405 fatal(NULL); 406 memcpy(ra_dnssl_conf, imsg.data, sizeof(struct 407 ra_dnssl_conf)); 408 SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list, 409 ra_dnssl_conf, entry); 410 break; 411 case IMSG_RECONF_RA_PREF64: 412 if(IMSG_DATA_SIZE(imsg) != sizeof(struct 413 ra_pref64_conf)) 414 fatalx("%s: IMSG_RECONF_RA_PREF64 wrong length: " 415 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 416 if ((pref64 = malloc(sizeof(struct ra_pref64_conf))) == 417 NULL) 418 fatal(NULL); 419 memcpy(pref64, imsg.data, sizeof(struct ra_pref64_conf)); 420 SIMPLEQ_INSERT_TAIL(&ra_options->ra_pref64_list, pref64, 421 entry); 422 break; 423 case IMSG_RECONF_END: 424 if (nconf == NULL) 425 fatalx("%s: IMSG_RECONF_END without " 426 "IMSG_RECONF_CONF", __func__); 427 merge_config(engine_conf, nconf); 428 nconf = NULL; 429 break; 430 default: 431 log_debug("%s: unexpected imsg %d", __func__, 432 imsg.hdr.type); 433 break; 434 } 435 imsg_free(&imsg); 436 } 437 if (!shut) 438 imsg_event_add(iev); 439 else { 440 /* This pipe is dead. Remove its event handler. */ 441 event_del(&iev->ev); 442 event_loopexit(NULL); 443 } 444 } 445 446 447 void 448 parse_ra_rs(struct imsg_ra_rs *ra_rs) 449 { 450 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 451 struct icmp6_hdr *hdr; 452 453 hdr = (struct icmp6_hdr *) ra_rs->packet; 454 455 switch (hdr->icmp6_type) { 456 case ND_ROUTER_ADVERT: 457 parse_ra(ra_rs); 458 break; 459 case ND_ROUTER_SOLICIT: 460 parse_rs(ra_rs); 461 break; 462 default: 463 log_warnx("unexpected icmp6_type: %d from %s on %s", 464 hdr->icmp6_type, inet_ntop(AF_INET6, &ra_rs->from.sin6_addr, 465 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(ra_rs->if_index, 466 ifnamebuf)); 467 break; 468 } 469 } 470 471 void 472 parse_ra(struct imsg_ra_rs *ra) 473 { 474 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 475 log_debug("got RA from %s on %s", 476 inet_ntop(AF_INET6, &ra->from.sin6_addr, ntopbuf, 477 INET6_ADDRSTRLEN), if_indextoname(ra->if_index, 478 ifnamebuf)); 479 /* XXX not yet */ 480 } 481 482 void 483 parse_rs(struct imsg_ra_rs *rs) 484 { 485 struct nd_router_solicit *nd_rs; 486 struct engine_iface *engine_iface; 487 ssize_t len; 488 int unicast_ra = 0; 489 const char *hbuf; 490 char ifnamebuf[IFNAMSIZ]; 491 uint8_t *p; 492 493 hbuf = sin6_to_str(&rs->from); 494 495 log_debug("got RS from %s on %s", hbuf, if_indextoname(rs->if_index, 496 ifnamebuf)); 497 498 if ((engine_iface = find_engine_iface_by_id(rs->if_index)) == NULL) 499 return; 500 501 len = rs->len; 502 503 if (!(IN6_IS_ADDR_LINKLOCAL(&rs->from.sin6_addr) || 504 IN6_IS_ADDR_UNSPECIFIED(&rs->from.sin6_addr))) { 505 log_warnx("RA from invalid address %s on %s", hbuf, 506 if_indextoname(rs->if_index, ifnamebuf)); 507 return; 508 } 509 510 if ((size_t)len < sizeof(struct nd_router_solicit)) { 511 log_warnx("received too short message (%ld) from %s", len, 512 hbuf); 513 return; 514 } 515 516 p = rs->packet; 517 nd_rs = (struct nd_router_solicit *)p; 518 len -= sizeof(struct nd_router_solicit); 519 p += sizeof(struct nd_router_solicit); 520 521 if (nd_rs->nd_rs_code != 0) { 522 log_warnx("invalid ICMPv6 code (%d) from %s", nd_rs->nd_rs_code, 523 hbuf); 524 return; 525 } 526 while ((size_t)len >= sizeof(struct nd_opt_hdr)) { 527 struct nd_opt_hdr *nd_opt_hdr = (struct nd_opt_hdr *)p; 528 529 len -= sizeof(struct nd_opt_hdr); 530 p += sizeof(struct nd_opt_hdr); 531 532 if (nd_opt_hdr->nd_opt_len * 8 - 2 > len) { 533 log_warnx("invalid option len: %u > %ld", 534 nd_opt_hdr->nd_opt_len, len); 535 return; 536 } 537 switch (nd_opt_hdr->nd_opt_type) { 538 case ND_OPT_SOURCE_LINKADDR: 539 log_debug("got RS with source linkaddr option"); 540 unicast_ra = 1; 541 break; 542 default: 543 log_debug("\t\tUNKNOWN: %d", nd_opt_hdr->nd_opt_type); 544 break; 545 } 546 len -= nd_opt_hdr->nd_opt_len * 8 - 2; 547 p += nd_opt_hdr->nd_opt_len * 8 - 2; 548 } 549 550 if (unicast_ra) { 551 struct imsg_send_ra send_ra; 552 553 send_ra.if_index = rs->if_index; 554 memcpy(&send_ra.to, &rs->from, sizeof(send_ra.to)); 555 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 556 sizeof(send_ra)); 557 } else { 558 struct timespec now, diff, ra_delay = {MIN_DELAY_BETWEEN_RAS, 0}; 559 struct timeval tv = {0, 0}; 560 561 /* a multicast RA is already scheduled within the next 3 seconds */ 562 if (engine_iface->ras_delayed) 563 return; 564 565 engine_iface->ras_delayed = 1; 566 clock_gettime(CLOCK_MONOTONIC, &now); 567 timespecsub(&now, &engine_iface->last_ra, &diff); 568 569 if (timespeccmp(&diff, &ra_delay, <)) { 570 timespecsub(&ra_delay, &diff, &ra_delay); 571 TIMESPEC_TO_TIMEVAL(&tv, &ra_delay); 572 } 573 574 tv.tv_usec = arc4random_uniform(MAX_RA_DELAY_TIME * 1000); 575 evtimer_add(&engine_iface->timer, &tv); 576 } 577 } 578 579 struct engine_iface* 580 find_engine_iface_by_id(uint32_t if_index) 581 { 582 struct engine_iface *engine_iface; 583 584 TAILQ_FOREACH(engine_iface, &engine_interfaces, entry) { 585 if (engine_iface->if_index == if_index) 586 return engine_iface; 587 } 588 return (NULL); 589 } 590 591 void 592 update_iface(uint32_t if_index) 593 { 594 struct engine_iface *engine_iface; 595 struct timeval tv; 596 597 if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) { 598 engine_iface = calloc(1, sizeof(*engine_iface)); 599 engine_iface->if_index = if_index; 600 evtimer_set(&engine_iface->timer, iface_timeout, engine_iface); 601 TAILQ_INSERT_TAIL(&engine_interfaces, engine_iface, entry); 602 } 603 604 tv.tv_sec = 0; 605 tv.tv_usec = arc4random_uniform(1000000); 606 evtimer_add(&engine_iface->timer, &tv); 607 } 608 609 void 610 remove_iface(uint32_t if_index) 611 { 612 struct engine_iface *engine_iface; 613 struct imsg_send_ra send_ra; 614 char if_name[IF_NAMESIZE]; 615 616 if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) { 617 /* we don't know this interface, frontend can delete it */ 618 engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0, 619 &if_index, sizeof(if_index)); 620 return; 621 } 622 623 send_ra.if_index = engine_iface->if_index; 624 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 625 626 TAILQ_REMOVE(&engine_interfaces, engine_iface, entry); 627 evtimer_del(&engine_iface->timer); 628 629 if (if_indextoname(if_index, if_name) != NULL) 630 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 631 sizeof(send_ra)); 632 engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0, 633 &engine_iface->if_index, sizeof(engine_iface->if_index)); 634 free(engine_iface); 635 } 636 637 void 638 iface_timeout(int fd, short events, void *arg) 639 { 640 struct engine_iface *engine_iface = (struct engine_iface *)arg; 641 struct imsg_send_ra send_ra; 642 struct timeval tv; 643 644 tv.tv_sec = MIN_RTR_ADV_INTERVAL + 645 arc4random_uniform(MAX_RTR_ADV_INTERVAL - MIN_RTR_ADV_INTERVAL); 646 tv.tv_usec = arc4random_uniform(1000000); 647 648 log_debug("%s new timeout in %lld", __func__, tv.tv_sec); 649 650 evtimer_add(&engine_iface->timer, &tv); 651 652 send_ra.if_index = engine_iface->if_index; 653 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 654 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 655 sizeof(send_ra)); 656 clock_gettime(CLOCK_MONOTONIC, &engine_iface->last_ra); 657 engine_iface->ras_delayed = 0; 658 } 659