1 /* $OpenBSD: kroute.c,v 1.48 2015/07/17 20:12:38 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/socket.h> 22 #include <sys/sysctl.h> 23 #include <sys/tree.h> 24 #include <sys/uio.h> 25 #include <netinet/in.h> 26 #include <arpa/inet.h> 27 #include <net/if.h> 28 #include <net/if_dl.h> 29 #include <net/if_types.h> 30 #include <net/route.h> 31 #include <err.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 #include <limits.h> 39 40 #include "ospf6d.h" 41 #include "ospfe.h" 42 #include "log.h" 43 44 struct { 45 u_int32_t rtseq; 46 pid_t pid; 47 int fib_sync; 48 int fd; 49 struct event ev; 50 } kr_state; 51 52 struct kroute_node { 53 RB_ENTRY(kroute_node) entry; 54 struct kroute r; 55 struct kroute_node *next; 56 }; 57 58 void kr_redist_remove(struct kroute_node *, struct kroute_node *); 59 int kr_redist_eval(struct kroute *, struct rroute *); 60 void kr_redistribute(struct kroute_node *); 61 int kroute_compare(struct kroute_node *, struct kroute_node *); 62 63 struct kroute_node *kroute_find(const struct in6_addr *, u_int8_t); 64 struct kroute_node *kroute_matchgw(struct kroute_node *, 65 struct in6_addr *, unsigned int); 66 int kroute_insert(struct kroute_node *); 67 int kroute_remove(struct kroute_node *); 68 void kroute_clear(void); 69 70 struct iface *kif_update(u_short, int, struct if_data *, 71 struct sockaddr_dl *); 72 int kif_validate(u_short); 73 74 struct kroute_node *kroute_match(struct in6_addr *); 75 76 int protect_lo(void); 77 void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 78 void if_change(u_short, int, struct if_data *); 79 void if_newaddr(u_short, struct sockaddr_in6 *, 80 struct sockaddr_in6 *, struct sockaddr_in6 *); 81 void if_deladdr(u_short, struct sockaddr_in6 *, 82 struct sockaddr_in6 *, struct sockaddr_in6 *); 83 void if_announce(void *); 84 85 int send_rtmsg(int, int, struct kroute *); 86 int dispatch_rtmsg(void); 87 int fetchtable(void); 88 89 RB_HEAD(kroute_tree, kroute_node) krt; 90 RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare) 91 RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare) 92 93 int 94 kr_init(int fs) 95 { 96 int opt = 0, rcvbuf, default_rcvbuf; 97 socklen_t optlen; 98 99 kr_state.fib_sync = fs; 100 101 if ((kr_state.fd = socket(AF_ROUTE, 102 SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { 103 log_warn("kr_init: socket"); 104 return (-1); 105 } 106 107 /* not interested in my own messages */ 108 if (setsockopt(kr_state.fd, SOL_SOCKET, SO_USELOOPBACK, 109 &opt, sizeof(opt)) == -1) 110 log_warn("kr_init: setsockopt"); /* not fatal */ 111 112 /* grow receive buffer, don't wanna miss messages */ 113 optlen = sizeof(default_rcvbuf); 114 if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, 115 &default_rcvbuf, &optlen) == -1) 116 log_warn("kr_init getsockopt SOL_SOCKET SO_RCVBUF"); 117 else 118 for (rcvbuf = MAX_RTSOCK_BUF; 119 rcvbuf > default_rcvbuf && 120 setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, 121 &rcvbuf, sizeof(rcvbuf)) == -1 && errno == ENOBUFS; 122 rcvbuf /= 2) 123 ; /* nothing */ 124 125 kr_state.pid = getpid(); 126 kr_state.rtseq = 1; 127 128 RB_INIT(&krt); 129 130 if (fetchtable() == -1) 131 return (-1); 132 133 if (protect_lo() == -1) 134 return (-1); 135 136 event_set(&kr_state.ev, kr_state.fd, EV_READ | EV_PERSIST, 137 kr_dispatch_msg, NULL); 138 event_add(&kr_state.ev, NULL); 139 140 return (0); 141 } 142 143 int 144 kr_change(struct kroute *kroute) 145 { 146 struct kroute_node *kr; 147 int action = RTM_ADD; 148 149 kroute->rtlabel = rtlabel_tag2id(kroute->ext_tag); 150 151 if ((kr = kroute_find(&kroute->prefix, kroute->prefixlen)) != 152 NULL) { 153 if (!(kr->r.flags & F_KERNEL)) 154 action = RTM_CHANGE; 155 else { /* a non-ospf route already exists. not a problem */ 156 if (!(kr->r.flags & F_BGPD_INSERTED)) { 157 do { 158 kr->r.flags |= F_OSPFD_INSERTED; 159 kr = kr->next; 160 } while (kr); 161 return (0); 162 } 163 /* 164 * XXX as long as there is no multipath support in 165 * bgpd this is safe else we end up in a bad situation. 166 */ 167 /* 168 * ospf route has higher pref 169 * - reset flags to the ospf ones 170 * - use RTM_CHANGE 171 * - zero out ifindex (this is no longer relevant) 172 */ 173 action = RTM_CHANGE; 174 kr->r.flags = kroute->flags | F_OSPFD_INSERTED; 175 kr->r.ifindex = 0; 176 rtlabel_unref(kr->r.rtlabel); 177 kr->r.ext_tag = kroute->ext_tag; 178 kr->r.rtlabel = kroute->rtlabel; 179 } 180 } 181 182 /* nexthop within 127/8 -> ignore silently */ 183 if (kr && IN6_IS_ADDR_LOOPBACK(&kr->r.nexthop)) 184 return (0); 185 186 /* 187 * Ingnore updates that did not change the route. 188 * Currently only the nexthop can change. 189 */ 190 if (kr && kr->r.scope == kroute->scope && 191 IN6_ARE_ADDR_EQUAL(&kr->r.nexthop, &kroute->nexthop)) 192 return (0); 193 194 if (send_rtmsg(kr_state.fd, action, kroute) == -1) 195 return (-1); 196 197 if (action == RTM_ADD) { 198 if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { 199 log_warn("kr_change"); 200 return (-1); 201 } 202 kr->r.prefix = kroute->prefix; 203 kr->r.prefixlen = kroute->prefixlen; 204 kr->r.nexthop = kroute->nexthop; 205 kr->r.scope = kroute->scope; 206 kr->r.flags = kroute->flags | F_OSPFD_INSERTED; 207 kr->r.ext_tag = kroute->ext_tag; 208 kr->r.rtlabel = kroute->rtlabel; 209 210 if (kroute_insert(kr) == -1) 211 free(kr); 212 } else if (kr) { 213 kr->r.nexthop = kroute->nexthop; 214 kr->r.scope = kroute->scope; 215 } 216 217 return (0); 218 } 219 220 int 221 kr_delete(struct kroute *kroute) 222 { 223 struct kroute_node *kr; 224 225 if ((kr = kroute_find(&kroute->prefix, kroute->prefixlen)) == 226 NULL) 227 return (0); 228 229 if (!(kr->r.flags & F_OSPFD_INSERTED)) 230 return (0); 231 232 if (kr->r.flags & F_KERNEL) { 233 /* remove F_OSPFD_INSERTED flag, route still exists in kernel */ 234 do { 235 kr->r.flags &= ~F_OSPFD_INSERTED; 236 kr = kr->next; 237 } while (kr); 238 return (0); 239 } 240 241 if (send_rtmsg(kr_state.fd, RTM_DELETE, kroute) == -1) 242 return (-1); 243 244 if (kroute_remove(kr) == -1) 245 return (-1); 246 247 return (0); 248 } 249 250 void 251 kr_shutdown(void) 252 { 253 kr_fib_decouple(); 254 kroute_clear(); 255 } 256 257 void 258 kr_fib_couple(void) 259 { 260 struct kroute_node *kr; 261 262 if (kr_state.fib_sync == 1) /* already coupled */ 263 return; 264 265 kr_state.fib_sync = 1; 266 267 RB_FOREACH(kr, kroute_tree, &krt) 268 if (!(kr->r.flags & F_KERNEL)) 269 send_rtmsg(kr_state.fd, RTM_ADD, &kr->r); 270 271 log_info("kernel routing table coupled"); 272 } 273 274 void 275 kr_fib_decouple(void) 276 { 277 struct kroute_node *kr; 278 279 if (kr_state.fib_sync == 0) /* already decoupled */ 280 return; 281 282 RB_FOREACH(kr, kroute_tree, &krt) 283 if (!(kr->r.flags & F_KERNEL)) 284 send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); 285 286 kr_state.fib_sync = 0; 287 288 log_info("kernel routing table decoupled"); 289 } 290 291 /* ARGSUSED */ 292 void 293 kr_dispatch_msg(int fd, short event, void *bula) 294 { 295 dispatch_rtmsg(); 296 } 297 298 void 299 kr_show_route(struct imsg *imsg) 300 { 301 struct kroute_node *kr; 302 struct kroute_node *kn; 303 int flags; 304 struct in6_addr addr; 305 306 switch (imsg->hdr.type) { 307 case IMSG_CTL_KROUTE: 308 if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(flags)) { 309 log_warnx("kr_show_route: wrong imsg len"); 310 return; 311 } 312 memcpy(&flags, imsg->data, sizeof(flags)); 313 RB_FOREACH(kr, kroute_tree, &krt) 314 if (!flags || kr->r.flags & flags) { 315 kn = kr; 316 do { 317 main_imsg_compose_ospfe(IMSG_CTL_KROUTE, 318 imsg->hdr.pid, 319 &kn->r, sizeof(kn->r)); 320 } while ((kn = kn->next) != NULL); 321 } 322 break; 323 case IMSG_CTL_KROUTE_ADDR: 324 if (imsg->hdr.len != IMSG_HEADER_SIZE + 325 sizeof(struct in6_addr)) { 326 log_warnx("kr_show_route: wrong imsg len"); 327 return; 328 } 329 memcpy(&addr, imsg->data, sizeof(addr)); 330 kr = NULL; 331 kr = kroute_match(&addr); 332 if (kr != NULL) 333 main_imsg_compose_ospfe(IMSG_CTL_KROUTE, imsg->hdr.pid, 334 &kr->r, sizeof(kr->r)); 335 break; 336 default: 337 log_debug("kr_show_route: error handling imsg"); 338 break; 339 } 340 341 main_imsg_compose_ospfe(IMSG_CTL_END, imsg->hdr.pid, NULL, 0); 342 } 343 344 void 345 kr_redist_remove(struct kroute_node *kh, struct kroute_node *kn) 346 { 347 struct rroute rr; 348 349 /* was the route redistributed? */ 350 if ((kn->r.flags & F_REDISTRIBUTED) == 0) 351 return; 352 353 /* remove redistributed flag */ 354 kn->r.flags &= ~F_REDISTRIBUTED; 355 rr.kr = kn->r; 356 rr.metric = DEFAULT_REDIST_METRIC; /* some dummy value */ 357 358 /* probably inform the RDE (check if no other path is redistributed) */ 359 for (kn = kh; kn; kn = kn->next) 360 if (kn->r.flags & F_REDISTRIBUTED) 361 break; 362 363 if (kn == NULL) 364 main_imsg_compose_rde(IMSG_NETWORK_DEL, 0, &rr, 365 sizeof(struct rroute)); 366 } 367 368 int 369 kr_redist_eval(struct kroute *kr, struct rroute *rr) 370 { 371 u_int32_t metric = 0; 372 373 /* Only non-ospfd routes are considered for redistribution. */ 374 if (!(kr->flags & F_KERNEL)) 375 goto dont_redistribute; 376 377 /* Dynamic routes are not redistributable. */ 378 if (kr->flags & F_DYNAMIC) 379 goto dont_redistribute; 380 381 /* interface is not up and running so don't announce */ 382 if (kr->flags & F_DOWN) 383 goto dont_redistribute; 384 385 /* 386 * We consider loopback, multicast, link- and site-local, 387 * IPv4 mapped and IPv4 compatible addresses as not redistributable. 388 */ 389 if (IN6_IS_ADDR_LOOPBACK(&kr->prefix) || 390 IN6_IS_ADDR_MULTICAST(&kr->prefix) || 391 IN6_IS_ADDR_LINKLOCAL(&kr->prefix) || 392 IN6_IS_ADDR_SITELOCAL(&kr->prefix) || 393 IN6_IS_ADDR_V4MAPPED(&kr->prefix) || 394 IN6_IS_ADDR_V4COMPAT(&kr->prefix)) 395 goto dont_redistribute; 396 /* 397 * Consider networks with nexthop loopback as not redistributable 398 * unless it is a reject or blackhole route. 399 */ 400 if (IN6_IS_ADDR_LOOPBACK(&kr->nexthop) && 401 !(kr->flags & (F_BLACKHOLE|F_REJECT))) 402 goto dont_redistribute; 403 404 /* Should we redistribute this route? */ 405 if (!ospf_redistribute(kr, &metric)) 406 goto dont_redistribute; 407 408 /* prefix should be redistributed */ 409 kr->flags |= F_REDISTRIBUTED; 410 /* 411 * only one of all multipath routes can be redistributed so 412 * redistribute the best one. 413 */ 414 if (rr->metric > metric) { 415 rr->kr = *kr; 416 rr->metric = metric; 417 } 418 419 return (1); 420 421 dont_redistribute: 422 /* was the route redistributed? */ 423 if ((kr->flags & F_REDISTRIBUTED) == 0) 424 return (0); 425 426 kr->flags &= ~F_REDISTRIBUTED; 427 return (1); 428 } 429 430 void 431 kr_redistribute(struct kroute_node *kh) 432 { 433 struct kroute_node *kn; 434 struct rroute rr; 435 int redistribute = 0; 436 437 bzero(&rr, sizeof(rr)); 438 rr.metric = UINT_MAX; 439 for (kn = kh; kn; kn = kn->next) 440 if (kr_redist_eval(&kn->r, &rr)) 441 redistribute = 1; 442 443 if (!redistribute) 444 return; 445 446 if (rr.kr.flags & F_REDISTRIBUTED) { 447 main_imsg_compose_rde(IMSG_NETWORK_ADD, 0, &rr, 448 sizeof(struct rroute)); 449 } else { 450 rr.metric = DEFAULT_REDIST_METRIC; /* some dummy value */ 451 rr.kr = kh->r; 452 main_imsg_compose_rde(IMSG_NETWORK_DEL, 0, &rr, 453 sizeof(struct rroute)); 454 } 455 } 456 457 void 458 kr_reload(void) 459 { 460 struct kroute_node *kr, *kn; 461 u_int32_t dummy; 462 int r; 463 464 RB_FOREACH(kr, kroute_tree, &krt) { 465 for (kn = kr; kn; kn = kn->next) { 466 r = ospf_redistribute(&kn->r, &dummy); 467 /* 468 * if it is redistributed, redistribute again metric 469 * may have changed. 470 */ 471 if ((kn->r.flags & F_REDISTRIBUTED && !r) || r) 472 break; 473 } 474 if (kn) { 475 /* 476 * kr_redistribute copes with removes and RDE with 477 * duplicates 478 */ 479 kr_redistribute(kr); 480 } 481 } 482 } 483 484 /* rb-tree compare */ 485 int 486 kroute_compare(struct kroute_node *a, struct kroute_node *b) 487 { 488 int i; 489 490 /* XXX maybe switch a & b */ 491 i = memcmp(&a->r.prefix, &b->r.prefix, sizeof(a->r.prefix)); 492 if (i) 493 return (i); 494 if (a->r.prefixlen < b->r.prefixlen) 495 return (-1); 496 if (a->r.prefixlen > b->r.prefixlen) 497 return (1); 498 return (0); 499 } 500 501 /* tree management */ 502 struct kroute_node * 503 kroute_find(const struct in6_addr *prefix, u_int8_t prefixlen) 504 { 505 struct kroute_node s; 506 507 s.r.prefix = *prefix; 508 s.r.prefixlen = prefixlen; 509 510 return (RB_FIND(kroute_tree, &krt, &s)); 511 } 512 513 struct kroute_node * 514 kroute_matchgw(struct kroute_node *kr, struct in6_addr *nh, unsigned int scope) 515 { 516 while (kr) { 517 if (scope == kr->r.scope && 518 IN6_ARE_ADDR_EQUAL(&kr->r.nexthop, nh)) 519 return (kr); 520 kr = kr->next; 521 } 522 523 return (NULL); 524 } 525 526 int 527 kroute_insert(struct kroute_node *kr) 528 { 529 struct kroute_node *krm, *krh; 530 531 if ((krh = RB_INSERT(kroute_tree, &krt, kr)) != NULL) { 532 /* 533 * Multipath route, add at end of list and clone the 534 * ospfd inserted flag. 535 */ 536 krm = krh; 537 kr->r.flags |= krm->r.flags & F_OSPFD_INSERTED; 538 while (krm->next != NULL) 539 krm = krm->next; 540 krm->next = kr; 541 kr->next = NULL; /* to be sure */ 542 } else 543 krh = kr; 544 545 if (!(kr->r.flags & F_KERNEL)) { 546 /* don't validate or redistribute ospf route */ 547 kr->r.flags &= ~F_DOWN; 548 return (0); 549 } 550 551 if (kif_validate(kr->r.ifindex)) 552 kr->r.flags &= ~F_DOWN; 553 else 554 kr->r.flags |= F_DOWN; 555 556 kr_redistribute(krh); 557 return (0); 558 } 559 560 int 561 kroute_remove(struct kroute_node *kr) 562 { 563 struct kroute_node *krm; 564 565 if ((krm = RB_FIND(kroute_tree, &krt, kr)) == NULL) { 566 log_warnx("kroute_remove failed to find %s/%u", 567 log_in6addr(&kr->r.prefix), kr->r.prefixlen); 568 return (-1); 569 } 570 571 if (krm == kr) { 572 /* head element */ 573 if (RB_REMOVE(kroute_tree, &krt, kr) == NULL) { 574 log_warnx("kroute_remove failed for %s/%u", 575 log_in6addr(&kr->r.prefix), kr->r.prefixlen); 576 return (-1); 577 } 578 if (kr->next != NULL) { 579 if (RB_INSERT(kroute_tree, &krt, kr->next) != NULL) { 580 log_warnx("kroute_remove failed to add %s/%u", 581 log_in6addr(&kr->r.prefix), 582 kr->r.prefixlen); 583 return (-1); 584 } 585 } 586 } else { 587 /* somewhere in the list */ 588 while (krm->next != kr && krm->next != NULL) 589 krm = krm->next; 590 if (krm->next == NULL) { 591 log_warnx("kroute_remove multipath list corrupted " 592 "for %s/%u", log_in6addr(&kr->r.prefix), 593 kr->r.prefixlen); 594 return (-1); 595 } 596 krm->next = kr->next; 597 } 598 599 kr_redist_remove(krm, kr); 600 rtlabel_unref(kr->r.rtlabel); 601 602 free(kr); 603 return (0); 604 } 605 606 void 607 kroute_clear(void) 608 { 609 struct kroute_node *kr; 610 611 while ((kr = RB_MIN(kroute_tree, &krt)) != NULL) 612 kroute_remove(kr); 613 } 614 615 struct iface * 616 kif_update(u_short ifindex, int flags, struct if_data *ifd, 617 struct sockaddr_dl *sdl) 618 { 619 struct iface *iface; 620 char ifname[IF_NAMESIZE]; 621 622 if ((iface = if_find(ifindex)) == NULL) { 623 bzero(ifname, sizeof(ifname)); 624 if (sdl && sdl->sdl_family == AF_LINK) { 625 if (sdl->sdl_nlen >= sizeof(ifname)) 626 memcpy(ifname, sdl->sdl_data, 627 sizeof(ifname) - 1); 628 else if (sdl->sdl_nlen > 0) 629 memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen); 630 else 631 return (NULL); 632 } else 633 return (NULL); 634 if ((iface = if_new(ifindex, ifname)) == NULL) 635 return (NULL); 636 iface->cflags |= F_IFACE_AVAIL; 637 } 638 639 if_update(iface, ifd->ifi_mtu, flags, ifd->ifi_type, 640 ifd->ifi_link_state, ifd->ifi_baudrate); 641 642 return (iface); 643 } 644 645 int 646 kif_validate(u_short ifindex) 647 { 648 struct iface *iface; 649 650 if ((iface = if_find(ifindex)) == NULL) { 651 log_warnx("interface with index %u not found", ifindex); 652 return (-1); 653 } 654 655 return ((iface->flags & IFF_UP) && LINK_STATE_IS_UP(iface->linkstate)); 656 } 657 658 struct kroute_node * 659 kroute_match(struct in6_addr *key) 660 { 661 int i; 662 struct kroute_node *kr; 663 struct in6_addr ina; 664 665 /* we will never match the default route */ 666 for (i = 128; i > 0; i--) { 667 inet6applymask(&ina, key, i); 668 if ((kr = kroute_find(&ina, i)) != NULL) 669 return (kr); 670 } 671 672 /* if we don't have a match yet, try to find a default route */ 673 if ((kr = kroute_find(&in6addr_any, 0)) != NULL) 674 return (kr); 675 676 return (NULL); 677 } 678 679 /* misc */ 680 int 681 protect_lo(void) 682 { 683 struct kroute_node *kr; 684 685 /* special protection for loopback */ 686 if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { 687 log_warn("protect_lo"); 688 return (-1); 689 } 690 memcpy(&kr->r.prefix, &in6addr_loopback, sizeof(kr->r.prefix)); 691 kr->r.prefixlen = 128; 692 kr->r.flags = F_KERNEL|F_CONNECTED; 693 694 if (RB_INSERT(kroute_tree, &krt, kr) != NULL) 695 free(kr); /* kernel route already there, no problem */ 696 697 return (0); 698 } 699 700 #define ROUNDUP(a) \ 701 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 702 703 void 704 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 705 { 706 int i; 707 708 for (i = 0; i < RTAX_MAX; i++) { 709 if (addrs & (1 << i)) { 710 rti_info[i] = sa; 711 sa = (struct sockaddr *)((char *)(sa) + 712 ROUNDUP(sa->sa_len)); 713 } else 714 rti_info[i] = NULL; 715 } 716 } 717 718 void 719 if_change(u_short ifindex, int flags, struct if_data *ifd) 720 { 721 struct kroute_node *kr, *tkr; 722 struct iface *iface; 723 u_int8_t wasvalid, isvalid; 724 725 wasvalid = kif_validate(ifindex); 726 727 if ((iface = kif_update(ifindex, flags, ifd, NULL)) == NULL) { 728 log_warn("if_change: kif_update(%u)", ifindex); 729 return; 730 } 731 732 isvalid = (iface->flags & IFF_UP) && 733 LINK_STATE_IS_UP(iface->linkstate); 734 735 if (wasvalid == isvalid) 736 return; /* nothing changed wrt validity */ 737 738 /* inform engine and rde about state change if interface is used */ 739 if (iface->cflags & F_IFACE_CONFIGURED) { 740 main_imsg_compose_ospfe(IMSG_IFINFO, 0, iface, 741 sizeof(struct iface)); 742 main_imsg_compose_rde(IMSG_IFINFO, 0, iface, 743 sizeof(struct iface)); 744 } 745 746 /* update redistribute list */ 747 RB_FOREACH(kr, kroute_tree, &krt) { 748 for (tkr = kr; tkr != NULL; tkr = tkr->next) { 749 if (tkr->r.ifindex == ifindex) { 750 if (isvalid) 751 tkr->r.flags &= ~F_DOWN; 752 else 753 tkr->r.flags |= F_DOWN; 754 755 } 756 } 757 kr_redistribute(kr); 758 } 759 } 760 761 void 762 if_newaddr(u_short ifindex, struct sockaddr_in6 *ifa, struct sockaddr_in6 *mask, 763 struct sockaddr_in6 *brd) 764 { 765 struct iface *iface; 766 struct iface_addr *ia; 767 struct ifaddrchange ifc; 768 769 if (ifa == NULL || ifa->sin6_family != AF_INET6) 770 return; 771 if ((iface = if_find(ifindex)) == NULL) { 772 log_warnx("if_newaddr: corresponding if %d not found", ifindex); 773 return; 774 } 775 776 /* We only care about link-local and global-scope. */ 777 if (IN6_IS_ADDR_UNSPECIFIED(&ifa->sin6_addr) || 778 IN6_IS_ADDR_LOOPBACK(&ifa->sin6_addr) || 779 IN6_IS_ADDR_MULTICAST(&ifa->sin6_addr) || 780 IN6_IS_ADDR_SITELOCAL(&ifa->sin6_addr) || 781 IN6_IS_ADDR_V4MAPPED(&ifa->sin6_addr) || 782 IN6_IS_ADDR_V4COMPAT(&ifa->sin6_addr)) 783 return; 784 785 clearscope(&ifa->sin6_addr); 786 787 if (IN6_IS_ADDR_LINKLOCAL(&ifa->sin6_addr) || 788 iface->flags & IFF_LOOPBACK) 789 iface->addr = ifa->sin6_addr; 790 791 if ((ia = calloc(1, sizeof(struct iface_addr))) == NULL) 792 fatal("if_newaddr"); 793 794 ia->addr = ifa->sin6_addr; 795 796 if (mask) 797 ia->prefixlen = mask2prefixlen(mask); 798 else 799 ia->prefixlen = 0; 800 if (brd && brd->sin6_family == AF_INET6) 801 ia->dstbrd = brd->sin6_addr; 802 else 803 bzero(&ia->dstbrd, sizeof(ia->dstbrd)); 804 805 switch (iface->type) { 806 case IF_TYPE_BROADCAST: 807 case IF_TYPE_NBMA: 808 log_debug("if_newaddr: ifindex %u, addr %s/%d", 809 ifindex, log_in6addr(&ia->addr), ia->prefixlen); 810 break; 811 case IF_TYPE_VIRTUALLINK: /* FIXME */ 812 break; 813 case IF_TYPE_POINTOPOINT: 814 case IF_TYPE_POINTOMULTIPOINT: 815 log_debug("if_newaddr: ifindex %u, addr %s/%d, " 816 "dest %s", ifindex, log_in6addr(&ia->addr), 817 ia->prefixlen, log_in6addr(&ia->dstbrd)); 818 break; 819 default: 820 fatalx("if_newaddr: unknown interface type"); 821 } 822 823 TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry); 824 /* inform engine and rde if interface is used */ 825 if (iface->cflags & F_IFACE_CONFIGURED) { 826 ifc.addr = ia->addr; 827 ifc.dstbrd = ia->dstbrd; 828 ifc.prefixlen = ia->prefixlen; 829 ifc.ifindex = ifindex; 830 main_imsg_compose_ospfe(IMSG_IFADDRNEW, 0, &ifc, sizeof(ifc)); 831 main_imsg_compose_rde(IMSG_IFADDRNEW, 0, &ifc, sizeof(ifc)); 832 } 833 } 834 835 void 836 if_deladdr(u_short ifindex, struct sockaddr_in6 *ifa, struct sockaddr_in6 *mask, 837 struct sockaddr_in6 *brd) 838 { 839 struct iface *iface; 840 struct iface_addr *ia, *nia; 841 struct ifaddrchange ifc; 842 843 if (ifa == NULL || ifa->sin6_family != AF_INET6) 844 return; 845 if ((iface = if_find(ifindex)) == NULL) { 846 log_warnx("if_deladdr: corresponding if %d not found", ifindex); 847 return; 848 } 849 850 /* We only care about link-local and global-scope. */ 851 if (IN6_IS_ADDR_UNSPECIFIED(&ifa->sin6_addr) || 852 IN6_IS_ADDR_LOOPBACK(&ifa->sin6_addr) || 853 IN6_IS_ADDR_MULTICAST(&ifa->sin6_addr) || 854 IN6_IS_ADDR_SITELOCAL(&ifa->sin6_addr) || 855 IN6_IS_ADDR_V4MAPPED(&ifa->sin6_addr) || 856 IN6_IS_ADDR_V4COMPAT(&ifa->sin6_addr)) 857 return; 858 859 clearscope(&ifa->sin6_addr); 860 861 for (ia = TAILQ_FIRST(&iface->ifa_list); ia != NULL; ia = nia) { 862 nia = TAILQ_NEXT(ia, entry); 863 864 if (IN6_ARE_ADDR_EQUAL(&ia->addr, &ifa->sin6_addr)) { 865 log_debug("if_deladdr: ifindex %u, addr %s/%d", 866 ifindex, log_in6addr(&ia->addr), ia->prefixlen); 867 TAILQ_REMOVE(&iface->ifa_list, ia, entry); 868 /* inform engine and rde if interface is used */ 869 if (iface->cflags & F_IFACE_CONFIGURED) { 870 ifc.addr = ia->addr; 871 ifc.dstbrd = ia->dstbrd; 872 ifc.prefixlen = ia->prefixlen; 873 ifc.ifindex = ifindex; 874 main_imsg_compose_ospfe(IMSG_IFADDRDEL, 0, &ifc, 875 sizeof(ifc)); 876 main_imsg_compose_rde(IMSG_IFADDRDEL, 0, &ifc, 877 sizeof(ifc)); 878 } 879 free(ia); 880 return; 881 } 882 } 883 } 884 885 void 886 if_announce(void *msg) 887 { 888 struct if_announcemsghdr *ifan; 889 struct iface *iface; 890 891 ifan = msg; 892 893 switch (ifan->ifan_what) { 894 case IFAN_ARRIVAL: 895 if ((iface = if_new(ifan->ifan_index, ifan->ifan_name)) == NULL) 896 fatal("if_announce failed"); 897 iface->cflags |= F_IFACE_AVAIL; 898 break; 899 case IFAN_DEPARTURE: 900 iface = if_find(ifan->ifan_index); 901 if (iface->cflags & F_IFACE_CONFIGURED) { 902 main_imsg_compose_rde(IMSG_IFDELETE, 0, 903 &iface->ifindex, sizeof(iface->ifindex)); 904 main_imsg_compose_ospfe(IMSG_IFDELETE, 0, 905 &iface->ifindex, sizeof(iface->ifindex)); 906 } 907 if_del(iface); 908 break; 909 } 910 } 911 912 /* rtsock */ 913 int 914 send_rtmsg(int fd, int action, struct kroute *kroute) 915 { 916 struct iovec iov[5]; 917 struct rt_msghdr hdr; 918 struct pad { 919 struct sockaddr_in6 addr; 920 char pad[sizeof(long)]; /* thank you IPv6 */ 921 } prefix, nexthop, mask; 922 struct { 923 struct sockaddr_dl addr; 924 char pad[sizeof(long)]; 925 } ifp; 926 struct sockaddr_rtlabel sa_rl; 927 int iovcnt = 0; 928 const char *label; 929 930 if (kr_state.fib_sync == 0) 931 return (0); 932 933 /* initialize header */ 934 bzero(&hdr, sizeof(hdr)); 935 hdr.rtm_version = RTM_VERSION; 936 hdr.rtm_type = action; 937 hdr.rtm_flags = RTF_UP; 938 hdr.rtm_priority = RTP_OSPF; 939 if (action == RTM_CHANGE) 940 hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE; 941 hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ 942 hdr.rtm_hdrlen = sizeof(hdr); 943 hdr.rtm_msglen = sizeof(hdr); 944 /* adjust iovec */ 945 iov[iovcnt].iov_base = &hdr; 946 iov[iovcnt++].iov_len = sizeof(hdr); 947 948 bzero(&prefix, sizeof(prefix)); 949 prefix.addr.sin6_len = sizeof(struct sockaddr_in6); 950 prefix.addr.sin6_family = AF_INET6; 951 prefix.addr.sin6_addr = kroute->prefix; 952 /* adjust header */ 953 hdr.rtm_addrs |= RTA_DST; 954 hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); 955 /* adjust iovec */ 956 iov[iovcnt].iov_base = &prefix; 957 iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); 958 959 if (!IN6_IS_ADDR_UNSPECIFIED(&kroute->nexthop)) { 960 bzero(&nexthop, sizeof(nexthop)); 961 nexthop.addr.sin6_len = sizeof(struct sockaddr_in6); 962 nexthop.addr.sin6_family = AF_INET6; 963 nexthop.addr.sin6_addr = kroute->nexthop; 964 nexthop.addr.sin6_scope_id = kroute->scope; 965 /* 966 * XXX we should set the sin6_scope_id but the kernel 967 * XXX does not expect it that way. It must be fiddled 968 * XXX into the sin6_addr. Welcome to the typical 969 * XXX IPv6 insanity and all without wine bottles. 970 */ 971 embedscope(&nexthop.addr); 972 973 /* adjust header */ 974 hdr.rtm_flags |= RTF_GATEWAY; 975 hdr.rtm_addrs |= RTA_GATEWAY; 976 hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); 977 /* adjust iovec */ 978 iov[iovcnt].iov_base = &nexthop; 979 iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); 980 } else if (kroute->ifindex) { 981 /* 982 * We don't have an interface address in that network, 983 * so we install a cloning route. The kernel will then 984 * do neigbor discovery. 985 */ 986 bzero(&ifp, sizeof(ifp)); 987 ifp.addr.sdl_len = sizeof(struct sockaddr_dl); 988 ifp.addr.sdl_family = AF_LINK; 989 990 ifp.addr.sdl_index = kroute->ifindex; 991 /* adjust header */ 992 hdr.rtm_flags |= RTF_CLONING; 993 hdr.rtm_addrs |= RTA_GATEWAY; 994 hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_dl)); 995 /* adjust iovec */ 996 iov[iovcnt].iov_base = &ifp; 997 iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_dl)); 998 } 999 1000 bzero(&mask, sizeof(mask)); 1001 mask.addr.sin6_len = sizeof(struct sockaddr_in6); 1002 mask.addr.sin6_family = AF_INET6; 1003 mask.addr.sin6_addr = *prefixlen2mask(kroute->prefixlen); 1004 /* adjust header */ 1005 if (kroute->prefixlen == 128) 1006 hdr.rtm_flags |= RTF_HOST; 1007 hdr.rtm_addrs |= RTA_NETMASK; 1008 hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); 1009 /* adjust iovec */ 1010 iov[iovcnt].iov_base = &mask; 1011 iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); 1012 1013 if (kroute->rtlabel != 0) { 1014 sa_rl.sr_len = sizeof(sa_rl); 1015 sa_rl.sr_family = AF_UNSPEC; 1016 label = rtlabel_id2name(kroute->rtlabel); 1017 if (strlcpy(sa_rl.sr_label, label, 1018 sizeof(sa_rl.sr_label)) >= sizeof(sa_rl.sr_label)) { 1019 log_warnx("send_rtmsg: invalid rtlabel"); 1020 return (-1); 1021 } 1022 /* adjust header */ 1023 hdr.rtm_addrs |= RTA_LABEL; 1024 hdr.rtm_msglen += sizeof(sa_rl); 1025 /* adjust iovec */ 1026 iov[iovcnt].iov_base = &sa_rl; 1027 iov[iovcnt++].iov_len = sizeof(sa_rl); 1028 } 1029 1030 retry: 1031 if (writev(fd, iov, iovcnt) == -1) { 1032 if (errno == ESRCH) { 1033 if (hdr.rtm_type == RTM_CHANGE) { 1034 hdr.rtm_type = RTM_ADD; 1035 goto retry; 1036 } else if (hdr.rtm_type == RTM_DELETE) { 1037 log_info("route %s/%u vanished before delete", 1038 log_sockaddr(&prefix), kroute->prefixlen); 1039 return (0); 1040 } 1041 } 1042 log_warn("send_rtmsg: action %u, prefix %s/%u", hdr.rtm_type, 1043 log_sockaddr(&prefix), kroute->prefixlen); 1044 return (0); 1045 } 1046 1047 return (0); 1048 } 1049 1050 int 1051 fetchtable(void) 1052 { 1053 size_t len; 1054 int mib[7]; 1055 char *buf, *next, *lim; 1056 struct rt_msghdr *rtm; 1057 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1058 struct sockaddr_in6 *sa_in6; 1059 struct sockaddr_rtlabel *label; 1060 struct kroute_node *kr; 1061 1062 mib[0] = CTL_NET; 1063 mib[1] = PF_ROUTE; 1064 mib[2] = 0; 1065 mib[3] = AF_INET6; 1066 mib[4] = NET_RT_DUMP; 1067 mib[5] = 0; 1068 mib[6] = 0; /* rtableid */ 1069 1070 if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { 1071 log_warn("sysctl"); 1072 return (-1); 1073 } 1074 if ((buf = malloc(len)) == NULL) { 1075 log_warn("fetchtable"); 1076 return (-1); 1077 } 1078 if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { 1079 log_warn("sysctl"); 1080 free(buf); 1081 return (-1); 1082 } 1083 1084 lim = buf + len; 1085 for (next = buf; next < lim; next += rtm->rtm_msglen) { 1086 rtm = (struct rt_msghdr *)next; 1087 if (rtm->rtm_version != RTM_VERSION) 1088 continue; 1089 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); 1090 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 1091 1092 if ((sa = rti_info[RTAX_DST]) == NULL) 1093 continue; 1094 1095 /* Skip ARP/ND cache and broadcast routes. */ 1096 if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST)) 1097 continue; 1098 1099 if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { 1100 log_warn("fetchtable"); 1101 free(buf); 1102 return (-1); 1103 } 1104 1105 kr->r.flags = F_KERNEL; 1106 1107 switch (sa->sa_family) { 1108 case AF_INET6: 1109 kr->r.prefix = 1110 ((struct sockaddr_in6 *)sa)->sin6_addr; 1111 sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK]; 1112 if (rtm->rtm_flags & RTF_STATIC) 1113 kr->r.flags |= F_STATIC; 1114 if (rtm->rtm_flags & RTF_BLACKHOLE) 1115 kr->r.flags |= F_BLACKHOLE; 1116 if (rtm->rtm_flags & RTF_REJECT) 1117 kr->r.flags |= F_REJECT; 1118 if (rtm->rtm_flags & RTF_DYNAMIC) 1119 kr->r.flags |= F_DYNAMIC; 1120 if (rtm->rtm_flags & RTF_PROTO1) 1121 kr->r.flags |= F_BGPD_INSERTED; 1122 if (sa_in6 != NULL) { 1123 if (sa_in6->sin6_len == 0) 1124 break; 1125 kr->r.prefixlen = 1126 mask2prefixlen(sa_in6); 1127 } else if (rtm->rtm_flags & RTF_HOST) 1128 kr->r.prefixlen = 128; 1129 else 1130 fatalx("classful IPv6 route?!!"); 1131 break; 1132 default: 1133 free(kr); 1134 continue; 1135 } 1136 1137 kr->r.ifindex = rtm->rtm_index; 1138 if ((sa = rti_info[RTAX_GATEWAY]) != NULL) 1139 switch (sa->sa_family) { 1140 case AF_INET6: 1141 if (rtm->rtm_flags & RTF_CONNECTED) { 1142 kr->r.flags |= F_CONNECTED; 1143 break; 1144 } 1145 1146 sa_in6 = (struct sockaddr_in6 *)sa; 1147 /* 1148 * XXX The kernel provides the scope via the 1149 * XXX kame hack instead of the scope_id field. 1150 */ 1151 recoverscope(sa_in6); 1152 kr->r.nexthop = sa_in6->sin6_addr; 1153 kr->r.scope = sa_in6->sin6_scope_id; 1154 break; 1155 case AF_LINK: 1156 /* 1157 * Traditional BSD connected routes have 1158 * a gateway of type AF_LINK. 1159 */ 1160 kr->r.flags |= F_CONNECTED; 1161 break; 1162 } 1163 1164 if (rtm->rtm_flags & RTF_PROTO2) { 1165 send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); 1166 free(kr); 1167 } else { 1168 if ((label = (struct sockaddr_rtlabel *) 1169 rti_info[RTAX_LABEL]) != NULL) { 1170 kr->r.rtlabel = 1171 rtlabel_name2id(label->sr_label); 1172 kr->r.ext_tag = 1173 rtlabel_id2tag(kr->r.rtlabel); 1174 } 1175 kroute_insert(kr); 1176 } 1177 1178 } 1179 free(buf); 1180 return (0); 1181 } 1182 1183 int 1184 fetchifs(u_short ifindex) 1185 { 1186 size_t len; 1187 int mib[6]; 1188 char *buf, *next, *lim; 1189 struct rt_msghdr *rtm; 1190 struct if_msghdr ifm; 1191 struct ifa_msghdr *ifam; 1192 struct iface *iface; 1193 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1194 1195 mib[0] = CTL_NET; 1196 mib[1] = PF_ROUTE; 1197 mib[2] = 0; 1198 mib[3] = AF_INET6; 1199 mib[4] = NET_RT_IFLIST; 1200 mib[5] = ifindex; 1201 1202 if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { 1203 log_warn("sysctl"); 1204 return (-1); 1205 } 1206 if ((buf = malloc(len)) == NULL) { 1207 log_warn("fetchifs"); 1208 return (-1); 1209 } 1210 if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) { 1211 log_warn("sysctl"); 1212 free(buf); 1213 return (-1); 1214 } 1215 1216 lim = buf + len; 1217 for (next = buf; next < lim; next += rtm->rtm_msglen) { 1218 rtm = (struct rt_msghdr *)next; 1219 if (rtm->rtm_version != RTM_VERSION) 1220 continue; 1221 switch (rtm->rtm_type) { 1222 case RTM_IFINFO: 1223 bcopy(rtm, &ifm, sizeof ifm); 1224 sa = (struct sockaddr *)(next + sizeof(ifm)); 1225 get_rtaddrs(ifm.ifm_addrs, sa, rti_info); 1226 1227 if ((iface = kif_update(ifm.ifm_index, 1228 ifm.ifm_flags, &ifm.ifm_data, 1229 (struct sockaddr_dl *)rti_info[RTAX_IFP])) == NULL) 1230 break; 1231 case RTM_NEWADDR: 1232 ifam = (struct ifa_msghdr *)rtm; 1233 if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | 1234 RTA_BRD)) == 0) 1235 break; 1236 sa = (struct sockaddr *)(ifam + 1); 1237 get_rtaddrs(ifam->ifam_addrs, sa, rti_info); 1238 1239 if_newaddr(ifam->ifam_index, 1240 (struct sockaddr_in6 *)rti_info[RTAX_IFA], 1241 (struct sockaddr_in6 *)rti_info[RTAX_NETMASK], 1242 (struct sockaddr_in6 *)rti_info[RTAX_BRD]); 1243 break; 1244 } 1245 } 1246 free(buf); 1247 return (0); 1248 } 1249 1250 int 1251 dispatch_rtmsg(void) 1252 { 1253 char buf[RT_BUF_SIZE]; 1254 ssize_t n; 1255 char *next, *lim; 1256 struct rt_msghdr *rtm; 1257 struct if_msghdr ifm; 1258 struct ifa_msghdr *ifam; 1259 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1260 struct sockaddr_in6 *sa_in6; 1261 struct sockaddr_rtlabel *label; 1262 struct kroute_node *kr, *okr; 1263 struct in6_addr prefix, nexthop; 1264 u_int8_t prefixlen; 1265 int flags, mpath; 1266 unsigned int scope; 1267 u_short ifindex = 0; 1268 1269 if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) { 1270 if (errno == EAGAIN || errno == EINTR) 1271 return (0); 1272 log_warn("dispatch_rtmsg: read error"); 1273 return (-1); 1274 } 1275 1276 if (n == 0) { 1277 log_warnx("routing socket closed"); 1278 return (-1); 1279 } 1280 1281 lim = buf + n; 1282 for (next = buf; next < lim; next += rtm->rtm_msglen) { 1283 rtm = (struct rt_msghdr *)next; 1284 if (lim < next + sizeof(u_short) || 1285 lim < next + rtm->rtm_msglen) 1286 fatalx("dispatch_rtmsg: partial rtm in buffer"); 1287 if (rtm->rtm_version != RTM_VERSION) 1288 continue; 1289 1290 bzero(&prefix, sizeof(prefix)); 1291 bzero(&nexthop, sizeof(nexthop)); 1292 scope = 0; 1293 prefixlen = 0; 1294 flags = F_KERNEL; 1295 mpath = 0; 1296 1297 if (rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE || 1298 rtm->rtm_type == RTM_DELETE) { 1299 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); 1300 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 1301 1302 if (rtm->rtm_tableid != 0) 1303 continue; 1304 1305 if (rtm->rtm_pid == kr_state.pid) /* caused by us */ 1306 continue; 1307 1308 if (rtm->rtm_errno) /* failed attempts... */ 1309 continue; 1310 1311 /* Skip ARP/ND cache and broadcast routes. */ 1312 if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST)) 1313 continue; 1314 1315 #ifdef RTF_MPATH 1316 if (rtm->rtm_flags & RTF_MPATH) 1317 mpath = 1; 1318 #endif 1319 switch (sa->sa_family) { 1320 case AF_INET6: 1321 prefix = 1322 ((struct sockaddr_in6 *)sa)->sin6_addr; 1323 sa_in6 = (struct sockaddr_in6 *) 1324 rti_info[RTAX_NETMASK]; 1325 if (sa_in6 != NULL) { 1326 if (sa_in6->sin6_len != 0) 1327 prefixlen = mask2prefixlen( 1328 sa_in6); 1329 } else if (rtm->rtm_flags & RTF_HOST) 1330 prefixlen = 128; 1331 else 1332 fatalx("classful IPv6 address?!!"); 1333 if (rtm->rtm_flags & RTF_STATIC) 1334 flags |= F_STATIC; 1335 if (rtm->rtm_flags & RTF_BLACKHOLE) 1336 flags |= F_BLACKHOLE; 1337 if (rtm->rtm_flags & RTF_REJECT) 1338 flags |= F_REJECT; 1339 if (rtm->rtm_flags & RTF_DYNAMIC) 1340 flags |= F_DYNAMIC; 1341 if (rtm->rtm_flags & RTF_PROTO1) 1342 flags |= F_BGPD_INSERTED; 1343 break; 1344 default: 1345 continue; 1346 } 1347 1348 ifindex = rtm->rtm_index; 1349 if ((sa = rti_info[RTAX_GATEWAY]) != NULL) { 1350 switch (sa->sa_family) { 1351 case AF_INET6: 1352 sa_in6 = (struct sockaddr_in6 *)sa; 1353 /* 1354 * XXX The kernel provides the scope 1355 * XXX via the kame hack instead of 1356 * XXX the scope_id field. 1357 */ 1358 recoverscope(sa_in6); 1359 nexthop = sa_in6->sin6_addr; 1360 scope = sa_in6->sin6_scope_id; 1361 break; 1362 case AF_LINK: 1363 flags |= F_CONNECTED; 1364 break; 1365 } 1366 } 1367 } 1368 1369 switch (rtm->rtm_type) { 1370 case RTM_ADD: 1371 case RTM_CHANGE: 1372 if (IN6_IS_ADDR_UNSPECIFIED(&nexthop) && 1373 !(flags & F_CONNECTED)) { 1374 log_warnx("dispatch_rtmsg no nexthop for %s/%u", 1375 log_in6addr(&prefix), prefixlen); 1376 continue; 1377 } 1378 1379 if ((okr = kroute_find(&prefix, prefixlen)) != 1380 NULL) { 1381 /* just add new multipath routes */ 1382 if (mpath && rtm->rtm_type == RTM_ADD) 1383 goto add; 1384 /* get the correct route */ 1385 kr = okr; 1386 if (mpath && (kr = kroute_matchgw(okr, 1387 &nexthop, scope)) == NULL) { 1388 log_warnx("dispatch_rtmsg mpath route" 1389 " not found"); 1390 /* add routes we missed out earlier */ 1391 goto add; 1392 } 1393 1394 /* 1395 * ospf route overridden by kernel. Preference 1396 * of the route is not checked because this is 1397 * forced -- most probably by a user. 1398 */ 1399 if (kr->r.flags & F_OSPFD_INSERTED) 1400 flags |= F_OSPFD_INSERTED; 1401 if (kr->r.flags & F_REDISTRIBUTED) 1402 flags |= F_REDISTRIBUTED; 1403 kr->r.nexthop = nexthop; 1404 kr->r.scope = scope; 1405 kr->r.flags = flags; 1406 kr->r.ifindex = ifindex; 1407 1408 rtlabel_unref(kr->r.rtlabel); 1409 kr->r.rtlabel = 0; 1410 kr->r.ext_tag = 0; 1411 if ((label = (struct sockaddr_rtlabel *) 1412 rti_info[RTAX_LABEL]) != NULL) { 1413 kr->r.rtlabel = 1414 rtlabel_name2id(label->sr_label); 1415 kr->r.ext_tag = 1416 rtlabel_id2tag(kr->r.rtlabel); 1417 } 1418 1419 if (kif_validate(kr->r.ifindex)) 1420 kr->r.flags &= ~F_DOWN; 1421 else 1422 kr->r.flags |= F_DOWN; 1423 1424 /* just readd, the RDE will care */ 1425 kr_redistribute(okr); 1426 } else { 1427 add: 1428 if ((kr = calloc(1, 1429 sizeof(struct kroute_node))) == NULL) { 1430 log_warn("dispatch_rtmsg"); 1431 return (-1); 1432 } 1433 kr->r.prefix = prefix; 1434 kr->r.prefixlen = prefixlen; 1435 kr->r.nexthop = nexthop; 1436 kr->r.scope = scope; 1437 kr->r.flags = flags; 1438 kr->r.ifindex = ifindex; 1439 1440 if ((label = (struct sockaddr_rtlabel *) 1441 rti_info[RTAX_LABEL]) != NULL) { 1442 kr->r.rtlabel = 1443 rtlabel_name2id(label->sr_label); 1444 kr->r.ext_tag = 1445 rtlabel_id2tag(kr->r.rtlabel); 1446 } 1447 1448 kroute_insert(kr); 1449 } 1450 break; 1451 case RTM_DELETE: 1452 if ((kr = kroute_find(&prefix, prefixlen)) == 1453 NULL) 1454 continue; 1455 if (!(kr->r.flags & F_KERNEL)) 1456 continue; 1457 /* get the correct route */ 1458 okr = kr; 1459 if (mpath && (kr = kroute_matchgw(kr, &nexthop, 1460 scope)) == NULL) { 1461 log_warnx("dispatch_rtmsg mpath route" 1462 " not found"); 1463 return (-1); 1464 } 1465 /* 1466 * last route is getting removed request the 1467 * ospf route from the RDE to insert instead 1468 */ 1469 if (okr == kr && kr->next == NULL && 1470 kr->r.flags & F_OSPFD_INSERTED) 1471 main_imsg_compose_rde(IMSG_KROUTE_GET, 0, 1472 &kr->r, sizeof(struct kroute)); 1473 if (kroute_remove(kr) == -1) 1474 return (-1); 1475 break; 1476 case RTM_IFINFO: 1477 memcpy(&ifm, next, sizeof(ifm)); 1478 if_change(ifm.ifm_index, ifm.ifm_flags, 1479 &ifm.ifm_data); 1480 break; 1481 case RTM_NEWADDR: 1482 ifam = (struct ifa_msghdr *)rtm; 1483 if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | 1484 RTA_BRD)) == 0) 1485 break; 1486 sa = (struct sockaddr *)(ifam + 1); 1487 get_rtaddrs(ifam->ifam_addrs, sa, rti_info); 1488 1489 if_newaddr(ifam->ifam_index, 1490 (struct sockaddr_in6 *)rti_info[RTAX_IFA], 1491 (struct sockaddr_in6 *)rti_info[RTAX_NETMASK], 1492 (struct sockaddr_in6 *)rti_info[RTAX_BRD]); 1493 break; 1494 case RTM_DELADDR: 1495 ifam = (struct ifa_msghdr *)rtm; 1496 if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | 1497 RTA_BRD)) == 0) 1498 break; 1499 sa = (struct sockaddr *)(ifam + 1); 1500 get_rtaddrs(ifam->ifam_addrs, sa, rti_info); 1501 1502 if_deladdr(ifam->ifam_index, 1503 (struct sockaddr_in6 *)rti_info[RTAX_IFA], 1504 (struct sockaddr_in6 *)rti_info[RTAX_NETMASK], 1505 (struct sockaddr_in6 *)rti_info[RTAX_BRD]); 1506 break; 1507 case RTM_IFANNOUNCE: 1508 if_announce(next); 1509 break; 1510 default: 1511 /* ignore for now */ 1512 break; 1513 } 1514 } 1515 return (0); 1516 } 1517