1 /* $OpenBSD: rde.c,v 1.22 2016/09/02 16:44:33 renato Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org> 5 * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/socket.h> 24 #include <net/route.h> 25 26 #include <errno.h> 27 #include <pwd.h> 28 #include <signal.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <unistd.h> 32 33 #include "eigrpd.h" 34 #include "eigrpe.h" 35 #include "rde.h" 36 #include "log.h" 37 38 static void rde_sig_handler(int sig, short, void *); 39 static __dead void rde_shutdown(void); 40 static void rde_dispatch_imsg(int, short, void *); 41 static void rde_dispatch_parent(int, short, void *); 42 static struct redistribute *eigrp_redistribute(struct eigrp *, struct kroute *); 43 static void rt_redist_set(struct kroute *, int); 44 static void rt_snap(struct rde_nbr *); 45 static struct ctl_rt *rt_to_ctl(struct rt_node *, struct eigrp_route *); 46 static void rt_dump(struct ctl_show_topology_req *, pid_t); 47 48 struct eigrpd_conf *rdeconf; 49 50 static struct imsgev *iev_eigrpe; 51 static struct imsgev *iev_main; 52 53 /* ARGSUSED */ 54 static void 55 rde_sig_handler(int sig, short event, void *arg) 56 { 57 /* 58 * signal handler rules don't apply, libevent decouples for us 59 */ 60 61 switch (sig) { 62 case SIGINT: 63 case SIGTERM: 64 rde_shutdown(); 65 /* NOTREACHED */ 66 default: 67 fatalx("unexpected signal"); 68 } 69 } 70 71 /* route decision engine */ 72 pid_t 73 rde(int debug, int verbose) 74 { 75 struct event ev_sigint, ev_sigterm; 76 struct timeval now; 77 struct passwd *pw; 78 79 rdeconf = config_new_empty(); 80 81 log_init(debug); 82 log_verbose(verbose); 83 84 if ((pw = getpwnam(EIGRPD_USER)) == NULL) 85 fatal("getpwnam"); 86 87 if (chroot(pw->pw_dir) == -1) 88 fatal("chroot"); 89 if (chdir("/") == -1) 90 fatal("chdir(\"/\")"); 91 92 setproctitle("route decision engine"); 93 eigrpd_process = PROC_RDE_ENGINE; 94 95 if (setgroups(1, &pw->pw_gid) || 96 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 97 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 98 fatal("can't drop privileges"); 99 100 if (pledge("stdio recvfd", NULL) == -1) 101 fatal("pledge"); 102 103 event_init(); 104 105 /* setup signal handler */ 106 signal_set(&ev_sigint, SIGINT, rde_sig_handler, NULL); 107 signal_set(&ev_sigterm, SIGTERM, rde_sig_handler, NULL); 108 signal_add(&ev_sigint, NULL); 109 signal_add(&ev_sigterm, NULL); 110 signal(SIGPIPE, SIG_IGN); 111 signal(SIGHUP, SIG_IGN); 112 113 /* setup pipe and event handler to the parent process */ 114 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 115 fatal(NULL); 116 imsg_init(&iev_main->ibuf, 3); 117 iev_main->handler = rde_dispatch_parent; 118 iev_main->events = EV_READ; 119 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 120 iev_main->handler, iev_main); 121 event_add(&iev_main->ev, NULL); 122 123 gettimeofday(&now, NULL); 124 global.uptime = now.tv_sec; 125 126 event_dispatch(); 127 128 rde_shutdown(); 129 /* NOTREACHED */ 130 131 return (0); 132 } 133 134 static __dead void 135 rde_shutdown(void) 136 { 137 /* close pipes */ 138 msgbuf_clear(&iev_eigrpe->ibuf.w); 139 close(iev_eigrpe->ibuf.fd); 140 msgbuf_clear(&iev_main->ibuf.w); 141 close(iev_main->ibuf.fd); 142 143 config_clear(rdeconf); 144 145 free(iev_eigrpe); 146 free(iev_main); 147 148 log_info("route decision engine exiting"); 149 exit(0); 150 } 151 152 int 153 rde_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen) 154 { 155 return (imsg_compose_event(iev_main, type, 0, pid, -1, 156 data, datalen)); 157 } 158 159 int 160 rde_imsg_compose_eigrpe(int type, uint32_t peerid, pid_t pid, void *data, 161 uint16_t datalen) 162 { 163 return (imsg_compose_event(iev_eigrpe, type, peerid, pid, -1, 164 data, datalen)); 165 } 166 167 /* ARGSUSED */ 168 static void 169 rde_dispatch_imsg(int fd, short event, void *bula) 170 { 171 struct imsgev *iev = bula; 172 struct imsgbuf *ibuf; 173 struct imsg imsg; 174 struct rde_nbr *nbr; 175 struct rde_nbr new; 176 struct rinfo rinfo; 177 ssize_t n; 178 int shut = 0, verbose; 179 180 ibuf = &iev->ibuf; 181 182 if (event & EV_READ) { 183 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 184 fatal("imsg_read error"); 185 if (n == 0) /* connection closed */ 186 shut = 1; 187 } 188 if (event & EV_WRITE) { 189 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 190 fatal("msgbuf_write"); 191 if (n == 0) /* connection closed */ 192 shut = 1; 193 } 194 195 for (;;) { 196 if ((n = imsg_get(ibuf, &imsg)) == -1) 197 fatal("rde_dispatch_imsg: imsg_get error"); 198 if (n == 0) 199 break; 200 201 switch (imsg.hdr.type) { 202 case IMSG_NEIGHBOR_UP: 203 if (imsg.hdr.len - IMSG_HEADER_SIZE != 204 sizeof(struct rde_nbr)) 205 fatalx("invalid size of neighbor request"); 206 memcpy(&new, imsg.data, sizeof(new)); 207 208 if (rde_nbr_find(imsg.hdr.peerid)) 209 fatalx("rde_dispatch_imsg: " 210 "neighbor already exists"); 211 rde_nbr_new(imsg.hdr.peerid, &new); 212 break; 213 case IMSG_NEIGHBOR_DOWN: 214 nbr = rde_nbr_find(imsg.hdr.peerid); 215 if (nbr == NULL) { 216 log_debug("%s: cannot find rde neighbor", 217 __func__); 218 break; 219 } 220 221 rde_check_link_down_nbr(nbr); 222 rde_flush_queries(); 223 rde_nbr_del(rde_nbr_find(imsg.hdr.peerid), 0); 224 break; 225 case IMSG_RECV_UPDATE_INIT: 226 nbr = rde_nbr_find(imsg.hdr.peerid); 227 if (nbr == NULL) { 228 log_debug("%s: cannot find rde neighbor", 229 __func__); 230 break; 231 } 232 233 rt_snap(nbr); 234 break; 235 case IMSG_RECV_UPDATE: 236 case IMSG_RECV_QUERY: 237 case IMSG_RECV_REPLY: 238 case IMSG_RECV_SIAQUERY: 239 case IMSG_RECV_SIAREPLY: 240 nbr = rde_nbr_find(imsg.hdr.peerid); 241 if (nbr == NULL) { 242 log_debug("%s: cannot find rde neighbor", 243 __func__); 244 break; 245 } 246 247 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rinfo)) 248 fatalx("invalid size of rinfo"); 249 memcpy(&rinfo, imsg.data, sizeof(rinfo)); 250 251 switch (imsg.hdr.type) { 252 case IMSG_RECV_UPDATE: 253 rde_check_update(nbr, &rinfo); 254 break; 255 case IMSG_RECV_QUERY: 256 rde_check_query(nbr, &rinfo, 0); 257 break; 258 case IMSG_RECV_REPLY: 259 rde_check_reply(nbr, &rinfo, 0); 260 break; 261 case IMSG_RECV_SIAQUERY: 262 rde_check_query(nbr, &rinfo, 1); 263 break; 264 case IMSG_RECV_SIAREPLY: 265 rde_check_reply(nbr, &rinfo, 1); 266 break; 267 } 268 break; 269 case IMSG_CTL_SHOW_TOPOLOGY: 270 if (imsg.hdr.len != IMSG_HEADER_SIZE + 271 sizeof(struct ctl_show_topology_req)) { 272 log_warnx("%s: wrong imsg len", __func__); 273 break; 274 } 275 276 rt_dump(imsg.data, imsg.hdr.pid); 277 rde_imsg_compose_eigrpe(IMSG_CTL_END, 0, imsg.hdr.pid, 278 NULL, 0); 279 break; 280 case IMSG_CTL_LOG_VERBOSE: 281 /* already checked by eigrpe */ 282 memcpy(&verbose, imsg.data, sizeof(verbose)); 283 log_verbose(verbose); 284 break; 285 default: 286 log_debug("rde_dispatch_imsg: unexpected imsg %d", 287 imsg.hdr.type); 288 break; 289 } 290 imsg_free(&imsg); 291 } 292 if (!shut) 293 imsg_event_add(iev); 294 else { 295 /* this pipe is dead, so remove the event handler */ 296 event_del(&iev->ev); 297 event_loopexit(NULL); 298 } 299 } 300 301 /* ARGSUSED */ 302 static void 303 rde_dispatch_parent(int fd, short event, void *bula) 304 { 305 static struct eigrpd_conf *nconf; 306 static struct iface *niface; 307 static struct eigrp *neigrp; 308 struct eigrp_iface *nei; 309 struct imsg imsg; 310 struct imsgev *iev = bula; 311 struct imsgbuf *ibuf; 312 struct kif *kif; 313 ssize_t n; 314 int shut = 0; 315 316 ibuf = &iev->ibuf; 317 318 if (event & EV_READ) { 319 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 320 fatal("imsg_read error"); 321 if (n == 0) /* connection closed */ 322 shut = 1; 323 } 324 if (event & EV_WRITE) { 325 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 326 fatal("msgbuf_write"); 327 if (n == 0) /* connection closed */ 328 shut = 1; 329 } 330 331 for (;;) { 332 if ((n = imsg_get(ibuf, &imsg)) == -1) 333 fatal("rde_dispatch_parent: imsg_get error"); 334 if (n == 0) 335 break; 336 337 switch (imsg.hdr.type) { 338 case IMSG_IFDOWN: 339 if (imsg.hdr.len != IMSG_HEADER_SIZE + 340 sizeof(struct kif)) 341 fatalx("IFDOWN imsg with wrong len"); 342 kif = imsg.data; 343 rde_check_link_down(kif->ifindex); 344 break; 345 case IMSG_NETWORK_ADD: 346 if (imsg.hdr.len != IMSG_HEADER_SIZE + 347 sizeof(struct kroute)) 348 fatalx("IMSG_NETWORK_ADD imsg with wrong len"); 349 rt_redist_set(imsg.data, 0); 350 break; 351 case IMSG_NETWORK_DEL: 352 if (imsg.hdr.len != IMSG_HEADER_SIZE + 353 sizeof(struct kroute)) 354 fatalx("IMSG_NETWORK_DEL imsg with wrong len"); 355 rt_redist_set(imsg.data, 1); 356 break; 357 case IMSG_SOCKET_IPC: 358 if (iev_eigrpe) { 359 log_warnx("%s: received unexpected imsg fd " 360 "to eigrpe", __func__); 361 break; 362 } 363 if ((fd = imsg.fd) == -1) { 364 log_warnx("%s: expected to receive imsg fd to " 365 "eigrpe but didn't receive any", __func__); 366 break; 367 } 368 369 iev_eigrpe = malloc(sizeof(struct imsgev)); 370 if (iev_eigrpe == NULL) 371 fatal(NULL); 372 imsg_init(&iev_eigrpe->ibuf, fd); 373 iev_eigrpe->handler = rde_dispatch_imsg; 374 iev_eigrpe->events = EV_READ; 375 event_set(&iev_eigrpe->ev, iev_eigrpe->ibuf.fd, 376 iev_eigrpe->events, iev_eigrpe->handler, 377 iev_eigrpe); 378 event_add(&iev_eigrpe->ev, NULL); 379 break; 380 case IMSG_RECONF_CONF: 381 if ((nconf = malloc(sizeof(struct eigrpd_conf))) == 382 NULL) 383 fatal(NULL); 384 memcpy(nconf, imsg.data, sizeof(struct eigrpd_conf)); 385 386 TAILQ_INIT(&nconf->iface_list); 387 TAILQ_INIT(&nconf->instances); 388 break; 389 case IMSG_RECONF_INSTANCE: 390 if ((neigrp = malloc(sizeof(struct eigrp))) == NULL) 391 fatal(NULL); 392 memcpy(neigrp, imsg.data, sizeof(struct eigrp)); 393 394 SIMPLEQ_INIT(&neigrp->redist_list); 395 TAILQ_INIT(&neigrp->ei_list); 396 RB_INIT(&neigrp->nbrs); 397 RB_INIT(&neigrp->topology); 398 TAILQ_INSERT_TAIL(&nconf->instances, neigrp, entry); 399 break; 400 case IMSG_RECONF_IFACE: 401 niface = imsg.data; 402 niface = if_lookup(nconf, niface->ifindex); 403 if (niface) 404 break; 405 406 if ((niface = malloc(sizeof(struct iface))) == NULL) 407 fatal(NULL); 408 memcpy(niface, imsg.data, sizeof(struct iface)); 409 410 TAILQ_INIT(&niface->ei_list); 411 TAILQ_INIT(&niface->addr_list); 412 TAILQ_INSERT_TAIL(&nconf->iface_list, niface, entry); 413 break; 414 case IMSG_RECONF_EIGRP_IFACE: 415 if (niface == NULL) 416 break; 417 if ((nei = malloc(sizeof(struct eigrp_iface))) == NULL) 418 fatal(NULL); 419 memcpy(nei, imsg.data, sizeof(struct eigrp_iface)); 420 421 nei->iface = niface; 422 nei->eigrp = neigrp; 423 TAILQ_INIT(&nei->nbr_list); 424 TAILQ_INIT(&nei->update_list); 425 TAILQ_INIT(&nei->query_list); 426 TAILQ_INIT(&nei->summary_list); 427 TAILQ_INSERT_TAIL(&niface->ei_list, nei, i_entry); 428 TAILQ_INSERT_TAIL(&neigrp->ei_list, nei, e_entry); 429 if (RB_INSERT(iface_id_head, &ifaces_by_id, nei) != 430 NULL) 431 fatalx("rde_dispatch_parent: " 432 "RB_INSERT(ifaces_by_id) failed"); 433 break; 434 case IMSG_RECONF_END: 435 merge_config(rdeconf, nconf); 436 nconf = NULL; 437 break; 438 default: 439 log_debug("%s: unexpected imsg %d", __func__, 440 imsg.hdr.type); 441 break; 442 } 443 imsg_free(&imsg); 444 } 445 if (!shut) 446 imsg_event_add(iev); 447 else { 448 /* this pipe is dead, so remove the event handler */ 449 event_del(&iev->ev); 450 event_loopexit(NULL); 451 } 452 } 453 454 void 455 rde_instance_init(struct eigrp *eigrp) 456 { 457 struct rde_nbr nbr; 458 459 memset(&nbr, 0, sizeof(nbr)); 460 nbr.flags = F_RDE_NBR_SELF | F_RDE_NBR_REDIST; 461 eigrp->rnbr_redist = rde_nbr_new(NBR_IDSELF, &nbr); 462 eigrp->rnbr_redist->eigrp = eigrp; 463 nbr.flags = F_RDE_NBR_SELF | F_RDE_NBR_SUMMARY; 464 eigrp->rnbr_summary = rde_nbr_new(NBR_IDSELF, &nbr); 465 eigrp->rnbr_summary->eigrp = eigrp; 466 } 467 468 void 469 rde_instance_del(struct eigrp *eigrp) 470 { 471 struct rde_nbr *nbr, *safe; 472 struct rt_node *rn; 473 474 /* clear topology */ 475 while((rn = RB_MIN(rt_tree, &eigrp->topology)) != NULL) 476 rt_del(rn); 477 478 /* clear nbrs */ 479 RB_FOREACH_SAFE(nbr, rde_nbr_head, &rde_nbrs, safe) 480 if (nbr->eigrp == eigrp) 481 rde_nbr_del(nbr, 0); 482 rde_nbr_del(eigrp->rnbr_redist, 0); 483 rde_nbr_del(eigrp->rnbr_summary, 0); 484 485 free(eigrp); 486 } 487 488 void 489 rde_send_change_kroute(struct rt_node *rn, struct eigrp_route *route) 490 { 491 struct eigrp *eigrp = route->nbr->eigrp; 492 struct kroute kr; 493 struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; 494 495 log_debug("%s: %s nbr %s", __func__, log_prefix(rn), 496 log_addr(eigrp->af, &route->nbr->addr)); 497 498 memset(&kr, 0, sizeof(kr)); 499 kr.af = eigrp->af; 500 kr.prefix = rn->prefix; 501 kr.prefixlen = rn->prefixlen; 502 if (route->nbr->ei) { 503 kr.nexthop = route->nexthop; 504 kr.ifindex = route->nbr->ei->iface->ifindex; 505 } else { 506 switch (eigrp->af) { 507 case AF_INET: 508 kr.nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); 509 break; 510 case AF_INET6: 511 kr.nexthop.v6 = lo6; 512 break; 513 default: 514 fatalx("rde_send_delete_kroute: unknown af"); 515 break; 516 } 517 kr.flags = F_BLACKHOLE; 518 } 519 if (route->type == EIGRP_ROUTE_EXTERNAL) 520 kr.priority = rdeconf->fib_priority_external; 521 else { 522 if (route->nbr->flags & F_RDE_NBR_SUMMARY) 523 kr.priority = rdeconf->fib_priority_summary; 524 else 525 kr.priority = rdeconf->fib_priority_internal; 526 } 527 528 rde_imsg_compose_parent(IMSG_KROUTE_CHANGE, 0, &kr, sizeof(kr)); 529 530 route->flags |= F_EIGRP_ROUTE_INSTALLED; 531 } 532 533 void 534 rde_send_delete_kroute(struct rt_node *rn, struct eigrp_route *route) 535 { 536 struct eigrp *eigrp = route->nbr->eigrp; 537 struct kroute kr; 538 struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; 539 540 log_debug("%s: %s nbr %s", __func__, log_prefix(rn), 541 log_addr(eigrp->af, &route->nbr->addr)); 542 543 memset(&kr, 0, sizeof(kr)); 544 kr.af = eigrp->af; 545 kr.prefix = rn->prefix; 546 kr.prefixlen = rn->prefixlen; 547 if (route->nbr->ei) { 548 kr.nexthop = route->nexthop; 549 kr.ifindex = route->nbr->ei->iface->ifindex; 550 } else { 551 switch (eigrp->af) { 552 case AF_INET: 553 kr.nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); 554 break; 555 case AF_INET6: 556 kr.nexthop.v6 = lo6; 557 break; 558 default: 559 fatalx("rde_send_delete_kroute: unknown af"); 560 break; 561 } 562 kr.flags = F_BLACKHOLE; 563 } 564 if (route->type == EIGRP_ROUTE_EXTERNAL) 565 kr.priority = rdeconf->fib_priority_external; 566 else { 567 if (route->nbr->flags & F_RDE_NBR_SUMMARY) 568 kr.priority = rdeconf->fib_priority_summary; 569 else 570 kr.priority = rdeconf->fib_priority_internal; 571 } 572 573 rde_imsg_compose_parent(IMSG_KROUTE_DELETE, 0, &kr, sizeof(kr)); 574 575 route->flags &= ~F_EIGRP_ROUTE_INSTALLED; 576 } 577 578 static struct redistribute * 579 eigrp_redistribute(struct eigrp *eigrp, struct kroute *kr) 580 { 581 struct redistribute *r; 582 uint8_t is_default = 0; 583 union eigrpd_addr addr; 584 585 /* only allow the default route via REDIST_DEFAULT */ 586 if (!eigrp_addrisset(kr->af, &kr->prefix) && kr->prefixlen == 0) 587 is_default = 1; 588 589 SIMPLEQ_FOREACH(r, &eigrp->redist_list, entry) { 590 switch (r->type & ~REDIST_NO) { 591 case REDIST_STATIC: 592 if (is_default) 593 continue; 594 if (kr->flags & F_STATIC) 595 return (r->type & REDIST_NO ? NULL : r); 596 break; 597 case REDIST_RIP: 598 if (is_default) 599 continue; 600 if (kr->priority == RTP_RIP) 601 return (r->type & REDIST_NO ? NULL : r); 602 break; 603 case REDIST_OSPF: 604 if (is_default) 605 continue; 606 if (kr->priority == RTP_OSPF) 607 return (r->type & REDIST_NO ? NULL : r); 608 break; 609 case REDIST_CONNECTED: 610 if (is_default) 611 continue; 612 if (kr->flags & F_CONNECTED) 613 return (r->type & REDIST_NO ? NULL : r); 614 break; 615 case REDIST_ADDR: 616 if (eigrp_addrisset(r->af, &r->addr) && 617 r->prefixlen == 0) { 618 if (is_default) 619 return (r->type & REDIST_NO ? NULL : r); 620 else 621 return (0); 622 } 623 624 eigrp_applymask(kr->af, &addr, &kr->prefix, 625 r->prefixlen); 626 if (eigrp_addrcmp(kr->af, &addr, &r->addr) == 0 && 627 kr->prefixlen >= r->prefixlen) 628 return (r->type & REDIST_NO ? NULL : r); 629 break; 630 case REDIST_DEFAULT: 631 if (is_default) 632 return (r->type & REDIST_NO ? NULL : r); 633 break; 634 } 635 } 636 637 return (NULL); 638 } 639 640 static void 641 rt_redist_set(struct kroute *kr, int withdraw) 642 { 643 struct eigrp *eigrp; 644 struct redistribute *r; 645 struct redist_metric *rmetric; 646 struct rinfo ri; 647 648 TAILQ_FOREACH(eigrp, &rdeconf->instances, entry) { 649 if (eigrp->af != kr->af) 650 continue; 651 652 r = eigrp_redistribute(eigrp, kr); 653 if (r == NULL) 654 continue; 655 656 if (r->metric) 657 rmetric = r->metric; 658 else if (eigrp->dflt_metric) 659 rmetric = eigrp->dflt_metric; 660 else 661 continue; 662 663 memset(&ri, 0, sizeof(ri)); 664 ri.af = kr->af; 665 ri.type = EIGRP_ROUTE_EXTERNAL; 666 ri.prefix = kr->prefix; 667 ri.prefixlen = kr->prefixlen; 668 669 /* metric */ 670 if (withdraw) 671 ri.metric.delay = EIGRP_INFINITE_METRIC; 672 else 673 ri.metric.delay = eigrp_composite_delay(rmetric->delay); 674 ri.metric.bandwidth = 675 eigrp_composite_bandwidth(rmetric->bandwidth); 676 metric_encode_mtu(ri.metric.mtu, rmetric->mtu); 677 ri.metric.hop_count = 0; 678 ri.metric.reliability = rmetric->reliability; 679 ri.metric.load = rmetric->load; 680 ri.metric.tag = 0; 681 ri.metric.flags = 0; 682 683 /* external metric */ 684 ri.emetric.routerid = htonl(rdeconf->rtr_id.s_addr); 685 ri.emetric.as = r->emetric.as; 686 ri.emetric.tag = r->emetric.tag; 687 ri.emetric.metric = r->emetric.metric; 688 if (kr->priority == rdeconf->fib_priority_internal) 689 ri.emetric.protocol = EIGRP_EXT_PROTO_EIGRP; 690 else if (kr->priority == RTP_STATIC) 691 ri.emetric.protocol = EIGRP_EXT_PROTO_STATIC; 692 else if (kr->priority == RTP_RIP) 693 ri.emetric.protocol = EIGRP_EXT_PROTO_RIP; 694 else if (kr->priority == RTP_OSPF) 695 ri.emetric.protocol = EIGRP_EXT_PROTO_OSPF; 696 else 697 ri.emetric.protocol = EIGRP_EXT_PROTO_CONN; 698 ri.emetric.flags = 0; 699 700 rde_check_update(eigrp->rnbr_redist, &ri); 701 } 702 } 703 704 void 705 rt_summary_set(struct eigrp *eigrp, struct summary_addr *summary, 706 struct classic_metric *metric) 707 { 708 struct rinfo ri; 709 710 memset(&ri, 0, sizeof(ri)); 711 ri.af = eigrp->af; 712 ri.type = EIGRP_ROUTE_INTERNAL; 713 ri.prefix = summary->prefix; 714 ri.prefixlen = summary->prefixlen; 715 ri.metric = *metric; 716 717 rde_check_update(eigrp->rnbr_summary, &ri); 718 } 719 720 /* send all known routing information to new neighbor */ 721 static void 722 rt_snap(struct rde_nbr *nbr) 723 { 724 struct eigrp *eigrp = nbr->eigrp; 725 struct rt_node *rn; 726 struct rinfo ri; 727 728 RB_FOREACH(rn, rt_tree, &eigrp->topology) 729 if (rn->state == DUAL_STA_PASSIVE && 730 !rde_summary_check(nbr->ei, &rn->prefix, rn->prefixlen)) { 731 rinfo_fill_successor(rn, &ri); 732 rde_imsg_compose_eigrpe(IMSG_SEND_UPDATE, 733 nbr->peerid, 0, &ri, sizeof(ri)); 734 } 735 736 rde_imsg_compose_eigrpe(IMSG_SEND_UPDATE_END, nbr->peerid, 0, 737 NULL, 0); 738 } 739 740 static struct ctl_rt * 741 rt_to_ctl(struct rt_node *rn, struct eigrp_route *route) 742 { 743 static struct ctl_rt rtctl; 744 745 memset(&rtctl, 0, sizeof(rtctl)); 746 rtctl.af = route->nbr->eigrp->af; 747 rtctl.as = route->nbr->eigrp->as; 748 rtctl.prefix = rn->prefix; 749 rtctl.prefixlen = rn->prefixlen; 750 rtctl.type = route->type; 751 rtctl.nexthop = route->nexthop; 752 if (route->nbr->flags & F_RDE_NBR_REDIST) 753 strlcpy(rtctl.ifname, "redistribute", sizeof(rtctl.ifname)); 754 else if (route->nbr->flags & F_RDE_NBR_SUMMARY) 755 strlcpy(rtctl.ifname, "summary", sizeof(rtctl.ifname)); 756 else 757 memcpy(rtctl.ifname, route->nbr->ei->iface->name, 758 sizeof(rtctl.ifname)); 759 rtctl.distance = route->distance; 760 rtctl.rdistance = route->rdistance; 761 rtctl.fdistance = rn->successor.fdistance; 762 rtctl.state = rn->state; 763 /* metric */ 764 rtctl.metric.delay = eigrp_real_delay(route->metric.delay); 765 /* translate to microseconds */ 766 rtctl.metric.delay *= 10; 767 rtctl.metric.bandwidth = eigrp_real_bandwidth(route->metric.bandwidth); 768 rtctl.metric.mtu = metric_decode_mtu(route->metric.mtu); 769 rtctl.metric.hop_count = route->metric.hop_count; 770 rtctl.metric.reliability = route->metric.reliability; 771 rtctl.metric.load = route->metric.load; 772 /* external metric */ 773 rtctl.emetric = route->emetric; 774 775 if (route->nbr == rn->successor.nbr) 776 rtctl.flags |= F_CTL_RT_SUCCESSOR; 777 else if (route->rdistance < rn->successor.fdistance) 778 rtctl.flags |= F_CTL_RT_FSUCCESSOR; 779 780 return (&rtctl); 781 } 782 783 static void 784 rt_dump(struct ctl_show_topology_req *treq, pid_t pid) 785 { 786 struct eigrp *eigrp; 787 struct rt_node *rn; 788 struct eigrp_route *route; 789 struct ctl_rt *rtctl; 790 int first = 1; 791 792 TAILQ_FOREACH(eigrp, &rdeconf->instances, entry) { 793 RB_FOREACH(rn, rt_tree, &eigrp->topology) { 794 if (eigrp_addrisset(treq->af, &treq->prefix) && 795 eigrp_addrcmp(treq->af, &treq->prefix, 796 &rn->prefix)) 797 continue; 798 799 if (treq->prefixlen && 800 (treq->prefixlen != rn->prefixlen)) 801 continue; 802 803 first = 1; 804 TAILQ_FOREACH(route, &rn->routes, entry) { 805 if (treq->flags & F_CTL_ACTIVE && 806 !(rn->state & DUAL_STA_ACTIVE_ALL)) 807 continue; 808 if (!(treq->flags & F_CTL_ALLLINKS) && 809 route->rdistance >= rn->successor.fdistance) 810 continue; 811 812 rtctl = rt_to_ctl(rn, route); 813 if (first) { 814 rtctl->flags |= F_CTL_RT_FIRST; 815 first = 0; 816 } 817 rde_imsg_compose_eigrpe(IMSG_CTL_SHOW_TOPOLOGY, 818 0, pid, rtctl, sizeof(*rtctl)); 819 } 820 } 821 } 822 } 823