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