ospfctl.c revision 1.9
1/* $OpenBSD: ospfctl.c,v 1.9 2005/03/23 20:18:19 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 imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0); 163 show_interface_head(); 164 break; 165 case RELOAD: 166 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 167 printf("reload request sent.\n"); 168 done = 1; 169 break; 170 } 171 172 while (ibuf->w.queued) 173 if (msgbuf_write(&ibuf->w) < 0) 174 err(1, "write error"); 175 176 while (!done) { 177 if ((n = imsg_read(ibuf)) == -1) 178 errx(1, "imsg_read error"); 179 if (n == 0) 180 errx(1, "pipe closed"); 181 182 while (!done) { 183 if ((n = imsg_get(ibuf, &imsg)) == -1) 184 errx(1, "imsg_get error"); 185 if (n == 0) 186 break; 187 switch (res->action) { 188 case SHOW: 189 case SHOW_SUM: 190 done = show_summary_msg(&imsg); 191 break; 192 case SHOW_IFACE: 193 done = show_interface_msg(&imsg); 194 break; 195 case SHOW_NBR: 196 done = show_nbr_msg(&imsg); 197 break; 198 case SHOW_NBR_DTAIL: 199 done = show_nbr_detail_msg(&imsg); 200 break; 201 case SHOW_DB: 202 case SHOW_DBBYAREA: 203 done = show_database_msg(&imsg); 204 break; 205 case SHOW_RIB: 206 done = show_rib_msg(&imsg); 207 break; 208 case SHOW_RIB_DTAIL: 209 done = show_rib_detail_msg(&imsg); 210 break; 211 case SHOW_FIB: 212 done = show_fib_msg(&imsg); 213 break; 214 case SHOW_FIB_IFACE: 215 done = show_fib_interface_msg(&imsg); 216 break; 217 case NONE: 218 case RELOAD: 219 break; 220 } 221 imsg_free(&imsg); 222 } 223 } 224 close(ctl_sock); 225 free(ibuf); 226 227 return (0); 228} 229 230int 231show_summary_msg(struct imsg *imsg) 232{ 233 struct ctl_sum *sum; 234 struct ctl_sum_area *sumarea; 235 236 switch (imsg->hdr.type) { 237 case IMSG_CTL_SHOW_SUM: 238 sum = imsg->data; 239 printf("Router ID: %s\n", inet_ntoa(sum->rtr_id)); 240 printf("RFC1583 compatibility flag is "); 241 if (sum->rfc1583compat) 242 printf("enabled\n"); 243 else 244 printf("disabled\n"); 245 246 printf("SPF delay is %d sec(s), hold time between two SPFs " 247 "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time); 248 printf("Number of external LSA(s) %d\n", sum->num_ext_lsa); 249 printf("Number of areas attached to this router: %d\n", 250 sum->num_area); 251 break; 252 case IMSG_CTL_SHOW_SUM_AREA: 253 sumarea = imsg->data; 254 printf("\nArea ID: %s\n", inet_ntoa(sumarea->area)); 255 printf(" Number of interfaces in this area: %d\n", 256 sumarea->num_iface); 257 printf(" Number of fully adjacent neighbors in this " 258 "area: %d\n", sumarea->num_adj_nbr); 259 printf(" SPF algorithm executed %d time(s)\n", 260 sumarea->num_spf_calc); 261 printf(" Number LSA(s) %d\n", sumarea->num_lsa); 262 break; 263 case IMSG_CTL_END: 264 printf("\n"); 265 return (1); 266 default: 267 break; 268 } 269 270 return (0); 271} 272 273int 274show_interface_msg(struct imsg *imsg) 275{ 276 struct ctl_iface *iface; 277 278 switch (imsg->hdr.type) { 279 case IMSG_CTL_SHOW_INTERFACE: 280 iface = imsg->data; 281 printf("\n"); 282 printf("Interface %s is %d, line protocol is %s\n", 283 iface->name, iface->linkstate, print_link(iface->flags)); 284 printf(" Internet address %s/%d, ", 285 inet_ntoa(iface->addr), 286 mask2prefixlen(iface->mask.s_addr)); 287 printf("Area %s\n", inet_ntoa(iface->area)); 288 printf(" Router ID %s, network type %s, cost: %d\n", 289 inet_ntoa(iface->rtr_id), 290 print_if_type(iface->type), iface->metric); 291 printf(" Transmit delay is %d sec(s), state %s, priority %d\n", 292 iface->transfer_delay, print_if_state(iface->state), 293 iface->priority); 294 printf(" Designated Router (ID) %s, ", 295 inet_ntoa(iface->dr_id)); 296 printf("interface address %s\n", inet_ntoa(iface->dr_addr)); 297 printf(" Backup Designated Router (ID) %s, ", 298 inet_ntoa(iface->bdr_id)); 299 printf("interface address %s\n", inet_ntoa(iface->bdr_addr)); 300 printf(" Timer intervals configured, " 301 "hello %d, dead %d, wait %d, retransmit %d\n", 302 iface->hello_interval, iface->dead_interval, 303 iface->dead_interval, iface->rxmt_interval); 304 if (iface->hello_timer < 0) 305 printf(" Hello timer not running\n"); 306 else 307 printf(" Hello timer due in %s\n", 308 fmt_timeframe_core(iface->hello_timer)); 309 printf(" Neighbor count is %d, adjacent neighbor count is " 310 "%d\n", iface->nbr_cnt, iface->adj_cnt); 311 break; 312 case IMSG_CTL_END: 313 printf("\n"); 314 return (1); 315 default: 316 break; 317 } 318 319 return (0); 320} 321 322const char * 323print_if_type(enum iface_type type) 324{ 325 switch (type) { 326 case IF_TYPE_POINTOPOINT: 327 return ("POINTOPOINT"); 328 case IF_TYPE_BROADCAST: 329 return ("BROADCAST"); 330 case IF_TYPE_NBMA: 331 return ("NBMA"); 332 case IF_TYPE_POINTOMULTIPOINT: 333 return ("POINTOMULTIPOINT"); 334 case IF_TYPE_VIRTUALLINK: 335 return ("VIRTUALLINK"); 336 default: 337 return ("UNKNOWN"); 338 } 339} 340 341const char * 342print_if_state(int state) 343{ 344 switch (state) { 345 case IF_STA_DOWN: 346 return ("DOWN"); 347 case IF_STA_LOOPBACK: 348 return ("LOOPBACK"); 349 case IF_STA_WAITING: 350 return ("WAITING"); 351 case IF_STA_POINTTOPOINT: 352 return ("P2P"); 353 case IF_STA_DROTHER: 354 return ("DROTHER"); 355 case IF_STA_BACKUP: 356 return ("BACKUP"); 357 case IF_STA_DR: 358 return ("DR"); 359 default: 360 return ("UNKNOWN"); 361 } 362} 363 364const char * 365print_nbr_state(int state) 366{ 367 switch (state) { 368 case NBR_STA_DOWN: 369 return ("DOWN"); 370 case NBR_STA_ATTEMPT: 371 return ("ATTEMPT"); 372 case NBR_STA_INIT: 373 return ("INIT"); 374 case NBR_STA_2_WAY: 375 return ("2-WAY"); 376 case NBR_STA_XSTRT: 377 return ("EXSTART"); 378 case NBR_STA_SNAP: 379 return ("SNAPSHOT"); 380 case NBR_STA_XCHNG: 381 return ("EXCHANGE"); 382 case NBR_STA_LOAD: 383 return ("LOADING"); 384 case NBR_STA_FULL: 385 return ("FULL"); 386 default: 387 return ("UNKNOWN"); 388 } 389} 390 391const char * 392print_link(int state) 393{ 394 if (state & IFF_UP) 395 return ("UP"); 396 else 397 return ("DOWN"); 398} 399 400#define TF_BUFS 8 401#define TF_LEN 9 402 403const char * 404fmt_timeframe(time_t t) 405{ 406 if (t == 0) 407 return ("Never"); 408 else 409 return (fmt_timeframe_core(time(NULL) - t)); 410} 411 412const char * 413fmt_timeframe_core(time_t t) 414{ 415 char *buf; 416 static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 417 static int idx = 0; 418 unsigned sec, min, hrs, day, week; 419 420 if (t == 0) 421 return ("Stopped"); 422 423 buf = tfbuf[idx++]; 424 if (idx == TF_BUFS) 425 idx = 0; 426 427 week = t; 428 429 sec = week % 60; 430 week /= 60; 431 min = week % 60; 432 week /= 60; 433 hrs = week % 24; 434 week /= 24; 435 day = week % 7; 436 week /= 7; 437 438 if (week > 0) 439 snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); 440 else if (day > 0) 441 snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 442 else 443 snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 444 445 return (buf); 446} 447 448const char * 449log_id(u_int32_t id) 450{ 451 static char buf[48]; 452 struct in_addr addr; 453 454 addr.s_addr = id; 455 456 if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 457 return ("?"); 458 else 459 return (buf); 460} 461 462const char * 463log_adv_rtr(u_int32_t adv_rtr) 464{ 465 static char buf[48]; 466 struct in_addr addr; 467 468 addr.s_addr = adv_rtr; 469 470 if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 471 return ("?"); 472 else 473 return (buf); 474} 475 476/* prototype defined in ospfd.h and shared with the kroute.c version */ 477u_int8_t 478mask2prefixlen(in_addr_t ina) 479{ 480 if (ina == 0) 481 return (0); 482 else 483 return (33 - ffs(ntohl(ina))); 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