ospfctl.c revision 1.8
1/* $OpenBSD: ospfctl.c,v 1.8 2005/03/15 22:09:43 claudio Exp $ */ 2 3/* 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21#include <sys/types.h> 22#include <sys/socket.h> 23#include <sys/un.h> 24#include <netinet/in.h> 25#include <arpa/inet.h> 26#include <net/if_media.h> 27#include <net/if_types.h> 28 29#include <err.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33#include <unistd.h> 34 35#include "ospf.h" 36#include "ospfd.h" 37#include "ospfe.h" 38#include "parser.h" 39#include "log.h" 40 41__dead void usage(void); 42int show_summary_msg(struct imsg *); 43int show_interface_msg(struct imsg *); 44void print_baudrate(u_long); 45const char *print_if_type(enum iface_type type); 46const char *print_if_state(int); 47const char *print_nbr_state(int); 48const char *print_link(int); 49const char *fmt_timeframe(time_t t); 50const char *fmt_timeframe_core(time_t t); 51const char *log_id(u_int32_t ); 52const char *log_adv_rtr(u_int32_t); 53u_int8_t mask2prefixlen(struct in_addr); 54void show_database_head(struct in_addr, u_int8_t); 55int show_database_msg(struct imsg *); 56int show_nbr_msg(struct imsg *); 57const char *print_ospf_options(u_int8_t); 58int show_nbr_detail_msg(struct imsg *); 59int show_rib_msg(struct imsg *); 60void show_rib_head(struct in_addr, u_int8_t, u_int8_t); 61int show_rib_detail_msg(struct imsg *); 62void show_fib_head(void); 63int show_fib_msg(struct imsg *); 64void show_interface_head(void); 65const char * get_media_descr(int); 66const char * get_linkstate(int, int); 67void print_baudrate(u_long); 68int show_fib_interface_msg(struct imsg *); 69 70struct imsgbuf *ibuf; 71 72__dead void 73usage(void) 74{ 75 extern char *__progname; 76 77 fprintf(stderr, "usage: %s <command> [arg [...]]\n", __progname); 78 exit(1); 79} 80 81void 82imsg_event_add(struct imsgbuf *i) 83{ 84} 85 86int 87main(int argc, char *argv[]) 88{ 89 struct sockaddr_un sun; 90 struct parse_result *res; 91 struct imsg imsg; 92 unsigned int ifidx = 0; 93 int ctl_sock; 94 int done = 0; 95 int n; 96 97 /* parse options */ 98 if ((res = parse(argc - 1, argv + 1)) == NULL) 99 exit(1); 100 101 /* connect to ospfd control socket */ 102 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 103 err(1, "socket"); 104 105 bzero(&sun, sizeof(sun)); 106 sun.sun_family = AF_UNIX; 107 strlcpy(sun.sun_path, OSPFD_SOCKET, sizeof(sun.sun_path)); 108 if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) 109 err(1, "connect: %s", OSPFD_SOCKET); 110 111 if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 112 fatal(NULL); 113 imsg_init(ibuf, ctl_sock, NULL); 114 done = 0; 115 116 /* process user request */ 117 switch (res->action) { 118 case NONE: 119 usage(); 120 /* not reached */ 121 case SHOW: 122 case SHOW_SUM: 123 imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0); 124 break; 125 case SHOW_IFACE: 126 if (*res->ifname) { 127 ifidx = if_nametoindex(res->ifname); 128 if (ifidx == 0) 129 errx(1, "no such interface %s", res->ifname); 130 } 131 imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, 132 &ifidx, sizeof(ifidx)); 133 break; 134 case SHOW_NBR: 135 printf("%-15s %-3s %-17s %-9s %-15s %s\n", "ID", "Pri", 136 "State", "DeadTime", "Address", "Interface"); 137 case SHOW_NBR_DTAIL: 138 imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); 139 break; 140 case SHOW_DB: 141 imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0); 142 break; 143 case SHOW_DBBYAREA: 144 imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, 145 &res->addr, sizeof(res->addr)); 146 break; 147 case SHOW_RIB: 148 printf("%-20s %-17s %-12s %-9s %-7s\n", "Destination", 149 "Nexthop", "Path Type", "Type", "Cost"); 150 case SHOW_RIB_DTAIL: 151 imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0); 152 break; 153 case SHOW_FIB: 154 if (!res->addr.s_addr) 155 imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1, 156 &res->flags, sizeof(res->flags)); 157 else 158 imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, 159 &res->addr, sizeof(res->addr)); 160 show_fib_head(); 161 break; 162 case SHOW_FIB_IFACE: 163 imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0); 164 show_interface_head(); 165 break; 166 case RELOAD: 167 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 168 printf("reload request sent.\n"); 169 done = 1; 170 break; 171 } 172 173 while (ibuf->w.queued) 174 if (msgbuf_write(&ibuf->w) < 0) 175 err(1, "write error"); 176 177 while (!done) { 178 if ((n = imsg_read(ibuf)) == -1) 179 errx(1, "imsg_read error"); 180 if (n == 0) 181 errx(1, "pipe closed"); 182 183 while (!done) { 184 if ((n = imsg_get(ibuf, &imsg)) == -1) 185 errx(1, "imsg_get error"); 186 if (n == 0) 187 break; 188 switch (res->action) { 189 case SHOW: 190 case SHOW_SUM: 191 done = show_summary_msg(&imsg); 192 break; 193 case SHOW_IFACE: 194 done = show_interface_msg(&imsg); 195 break; 196 case SHOW_NBR: 197 done = show_nbr_msg(&imsg); 198 break; 199 case SHOW_NBR_DTAIL: 200 done = show_nbr_detail_msg(&imsg); 201 break; 202 case SHOW_DB: 203 case SHOW_DBBYAREA: 204 done = show_database_msg(&imsg); 205 break; 206 case SHOW_RIB: 207 done = show_rib_msg(&imsg); 208 break; 209 case SHOW_RIB_DTAIL: 210 done = show_rib_detail_msg(&imsg); 211 break; 212 case SHOW_FIB: 213 done = show_fib_msg(&imsg); 214 break; 215 case SHOW_FIB_IFACE: 216 done = show_fib_interface_msg(&imsg); 217 break; 218 case NONE: 219 case RELOAD: 220 break; 221 } 222 imsg_free(&imsg); 223 } 224 } 225 close(ctl_sock); 226 free(ibuf); 227 228 return (0); 229} 230 231int 232show_summary_msg(struct imsg *imsg) 233{ 234 struct ctl_sum *sum; 235 struct ctl_sum_area *sumarea; 236 237 switch (imsg->hdr.type) { 238 case IMSG_CTL_SHOW_SUM: 239 sum = imsg->data; 240 printf("Router ID: %s\n", inet_ntoa(sum->rtr_id)); 241 printf("RFC1583 compatibility flag is "); 242 if (sum->rfc1583compat) 243 printf("enabled\n"); 244 else 245 printf("disabled\n"); 246 247 printf("SPF delay is %d sec(s), hold time between two SPFs " 248 "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time); 249 printf("Number of external LSA(s) %d\n", sum->num_ext_lsa); 250 printf("Number of areas attached to this router: %d\n", 251 sum->num_area); 252 break; 253 case IMSG_CTL_SHOW_SUM_AREA: 254 sumarea = imsg->data; 255 printf("\nArea ID: %s\n", inet_ntoa(sumarea->area)); 256 printf(" Number of interfaces in this area: %d\n", 257 sumarea->num_iface); 258 printf(" Number of fully adjacent neighbors in this " 259 "area: %d\n", sumarea->num_adj_nbr); 260 printf(" SPF algorithm executed %d time(s)\n", 261 sumarea->num_spf_calc); 262 printf(" Number LSA(s) %d\n", sumarea->num_lsa); 263 break; 264 case IMSG_CTL_END: 265 printf("\n"); 266 return (1); 267 default: 268 break; 269 } 270 271 return (0); 272} 273 274int 275show_interface_msg(struct imsg *imsg) 276{ 277 struct ctl_iface *iface; 278 279 switch (imsg->hdr.type) { 280 case IMSG_CTL_SHOW_INTERFACE: 281 iface = imsg->data; 282 printf("\n"); 283 printf("Interface %s is %d, line protocol is %s\n", 284 iface->name, iface->linkstate, print_link(iface->flags)); 285 printf(" Internet address %s/%d, ", 286 inet_ntoa(iface->addr), 287 mask2prefixlen(iface->mask)); 288 printf("Area %s\n", inet_ntoa(iface->area)); 289 printf(" Router ID %s, network type %s, cost: %d\n", 290 inet_ntoa(iface->rtr_id), 291 print_if_type(iface->type), iface->metric); 292 printf(" Transmit delay is %d sec(s), state %s, priority %d\n", 293 iface->transfer_delay, print_if_state(iface->state), 294 iface->priority); 295 printf(" Designated Router (ID) %s, ", 296 inet_ntoa(iface->dr_id)); 297 printf("interface address %s\n", inet_ntoa(iface->dr_addr)); 298 printf(" Backup Designated Router (ID) %s, ", 299 inet_ntoa(iface->bdr_id)); 300 printf("interface address %s\n", inet_ntoa(iface->bdr_addr)); 301 printf(" Timer intervals configured, " 302 "hello %d, dead %d, wait %d, retransmit %d\n", 303 iface->hello_interval, iface->dead_interval, 304 iface->dead_interval, iface->rxmt_interval); 305 if (iface->hello_timer < 0) 306 printf(" Hello timer not running\n"); 307 else 308 printf(" Hello timer due in %s\n", 309 fmt_timeframe_core(iface->hello_timer)); 310 printf(" Neighbor count is %d, adjacent neighbor count is " 311 "%d\n", iface->nbr_cnt, iface->adj_cnt); 312 break; 313 case IMSG_CTL_END: 314 printf("\n"); 315 return (1); 316 default: 317 break; 318 } 319 320 return (0); 321} 322 323const char * 324print_if_type(enum iface_type type) 325{ 326 switch (type) { 327 case IF_TYPE_POINTOPOINT: 328 return ("POINTOPOINT"); 329 case IF_TYPE_BROADCAST: 330 return ("BROADCAST"); 331 case IF_TYPE_NBMA: 332 return ("NBMA"); 333 case IF_TYPE_POINTOMULTIPOINT: 334 return ("POINTOMULTIPOINT"); 335 case IF_TYPE_VIRTUALLINK: 336 return ("VIRTUALLINK"); 337 default: 338 return ("UNKNOWN"); 339 } 340} 341 342const char * 343print_if_state(int state) 344{ 345 switch (state) { 346 case IF_STA_DOWN: 347 return ("DOWN"); 348 case IF_STA_LOOPBACK: 349 return ("LOOPBACK"); 350 case IF_STA_WAITING: 351 return ("WAITING"); 352 case IF_STA_POINTTOPOINT: 353 return ("P2P"); 354 case IF_STA_DROTHER: 355 return ("DROTHER"); 356 case IF_STA_BACKUP: 357 return ("BACKUP"); 358 case IF_STA_DR: 359 return ("DR"); 360 default: 361 return ("UNKNOWN"); 362 } 363} 364 365const char * 366print_nbr_state(int state) 367{ 368 switch (state) { 369 case NBR_STA_DOWN: 370 return ("DOWN"); 371 case NBR_STA_ATTEMPT: 372 return ("ATTEMPT"); 373 case NBR_STA_INIT: 374 return ("INIT"); 375 case NBR_STA_2_WAY: 376 return ("2-WAY"); 377 case NBR_STA_XSTRT: 378 return ("EXSTART"); 379 case NBR_STA_SNAP: 380 return ("SNAPSHOT"); 381 case NBR_STA_XCHNG: 382 return ("EXCHANGE"); 383 case NBR_STA_LOAD: 384 return ("LOADING"); 385 case NBR_STA_FULL: 386 return ("FULL"); 387 default: 388 return ("UNKNOWN"); 389 } 390} 391 392const char * 393print_link(int state) 394{ 395 if (state & IFF_UP) 396 return ("UP"); 397 else 398 return ("DOWN"); 399} 400 401#define TF_BUFS 8 402#define TF_LEN 9 403 404const char * 405fmt_timeframe(time_t t) 406{ 407 if (t == 0) 408 return ("Never"); 409 else 410 return (fmt_timeframe_core(time(NULL) - t)); 411} 412 413const char * 414fmt_timeframe_core(time_t t) 415{ 416 char *buf; 417 static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 418 static int idx = 0; 419 unsigned sec, min, hrs, day, week; 420 421 if (t == 0) 422 return ("Stopped"); 423 424 buf = tfbuf[idx++]; 425 if (idx == TF_BUFS) 426 idx = 0; 427 428 week = t; 429 430 sec = week % 60; 431 week /= 60; 432 min = week % 60; 433 week /= 60; 434 hrs = week % 24; 435 week /= 24; 436 day = week % 7; 437 week /= 7; 438 439 if (week > 0) 440 snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); 441 else if (day > 0) 442 snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 443 else 444 snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 445 446 return (buf); 447} 448 449const char * 450log_id(u_int32_t id) 451{ 452 static char buf[48]; 453 struct in_addr addr; 454 455 addr.s_addr = id; 456 457 if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 458 return ("?"); 459 else 460 return (buf); 461} 462 463const char * 464log_adv_rtr(u_int32_t adv_rtr) 465{ 466 static char buf[48]; 467 struct in_addr addr; 468 469 addr.s_addr = adv_rtr; 470 471 if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 472 return ("?"); 473 else 474 return (buf); 475} 476 477u_int8_t 478mask2prefixlen(struct in_addr ina) 479{ 480 if (ina.s_addr == 0) 481 return (0); 482 else 483 return (33 - ffs(ntohl(ina.s_addr))); 484} 485 486void 487show_database_head(struct in_addr aid, u_int8_t type) 488{ 489 char *header, *format; 490 491 switch (type) { 492 case LSA_TYPE_ROUTER: 493 format = "Router Link States"; 494 break; 495 case LSA_TYPE_NETWORK: 496 format = "Net Link States"; 497 break; 498 case LSA_TYPE_SUM_NETWORK: 499 format = "Summary Net Link States"; 500 break; 501 case LSA_TYPE_SUM_ROUTER: 502 format = "Summary Router Link States"; 503 break; 504 case LSA_TYPE_EXTERNAL: 505 format = NULL; 506 if ((header = strdup("Type-5 AS External Link States")) == NULL) 507 err(1, NULL); 508 break; 509 default: 510 errx(1, "unknown LSA type"); 511 } 512 if (type != LSA_TYPE_EXTERNAL) 513 if (asprintf(&header, "%s (Area %s)", format, 514 inet_ntoa(aid)) == -1) 515 err(1, NULL); 516 517 printf("\n%-15s %s\n", "", header); 518 free(header); 519 520 printf("\n%-15s %-15s %-4s %-10s %-8s\n", "Link ID", "Adv Router", 521 "Age", "Seq#", "Checksum"); 522} 523 524int 525show_database_msg(struct imsg *imsg) 526{ 527 static struct in_addr area_id; 528 static u_int8_t lasttype; 529 struct area *area; 530 struct lsa_hdr *lsa; 531 532 switch (imsg->hdr.type) { 533 case IMSG_CTL_SHOW_DATABASE: 534 lsa = imsg->data; 535 if (lsa->type != lasttype) 536 show_database_head(area_id, lsa->type); 537 printf("%-15s %-15s %-4d 0x%08x 0x%04x\n", 538 log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr), 539 ntohs(lsa->age), ntohl(lsa->seq_num), 540 ntohs(lsa->ls_chksum)); 541 lasttype = lsa->type; 542 break; 543 case IMSG_CTL_AREA: 544 area = imsg->data; 545 area_id = area->id; 546 break; 547 case IMSG_CTL_END: 548 return (1); 549 default: 550 break; 551 } 552 553 return (0); 554} 555 556int 557show_nbr_msg(struct imsg *imsg) 558{ 559 struct ctl_nbr *nbr; 560 char *state; 561 562 switch (imsg->hdr.type) { 563 case IMSG_CTL_SHOW_NBR: 564 nbr = imsg->data; 565 if (asprintf(&state, "%s/%s", print_nbr_state(nbr->nbr_state), 566 print_if_state(nbr->iface_state)) == -1) 567 err(1, NULL); 568 printf("%-15s %-3d %-17s %-9s ", inet_ntoa(nbr->id), 569 nbr->priority, state, fmt_timeframe_core(nbr->dead_timer)); 570 printf("%-15s %s\n", inet_ntoa(nbr->addr), nbr->name); 571 free(state); 572 break; 573 case IMSG_CTL_END: 574 printf("\n"); 575 return (1); 576 default: 577 break; 578 } 579 580 return (0); 581} 582 583const char * 584print_ospf_options(u_int8_t opts) 585{ 586 static char optbuf[32]; 587 588 snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|%s|%s|*", 589 opts & OSPF_OPTION_DC ? "DC" : "-", 590 opts & OSPF_OPTION_EA ? "EA" : "-", 591 opts & OSPF_OPTION_NP ? "N/P" : "-", 592 opts & OSPF_OPTION_MC ? "MC" : "-", 593 opts & OSPF_OPTION_E ? "E" : "-"); 594 return (optbuf); 595} 596 597int 598show_nbr_detail_msg(struct imsg *imsg) 599{ 600 struct ctl_nbr *nbr; 601 602 switch (imsg->hdr.type) { 603 case IMSG_CTL_SHOW_NBR: 604 nbr = imsg->data; 605 printf("\nNeighbor %s, ", inet_ntoa(nbr->id)); 606 printf("interface address %s\n", inet_ntoa(nbr->addr)); 607 printf(" In the area %s via interface %s\n", 608 inet_ntoa(nbr->area), nbr->name); 609 printf(" Neighbor priority is %d, " 610 "State is %s, %d state changes\n", 611 nbr->priority, print_nbr_state(nbr->nbr_state), 612 nbr->state_chng_cnt); 613 printf(" DR is %s, ", inet_ntoa(nbr->dr)); 614 printf("BDR is %s\n", inet_ntoa(nbr->bdr)); 615 printf(" Options is 0x%x %s\n", nbr->options, 616 print_ospf_options(nbr->options)); 617 printf(" Dead timer due in %s\n", 618 fmt_timeframe_core(nbr->dead_timer)); 619 printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt); 620 printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt); 621 printf(" Link State Retransmission List %d\n", 622 nbr->ls_retrans_lst_cnt); 623 break; 624 case IMSG_CTL_END: 625 printf("\n"); 626 return (1); 627 default: 628 break; 629 } 630 631 return (0); 632} 633 634int 635show_rib_msg(struct imsg *imsg) 636{ 637 struct ctl_rt *rt; 638 char *dstnet; 639 640 switch (imsg->hdr.type) { 641 case IMSG_CTL_SHOW_RIB: 642 rt = imsg->data; 643 switch (rt->d_type) { 644 case DT_NET: 645 if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix), 646 rt->prefixlen) == -1) 647 err(1, NULL); 648 break; 649 case DT_RTR: 650 if (asprintf(&dstnet, "%s", 651 inet_ntoa(rt->prefix)) == -1) 652 err(1, NULL); 653 break; 654 default: 655 errx(1, "Invalid route type"); 656 } 657 658 printf("%-20s %-17s %-12s %-9s %-7d\n", dstnet, 659 inet_ntoa(rt->nexthop), path_type_names[rt->p_type], 660 dst_type_names[rt->d_type], rt->cost); 661 free(dstnet); 662 break; 663 case IMSG_CTL_END: 664 printf("\n"); 665 return (1); 666 default: 667 break; 668 } 669 670 return (0); 671} 672 673void 674show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type) 675{ 676 char *header, *format; 677 678 switch (p_type) { 679 case PT_INTRA_AREA: 680 case PT_INTER_AREA: 681 switch (d_type) { 682 case DT_NET: 683 format = "Network Routing Table"; 684 break; 685 case DT_RTR: 686 format = "Router Routing Table"; 687 break; 688 default: 689 errx(1, "unknown route type"); 690 } 691 break; 692 case PT_TYPE1_EXT: 693 case PT_TYPE2_EXT: 694 format = NULL; 695 if ((header = strdup("External Routing Table")) == NULL) 696 err(1, NULL); 697 break; 698 default: 699 errx(1, "unknown route type"); 700 } 701 702 if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT) 703 if (asprintf(&header, "%s (Area %s)", format, 704 inet_ntoa(aid)) == -1) 705 err(1, NULL); 706 707 printf("\n%-15s %s\n", "", header); 708 free(header); 709 710 printf("\n%-20s %-17s %-17s %-12s %-8s\n", 711 "Destination", "Nexthop", "Adv Router", "Path type", "Cost"); 712 713} 714 715int 716show_rib_detail_msg(struct imsg *imsg) 717{ 718 static struct in_addr area_id; 719 struct ctl_rt *rt; 720 struct area *area; 721 char *dstnet; 722 static u_int8_t lasttype; 723 724 switch (imsg->hdr.type) { 725 case IMSG_CTL_SHOW_RIB: 726 rt = imsg->data; 727 728 switch (rt->p_type) { 729 case PT_INTRA_AREA: 730 case PT_INTER_AREA: 731 switch (rt->d_type) { 732 case DT_NET: 733 if (lasttype != RIB_NET) 734 show_rib_head(rt->area, rt->d_type, 735 rt->p_type); 736 if (asprintf(&dstnet, "%s/%d", 737 inet_ntoa(rt->prefix), rt->prefixlen) == -1) 738 err(1, NULL); 739 lasttype = RIB_NET; 740 break; 741 case DT_RTR: 742 if (lasttype != RIB_RTR) 743 show_rib_head(rt->area, rt->d_type, 744 rt->p_type); 745 if (asprintf(&dstnet, "%s", 746 inet_ntoa(rt->prefix)) == -1) 747 err(1, NULL); 748 lasttype = RIB_RTR; 749 break; 750 default: 751 errx(1, "unknown route type"); 752 } 753 printf("%-20s %-17s ", dstnet, inet_ntoa(rt->nexthop)); 754 printf("%-17s %-12s %-7d\n", inet_ntoa(rt->adv_rtr), 755 path_type_names[rt->p_type], rt->cost); 756 free(dstnet); 757 break; 758 case PT_TYPE1_EXT: 759 case PT_TYPE2_EXT: 760 /* XXX TODO */ 761 break; 762 default: 763 errx(1, "unknown route type"); 764 } 765 break; 766 case IMSG_CTL_AREA: 767 area = imsg->data; 768 area_id = area->id; 769 break; 770 case IMSG_CTL_END: 771 printf("\n"); 772 return (1); 773 default: 774 break; 775 } 776 777 return (0); 778} 779 780void 781show_fib_head(void) 782{ 783 printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n"); 784 printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop"); 785} 786 787int 788show_fib_msg(struct imsg *imsg) 789{ 790 struct kroute *k; 791 char *p; 792 793 switch (imsg->hdr.type) { 794 case IMSG_CTL_KROUTE: 795 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 796 errx(1, "wrong imsg len"); 797 k = imsg->data; 798 799 if (k->flags & F_DOWN) 800 printf(" "); 801 else 802 printf("*"); 803 804 if (k->flags & F_OSPFD_INSERTED) 805 printf("O"); 806 else if (k->flags & F_CONNECTED) 807 printf("C"); 808 else if (k->flags & F_KERNEL) 809 printf("S"); 810 else 811 printf(" "); 812 813 printf(" "); 814 if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) == 815 -1) 816 err(1, NULL); 817 printf("%-20s ", p); 818 free(p); 819 820 if (k->nexthop.s_addr) 821 printf("%s", inet_ntoa(k->nexthop)); 822 else if (k->flags & F_CONNECTED) 823 printf("link#%u", k->ifindex); 824 printf("\n"); 825 826 break; 827 case IMSG_CTL_END: 828 printf("\n"); 829 return (1); 830 default: 831 break; 832 } 833 834 return (0); 835} 836 837void 838show_interface_head(void) 839{ 840 printf("%-15s%-15s%-15s%s\n", "Interface", "Nexthop state", "Flags", 841 "Link state"); 842} 843 844const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 845const struct ifmedia_status_description 846 ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS; 847const struct ifmedia_description 848 ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 849 850const char * 851get_media_descr(int media_type) 852{ 853 const struct ifmedia_description *p; 854 855 for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 856 if (media_type == p->ifmt_word) 857 return (p->ifmt_string); 858 859 return ("unknown media"); 860} 861 862const char * 863get_linkstate(int media_type, int link_state) 864{ 865 const struct ifmedia_status_description *p; 866 int i; 867 868 if (link_state == LINK_STATE_UNKNOWN) 869 return ("unknown"); 870 871 for (i = 0; ifm_status_valid_list[i] != 0; i++) 872 for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) { 873 if (p->ifms_type != media_type || 874 p->ifms_valid != ifm_status_valid_list[i]) 875 continue; 876 return (p->ifms_string[link_state == LINK_STATE_UP]); 877 } 878 879 return ("unknown link state"); 880} 881 882void 883print_baudrate(u_long baudrate) 884{ 885 if (baudrate > IF_Gbps(1)) 886 printf("%lu GBit/s", baudrate / IF_Gbps(1)); 887 else if (baudrate > IF_Mbps(1)) 888 printf("%lu MBit/s", baudrate / IF_Mbps(1)); 889 else if (baudrate > IF_Kbps(1)) 890 printf("%lu KBit/s", baudrate / IF_Kbps(1)); 891 else 892 printf("%lu Bit/s", baudrate); 893} 894 895 896int 897show_fib_interface_msg(struct imsg *imsg) 898{ 899 struct kif *k; 900 int ifms_type; 901 902 switch (imsg->hdr.type) { 903 case IMSG_CTL_SHOW_INTERFACE: 904 k = imsg->data; 905 printf("%-15s", k->ifname); 906 printf("%-15s", k->nh_reachable ? "ok" : "invalid"); 907 printf("%-15s", k->flags & IFF_UP ? "UP" : ""); 908 switch (k->media_type) { 909 case IFT_ETHER: 910 ifms_type = IFM_ETHER; 911 break; 912 case IFT_FDDI: 913 ifms_type = IFM_FDDI; 914 break; 915 case IFT_ISO88025: 916 ifms_type = IFM_TOKEN; 917 break; 918 case IFT_CARP: 919 ifms_type = IFM_CARP; 920 break; 921 default: 922 ifms_type = 0; 923 break; 924 } 925 926 if (ifms_type) 927 printf("%s, %s", get_media_descr(ifms_type), 928 get_linkstate(ifms_type, k->link_state)); 929 else if (k->link_state == LINK_STATE_UNKNOWN) 930 printf("unknown"); 931 else 932 printf("link state %u", k->link_state); 933 934 if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { 935 printf(", "); 936 print_baudrate(k->baudrate); 937 } 938 printf("\n"); 939 break; 940 case IMSG_CTL_END: 941 printf("\n"); 942 return (1); 943 default: 944 break; 945 } 946 947 return (0); 948} 949 950