1 /* $OpenBSD: ospf6ctl.c,v 1.46 2017/08/12 22:09:54 benno 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 } else { 589 if (asprintf(&header, "%s", format) == -1) 590 err(1, NULL); 591 } 592 593 printf("\n%-15s %s\n\n", "", header); 594 free(header); 595 if (cleanup) 596 free(format); 597 } 598 599 int 600 show_database_msg(struct imsg *imsg) 601 { 602 static struct in_addr area_id; 603 static char ifname[IF_NAMESIZE]; 604 static u_int16_t lasttype; 605 struct area *area; 606 struct iface *iface; 607 struct lsa_hdr *lsa; 608 609 switch (imsg->hdr.type) { 610 case IMSG_CTL_SHOW_DATABASE: 611 case IMSG_CTL_SHOW_DB_SELF: 612 lsa = imsg->data; 613 if (lsa->type != lasttype) { 614 show_database_head(area_id, ifname, lsa->type); 615 printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID", 616 "Adv Router", "Age", "Seq#", "Checksum"); 617 } 618 printf("%-15s %-15s %-4d 0x%08x 0x%04x\n", 619 log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr), 620 ntohs(lsa->age), ntohl(lsa->seq_num), 621 ntohs(lsa->ls_chksum)); 622 lasttype = lsa->type; 623 break; 624 case IMSG_CTL_AREA: 625 area = imsg->data; 626 area_id = area->id; 627 lasttype = 0; 628 break; 629 case IMSG_CTL_IFACE: 630 iface = imsg->data; 631 strlcpy(ifname, iface->name, sizeof(ifname)); 632 lasttype = 0; 633 break; 634 case IMSG_CTL_END: 635 printf("\n"); 636 return (1); 637 default: 638 break; 639 } 640 641 return (0); 642 } 643 644 char * 645 print_ls_type(u_int16_t type) 646 { 647 switch (ntohs(type)) { 648 case LSA_TYPE_LINK: 649 return ("Link"); 650 case LSA_TYPE_ROUTER: 651 return ("Router"); 652 case LSA_TYPE_NETWORK: 653 return ("Network"); 654 case LSA_TYPE_INTER_A_PREFIX: 655 return ("Inter Area (Prefix)"); 656 case LSA_TYPE_INTER_A_ROUTER: 657 return ("Inter Area (Router)"); 658 case LSA_TYPE_INTRA_A_PREFIX: 659 return ("Intra Area (Prefix)"); 660 case LSA_TYPE_EXTERNAL: 661 return ("AS External"); 662 default: 663 return ("Unknown"); 664 } 665 } 666 667 void 668 show_db_hdr_msg_detail(struct lsa_hdr *lsa) 669 { 670 printf("LS age: %d\n", ntohs(lsa->age)); 671 printf("LS Type: %s\n", print_ls_type(lsa->type)); 672 673 switch (ntohs(lsa->type)) { 674 case LSA_TYPE_ROUTER: 675 case LSA_TYPE_INTER_A_PREFIX: 676 case LSA_TYPE_INTER_A_ROUTER: 677 case LSA_TYPE_INTRA_A_PREFIX: 678 case LSA_TYPE_EXTERNAL: 679 printf("Link State ID: %s\n", log_id(lsa->ls_id)); 680 break; 681 case LSA_TYPE_LINK: 682 printf("Link State ID: %s (Interface ID of Advertising " 683 "Router)\n", log_id(lsa->ls_id)); 684 break; 685 case LSA_TYPE_NETWORK: 686 printf("Link State ID: %s (Interface ID of Designated " 687 "Router)\n", log_id(lsa->ls_id)); 688 break; 689 } 690 691 printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr)); 692 printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num)); 693 printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum)); 694 printf("Length: %d\n", ntohs(lsa->len)); 695 } 696 697 char * 698 print_rtr_link_type(u_int8_t type) 699 { 700 switch (type) { 701 case LINK_TYPE_POINTTOPOINT: 702 return ("Point-to-Point"); 703 case LINK_TYPE_TRANSIT_NET: 704 return ("Transit Network"); 705 case LINK_TYPE_RESERVED: 706 return ("Reserved"); 707 case LINK_TYPE_VIRTUAL: 708 return ("Virtual Link"); 709 default: 710 return ("Unknown"); 711 } 712 } 713 714 const char * 715 print_ospf_flags(u_int8_t opts) 716 { 717 static char optbuf[32]; 718 719 snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s", 720 opts & OSPF_RTR_V ? "V" : "-", 721 opts & OSPF_RTR_E ? "E" : "-", 722 opts & OSPF_RTR_B ? "B" : "-"); 723 return (optbuf); 724 } 725 726 const char * 727 print_asext_flags(u_int32_t opts) 728 { 729 static char optbuf[32]; 730 731 snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s", 732 opts & LSA_ASEXT_E_FLAG ? "E" : "-", 733 opts & LSA_ASEXT_F_FLAG ? "F" : "-", 734 opts & LSA_ASEXT_T_FLAG ? "T" : "-"); 735 return (optbuf); 736 } 737 738 const char * 739 print_prefix_opt(u_int8_t opts) 740 { 741 static char optbuf[32]; 742 743 if (opts) { 744 snprintf(optbuf, sizeof(optbuf), 745 " Options: *|*|*|%s|%s|x|%s|%s", 746 opts & OSPF_PREFIX_DN ? "DN" : "-", 747 opts & OSPF_PREFIX_P ? "P" : "-", 748 opts & OSPF_PREFIX_LA ? "LA" : "-", 749 opts & OSPF_PREFIX_NU ? "NU" : "-"); 750 return (optbuf); 751 } 752 return (""); 753 } 754 755 int 756 show_db_msg_detail(struct imsg *imsg) 757 { 758 static struct in_addr area_id; 759 static char ifname[IF_NAMESIZE]; 760 static u_int16_t lasttype; 761 struct in6_addr ia6; 762 struct in_addr addr, data; 763 struct area *area; 764 struct iface *iface; 765 struct lsa *lsa; 766 struct lsa_rtr_link *rtr_link; 767 struct lsa_net_link *net_link; 768 struct lsa_prefix *prefix; 769 struct lsa_asext *asext; 770 u_int32_t ext_tag; 771 u_int16_t i, nlinks, off; 772 773 /* XXX sanity checks! */ 774 775 switch (imsg->hdr.type) { 776 case IMSG_CTL_SHOW_DB_EXT: 777 lsa = imsg->data; 778 if (lsa->hdr.type != lasttype) 779 show_database_head(area_id, ifname, lsa->hdr.type); 780 show_db_hdr_msg_detail(&lsa->hdr); 781 782 asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr)); 783 784 printf(" Flags: %s\n", 785 print_asext_flags(ntohl(lsa->data.asext.metric))); 786 printf(" Metric: %d Type: ", ntohl(asext->metric) 787 & LSA_METRIC_MASK); 788 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG) 789 printf("2\n"); 790 else 791 printf("1\n"); 792 793 prefix = &asext->prefix; 794 bzero(&ia6, sizeof(ia6)); 795 bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen)); 796 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 797 prefix->prefixlen, print_prefix_opt(prefix->options)); 798 799 off = sizeof(*asext) + LSA_PREFIXSIZE(prefix->prefixlen); 800 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_F_FLAG) { 801 bcopy((char *)asext + off, &ia6, sizeof(ia6)); 802 printf(" Forwarding Address: %s\n", 803 log_in6addr(&ia6)); 804 off += sizeof(ia6); 805 } 806 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_T_FLAG) { 807 bcopy((char *)asext + off, &ext_tag, sizeof(ext_tag)); 808 printf(" External Route Tag: %d\n", ntohl(ext_tag)); 809 } 810 printf("\n"); 811 lasttype = lsa->hdr.type; 812 break; 813 case IMSG_CTL_SHOW_DB_LINK: 814 lsa = imsg->data; 815 if (lsa->hdr.type != lasttype) 816 show_database_head(area_id, ifname, lsa->hdr.type); 817 show_db_hdr_msg_detail(&lsa->hdr); 818 printf("Options: %s\n", print_ospf_options(LSA_24_GETLO( 819 ntohl(lsa->data.link.opts)))); 820 printf("Link Local Address: %s\n", 821 log_in6addr(&lsa->data.link.lladdr)); 822 823 nlinks = ntohl(lsa->data.link.numprefix); 824 printf("Number of Prefixes: %d\n", nlinks); 825 off = sizeof(lsa->hdr) + sizeof(struct lsa_link); 826 827 for (i = 0; i < nlinks; i++) { 828 prefix = (struct lsa_prefix *)((char *)lsa + off); 829 bzero(&ia6, sizeof(ia6)); 830 bcopy(prefix + 1, &ia6, 831 LSA_PREFIXSIZE(prefix->prefixlen)); 832 833 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 834 prefix->prefixlen, 835 print_prefix_opt(prefix->options)); 836 837 off += sizeof(struct lsa_prefix) 838 + LSA_PREFIXSIZE(prefix->prefixlen); 839 } 840 841 printf("\n"); 842 lasttype = lsa->hdr.type; 843 break; 844 case IMSG_CTL_SHOW_DB_NET: 845 lsa = imsg->data; 846 if (lsa->hdr.type != lasttype) 847 show_database_head(area_id, ifname, lsa->hdr.type); 848 show_db_hdr_msg_detail(&lsa->hdr); 849 printf("Options: %s\n", 850 print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts)))); 851 852 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) - 853 sizeof(struct lsa_net)) / sizeof(struct lsa_net_link); 854 net_link = (struct lsa_net_link *)((char *)lsa + 855 sizeof(lsa->hdr) + sizeof(lsa->data.net)); 856 printf("Number of Routers: %d\n", nlinks); 857 858 for (i = 0; i < nlinks; i++) { 859 addr.s_addr = net_link->att_rtr; 860 printf(" Attached Router: %s\n", inet_ntoa(addr)); 861 net_link++; 862 } 863 864 printf("\n"); 865 lasttype = lsa->hdr.type; 866 break; 867 case IMSG_CTL_SHOW_DB_RTR: 868 lsa = imsg->data; 869 if (lsa->hdr.type != lasttype) 870 show_database_head(area_id, ifname, lsa->hdr.type); 871 show_db_hdr_msg_detail(&lsa->hdr); 872 printf("Flags: %s\n", 873 print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts)))); 874 printf("Options: %s\n", 875 print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts)))); 876 877 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) 878 - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link); 879 printf("Number of Links: %d\n\n", nlinks); 880 881 off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr); 882 883 for (i = 0; i < nlinks; i++) { 884 rtr_link = (struct lsa_rtr_link *)((char *)lsa + off); 885 886 printf(" Link (Interface ID %s) connected to: %s\n", 887 log_id(rtr_link->iface_id), 888 print_rtr_link_type(rtr_link->type)); 889 890 addr.s_addr = rtr_link->nbr_rtr_id; 891 data.s_addr = rtr_link->nbr_iface_id; 892 893 switch (rtr_link->type) { 894 case LINK_TYPE_POINTTOPOINT: 895 case LINK_TYPE_VIRTUAL: 896 printf(" Router ID: %s\n", inet_ntoa(addr)); 897 printf(" Interface ID: %s\n", 898 inet_ntoa(data)); 899 break; 900 case LINK_TYPE_TRANSIT_NET: 901 printf(" Designated Router ID: %s\n", 902 inet_ntoa(addr)); 903 printf(" DR Interface ID: %s\n", 904 inet_ntoa(data)); 905 break; 906 default: 907 printf(" Link ID (Unknown type %d): %s\n", 908 rtr_link->type, inet_ntoa(addr)); 909 printf(" Link Data (Unknown): %s\n", 910 inet_ntoa(data)); 911 break; 912 } 913 914 printf(" Metric: %d\n\n", ntohs(rtr_link->metric)); 915 916 off += sizeof(struct lsa_rtr_link); 917 } 918 919 lasttype = lsa->hdr.type; 920 break; 921 case IMSG_CTL_SHOW_DB_INTRA: 922 lsa = imsg->data; 923 if (lsa->hdr.type != lasttype) 924 show_database_head(area_id, ifname, lsa->hdr.type); 925 show_db_hdr_msg_detail(&lsa->hdr); 926 printf("Referenced LS Type: %s\n", 927 print_ls_type(lsa->data.pref_intra.ref_type)); 928 addr.s_addr = lsa->data.pref_intra.ref_ls_id; 929 printf("Referenced Link State ID: %s\n", inet_ntoa(addr)); 930 addr.s_addr = lsa->data.pref_intra.ref_adv_rtr; 931 printf("Referenced Advertising Router: %s\n", inet_ntoa(addr)); 932 nlinks = ntohs(lsa->data.pref_intra.numprefix); 933 printf("Number of Prefixes: %d\n", nlinks); 934 935 off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix); 936 937 for (i = 0; i < nlinks; i++) { 938 prefix = (struct lsa_prefix *)((char *)lsa + off); 939 bzero(&ia6, sizeof(ia6)); 940 bcopy(prefix + 1, &ia6, 941 LSA_PREFIXSIZE(prefix->prefixlen)); 942 943 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 944 prefix->prefixlen, 945 print_prefix_opt(prefix->options)); 946 947 off += sizeof(struct lsa_prefix) 948 + LSA_PREFIXSIZE(prefix->prefixlen); 949 } 950 951 printf("\n"); 952 lasttype = lsa->hdr.type; 953 break; 954 case IMSG_CTL_SHOW_DB_SUM: 955 lsa = imsg->data; 956 if (lsa->hdr.type != lasttype) 957 show_database_head(area_id, ifname, lsa->hdr.type); 958 show_db_hdr_msg_detail(&lsa->hdr); 959 printf("Prefix: XXX\n"); 960 printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) & 961 LSA_METRIC_MASK); 962 lasttype = lsa->hdr.type; 963 break; 964 case IMSG_CTL_SHOW_DB_ASBR: 965 lsa = imsg->data; 966 if (lsa->hdr.type != lasttype) 967 show_database_head(area_id, ifname, lsa->hdr.type); 968 show_db_hdr_msg_detail(&lsa->hdr); 969 970 addr.s_addr = lsa->data.rtr_sum.dest_rtr_id; 971 printf("Destination Router ID: %s\n", inet_ntoa(addr)); 972 printf("Options: %s\n", 973 print_ospf_options(ntohl(lsa->data.rtr_sum.opts))); 974 printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) & 975 LSA_METRIC_MASK); 976 case IMSG_CTL_AREA: 977 area = imsg->data; 978 area_id = area->id; 979 lasttype = 0; 980 break; 981 case IMSG_CTL_IFACE: 982 iface = imsg->data; 983 strlcpy(ifname, iface->name, sizeof(ifname)); 984 lasttype = 0; 985 break; 986 case IMSG_CTL_END: 987 return (1); 988 default: 989 break; 990 } 991 992 return (0); 993 } 994 995 int 996 show_nbr_msg(struct imsg *imsg) 997 { 998 struct ctl_nbr *nbr; 999 char *state; 1000 1001 switch (imsg->hdr.type) { 1002 case IMSG_CTL_SHOW_NBR: 1003 nbr = imsg->data; 1004 if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state), 1005 if_state_name(nbr->iface_state)) == -1) 1006 err(1, NULL); 1007 printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id), 1008 nbr->priority, state, fmt_timeframe_core(nbr->dead_timer)); 1009 printf("%-11s %s\n", nbr->name, 1010 nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime)); 1011 free(state); 1012 break; 1013 case IMSG_CTL_END: 1014 printf("\n"); 1015 return (1); 1016 default: 1017 break; 1018 } 1019 1020 return (0); 1021 } 1022 1023 const char * 1024 print_ospf_options(u_int32_t opts) 1025 { 1026 static char optbuf[32]; 1027 1028 snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s", 1029 opts & OSPF_OPTION_DC ? "DC" : "-", 1030 opts & OSPF_OPTION_R ? "R" : "-", 1031 opts & OSPF_OPTION_N ? "N" : "-", 1032 opts & OSPF_OPTION_E ? "E" : "-", 1033 opts & OSPF_OPTION_V6 ? "V6" : "-"); 1034 return (optbuf); 1035 } 1036 1037 int 1038 show_nbr_detail_msg(struct imsg *imsg) 1039 { 1040 struct ctl_nbr *nbr; 1041 1042 switch (imsg->hdr.type) { 1043 case IMSG_CTL_SHOW_NBR: 1044 nbr = imsg->data; 1045 printf("\nNeighbor %s, ", inet_ntoa(nbr->id)); 1046 printf("interface address %s\n", log_in6addr(&nbr->addr)); 1047 printf(" Area %s, interface %s\n", inet_ntoa(nbr->area), 1048 nbr->name); 1049 printf(" Neighbor priority is %d, " 1050 "State is %s, %d state changes\n", 1051 nbr->priority, nbr_state_name(nbr->nbr_state), 1052 nbr->state_chng_cnt); 1053 printf(" DR is %s, ", inet_ntoa(nbr->dr)); 1054 printf("BDR is %s\n", inet_ntoa(nbr->bdr)); 1055 printf(" Options %s\n", print_ospf_options(nbr->options)); 1056 printf(" Dead timer due in %s\n", 1057 fmt_timeframe_core(nbr->dead_timer)); 1058 printf(" Uptime %s\n", fmt_timeframe_core(nbr->uptime)); 1059 printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt); 1060 printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt); 1061 printf(" Link State Retransmission List %d\n", 1062 nbr->ls_retrans_lst_cnt); 1063 break; 1064 case IMSG_CTL_END: 1065 printf("\n"); 1066 return (1); 1067 default: 1068 break; 1069 } 1070 1071 return (0); 1072 } 1073 1074 int 1075 show_rib_msg(struct imsg *imsg) 1076 { 1077 struct ctl_rt *rt; 1078 char *dstnet; 1079 1080 switch (imsg->hdr.type) { 1081 case IMSG_CTL_SHOW_RIB: 1082 rt = imsg->data; 1083 switch (rt->d_type) { 1084 case DT_NET: 1085 if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix), 1086 rt->prefixlen) == -1) 1087 err(1, NULL); 1088 break; 1089 case DT_RTR: 1090 if (asprintf(&dstnet, "%s", 1091 log_in6addr(&rt->prefix)) == -1) 1092 err(1, NULL); 1093 break; 1094 default: 1095 errx(1, "Invalid route type"); 1096 } 1097 1098 printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet, 1099 log_in6addr_scope(&rt->nexthop, rt->ifindex), 1100 path_type_name(rt->p_type), dst_type_name(rt->d_type), 1101 rt->cost, 1102 rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime)); 1103 free(dstnet); 1104 break; 1105 case IMSG_CTL_END: 1106 printf("\n"); 1107 return (1); 1108 default: 1109 break; 1110 } 1111 1112 return (0); 1113 } 1114 1115 void 1116 show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type) 1117 { 1118 char *header, *format, *format2; 1119 1120 switch (p_type) { 1121 case PT_INTRA_AREA: 1122 case PT_INTER_AREA: 1123 switch (d_type) { 1124 case DT_NET: 1125 format = "Network Routing Table"; 1126 format2 = ""; 1127 break; 1128 case DT_RTR: 1129 format = "Router Routing Table"; 1130 format2 = "Type"; 1131 break; 1132 default: 1133 errx(1, "unknown route type"); 1134 } 1135 break; 1136 case PT_TYPE1_EXT: 1137 case PT_TYPE2_EXT: 1138 format = NULL; 1139 format2 = "Cost 2"; 1140 if ((header = strdup("External Routing Table")) == NULL) 1141 err(1, NULL); 1142 break; 1143 default: 1144 errx(1, "unknown route type"); 1145 } 1146 1147 if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT) 1148 if (asprintf(&header, "%s (Area %s)", format, 1149 inet_ntoa(aid)) == -1) 1150 err(1, NULL); 1151 1152 printf("\n%-18s %s\n", "", header); 1153 free(header); 1154 1155 printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination", 1156 "Nexthop", "Adv Router", "Path type", "Cost", format2); 1157 } 1158 1159 const char * 1160 print_ospf_rtr_flags(u_int8_t opts) 1161 { 1162 static char optbuf[32]; 1163 1164 snprintf(optbuf, sizeof(optbuf), "%s%s%s", 1165 opts & OSPF_RTR_E ? "AS" : "", 1166 opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "", 1167 opts & OSPF_RTR_B ? "ABR" : ""); 1168 return (optbuf); 1169 } 1170 1171 int 1172 show_rib_detail_msg(struct imsg *imsg) 1173 { 1174 static struct in_addr area_id; 1175 struct ctl_rt *rt; 1176 struct area *area; 1177 char *dstnet; 1178 static u_int8_t lasttype; 1179 1180 switch (imsg->hdr.type) { 1181 case IMSG_CTL_SHOW_RIB: 1182 rt = imsg->data; 1183 1184 switch (rt->p_type) { 1185 case PT_INTRA_AREA: 1186 case PT_INTER_AREA: 1187 switch (rt->d_type) { 1188 case DT_NET: 1189 if (lasttype != RIB_NET) 1190 show_rib_head(rt->area, rt->d_type, 1191 rt->p_type); 1192 if (asprintf(&dstnet, "%s/%d", 1193 log_in6addr(&rt->prefix), 1194 rt->prefixlen) == -1) 1195 err(1, NULL); 1196 lasttype = RIB_NET; 1197 break; 1198 case DT_RTR: 1199 if (lasttype != RIB_RTR) 1200 show_rib_head(rt->area, rt->d_type, 1201 rt->p_type); 1202 if (asprintf(&dstnet, "%s", 1203 log_in6addr(&rt->prefix)) == -1) 1204 err(1, NULL); 1205 lasttype = RIB_RTR; 1206 break; 1207 default: 1208 errx(1, "unknown route type"); 1209 } 1210 printf("%-18s %-15s ", dstnet, 1211 log_in6addr_scope(&rt->nexthop, rt->ifindex)); 1212 printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr), 1213 path_type_name(rt->p_type), rt->cost); 1214 free(dstnet); 1215 1216 if (rt->d_type == DT_RTR) 1217 printf(" %-7s", 1218 print_ospf_rtr_flags(rt->flags)); 1219 1220 printf("\n"); 1221 break; 1222 case PT_TYPE1_EXT: 1223 case PT_TYPE2_EXT: 1224 if (lasttype != RIB_EXT) 1225 show_rib_head(rt->area, rt->d_type, rt->p_type); 1226 1227 if (asprintf(&dstnet, "%s/%d", 1228 log_in6addr(&rt->prefix), rt->prefixlen) == -1) 1229 err(1, NULL); 1230 1231 printf("%-18s %-15s ", dstnet, 1232 log_in6addr_scope(&rt->nexthop, rt->ifindex)); 1233 printf("%-15s %-12s %-7d %-7d\n", 1234 inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type), 1235 rt->cost, rt->cost2); 1236 free(dstnet); 1237 1238 lasttype = RIB_EXT; 1239 break; 1240 default: 1241 errx(1, "unknown route type"); 1242 } 1243 break; 1244 case IMSG_CTL_AREA: 1245 area = imsg->data; 1246 area_id = area->id; 1247 break; 1248 case IMSG_CTL_END: 1249 printf("\n"); 1250 return (1); 1251 default: 1252 break; 1253 } 1254 1255 return (0); 1256 } 1257 1258 void 1259 show_fib_head(void) 1260 { 1261 printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n"); 1262 printf("%-6s %-4s %-20s %-17s\n", 1263 "Flags", "Prio", "Destination", "Nexthop"); 1264 } 1265 1266 int 1267 show_fib_msg(struct imsg *imsg) 1268 { 1269 struct kroute *k; 1270 char *p; 1271 1272 switch (imsg->hdr.type) { 1273 case IMSG_CTL_KROUTE: 1274 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 1275 errx(1, "wrong imsg len"); 1276 k = imsg->data; 1277 1278 if (k->flags & F_DOWN) 1279 printf(" "); 1280 else 1281 printf("*"); 1282 1283 if (!(k->flags & F_KERNEL)) 1284 printf("O"); 1285 else if (k->flags & F_CONNECTED) 1286 printf("C"); 1287 else if (k->flags & F_STATIC) 1288 printf("S"); 1289 else 1290 printf(" "); 1291 1292 printf(" "); 1293 printf("%4d ", k->priority); 1294 if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix), 1295 k->prefixlen) == -1) 1296 err(1, NULL); 1297 printf("%-20s ", p); 1298 free(p); 1299 1300 if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop)) 1301 printf("%s", log_in6addr_scope(&k->nexthop, k->scope)); 1302 else if (k->flags & F_CONNECTED) 1303 printf("link#%u", k->ifindex); 1304 printf("\n"); 1305 1306 break; 1307 case IMSG_CTL_END: 1308 printf("\n"); 1309 return (1); 1310 default: 1311 break; 1312 } 1313 1314 return (0); 1315 } 1316 1317 const struct if_status_description 1318 if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; 1319 const struct ifmedia_description 1320 ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 1321 1322 const char * 1323 get_media_descr(uint64_t media_type) 1324 { 1325 const struct ifmedia_description *p; 1326 1327 for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 1328 if (media_type == p->ifmt_word) 1329 return (p->ifmt_string); 1330 1331 return ("unknown"); 1332 } 1333 1334 const char * 1335 get_linkstate(uint8_t if_type, int link_state) 1336 { 1337 const struct if_status_description *p; 1338 static char buf[8]; 1339 1340 for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 1341 if (LINK_STATE_DESC_MATCH(p, if_type, link_state)) 1342 return (p->ifs_string); 1343 } 1344 snprintf(buf, sizeof(buf), "[#%d]", link_state); 1345 return (buf); 1346 } 1347 1348 void 1349 print_baudrate(u_int64_t baudrate) 1350 { 1351 if (baudrate > IF_Gbps(1)) 1352 printf("%llu GBit/s", baudrate / IF_Gbps(1)); 1353 else if (baudrate > IF_Mbps(1)) 1354 printf("%llu MBit/s", baudrate / IF_Mbps(1)); 1355 else if (baudrate > IF_Kbps(1)) 1356 printf("%llu KBit/s", baudrate / IF_Kbps(1)); 1357 else 1358 printf("%llu Bit/s", baudrate); 1359 } 1360