1 /* $OpenBSD: ospf6ctl.c,v 1.47 2017/11/05 16:56:02 jca 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 <errno.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <unistd.h> 35 36 #include "ospf6.h" 37 #include "ospf6d.h" 38 #include "ospfe.h" 39 #include "parser.h" 40 #include "log.h" 41 42 __dead void usage(void); 43 int show_summary_msg(struct imsg *); 44 uint64_t get_ifms_type(uint8_t); 45 int show_interface_msg(struct imsg *); 46 int show_interface_detail_msg(struct imsg *); 47 const char *print_link(int); 48 const char *fmt_timeframe(time_t t); 49 const char *fmt_timeframe_core(time_t t); 50 const char *log_id(u_int32_t ); 51 const char *log_adv_rtr(u_int32_t); 52 void show_database_head(struct in_addr, char *, u_int16_t); 53 int show_database_msg(struct imsg *); 54 char *print_ls_type(u_int16_t); 55 void show_db_hdr_msg_detail(struct lsa_hdr *); 56 char *print_rtr_link_type(u_int8_t); 57 const char *print_ospf_flags(u_int8_t); 58 const char *print_asext_flags(u_int32_t); 59 const char *print_prefix_opt(u_int8_t); 60 int show_db_msg_detail(struct imsg *imsg); 61 int show_nbr_msg(struct imsg *); 62 const char *print_ospf_options(u_int32_t); 63 int show_nbr_detail_msg(struct imsg *); 64 int show_rib_msg(struct imsg *); 65 void show_rib_head(struct in_addr, u_int8_t, u_int8_t); 66 const char *print_ospf_rtr_flags(u_int8_t); 67 int show_rib_detail_msg(struct imsg *); 68 void show_fib_head(void); 69 int show_fib_msg(struct imsg *); 70 const char * get_media_descr(uint64_t); 71 const char * get_linkstate(uint8_t, int); 72 void print_baudrate(u_int64_t); 73 74 struct imsgbuf *ibuf; 75 76 __dead void 77 usage(void) 78 { 79 extern char *__progname; 80 81 fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n", 82 __progname); 83 exit(1); 84 } 85 86 int 87 main(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, verbose = 0; 95 int n; 96 int ch; 97 char *sockname; 98 99 sockname = OSPF6D_SOCKET; 100 while ((ch = getopt(argc, argv, "s:")) != -1) { 101 switch (ch) { 102 case 's': 103 sockname = optarg; 104 break; 105 default: 106 usage(); 107 /* NOTREACHED */ 108 } 109 } 110 argc -= optind; 111 argv += optind; 112 113 /* parse options */ 114 if ((res = parse(argc, argv)) == NULL) 115 exit(1); 116 117 /* connect to ospf6d control socket */ 118 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 119 err(1, "socket"); 120 121 bzero(&sun, sizeof(sun)); 122 sun.sun_family = AF_UNIX; 123 strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path)); 124 if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) 125 err(1, "connect: %s", sockname); 126 127 if (pledge("stdio", NULL) == -1) 128 err(1, "pledge"); 129 130 if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 131 err(1, NULL); 132 imsg_init(ibuf, ctl_sock); 133 done = 0; 134 135 /* process user request */ 136 switch (res->action) { 137 case NONE: 138 usage(); 139 /* not reached */ 140 case SHOW: 141 case SHOW_SUM: 142 imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0); 143 break; 144 case SHOW_IFACE: 145 printf("%-11s %-29s %-6s %-10s %-10s %-8s\n", 146 "Interface", "Address", "State", "HelloTimer", "Linkstate", 147 "Uptime"); 148 /*FALLTHROUGH*/ 149 case SHOW_IFACE_DTAIL: 150 if (*res->ifname) { 151 ifidx = if_nametoindex(res->ifname); 152 if (ifidx == 0) 153 errx(1, "no such interface %s", res->ifname); 154 } 155 imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, 156 &ifidx, sizeof(ifidx)); 157 break; 158 case SHOW_NBR: 159 printf("%-15s %-3s %-12s %-9s %-11s %s\n", "ID", "Pri", 160 "State", "DeadTime", "Iface","Uptime"); 161 /*FALLTHROUGH*/ 162 case SHOW_NBR_DTAIL: 163 imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); 164 break; 165 case SHOW_DB: 166 imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0); 167 break; 168 case SHOW_DBBYAREA: 169 imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, 170 &res->addr, sizeof(res->addr)); 171 break; 172 case SHOW_DBEXT: 173 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0); 174 break; 175 case SHOW_DBLINK: 176 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_LINK, 0, 0, -1, NULL, 0); 177 break; 178 case SHOW_DBNET: 179 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0); 180 break; 181 case SHOW_DBRTR: 182 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0); 183 break; 184 case SHOW_DBINTRA: 185 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_INTRA, 0, 0, -1, NULL, 0); 186 break; 187 case SHOW_DBSELF: 188 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0); 189 break; 190 case SHOW_DBSUM: 191 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0); 192 break; 193 case SHOW_DBASBR: 194 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0); 195 break; 196 case SHOW_RIB: 197 printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination", 198 "Nexthop", "Path Type", "Type", "Cost", "Uptime"); 199 /*FALLTHROUGH*/ 200 case SHOW_RIB_DTAIL: 201 imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0); 202 break; 203 case SHOW_FIB: 204 if (IN6_IS_ADDR_UNSPECIFIED(&res->addr)) 205 imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1, 206 &res->flags, sizeof(res->flags)); 207 else 208 imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, 209 &res->addr, sizeof(res->addr)); 210 show_fib_head(); 211 break; 212 case FIB: 213 errx(1, "fib couple|decouple"); 214 break; 215 case FIB_COUPLE: 216 imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0); 217 printf("couple request sent.\n"); 218 done = 1; 219 break; 220 case FIB_DECOUPLE: 221 imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0); 222 printf("decouple request sent.\n"); 223 done = 1; 224 break; 225 case LOG_VERBOSE: 226 verbose = 1; 227 /* FALLTHROUGH */ 228 case LOG_BRIEF: 229 imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, 230 &verbose, sizeof(verbose)); 231 printf("logging request sent.\n"); 232 done = 1; 233 break; 234 case RELOAD: 235 #ifdef notyet 236 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 237 printf("reload request sent.\n"); 238 done = 1; 239 break; 240 #else 241 errx(1, "reload not supported"); 242 #endif 243 } 244 245 while (ibuf->w.queued) 246 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) 247 err(1, "write error"); 248 249 while (!done) { 250 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 251 errx(1, "imsg_read error"); 252 if (n == 0) 253 errx(1, "pipe closed"); 254 255 while (!done) { 256 if ((n = imsg_get(ibuf, &imsg)) == -1) 257 errx(1, "imsg_get error"); 258 if (n == 0) 259 break; 260 switch (res->action) { 261 case SHOW: 262 case SHOW_SUM: 263 done = show_summary_msg(&imsg); 264 break; 265 case SHOW_IFACE: 266 done = show_interface_msg(&imsg); 267 break; 268 case SHOW_IFACE_DTAIL: 269 done = show_interface_detail_msg(&imsg); 270 break; 271 case SHOW_NBR: 272 done = show_nbr_msg(&imsg); 273 break; 274 case SHOW_NBR_DTAIL: 275 done = show_nbr_detail_msg(&imsg); 276 break; 277 case SHOW_DB: 278 case SHOW_DBBYAREA: 279 case SHOW_DBSELF: 280 done = show_database_msg(&imsg); 281 break; 282 case SHOW_DBEXT: 283 case SHOW_DBLINK: 284 case SHOW_DBNET: 285 case SHOW_DBRTR: 286 case SHOW_DBINTRA: 287 case SHOW_DBSUM: 288 case SHOW_DBASBR: 289 done = show_db_msg_detail(&imsg); 290 break; 291 case SHOW_RIB: 292 done = show_rib_msg(&imsg); 293 break; 294 case SHOW_RIB_DTAIL: 295 done = show_rib_detail_msg(&imsg); 296 break; 297 case SHOW_FIB: 298 done = show_fib_msg(&imsg); 299 break; 300 case NONE: 301 case FIB: 302 case FIB_COUPLE: 303 case FIB_DECOUPLE: 304 case LOG_VERBOSE: 305 case LOG_BRIEF: 306 case RELOAD: 307 break; 308 } 309 imsg_free(&imsg); 310 } 311 } 312 close(ctl_sock); 313 free(ibuf); 314 315 return (0); 316 } 317 318 int 319 show_summary_msg(struct imsg *imsg) 320 { 321 struct ctl_sum *sum; 322 struct ctl_sum_area *sumarea; 323 324 switch (imsg->hdr.type) { 325 case IMSG_CTL_SHOW_SUM: 326 sum = imsg->data; 327 printf("Router ID: %s\n", inet_ntoa(sum->rtr_id)); 328 printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime)); 329 330 printf("SPF delay is %d sec(s), hold time between two SPFs " 331 "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time); 332 printf("Number of external LSA(s) %d\n", sum->num_ext_lsa); 333 printf("Number of areas attached to this router: %d\n", 334 sum->num_area); 335 break; 336 case IMSG_CTL_SHOW_SUM_AREA: 337 sumarea = imsg->data; 338 printf("\nArea ID: %s\n", inet_ntoa(sumarea->area)); 339 printf(" Number of interfaces in this area: %d\n", 340 sumarea->num_iface); 341 printf(" Number of fully adjacent neighbors in this " 342 "area: %d\n", sumarea->num_adj_nbr); 343 printf(" SPF algorithm executed %d time(s)\n", 344 sumarea->num_spf_calc); 345 printf(" Number LSA(s) %d\n", sumarea->num_lsa); 346 break; 347 case IMSG_CTL_END: 348 printf("\n"); 349 return (1); 350 default: 351 break; 352 } 353 354 return (0); 355 } 356 357 uint64_t 358 get_ifms_type(uint8_t if_type) 359 { 360 switch (if_type) { 361 case IFT_ETHER: 362 return (IFM_ETHER); 363 case IFT_FDDI: 364 return (IFM_FDDI); 365 case IFT_CARP: 366 return (IFM_CARP); 367 case IFT_PPP: 368 return (IFM_TDM); 369 default: 370 return (0); 371 } 372 } 373 374 int 375 show_interface_msg(struct imsg *imsg) 376 { 377 struct ctl_iface *iface; 378 char *netid; 379 380 switch (imsg->hdr.type) { 381 case IMSG_CTL_SHOW_INTERFACE: 382 iface = imsg->data; 383 384 if (asprintf(&netid, "%s", log_in6addr(&iface->addr)) == -1) 385 err(1, NULL); 386 printf("%-11s %-29s %-6s %-10s %-10s %s\n", 387 iface->name, netid, if_state_name(iface->state), 388 fmt_timeframe_core(iface->hello_timer), 389 get_linkstate(iface->if_type, iface->linkstate), 390 fmt_timeframe_core(iface->uptime)); 391 free(netid); 392 break; 393 case IMSG_CTL_END: 394 printf("\n"); 395 return (1); 396 default: 397 break; 398 } 399 400 return (0); 401 } 402 403 int 404 show_interface_detail_msg(struct imsg *imsg) 405 { 406 struct ctl_iface *iface; 407 408 switch (imsg->hdr.type) { 409 case IMSG_CTL_SHOW_INTERFACE: 410 iface = imsg->data; 411 printf("\n"); 412 printf("Interface %s, line protocol is %s\n", 413 iface->name, print_link(iface->flags)); 414 printf(" Internet address %s Area %s\n", 415 log_in6addr(&iface->addr), inet_ntoa(iface->area)); 416 printf(" Link type %s, state %s, mtu %d", 417 get_media_descr(get_ifms_type(iface->if_type)), 418 get_linkstate(iface->if_type, iface->linkstate), 419 iface->mtu); 420 if (iface->linkstate != LINK_STATE_DOWN && 421 iface->baudrate > 0) { 422 printf(", "); 423 print_baudrate(iface->baudrate); 424 } 425 printf("\n"); 426 printf(" Router ID %s, network type %s, cost: %d\n", 427 inet_ntoa(iface->rtr_id), 428 if_type_name(iface->type), iface->metric); 429 printf(" Transmit delay is %d sec(s), state %s, priority %d\n", 430 iface->transmit_delay, if_state_name(iface->state), 431 iface->priority); 432 printf(" Designated Router (ID) %s\n", 433 inet_ntoa(iface->dr_id)); 434 printf(" Interface address %s\n", 435 log_in6addr(&iface->dr_addr)); 436 printf(" Backup Designated Router (ID) %s\n", 437 inet_ntoa(iface->bdr_id)); 438 printf(" Interface address %s\n", 439 log_in6addr(&iface->bdr_addr)); 440 printf(" Timer intervals configured, " 441 "hello %d, dead %d, wait %d, retransmit %d\n", 442 iface->hello_interval, iface->dead_interval, 443 iface->dead_interval, iface->rxmt_interval); 444 if (iface->passive) 445 printf(" Passive interface (No Hellos)\n"); 446 else if (iface->hello_timer < 0) 447 printf(" Hello timer not running\n"); 448 else 449 printf(" Hello timer due in %s\n", 450 fmt_timeframe_core(iface->hello_timer)); 451 printf(" Uptime %s\n", fmt_timeframe_core(iface->uptime)); 452 printf(" Neighbor count is %d, adjacent neighbor count is " 453 "%d\n", iface->nbr_cnt, iface->adj_cnt); 454 break; 455 case IMSG_CTL_END: 456 printf("\n"); 457 return (1); 458 default: 459 break; 460 } 461 462 return (0); 463 } 464 465 const char * 466 print_link(int state) 467 { 468 if (state & IFF_UP) 469 return ("UP"); 470 else 471 return ("DOWN"); 472 } 473 474 #define TF_BUFS 8 475 #define TF_LEN 9 476 477 const char * 478 fmt_timeframe(time_t t) 479 { 480 if (t == 0) 481 return ("Never"); 482 else 483 return (fmt_timeframe_core(time(NULL) - t)); 484 } 485 486 const char * 487 fmt_timeframe_core(time_t t) 488 { 489 char *buf; 490 static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 491 static int idx = 0; 492 unsigned int sec, min, hrs, day, week; 493 494 if (t == 0) 495 return ("00:00:00"); 496 497 buf = tfbuf[idx++]; 498 if (idx == TF_BUFS) 499 idx = 0; 500 501 week = t; 502 503 sec = week % 60; 504 week /= 60; 505 min = week % 60; 506 week /= 60; 507 hrs = week % 24; 508 week /= 24; 509 day = week % 7; 510 week /= 7; 511 512 if (week > 0) 513 snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); 514 else if (day > 0) 515 snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 516 else 517 snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 518 519 return (buf); 520 } 521 522 const char * 523 log_id(u_int32_t id) 524 { 525 static char buf[48]; 526 struct in_addr addr; 527 528 addr.s_addr = id; 529 530 if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 531 return ("?"); 532 else 533 return (buf); 534 } 535 536 const char * 537 log_adv_rtr(u_int32_t adv_rtr) 538 { 539 static char buf[48]; 540 struct in_addr addr; 541 542 addr.s_addr = adv_rtr; 543 544 if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 545 return ("?"); 546 else 547 return (buf); 548 } 549 550 void 551 show_database_head(struct in_addr aid, char *ifname, u_int16_t type) 552 { 553 char *header, *format; 554 int cleanup = 0; 555 556 switch (ntohs(type)) { 557 case LSA_TYPE_LINK: 558 format = "Link (Type-8) Link States"; 559 break; 560 case LSA_TYPE_ROUTER: 561 format = "Router Link States"; 562 break; 563 case LSA_TYPE_NETWORK: 564 format = "Net Link States"; 565 break; 566 case LSA_TYPE_INTER_A_PREFIX: 567 format = "Inter Area Prefix Link States"; 568 break; 569 case LSA_TYPE_INTER_A_ROUTER: 570 format = "Inter Area Router Link States"; 571 break; 572 case LSA_TYPE_INTRA_A_PREFIX: 573 format = "Intra Area Prefix Link States"; 574 break; 575 case LSA_TYPE_EXTERNAL: 576 printf("\n%-15s %s\n\n", "", "Type-5 AS External Link States"); 577 return; 578 default: 579 if (asprintf(&format, "LSA type %x", ntohs(type)) == -1) 580 err(1, NULL); 581 cleanup = 1; 582 break; 583 } 584 if (LSA_IS_SCOPE_AREA(ntohs(type))) { 585 if (asprintf(&header, "%s (Area %s)", format, 586 inet_ntoa(aid)) == -1) 587 err(1, NULL); 588 } else if (LSA_IS_SCOPE_LLOCAL(ntohs(type))) { 589 if (asprintf(&header, "%s (Area %s Interface %s)", format, 590 inet_ntoa(aid), ifname) == -1) 591 err(1, NULL); 592 } else { 593 if (asprintf(&header, "%s", format) == -1) 594 err(1, NULL); 595 } 596 597 printf("\n%-15s %s\n\n", "", header); 598 free(header); 599 if (cleanup) 600 free(format); 601 } 602 603 int 604 show_database_msg(struct imsg *imsg) 605 { 606 static struct in_addr area_id; 607 static char ifname[IF_NAMESIZE]; 608 static u_int16_t lasttype; 609 struct area *area; 610 struct iface *iface; 611 struct lsa_hdr *lsa; 612 613 switch (imsg->hdr.type) { 614 case IMSG_CTL_SHOW_DATABASE: 615 case IMSG_CTL_SHOW_DB_SELF: 616 lsa = imsg->data; 617 if (lsa->type != lasttype) { 618 show_database_head(area_id, ifname, lsa->type); 619 printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID", 620 "Adv Router", "Age", "Seq#", "Checksum"); 621 } 622 printf("%-15s %-15s %-4d 0x%08x 0x%04x\n", 623 log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr), 624 ntohs(lsa->age), ntohl(lsa->seq_num), 625 ntohs(lsa->ls_chksum)); 626 lasttype = lsa->type; 627 break; 628 case IMSG_CTL_AREA: 629 area = imsg->data; 630 area_id = area->id; 631 lasttype = 0; 632 break; 633 case IMSG_CTL_IFACE: 634 iface = imsg->data; 635 strlcpy(ifname, iface->name, sizeof(ifname)); 636 lasttype = 0; 637 break; 638 case IMSG_CTL_END: 639 printf("\n"); 640 return (1); 641 default: 642 break; 643 } 644 645 return (0); 646 } 647 648 char * 649 print_ls_type(u_int16_t type) 650 { 651 switch (ntohs(type)) { 652 case LSA_TYPE_LINK: 653 return ("Link"); 654 case LSA_TYPE_ROUTER: 655 return ("Router"); 656 case LSA_TYPE_NETWORK: 657 return ("Network"); 658 case LSA_TYPE_INTER_A_PREFIX: 659 return ("Inter Area (Prefix)"); 660 case LSA_TYPE_INTER_A_ROUTER: 661 return ("Inter Area (Router)"); 662 case LSA_TYPE_INTRA_A_PREFIX: 663 return ("Intra Area (Prefix)"); 664 case LSA_TYPE_EXTERNAL: 665 return ("AS External"); 666 default: 667 return ("Unknown"); 668 } 669 } 670 671 void 672 show_db_hdr_msg_detail(struct lsa_hdr *lsa) 673 { 674 printf("LS age: %d\n", ntohs(lsa->age)); 675 printf("LS Type: %s\n", print_ls_type(lsa->type)); 676 677 switch (ntohs(lsa->type)) { 678 case LSA_TYPE_ROUTER: 679 case LSA_TYPE_INTER_A_PREFIX: 680 case LSA_TYPE_INTER_A_ROUTER: 681 case LSA_TYPE_INTRA_A_PREFIX: 682 case LSA_TYPE_EXTERNAL: 683 printf("Link State ID: %s\n", log_id(lsa->ls_id)); 684 break; 685 case LSA_TYPE_LINK: 686 printf("Link State ID: %s (Interface ID of Advertising " 687 "Router)\n", log_id(lsa->ls_id)); 688 break; 689 case LSA_TYPE_NETWORK: 690 printf("Link State ID: %s (Interface ID of Designated " 691 "Router)\n", log_id(lsa->ls_id)); 692 break; 693 } 694 695 printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr)); 696 printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num)); 697 printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum)); 698 printf("Length: %d\n", ntohs(lsa->len)); 699 } 700 701 char * 702 print_rtr_link_type(u_int8_t type) 703 { 704 switch (type) { 705 case LINK_TYPE_POINTTOPOINT: 706 return ("Point-to-Point"); 707 case LINK_TYPE_TRANSIT_NET: 708 return ("Transit Network"); 709 case LINK_TYPE_RESERVED: 710 return ("Reserved"); 711 case LINK_TYPE_VIRTUAL: 712 return ("Virtual Link"); 713 default: 714 return ("Unknown"); 715 } 716 } 717 718 const char * 719 print_ospf_flags(u_int8_t opts) 720 { 721 static char optbuf[32]; 722 723 snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s", 724 opts & OSPF_RTR_V ? "V" : "-", 725 opts & OSPF_RTR_E ? "E" : "-", 726 opts & OSPF_RTR_B ? "B" : "-"); 727 return (optbuf); 728 } 729 730 const char * 731 print_asext_flags(u_int32_t opts) 732 { 733 static char optbuf[32]; 734 735 snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s", 736 opts & LSA_ASEXT_E_FLAG ? "E" : "-", 737 opts & LSA_ASEXT_F_FLAG ? "F" : "-", 738 opts & LSA_ASEXT_T_FLAG ? "T" : "-"); 739 return (optbuf); 740 } 741 742 const char * 743 print_prefix_opt(u_int8_t opts) 744 { 745 static char optbuf[32]; 746 747 if (opts) { 748 snprintf(optbuf, sizeof(optbuf), 749 " Options: *|*|*|%s|%s|x|%s|%s", 750 opts & OSPF_PREFIX_DN ? "DN" : "-", 751 opts & OSPF_PREFIX_P ? "P" : "-", 752 opts & OSPF_PREFIX_LA ? "LA" : "-", 753 opts & OSPF_PREFIX_NU ? "NU" : "-"); 754 return (optbuf); 755 } 756 return (""); 757 } 758 759 int 760 show_db_msg_detail(struct imsg *imsg) 761 { 762 static struct in_addr area_id; 763 static char ifname[IF_NAMESIZE]; 764 static u_int16_t lasttype; 765 struct in6_addr ia6; 766 struct in_addr addr, data; 767 struct area *area; 768 struct iface *iface; 769 struct lsa *lsa; 770 struct lsa_rtr_link *rtr_link; 771 struct lsa_net_link *net_link; 772 struct lsa_prefix *prefix; 773 struct lsa_asext *asext; 774 u_int32_t ext_tag; 775 u_int16_t i, nlinks, off; 776 777 /* XXX sanity checks! */ 778 779 switch (imsg->hdr.type) { 780 case IMSG_CTL_SHOW_DB_EXT: 781 lsa = imsg->data; 782 if (lsa->hdr.type != lasttype) 783 show_database_head(area_id, ifname, lsa->hdr.type); 784 show_db_hdr_msg_detail(&lsa->hdr); 785 786 asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr)); 787 788 printf(" Flags: %s\n", 789 print_asext_flags(ntohl(lsa->data.asext.metric))); 790 printf(" Metric: %d Type: ", ntohl(asext->metric) 791 & LSA_METRIC_MASK); 792 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG) 793 printf("2\n"); 794 else 795 printf("1\n"); 796 797 prefix = &asext->prefix; 798 bzero(&ia6, sizeof(ia6)); 799 bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen)); 800 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 801 prefix->prefixlen, print_prefix_opt(prefix->options)); 802 803 off = sizeof(*asext) + LSA_PREFIXSIZE(prefix->prefixlen); 804 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_F_FLAG) { 805 bcopy((char *)asext + off, &ia6, sizeof(ia6)); 806 printf(" Forwarding Address: %s\n", 807 log_in6addr(&ia6)); 808 off += sizeof(ia6); 809 } 810 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_T_FLAG) { 811 bcopy((char *)asext + off, &ext_tag, sizeof(ext_tag)); 812 printf(" External Route Tag: %d\n", ntohl(ext_tag)); 813 } 814 printf("\n"); 815 lasttype = lsa->hdr.type; 816 break; 817 case IMSG_CTL_SHOW_DB_LINK: 818 lsa = imsg->data; 819 if (lsa->hdr.type != lasttype) 820 show_database_head(area_id, ifname, lsa->hdr.type); 821 show_db_hdr_msg_detail(&lsa->hdr); 822 printf("Options: %s\n", print_ospf_options(LSA_24_GETLO( 823 ntohl(lsa->data.link.opts)))); 824 printf("Link Local Address: %s\n", 825 log_in6addr(&lsa->data.link.lladdr)); 826 827 nlinks = ntohl(lsa->data.link.numprefix); 828 printf("Number of Prefixes: %d\n", nlinks); 829 off = sizeof(lsa->hdr) + sizeof(struct lsa_link); 830 831 for (i = 0; i < nlinks; i++) { 832 prefix = (struct lsa_prefix *)((char *)lsa + off); 833 bzero(&ia6, sizeof(ia6)); 834 bcopy(prefix + 1, &ia6, 835 LSA_PREFIXSIZE(prefix->prefixlen)); 836 837 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 838 prefix->prefixlen, 839 print_prefix_opt(prefix->options)); 840 841 off += sizeof(struct lsa_prefix) 842 + LSA_PREFIXSIZE(prefix->prefixlen); 843 } 844 845 printf("\n"); 846 lasttype = lsa->hdr.type; 847 break; 848 case IMSG_CTL_SHOW_DB_NET: 849 lsa = imsg->data; 850 if (lsa->hdr.type != lasttype) 851 show_database_head(area_id, ifname, lsa->hdr.type); 852 show_db_hdr_msg_detail(&lsa->hdr); 853 printf("Options: %s\n", 854 print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts)))); 855 856 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) - 857 sizeof(struct lsa_net)) / sizeof(struct lsa_net_link); 858 net_link = (struct lsa_net_link *)((char *)lsa + 859 sizeof(lsa->hdr) + sizeof(lsa->data.net)); 860 printf("Number of Routers: %d\n", nlinks); 861 862 for (i = 0; i < nlinks; i++) { 863 addr.s_addr = net_link->att_rtr; 864 printf(" Attached Router: %s\n", inet_ntoa(addr)); 865 net_link++; 866 } 867 868 printf("\n"); 869 lasttype = lsa->hdr.type; 870 break; 871 case IMSG_CTL_SHOW_DB_RTR: 872 lsa = imsg->data; 873 if (lsa->hdr.type != lasttype) 874 show_database_head(area_id, ifname, lsa->hdr.type); 875 show_db_hdr_msg_detail(&lsa->hdr); 876 printf("Flags: %s\n", 877 print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts)))); 878 printf("Options: %s\n", 879 print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts)))); 880 881 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) 882 - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link); 883 printf("Number of Links: %d\n\n", nlinks); 884 885 off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr); 886 887 for (i = 0; i < nlinks; i++) { 888 rtr_link = (struct lsa_rtr_link *)((char *)lsa + off); 889 890 printf(" Link (Interface ID %s) connected to: %s\n", 891 log_id(rtr_link->iface_id), 892 print_rtr_link_type(rtr_link->type)); 893 894 addr.s_addr = rtr_link->nbr_rtr_id; 895 data.s_addr = rtr_link->nbr_iface_id; 896 897 switch (rtr_link->type) { 898 case LINK_TYPE_POINTTOPOINT: 899 case LINK_TYPE_VIRTUAL: 900 printf(" Router ID: %s\n", inet_ntoa(addr)); 901 printf(" Interface ID: %s\n", 902 inet_ntoa(data)); 903 break; 904 case LINK_TYPE_TRANSIT_NET: 905 printf(" Designated Router ID: %s\n", 906 inet_ntoa(addr)); 907 printf(" DR Interface ID: %s\n", 908 inet_ntoa(data)); 909 break; 910 default: 911 printf(" Link ID (Unknown type %d): %s\n", 912 rtr_link->type, inet_ntoa(addr)); 913 printf(" Link Data (Unknown): %s\n", 914 inet_ntoa(data)); 915 break; 916 } 917 918 printf(" Metric: %d\n\n", ntohs(rtr_link->metric)); 919 920 off += sizeof(struct lsa_rtr_link); 921 } 922 923 lasttype = lsa->hdr.type; 924 break; 925 case IMSG_CTL_SHOW_DB_INTRA: 926 lsa = imsg->data; 927 if (lsa->hdr.type != lasttype) 928 show_database_head(area_id, ifname, lsa->hdr.type); 929 show_db_hdr_msg_detail(&lsa->hdr); 930 printf("Referenced LS Type: %s\n", 931 print_ls_type(lsa->data.pref_intra.ref_type)); 932 addr.s_addr = lsa->data.pref_intra.ref_ls_id; 933 printf("Referenced Link State ID: %s\n", inet_ntoa(addr)); 934 addr.s_addr = lsa->data.pref_intra.ref_adv_rtr; 935 printf("Referenced Advertising Router: %s\n", inet_ntoa(addr)); 936 nlinks = ntohs(lsa->data.pref_intra.numprefix); 937 printf("Number of Prefixes: %d\n", nlinks); 938 939 off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix); 940 941 for (i = 0; i < nlinks; i++) { 942 prefix = (struct lsa_prefix *)((char *)lsa + off); 943 bzero(&ia6, sizeof(ia6)); 944 bcopy(prefix + 1, &ia6, 945 LSA_PREFIXSIZE(prefix->prefixlen)); 946 947 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 948 prefix->prefixlen, 949 print_prefix_opt(prefix->options)); 950 951 off += sizeof(struct lsa_prefix) 952 + LSA_PREFIXSIZE(prefix->prefixlen); 953 } 954 955 printf("\n"); 956 lasttype = lsa->hdr.type; 957 break; 958 case IMSG_CTL_SHOW_DB_SUM: 959 lsa = imsg->data; 960 if (lsa->hdr.type != lasttype) 961 show_database_head(area_id, ifname, lsa->hdr.type); 962 show_db_hdr_msg_detail(&lsa->hdr); 963 printf("Prefix: XXX\n"); 964 printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) & 965 LSA_METRIC_MASK); 966 lasttype = lsa->hdr.type; 967 break; 968 case IMSG_CTL_SHOW_DB_ASBR: 969 lsa = imsg->data; 970 if (lsa->hdr.type != lasttype) 971 show_database_head(area_id, ifname, lsa->hdr.type); 972 show_db_hdr_msg_detail(&lsa->hdr); 973 974 addr.s_addr = lsa->data.rtr_sum.dest_rtr_id; 975 printf("Destination Router ID: %s\n", inet_ntoa(addr)); 976 printf("Options: %s\n", 977 print_ospf_options(ntohl(lsa->data.rtr_sum.opts))); 978 printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) & 979 LSA_METRIC_MASK); 980 case IMSG_CTL_AREA: 981 area = imsg->data; 982 area_id = area->id; 983 lasttype = 0; 984 break; 985 case IMSG_CTL_IFACE: 986 iface = imsg->data; 987 strlcpy(ifname, iface->name, sizeof(ifname)); 988 lasttype = 0; 989 break; 990 case IMSG_CTL_END: 991 return (1); 992 default: 993 break; 994 } 995 996 return (0); 997 } 998 999 int 1000 show_nbr_msg(struct imsg *imsg) 1001 { 1002 struct ctl_nbr *nbr; 1003 char *state; 1004 1005 switch (imsg->hdr.type) { 1006 case IMSG_CTL_SHOW_NBR: 1007 nbr = imsg->data; 1008 if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state), 1009 if_state_name(nbr->iface_state)) == -1) 1010 err(1, NULL); 1011 printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id), 1012 nbr->priority, state, fmt_timeframe_core(nbr->dead_timer)); 1013 printf("%-11s %s\n", nbr->name, 1014 nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime)); 1015 free(state); 1016 break; 1017 case IMSG_CTL_END: 1018 printf("\n"); 1019 return (1); 1020 default: 1021 break; 1022 } 1023 1024 return (0); 1025 } 1026 1027 const char * 1028 print_ospf_options(u_int32_t opts) 1029 { 1030 static char optbuf[32]; 1031 1032 snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s", 1033 opts & OSPF_OPTION_DC ? "DC" : "-", 1034 opts & OSPF_OPTION_R ? "R" : "-", 1035 opts & OSPF_OPTION_N ? "N" : "-", 1036 opts & OSPF_OPTION_E ? "E" : "-", 1037 opts & OSPF_OPTION_V6 ? "V6" : "-"); 1038 return (optbuf); 1039 } 1040 1041 int 1042 show_nbr_detail_msg(struct imsg *imsg) 1043 { 1044 struct ctl_nbr *nbr; 1045 1046 switch (imsg->hdr.type) { 1047 case IMSG_CTL_SHOW_NBR: 1048 nbr = imsg->data; 1049 printf("\nNeighbor %s, ", inet_ntoa(nbr->id)); 1050 printf("interface address %s\n", log_in6addr(&nbr->addr)); 1051 printf(" Area %s, interface %s\n", inet_ntoa(nbr->area), 1052 nbr->name); 1053 printf(" Neighbor priority is %d, " 1054 "State is %s, %d state changes\n", 1055 nbr->priority, nbr_state_name(nbr->nbr_state), 1056 nbr->state_chng_cnt); 1057 printf(" DR is %s, ", inet_ntoa(nbr->dr)); 1058 printf("BDR is %s\n", inet_ntoa(nbr->bdr)); 1059 printf(" Options %s\n", print_ospf_options(nbr->options)); 1060 printf(" Dead timer due in %s\n", 1061 fmt_timeframe_core(nbr->dead_timer)); 1062 printf(" Uptime %s\n", fmt_timeframe_core(nbr->uptime)); 1063 printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt); 1064 printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt); 1065 printf(" Link State Retransmission List %d\n", 1066 nbr->ls_retrans_lst_cnt); 1067 break; 1068 case IMSG_CTL_END: 1069 printf("\n"); 1070 return (1); 1071 default: 1072 break; 1073 } 1074 1075 return (0); 1076 } 1077 1078 int 1079 show_rib_msg(struct imsg *imsg) 1080 { 1081 struct ctl_rt *rt; 1082 char *dstnet; 1083 1084 switch (imsg->hdr.type) { 1085 case IMSG_CTL_SHOW_RIB: 1086 rt = imsg->data; 1087 switch (rt->d_type) { 1088 case DT_NET: 1089 if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix), 1090 rt->prefixlen) == -1) 1091 err(1, NULL); 1092 break; 1093 case DT_RTR: 1094 if (asprintf(&dstnet, "%s", 1095 log_in6addr(&rt->prefix)) == -1) 1096 err(1, NULL); 1097 break; 1098 default: 1099 errx(1, "Invalid route type"); 1100 } 1101 1102 printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet, 1103 log_in6addr_scope(&rt->nexthop, rt->ifindex), 1104 path_type_name(rt->p_type), dst_type_name(rt->d_type), 1105 rt->cost, 1106 rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime)); 1107 free(dstnet); 1108 break; 1109 case IMSG_CTL_END: 1110 printf("\n"); 1111 return (1); 1112 default: 1113 break; 1114 } 1115 1116 return (0); 1117 } 1118 1119 void 1120 show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type) 1121 { 1122 char *header, *format, *format2; 1123 1124 switch (p_type) { 1125 case PT_INTRA_AREA: 1126 case PT_INTER_AREA: 1127 switch (d_type) { 1128 case DT_NET: 1129 format = "Network Routing Table"; 1130 format2 = ""; 1131 break; 1132 case DT_RTR: 1133 format = "Router Routing Table"; 1134 format2 = "Type"; 1135 break; 1136 default: 1137 errx(1, "unknown route type"); 1138 } 1139 break; 1140 case PT_TYPE1_EXT: 1141 case PT_TYPE2_EXT: 1142 format = NULL; 1143 format2 = "Cost 2"; 1144 if ((header = strdup("External Routing Table")) == NULL) 1145 err(1, NULL); 1146 break; 1147 default: 1148 errx(1, "unknown route type"); 1149 } 1150 1151 if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT) 1152 if (asprintf(&header, "%s (Area %s)", format, 1153 inet_ntoa(aid)) == -1) 1154 err(1, NULL); 1155 1156 printf("\n%-18s %s\n", "", header); 1157 free(header); 1158 1159 printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination", 1160 "Nexthop", "Adv Router", "Path type", "Cost", format2); 1161 } 1162 1163 const char * 1164 print_ospf_rtr_flags(u_int8_t opts) 1165 { 1166 static char optbuf[32]; 1167 1168 snprintf(optbuf, sizeof(optbuf), "%s%s%s", 1169 opts & OSPF_RTR_E ? "AS" : "", 1170 opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "", 1171 opts & OSPF_RTR_B ? "ABR" : ""); 1172 return (optbuf); 1173 } 1174 1175 int 1176 show_rib_detail_msg(struct imsg *imsg) 1177 { 1178 static struct in_addr area_id; 1179 struct ctl_rt *rt; 1180 struct area *area; 1181 char *dstnet; 1182 static u_int8_t lasttype; 1183 1184 switch (imsg->hdr.type) { 1185 case IMSG_CTL_SHOW_RIB: 1186 rt = imsg->data; 1187 1188 switch (rt->p_type) { 1189 case PT_INTRA_AREA: 1190 case PT_INTER_AREA: 1191 switch (rt->d_type) { 1192 case DT_NET: 1193 if (lasttype != RIB_NET) 1194 show_rib_head(rt->area, rt->d_type, 1195 rt->p_type); 1196 if (asprintf(&dstnet, "%s/%d", 1197 log_in6addr(&rt->prefix), 1198 rt->prefixlen) == -1) 1199 err(1, NULL); 1200 lasttype = RIB_NET; 1201 break; 1202 case DT_RTR: 1203 if (lasttype != RIB_RTR) 1204 show_rib_head(rt->area, rt->d_type, 1205 rt->p_type); 1206 if (asprintf(&dstnet, "%s", 1207 log_in6addr(&rt->prefix)) == -1) 1208 err(1, NULL); 1209 lasttype = RIB_RTR; 1210 break; 1211 default: 1212 errx(1, "unknown route type"); 1213 } 1214 printf("%-18s %-15s ", dstnet, 1215 log_in6addr_scope(&rt->nexthop, rt->ifindex)); 1216 printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr), 1217 path_type_name(rt->p_type), rt->cost); 1218 free(dstnet); 1219 1220 if (rt->d_type == DT_RTR) 1221 printf(" %-7s", 1222 print_ospf_rtr_flags(rt->flags)); 1223 1224 printf("\n"); 1225 break; 1226 case PT_TYPE1_EXT: 1227 case PT_TYPE2_EXT: 1228 if (lasttype != RIB_EXT) 1229 show_rib_head(rt->area, rt->d_type, rt->p_type); 1230 1231 if (asprintf(&dstnet, "%s/%d", 1232 log_in6addr(&rt->prefix), rt->prefixlen) == -1) 1233 err(1, NULL); 1234 1235 printf("%-18s %-15s ", dstnet, 1236 log_in6addr_scope(&rt->nexthop, rt->ifindex)); 1237 printf("%-15s %-12s %-7d %-7d\n", 1238 inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type), 1239 rt->cost, rt->cost2); 1240 free(dstnet); 1241 1242 lasttype = RIB_EXT; 1243 break; 1244 default: 1245 errx(1, "unknown route type"); 1246 } 1247 break; 1248 case IMSG_CTL_AREA: 1249 area = imsg->data; 1250 area_id = area->id; 1251 break; 1252 case IMSG_CTL_END: 1253 printf("\n"); 1254 return (1); 1255 default: 1256 break; 1257 } 1258 1259 return (0); 1260 } 1261 1262 void 1263 show_fib_head(void) 1264 { 1265 printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n"); 1266 printf("%-6s %-4s %-20s %-17s\n", 1267 "Flags", "Prio", "Destination", "Nexthop"); 1268 } 1269 1270 int 1271 show_fib_msg(struct imsg *imsg) 1272 { 1273 struct kroute *k; 1274 char *p; 1275 1276 switch (imsg->hdr.type) { 1277 case IMSG_CTL_KROUTE: 1278 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 1279 errx(1, "wrong imsg len"); 1280 k = imsg->data; 1281 1282 if (k->flags & F_DOWN) 1283 printf(" "); 1284 else 1285 printf("*"); 1286 1287 if (!(k->flags & F_KERNEL)) 1288 printf("O"); 1289 else if (k->flags & F_CONNECTED) 1290 printf("C"); 1291 else if (k->flags & F_STATIC) 1292 printf("S"); 1293 else 1294 printf(" "); 1295 1296 printf(" "); 1297 printf("%4d ", k->priority); 1298 if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix), 1299 k->prefixlen) == -1) 1300 err(1, NULL); 1301 printf("%-20s ", p); 1302 free(p); 1303 1304 if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop)) 1305 printf("%s", log_in6addr_scope(&k->nexthop, k->scope)); 1306 else if (k->flags & F_CONNECTED) 1307 printf("link#%u", k->ifindex); 1308 printf("\n"); 1309 1310 break; 1311 case IMSG_CTL_END: 1312 printf("\n"); 1313 return (1); 1314 default: 1315 break; 1316 } 1317 1318 return (0); 1319 } 1320 1321 const struct if_status_description 1322 if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; 1323 const struct ifmedia_description 1324 ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 1325 1326 const char * 1327 get_media_descr(uint64_t media_type) 1328 { 1329 const struct ifmedia_description *p; 1330 1331 for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 1332 if (media_type == p->ifmt_word) 1333 return (p->ifmt_string); 1334 1335 return ("unknown"); 1336 } 1337 1338 const char * 1339 get_linkstate(uint8_t if_type, int link_state) 1340 { 1341 const struct if_status_description *p; 1342 static char buf[8]; 1343 1344 for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 1345 if (LINK_STATE_DESC_MATCH(p, if_type, link_state)) 1346 return (p->ifs_string); 1347 } 1348 snprintf(buf, sizeof(buf), "[#%d]", link_state); 1349 return (buf); 1350 } 1351 1352 void 1353 print_baudrate(u_int64_t baudrate) 1354 { 1355 if (baudrate > IF_Gbps(1)) 1356 printf("%llu GBit/s", baudrate / IF_Gbps(1)); 1357 else if (baudrate > IF_Mbps(1)) 1358 printf("%llu MBit/s", baudrate / IF_Mbps(1)); 1359 else if (baudrate > IF_Kbps(1)) 1360 printf("%llu KBit/s", baudrate / IF_Kbps(1)); 1361 else 1362 printf("%llu Bit/s", baudrate); 1363 } 1364