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