1 /* $OpenBSD: frontend.c,v 1.26 2019/03/15 16:47:19 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2018 Florian Obser <florian@openbsd.org> 5 * Copyright (c) 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/ioctl.h> 53 #include <sys/queue.h> 54 #include <sys/socket.h> 55 #include <sys/syslog.h> 56 #include <sys/uio.h> 57 58 #include <net/if.h> 59 #include <net/if_dl.h> 60 #include <net/if_types.h> 61 #include <net/route.h> 62 63 #include <arpa/inet.h> 64 65 #include <netinet/in.h> 66 #include <netinet/if_ether.h> 67 #include <netinet6/nd6.h> 68 #include <netinet6/in6_var.h> 69 #include <netinet/ip6.h> 70 #include <netinet6/ip6_var.h> 71 #include <netinet/icmp6.h> 72 73 #include <ctype.h> 74 #include <errno.h> 75 #include <event.h> 76 #include <ifaddrs.h> 77 #include <imsg.h> 78 #include <pwd.h> 79 #include <signal.h> 80 #include <stdio.h> 81 #include <stdlib.h> 82 #include <string.h> 83 #include <unistd.h> 84 85 #include "log.h" 86 #include "rad.h" 87 #include "frontend.h" 88 #include "control.h" 89 90 #define RA_MAX_SIZE 1500 91 #define ROUTE_SOCKET_BUF_SIZE 16384 92 93 struct icmp6_ev { 94 struct event ev; 95 uint8_t answer[1500]; 96 struct msghdr rcvmhdr; 97 struct iovec rcviov[1]; 98 struct sockaddr_in6 from; 99 } icmp6ev; 100 101 struct ra_iface { 102 TAILQ_ENTRY(ra_iface) entry; 103 struct ra_prefix_conf_head prefixes; 104 char name[IF_NAMESIZE]; 105 char conf_name[IF_NAMESIZE]; 106 uint32_t if_index; 107 int removed; 108 int prefix_count; 109 size_t datalen; 110 uint8_t data[RA_MAX_SIZE]; 111 }; 112 113 TAILQ_HEAD(, ra_iface) ra_interfaces; 114 115 __dead void frontend_shutdown(void); 116 void frontend_sig_handler(int, short, void *); 117 void frontend_startup(void); 118 void icmp6_receive(int, short, void *); 119 void join_all_routers_mcast_group(struct ra_iface *); 120 void leave_all_routers_mcast_group(struct ra_iface *); 121 void merge_ra_interface(char *, char *); 122 void merge_ra_interfaces(void); 123 struct ra_iface *find_ra_iface_by_id(uint32_t); 124 struct ra_iface *find_ra_iface_by_name(char *); 125 struct ra_iface_conf *find_ra_iface_conf(struct ra_iface_conf_head *, 126 char *); 127 struct ra_prefix_conf *find_ra_prefix_conf(struct ra_prefix_conf_head*, 128 struct in6_addr *, int); 129 void add_new_prefix_to_ra_iface(struct ra_iface *r, 130 struct in6_addr *, int, struct ra_prefix_conf *); 131 void free_ra_iface(struct ra_iface *); 132 int in6_mask2prefixlen(struct in6_addr *); 133 void get_interface_prefixes(struct ra_iface *, 134 struct ra_prefix_conf *); 135 void build_packet(struct ra_iface *); 136 void build_leaving_packet(struct ra_iface *); 137 void ra_output(struct ra_iface *, struct sockaddr_in6 *); 138 void get_rtaddrs(int, struct sockaddr *, 139 struct sockaddr **); 140 void route_receive(int, short, void *); 141 void handle_route_message(struct rt_msghdr *, 142 struct sockaddr **); 143 144 struct rad_conf *frontend_conf; 145 struct imsgev *iev_main; 146 struct imsgev *iev_engine; 147 struct event ev_route; 148 int icmp6sock = -1, ioctlsock = -1; 149 struct ipv6_mreq all_routers; 150 struct sockaddr_in6 all_nodes; 151 struct msghdr sndmhdr; 152 struct iovec sndiov[2]; 153 154 void 155 frontend_sig_handler(int sig, short event, void *bula) 156 { 157 /* 158 * Normal signal handler rules don't apply because libevent 159 * decouples for us. 160 */ 161 162 switch (sig) { 163 case SIGINT: 164 case SIGTERM: 165 frontend_shutdown(); 166 default: 167 fatalx("unexpected signal"); 168 } 169 } 170 171 void 172 frontend(int debug, int verbose) 173 { 174 struct event ev_sigint, ev_sigterm; 175 struct passwd *pw; 176 size_t rcvcmsglen, sndcmsgbuflen; 177 uint8_t *rcvcmsgbuf; 178 uint8_t *sndcmsgbuf = NULL; 179 180 frontend_conf = config_new_empty(); 181 control_state.fd = -1; 182 183 log_init(debug, LOG_DAEMON); 184 log_setverbose(verbose); 185 186 if ((pw = getpwnam(RAD_USER)) == NULL) 187 fatal("getpwnam"); 188 189 if (chroot(pw->pw_dir) == -1) 190 fatal("chroot"); 191 if (chdir("/") == -1) 192 fatal("chdir(\"/\")"); 193 194 rad_process = PROC_FRONTEND; 195 setproctitle("%s", log_procnames[rad_process]); 196 log_procinit(log_procnames[rad_process]); 197 198 if (setgroups(1, &pw->pw_gid) || 199 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 200 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 201 fatal("can't drop privileges"); 202 203 /* XXX pass in from main */ 204 if ((ioctlsock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) 205 fatal("socket"); 206 207 if (pledge("stdio inet unix recvfd route mcast", NULL) == -1) 208 fatal("pledge"); 209 210 event_init(); 211 212 /* Setup signal handler. */ 213 signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL); 214 signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL); 215 signal_add(&ev_sigint, NULL); 216 signal_add(&ev_sigterm, NULL); 217 signal(SIGPIPE, SIG_IGN); 218 signal(SIGHUP, SIG_IGN); 219 220 /* Setup pipe and event handler to the parent process. */ 221 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 222 fatal(NULL); 223 imsg_init(&iev_main->ibuf, 3); 224 iev_main->handler = frontend_dispatch_main; 225 iev_main->events = EV_READ; 226 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 227 iev_main->handler, iev_main); 228 event_add(&iev_main->ev, NULL); 229 230 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 231 CMSG_SPACE(sizeof(int)); 232 if((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) 233 fatal("malloc"); 234 235 icmp6ev.rcviov[0].iov_base = (caddr_t)icmp6ev.answer; 236 icmp6ev.rcviov[0].iov_len = sizeof(icmp6ev.answer); 237 icmp6ev.rcvmhdr.msg_name = (caddr_t)&icmp6ev.from; 238 icmp6ev.rcvmhdr.msg_namelen = sizeof(icmp6ev.from); 239 icmp6ev.rcvmhdr.msg_iov = icmp6ev.rcviov; 240 icmp6ev.rcvmhdr.msg_iovlen = 1; 241 icmp6ev.rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 242 icmp6ev.rcvmhdr.msg_controllen = rcvcmsglen; 243 244 if (inet_pton(AF_INET6, "ff02::2", 245 &all_routers.ipv6mr_multiaddr.s6_addr) == -1) 246 fatal("inet_pton"); 247 248 all_nodes.sin6_len = sizeof(all_nodes); 249 all_nodes.sin6_family = AF_INET6; 250 if (inet_pton(AF_INET6, "ff02::1", &all_nodes.sin6_addr) != 1) 251 fatal("inet_pton"); 252 253 sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 254 CMSG_SPACE(sizeof(int)); 255 if ((sndcmsgbuf = malloc(sndcmsgbuflen)) == NULL) 256 fatal("%s", __func__); 257 258 sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); 259 sndmhdr.msg_iov = sndiov; 260 sndmhdr.msg_iovlen = 1; 261 sndmhdr.msg_control = sndcmsgbuf; 262 sndmhdr.msg_controllen = sndcmsgbuflen; 263 264 TAILQ_INIT(&ra_interfaces); 265 266 event_dispatch(); 267 268 frontend_shutdown(); 269 } 270 271 __dead void 272 frontend_shutdown(void) 273 { 274 /* Close pipes. */ 275 msgbuf_write(&iev_engine->ibuf.w); 276 msgbuf_clear(&iev_engine->ibuf.w); 277 close(iev_engine->ibuf.fd); 278 msgbuf_write(&iev_main->ibuf.w); 279 msgbuf_clear(&iev_main->ibuf.w); 280 close(iev_main->ibuf.fd); 281 282 config_clear(frontend_conf); 283 284 free(iev_engine); 285 free(iev_main); 286 287 log_info("frontend exiting"); 288 exit(0); 289 } 290 291 int 292 frontend_imsg_compose_main(int type, pid_t pid, void *data, uint16_t datalen) 293 { 294 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, 295 datalen)); 296 } 297 298 int 299 frontend_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen) 300 { 301 return (imsg_compose_event(iev_engine, type, 0, pid, -1, data, 302 datalen)); 303 } 304 305 void 306 frontend_dispatch_main(int fd, short event, void *bula) 307 { 308 static struct rad_conf *nconf; 309 static struct ra_iface_conf *ra_iface_conf; 310 static struct ra_options_conf *ra_options; 311 struct imsg imsg; 312 struct imsgev *iev = bula; 313 struct imsgbuf *ibuf = &iev->ibuf; 314 struct ra_prefix_conf *ra_prefix_conf; 315 struct ra_rdnss_conf *ra_rdnss_conf; 316 struct ra_dnssl_conf *ra_dnssl_conf; 317 int n, shut = 0; 318 319 if (event & EV_READ) { 320 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 321 fatal("imsg_read error"); 322 if (n == 0) /* Connection closed. */ 323 shut = 1; 324 } 325 if (event & EV_WRITE) { 326 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 327 fatal("msgbuf_write"); 328 if (n == 0) /* Connection closed. */ 329 shut = 1; 330 } 331 332 for (;;) { 333 if ((n = imsg_get(ibuf, &imsg)) == -1) 334 fatal("%s: imsg_get error", __func__); 335 if (n == 0) /* No more messages. */ 336 break; 337 338 switch (imsg.hdr.type) { 339 case IMSG_SOCKET_IPC: 340 /* 341 * Setup pipe and event handler to the engine 342 * process. 343 */ 344 if (iev_engine) 345 fatalx("%s: received unexpected imsg fd to " 346 "frontend", __func__); 347 if ((fd = imsg.fd) == -1) 348 fatalx("%s: expected to receive imsg fd to " 349 "frontend but didn't receive any", 350 __func__); 351 352 iev_engine = malloc(sizeof(struct imsgev)); 353 if (iev_engine == NULL) 354 fatal(NULL); 355 356 imsg_init(&iev_engine->ibuf, fd); 357 iev_engine->handler = frontend_dispatch_engine; 358 iev_engine->events = EV_READ; 359 360 event_set(&iev_engine->ev, iev_engine->ibuf.fd, 361 iev_engine->events, iev_engine->handler, iev_engine); 362 event_add(&iev_engine->ev, NULL); 363 break; 364 case IMSG_RECONF_CONF: 365 if (nconf != NULL) 366 fatalx("%s: IMSG_RECONF_CONF already in " 367 "progress", __func__); 368 if (IMSG_DATA_SIZE(imsg) != sizeof(struct rad_conf)) 369 fatalx("%s: IMSG_RECONF_CONF wrong length: %lu", 370 __func__, IMSG_DATA_SIZE(imsg)); 371 if ((nconf = malloc(sizeof(struct rad_conf))) == 372 NULL) 373 fatal(NULL); 374 memcpy(nconf, imsg.data, sizeof(struct rad_conf)); 375 SIMPLEQ_INIT(&nconf->ra_iface_list); 376 SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list); 377 SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list); 378 ra_options = &nconf->ra_options; 379 break; 380 case IMSG_RECONF_RA_IFACE: 381 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 382 ra_iface_conf)) 383 fatalx("%s: IMSG_RECONF_RA_IFACE wrong length: " 384 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 385 if ((ra_iface_conf = malloc(sizeof(struct 386 ra_iface_conf))) == NULL) 387 fatal(NULL); 388 memcpy(ra_iface_conf, imsg.data, sizeof(struct 389 ra_iface_conf)); 390 ra_iface_conf->autoprefix = NULL; 391 SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list); 392 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list); 393 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list); 394 SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list, 395 ra_iface_conf, entry); 396 ra_options = &ra_iface_conf->ra_options; 397 break; 398 case IMSG_RECONF_RA_AUTOPREFIX: 399 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 400 ra_prefix_conf)) 401 fatalx("%s: IMSG_RECONF_RA_AUTOPREFIX wrong " 402 "length: %lu", __func__, 403 IMSG_DATA_SIZE(imsg)); 404 if ((ra_iface_conf->autoprefix = malloc(sizeof(struct 405 ra_prefix_conf))) == NULL) 406 fatal(NULL); 407 memcpy(ra_iface_conf->autoprefix, imsg.data, 408 sizeof(struct ra_prefix_conf)); 409 break; 410 case IMSG_RECONF_RA_PREFIX: 411 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 412 ra_prefix_conf)) 413 fatalx("%s: IMSG_RECONF_RA_PREFIX wrong " 414 "length: %lu", __func__, 415 IMSG_DATA_SIZE(imsg)); 416 if ((ra_prefix_conf = malloc(sizeof(struct 417 ra_prefix_conf))) == NULL) 418 fatal(NULL); 419 memcpy(ra_prefix_conf, imsg.data, 420 sizeof(struct ra_prefix_conf)); 421 SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_prefix_list, 422 ra_prefix_conf, entry); 423 break; 424 case IMSG_RECONF_RA_RDNSS: 425 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 426 ra_rdnss_conf)) 427 fatalx("%s: IMSG_RECONF_RA_RDNSS wrong length: " 428 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 429 if ((ra_rdnss_conf = malloc(sizeof(struct 430 ra_rdnss_conf))) == NULL) 431 fatal(NULL); 432 memcpy(ra_rdnss_conf, imsg.data, sizeof(struct 433 ra_rdnss_conf)); 434 SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list, 435 ra_rdnss_conf, entry); 436 break; 437 case IMSG_RECONF_RA_DNSSL: 438 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 439 ra_dnssl_conf)) 440 fatalx("%s: IMSG_RECONF_RA_DNSSL wrong length: " 441 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 442 if ((ra_dnssl_conf = malloc(sizeof(struct 443 ra_dnssl_conf))) == NULL) 444 fatal(NULL); 445 memcpy(ra_dnssl_conf, imsg.data, sizeof(struct 446 ra_dnssl_conf)); 447 SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list, 448 ra_dnssl_conf, entry); 449 break; 450 case IMSG_RECONF_END: 451 if (nconf == NULL) 452 fatalx("%s: IMSG_RECONF_END without " 453 "IMSG_RECONF_CONF", __func__); 454 merge_config(frontend_conf, nconf); 455 merge_ra_interfaces(); 456 nconf = NULL; 457 break; 458 case IMSG_ICMP6SOCK: 459 if ((icmp6sock = imsg.fd) == -1) 460 fatalx("%s: expected to receive imsg " 461 "ICMPv6 fd but didn't receive any", 462 __func__); 463 event_set(&icmp6ev.ev, icmp6sock, EV_READ | EV_PERSIST, 464 icmp6_receive, NULL); 465 case IMSG_ROUTESOCK: 466 if ((fd = imsg.fd) == -1) 467 fatalx("%s: expected to receive imsg " 468 "routesocket fd but didn't receive any", 469 __func__); 470 event_set(&ev_route, fd, EV_READ | EV_PERSIST, 471 route_receive, NULL); 472 break; 473 case IMSG_STARTUP: 474 if (pledge("stdio inet unix route mcast", NULL) == -1) 475 fatal("pledge"); 476 frontend_startup(); 477 break; 478 case IMSG_CONTROLFD: 479 if (control_state.fd != -1) 480 fatalx("%s: received unexpected controlsock", 481 __func__); 482 if ((fd = imsg.fd) == -1) 483 fatalx("%s: expected to receive imsg " 484 "control fd but didn't receive any", 485 __func__); 486 control_state.fd = fd; 487 /* Listen on control socket. */ 488 TAILQ_INIT(&ctl_conns); 489 control_listen(); 490 break; 491 default: 492 log_debug("%s: error handling imsg %d", __func__, 493 imsg.hdr.type); 494 break; 495 } 496 imsg_free(&imsg); 497 } 498 if (!shut) 499 imsg_event_add(iev); 500 else { 501 /* This pipe is dead. Remove its event handler. */ 502 event_del(&iev->ev); 503 event_loopexit(NULL); 504 } 505 } 506 507 void 508 frontend_dispatch_engine(int fd, short event, void *bula) 509 { 510 struct imsgev *iev = bula; 511 struct imsgbuf *ibuf = &iev->ibuf; 512 struct imsg imsg; 513 struct imsg_send_ra send_ra; 514 struct ra_iface *ra_iface; 515 uint32_t if_index; 516 int n, shut = 0; 517 518 if (event & EV_READ) { 519 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 520 fatal("imsg_read error"); 521 if (n == 0) /* Connection closed. */ 522 shut = 1; 523 } 524 if (event & EV_WRITE) { 525 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 526 fatal("msgbuf_write"); 527 if (n == 0) /* Connection closed. */ 528 shut = 1; 529 } 530 531 for (;;) { 532 if ((n = imsg_get(ibuf, &imsg)) == -1) 533 fatal("%s: imsg_get error", __func__); 534 if (n == 0) /* No more messages. */ 535 break; 536 537 switch (imsg.hdr.type) { 538 case IMSG_SEND_RA: 539 if (IMSG_DATA_SIZE(imsg) != sizeof(send_ra)) 540 fatalx("%s: IMSG_SEND_RA wrong length: %lu", 541 __func__, IMSG_DATA_SIZE(imsg)); 542 memcpy(&send_ra, imsg.data, sizeof(send_ra)); 543 ra_iface = find_ra_iface_by_id(send_ra.if_index); 544 if (ra_iface) 545 ra_output(ra_iface, &send_ra.to); 546 break; 547 case IMSG_REMOVE_IF: 548 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 549 fatalx("%s: IMSG_REMOVE_IF wrong length: %lu", 550 __func__, IMSG_DATA_SIZE(imsg)); 551 memcpy(&if_index, imsg.data, sizeof(if_index)); 552 ra_iface = find_ra_iface_by_id(if_index); 553 if (ra_iface) { 554 TAILQ_REMOVE(&ra_interfaces, ra_iface, entry); 555 free_ra_iface(ra_iface); 556 } 557 break; 558 default: 559 log_debug("%s: error handling imsg %d", __func__, 560 imsg.hdr.type); 561 break; 562 } 563 imsg_free(&imsg); 564 } 565 if (!shut) 566 imsg_event_add(iev); 567 else { 568 /* This pipe is dead. Remove its event handler. */ 569 event_del(&iev->ev); 570 event_loopexit(NULL); 571 } 572 } 573 574 void 575 frontend_startup(void) 576 { 577 if (!event_initialized(&ev_route)) 578 fatalx("%s: did not receive a route socket from the main " 579 "process", __func__); 580 581 event_add(&ev_route, NULL); 582 583 if (!event_initialized(&icmp6ev.ev)) 584 fatalx("%s: did not receive a icmp6 socket fd from the main " 585 "process", __func__); 586 587 event_add(&icmp6ev.ev, NULL); 588 589 frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0); 590 } 591 592 593 void 594 icmp6_receive(int fd, short events, void *arg) 595 { 596 struct imsg_ra_rs ra_rs; 597 struct in6_pktinfo *pi = NULL; 598 struct cmsghdr *cm; 599 ssize_t len; 600 int if_index = 0, *hlimp = NULL; 601 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 602 603 if ((len = recvmsg(fd, &icmp6ev.rcvmhdr, 0)) < 0) { 604 log_warn("recvmsg"); 605 return; 606 } 607 608 /* extract optional information via Advanced API */ 609 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev.rcvmhdr); cm; 610 cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev.rcvmhdr, cm)) { 611 if (cm->cmsg_level == IPPROTO_IPV6 && 612 cm->cmsg_type == IPV6_PKTINFO && 613 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { 614 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 615 if_index = pi->ipi6_ifindex; 616 } 617 if (cm->cmsg_level == IPPROTO_IPV6 && 618 cm->cmsg_type == IPV6_HOPLIMIT && 619 cm->cmsg_len == CMSG_LEN(sizeof(int))) 620 hlimp = (int *)CMSG_DATA(cm); 621 } 622 623 if (if_index == 0) { 624 log_warnx("failed to get receiving interface"); 625 return; 626 } 627 628 if (hlimp == NULL) { 629 log_warnx("failed to get receiving hop limit"); 630 return; 631 } 632 633 if (*hlimp != 255) { 634 log_warnx("invalid RA or RS with hop limit of %d from %s on %s", 635 *hlimp, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr, 636 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 637 ifnamebuf)); 638 return; 639 } 640 641 log_debug("RA or RS with hop limit of %d from %s on %s", 642 *hlimp, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr, 643 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 644 ifnamebuf)); 645 646 if ((size_t)len > sizeof(ra_rs.packet)) { 647 log_warnx("invalid RA or RS with size %ld from %s on %s", 648 len, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr, 649 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 650 ifnamebuf)); 651 return; 652 } 653 654 ra_rs.if_index = if_index; 655 memcpy(&ra_rs.from, &icmp6ev.from, sizeof(ra_rs.from)); 656 ra_rs.len = len; 657 memcpy(ra_rs.packet, icmp6ev.answer, len); 658 659 frontend_imsg_compose_engine(IMSG_RA_RS, 0, &ra_rs, sizeof(ra_rs)); 660 } 661 662 void 663 join_all_routers_mcast_group(struct ra_iface *ra_iface) 664 { 665 log_debug("joining multicast group on %s", ra_iface->name); 666 all_routers.ipv6mr_interface = ra_iface->if_index; 667 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 668 &all_routers, sizeof(all_routers)) == -1) 669 fatal("IPV6_JOIN_GROUP(%s)", ra_iface->name); 670 } 671 672 void 673 leave_all_routers_mcast_group(struct ra_iface *ra_iface) 674 { 675 log_debug("leaving multicast group on %s", ra_iface->name); 676 all_routers.ipv6mr_interface = ra_iface->if_index; 677 setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, 678 &all_routers, sizeof(all_routers)); 679 } 680 681 struct ra_iface* 682 find_ra_iface_by_id(uint32_t if_index) 683 { 684 struct ra_iface *ra_iface; 685 686 TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) { 687 if (ra_iface->if_index == if_index) 688 return ra_iface; 689 } 690 return (NULL); 691 } 692 693 struct ra_iface* 694 find_ra_iface_by_name(char *if_name) 695 { 696 struct ra_iface *ra_iface; 697 698 TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) { 699 if (strcmp(ra_iface->name, if_name) == 0) 700 return ra_iface; 701 } 702 return (NULL); 703 } 704 705 struct ra_iface_conf* 706 find_ra_iface_conf(struct ra_iface_conf_head *head, char *if_name) 707 { 708 struct ra_iface_conf *ra_iface_conf; 709 710 SIMPLEQ_FOREACH(ra_iface_conf, head, entry) { 711 if (strcmp(ra_iface_conf->name, if_name) == 0) 712 return ra_iface_conf; 713 } 714 return (NULL); 715 } 716 717 void 718 merge_ra_interface(char *name, char *conf_name) 719 { 720 struct ra_iface *ra_iface; 721 uint32_t if_index; 722 723 if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { 724 log_debug("keeping interface %s", name); 725 ra_iface->removed = 0; 726 return; 727 } 728 729 log_debug("new interface %s", name); 730 if ((if_index = if_nametoindex(name)) == 0) 731 return; 732 log_debug("adding interface %s", name); 733 if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL) 734 fatal("%s", __func__); 735 736 strlcpy(ra_iface->name, name, sizeof(ra_iface->name)); 737 strlcpy(ra_iface->conf_name, conf_name, 738 sizeof(ra_iface->conf_name)); 739 740 ra_iface->if_index = if_index; 741 SIMPLEQ_INIT(&ra_iface->prefixes); 742 TAILQ_INSERT_TAIL(&ra_interfaces, ra_iface, entry); 743 join_all_routers_mcast_group(ra_iface); 744 } 745 746 void 747 merge_ra_interfaces(void) 748 { 749 struct ra_iface_conf *ra_iface_conf; 750 struct ra_prefix_conf *ra_prefix_conf; 751 struct ra_iface *ra_iface; 752 struct ifgroupreq ifgr; 753 struct ifg_req *ifg; 754 char *conf_name; 755 unsigned int len; 756 757 TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) 758 ra_iface->removed = 1; 759 760 SIMPLEQ_FOREACH(ra_iface_conf, &frontend_conf->ra_iface_list, entry) { 761 conf_name = ra_iface_conf->name; 762 763 /* check if network interface or group */ 764 if (isdigit((unsigned char)conf_name[strlen(conf_name) - 1])) { 765 merge_ra_interface(conf_name, conf_name); 766 } else { 767 log_debug("interface group %s", conf_name); 768 769 memset(&ifgr, 0, sizeof(ifgr)); 770 strlcpy(ifgr.ifgr_name, conf_name, 771 sizeof(ifgr.ifgr_name)); 772 if (ioctl(ioctlsock, SIOCGIFGMEMB, 773 (caddr_t)&ifgr) == -1) 774 continue; 775 776 len = ifgr.ifgr_len; 777 if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 778 fatal("%s: calloc", __func__); 779 if (ioctl(ioctlsock, SIOCGIFGMEMB, 780 (caddr_t)&ifgr) == -1) { 781 log_debug("group %s without members", 782 conf_name); 783 free(ifgr.ifgr_groups); 784 continue; 785 } 786 787 for (ifg = ifgr.ifgr_groups; 788 (ifg != NULL) && (len >= sizeof(struct ifg_req)); 789 ifg++) { 790 len -= sizeof(struct ifg_req); 791 merge_ra_interface(ifg->ifgrq_member, 792 conf_name); 793 } 794 free(ifgr.ifgr_groups); 795 } 796 } 797 798 TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) { 799 while ((ra_prefix_conf = SIMPLEQ_FIRST(&ra_iface->prefixes)) 800 != NULL) { 801 SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes, 802 entry); 803 free(ra_prefix_conf); 804 } 805 ra_iface->prefix_count = 0; 806 807 if (ra_iface->removed) { 808 log_debug("iface removed: %s", ra_iface->name); 809 build_leaving_packet(ra_iface); 810 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 811 &ra_iface->if_index, sizeof(ra_iface->if_index)); 812 continue; 813 } 814 815 ra_iface_conf = find_ra_iface_conf( 816 &frontend_conf->ra_iface_list, ra_iface->conf_name); 817 818 log_debug("add static prefixes for %s", ra_iface->name); 819 820 SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface_conf->ra_prefix_list, 821 entry) { 822 add_new_prefix_to_ra_iface(ra_iface, 823 &ra_prefix_conf->prefix, 824 ra_prefix_conf->prefixlen, ra_prefix_conf); 825 } 826 827 if (ra_iface_conf->autoprefix) 828 get_interface_prefixes(ra_iface, 829 ra_iface_conf->autoprefix); 830 831 build_packet(ra_iface); 832 } 833 } 834 835 void 836 free_ra_iface(struct ra_iface *ra_iface) 837 { 838 struct ra_prefix_conf *prefix; 839 840 leave_all_routers_mcast_group(ra_iface); 841 842 while ((prefix = SIMPLEQ_FIRST(&ra_iface->prefixes)) != NULL) { 843 SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes, entry); 844 free(prefix); 845 } 846 847 free(ra_iface); 848 } 849 850 /* from kame via ifconfig, where it's called prefix() */ 851 int 852 in6_mask2prefixlen(struct in6_addr *in6) 853 { 854 u_char *nam = (u_char *)in6; 855 int byte, bit, plen = 0, size = sizeof(struct in6_addr); 856 857 for (byte = 0; byte < size; byte++, plen += 8) 858 if (nam[byte] != 0xff) 859 break; 860 if (byte == size) 861 return (plen); 862 for (bit = 7; bit != 0; bit--, plen++) 863 if (!(nam[byte] & (1 << bit))) 864 break; 865 for (; bit != 0; bit--) 866 if (nam[byte] & (1 << bit)) 867 return (0); 868 byte++; 869 for (; byte < size; byte++) 870 if (nam[byte]) 871 return (0); 872 return (plen); 873 } 874 875 void 876 get_interface_prefixes(struct ra_iface *ra_iface, struct ra_prefix_conf 877 *autoprefix) 878 { 879 struct in6_ifreq ifr6; 880 struct ifaddrs *ifap, *ifa; 881 struct sockaddr_in6 *sin6; 882 int prefixlen; 883 884 log_debug("%s: %s", __func__, ra_iface->name); 885 886 if (getifaddrs(&ifap) != 0) 887 fatal("getifaddrs"); 888 889 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 890 if (strcmp(ra_iface->name, ifa->ifa_name) != 0) 891 continue; 892 if (ifa->ifa_addr->sa_family != AF_INET6) 893 continue; 894 895 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 896 897 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 898 continue; 899 900 memset(&ifr6, 0, sizeof(ifr6)); 901 (void) strlcpy(ifr6.ifr_name, ra_iface->name, 902 sizeof(ifr6.ifr_name)); 903 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 904 905 if (ioctl(ioctlsock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) 906 continue; /* addr got deleted while we were looking */ 907 908 prefixlen = in6_mask2prefixlen(&((struct sockaddr_in6 *) 909 &ifr6.ifr_addr)->sin6_addr); 910 911 if (prefixlen == 128) 912 continue; 913 914 mask_prefix(&sin6->sin6_addr, prefixlen); 915 916 add_new_prefix_to_ra_iface(ra_iface, &sin6->sin6_addr, 917 prefixlen, autoprefix); 918 } 919 freeifaddrs(ifap); 920 } 921 922 struct ra_prefix_conf* 923 find_ra_prefix_conf(struct ra_prefix_conf_head* head, struct in6_addr *prefix, 924 int prefixlen) 925 { 926 struct ra_prefix_conf *ra_prefix_conf; 927 928 SIMPLEQ_FOREACH(ra_prefix_conf, head, entry) { 929 if (ra_prefix_conf->prefixlen == prefixlen && 930 memcmp(&ra_prefix_conf->prefix, prefix, sizeof(*prefix)) == 931 0) 932 return (ra_prefix_conf); 933 } 934 return (NULL); 935 } 936 937 void 938 add_new_prefix_to_ra_iface(struct ra_iface *ra_iface, struct in6_addr *addr, 939 int prefixlen, struct ra_prefix_conf *ra_prefix_conf) 940 { 941 struct ra_prefix_conf *new_ra_prefix_conf; 942 943 if (find_ra_prefix_conf(&ra_iface->prefixes, addr, prefixlen)) { 944 log_debug("ignoring duplicate %s/%d prefix", 945 in6_to_str(addr), prefixlen); 946 return; 947 } 948 949 log_debug("adding %s/%d prefix", in6_to_str(addr), prefixlen); 950 951 if ((new_ra_prefix_conf = calloc(1, sizeof(*ra_prefix_conf))) == NULL) 952 fatal("%s", __func__); 953 new_ra_prefix_conf->prefix = *addr; 954 new_ra_prefix_conf->prefixlen = prefixlen; 955 new_ra_prefix_conf->vltime = ra_prefix_conf->vltime; 956 new_ra_prefix_conf->pltime = ra_prefix_conf->pltime; 957 new_ra_prefix_conf->aflag = ra_prefix_conf->aflag; 958 new_ra_prefix_conf->lflag = ra_prefix_conf->lflag; 959 SIMPLEQ_INSERT_TAIL(&ra_iface->prefixes, new_ra_prefix_conf, entry); 960 ra_iface->prefix_count++; 961 } 962 963 void 964 build_packet(struct ra_iface *ra_iface) 965 { 966 struct nd_router_advert *ra; 967 struct nd_opt_mtu *ndopt_mtu; 968 struct nd_opt_prefix_info *ndopt_pi; 969 struct ra_iface_conf *ra_iface_conf; 970 struct ra_options_conf *ra_options_conf; 971 struct ra_prefix_conf *ra_prefix_conf; 972 struct nd_opt_rdnss *ndopt_rdnss; 973 struct nd_opt_dnssl *ndopt_dnssl; 974 struct ra_rdnss_conf *ra_rdnss; 975 struct ra_dnssl_conf *ra_dnssl; 976 size_t len, label_len; 977 uint8_t *p, buf[RA_MAX_SIZE]; 978 char *label_start, *label_end; 979 980 ra_iface_conf = find_ra_iface_conf(&frontend_conf->ra_iface_list, 981 ra_iface->conf_name); 982 ra_options_conf = &ra_iface_conf->ra_options; 983 984 len = sizeof(*ra); 985 if (ra_options_conf->mtu > 0) 986 len += sizeof(*ndopt_mtu); 987 len += sizeof(*ndopt_pi) * ra_iface->prefix_count; 988 if (ra_iface_conf->ra_options.rdnss_count > 0) 989 len += sizeof(*ndopt_rdnss) + 990 ra_iface_conf->ra_options.rdnss_count * 991 sizeof(struct in6_addr); 992 993 if (ra_iface_conf->ra_options.dnssl_len > 0) 994 /* round up to 8 byte boundary */ 995 len += sizeof(*ndopt_dnssl) + 996 ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7); 997 998 if (len > sizeof(ra_iface->data)) 999 fatalx("%s: packet too big", __func__); /* XXX send multiple */ 1000 1001 p = buf; 1002 1003 ra = (struct nd_router_advert *)p; 1004 1005 memset(ra, 0, sizeof(*ra)); 1006 1007 ra->nd_ra_type = ND_ROUTER_ADVERT; 1008 ra->nd_ra_curhoplimit = ra_options_conf->cur_hl; 1009 if (ra_options_conf->m_flag) 1010 ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; 1011 if (ra_options_conf->o_flag) 1012 ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; 1013 if (ra_iface->removed) 1014 /* tell clients that we are no longer a default router */ 1015 ra->nd_ra_router_lifetime = 0; 1016 else if (ra_options_conf->dfr) { 1017 ra->nd_ra_router_lifetime = 1018 htons(ra_options_conf->router_lifetime); 1019 } 1020 ra->nd_ra_reachable = htonl(ra_options_conf->reachable_time); 1021 ra->nd_ra_retransmit = htonl(ra_options_conf->retrans_timer); 1022 p += sizeof(*ra); 1023 1024 if (ra_options_conf->mtu > 0) { 1025 ndopt_mtu = (struct nd_opt_mtu *)p; 1026 ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU; 1027 ndopt_mtu->nd_opt_mtu_len = 1; 1028 ndopt_mtu->nd_opt_mtu_reserved = 0; 1029 ndopt_mtu->nd_opt_mtu_mtu = htonl(ra_options_conf->mtu); 1030 p += sizeof(*ndopt_mtu); 1031 } 1032 1033 SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface->prefixes, entry) { 1034 ndopt_pi = (struct nd_opt_prefix_info *)p; 1035 memset(ndopt_pi, 0, sizeof(*ndopt_pi)); 1036 ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; 1037 ndopt_pi->nd_opt_pi_len = 4; 1038 ndopt_pi->nd_opt_pi_prefix_len = ra_prefix_conf->prefixlen; 1039 if (ra_prefix_conf->lflag) 1040 ndopt_pi->nd_opt_pi_flags_reserved |= 1041 ND_OPT_PI_FLAG_ONLINK; 1042 if (ra_prefix_conf->aflag) 1043 ndopt_pi->nd_opt_pi_flags_reserved |= 1044 ND_OPT_PI_FLAG_AUTO; 1045 ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime); 1046 ndopt_pi->nd_opt_pi_preferred_time = 1047 htonl(ra_prefix_conf->pltime); 1048 ndopt_pi->nd_opt_pi_prefix = ra_prefix_conf->prefix; 1049 1050 p += sizeof(*ndopt_pi); 1051 } 1052 1053 if (ra_iface_conf->ra_options.rdnss_count > 0) { 1054 ndopt_rdnss = (struct nd_opt_rdnss *)p; 1055 ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS; 1056 ndopt_rdnss->nd_opt_rdnss_len = 1 + 1057 ra_iface_conf->ra_options.rdnss_count * 2; 1058 ndopt_rdnss->nd_opt_rdnss_reserved = 0; 1059 ndopt_rdnss->nd_opt_rdnss_lifetime = 1060 htonl(ra_iface_conf->ra_options.rdns_lifetime); 1061 p += sizeof(struct nd_opt_rdnss); 1062 SIMPLEQ_FOREACH(ra_rdnss, 1063 &ra_iface_conf->ra_options.ra_rdnss_list, entry) { 1064 memcpy(p, &ra_rdnss->rdnss, sizeof(ra_rdnss->rdnss)); 1065 p += sizeof(ra_rdnss->rdnss); 1066 } 1067 } 1068 1069 if (ra_iface_conf->ra_options.dnssl_len > 0) { 1070 ndopt_dnssl = (struct nd_opt_dnssl *)p; 1071 ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL; 1072 /* round up to 8 byte boundary */ 1073 ndopt_dnssl->nd_opt_dnssl_len = 1 + 1074 ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7) / 8; 1075 ndopt_dnssl->nd_opt_dnssl_reserved = 0; 1076 ndopt_dnssl->nd_opt_dnssl_lifetime = 1077 htonl(ra_iface_conf->ra_options.rdns_lifetime); 1078 p += sizeof(struct nd_opt_dnssl); 1079 1080 SIMPLEQ_FOREACH(ra_dnssl, 1081 &ra_iface_conf->ra_options.ra_dnssl_list, entry) { 1082 label_start = ra_dnssl->search; 1083 while ((label_end = strchr(label_start, '.')) != NULL) { 1084 label_len = label_end - label_start; 1085 *p++ = label_len; 1086 memcpy(p, label_start, label_len); 1087 p += label_len; 1088 label_start = label_end + 1; 1089 } 1090 *p++ = '\0'; /* last dot */ 1091 } 1092 /* zero pad */ 1093 while (((uintptr_t)p) % 8 != 0) 1094 *p++ = '\0'; 1095 } 1096 1097 if (len != ra_iface->datalen || memcmp(buf, ra_iface->data, len) 1098 != 0) { 1099 memcpy(ra_iface->data, buf, len); 1100 ra_iface->datalen = len; 1101 /* packet changed; tell engine to send new advertisments */ 1102 frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0, 1103 &ra_iface->if_index, sizeof(ra_iface->if_index)); 1104 } 1105 } 1106 1107 void 1108 build_leaving_packet(struct ra_iface *ra_iface) 1109 { 1110 struct nd_router_advert ra; 1111 size_t len; 1112 1113 len = sizeof(ra); 1114 1115 memset(&ra, 0, sizeof(ra)); 1116 1117 ra.nd_ra_type = ND_ROUTER_ADVERT; 1118 1119 memcpy(ra_iface->data, &ra, sizeof(ra)); 1120 ra_iface->datalen = sizeof(ra); 1121 } 1122 1123 void 1124 ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to) 1125 { 1126 1127 struct cmsghdr *cm; 1128 struct in6_pktinfo *pi; 1129 ssize_t len; 1130 int hoplimit = 255; 1131 1132 sndmhdr.msg_name = to; 1133 sndmhdr.msg_iov[0].iov_base = ra_iface->data; 1134 sndmhdr.msg_iov[0].iov_len = ra_iface->datalen; 1135 1136 cm = CMSG_FIRSTHDR(&sndmhdr); 1137 /* specify the outgoing interface */ 1138 cm->cmsg_level = IPPROTO_IPV6; 1139 cm->cmsg_type = IPV6_PKTINFO; 1140 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1141 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 1142 memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); 1143 pi->ipi6_ifindex = ra_iface->if_index; 1144 1145 /* specify the hop limit of the packet */ 1146 cm = CMSG_NXTHDR(&sndmhdr, cm); 1147 cm->cmsg_level = IPPROTO_IPV6; 1148 cm->cmsg_type = IPV6_HOPLIMIT; 1149 cm->cmsg_len = CMSG_LEN(sizeof(int)); 1150 memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); 1151 1152 log_debug("send RA on %s", ra_iface->name); 1153 1154 len = sendmsg(icmp6sock, &sndmhdr, 0); 1155 if (len < 0) 1156 log_warn("sendmsg on %s", ra_iface->name); 1157 1158 } 1159 1160 #define ROUNDUP(a) \ 1161 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 1162 1163 void 1164 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 1165 { 1166 int i; 1167 1168 for (i = 0; i < RTAX_MAX; i++) { 1169 if (addrs & (1 << i)) { 1170 rti_info[i] = sa; 1171 sa = (struct sockaddr *)((char *)(sa) + 1172 ROUNDUP(sa->sa_len)); 1173 } else 1174 rti_info[i] = NULL; 1175 } 1176 } 1177 1178 void 1179 route_receive(int fd, short events, void *arg) 1180 { 1181 static uint8_t *buf; 1182 1183 struct rt_msghdr *rtm; 1184 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1185 ssize_t n; 1186 1187 if (buf == NULL) { 1188 buf = malloc(ROUTE_SOCKET_BUF_SIZE); 1189 if (buf == NULL) 1190 fatal("malloc"); 1191 } 1192 rtm = (struct rt_msghdr *)buf; 1193 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) { 1194 if (errno == EAGAIN || errno == EINTR) 1195 return; 1196 log_warn("dispatch_rtmsg: read error"); 1197 return; 1198 } 1199 1200 if (n == 0) 1201 fatal("routing socket closed"); 1202 1203 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) { 1204 log_warnx("partial rtm of %zd in buffer", n); 1205 return; 1206 } 1207 1208 if (rtm->rtm_version != RTM_VERSION) 1209 return; 1210 1211 sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen); 1212 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 1213 1214 handle_route_message(rtm, rti_info); 1215 } 1216 1217 void 1218 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) 1219 { 1220 switch (rtm->rtm_type) { 1221 case RTM_IFINFO: 1222 case RTM_NEWADDR: 1223 case RTM_DELADDR: 1224 /* 1225 * do the same thing as after a config reload when interfaces 1226 * change or IPv6 addresses show up / disappear 1227 */ 1228 merge_ra_interfaces(); 1229 break; 1230 default: 1231 log_debug("unexpected RTM: %d", rtm->rtm_type); 1232 break; 1233 } 1234 } 1235