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