1 /* $OpenBSD: kroute.c,v 1.312 2025/01/27 15:22:11 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 5 * Copyright (c) 2022 Claudio Jeker <claudio@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/queue.h> 22 #include <sys/tree.h> 23 #include <sys/ioctl.h> 24 #include <sys/socket.h> 25 #include <sys/sysctl.h> 26 #include <sys/uio.h> 27 #include <arpa/inet.h> 28 #include <netinet/in.h> 29 #include <net/if.h> 30 #include <net/if_dl.h> 31 #include <net/if_media.h> 32 #include <net/if_types.h> 33 #include <net/route.h> 34 #include <netmpls/mpls.h> 35 36 #include <errno.h> 37 #include <ifaddrs.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <imsg.h> 43 44 #include "bgpd.h" 45 #include "log.h" 46 47 #define RTP_MINE 0xff 48 49 struct ktable **krt; 50 u_int krt_size; 51 52 struct { 53 uint32_t rtseq; 54 pid_t pid; 55 int fd; 56 uint8_t fib_prio; 57 } kr_state; 58 59 struct kroute { 60 RB_ENTRY(kroute) entry; 61 struct kroute *next; 62 struct in_addr prefix; 63 struct in_addr nexthop; 64 uint32_t mplslabel; 65 uint16_t flags; 66 uint16_t labelid; 67 u_short ifindex; 68 uint8_t prefixlen; 69 uint8_t priority; 70 }; 71 72 struct kroute6 { 73 RB_ENTRY(kroute6) entry; 74 struct kroute6 *next; 75 struct in6_addr prefix; 76 struct in6_addr nexthop; 77 uint32_t prefix_scope_id; /* because ... */ 78 uint32_t nexthop_scope_id; 79 uint32_t mplslabel; 80 uint16_t flags; 81 uint16_t labelid; 82 u_short ifindex; 83 uint8_t prefixlen; 84 uint8_t priority; 85 }; 86 87 struct knexthop { 88 RB_ENTRY(knexthop) entry; 89 struct bgpd_addr nexthop; 90 void *kroute; 91 u_short ifindex; 92 }; 93 94 struct kredist_node { 95 RB_ENTRY(kredist_node) entry; 96 struct bgpd_addr prefix; 97 uint64_t rd; 98 uint8_t prefixlen; 99 uint8_t dynamic; 100 }; 101 102 struct kif { 103 RB_ENTRY(kif) entry; 104 char ifname[IFNAMSIZ]; 105 uint64_t baudrate; 106 u_int rdomain; 107 int flags; 108 u_short ifindex; 109 uint8_t if_type; 110 uint8_t link_state; 111 uint8_t nh_reachable; /* for nexthop verification */ 112 uint8_t depend_state; /* for session depend on */ 113 }; 114 115 int ktable_new(u_int, u_int, char *, int); 116 void ktable_free(u_int); 117 void ktable_destroy(struct ktable *); 118 struct ktable *ktable_get(u_int); 119 120 int kr4_change(struct ktable *, struct kroute_full *); 121 int kr6_change(struct ktable *, struct kroute_full *); 122 int krVPN4_change(struct ktable *, struct kroute_full *); 123 int krVPN6_change(struct ktable *, struct kroute_full *); 124 int kr_net_match(struct ktable *, struct network_config *, uint16_t, int); 125 struct network *kr_net_find(struct ktable *, struct network *); 126 void kr_net_clear(struct ktable *); 127 void kr_redistribute(int, struct ktable *, struct kroute_full *); 128 uint8_t kr_priority(struct kroute_full *); 129 struct kroute_full *kr_tofull(struct kroute *); 130 struct kroute_full *kr6_tofull(struct kroute6 *); 131 int kroute_compare(struct kroute *, struct kroute *); 132 int kroute6_compare(struct kroute6 *, struct kroute6 *); 133 int knexthop_compare(struct knexthop *, struct knexthop *); 134 int kredist_compare(struct kredist_node *, struct kredist_node *); 135 int kif_compare(struct kif *, struct kif *); 136 137 struct kroute *kroute_find(struct ktable *, const struct bgpd_addr *, 138 uint8_t, uint8_t); 139 struct kroute *kroute_matchgw(struct kroute *, struct kroute_full *); 140 int kroute_insert(struct ktable *, struct kroute_full *); 141 int kroute_remove(struct ktable *, struct kroute_full *, int); 142 void kroute_clear(struct ktable *); 143 144 struct kroute6 *kroute6_find(struct ktable *, const struct bgpd_addr *, 145 uint8_t, uint8_t); 146 struct kroute6 *kroute6_matchgw(struct kroute6 *, struct kroute_full *); 147 void kroute6_clear(struct ktable *); 148 149 struct knexthop *knexthop_find(struct ktable *, struct bgpd_addr *); 150 int knexthop_insert(struct ktable *, struct knexthop *); 151 void knexthop_remove(struct ktable *, struct knexthop *); 152 void knexthop_clear(struct ktable *); 153 154 struct kif *kif_find(int); 155 int kif_insert(struct kif *); 156 int kif_remove(struct kif *); 157 void kif_clear(void); 158 159 int kroute_validate(struct kroute *); 160 int kroute6_validate(struct kroute6 *); 161 int knexthop_true_nexthop(struct ktable *, struct kroute_full *); 162 void knexthop_validate(struct ktable *, struct knexthop *); 163 void knexthop_track(struct ktable *, u_short); 164 void knexthop_update(struct ktable *, struct kroute_full *); 165 void knexthop_send_update(struct knexthop *); 166 struct kroute *kroute_match(struct ktable *, struct bgpd_addr *, int); 167 struct kroute6 *kroute6_match(struct ktable *, struct bgpd_addr *, int); 168 void kroute_detach_nexthop(struct ktable *, struct knexthop *); 169 170 uint8_t prefixlen_classful(in_addr_t); 171 uint64_t ift2ifm(uint8_t); 172 const char *get_media_descr(uint64_t); 173 const char *get_linkstate(uint8_t, int); 174 void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 175 void if_change(u_short, int, struct if_data *); 176 void if_announce(void *); 177 178 int send_rtmsg(int, struct ktable *, struct kroute_full *); 179 int dispatch_rtmsg(void); 180 int fetchtable(struct ktable *); 181 int fetchifs(int); 182 int dispatch_rtmsg_addr(struct rt_msghdr *, struct kroute_full *); 183 int kr_fib_delete(struct ktable *, struct kroute_full *, int); 184 int kr_fib_change(struct ktable *, struct kroute_full *, int, int); 185 186 RB_PROTOTYPE(kroute_tree, kroute, entry, kroute_compare) 187 RB_GENERATE(kroute_tree, kroute, entry, kroute_compare) 188 189 RB_PROTOTYPE(kroute6_tree, kroute6, entry, kroute6_compare) 190 RB_GENERATE(kroute6_tree, kroute6, entry, kroute6_compare) 191 192 RB_PROTOTYPE(knexthop_tree, knexthop, entry, knexthop_compare) 193 RB_GENERATE(knexthop_tree, knexthop, entry, knexthop_compare) 194 195 RB_PROTOTYPE(kredist_tree, kredist_node, entry, kredist_compare) 196 RB_GENERATE(kredist_tree, kredist_node, entry, kredist_compare) 197 198 RB_HEAD(kif_tree, kif) kit; 199 RB_PROTOTYPE(kif_tree, kif, entry, kif_compare) 200 RB_GENERATE(kif_tree, kif, entry, kif_compare) 201 202 #define KT2KNT(x) (&(ktable_get((x)->nhtableid)->knt)) 203 204 /* 205 * exported functions 206 */ 207 208 int 209 kr_init(int *fd, uint8_t fib_prio) 210 { 211 int opt = 0, rcvbuf, default_rcvbuf; 212 unsigned int tid = RTABLE_ANY; 213 socklen_t optlen; 214 215 if ((kr_state.fd = socket(AF_ROUTE, 216 SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { 217 log_warn("%s: socket", __func__); 218 return (-1); 219 } 220 221 /* not interested in my own messages */ 222 if (setsockopt(kr_state.fd, SOL_SOCKET, SO_USELOOPBACK, 223 &opt, sizeof(opt)) == -1) 224 log_warn("%s: setsockopt", __func__); /* not fatal */ 225 226 /* grow receive buffer, don't wanna miss messages */ 227 optlen = sizeof(default_rcvbuf); 228 if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, 229 &default_rcvbuf, &optlen) == -1) 230 log_warn("%s: getsockopt SOL_SOCKET SO_RCVBUF", __func__); 231 else 232 for (rcvbuf = MAX_RTSOCK_BUF; 233 rcvbuf > default_rcvbuf && 234 setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, 235 &rcvbuf, sizeof(rcvbuf)) == -1 && errno == ENOBUFS; 236 rcvbuf /= 2) 237 ; /* nothing */ 238 239 if (setsockopt(kr_state.fd, AF_ROUTE, ROUTE_TABLEFILTER, &tid, 240 sizeof(tid)) == -1) { 241 log_warn("%s: setsockopt AF_ROUTE ROUTE_TABLEFILTER", __func__); 242 return (-1); 243 } 244 245 kr_state.pid = getpid(); 246 kr_state.rtseq = 1; 247 kr_state.fib_prio = fib_prio; 248 249 RB_INIT(&kit); 250 251 if (fetchifs(0) == -1) 252 return (-1); 253 254 *fd = kr_state.fd; 255 return (0); 256 } 257 258 int 259 kr_default_prio(void) 260 { 261 return RTP_BGP; 262 } 263 264 int 265 kr_check_prio(long long prio) 266 { 267 if (prio <= RTP_LOCAL || prio > RTP_MAX) 268 return 0; 269 return 1; 270 } 271 272 int 273 ktable_new(u_int rtableid, u_int rdomid, char *name, int fs) 274 { 275 struct ktable **xkrt; 276 struct ktable *kt; 277 size_t oldsize; 278 279 /* resize index table if needed */ 280 if (rtableid >= krt_size) { 281 oldsize = sizeof(struct ktable *) * krt_size; 282 if ((xkrt = reallocarray(krt, rtableid + 1, 283 sizeof(struct ktable *))) == NULL) { 284 log_warn("%s", __func__); 285 return (-1); 286 } 287 krt = xkrt; 288 krt_size = rtableid + 1; 289 memset((char *)krt + oldsize, 0, 290 krt_size * sizeof(struct ktable *) - oldsize); 291 } 292 293 if (krt[rtableid]) 294 fatalx("ktable_new: table already exists."); 295 296 /* allocate new element */ 297 kt = krt[rtableid] = calloc(1, sizeof(struct ktable)); 298 if (kt == NULL) { 299 log_warn("%s", __func__); 300 return (-1); 301 } 302 303 /* initialize structure ... */ 304 strlcpy(kt->descr, name, sizeof(kt->descr)); 305 RB_INIT(&kt->krt); 306 RB_INIT(&kt->krt6); 307 RB_INIT(&kt->knt); 308 TAILQ_INIT(&kt->krn); 309 kt->fib_conf = kt->fib_sync = fs; 310 kt->rtableid = rtableid; 311 kt->nhtableid = rdomid; 312 /* bump refcount of rdomain table for the nexthop lookups */ 313 ktable_get(kt->nhtableid)->nhrefcnt++; 314 315 /* ... and load it */ 316 if (fetchtable(kt) == -1) 317 return (-1); 318 319 /* everything is up and running */ 320 kt->state = RECONF_REINIT; 321 log_debug("%s: %s with rtableid %d rdomain %d", __func__, name, 322 rtableid, rdomid); 323 return (0); 324 } 325 326 void 327 ktable_free(u_int rtableid) 328 { 329 struct ktable *kt, *nkt; 330 331 if ((kt = ktable_get(rtableid)) == NULL) 332 return; 333 334 /* decouple from kernel, no new routes will be entered from here */ 335 kr_fib_decouple(kt->rtableid); 336 337 /* first unhook from the nexthop table */ 338 nkt = ktable_get(kt->nhtableid); 339 nkt->nhrefcnt--; 340 341 /* 342 * Evil little details: 343 * If kt->nhrefcnt > 0 then kt == nkt and nothing needs to be done. 344 * If kt != nkt then kt->nhrefcnt must be 0 and kt must be killed. 345 * If nkt is no longer referenced it must be killed (possible double 346 * free so check that kt != nkt). 347 */ 348 if (kt != nkt && nkt->nhrefcnt <= 0) 349 ktable_destroy(nkt); 350 if (kt->nhrefcnt <= 0) 351 ktable_destroy(kt); 352 } 353 354 void 355 ktable_destroy(struct ktable *kt) 356 { 357 /* decouple just to be sure, does not hurt */ 358 kr_fib_decouple(kt->rtableid); 359 360 log_debug("%s: freeing ktable %s rtableid %u", __func__, kt->descr, 361 kt->rtableid); 362 /* only clear nexthop table if it is the main rdomain table */ 363 if (kt->rtableid == kt->nhtableid) 364 knexthop_clear(kt); 365 kroute_clear(kt); 366 kroute6_clear(kt); 367 kr_net_clear(kt); 368 369 krt[kt->rtableid] = NULL; 370 free(kt); 371 } 372 373 struct ktable * 374 ktable_get(u_int rtableid) 375 { 376 if (rtableid >= krt_size) 377 return (NULL); 378 return (krt[rtableid]); 379 } 380 381 int 382 ktable_update(u_int rtableid, char *name, int flags) 383 { 384 struct ktable *kt, *rkt; 385 u_int rdomid; 386 387 if (!ktable_exists(rtableid, &rdomid)) 388 fatalx("King Bula lost a table"); /* may not happen */ 389 390 if (rdomid != rtableid || flags & F_RIB_NOFIB) { 391 rkt = ktable_get(rdomid); 392 if (rkt == NULL) { 393 char buf[32]; 394 snprintf(buf, sizeof(buf), "rdomain_%d", rdomid); 395 if (ktable_new(rdomid, rdomid, buf, 0)) 396 return (-1); 397 } else { 398 /* there is no need for full fib synchronisation if 399 * the table is only used for nexthop lookups. 400 */ 401 if (rkt->state == RECONF_DELETE) { 402 rkt->fib_conf = 0; 403 rkt->state = RECONF_KEEP; 404 } 405 } 406 } 407 408 if (flags & (F_RIB_NOFIB | F_RIB_NOEVALUATE)) 409 /* only rdomain table must exist */ 410 return (0); 411 412 kt = ktable_get(rtableid); 413 if (kt == NULL) { 414 if (ktable_new(rtableid, rdomid, name, 415 !(flags & F_RIB_NOFIBSYNC))) 416 return (-1); 417 } else { 418 /* fib sync has higher preference then no sync */ 419 if (kt->state == RECONF_DELETE) { 420 kt->fib_conf = !(flags & F_RIB_NOFIBSYNC); 421 kt->state = RECONF_KEEP; 422 } else if (!kt->fib_conf) 423 kt->fib_conf = !(flags & F_RIB_NOFIBSYNC); 424 425 strlcpy(kt->descr, name, sizeof(kt->descr)); 426 } 427 return (0); 428 } 429 430 int 431 ktable_exists(u_int rtableid, u_int *rdomid) 432 { 433 size_t len; 434 struct rt_tableinfo info; 435 int mib[6]; 436 437 mib[0] = CTL_NET; 438 mib[1] = PF_ROUTE; 439 mib[2] = 0; 440 mib[3] = 0; 441 mib[4] = NET_RT_TABLE; 442 mib[5] = rtableid; 443 444 len = sizeof(info); 445 if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) { 446 if (errno == ENOENT) 447 /* table nonexistent */ 448 return (0); 449 log_warn("sysctl net.route.rtableid"); 450 /* must return 0 so that the table is considered non-existent */ 451 return (0); 452 } 453 if (rdomid) 454 *rdomid = info.rti_domainid; 455 return (1); 456 } 457 458 int 459 kr_change(u_int rtableid, struct kroute_full *kf) 460 { 461 struct ktable *kt; 462 463 if ((kt = ktable_get(rtableid)) == NULL) 464 /* too noisy during reloads, just ignore */ 465 return (0); 466 kf->flags |= F_BGPD; 467 kf->priority = RTP_MINE; 468 if (!knexthop_true_nexthop(kt, kf)) 469 return kroute_remove(kt, kf, 1); 470 switch (kf->prefix.aid) { 471 case AID_INET: 472 return (kr4_change(kt, kf)); 473 case AID_INET6: 474 return (kr6_change(kt, kf)); 475 case AID_VPN_IPv4: 476 return (krVPN4_change(kt, kf)); 477 case AID_VPN_IPv6: 478 return (krVPN6_change(kt, kf)); 479 case AID_EVPN: 480 /* XXX ignored for now */ 481 return (0); 482 } 483 log_warnx("%s: not handled AID", __func__); 484 return (-1); 485 } 486 487 int 488 kr4_change(struct ktable *kt, struct kroute_full *kf) 489 { 490 struct kroute *kr; 491 492 /* for blackhole and reject routes nexthop needs to be 127.0.0.1 */ 493 if (kf->flags & (F_BLACKHOLE|F_REJECT)) 494 kf->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); 495 /* nexthop within 127/8 -> ignore silently */ 496 else if ((kf->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) == 497 htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) 498 return (0); 499 500 if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen, 501 kf->priority)) == NULL) { 502 if (kroute_insert(kt, kf) == -1) 503 return (-1); 504 } else { 505 kr->nexthop.s_addr = kf->nexthop.v4.s_addr; 506 rtlabel_unref(kr->labelid); 507 kr->labelid = rtlabel_name2id(kf->label); 508 if (kf->flags & F_BLACKHOLE) 509 kr->flags |= F_BLACKHOLE; 510 else 511 kr->flags &= ~F_BLACKHOLE; 512 if (kf->flags & F_REJECT) 513 kr->flags |= F_REJECT; 514 else 515 kr->flags &= ~F_REJECT; 516 517 if (kr->flags & F_NEXTHOP) 518 knexthop_update(kt, kf); 519 520 if (send_rtmsg(RTM_CHANGE, kt, kf)) 521 kr->flags |= F_BGPD_INSERTED; 522 } 523 524 return (0); 525 } 526 527 int 528 kr6_change(struct ktable *kt, struct kroute_full *kf) 529 { 530 struct kroute6 *kr6; 531 struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; 532 533 /* for blackhole and reject routes nexthop needs to be ::1 */ 534 if (kf->flags & (F_BLACKHOLE|F_REJECT)) 535 memcpy(&kf->nexthop.v6, &lo6, sizeof(kf->nexthop.v6)); 536 /* nexthop to loopback -> ignore silently */ 537 else if (IN6_IS_ADDR_LOOPBACK(&kf->nexthop.v6)) 538 return (0); 539 540 if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen, 541 kf->priority)) == NULL) { 542 if (kroute_insert(kt, kf) == -1) 543 return (-1); 544 } else { 545 memcpy(&kr6->nexthop, &kf->nexthop.v6, sizeof(struct in6_addr)); 546 kr6->nexthop_scope_id = kf->nexthop.scope_id; 547 rtlabel_unref(kr6->labelid); 548 kr6->labelid = rtlabel_name2id(kf->label); 549 if (kf->flags & F_BLACKHOLE) 550 kr6->flags |= F_BLACKHOLE; 551 else 552 kr6->flags &= ~F_BLACKHOLE; 553 if (kf->flags & F_REJECT) 554 kr6->flags |= F_REJECT; 555 else 556 kr6->flags &= ~F_REJECT; 557 558 if (kr6->flags & F_NEXTHOP) 559 knexthop_update(kt, kf); 560 561 if (send_rtmsg(RTM_CHANGE, kt, kf)) 562 kr6->flags |= F_BGPD_INSERTED; 563 } 564 565 return (0); 566 } 567 568 int 569 krVPN4_change(struct ktable *kt, struct kroute_full *kf) 570 { 571 struct kroute *kr; 572 uint32_t mplslabel = 0; 573 574 /* nexthop within 127/8 -> ignore silently */ 575 if ((kf->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) == 576 htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) 577 return (0); 578 579 /* only a single MPLS label is supported for now */ 580 if (kf->prefix.labellen != 3) { 581 log_warnx("%s: %s/%u has not a single label", __func__, 582 log_addr(&kf->prefix), kf->prefixlen); 583 return (0); 584 } 585 mplslabel = (kf->prefix.labelstack[0] << 24) | 586 (kf->prefix.labelstack[1] << 16) | 587 (kf->prefix.labelstack[2] << 8); 588 mplslabel = htonl(mplslabel); 589 590 kf->flags |= F_MPLS; 591 kf->mplslabel = mplslabel; 592 593 /* for blackhole and reject routes nexthop needs to be 127.0.0.1 */ 594 if (kf->flags & (F_BLACKHOLE|F_REJECT)) 595 kf->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); 596 597 if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen, 598 kf->priority)) == NULL) { 599 if (kroute_insert(kt, kf) == -1) 600 return (-1); 601 } else { 602 kr->mplslabel = mplslabel; 603 kr->flags |= F_MPLS; 604 kr->ifindex = kf->ifindex; 605 kr->nexthop.s_addr = kf->nexthop.v4.s_addr; 606 rtlabel_unref(kr->labelid); 607 kr->labelid = rtlabel_name2id(kf->label); 608 if (kf->flags & F_BLACKHOLE) 609 kr->flags |= F_BLACKHOLE; 610 else 611 kr->flags &= ~F_BLACKHOLE; 612 if (kf->flags & F_REJECT) 613 kr->flags |= F_REJECT; 614 else 615 kr->flags &= ~F_REJECT; 616 617 if (send_rtmsg(RTM_CHANGE, kt, kf)) 618 kr->flags |= F_BGPD_INSERTED; 619 } 620 621 return (0); 622 } 623 624 int 625 krVPN6_change(struct ktable *kt, struct kroute_full *kf) 626 { 627 struct kroute6 *kr6; 628 struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; 629 uint32_t mplslabel = 0; 630 631 /* nexthop to loopback -> ignore silently */ 632 if (IN6_IS_ADDR_LOOPBACK(&kf->nexthop.v6)) 633 return (0); 634 635 /* only a single MPLS label is supported for now */ 636 if (kf->prefix.labellen != 3) { 637 log_warnx("%s: %s/%u has not a single label", __func__, 638 log_addr(&kf->prefix), kf->prefixlen); 639 return (0); 640 } 641 mplslabel = (kf->prefix.labelstack[0] << 24) | 642 (kf->prefix.labelstack[1] << 16) | 643 (kf->prefix.labelstack[2] << 8); 644 mplslabel = htonl(mplslabel); 645 646 kf->flags |= F_MPLS; 647 kf->mplslabel = mplslabel; 648 649 /* for blackhole and reject routes nexthop needs to be ::1 */ 650 if (kf->flags & (F_BLACKHOLE|F_REJECT)) 651 memcpy(&kf->nexthop.v6, &lo6, sizeof(kf->nexthop.v6)); 652 653 if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen, 654 kf->priority)) == NULL) { 655 if (kroute_insert(kt, kf) == -1) 656 return (-1); 657 } else { 658 kr6->mplslabel = mplslabel; 659 kr6->flags |= F_MPLS; 660 kr6->ifindex = kf->ifindex; 661 memcpy(&kr6->nexthop, &kf->nexthop.v6, sizeof(struct in6_addr)); 662 kr6->nexthop_scope_id = kf->nexthop.scope_id; 663 rtlabel_unref(kr6->labelid); 664 kr6->labelid = rtlabel_name2id(kf->label); 665 if (kf->flags & F_BLACKHOLE) 666 kr6->flags |= F_BLACKHOLE; 667 else 668 kr6->flags &= ~F_BLACKHOLE; 669 if (kf->flags & F_REJECT) 670 kr6->flags |= F_REJECT; 671 else 672 kr6->flags &= ~F_REJECT; 673 674 if (send_rtmsg(RTM_CHANGE, kt, kf)) 675 kr6->flags |= F_BGPD_INSERTED; 676 } 677 678 return (0); 679 } 680 681 int 682 kr_delete(u_int rtableid, struct kroute_full *kf) 683 { 684 struct ktable *kt; 685 686 if ((kt = ktable_get(rtableid)) == NULL) 687 /* too noisy during reloads, just ignore */ 688 return (0); 689 kf->flags |= F_BGPD; 690 kf->priority = RTP_MINE; 691 return kroute_remove(kt, kf, 1); 692 } 693 694 int 695 kr_flush(u_int rtableid) 696 { 697 struct ktable *kt; 698 struct kroute *kr, *next; 699 struct kroute6 *kr6, *next6; 700 701 if ((kt = ktable_get(rtableid)) == NULL) 702 /* too noisy during reloads, just ignore */ 703 return (0); 704 705 RB_FOREACH_SAFE(kr, kroute_tree, &kt->krt, next) 706 if ((kr->flags & F_BGPD_INSERTED)) { 707 if (kroute_remove(kt, kr_tofull(kr), 1) == -1) 708 return (-1); 709 } 710 RB_FOREACH_SAFE(kr6, kroute6_tree, &kt->krt6, next6) 711 if ((kr6->flags & F_BGPD_INSERTED)) { 712 if (kroute_remove(kt, kr6_tofull(kr6), 1) == -1) 713 return (-1); 714 } 715 716 kt->fib_sync = 0; 717 return (0); 718 } 719 720 void 721 kr_shutdown(void) 722 { 723 u_int i; 724 725 for (i = krt_size; i > 0; i--) 726 ktable_free(i - 1); 727 kif_clear(); 728 free(krt); 729 } 730 731 void 732 kr_fib_couple(u_int rtableid) 733 { 734 struct ktable *kt; 735 struct kroute *kr; 736 struct kroute6 *kr6; 737 738 if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */ 739 return; 740 741 if (kt->fib_sync) /* already coupled */ 742 return; 743 744 kt->fib_sync = 1; 745 746 RB_FOREACH(kr, kroute_tree, &kt->krt) 747 if (kr->flags & F_BGPD) { 748 if (send_rtmsg(RTM_ADD, kt, kr_tofull(kr))) 749 kr->flags |= F_BGPD_INSERTED; 750 } 751 RB_FOREACH(kr6, kroute6_tree, &kt->krt6) 752 if (kr6->flags & F_BGPD) { 753 if (send_rtmsg(RTM_ADD, kt, kr6_tofull(kr6))) 754 kr6->flags |= F_BGPD_INSERTED; 755 } 756 log_info("kernel routing table %u (%s) coupled", kt->rtableid, 757 kt->descr); 758 } 759 760 void 761 kr_fib_couple_all(void) 762 { 763 u_int i; 764 765 for (i = krt_size; i > 0; i--) 766 kr_fib_couple(i - 1); 767 } 768 769 void 770 kr_fib_decouple(u_int rtableid) 771 { 772 struct ktable *kt; 773 struct kroute *kr; 774 struct kroute6 *kr6; 775 776 if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */ 777 return; 778 779 if (!kt->fib_sync) /* already decoupled */ 780 return; 781 782 RB_FOREACH(kr, kroute_tree, &kt->krt) 783 if ((kr->flags & F_BGPD_INSERTED)) { 784 if (send_rtmsg(RTM_DELETE, kt, kr_tofull(kr))) 785 kr->flags &= ~F_BGPD_INSERTED; 786 } 787 RB_FOREACH(kr6, kroute6_tree, &kt->krt6) 788 if ((kr6->flags & F_BGPD_INSERTED)) { 789 if (send_rtmsg(RTM_DELETE, kt, kr6_tofull(kr6))) 790 kr6->flags &= ~F_BGPD_INSERTED; 791 } 792 793 kt->fib_sync = 0; 794 795 log_info("kernel routing table %u (%s) decoupled", kt->rtableid, 796 kt->descr); 797 } 798 799 void 800 kr_fib_decouple_all(void) 801 { 802 u_int i; 803 804 for (i = krt_size; i > 0; i--) 805 kr_fib_decouple(i - 1); 806 } 807 808 void 809 kr_fib_prio_set(uint8_t prio) 810 { 811 kr_state.fib_prio = prio; 812 } 813 814 int 815 kr_dispatch_msg(void) 816 { 817 return (dispatch_rtmsg()); 818 } 819 820 int 821 kr_nexthop_add(u_int rtableid, struct bgpd_addr *addr) 822 { 823 struct ktable *kt; 824 struct knexthop *h; 825 826 if ((kt = ktable_get(rtableid)) == NULL) { 827 log_warnx("%s: non-existent rtableid %d", __func__, rtableid); 828 return (0); 829 } 830 if ((h = knexthop_find(kt, addr)) != NULL) { 831 /* should not happen... this is actually an error path */ 832 knexthop_send_update(h); 833 } else { 834 if ((h = calloc(1, sizeof(*h))) == NULL) { 835 log_warn("%s", __func__); 836 return (-1); 837 } 838 memcpy(&h->nexthop, addr, sizeof(h->nexthop)); 839 840 if (knexthop_insert(kt, h) == -1) 841 return (-1); 842 } 843 844 return (0); 845 } 846 847 void 848 kr_nexthop_delete(u_int rtableid, struct bgpd_addr *addr) 849 { 850 struct ktable *kt; 851 struct knexthop *kn; 852 853 if ((kt = ktable_get(rtableid)) == NULL) { 854 log_warnx("%s: non-existent rtableid %d", __func__, 855 rtableid); 856 return; 857 } 858 if ((kn = knexthop_find(kt, addr)) == NULL) 859 return; 860 861 knexthop_remove(kt, kn); 862 } 863 864 static struct ctl_show_interface * 865 kr_show_interface(struct kif *kif) 866 { 867 static struct ctl_show_interface iface; 868 uint64_t ifms_type; 869 870 memset(&iface, 0, sizeof(iface)); 871 strlcpy(iface.ifname, kif->ifname, sizeof(iface.ifname)); 872 873 snprintf(iface.linkstate, sizeof(iface.linkstate), 874 "%s", get_linkstate(kif->if_type, kif->link_state)); 875 876 if ((ifms_type = ift2ifm(kif->if_type)) != 0) 877 snprintf(iface.media, sizeof(iface.media), 878 "%s", get_media_descr(ifms_type)); 879 880 iface.baudrate = kif->baudrate; 881 iface.rdomain = kif->rdomain; 882 iface.nh_reachable = kif->nh_reachable; 883 iface.is_up = (kif->flags & IFF_UP) == IFF_UP; 884 885 return &iface; 886 } 887 888 void 889 kr_show_route(struct imsg *imsg) 890 { 891 struct ktable *kt; 892 struct kroute *kr, *kn; 893 struct kroute6 *kr6, *kn6; 894 struct kroute_full *kf; 895 struct bgpd_addr addr; 896 struct ctl_kroute_req req; 897 struct ctl_show_nexthop snh; 898 struct knexthop *h; 899 struct kif *kif; 900 uint32_t tableid; 901 pid_t pid; 902 u_int i; 903 u_short ifindex = 0; 904 905 tableid = imsg_get_id(imsg); 906 pid = imsg_get_pid(imsg); 907 switch (imsg_get_type(imsg)) { 908 case IMSG_CTL_KROUTE: 909 if (imsg_get_data(imsg, &req, sizeof(req)) == -1) { 910 log_warnx("%s: wrong imsg len", __func__); 911 break; 912 } 913 kt = ktable_get(tableid); 914 if (kt == NULL) { 915 log_warnx("%s: table %u does not exist", __func__, 916 tableid); 917 break; 918 } 919 if (!req.af || req.af == AF_INET) 920 RB_FOREACH(kr, kroute_tree, &kt->krt) { 921 if (req.flags && (kr->flags & req.flags) == 0) 922 continue; 923 kn = kr; 924 do { 925 kf = kr_tofull(kn); 926 kf->priority = kr_priority(kf); 927 send_imsg_session(IMSG_CTL_KROUTE, 928 pid, kf, sizeof(*kf)); 929 } while ((kn = kn->next) != NULL); 930 } 931 if (!req.af || req.af == AF_INET6) 932 RB_FOREACH(kr6, kroute6_tree, &kt->krt6) { 933 if (req.flags && (kr6->flags & req.flags) == 0) 934 continue; 935 kn6 = kr6; 936 do { 937 kf = kr6_tofull(kn6); 938 kf->priority = kr_priority(kf); 939 send_imsg_session(IMSG_CTL_KROUTE, 940 pid, kf, sizeof(*kf)); 941 } while ((kn6 = kn6->next) != NULL); 942 } 943 break; 944 case IMSG_CTL_KROUTE_ADDR: 945 if (imsg_get_data(imsg, &addr, sizeof(addr)) == -1) { 946 log_warnx("%s: wrong imsg len", __func__); 947 break; 948 } 949 kt = ktable_get(tableid); 950 if (kt == NULL) { 951 log_warnx("%s: table %u does not exist", __func__, 952 tableid); 953 break; 954 } 955 kr = NULL; 956 switch (addr.aid) { 957 case AID_INET: 958 kr = kroute_match(kt, &addr, 1); 959 if (kr != NULL) { 960 kf = kr_tofull(kr); 961 kf->priority = kr_priority(kf); 962 send_imsg_session(IMSG_CTL_KROUTE, 963 pid, kf, sizeof(*kf)); 964 } 965 break; 966 case AID_INET6: 967 kr6 = kroute6_match(kt, &addr, 1); 968 if (kr6 != NULL) { 969 kf = kr6_tofull(kr6); 970 kf->priority = kr_priority(kf); 971 send_imsg_session(IMSG_CTL_KROUTE, 972 pid, kf, sizeof(*kf)); 973 } 974 break; 975 } 976 break; 977 case IMSG_CTL_SHOW_NEXTHOP: 978 kt = ktable_get(tableid); 979 if (kt == NULL) { 980 log_warnx("%s: table %u does not exist", __func__, 981 tableid); 982 break; 983 } 984 RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) { 985 memset(&snh, 0, sizeof(snh)); 986 memcpy(&snh.addr, &h->nexthop, sizeof(snh.addr)); 987 if (h->kroute != NULL) { 988 switch (h->nexthop.aid) { 989 case AID_INET: 990 kr = h->kroute; 991 snh.valid = kroute_validate(kr); 992 snh.krvalid = 1; 993 snh.kr = *kr_tofull(kr); 994 ifindex = kr->ifindex; 995 break; 996 case AID_INET6: 997 kr6 = h->kroute; 998 snh.valid = kroute6_validate(kr6); 999 snh.krvalid = 1; 1000 snh.kr = *kr6_tofull(kr6); 1001 ifindex = kr6->ifindex; 1002 break; 1003 } 1004 snh.kr.priority = kr_priority(&snh.kr); 1005 if ((kif = kif_find(ifindex)) != NULL) 1006 memcpy(&snh.iface, 1007 kr_show_interface(kif), 1008 sizeof(snh.iface)); 1009 } 1010 send_imsg_session(IMSG_CTL_SHOW_NEXTHOP, pid, 1011 &snh, sizeof(snh)); 1012 } 1013 break; 1014 case IMSG_CTL_SHOW_INTERFACE: 1015 RB_FOREACH(kif, kif_tree, &kit) 1016 send_imsg_session(IMSG_CTL_SHOW_INTERFACE, 1017 pid, kr_show_interface(kif), 1018 sizeof(struct ctl_show_interface)); 1019 break; 1020 case IMSG_CTL_SHOW_FIB_TABLES: 1021 for (i = 0; i < krt_size; i++) { 1022 struct ktable ktab; 1023 1024 if ((kt = ktable_get(i)) == NULL) 1025 continue; 1026 1027 ktab = *kt; 1028 /* do not leak internal information */ 1029 RB_INIT(&ktab.krt); 1030 RB_INIT(&ktab.krt6); 1031 RB_INIT(&ktab.knt); 1032 TAILQ_INIT(&ktab.krn); 1033 1034 send_imsg_session(IMSG_CTL_SHOW_FIB_TABLES, 1035 pid, &ktab, sizeof(ktab)); 1036 } 1037 break; 1038 default: /* nada */ 1039 break; 1040 } 1041 1042 send_imsg_session(IMSG_CTL_END, pid, NULL, 0); 1043 } 1044 1045 static void 1046 kr_send_dependon(struct kif *kif) 1047 { 1048 struct session_dependon sdon = { 0 }; 1049 1050 strlcpy(sdon.ifname, kif->ifname, sizeof(sdon.ifname)); 1051 sdon.depend_state = kif->depend_state; 1052 send_imsg_session(IMSG_SESSION_DEPENDON, 0, &sdon, sizeof(sdon)); 1053 } 1054 1055 void 1056 kr_ifinfo(char *ifname) 1057 { 1058 struct kif *kif; 1059 1060 RB_FOREACH(kif, kif_tree, &kit) 1061 if (!strcmp(ifname, kif->ifname)) { 1062 kr_send_dependon(kif); 1063 return; 1064 } 1065 } 1066 1067 static int 1068 kr_net_redist_add(struct ktable *kt, struct network_config *net, 1069 struct filter_set_head *attr, int dynamic) 1070 { 1071 struct kredist_node *r, *xr; 1072 1073 if ((r = calloc(1, sizeof(*r))) == NULL) 1074 fatal("%s", __func__); 1075 r->prefix = net->prefix; 1076 r->prefixlen = net->prefixlen; 1077 r->rd = net->rd; 1078 r->dynamic = dynamic; 1079 1080 xr = RB_INSERT(kredist_tree, &kt->kredist, r); 1081 if (xr != NULL) { 1082 free(r); 1083 1084 if (dynamic != xr->dynamic && dynamic) { 1085 /* 1086 * ignore update a non-dynamic announcement is 1087 * already present which has preference. 1088 */ 1089 return 0; 1090 } 1091 /* 1092 * only equal or non-dynamic announcement ends up here. 1093 * In both cases reset the dynamic flag (nop for equal) and 1094 * redistribute. 1095 */ 1096 xr->dynamic = dynamic; 1097 } 1098 1099 if (send_network(IMSG_NETWORK_ADD, net, attr) == -1) 1100 log_warnx("%s: failed to send network update", __func__); 1101 return 1; 1102 } 1103 1104 static void 1105 kr_net_redist_del(struct ktable *kt, struct network_config *net, int dynamic) 1106 { 1107 struct kredist_node *r, node; 1108 1109 memset(&node, 0, sizeof(node)); 1110 node.prefix = net->prefix; 1111 node.prefixlen = net->prefixlen; 1112 node.rd = net->rd; 1113 1114 r = RB_FIND(kredist_tree, &kt->kredist, &node); 1115 if (r == NULL || dynamic != r->dynamic) 1116 return; 1117 1118 if (RB_REMOVE(kredist_tree, &kt->kredist, r) == NULL) { 1119 log_warnx("%s: failed to remove network %s/%u", __func__, 1120 log_addr(&node.prefix), node.prefixlen); 1121 return; 1122 } 1123 free(r); 1124 1125 if (send_network(IMSG_NETWORK_REMOVE, net, NULL) == -1) 1126 log_warnx("%s: failed to send network removal", __func__); 1127 } 1128 1129 int 1130 kr_net_match(struct ktable *kt, struct network_config *net, uint16_t flags, 1131 int loopback) 1132 { 1133 struct network *xn; 1134 1135 TAILQ_FOREACH(xn, &kt->krn, entry) { 1136 if (xn->net.prefix.aid != net->prefix.aid) 1137 continue; 1138 switch (xn->net.type) { 1139 case NETWORK_DEFAULT: 1140 /* static match already redistributed */ 1141 continue; 1142 case NETWORK_STATIC: 1143 /* Skip networks with nexthop on loopback. */ 1144 if (loopback) 1145 continue; 1146 if (flags & F_STATIC) 1147 break; 1148 continue; 1149 case NETWORK_CONNECTED: 1150 /* Skip networks with nexthop on loopback. */ 1151 if (loopback) 1152 continue; 1153 if (flags & F_CONNECTED) 1154 break; 1155 continue; 1156 case NETWORK_RTLABEL: 1157 if (net->rtlabel == xn->net.rtlabel) 1158 break; 1159 continue; 1160 case NETWORK_PRIORITY: 1161 if (net->priority == xn->net.priority) 1162 break; 1163 continue; 1164 case NETWORK_MRTCLONE: 1165 case NETWORK_PREFIXSET: 1166 /* must not happen */ 1167 log_warnx("%s: found a NETWORK_PREFIXSET, " 1168 "please send a bug report", __func__); 1169 continue; 1170 } 1171 1172 net->rd = xn->net.rd; 1173 if (kr_net_redist_add(kt, net, &xn->net.attrset, 1)) 1174 return (1); 1175 } 1176 return (0); 1177 } 1178 1179 struct network * 1180 kr_net_find(struct ktable *kt, struct network *n) 1181 { 1182 struct network *xn; 1183 1184 TAILQ_FOREACH(xn, &kt->krn, entry) { 1185 if (n->net.type != xn->net.type || 1186 n->net.prefixlen != xn->net.prefixlen || 1187 n->net.rd != xn->net.rd || 1188 n->net.rtlabel != xn->net.rtlabel || 1189 n->net.priority != xn->net.priority) 1190 continue; 1191 if (memcmp(&n->net.prefix, &xn->net.prefix, 1192 sizeof(n->net.prefix)) == 0) 1193 return (xn); 1194 } 1195 return (NULL); 1196 } 1197 1198 void 1199 kr_net_reload(u_int rtableid, uint64_t rd, struct network_head *nh) 1200 { 1201 struct network *n, *xn; 1202 struct ktable *kt; 1203 1204 if ((kt = ktable_get(rtableid)) == NULL) 1205 fatalx("%s: non-existent rtableid %d", __func__, rtableid); 1206 1207 while ((n = TAILQ_FIRST(nh)) != NULL) { 1208 TAILQ_REMOVE(nh, n, entry); 1209 n->net.old = 0; 1210 n->net.rd = rd; 1211 xn = kr_net_find(kt, n); 1212 if (xn) { 1213 xn->net.old = 0; 1214 filterset_free(&xn->net.attrset); 1215 filterset_move(&n->net.attrset, &xn->net.attrset); 1216 network_free(n); 1217 } else 1218 TAILQ_INSERT_TAIL(&kt->krn, n, entry); 1219 } 1220 } 1221 1222 void 1223 kr_net_clear(struct ktable *kt) 1224 { 1225 struct network *n, *xn; 1226 1227 TAILQ_FOREACH_SAFE(n, &kt->krn, entry, xn) { 1228 TAILQ_REMOVE(&kt->krn, n, entry); 1229 if (n->net.type == NETWORK_DEFAULT) 1230 kr_net_redist_del(kt, &n->net, 0); 1231 network_free(n); 1232 } 1233 } 1234 1235 void 1236 kr_redistribute(int type, struct ktable *kt, struct kroute_full *kf) 1237 { 1238 struct network_config net; 1239 uint32_t a; 1240 int loflag = 0; 1241 1242 memset(&net, 0, sizeof(net)); 1243 net.prefix = kf->prefix; 1244 net.prefixlen = kf->prefixlen; 1245 net.rtlabel = rtlabel_name2id(kf->label); 1246 rtlabel_unref(net.rtlabel); /* drop reference now, which is ok here */ 1247 net.priority = kf->priority; 1248 1249 /* shortcut for removals */ 1250 if (type == IMSG_NETWORK_REMOVE) { 1251 kr_net_redist_del(kt, &net, 1); 1252 return; 1253 } 1254 1255 if (kf->flags & F_BGPD) 1256 return; 1257 1258 switch (kf->prefix.aid) { 1259 case AID_INET: 1260 /* 1261 * We consider the loopback net and multicast addresses 1262 * as not redistributable. 1263 */ 1264 a = ntohl(kf->prefix.v4.s_addr); 1265 if (IN_MULTICAST(a) || 1266 (a >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 1267 return; 1268 1269 /* Check if the nexthop is the loopback addr. */ 1270 if (kf->nexthop.v4.s_addr == htonl(INADDR_LOOPBACK)) 1271 loflag = 1; 1272 break; 1273 1274 case AID_INET6: 1275 /* 1276 * We consider unspecified, loopback, multicast, 1277 * link- and site-local, IPv4 mapped and IPv4 compatible 1278 * addresses as not redistributable. 1279 */ 1280 if (IN6_IS_ADDR_UNSPECIFIED(&kf->prefix.v6) || 1281 IN6_IS_ADDR_LOOPBACK(&kf->prefix.v6) || 1282 IN6_IS_ADDR_MULTICAST(&kf->prefix.v6) || 1283 IN6_IS_ADDR_LINKLOCAL(&kf->prefix.v6) || 1284 IN6_IS_ADDR_SITELOCAL(&kf->prefix.v6) || 1285 IN6_IS_ADDR_V4MAPPED(&kf->prefix.v6) || 1286 IN6_IS_ADDR_V4COMPAT(&kf->prefix.v6)) 1287 return; 1288 1289 /* Check if the nexthop is the loopback addr. */ 1290 if (IN6_IS_ADDR_LOOPBACK(&kf->nexthop.v6)) 1291 loflag = 1; 1292 break; 1293 default: 1294 /* unhandled AID cannot be redistributed */ 1295 return; 1296 } 1297 1298 /* 1299 * never allow 0/0 or ::/0 the default route can only be redistributed 1300 * with announce default. 1301 */ 1302 if (kf->prefixlen == 0) 1303 return; 1304 1305 if (kr_net_match(kt, &net, kf->flags, loflag) == 0) 1306 /* no longer matches, if still present remove it */ 1307 kr_net_redist_del(kt, &net, 1); 1308 } 1309 1310 void 1311 ktable_preload(void) 1312 { 1313 struct ktable *kt; 1314 struct network *n; 1315 u_int i; 1316 1317 for (i = 0; i < krt_size; i++) { 1318 if ((kt = ktable_get(i)) == NULL) 1319 continue; 1320 kt->state = RECONF_DELETE; 1321 1322 /* mark all networks as old */ 1323 TAILQ_FOREACH(n, &kt->krn, entry) 1324 n->net.old = 1; 1325 } 1326 } 1327 1328 void 1329 ktable_postload(void) 1330 { 1331 struct ktable *kt; 1332 struct network *n, *xn; 1333 u_int i; 1334 1335 for (i = krt_size; i > 0; i--) { 1336 if ((kt = ktable_get(i - 1)) == NULL) 1337 continue; 1338 if (kt->state == RECONF_DELETE) { 1339 ktable_free(i - 1); 1340 continue; 1341 } else if (kt->state == RECONF_REINIT) { 1342 if (kt->fib_sync != kt->fib_conf) { 1343 kt->fib_sync = kt->fib_conf; 1344 if (kt->fib_sync) 1345 fetchtable(kt); 1346 } 1347 } 1348 1349 /* cleanup old networks */ 1350 TAILQ_FOREACH_SAFE(n, &kt->krn, entry, xn) { 1351 if (n->net.old) { 1352 TAILQ_REMOVE(&kt->krn, n, entry); 1353 if (n->net.type == NETWORK_DEFAULT) 1354 kr_net_redist_del(kt, &n->net, 0); 1355 network_free(n); 1356 } 1357 } 1358 } 1359 } 1360 1361 int 1362 kr_reload(void) 1363 { 1364 struct ktable *kt; 1365 struct kroute *kr; 1366 struct kroute6 *kr6; 1367 struct knexthop *nh; 1368 struct network *n; 1369 u_int rid; 1370 int hasdyn = 0; 1371 1372 for (rid = 0; rid < krt_size; rid++) { 1373 if ((kt = ktable_get(rid)) == NULL) 1374 continue; 1375 1376 /* if this is the main nexthop table revalidate nexthops */ 1377 if (kt->rtableid == kt->nhtableid) 1378 RB_FOREACH(nh, knexthop_tree, KT2KNT(kt)) 1379 knexthop_validate(kt, nh); 1380 1381 TAILQ_FOREACH(n, &kt->krn, entry) 1382 if (n->net.type == NETWORK_DEFAULT) { 1383 kr_net_redist_add(kt, &n->net, 1384 &n->net.attrset, 0); 1385 } else 1386 hasdyn = 1; 1387 1388 if (hasdyn) { 1389 /* only evaluate the full tree if we need */ 1390 RB_FOREACH(kr, kroute_tree, &kt->krt) 1391 kr_redistribute(IMSG_NETWORK_ADD, kt, 1392 kr_tofull(kr)); 1393 RB_FOREACH(kr6, kroute6_tree, &kt->krt6) 1394 kr_redistribute(IMSG_NETWORK_ADD, kt, 1395 kr6_tofull(kr6)); 1396 } 1397 } 1398 1399 return (0); 1400 } 1401 1402 uint8_t 1403 kr_priority(struct kroute_full *kf) 1404 { 1405 if (kf->priority == RTP_MINE) 1406 return kr_state.fib_prio; 1407 return kf->priority; 1408 } 1409 1410 struct kroute_full * 1411 kr_tofull(struct kroute *kr) 1412 { 1413 static struct kroute_full kf; 1414 1415 memset(&kf, 0, sizeof(kf)); 1416 1417 kf.prefix.aid = AID_INET; 1418 kf.prefix.v4.s_addr = kr->prefix.s_addr; 1419 kf.nexthop.aid = AID_INET; 1420 kf.nexthop.v4.s_addr = kr->nexthop.s_addr; 1421 strlcpy(kf.label, rtlabel_id2name(kr->labelid), sizeof(kf.label)); 1422 kf.flags = kr->flags; 1423 kf.ifindex = kr->ifindex; 1424 kf.prefixlen = kr->prefixlen; 1425 kf.priority = kr->priority; 1426 kf.mplslabel = kr->mplslabel; 1427 1428 return (&kf); 1429 } 1430 1431 struct kroute_full * 1432 kr6_tofull(struct kroute6 *kr6) 1433 { 1434 static struct kroute_full kf; 1435 1436 memset(&kf, 0, sizeof(kf)); 1437 1438 kf.prefix.aid = AID_INET6; 1439 kf.prefix.v6 = kr6->prefix; 1440 kf.prefix.scope_id = kr6->prefix_scope_id; 1441 kf.nexthop.aid = AID_INET6; 1442 kf.nexthop.v6 = kr6->nexthop; 1443 kf.nexthop.scope_id = kr6->nexthop_scope_id; 1444 strlcpy(kf.label, rtlabel_id2name(kr6->labelid), sizeof(kf.label)); 1445 kf.flags = kr6->flags; 1446 kf.ifindex = kr6->ifindex; 1447 kf.prefixlen = kr6->prefixlen; 1448 kf.priority = kr6->priority; 1449 kf.mplslabel = kr6->mplslabel; 1450 1451 return (&kf); 1452 } 1453 1454 /* 1455 * RB-tree compare functions 1456 */ 1457 1458 int 1459 kroute_compare(struct kroute *a, struct kroute *b) 1460 { 1461 if (ntohl(a->prefix.s_addr) < ntohl(b->prefix.s_addr)) 1462 return (-1); 1463 if (ntohl(a->prefix.s_addr) > ntohl(b->prefix.s_addr)) 1464 return (1); 1465 if (a->prefixlen < b->prefixlen) 1466 return (-1); 1467 if (a->prefixlen > b->prefixlen) 1468 return (1); 1469 1470 /* if the priority is RTP_ANY finish on the first address hit */ 1471 if (a->priority == RTP_ANY || b->priority == RTP_ANY) 1472 return (0); 1473 if (a->priority < b->priority) 1474 return (-1); 1475 if (a->priority > b->priority) 1476 return (1); 1477 return (0); 1478 } 1479 1480 int 1481 kroute6_compare(struct kroute6 *a, struct kroute6 *b) 1482 { 1483 int i; 1484 1485 for (i = 0; i < 16; i++) { 1486 if (a->prefix.s6_addr[i] < b->prefix.s6_addr[i]) 1487 return (-1); 1488 if (a->prefix.s6_addr[i] > b->prefix.s6_addr[i]) 1489 return (1); 1490 } 1491 if (a->prefix_scope_id < b->prefix_scope_id) 1492 return (-1); 1493 if (a->prefix_scope_id > b->prefix_scope_id) 1494 return (1); 1495 1496 if (a->prefixlen < b->prefixlen) 1497 return (-1); 1498 if (a->prefixlen > b->prefixlen) 1499 return (1); 1500 1501 /* if the priority is RTP_ANY finish on the first address hit */ 1502 if (a->priority == RTP_ANY || b->priority == RTP_ANY) 1503 return (0); 1504 if (a->priority < b->priority) 1505 return (-1); 1506 if (a->priority > b->priority) 1507 return (1); 1508 return (0); 1509 } 1510 1511 int 1512 knexthop_compare(struct knexthop *a, struct knexthop *b) 1513 { 1514 int i; 1515 1516 if (a->nexthop.aid != b->nexthop.aid) 1517 return (b->nexthop.aid - a->nexthop.aid); 1518 1519 switch (a->nexthop.aid) { 1520 case AID_INET: 1521 if (ntohl(a->nexthop.v4.s_addr) < ntohl(b->nexthop.v4.s_addr)) 1522 return (-1); 1523 if (ntohl(a->nexthop.v4.s_addr) > ntohl(b->nexthop.v4.s_addr)) 1524 return (1); 1525 break; 1526 case AID_INET6: 1527 for (i = 0; i < 16; i++) { 1528 if (a->nexthop.v6.s6_addr[i] < b->nexthop.v6.s6_addr[i]) 1529 return (-1); 1530 if (a->nexthop.v6.s6_addr[i] > b->nexthop.v6.s6_addr[i]) 1531 return (1); 1532 } 1533 break; 1534 default: 1535 fatalx("%s: unknown AF", __func__); 1536 } 1537 1538 return (0); 1539 } 1540 1541 int 1542 kredist_compare(struct kredist_node *a, struct kredist_node *b) 1543 { 1544 int i; 1545 1546 if (a->prefix.aid != b->prefix.aid) 1547 return (b->prefix.aid - a->prefix.aid); 1548 1549 if (a->prefixlen < b->prefixlen) 1550 return (-1); 1551 if (a->prefixlen > b->prefixlen) 1552 return (1); 1553 1554 switch (a->prefix.aid) { 1555 case AID_INET: 1556 if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr)) 1557 return (-1); 1558 if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr)) 1559 return (1); 1560 break; 1561 case AID_INET6: 1562 for (i = 0; i < 16; i++) { 1563 if (a->prefix.v6.s6_addr[i] < b->prefix.v6.s6_addr[i]) 1564 return (-1); 1565 if (a->prefix.v6.s6_addr[i] > b->prefix.v6.s6_addr[i]) 1566 return (1); 1567 } 1568 break; 1569 default: 1570 fatalx("%s: unknown AF", __func__); 1571 } 1572 1573 if (a->rd < b->rd) 1574 return (-1); 1575 if (a->rd > b->rd) 1576 return (1); 1577 1578 return (0); 1579 } 1580 1581 int 1582 kif_compare(struct kif *a, struct kif *b) 1583 { 1584 return (b->ifindex - a->ifindex); 1585 } 1586 1587 1588 /* 1589 * tree management functions 1590 */ 1591 1592 struct kroute * 1593 kroute_find(struct ktable *kt, const struct bgpd_addr *prefix, 1594 uint8_t prefixlen, uint8_t prio) 1595 { 1596 struct kroute s; 1597 struct kroute *kn, *tmp; 1598 1599 s.prefix = prefix->v4; 1600 s.prefixlen = prefixlen; 1601 s.priority = prio; 1602 1603 kn = RB_FIND(kroute_tree, &kt->krt, &s); 1604 if (kn && prio == RTP_ANY) { 1605 tmp = RB_PREV(kroute_tree, &kt->krt, kn); 1606 while (tmp) { 1607 if (kroute_compare(&s, tmp) == 0) 1608 kn = tmp; 1609 else 1610 break; 1611 tmp = RB_PREV(kroute_tree, &kt->krt, kn); 1612 } 1613 } 1614 return (kn); 1615 } 1616 1617 struct kroute * 1618 kroute_matchgw(struct kroute *kr, struct kroute_full *kf) 1619 { 1620 in_addr_t nexthop; 1621 1622 if (kf->flags & F_CONNECTED) { 1623 do { 1624 if (kr->ifindex == kf->ifindex) 1625 return (kr); 1626 kr = kr->next; 1627 } while (kr); 1628 return (NULL); 1629 } 1630 1631 nexthop = kf->nexthop.v4.s_addr; 1632 do { 1633 if (kr->nexthop.s_addr == nexthop) 1634 return (kr); 1635 kr = kr->next; 1636 } while (kr); 1637 1638 return (NULL); 1639 } 1640 1641 int 1642 kroute_insert(struct ktable *kt, struct kroute_full *kf) 1643 { 1644 struct kroute *kr, *krm; 1645 struct kroute6 *kr6, *kr6m; 1646 struct knexthop *n; 1647 uint32_t mplslabel = 0; 1648 int multipath = 0; 1649 1650 if (kf->prefix.aid == AID_VPN_IPv4 || 1651 kf->prefix.aid == AID_VPN_IPv6) { 1652 /* only a single MPLS label is supported for now */ 1653 if (kf->prefix.labellen != 3) { 1654 log_warnx("%s/%u does not have a single label", 1655 log_addr(&kf->prefix), kf->prefixlen); 1656 return -1; 1657 } 1658 mplslabel = (kf->prefix.labelstack[0] << 24) | 1659 (kf->prefix.labelstack[1] << 16) | 1660 (kf->prefix.labelstack[2] << 8); 1661 } 1662 1663 switch (kf->prefix.aid) { 1664 case AID_INET: 1665 case AID_VPN_IPv4: 1666 if ((kr = calloc(1, sizeof(*kr))) == NULL) { 1667 log_warn("%s", __func__); 1668 return (-1); 1669 } 1670 kr->flags = kf->flags; 1671 kr->prefix = kf->prefix.v4; 1672 kr->prefixlen = kf->prefixlen; 1673 if (kf->nexthop.aid == AID_INET) 1674 kr->nexthop = kf->nexthop.v4; 1675 1676 if (kf->prefix.aid == AID_VPN_IPv4) { 1677 kr->flags |= F_MPLS; 1678 kr->mplslabel = htonl(mplslabel); 1679 } 1680 1681 kr->ifindex = kf->ifindex; 1682 kr->priority = kf->priority; 1683 kr->labelid = rtlabel_name2id(kf->label); 1684 1685 if ((krm = RB_INSERT(kroute_tree, &kt->krt, kr)) != NULL) { 1686 /* multipath route, add at end of list */ 1687 while (krm->next != NULL) 1688 krm = krm->next; 1689 krm->next = kr; 1690 multipath = 1; 1691 } 1692 1693 if (kf->flags & F_BGPD) 1694 if (send_rtmsg(RTM_ADD, kt, kf)) 1695 kr->flags |= F_BGPD_INSERTED; 1696 break; 1697 case AID_INET6: 1698 case AID_VPN_IPv6: 1699 if ((kr6 = calloc(1, sizeof(*kr6))) == NULL) { 1700 log_warn("%s", __func__); 1701 return (-1); 1702 } 1703 kr6->flags = kf->flags; 1704 kr6->prefix = kf->prefix.v6; 1705 kr6->prefix_scope_id = kf->prefix.scope_id; 1706 kr6->prefixlen = kf->prefixlen; 1707 if (kf->nexthop.aid == AID_INET6) { 1708 kr6->nexthop = kf->nexthop.v6; 1709 kr6->nexthop_scope_id = kf->nexthop.scope_id; 1710 } else 1711 kr6->nexthop = in6addr_any; 1712 1713 if (kf->prefix.aid == AID_VPN_IPv6) { 1714 kr6->flags |= F_MPLS; 1715 kr6->mplslabel = htonl(mplslabel); 1716 } 1717 1718 kr6->ifindex = kf->ifindex; 1719 kr6->priority = kf->priority; 1720 kr6->labelid = rtlabel_name2id(kf->label); 1721 1722 if ((kr6m = RB_INSERT(kroute6_tree, &kt->krt6, kr6)) != NULL) { 1723 /* multipath route, add at end of list */ 1724 while (kr6m->next != NULL) 1725 kr6m = kr6m->next; 1726 kr6m->next = kr6; 1727 multipath = 1; 1728 } 1729 1730 if (kf->flags & F_BGPD) 1731 if (send_rtmsg(RTM_ADD, kt, kf)) 1732 kr6->flags |= F_BGPD_INSERTED; 1733 break; 1734 } 1735 1736 if (bgpd_has_bgpnh() || !(kf->flags & F_BGPD)) { 1737 RB_FOREACH(n, knexthop_tree, KT2KNT(kt)) 1738 if (prefix_compare(&kf->prefix, &n->nexthop, 1739 kf->prefixlen) == 0) 1740 knexthop_validate(kt, n); 1741 } 1742 1743 if (!(kf->flags & F_BGPD)) { 1744 /* redistribute multipath routes only once */ 1745 if (!multipath) 1746 kr_redistribute(IMSG_NETWORK_ADD, kt, kf); 1747 } 1748 1749 return (0); 1750 } 1751 1752 1753 static int 1754 kroute4_remove(struct ktable *kt, struct kroute_full *kf, int any) 1755 { 1756 struct kroute *kr, *krm; 1757 struct knexthop *n; 1758 int multipath = 1; 1759 1760 if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen, 1761 kf->priority)) == NULL) 1762 return (-1); 1763 1764 if ((kr->flags & F_BGPD) != (kf->flags & F_BGPD)) { 1765 log_warnx("%s: wrong type for %s/%u", __func__, 1766 log_addr(&kf->prefix), kf->prefixlen); 1767 if (!(kf->flags & F_BGPD)) 1768 kr->flags &= ~F_BGPD_INSERTED; 1769 return (-1); 1770 } 1771 1772 /* get the correct route to remove */ 1773 krm = kr; 1774 if (!any) { 1775 if ((krm = kroute_matchgw(kr, kf)) == NULL) { 1776 log_warnx("delete %s/%u: route not found", 1777 log_addr(&kf->prefix), kf->prefixlen); 1778 return (-2); 1779 } 1780 } 1781 1782 if (krm == kr) { 1783 /* head element */ 1784 RB_REMOVE(kroute_tree, &kt->krt, krm); 1785 if (krm->next != NULL) { 1786 kr = krm->next; 1787 if (RB_INSERT(kroute_tree, &kt->krt, kr) != NULL) { 1788 log_warnx("%s: failed to add %s/%u", 1789 __func__, inet_ntoa(kr->prefix), 1790 kr->prefixlen); 1791 return (-2); 1792 } 1793 } else { 1794 multipath = 0; 1795 } 1796 } else { 1797 /* somewhere in the list */ 1798 while (kr->next != krm && kr->next != NULL) 1799 kr = kr->next; 1800 if (kr->next == NULL) { 1801 log_warnx("%s: multipath list corrupted for %s/%u", 1802 __func__, inet_ntoa(kr->prefix), kr->prefixlen); 1803 return (-2); 1804 } 1805 kr->next = krm->next; 1806 } 1807 1808 /* check whether a nexthop depends on this kroute */ 1809 if (krm->flags & F_NEXTHOP) { 1810 RB_FOREACH(n, knexthop_tree, KT2KNT(kt)) { 1811 if (n->kroute == krm) 1812 knexthop_validate(kt, n); 1813 } 1814 } 1815 1816 *kf = *kr_tofull(krm); 1817 1818 rtlabel_unref(krm->labelid); 1819 free(krm); 1820 return (multipath); 1821 } 1822 1823 static int 1824 kroute6_remove(struct ktable *kt, struct kroute_full *kf, int any) 1825 { 1826 struct kroute6 *kr, *krm; 1827 struct knexthop *n; 1828 int multipath = 1; 1829 1830 if ((kr = kroute6_find(kt, &kf->prefix, kf->prefixlen, 1831 kf->priority)) == NULL) 1832 return (-1); 1833 1834 if ((kr->flags & F_BGPD) != (kf->flags & F_BGPD)) { 1835 log_warnx("%s: wrong type for %s/%u", __func__, 1836 log_addr(&kf->prefix), kf->prefixlen); 1837 if (!(kf->flags & F_BGPD)) 1838 kr->flags &= ~F_BGPD_INSERTED; 1839 return (-1); 1840 } 1841 1842 /* get the correct route to remove */ 1843 krm = kr; 1844 if (!any) { 1845 if ((krm = kroute6_matchgw(kr, kf)) == NULL) { 1846 log_warnx("delete %s/%u: route not found", 1847 log_addr(&kf->prefix), kf->prefixlen); 1848 return (-2); 1849 } 1850 } 1851 1852 if (krm == kr) { 1853 /* head element */ 1854 RB_REMOVE(kroute6_tree, &kt->krt6, krm); 1855 if (krm->next != NULL) { 1856 kr = krm->next; 1857 if (RB_INSERT(kroute6_tree, &kt->krt6, kr) != NULL) { 1858 log_warnx("%s: failed to add %s/%u", __func__, 1859 log_in6addr(&kr->prefix), kr->prefixlen); 1860 return (-2); 1861 } 1862 } else { 1863 multipath = 0; 1864 } 1865 } else { 1866 /* somewhere in the list */ 1867 while (kr->next != krm && kr->next != NULL) 1868 kr = kr->next; 1869 if (kr->next == NULL) { 1870 log_warnx("%s: multipath list corrupted for %s/%u", 1871 __func__, log_in6addr(&kr->prefix), kr->prefixlen); 1872 return (-2); 1873 } 1874 kr->next = krm->next; 1875 } 1876 1877 /* check whether a nexthop depends on this kroute */ 1878 if (krm->flags & F_NEXTHOP) { 1879 RB_FOREACH(n, knexthop_tree, KT2KNT(kt)) { 1880 if (n->kroute == krm) 1881 knexthop_validate(kt, n); 1882 } 1883 } 1884 1885 *kf = *kr6_tofull(krm); 1886 1887 rtlabel_unref(krm->labelid); 1888 free(krm); 1889 return (multipath); 1890 } 1891 1892 1893 int 1894 kroute_remove(struct ktable *kt, struct kroute_full *kf, int any) 1895 { 1896 int multipath; 1897 1898 switch (kf->prefix.aid) { 1899 case AID_INET: 1900 case AID_VPN_IPv4: 1901 multipath = kroute4_remove(kt, kf, any); 1902 break; 1903 case AID_INET6: 1904 case AID_VPN_IPv6: 1905 multipath = kroute6_remove(kt, kf, any); 1906 break; 1907 case AID_EVPN: 1908 /* XXX ignored for now */ 1909 return (0); 1910 default: 1911 log_warnx("%s: not handled AID", __func__); 1912 return (-1); 1913 } 1914 1915 if (multipath < 0) 1916 return (multipath + 1); 1917 1918 if (kf->flags & F_BGPD_INSERTED) 1919 send_rtmsg(RTM_DELETE, kt, kf); 1920 1921 /* remove only once all multipath routes are gone */ 1922 if (!(kf->flags & F_BGPD) && !multipath) 1923 kr_redistribute(IMSG_NETWORK_REMOVE, kt, kf); 1924 1925 return (0); 1926 } 1927 1928 void 1929 kroute_clear(struct ktable *kt) 1930 { 1931 struct kroute *kr; 1932 1933 while ((kr = RB_MIN(kroute_tree, &kt->krt)) != NULL) 1934 kroute_remove(kt, kr_tofull(kr), 1); 1935 } 1936 1937 struct kroute6 * 1938 kroute6_find(struct ktable *kt, const struct bgpd_addr *prefix, 1939 uint8_t prefixlen, uint8_t prio) 1940 { 1941 struct kroute6 s; 1942 struct kroute6 *kn6, *tmp; 1943 1944 s.prefix = prefix->v6; 1945 s.prefix_scope_id = prefix->scope_id; 1946 s.prefixlen = prefixlen; 1947 s.priority = prio; 1948 1949 kn6 = RB_FIND(kroute6_tree, &kt->krt6, &s); 1950 if (kn6 && prio == RTP_ANY) { 1951 tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); 1952 while (tmp) { 1953 if (kroute6_compare(&s, tmp) == 0) 1954 kn6 = tmp; 1955 else 1956 break; 1957 tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); 1958 } 1959 } 1960 return (kn6); 1961 } 1962 1963 struct kroute6 * 1964 kroute6_matchgw(struct kroute6 *kr, struct kroute_full *kf) 1965 { 1966 struct in6_addr nexthop; 1967 1968 if (kf->flags & F_CONNECTED) { 1969 do { 1970 if (kr->ifindex == kf->ifindex) 1971 return (kr); 1972 kr = kr->next; 1973 } while (kr); 1974 return (NULL); 1975 } 1976 1977 nexthop = kf->nexthop.v6; 1978 do { 1979 if (memcmp(&kr->nexthop, &nexthop, sizeof(nexthop)) == 0 && 1980 kr->nexthop_scope_id == kf->nexthop.scope_id) 1981 return (kr); 1982 kr = kr->next; 1983 } while (kr); 1984 1985 return (NULL); 1986 } 1987 1988 void 1989 kroute6_clear(struct ktable *kt) 1990 { 1991 struct kroute6 *kr; 1992 1993 while ((kr = RB_MIN(kroute6_tree, &kt->krt6)) != NULL) 1994 kroute_remove(kt, kr6_tofull(kr), 1); 1995 } 1996 1997 struct knexthop * 1998 knexthop_find(struct ktable *kt, struct bgpd_addr *addr) 1999 { 2000 struct knexthop s; 2001 2002 memset(&s, 0, sizeof(s)); 2003 memcpy(&s.nexthop, addr, sizeof(s.nexthop)); 2004 2005 return (RB_FIND(knexthop_tree, KT2KNT(kt), &s)); 2006 } 2007 2008 int 2009 knexthop_insert(struct ktable *kt, struct knexthop *kn) 2010 { 2011 if (RB_INSERT(knexthop_tree, KT2KNT(kt), kn) != NULL) { 2012 log_warnx("%s: failed for %s", __func__, 2013 log_addr(&kn->nexthop)); 2014 free(kn); 2015 return (-1); 2016 } 2017 2018 knexthop_validate(kt, kn); 2019 2020 return (0); 2021 } 2022 2023 void 2024 knexthop_remove(struct ktable *kt, struct knexthop *kn) 2025 { 2026 kroute_detach_nexthop(kt, kn); 2027 RB_REMOVE(knexthop_tree, KT2KNT(kt), kn); 2028 free(kn); 2029 } 2030 2031 void 2032 knexthop_clear(struct ktable *kt) 2033 { 2034 struct knexthop *kn; 2035 2036 while ((kn = RB_MIN(knexthop_tree, KT2KNT(kt))) != NULL) 2037 knexthop_remove(kt, kn); 2038 } 2039 2040 struct kif * 2041 kif_find(int ifindex) 2042 { 2043 struct kif s; 2044 2045 memset(&s, 0, sizeof(s)); 2046 s.ifindex = ifindex; 2047 2048 return (RB_FIND(kif_tree, &kit, &s)); 2049 } 2050 2051 int 2052 kif_insert(struct kif *kif) 2053 { 2054 if (RB_INSERT(kif_tree, &kit, kif) != NULL) { 2055 log_warnx("RB_INSERT(kif_tree, &kit, kif)"); 2056 free(kif); 2057 return (-1); 2058 } 2059 2060 return (0); 2061 } 2062 2063 int 2064 kif_remove(struct kif *kif) 2065 { 2066 struct ktable *kt; 2067 2068 kif->flags &= ~IFF_UP; 2069 2070 /* 2071 * TODO, remove all kroutes using this interface, 2072 * the kernel does this for us but better to do it 2073 * here as well. 2074 */ 2075 2076 if ((kt = ktable_get(kif->rdomain)) != NULL) 2077 knexthop_track(kt, kif->ifindex); 2078 2079 RB_REMOVE(kif_tree, &kit, kif); 2080 free(kif); 2081 return (0); 2082 } 2083 2084 void 2085 kif_clear(void) 2086 { 2087 struct kif *kif; 2088 2089 while ((kif = RB_MIN(kif_tree, &kit)) != NULL) 2090 kif_remove(kif); 2091 } 2092 2093 /* 2094 * nexthop validation 2095 */ 2096 2097 static int 2098 kif_validate(struct kif *kif) 2099 { 2100 if (!(kif->flags & IFF_UP)) 2101 return (0); 2102 2103 /* 2104 * we treat link_state == LINK_STATE_UNKNOWN as valid, 2105 * not all interfaces have a concept of "link state" and/or 2106 * do not report up 2107 */ 2108 2109 if (kif->link_state == LINK_STATE_DOWN) 2110 return (0); 2111 2112 return (1); 2113 } 2114 2115 /* 2116 * return 1 when the interface is up and the link state is up or unknown 2117 * except when this is a carp interface, then return 1 only when link state 2118 * is up 2119 */ 2120 static int 2121 kif_depend_state(struct kif *kif) 2122 { 2123 if (!(kif->flags & IFF_UP)) 2124 return (0); 2125 2126 if (kif->if_type == IFT_CARP && 2127 kif->link_state == LINK_STATE_UNKNOWN) 2128 return (0); 2129 2130 return LINK_STATE_IS_UP(kif->link_state); 2131 } 2132 2133 int 2134 kroute_validate(struct kroute *kr) 2135 { 2136 struct kif *kif; 2137 2138 if (kr->flags & (F_REJECT | F_BLACKHOLE)) 2139 return (0); 2140 2141 if ((kif = kif_find(kr->ifindex)) == NULL) { 2142 if (kr->ifindex) 2143 log_warnx("%s: interface with index %d not found, " 2144 "referenced from route for %s/%u", __func__, 2145 kr->ifindex, inet_ntoa(kr->prefix), 2146 kr->prefixlen); 2147 return (1); 2148 } 2149 2150 return (kif->nh_reachable); 2151 } 2152 2153 int 2154 kroute6_validate(struct kroute6 *kr) 2155 { 2156 struct kif *kif; 2157 2158 if (kr->flags & (F_REJECT | F_BLACKHOLE)) 2159 return (0); 2160 2161 if ((kif = kif_find(kr->ifindex)) == NULL) { 2162 if (kr->ifindex) 2163 log_warnx("%s: interface with index %d not found, " 2164 "referenced from route for %s/%u", __func__, 2165 kr->ifindex, log_in6addr(&kr->prefix), 2166 kr->prefixlen); 2167 return (1); 2168 } 2169 2170 return (kif->nh_reachable); 2171 } 2172 2173 int 2174 knexthop_true_nexthop(struct ktable *kt, struct kroute_full *kf) 2175 { 2176 struct bgpd_addr gateway = { 0 }; 2177 struct knexthop *kn; 2178 struct kroute *kr; 2179 struct kroute6 *kr6; 2180 2181 /* 2182 * Ignore the nexthop for VPN routes. The gateway is forced 2183 * to an mpe(4) interface route using an MPLS label. 2184 */ 2185 switch (kf->prefix.aid) { 2186 case AID_VPN_IPv4: 2187 case AID_VPN_IPv6: 2188 return 1; 2189 } 2190 2191 kn = knexthop_find(kt, &kf->nexthop); 2192 if (kn == NULL) { 2193 log_warnx("%s: nexthop %s not found", __func__, 2194 log_addr(&kf->nexthop)); 2195 return 0; 2196 } 2197 if (kn->kroute == NULL) 2198 return 0; 2199 2200 switch (kn->nexthop.aid) { 2201 case AID_INET: 2202 kr = kn->kroute; 2203 if (kr->flags & F_CONNECTED) 2204 return 1; 2205 gateway.aid = AID_INET; 2206 gateway.v4.s_addr = kr->nexthop.s_addr; 2207 break; 2208 case AID_INET6: 2209 kr6 = kn->kroute; 2210 if (kr6->flags & F_CONNECTED) 2211 return 1; 2212 gateway.aid = AID_INET6; 2213 gateway.v6 = kr6->nexthop; 2214 gateway.scope_id = kr6->nexthop_scope_id; 2215 break; 2216 } 2217 2218 kf->nexthop = gateway; 2219 return 1; 2220 } 2221 2222 void 2223 knexthop_validate(struct ktable *kt, struct knexthop *kn) 2224 { 2225 void *oldk; 2226 struct kroute *kr; 2227 struct kroute6 *kr6; 2228 2229 oldk = kn->kroute; 2230 kroute_detach_nexthop(kt, kn); 2231 2232 if ((kt = ktable_get(kt->nhtableid)) == NULL) 2233 fatalx("%s: lost nexthop routing table", __func__); 2234 2235 switch (kn->nexthop.aid) { 2236 case AID_INET: 2237 kr = kroute_match(kt, &kn->nexthop, 0); 2238 2239 if (kr != NULL) { 2240 kn->kroute = kr; 2241 kn->ifindex = kr->ifindex; 2242 kr->flags |= F_NEXTHOP; 2243 } 2244 2245 /* 2246 * Send update if nexthop route changed under us if 2247 * the route remains the same then the NH state has not 2248 * changed. 2249 */ 2250 if (kr != oldk) 2251 knexthop_send_update(kn); 2252 break; 2253 case AID_INET6: 2254 kr6 = kroute6_match(kt, &kn->nexthop, 0); 2255 2256 if (kr6 != NULL) { 2257 kn->kroute = kr6; 2258 kn->ifindex = kr6->ifindex; 2259 kr6->flags |= F_NEXTHOP; 2260 } 2261 2262 if (kr6 != oldk) 2263 knexthop_send_update(kn); 2264 break; 2265 } 2266 } 2267 2268 /* 2269 * Called on interface state change. 2270 */ 2271 void 2272 knexthop_track(struct ktable *kt, u_short ifindex) 2273 { 2274 struct knexthop *kn; 2275 2276 RB_FOREACH(kn, knexthop_tree, KT2KNT(kt)) 2277 if (kn->ifindex == ifindex) 2278 knexthop_validate(kt, kn); 2279 } 2280 2281 /* 2282 * Called on route change. 2283 */ 2284 void 2285 knexthop_update(struct ktable *kt, struct kroute_full *kf) 2286 { 2287 struct knexthop *kn; 2288 2289 RB_FOREACH(kn, knexthop_tree, KT2KNT(kt)) 2290 if (prefix_compare(&kf->prefix, &kn->nexthop, 2291 kf->prefixlen) == 0) 2292 knexthop_send_update(kn); 2293 } 2294 2295 void 2296 knexthop_send_update(struct knexthop *kn) 2297 { 2298 struct kroute_nexthop n; 2299 struct kroute *kr; 2300 struct kroute6 *kr6; 2301 2302 memset(&n, 0, sizeof(n)); 2303 n.nexthop = kn->nexthop; 2304 2305 if (kn->kroute == NULL) { 2306 n.valid = 0; /* NH is not valid */ 2307 send_nexthop_update(&n); 2308 return; 2309 } 2310 2311 switch (kn->nexthop.aid) { 2312 case AID_INET: 2313 kr = kn->kroute; 2314 n.valid = kroute_validate(kr); 2315 n.connected = kr->flags & F_CONNECTED; 2316 if (!n.connected) { 2317 n.gateway.aid = AID_INET; 2318 n.gateway.v4.s_addr = kr->nexthop.s_addr; 2319 } else { 2320 n.gateway = n.nexthop; 2321 n.net.aid = AID_INET; 2322 n.net.v4.s_addr = kr->prefix.s_addr; 2323 n.netlen = kr->prefixlen; 2324 } 2325 break; 2326 case AID_INET6: 2327 kr6 = kn->kroute; 2328 n.valid = kroute6_validate(kr6); 2329 n.connected = kr6->flags & F_CONNECTED; 2330 if (!n.connected) { 2331 n.gateway.aid = AID_INET6; 2332 n.gateway.v6 = kr6->nexthop; 2333 n.gateway.scope_id = kr6->nexthop_scope_id; 2334 } else { 2335 n.gateway = n.nexthop; 2336 n.net.aid = AID_INET6; 2337 n.net.v6 = kr6->prefix; 2338 n.net.scope_id = kr6->prefix_scope_id; 2339 n.netlen = kr6->prefixlen; 2340 } 2341 break; 2342 } 2343 send_nexthop_update(&n); 2344 } 2345 2346 struct kroute * 2347 kroute_match(struct ktable *kt, struct bgpd_addr *key, int matchany) 2348 { 2349 int i; 2350 struct kroute *kr; 2351 struct bgpd_addr masked; 2352 2353 for (i = 32; i >= 0; i--) { 2354 applymask(&masked, key, i); 2355 if ((kr = kroute_find(kt, &masked, i, RTP_ANY)) != NULL) 2356 if (matchany || bgpd_oknexthop(kr_tofull(kr))) 2357 return (kr); 2358 } 2359 2360 return (NULL); 2361 } 2362 2363 struct kroute6 * 2364 kroute6_match(struct ktable *kt, struct bgpd_addr *key, int matchany) 2365 { 2366 int i; 2367 struct kroute6 *kr6; 2368 struct bgpd_addr masked; 2369 2370 for (i = 128; i >= 0; i--) { 2371 applymask(&masked, key, i); 2372 if ((kr6 = kroute6_find(kt, &masked, i, RTP_ANY)) != NULL) 2373 if (matchany || bgpd_oknexthop(kr6_tofull(kr6))) 2374 return (kr6); 2375 } 2376 2377 return (NULL); 2378 } 2379 2380 void 2381 kroute_detach_nexthop(struct ktable *kt, struct knexthop *kn) 2382 { 2383 struct knexthop *s; 2384 struct kroute *k; 2385 struct kroute6 *k6; 2386 2387 if (kn->kroute == NULL) 2388 return; 2389 2390 /* 2391 * check whether there's another nexthop depending on this kroute 2392 * if not remove the flag 2393 */ 2394 RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) 2395 if (s->kroute == kn->kroute && s != kn) 2396 break; 2397 2398 if (s == NULL) { 2399 switch (kn->nexthop.aid) { 2400 case AID_INET: 2401 k = kn->kroute; 2402 k->flags &= ~F_NEXTHOP; 2403 break; 2404 case AID_INET6: 2405 k6 = kn->kroute; 2406 k6->flags &= ~F_NEXTHOP; 2407 break; 2408 } 2409 } 2410 2411 kn->kroute = NULL; 2412 kn->ifindex = 0; 2413 } 2414 2415 /* 2416 * misc helpers 2417 */ 2418 2419 uint8_t 2420 prefixlen_classful(in_addr_t ina) 2421 { 2422 /* it hurt to write this. */ 2423 2424 if (ina >= 0xf0000000U) /* class E */ 2425 return (32); 2426 else if (ina >= 0xe0000000U) /* class D */ 2427 return (4); 2428 else if (ina >= 0xc0000000U) /* class C */ 2429 return (24); 2430 else if (ina >= 0x80000000U) /* class B */ 2431 return (16); 2432 else /* class A */ 2433 return (8); 2434 } 2435 2436 static uint8_t 2437 mask2prefixlen4(struct sockaddr_in *sa_in) 2438 { 2439 in_addr_t ina; 2440 2441 ina = sa_in->sin_addr.s_addr; 2442 if (ina == 0) 2443 return (0); 2444 else 2445 return (33 - ffs(ntohl(ina))); 2446 } 2447 2448 static uint8_t 2449 mask2prefixlen6(struct sockaddr_in6 *sa_in6) 2450 { 2451 uint8_t *ap, *ep; 2452 u_int l = 0; 2453 2454 /* 2455 * sin6_len is the size of the sockaddr so subtract the offset of 2456 * the possibly truncated sin6_addr struct. 2457 */ 2458 ap = (uint8_t *)&sa_in6->sin6_addr; 2459 ep = (uint8_t *)sa_in6 + sa_in6->sin6_len; 2460 for (; ap < ep; ap++) { 2461 /* this "beauty" is adopted from sbin/route/show.c ... */ 2462 switch (*ap) { 2463 case 0xff: 2464 l += 8; 2465 break; 2466 case 0xfe: 2467 l += 7; 2468 goto done; 2469 case 0xfc: 2470 l += 6; 2471 goto done; 2472 case 0xf8: 2473 l += 5; 2474 goto done; 2475 case 0xf0: 2476 l += 4; 2477 goto done; 2478 case 0xe0: 2479 l += 3; 2480 goto done; 2481 case 0xc0: 2482 l += 2; 2483 goto done; 2484 case 0x80: 2485 l += 1; 2486 goto done; 2487 case 0x00: 2488 goto done; 2489 default: 2490 fatalx("non contiguous inet6 netmask"); 2491 } 2492 } 2493 2494 done: 2495 if (l > sizeof(struct in6_addr) * 8) 2496 fatalx("%s: prefixlen %d out of bound", __func__, l); 2497 return (l); 2498 } 2499 2500 uint8_t 2501 mask2prefixlen(sa_family_t af, struct sockaddr *mask) 2502 { 2503 switch (af) { 2504 case AF_INET: 2505 return mask2prefixlen4((struct sockaddr_in *)mask); 2506 case AF_INET6: 2507 return mask2prefixlen6((struct sockaddr_in6 *)mask); 2508 default: 2509 fatalx("%s: unsupported af", __func__); 2510 } 2511 } 2512 2513 const struct if_status_description 2514 if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; 2515 const struct ifmedia_description 2516 ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 2517 2518 uint64_t 2519 ift2ifm(uint8_t if_type) 2520 { 2521 switch (if_type) { 2522 case IFT_ETHER: 2523 return (IFM_ETHER); 2524 case IFT_FDDI: 2525 return (IFM_FDDI); 2526 case IFT_CARP: 2527 return (IFM_CARP); 2528 case IFT_IEEE80211: 2529 return (IFM_IEEE80211); 2530 default: 2531 return (0); 2532 } 2533 } 2534 2535 const char * 2536 get_media_descr(uint64_t media_type) 2537 { 2538 const struct ifmedia_description *p; 2539 2540 for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 2541 if (media_type == p->ifmt_word) 2542 return (p->ifmt_string); 2543 2544 return ("unknown media"); 2545 } 2546 2547 const char * 2548 get_linkstate(uint8_t if_type, int link_state) 2549 { 2550 const struct if_status_description *p; 2551 static char buf[8]; 2552 2553 for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 2554 if (LINK_STATE_DESC_MATCH(p, if_type, link_state)) 2555 return (p->ifs_string); 2556 } 2557 snprintf(buf, sizeof(buf), "[#%d]", link_state); 2558 return (buf); 2559 } 2560 2561 #define ROUNDUP(a) \ 2562 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 2563 2564 void 2565 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 2566 { 2567 int i; 2568 2569 for (i = 0; i < RTAX_MAX; i++) { 2570 if (addrs & (1 << i)) { 2571 rti_info[i] = sa; 2572 sa = (struct sockaddr *)((char *)(sa) + 2573 ROUNDUP(sa->sa_len)); 2574 } else 2575 rti_info[i] = NULL; 2576 } 2577 } 2578 2579 void 2580 if_change(u_short ifindex, int flags, struct if_data *ifd) 2581 { 2582 struct ktable *kt; 2583 struct kif *kif; 2584 uint8_t reachable; 2585 2586 if ((kif = kif_find(ifindex)) == NULL) { 2587 log_warnx("%s: interface with index %u not found", 2588 __func__, ifindex); 2589 return; 2590 } 2591 2592 log_info("%s: %s: rdomain %u %s, %s, %s, %s", 2593 __func__, kif->ifname, ifd->ifi_rdomain, 2594 flags & IFF_UP ? "UP" : "DOWN", 2595 get_media_descr(ift2ifm(ifd->ifi_type)), 2596 get_linkstate(ifd->ifi_type, ifd->ifi_link_state), 2597 get_baudrate(ifd->ifi_baudrate, "bps")); 2598 2599 kif->flags = flags; 2600 kif->link_state = ifd->ifi_link_state; 2601 kif->if_type = ifd->ifi_type; 2602 kif->rdomain = ifd->ifi_rdomain; 2603 kif->baudrate = ifd->ifi_baudrate; 2604 kif->depend_state = kif_depend_state(kif); 2605 2606 kr_send_dependon(kif); 2607 2608 if ((reachable = kif_validate(kif)) == kif->nh_reachable) 2609 return; /* nothing changed wrt nexthop validity */ 2610 2611 kif->nh_reachable = reachable; 2612 2613 kt = ktable_get(kif->rdomain); 2614 if (kt == NULL) 2615 return; 2616 2617 knexthop_track(kt, ifindex); 2618 } 2619 2620 void 2621 if_announce(void *msg) 2622 { 2623 struct if_announcemsghdr *ifan; 2624 struct kif *kif; 2625 2626 ifan = msg; 2627 2628 switch (ifan->ifan_what) { 2629 case IFAN_ARRIVAL: 2630 if ((kif = calloc(1, sizeof(*kif))) == NULL) { 2631 log_warn("%s", __func__); 2632 return; 2633 } 2634 2635 kif->ifindex = ifan->ifan_index; 2636 strlcpy(kif->ifname, ifan->ifan_name, sizeof(kif->ifname)); 2637 kif_insert(kif); 2638 break; 2639 case IFAN_DEPARTURE: 2640 kif = kif_find(ifan->ifan_index); 2641 if (kif != NULL) 2642 kif_remove(kif); 2643 break; 2644 } 2645 } 2646 2647 int 2648 get_mpe_config(const char *name, u_int *rdomain, u_int *label) 2649 { 2650 struct ifreq ifr; 2651 struct shim_hdr shim; 2652 int s; 2653 2654 *label = 0; 2655 *rdomain = 0; 2656 2657 s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); 2658 if (s == -1) 2659 return (-1); 2660 2661 memset(&shim, 0, sizeof(shim)); 2662 memset(&ifr, 0, sizeof(ifr)); 2663 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2664 ifr.ifr_data = (caddr_t)&shim; 2665 2666 if (ioctl(s, SIOCGETLABEL, (caddr_t)&ifr) == -1) { 2667 close(s); 2668 return (-1); 2669 } 2670 2671 ifr.ifr_data = NULL; 2672 if (ioctl(s, SIOCGIFRDOMAIN, (caddr_t)&ifr) == -1) { 2673 close(s); 2674 return (-1); 2675 } 2676 2677 close(s); 2678 2679 *rdomain = ifr.ifr_rdomainid; 2680 *label = shim.shim_label; 2681 2682 return (0); 2683 } 2684 2685 /* 2686 * rtsock related functions 2687 */ 2688 #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) 2689 2690 int 2691 send_rtmsg(int action, struct ktable *kt, struct kroute_full *kf) 2692 { 2693 struct iovec iov[7]; 2694 struct rt_msghdr hdr; 2695 struct sockaddr_storage prefix, nexthop, mask, ifp, label, mpls; 2696 struct bgpd_addr netmask; 2697 struct sockaddr *sa; 2698 struct sockaddr_dl *dl; 2699 struct sockaddr_mpls *mp; 2700 struct sockaddr_rtlabel *la; 2701 socklen_t salen; 2702 int iovcnt = 0; 2703 2704 if (!kt->fib_sync) 2705 return (0); 2706 2707 /* initialize header */ 2708 memset(&hdr, 0, sizeof(hdr)); 2709 hdr.rtm_version = RTM_VERSION; 2710 hdr.rtm_type = action; 2711 hdr.rtm_tableid = kt->rtableid; 2712 hdr.rtm_priority = kr_state.fib_prio; 2713 if (kf->flags & F_BLACKHOLE) 2714 hdr.rtm_flags |= RTF_BLACKHOLE; 2715 if (kf->flags & F_REJECT) 2716 hdr.rtm_flags |= RTF_REJECT; 2717 if (action == RTM_CHANGE) /* reset these flags on change */ 2718 hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE; 2719 hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ 2720 hdr.rtm_msglen = sizeof(hdr); 2721 /* adjust iovec */ 2722 iov[iovcnt].iov_base = &hdr; 2723 iov[iovcnt++].iov_len = sizeof(hdr); 2724 2725 memset(&prefix, 0, sizeof(prefix)); 2726 sa = addr2sa(&kf->prefix, 0, &salen); 2727 sa->sa_len = salen; 2728 #ifdef __KAME__ 2729 /* XXX need to embed the stupid scope for now */ 2730 if (sa->sa_family == AF_INET6 && 2731 (IN6_IS_ADDR_LINKLOCAL(&satosin6(sa)->sin6_addr) || 2732 IN6_IS_ADDR_MC_LINKLOCAL(&satosin6(sa)->sin6_addr) || 2733 IN6_IS_ADDR_MC_NODELOCAL(&satosin6(sa)->sin6_addr))) { 2734 *(u_int16_t *)&satosin6(sa)->sin6_addr.s6_addr[2] = 2735 htons(satosin6(sa)->sin6_scope_id); 2736 satosin6(sa)->sin6_scope_id = 0; 2737 } 2738 #endif 2739 memcpy(&prefix, sa, salen); 2740 /* adjust header */ 2741 hdr.rtm_addrs |= RTA_DST; 2742 hdr.rtm_msglen += ROUNDUP(salen); 2743 /* adjust iovec */ 2744 iov[iovcnt].iov_base = &prefix; 2745 iov[iovcnt++].iov_len = ROUNDUP(salen); 2746 2747 /* XXX can we even have no nexthop ??? */ 2748 if (kf->nexthop.aid != AID_UNSPEC) { 2749 memset(&nexthop, 0, sizeof(nexthop)); 2750 sa = addr2sa(&kf->nexthop, 0, &salen); 2751 sa->sa_len = salen; 2752 #ifdef __KAME__ 2753 /* XXX need to embed the stupid scope for now */ 2754 if (sa->sa_family == AF_INET6 && 2755 (IN6_IS_ADDR_LINKLOCAL(&satosin6(sa)->sin6_addr) || 2756 IN6_IS_ADDR_MC_LINKLOCAL(&satosin6(sa)->sin6_addr) || 2757 IN6_IS_ADDR_MC_NODELOCAL(&satosin6(sa)->sin6_addr))) { 2758 *(u_int16_t *)&satosin6(sa)->sin6_addr.s6_addr[2] = 2759 htons(satosin6(sa)->sin6_scope_id); 2760 satosin6(sa)->sin6_scope_id = 0; 2761 } 2762 #endif 2763 memcpy(&nexthop, sa, salen); 2764 /* adjust header */ 2765 hdr.rtm_flags |= RTF_GATEWAY; 2766 hdr.rtm_addrs |= RTA_GATEWAY; 2767 hdr.rtm_msglen += ROUNDUP(salen); 2768 /* adjust iovec */ 2769 iov[iovcnt].iov_base = &nexthop; 2770 iov[iovcnt++].iov_len = ROUNDUP(salen); 2771 } 2772 2773 memset(&netmask, 0, sizeof(netmask)); 2774 memset(&netmask.v6, 0xff, sizeof(netmask.v6)); 2775 netmask.aid = kf->prefix.aid; 2776 applymask(&netmask, &netmask, kf->prefixlen); 2777 memset(&mask, 0, sizeof(mask)); 2778 sa = addr2sa(&netmask, 0, &salen); 2779 sa->sa_len = salen; 2780 memcpy(&mask, sa, salen); 2781 /* adjust header */ 2782 hdr.rtm_addrs |= RTA_NETMASK; 2783 hdr.rtm_msglen += ROUNDUP(salen); 2784 /* adjust iovec */ 2785 iov[iovcnt].iov_base = &mask; 2786 iov[iovcnt++].iov_len = ROUNDUP(salen); 2787 2788 if (kf->flags & F_MPLS) { 2789 /* need to force interface for mpe(4) routes */ 2790 memset(&ifp, 0, sizeof(ifp)); 2791 dl = (struct sockaddr_dl *)&ifp; 2792 salen = sizeof(*dl); 2793 dl->sdl_len = salen; 2794 dl->sdl_family = AF_LINK; 2795 dl->sdl_index = kf->ifindex; 2796 /* adjust header */ 2797 hdr.rtm_addrs |= RTA_IFP; 2798 hdr.rtm_msglen += ROUNDUP(salen); 2799 /* adjust iovec */ 2800 iov[iovcnt].iov_base = &ifp; 2801 iov[iovcnt++].iov_len = ROUNDUP(salen); 2802 2803 memset(&mpls, 0, sizeof(mpls)); 2804 mp = (struct sockaddr_mpls *)&mpls; 2805 salen = sizeof(*mp); 2806 mp->smpls_len = salen; 2807 mp->smpls_family = AF_MPLS; 2808 mp->smpls_label = kf->mplslabel; 2809 /* adjust header */ 2810 hdr.rtm_flags |= RTF_MPLS; 2811 hdr.rtm_mpls = MPLS_OP_PUSH; 2812 hdr.rtm_addrs |= RTA_SRC; 2813 hdr.rtm_msglen += ROUNDUP(salen); 2814 /* clear gateway flag since this is for mpe(4) */ 2815 hdr.rtm_flags &= ~RTF_GATEWAY; 2816 /* adjust iovec */ 2817 iov[iovcnt].iov_base = &mpls; 2818 iov[iovcnt++].iov_len = ROUNDUP(salen); 2819 } 2820 2821 if (kf->label[0] != '\0') { 2822 memset(&label, 0, sizeof(label)); 2823 la = (struct sockaddr_rtlabel *)&label; 2824 salen = sizeof(struct sockaddr_rtlabel); 2825 label.ss_len = salen; 2826 strlcpy(la->sr_label, kf->label, sizeof(la->sr_label)); 2827 /* adjust header */ 2828 hdr.rtm_addrs |= RTA_LABEL; 2829 hdr.rtm_msglen += ROUNDUP(salen); 2830 /* adjust iovec */ 2831 iov[iovcnt].iov_base = &label; 2832 iov[iovcnt++].iov_len = ROUNDUP(salen); 2833 } 2834 2835 retry: 2836 if (writev(kr_state.fd, iov, iovcnt) == -1) { 2837 if (errno == ESRCH) { 2838 if (hdr.rtm_type == RTM_CHANGE) { 2839 hdr.rtm_type = RTM_ADD; 2840 goto retry; 2841 } else if (hdr.rtm_type == RTM_DELETE) { 2842 log_info("route %s/%u vanished before delete", 2843 log_addr(&kf->prefix), kf->prefixlen); 2844 return (1); 2845 } 2846 } 2847 log_warn("%s: action %u, prefix %s/%u", __func__, hdr.rtm_type, 2848 log_addr(&kf->prefix), kf->prefixlen); 2849 return (0); 2850 } 2851 2852 return (1); 2853 } 2854 2855 int 2856 fetchtable(struct ktable *kt) 2857 { 2858 size_t len; 2859 int mib[7]; 2860 char *buf = NULL, *next, *lim; 2861 struct rt_msghdr *rtm; 2862 struct kroute_full kf; 2863 2864 mib[0] = CTL_NET; 2865 mib[1] = PF_ROUTE; 2866 mib[2] = 0; 2867 mib[3] = 0; 2868 mib[4] = NET_RT_DUMP; 2869 mib[5] = 0; 2870 mib[6] = kt->rtableid; 2871 2872 if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { 2873 if (kt->rtableid != 0 && errno == EINVAL) 2874 /* table nonexistent */ 2875 return (0); 2876 log_warn("%s: sysctl", __func__); 2877 return (-1); 2878 } 2879 if (len > 0) { 2880 if ((buf = malloc(len)) == NULL) { 2881 log_warn("%s", __func__); 2882 return (-1); 2883 } 2884 if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { 2885 log_warn("%s: sysctl2", __func__); 2886 free(buf); 2887 return (-1); 2888 } 2889 } 2890 2891 lim = buf + len; 2892 for (next = buf; next < lim; next += rtm->rtm_msglen) { 2893 rtm = (struct rt_msghdr *)next; 2894 if (rtm->rtm_version != RTM_VERSION) 2895 continue; 2896 2897 if (dispatch_rtmsg_addr(rtm, &kf) == -1) 2898 continue; 2899 2900 if (kf.priority == RTP_MINE) 2901 send_rtmsg(RTM_DELETE, kt, &kf); 2902 else 2903 kroute_insert(kt, &kf); 2904 } 2905 free(buf); 2906 return (0); 2907 } 2908 2909 int 2910 fetchifs(int ifindex) 2911 { 2912 size_t len; 2913 int mib[6]; 2914 char *buf, *next, *lim; 2915 struct if_msghdr ifm; 2916 struct kif *kif; 2917 struct sockaddr *sa, *rti_info[RTAX_MAX]; 2918 struct sockaddr_dl *sdl; 2919 2920 mib[0] = CTL_NET; 2921 mib[1] = PF_ROUTE; 2922 mib[2] = 0; 2923 mib[3] = AF_INET; /* AF does not matter but AF_INET is shorter */ 2924 mib[4] = NET_RT_IFLIST; 2925 mib[5] = ifindex; 2926 2927 if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { 2928 log_warn("%s: sysctl", __func__); 2929 return (-1); 2930 } 2931 if ((buf = malloc(len)) == NULL) { 2932 log_warn("%s", __func__); 2933 return (-1); 2934 } 2935 if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) { 2936 log_warn("%s: sysctl2", __func__); 2937 free(buf); 2938 return (-1); 2939 } 2940 2941 lim = buf + len; 2942 for (next = buf; next < lim; next += ifm.ifm_msglen) { 2943 memcpy(&ifm, next, sizeof(ifm)); 2944 if (ifm.ifm_version != RTM_VERSION) 2945 continue; 2946 if (ifm.ifm_type != RTM_IFINFO) 2947 continue; 2948 2949 sa = (struct sockaddr *)(next + sizeof(ifm)); 2950 get_rtaddrs(ifm.ifm_addrs, sa, rti_info); 2951 2952 if ((kif = calloc(1, sizeof(*kif))) == NULL) { 2953 log_warn("%s", __func__); 2954 free(buf); 2955 return (-1); 2956 } 2957 2958 kif->ifindex = ifm.ifm_index; 2959 kif->flags = ifm.ifm_flags; 2960 kif->link_state = ifm.ifm_data.ifi_link_state; 2961 kif->if_type = ifm.ifm_data.ifi_type; 2962 kif->rdomain = ifm.ifm_data.ifi_rdomain; 2963 kif->baudrate = ifm.ifm_data.ifi_baudrate; 2964 kif->nh_reachable = kif_validate(kif); 2965 kif->depend_state = kif_depend_state(kif); 2966 2967 if ((sa = rti_info[RTAX_IFP]) != NULL) 2968 if (sa->sa_family == AF_LINK) { 2969 sdl = (struct sockaddr_dl *)sa; 2970 if (sdl->sdl_nlen >= sizeof(kif->ifname)) 2971 memcpy(kif->ifname, sdl->sdl_data, 2972 sizeof(kif->ifname) - 1); 2973 else if (sdl->sdl_nlen > 0) 2974 memcpy(kif->ifname, sdl->sdl_data, 2975 sdl->sdl_nlen); 2976 /* string already terminated via calloc() */ 2977 } 2978 2979 kif_insert(kif); 2980 } 2981 free(buf); 2982 return (0); 2983 } 2984 2985 int 2986 dispatch_rtmsg(void) 2987 { 2988 char buf[RT_BUF_SIZE]; 2989 ssize_t n; 2990 char *next, *lim; 2991 struct rt_msghdr *rtm; 2992 struct if_msghdr ifm; 2993 struct kroute_full kf; 2994 struct ktable *kt; 2995 int mpath = 0; 2996 2997 if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) { 2998 if (errno == EAGAIN || errno == EINTR) 2999 return (0); 3000 log_warn("%s: read error", __func__); 3001 return (-1); 3002 } 3003 3004 if (n == 0) { 3005 log_warnx("routing socket closed"); 3006 return (-1); 3007 } 3008 3009 lim = buf + n; 3010 for (next = buf; next < lim; next += rtm->rtm_msglen) { 3011 rtm = (struct rt_msghdr *)next; 3012 if (lim < next + sizeof(u_short) || 3013 lim < next + rtm->rtm_msglen) 3014 fatalx("%s: partial rtm in buffer", __func__); 3015 if (rtm->rtm_version != RTM_VERSION) 3016 continue; 3017 3018 switch (rtm->rtm_type) { 3019 case RTM_ADD: 3020 case RTM_CHANGE: 3021 case RTM_DELETE: 3022 if (rtm->rtm_pid == kr_state.pid) /* cause by us */ 3023 continue; 3024 3025 /* failed attempts */ 3026 if (rtm->rtm_errno || !(rtm->rtm_flags & RTF_DONE)) 3027 continue; 3028 3029 if ((kt = ktable_get(rtm->rtm_tableid)) == NULL) 3030 continue; 3031 3032 if (dispatch_rtmsg_addr(rtm, &kf) == -1) 3033 continue; 3034 3035 if (rtm->rtm_flags & RTF_MPATH) 3036 mpath = 1; 3037 3038 switch (rtm->rtm_type) { 3039 case RTM_ADD: 3040 case RTM_CHANGE: 3041 if (kr_fib_change(kt, &kf, rtm->rtm_type, 3042 mpath) == -1) 3043 return -1; 3044 break; 3045 case RTM_DELETE: 3046 if (kr_fib_delete(kt, &kf, mpath) == -1) 3047 return -1; 3048 break; 3049 } 3050 break; 3051 case RTM_IFINFO: 3052 memcpy(&ifm, next, sizeof(ifm)); 3053 if_change(ifm.ifm_index, ifm.ifm_flags, &ifm.ifm_data); 3054 break; 3055 case RTM_IFANNOUNCE: 3056 if_announce(next); 3057 break; 3058 default: 3059 /* ignore for now */ 3060 break; 3061 } 3062 } 3063 return (0); 3064 } 3065 3066 int 3067 dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct kroute_full *kf) 3068 { 3069 struct sockaddr *sa, *rti_info[RTAX_MAX]; 3070 struct sockaddr_in *sa_in; 3071 struct sockaddr_in6 *sa_in6; 3072 struct sockaddr_rtlabel *label; 3073 3074 sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen); 3075 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 3076 3077 /* Skip ARP/ND cache, broadcast and dynamic routes. */ 3078 if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST|RTF_DYNAMIC)) 3079 return (-1); 3080 3081 if ((sa = rti_info[RTAX_DST]) == NULL) { 3082 log_warnx("route message without destination"); 3083 return (-1); 3084 } 3085 3086 memset(kf, 0, sizeof(*kf)); 3087 3088 if (rtm->rtm_flags & RTF_STATIC) 3089 kf->flags |= F_STATIC; 3090 if (rtm->rtm_flags & RTF_BLACKHOLE) 3091 kf->flags |= F_BLACKHOLE; 3092 if (rtm->rtm_flags & RTF_REJECT) 3093 kf->flags |= F_REJECT; 3094 3095 /* adjust priority here */ 3096 if (rtm->rtm_priority == kr_state.fib_prio) 3097 kf->priority = RTP_MINE; 3098 else 3099 kf->priority = rtm->rtm_priority; 3100 3101 label = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL]; 3102 if (label != NULL) 3103 if (strlcpy(kf->label, label->sr_label, sizeof(kf->label)) >= 3104 sizeof(kf->label)) 3105 fatalx("rtm label overflow"); 3106 3107 sa2addr(sa, &kf->prefix, NULL); 3108 switch (sa->sa_family) { 3109 case AF_INET: 3110 sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK]; 3111 if (rtm->rtm_flags & RTF_HOST) 3112 kf->prefixlen = 32; 3113 else if (sa_in != NULL) 3114 kf->prefixlen = mask2prefixlen4(sa_in); 3115 else 3116 kf->prefixlen = 3117 prefixlen_classful(kf->prefix.v4.s_addr); 3118 break; 3119 case AF_INET6: 3120 sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK]; 3121 if (rtm->rtm_flags & RTF_HOST) 3122 kf->prefixlen = 128; 3123 else if (sa_in6 != NULL) 3124 kf->prefixlen = mask2prefixlen6(sa_in6); 3125 else 3126 fatalx("in6 net addr without netmask"); 3127 break; 3128 default: 3129 return (-1); 3130 } 3131 3132 if ((sa = rti_info[RTAX_GATEWAY]) == NULL) { 3133 log_warnx("route %s/%u without gateway", 3134 log_addr(&kf->prefix), kf->prefixlen); 3135 return (-1); 3136 } 3137 3138 kf->ifindex = rtm->rtm_index; 3139 if (rtm->rtm_flags & RTF_GATEWAY) { 3140 switch (sa->sa_family) { 3141 case AF_LINK: 3142 kf->flags |= F_CONNECTED; 3143 break; 3144 case AF_INET: 3145 case AF_INET6: 3146 sa2addr(rti_info[RTAX_GATEWAY], &kf->nexthop, NULL); 3147 break; 3148 } 3149 } else { 3150 kf->flags |= F_CONNECTED; 3151 } 3152 3153 return (0); 3154 } 3155 3156 int 3157 kr_fib_delete(struct ktable *kt, struct kroute_full *kf, int mpath) 3158 { 3159 return kroute_remove(kt, kf, !mpath); 3160 } 3161 3162 int 3163 kr_fib_change(struct ktable *kt, struct kroute_full *kf, int type, int mpath) 3164 { 3165 struct kroute *kr; 3166 struct kroute6 *kr6; 3167 int flags, oflags; 3168 int changed = 0, rtlabel_changed = 0; 3169 uint16_t new_labelid; 3170 3171 flags = kf->flags; 3172 switch (kf->prefix.aid) { 3173 case AID_INET: 3174 if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen, 3175 kf->priority)) != NULL) { 3176 if (!(kf->flags & F_BGPD)) { 3177 /* get the correct route */ 3178 if (mpath && type == RTM_CHANGE && 3179 (kr = kroute_matchgw(kr, kf)) == NULL) { 3180 log_warnx("%s[change]: " 3181 "mpath route not found", __func__); 3182 goto add4; 3183 } else if (mpath && type == RTM_ADD) 3184 goto add4; 3185 3186 if (kf->nexthop.aid == AID_INET) { 3187 if (kr->nexthop.s_addr != 3188 kf->nexthop.v4.s_addr) 3189 changed = 1; 3190 kr->nexthop.s_addr = 3191 kf->nexthop.v4.s_addr; 3192 kr->ifindex = kf->ifindex; 3193 } else { 3194 if (kr->nexthop.s_addr != 0) 3195 changed = 1; 3196 kr->nexthop.s_addr = 0; 3197 kr->ifindex = kf->ifindex; 3198 } 3199 3200 if (kr->flags & F_NEXTHOP) 3201 flags |= F_NEXTHOP; 3202 3203 new_labelid = rtlabel_name2id(kf->label); 3204 if (kr->labelid != new_labelid) { 3205 rtlabel_unref(kr->labelid); 3206 kr->labelid = new_labelid; 3207 rtlabel_changed = 1; 3208 } 3209 3210 oflags = kr->flags; 3211 if (flags != oflags) 3212 changed = 1; 3213 kr->flags = flags; 3214 3215 if (rtlabel_changed) 3216 kr_redistribute(IMSG_NETWORK_ADD, 3217 kt, kr_tofull(kr)); 3218 3219 if ((oflags & F_CONNECTED) && 3220 !(flags & F_CONNECTED)) 3221 kr_redistribute(IMSG_NETWORK_ADD, 3222 kt, kr_tofull(kr)); 3223 if ((flags & F_CONNECTED) && 3224 !(oflags & F_CONNECTED)) 3225 kr_redistribute(IMSG_NETWORK_ADD, 3226 kt, kr_tofull(kr)); 3227 3228 if (kr->flags & F_NEXTHOP && changed) 3229 knexthop_update(kt, kf); 3230 } else { 3231 kr->flags &= ~F_BGPD_INSERTED; 3232 } 3233 } else { 3234 add4: 3235 kroute_insert(kt, kf); 3236 } 3237 break; 3238 case AID_INET6: 3239 if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen, 3240 kf->priority)) != NULL) { 3241 if (!(kf->flags & F_BGPD)) { 3242 /* get the correct route */ 3243 if (mpath && type == RTM_CHANGE && 3244 (kr6 = kroute6_matchgw(kr6, kf)) == NULL) { 3245 log_warnx("%s[change]: IPv6 mpath " 3246 "route not found", __func__); 3247 goto add6; 3248 } else if (mpath && type == RTM_ADD) 3249 goto add6; 3250 3251 if (kf->nexthop.aid == AID_INET6) { 3252 if (memcmp(&kr6->nexthop, 3253 &kf->nexthop.v6, 3254 sizeof(struct in6_addr)) || 3255 kr6->nexthop_scope_id != 3256 kf->nexthop.scope_id) 3257 changed = 1; 3258 kr6->nexthop = kf->nexthop.v6; 3259 kr6->nexthop_scope_id = 3260 kf->nexthop.scope_id; 3261 kr6->ifindex = kf->ifindex; 3262 } else { 3263 if (memcmp(&kr6->nexthop, 3264 &in6addr_any, 3265 sizeof(struct in6_addr))) 3266 changed = 1; 3267 kr6->nexthop = in6addr_any; 3268 kr6->nexthop_scope_id = 0; 3269 kr6->ifindex = kf->ifindex; 3270 } 3271 3272 if (kr6->flags & F_NEXTHOP) 3273 flags |= F_NEXTHOP; 3274 3275 new_labelid = rtlabel_name2id(kf->label); 3276 if (kr6->labelid != new_labelid) { 3277 rtlabel_unref(kr6->labelid); 3278 kr6->labelid = new_labelid; 3279 rtlabel_changed = 1; 3280 } 3281 3282 oflags = kr6->flags; 3283 if (flags != oflags) 3284 changed = 1; 3285 kr6->flags = flags; 3286 3287 if (rtlabel_changed) 3288 kr_redistribute(IMSG_NETWORK_ADD, 3289 kt, kr6_tofull(kr6)); 3290 3291 if ((oflags & F_CONNECTED) && 3292 !(flags & F_CONNECTED)) 3293 kr_redistribute(IMSG_NETWORK_ADD, 3294 kt, kr6_tofull(kr6)); 3295 if ((flags & F_CONNECTED) && 3296 !(oflags & F_CONNECTED)) 3297 kr_redistribute(IMSG_NETWORK_ADD, 3298 kt, kr6_tofull(kr6)); 3299 3300 if (kr6->flags & F_NEXTHOP && changed) 3301 knexthop_update(kt, kf); 3302 } else { 3303 kr6->flags &= ~F_BGPD_INSERTED; 3304 } 3305 } else { 3306 add6: 3307 kroute_insert(kt, kf); 3308 } 3309 break; 3310 } 3311 3312 return (0); 3313 } 3314