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