1 /* $OpenBSD: frontend.c,v 1.28 2019/04/12 07:03:11 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, routesock = -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 != -1) 460 fatalx("%s: received unexpected icmp6 fd", 461 __func__); 462 if ((icmp6sock = imsg.fd) == -1) 463 fatalx("%s: expected to receive imsg " 464 "ICMPv6 fd but didn't receive any", 465 __func__); 466 event_set(&icmp6ev.ev, icmp6sock, EV_READ | EV_PERSIST, 467 icmp6_receive, NULL); 468 break; 469 case IMSG_ROUTESOCK: 470 if (routesock != -1) 471 fatalx("%s: received unexpected routesock fd", 472 __func__); 473 if ((routesock = imsg.fd) == -1) 474 fatalx("%s: expected to receive imsg " 475 "routesocket fd but didn't receive any", 476 __func__); 477 event_set(&ev_route, routesock, EV_READ | EV_PERSIST, 478 route_receive, NULL); 479 break; 480 case IMSG_STARTUP: 481 if (pledge("stdio inet unix route mcast", NULL) == -1) 482 fatal("pledge"); 483 frontend_startup(); 484 break; 485 case IMSG_CONTROLFD: 486 if (control_state.fd != -1) 487 fatalx("%s: received unexpected controlsock", 488 __func__); 489 if ((fd = imsg.fd) == -1) 490 fatalx("%s: expected to receive imsg " 491 "control fd but didn't receive any", 492 __func__); 493 control_state.fd = fd; 494 /* Listen on control socket. */ 495 TAILQ_INIT(&ctl_conns); 496 control_listen(); 497 break; 498 default: 499 log_debug("%s: error handling imsg %d", __func__, 500 imsg.hdr.type); 501 break; 502 } 503 imsg_free(&imsg); 504 } 505 if (!shut) 506 imsg_event_add(iev); 507 else { 508 /* This pipe is dead. Remove its event handler. */ 509 event_del(&iev->ev); 510 event_loopexit(NULL); 511 } 512 } 513 514 void 515 frontend_dispatch_engine(int fd, short event, void *bula) 516 { 517 struct imsgev *iev = bula; 518 struct imsgbuf *ibuf = &iev->ibuf; 519 struct imsg imsg; 520 struct imsg_send_ra send_ra; 521 struct ra_iface *ra_iface; 522 uint32_t if_index; 523 int n, shut = 0; 524 525 if (event & EV_READ) { 526 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 527 fatal("imsg_read error"); 528 if (n == 0) /* Connection closed. */ 529 shut = 1; 530 } 531 if (event & EV_WRITE) { 532 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 533 fatal("msgbuf_write"); 534 if (n == 0) /* Connection closed. */ 535 shut = 1; 536 } 537 538 for (;;) { 539 if ((n = imsg_get(ibuf, &imsg)) == -1) 540 fatal("%s: imsg_get error", __func__); 541 if (n == 0) /* No more messages. */ 542 break; 543 544 switch (imsg.hdr.type) { 545 case IMSG_SEND_RA: 546 if (IMSG_DATA_SIZE(imsg) != sizeof(send_ra)) 547 fatalx("%s: IMSG_SEND_RA wrong length: %lu", 548 __func__, IMSG_DATA_SIZE(imsg)); 549 memcpy(&send_ra, imsg.data, sizeof(send_ra)); 550 ra_iface = find_ra_iface_by_id(send_ra.if_index); 551 if (ra_iface) 552 ra_output(ra_iface, &send_ra.to); 553 break; 554 case IMSG_REMOVE_IF: 555 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 556 fatalx("%s: IMSG_REMOVE_IF wrong length: %lu", 557 __func__, IMSG_DATA_SIZE(imsg)); 558 memcpy(&if_index, imsg.data, sizeof(if_index)); 559 ra_iface = find_ra_iface_by_id(if_index); 560 if (ra_iface) { 561 TAILQ_REMOVE(&ra_interfaces, ra_iface, entry); 562 free_ra_iface(ra_iface); 563 } 564 break; 565 default: 566 log_debug("%s: error handling imsg %d", __func__, 567 imsg.hdr.type); 568 break; 569 } 570 imsg_free(&imsg); 571 } 572 if (!shut) 573 imsg_event_add(iev); 574 else { 575 /* This pipe is dead. Remove its event handler. */ 576 event_del(&iev->ev); 577 event_loopexit(NULL); 578 } 579 } 580 581 void 582 frontend_startup(void) 583 { 584 if (!event_initialized(&ev_route)) 585 fatalx("%s: did not receive a route socket from the main " 586 "process", __func__); 587 588 event_add(&ev_route, NULL); 589 590 if (!event_initialized(&icmp6ev.ev)) 591 fatalx("%s: did not receive a icmp6 socket fd from the main " 592 "process", __func__); 593 594 event_add(&icmp6ev.ev, NULL); 595 596 frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0); 597 } 598 599 600 void 601 icmp6_receive(int fd, short events, void *arg) 602 { 603 struct imsg_ra_rs ra_rs; 604 struct in6_pktinfo *pi = NULL; 605 struct cmsghdr *cm; 606 ssize_t len; 607 int if_index = 0, *hlimp = NULL; 608 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 609 610 if ((len = recvmsg(fd, &icmp6ev.rcvmhdr, 0)) < 0) { 611 log_warn("recvmsg"); 612 return; 613 } 614 615 /* extract optional information via Advanced API */ 616 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev.rcvmhdr); cm; 617 cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev.rcvmhdr, cm)) { 618 if (cm->cmsg_level == IPPROTO_IPV6 && 619 cm->cmsg_type == IPV6_PKTINFO && 620 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { 621 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 622 if_index = pi->ipi6_ifindex; 623 } 624 if (cm->cmsg_level == IPPROTO_IPV6 && 625 cm->cmsg_type == IPV6_HOPLIMIT && 626 cm->cmsg_len == CMSG_LEN(sizeof(int))) 627 hlimp = (int *)CMSG_DATA(cm); 628 } 629 630 if (if_index == 0) { 631 log_warnx("failed to get receiving interface"); 632 return; 633 } 634 635 if (hlimp == NULL) { 636 log_warnx("failed to get receiving hop limit"); 637 return; 638 } 639 640 if (*hlimp != 255) { 641 log_warnx("invalid 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 return; 646 } 647 648 log_debug("RA or RS with hop limit of %d from %s on %s", 649 *hlimp, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr, 650 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 651 ifnamebuf)); 652 653 if ((size_t)len > sizeof(ra_rs.packet)) { 654 log_warnx("invalid RA or RS with size %ld from %s on %s", 655 len, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr, 656 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 657 ifnamebuf)); 658 return; 659 } 660 661 ra_rs.if_index = if_index; 662 memcpy(&ra_rs.from, &icmp6ev.from, sizeof(ra_rs.from)); 663 ra_rs.len = len; 664 memcpy(ra_rs.packet, icmp6ev.answer, len); 665 666 frontend_imsg_compose_engine(IMSG_RA_RS, 0, &ra_rs, sizeof(ra_rs)); 667 } 668 669 void 670 join_all_routers_mcast_group(struct ra_iface *ra_iface) 671 { 672 log_debug("joining multicast group on %s", ra_iface->name); 673 all_routers.ipv6mr_interface = ra_iface->if_index; 674 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 675 &all_routers, sizeof(all_routers)) == -1) 676 fatal("IPV6_JOIN_GROUP(%s)", ra_iface->name); 677 } 678 679 void 680 leave_all_routers_mcast_group(struct ra_iface *ra_iface) 681 { 682 log_debug("leaving multicast group on %s", ra_iface->name); 683 all_routers.ipv6mr_interface = ra_iface->if_index; 684 setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, 685 &all_routers, sizeof(all_routers)); 686 } 687 688 struct ra_iface* 689 find_ra_iface_by_id(uint32_t if_index) 690 { 691 struct ra_iface *ra_iface; 692 693 TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) { 694 if (ra_iface->if_index == if_index) 695 return ra_iface; 696 } 697 return (NULL); 698 } 699 700 struct ra_iface* 701 find_ra_iface_by_name(char *if_name) 702 { 703 struct ra_iface *ra_iface; 704 705 TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) { 706 if (strcmp(ra_iface->name, if_name) == 0) 707 return ra_iface; 708 } 709 return (NULL); 710 } 711 712 struct ra_iface_conf* 713 find_ra_iface_conf(struct ra_iface_conf_head *head, char *if_name) 714 { 715 struct ra_iface_conf *ra_iface_conf; 716 717 SIMPLEQ_FOREACH(ra_iface_conf, head, entry) { 718 if (strcmp(ra_iface_conf->name, if_name) == 0) 719 return ra_iface_conf; 720 } 721 return (NULL); 722 } 723 724 void 725 merge_ra_interface(char *name, char *conf_name) 726 { 727 struct ra_iface *ra_iface; 728 uint32_t if_index; 729 730 if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { 731 log_debug("keeping interface %s", name); 732 ra_iface->removed = 0; 733 return; 734 } 735 736 log_debug("new interface %s", name); 737 if ((if_index = if_nametoindex(name)) == 0) 738 return; 739 log_debug("adding interface %s", name); 740 if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL) 741 fatal("%s", __func__); 742 743 strlcpy(ra_iface->name, name, sizeof(ra_iface->name)); 744 strlcpy(ra_iface->conf_name, conf_name, 745 sizeof(ra_iface->conf_name)); 746 747 ra_iface->if_index = if_index; 748 SIMPLEQ_INIT(&ra_iface->prefixes); 749 TAILQ_INSERT_TAIL(&ra_interfaces, ra_iface, entry); 750 join_all_routers_mcast_group(ra_iface); 751 } 752 753 void 754 merge_ra_interfaces(void) 755 { 756 struct ra_iface_conf *ra_iface_conf; 757 struct ra_prefix_conf *ra_prefix_conf; 758 struct ra_iface *ra_iface; 759 struct ifgroupreq ifgr; 760 struct ifg_req *ifg; 761 char *conf_name; 762 unsigned int len; 763 764 TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) 765 ra_iface->removed = 1; 766 767 SIMPLEQ_FOREACH(ra_iface_conf, &frontend_conf->ra_iface_list, entry) { 768 conf_name = ra_iface_conf->name; 769 770 /* check if network interface or group */ 771 if (isdigit((unsigned char)conf_name[strlen(conf_name) - 1])) { 772 merge_ra_interface(conf_name, conf_name); 773 } else { 774 log_debug("interface group %s", conf_name); 775 776 memset(&ifgr, 0, sizeof(ifgr)); 777 strlcpy(ifgr.ifgr_name, conf_name, 778 sizeof(ifgr.ifgr_name)); 779 if (ioctl(ioctlsock, SIOCGIFGMEMB, 780 (caddr_t)&ifgr) == -1) 781 continue; 782 783 len = ifgr.ifgr_len; 784 if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 785 fatal("%s: calloc", __func__); 786 if (ioctl(ioctlsock, SIOCGIFGMEMB, 787 (caddr_t)&ifgr) == -1) { 788 log_debug("group %s without members", 789 conf_name); 790 free(ifgr.ifgr_groups); 791 continue; 792 } 793 794 for (ifg = ifgr.ifgr_groups; 795 (ifg != NULL) && (len >= sizeof(struct ifg_req)); 796 ifg++) { 797 len -= sizeof(struct ifg_req); 798 merge_ra_interface(ifg->ifgrq_member, 799 conf_name); 800 } 801 free(ifgr.ifgr_groups); 802 } 803 } 804 805 TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) { 806 while ((ra_prefix_conf = SIMPLEQ_FIRST(&ra_iface->prefixes)) 807 != NULL) { 808 SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes, 809 entry); 810 free(ra_prefix_conf); 811 } 812 ra_iface->prefix_count = 0; 813 814 if (ra_iface->removed) { 815 log_debug("iface removed: %s", ra_iface->name); 816 build_leaving_packet(ra_iface); 817 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 818 &ra_iface->if_index, sizeof(ra_iface->if_index)); 819 continue; 820 } 821 822 ra_iface_conf = find_ra_iface_conf( 823 &frontend_conf->ra_iface_list, ra_iface->conf_name); 824 825 log_debug("add static prefixes for %s", ra_iface->name); 826 827 SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface_conf->ra_prefix_list, 828 entry) { 829 add_new_prefix_to_ra_iface(ra_iface, 830 &ra_prefix_conf->prefix, 831 ra_prefix_conf->prefixlen, ra_prefix_conf); 832 } 833 834 if (ra_iface_conf->autoprefix) 835 get_interface_prefixes(ra_iface, 836 ra_iface_conf->autoprefix); 837 838 build_packet(ra_iface); 839 } 840 } 841 842 void 843 free_ra_iface(struct ra_iface *ra_iface) 844 { 845 struct ra_prefix_conf *prefix; 846 847 leave_all_routers_mcast_group(ra_iface); 848 849 while ((prefix = SIMPLEQ_FIRST(&ra_iface->prefixes)) != NULL) { 850 SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes, entry); 851 free(prefix); 852 } 853 854 free(ra_iface); 855 } 856 857 /* from kame via ifconfig, where it's called prefix() */ 858 int 859 in6_mask2prefixlen(struct in6_addr *in6) 860 { 861 u_char *nam = (u_char *)in6; 862 int byte, bit, plen = 0, size = sizeof(struct in6_addr); 863 864 for (byte = 0; byte < size; byte++, plen += 8) 865 if (nam[byte] != 0xff) 866 break; 867 if (byte == size) 868 return (plen); 869 for (bit = 7; bit != 0; bit--, plen++) 870 if (!(nam[byte] & (1 << bit))) 871 break; 872 for (; bit != 0; bit--) 873 if (nam[byte] & (1 << bit)) 874 return (0); 875 byte++; 876 for (; byte < size; byte++) 877 if (nam[byte]) 878 return (0); 879 return (plen); 880 } 881 882 void 883 get_interface_prefixes(struct ra_iface *ra_iface, struct ra_prefix_conf 884 *autoprefix) 885 { 886 struct in6_ifreq ifr6; 887 struct ifaddrs *ifap, *ifa; 888 struct sockaddr_in6 *sin6; 889 int prefixlen; 890 891 log_debug("%s: %s", __func__, ra_iface->name); 892 893 if (getifaddrs(&ifap) != 0) 894 fatal("getifaddrs"); 895 896 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 897 if (strcmp(ra_iface->name, ifa->ifa_name) != 0) 898 continue; 899 if (ifa->ifa_addr->sa_family != AF_INET6) 900 continue; 901 902 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 903 904 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 905 continue; 906 907 memset(&ifr6, 0, sizeof(ifr6)); 908 (void) strlcpy(ifr6.ifr_name, ra_iface->name, 909 sizeof(ifr6.ifr_name)); 910 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 911 912 if (ioctl(ioctlsock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) 913 continue; /* addr got deleted while we were looking */ 914 915 prefixlen = in6_mask2prefixlen(&((struct sockaddr_in6 *) 916 &ifr6.ifr_addr)->sin6_addr); 917 918 if (prefixlen == 128) 919 continue; 920 921 mask_prefix(&sin6->sin6_addr, prefixlen); 922 923 add_new_prefix_to_ra_iface(ra_iface, &sin6->sin6_addr, 924 prefixlen, autoprefix); 925 } 926 freeifaddrs(ifap); 927 } 928 929 struct ra_prefix_conf* 930 find_ra_prefix_conf(struct ra_prefix_conf_head* head, struct in6_addr *prefix, 931 int prefixlen) 932 { 933 struct ra_prefix_conf *ra_prefix_conf; 934 935 SIMPLEQ_FOREACH(ra_prefix_conf, head, entry) { 936 if (ra_prefix_conf->prefixlen == prefixlen && 937 memcmp(&ra_prefix_conf->prefix, prefix, sizeof(*prefix)) == 938 0) 939 return (ra_prefix_conf); 940 } 941 return (NULL); 942 } 943 944 void 945 add_new_prefix_to_ra_iface(struct ra_iface *ra_iface, struct in6_addr *addr, 946 int prefixlen, struct ra_prefix_conf *ra_prefix_conf) 947 { 948 struct ra_prefix_conf *new_ra_prefix_conf; 949 950 if (find_ra_prefix_conf(&ra_iface->prefixes, addr, prefixlen)) { 951 log_debug("ignoring duplicate %s/%d prefix", 952 in6_to_str(addr), prefixlen); 953 return; 954 } 955 956 log_debug("adding %s/%d prefix", in6_to_str(addr), prefixlen); 957 958 if ((new_ra_prefix_conf = calloc(1, sizeof(*ra_prefix_conf))) == NULL) 959 fatal("%s", __func__); 960 new_ra_prefix_conf->prefix = *addr; 961 new_ra_prefix_conf->prefixlen = prefixlen; 962 new_ra_prefix_conf->vltime = ra_prefix_conf->vltime; 963 new_ra_prefix_conf->pltime = ra_prefix_conf->pltime; 964 new_ra_prefix_conf->aflag = ra_prefix_conf->aflag; 965 new_ra_prefix_conf->lflag = ra_prefix_conf->lflag; 966 SIMPLEQ_INSERT_TAIL(&ra_iface->prefixes, new_ra_prefix_conf, entry); 967 ra_iface->prefix_count++; 968 } 969 970 void 971 build_packet(struct ra_iface *ra_iface) 972 { 973 struct nd_router_advert *ra; 974 struct nd_opt_mtu *ndopt_mtu; 975 struct nd_opt_prefix_info *ndopt_pi; 976 struct ra_iface_conf *ra_iface_conf; 977 struct ra_options_conf *ra_options_conf; 978 struct ra_prefix_conf *ra_prefix_conf; 979 struct nd_opt_rdnss *ndopt_rdnss; 980 struct nd_opt_dnssl *ndopt_dnssl; 981 struct ra_rdnss_conf *ra_rdnss; 982 struct ra_dnssl_conf *ra_dnssl; 983 size_t len, label_len; 984 uint8_t *p, buf[RA_MAX_SIZE]; 985 char *label_start, *label_end; 986 987 ra_iface_conf = find_ra_iface_conf(&frontend_conf->ra_iface_list, 988 ra_iface->conf_name); 989 ra_options_conf = &ra_iface_conf->ra_options; 990 991 len = sizeof(*ra); 992 if (ra_options_conf->mtu > 0) 993 len += sizeof(*ndopt_mtu); 994 len += sizeof(*ndopt_pi) * ra_iface->prefix_count; 995 if (ra_iface_conf->ra_options.rdnss_count > 0) 996 len += sizeof(*ndopt_rdnss) + 997 ra_iface_conf->ra_options.rdnss_count * 998 sizeof(struct in6_addr); 999 1000 if (ra_iface_conf->ra_options.dnssl_len > 0) 1001 /* round up to 8 byte boundary */ 1002 len += sizeof(*ndopt_dnssl) + 1003 ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7); 1004 1005 if (len > sizeof(ra_iface->data)) 1006 fatalx("%s: packet too big", __func__); /* XXX send multiple */ 1007 1008 p = buf; 1009 1010 ra = (struct nd_router_advert *)p; 1011 1012 memset(ra, 0, sizeof(*ra)); 1013 1014 ra->nd_ra_type = ND_ROUTER_ADVERT; 1015 ra->nd_ra_curhoplimit = ra_options_conf->cur_hl; 1016 if (ra_options_conf->m_flag) 1017 ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; 1018 if (ra_options_conf->o_flag) 1019 ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; 1020 if (ra_iface->removed) 1021 /* tell clients that we are no longer a default router */ 1022 ra->nd_ra_router_lifetime = 0; 1023 else if (ra_options_conf->dfr) { 1024 ra->nd_ra_router_lifetime = 1025 htons(ra_options_conf->router_lifetime); 1026 } 1027 ra->nd_ra_reachable = htonl(ra_options_conf->reachable_time); 1028 ra->nd_ra_retransmit = htonl(ra_options_conf->retrans_timer); 1029 p += sizeof(*ra); 1030 1031 if (ra_options_conf->mtu > 0) { 1032 ndopt_mtu = (struct nd_opt_mtu *)p; 1033 ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU; 1034 ndopt_mtu->nd_opt_mtu_len = 1; 1035 ndopt_mtu->nd_opt_mtu_reserved = 0; 1036 ndopt_mtu->nd_opt_mtu_mtu = htonl(ra_options_conf->mtu); 1037 p += sizeof(*ndopt_mtu); 1038 } 1039 1040 SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface->prefixes, entry) { 1041 ndopt_pi = (struct nd_opt_prefix_info *)p; 1042 memset(ndopt_pi, 0, sizeof(*ndopt_pi)); 1043 ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; 1044 ndopt_pi->nd_opt_pi_len = 4; 1045 ndopt_pi->nd_opt_pi_prefix_len = ra_prefix_conf->prefixlen; 1046 if (ra_prefix_conf->lflag) 1047 ndopt_pi->nd_opt_pi_flags_reserved |= 1048 ND_OPT_PI_FLAG_ONLINK; 1049 if (ra_prefix_conf->aflag) 1050 ndopt_pi->nd_opt_pi_flags_reserved |= 1051 ND_OPT_PI_FLAG_AUTO; 1052 ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime); 1053 ndopt_pi->nd_opt_pi_preferred_time = 1054 htonl(ra_prefix_conf->pltime); 1055 ndopt_pi->nd_opt_pi_prefix = ra_prefix_conf->prefix; 1056 1057 p += sizeof(*ndopt_pi); 1058 } 1059 1060 if (ra_iface_conf->ra_options.rdnss_count > 0) { 1061 ndopt_rdnss = (struct nd_opt_rdnss *)p; 1062 ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS; 1063 ndopt_rdnss->nd_opt_rdnss_len = 1 + 1064 ra_iface_conf->ra_options.rdnss_count * 2; 1065 ndopt_rdnss->nd_opt_rdnss_reserved = 0; 1066 ndopt_rdnss->nd_opt_rdnss_lifetime = 1067 htonl(ra_iface_conf->ra_options.rdns_lifetime); 1068 p += sizeof(struct nd_opt_rdnss); 1069 SIMPLEQ_FOREACH(ra_rdnss, 1070 &ra_iface_conf->ra_options.ra_rdnss_list, entry) { 1071 memcpy(p, &ra_rdnss->rdnss, sizeof(ra_rdnss->rdnss)); 1072 p += sizeof(ra_rdnss->rdnss); 1073 } 1074 } 1075 1076 if (ra_iface_conf->ra_options.dnssl_len > 0) { 1077 ndopt_dnssl = (struct nd_opt_dnssl *)p; 1078 ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL; 1079 /* round up to 8 byte boundary */ 1080 ndopt_dnssl->nd_opt_dnssl_len = 1 + 1081 ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7) / 8; 1082 ndopt_dnssl->nd_opt_dnssl_reserved = 0; 1083 ndopt_dnssl->nd_opt_dnssl_lifetime = 1084 htonl(ra_iface_conf->ra_options.rdns_lifetime); 1085 p += sizeof(struct nd_opt_dnssl); 1086 1087 SIMPLEQ_FOREACH(ra_dnssl, 1088 &ra_iface_conf->ra_options.ra_dnssl_list, entry) { 1089 label_start = ra_dnssl->search; 1090 while ((label_end = strchr(label_start, '.')) != NULL) { 1091 label_len = label_end - label_start; 1092 *p++ = label_len; 1093 memcpy(p, label_start, label_len); 1094 p += label_len; 1095 label_start = label_end + 1; 1096 } 1097 *p++ = '\0'; /* last dot */ 1098 } 1099 /* zero pad */ 1100 while (((uintptr_t)p) % 8 != 0) 1101 *p++ = '\0'; 1102 } 1103 1104 if (len != ra_iface->datalen || memcmp(buf, ra_iface->data, len) 1105 != 0) { 1106 memcpy(ra_iface->data, buf, len); 1107 ra_iface->datalen = len; 1108 /* packet changed; tell engine to send new advertisments */ 1109 frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0, 1110 &ra_iface->if_index, sizeof(ra_iface->if_index)); 1111 } 1112 } 1113 1114 void 1115 build_leaving_packet(struct ra_iface *ra_iface) 1116 { 1117 struct nd_router_advert ra; 1118 size_t len; 1119 1120 len = sizeof(ra); 1121 1122 memset(&ra, 0, sizeof(ra)); 1123 1124 ra.nd_ra_type = ND_ROUTER_ADVERT; 1125 1126 memcpy(ra_iface->data, &ra, sizeof(ra)); 1127 ra_iface->datalen = sizeof(ra); 1128 } 1129 1130 void 1131 ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to) 1132 { 1133 1134 struct cmsghdr *cm; 1135 struct in6_pktinfo *pi; 1136 ssize_t len; 1137 int hoplimit = 255; 1138 1139 sndmhdr.msg_name = to; 1140 sndmhdr.msg_iov[0].iov_base = ra_iface->data; 1141 sndmhdr.msg_iov[0].iov_len = ra_iface->datalen; 1142 1143 cm = CMSG_FIRSTHDR(&sndmhdr); 1144 /* specify the outgoing interface */ 1145 cm->cmsg_level = IPPROTO_IPV6; 1146 cm->cmsg_type = IPV6_PKTINFO; 1147 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1148 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 1149 memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); 1150 pi->ipi6_ifindex = ra_iface->if_index; 1151 1152 /* specify the hop limit of the packet */ 1153 cm = CMSG_NXTHDR(&sndmhdr, cm); 1154 cm->cmsg_level = IPPROTO_IPV6; 1155 cm->cmsg_type = IPV6_HOPLIMIT; 1156 cm->cmsg_len = CMSG_LEN(sizeof(int)); 1157 memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); 1158 1159 log_debug("send RA on %s", ra_iface->name); 1160 1161 len = sendmsg(icmp6sock, &sndmhdr, 0); 1162 if (len < 0) 1163 log_warn("sendmsg on %s", ra_iface->name); 1164 1165 } 1166 1167 #define ROUNDUP(a) \ 1168 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 1169 1170 void 1171 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 1172 { 1173 int i; 1174 1175 for (i = 0; i < RTAX_MAX; i++) { 1176 if (addrs & (1 << i)) { 1177 rti_info[i] = sa; 1178 sa = (struct sockaddr *)((char *)(sa) + 1179 ROUNDUP(sa->sa_len)); 1180 } else 1181 rti_info[i] = NULL; 1182 } 1183 } 1184 1185 void 1186 route_receive(int fd, short events, void *arg) 1187 { 1188 static uint8_t *buf; 1189 1190 struct rt_msghdr *rtm; 1191 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1192 ssize_t n; 1193 1194 if (buf == NULL) { 1195 buf = malloc(ROUTE_SOCKET_BUF_SIZE); 1196 if (buf == NULL) 1197 fatal("malloc"); 1198 } 1199 rtm = (struct rt_msghdr *)buf; 1200 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) { 1201 if (errno == EAGAIN || errno == EINTR) 1202 return; 1203 log_warn("dispatch_rtmsg: read error"); 1204 return; 1205 } 1206 1207 if (n == 0) 1208 fatal("routing socket closed"); 1209 1210 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) { 1211 log_warnx("partial rtm of %zd in buffer", n); 1212 return; 1213 } 1214 1215 if (rtm->rtm_version != RTM_VERSION) 1216 return; 1217 1218 sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen); 1219 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 1220 1221 handle_route_message(rtm, rti_info); 1222 } 1223 1224 void 1225 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) 1226 { 1227 switch (rtm->rtm_type) { 1228 case RTM_IFINFO: 1229 case RTM_NEWADDR: 1230 case RTM_DELADDR: 1231 /* 1232 * do the same thing as after a config reload when interfaces 1233 * change or IPv6 addresses show up / disappear 1234 */ 1235 merge_ra_interfaces(); 1236 break; 1237 default: 1238 log_debug("unexpected RTM: %d", rtm->rtm_type); 1239 break; 1240 } 1241 } 1242