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