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