1 /* $OpenBSD: ospf6ctl.c,v 1.43 2015/12/05 13:12:40 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <sys/un.h> 24 #include <netinet/in.h> 25 #include <arpa/inet.h> 26 #include <net/if_media.h> 27 #include <net/if_types.h> 28 29 #include <err.h> 30 #include <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", 413 get_media_descr(get_ifms_type(iface->if_type)), 414 get_linkstate(iface->if_type, iface->linkstate)); 415 if (iface->linkstate != LINK_STATE_DOWN && 416 iface->baudrate > 0) { 417 printf(", "); 418 print_baudrate(iface->baudrate); 419 } 420 printf("\n"); 421 printf(" Router ID %s, network type %s, cost: %d\n", 422 inet_ntoa(iface->rtr_id), 423 if_type_name(iface->type), iface->metric); 424 printf(" Transmit delay is %d sec(s), state %s, priority %d\n", 425 iface->transmit_delay, if_state_name(iface->state), 426 iface->priority); 427 printf(" Designated Router (ID) %s\n", 428 inet_ntoa(iface->dr_id)); 429 printf(" Interface address %s\n", 430 log_in6addr(&iface->dr_addr)); 431 printf(" Backup Designated Router (ID) %s\n", 432 inet_ntoa(iface->bdr_id)); 433 printf(" Interface address %s\n", 434 log_in6addr(&iface->bdr_addr)); 435 printf(" Timer intervals configured, " 436 "hello %d, dead %d, wait %d, retransmit %d\n", 437 iface->hello_interval, iface->dead_interval, 438 iface->dead_interval, iface->rxmt_interval); 439 if (iface->passive) 440 printf(" Passive interface (No Hellos)\n"); 441 else if (iface->hello_timer < 0) 442 printf(" Hello timer not running\n"); 443 else 444 printf(" Hello timer due in %s\n", 445 fmt_timeframe_core(iface->hello_timer)); 446 printf(" Uptime %s\n", fmt_timeframe_core(iface->uptime)); 447 printf(" Neighbor count is %d, adjacent neighbor count is " 448 "%d\n", iface->nbr_cnt, iface->adj_cnt); 449 break; 450 case IMSG_CTL_END: 451 printf("\n"); 452 return (1); 453 default: 454 break; 455 } 456 457 return (0); 458 } 459 460 const char * 461 print_link(int state) 462 { 463 if (state & IFF_UP) 464 return ("UP"); 465 else 466 return ("DOWN"); 467 } 468 469 #define TF_BUFS 8 470 #define TF_LEN 9 471 472 const char * 473 fmt_timeframe(time_t t) 474 { 475 if (t == 0) 476 return ("Never"); 477 else 478 return (fmt_timeframe_core(time(NULL) - t)); 479 } 480 481 const char * 482 fmt_timeframe_core(time_t t) 483 { 484 char *buf; 485 static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 486 static int idx = 0; 487 unsigned int sec, min, hrs, day, week; 488 489 if (t == 0) 490 return ("00:00:00"); 491 492 buf = tfbuf[idx++]; 493 if (idx == TF_BUFS) 494 idx = 0; 495 496 week = t; 497 498 sec = week % 60; 499 week /= 60; 500 min = week % 60; 501 week /= 60; 502 hrs = week % 24; 503 week /= 24; 504 day = week % 7; 505 week /= 7; 506 507 if (week > 0) 508 snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); 509 else if (day > 0) 510 snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 511 else 512 snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 513 514 return (buf); 515 } 516 517 const char * 518 log_id(u_int32_t id) 519 { 520 static char buf[48]; 521 struct in_addr addr; 522 523 addr.s_addr = id; 524 525 if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 526 return ("?"); 527 else 528 return (buf); 529 } 530 531 const char * 532 log_adv_rtr(u_int32_t adv_rtr) 533 { 534 static char buf[48]; 535 struct in_addr addr; 536 537 addr.s_addr = adv_rtr; 538 539 if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 540 return ("?"); 541 else 542 return (buf); 543 } 544 545 void 546 show_database_head(struct in_addr aid, char *ifname, u_int16_t type) 547 { 548 char *header, *format; 549 int cleanup = 0; 550 551 switch (ntohs(type)) { 552 case LSA_TYPE_LINK: 553 format = "Link (Type-8) Link States"; 554 break; 555 case LSA_TYPE_ROUTER: 556 format = "Router Link States"; 557 break; 558 case LSA_TYPE_NETWORK: 559 format = "Net Link States"; 560 break; 561 case LSA_TYPE_INTER_A_PREFIX: 562 format = "Inter Area Prefix Link States"; 563 break; 564 case LSA_TYPE_INTER_A_ROUTER: 565 format = "Inter Area Router Link States"; 566 break; 567 case LSA_TYPE_INTRA_A_PREFIX: 568 format = "Intra Area Prefix Link States"; 569 break; 570 case LSA_TYPE_EXTERNAL: 571 printf("\n%-15s %s\n\n", "", "Type-5 AS External Link States"); 572 return; 573 default: 574 if (asprintf(&format, "LSA type %x", ntohs(type)) == -1) 575 err(1, NULL); 576 cleanup = 1; 577 break; 578 } 579 if (LSA_IS_SCOPE_AREA(ntohs(type))) { 580 if (asprintf(&header, "%s (Area %s)", format, 581 inet_ntoa(aid)) == -1) 582 err(1, NULL); 583 } else if (LSA_IS_SCOPE_LLOCAL(ntohs(type))) { 584 if (asprintf(&header, "%s (Area %s Interface %s)", format, 585 inet_ntoa(aid), ifname) == -1) 586 err(1, NULL); 587 } 588 589 printf("\n%-15s %s\n\n", "", header); 590 free(header); 591 if (cleanup) 592 free(format); 593 } 594 595 int 596 show_database_msg(struct imsg *imsg) 597 { 598 static struct in_addr area_id; 599 static char ifname[IF_NAMESIZE]; 600 static u_int16_t lasttype; 601 struct area *area; 602 struct iface *iface; 603 struct lsa_hdr *lsa; 604 605 switch (imsg->hdr.type) { 606 case IMSG_CTL_SHOW_DATABASE: 607 case IMSG_CTL_SHOW_DB_SELF: 608 lsa = imsg->data; 609 if (lsa->type != lasttype) { 610 show_database_head(area_id, ifname, lsa->type); 611 printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID", 612 "Adv Router", "Age", "Seq#", "Checksum"); 613 } 614 printf("%-15s %-15s %-4d 0x%08x 0x%04x\n", 615 log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr), 616 ntohs(lsa->age), ntohl(lsa->seq_num), 617 ntohs(lsa->ls_chksum)); 618 lasttype = lsa->type; 619 break; 620 case IMSG_CTL_AREA: 621 area = imsg->data; 622 area_id = area->id; 623 lasttype = 0; 624 break; 625 case IMSG_CTL_IFACE: 626 iface = imsg->data; 627 strlcpy(ifname, iface->name, sizeof(ifname)); 628 lasttype = 0; 629 break; 630 case IMSG_CTL_END: 631 printf("\n"); 632 return (1); 633 default: 634 break; 635 } 636 637 return (0); 638 } 639 640 char * 641 print_ls_type(u_int16_t type) 642 { 643 switch (ntohs(type)) { 644 case LSA_TYPE_LINK: 645 return ("Link"); 646 case LSA_TYPE_ROUTER: 647 return ("Router"); 648 case LSA_TYPE_NETWORK: 649 return ("Network"); 650 case LSA_TYPE_INTER_A_PREFIX: 651 return ("Inter Area (Prefix)"); 652 case LSA_TYPE_INTER_A_ROUTER: 653 return ("Inter Area (Router)"); 654 case LSA_TYPE_INTRA_A_PREFIX: 655 return ("Intra Area (Prefix)"); 656 case LSA_TYPE_EXTERNAL: 657 return ("AS External"); 658 default: 659 return ("Unknown"); 660 } 661 } 662 663 void 664 show_db_hdr_msg_detail(struct lsa_hdr *lsa) 665 { 666 printf("LS age: %d\n", ntohs(lsa->age)); 667 printf("LS Type: %s\n", print_ls_type(lsa->type)); 668 669 switch (ntohs(lsa->type)) { 670 case LSA_TYPE_ROUTER: 671 case LSA_TYPE_INTER_A_PREFIX: 672 case LSA_TYPE_INTER_A_ROUTER: 673 case LSA_TYPE_INTRA_A_PREFIX: 674 case LSA_TYPE_EXTERNAL: 675 printf("Link State ID: %s\n", log_id(lsa->ls_id)); 676 break; 677 case LSA_TYPE_LINK: 678 printf("Link State ID: %s (Interface ID of Advertising " 679 "Router)\n", log_id(lsa->ls_id)); 680 break; 681 case LSA_TYPE_NETWORK: 682 printf("Link State ID: %s (Interface ID of Designated " 683 "Router)\n", log_id(lsa->ls_id)); 684 break; 685 } 686 687 printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr)); 688 printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num)); 689 printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum)); 690 printf("Length: %d\n", ntohs(lsa->len)); 691 } 692 693 char * 694 print_rtr_link_type(u_int8_t type) 695 { 696 switch (type) { 697 case LINK_TYPE_POINTTOPOINT: 698 return ("Point-to-Point"); 699 case LINK_TYPE_TRANSIT_NET: 700 return ("Transit Network"); 701 case LINK_TYPE_RESERVED: 702 return ("Reserved"); 703 case LINK_TYPE_VIRTUAL: 704 return ("Virtual Link"); 705 default: 706 return ("Unknown"); 707 } 708 } 709 710 const char * 711 print_ospf_flags(u_int8_t opts) 712 { 713 static char optbuf[32]; 714 715 snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s", 716 opts & OSPF_RTR_V ? "V" : "-", 717 opts & OSPF_RTR_E ? "E" : "-", 718 opts & OSPF_RTR_B ? "B" : "-"); 719 return (optbuf); 720 } 721 722 const char * 723 print_asext_flags(u_int32_t opts) 724 { 725 static char optbuf[32]; 726 727 snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s", 728 opts & LSA_ASEXT_E_FLAG ? "E" : "-", 729 opts & LSA_ASEXT_F_FLAG ? "F" : "-", 730 opts & LSA_ASEXT_T_FLAG ? "T" : "-"); 731 return (optbuf); 732 } 733 734 const char * 735 print_prefix_opt(u_int8_t opts) 736 { 737 static char optbuf[32]; 738 739 if (opts) { 740 snprintf(optbuf, sizeof(optbuf), 741 " Options: *|*|*|%s|%s|x|%s|%s", 742 opts & OSPF_PREFIX_DN ? "DN" : "-", 743 opts & OSPF_PREFIX_P ? "P" : "-", 744 opts & OSPF_PREFIX_LA ? "LA" : "-", 745 opts & OSPF_PREFIX_NU ? "NU" : "-"); 746 return (optbuf); 747 } 748 return (""); 749 } 750 751 int 752 show_db_msg_detail(struct imsg *imsg) 753 { 754 static struct in_addr area_id; 755 static char ifname[IF_NAMESIZE]; 756 static u_int16_t lasttype; 757 struct in6_addr ia6; 758 struct in_addr addr, data; 759 struct area *area; 760 struct iface *iface; 761 struct lsa *lsa; 762 struct lsa_rtr_link *rtr_link; 763 struct lsa_net_link *net_link; 764 struct lsa_prefix *prefix; 765 struct lsa_asext *asext; 766 u_int32_t ext_tag; 767 u_int16_t i, nlinks, off; 768 769 /* XXX sanity checks! */ 770 771 switch (imsg->hdr.type) { 772 case IMSG_CTL_SHOW_DB_EXT: 773 lsa = imsg->data; 774 if (lsa->hdr.type != lasttype) 775 show_database_head(area_id, ifname, lsa->hdr.type); 776 show_db_hdr_msg_detail(&lsa->hdr); 777 778 asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr)); 779 780 printf(" Flags: %s\n", 781 print_asext_flags(ntohl(lsa->data.asext.metric))); 782 printf(" Metric: %d Type: ", ntohl(asext->metric) 783 & LSA_METRIC_MASK); 784 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG) 785 printf("2\n"); 786 else 787 printf("1\n"); 788 789 prefix = &asext->prefix; 790 bzero(&ia6, sizeof(ia6)); 791 bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen)); 792 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 793 prefix->prefixlen, print_prefix_opt(prefix->options)); 794 795 off = sizeof(*asext) + LSA_PREFIXSIZE(prefix->prefixlen); 796 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_F_FLAG) { 797 bcopy((char *)asext + off, &ia6, sizeof(ia6)); 798 printf(" Forwarding Address: %s\n", 799 log_in6addr(&ia6)); 800 off += sizeof(ia6); 801 } 802 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_T_FLAG) { 803 bcopy((char *)asext + off, &ext_tag, sizeof(ext_tag)); 804 printf(" External Route Tag: %d\n", ntohl(ext_tag)); 805 } 806 printf("\n"); 807 lasttype = lsa->hdr.type; 808 break; 809 case IMSG_CTL_SHOW_DB_LINK: 810 lsa = imsg->data; 811 if (lsa->hdr.type != lasttype) 812 show_database_head(area_id, ifname, lsa->hdr.type); 813 show_db_hdr_msg_detail(&lsa->hdr); 814 printf("Options: %s\n", print_ospf_options(LSA_24_GETLO( 815 ntohl(lsa->data.link.opts)))); 816 printf("Link Local Address: %s\n", 817 log_in6addr(&lsa->data.link.lladdr)); 818 819 nlinks = ntohl(lsa->data.link.numprefix); 820 printf("Number of Prefixes: %d\n", nlinks); 821 off = sizeof(lsa->hdr) + sizeof(struct lsa_link); 822 823 for (i = 0; i < nlinks; i++) { 824 prefix = (struct lsa_prefix *)((char *)lsa + off); 825 bzero(&ia6, sizeof(ia6)); 826 bcopy(prefix + 1, &ia6, 827 LSA_PREFIXSIZE(prefix->prefixlen)); 828 829 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 830 prefix->prefixlen, 831 print_prefix_opt(prefix->options)); 832 833 off += sizeof(struct lsa_prefix) 834 + LSA_PREFIXSIZE(prefix->prefixlen); 835 } 836 837 printf("\n"); 838 lasttype = lsa->hdr.type; 839 break; 840 case IMSG_CTL_SHOW_DB_NET: 841 lsa = imsg->data; 842 if (lsa->hdr.type != lasttype) 843 show_database_head(area_id, ifname, lsa->hdr.type); 844 show_db_hdr_msg_detail(&lsa->hdr); 845 printf("Options: %s\n", 846 print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.net.opts)))); 847 848 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) - 849 sizeof(struct lsa_net)) / sizeof(struct lsa_net_link); 850 net_link = (struct lsa_net_link *)((char *)lsa + 851 sizeof(lsa->hdr) + sizeof(lsa->data.net)); 852 printf("Number of Routers: %d\n", nlinks); 853 854 for (i = 0; i < nlinks; i++) { 855 addr.s_addr = net_link->att_rtr; 856 printf(" Attached Router: %s\n", inet_ntoa(addr)); 857 net_link++; 858 } 859 860 printf("\n"); 861 lasttype = lsa->hdr.type; 862 break; 863 case IMSG_CTL_SHOW_DB_RTR: 864 lsa = imsg->data; 865 if (lsa->hdr.type != lasttype) 866 show_database_head(area_id, ifname, lsa->hdr.type); 867 show_db_hdr_msg_detail(&lsa->hdr); 868 printf("Flags: %s\n", 869 print_ospf_flags(LSA_24_GETHI(ntohl(lsa->data.rtr.opts)))); 870 printf("Options: %s\n", 871 print_ospf_options(LSA_24_GETLO(ntohl(lsa->data.rtr.opts)))); 872 873 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) 874 - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link); 875 printf("Number of Links: %d\n\n", nlinks); 876 877 off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr); 878 879 for (i = 0; i < nlinks; i++) { 880 rtr_link = (struct lsa_rtr_link *)((char *)lsa + off); 881 882 printf(" Link (Interface ID %s) connected to: %s\n", 883 log_id(rtr_link->iface_id), 884 print_rtr_link_type(rtr_link->type)); 885 886 addr.s_addr = rtr_link->nbr_rtr_id; 887 data.s_addr = rtr_link->nbr_iface_id; 888 889 switch (rtr_link->type) { 890 case LINK_TYPE_POINTTOPOINT: 891 case LINK_TYPE_VIRTUAL: 892 printf(" Router ID: %s\n", inet_ntoa(addr)); 893 printf(" Interface ID: %s\n", 894 inet_ntoa(data)); 895 break; 896 case LINK_TYPE_TRANSIT_NET: 897 printf(" Designated Router ID: %s\n", 898 inet_ntoa(addr)); 899 printf(" DR Interface ID: %s\n", 900 inet_ntoa(data)); 901 break; 902 default: 903 printf(" Link ID (Unknown type %d): %s\n", 904 rtr_link->type, inet_ntoa(addr)); 905 printf(" Link Data (Unknown): %s\n", 906 inet_ntoa(data)); 907 break; 908 } 909 910 printf(" Metric: %d\n\n", ntohs(rtr_link->metric)); 911 912 off += sizeof(struct lsa_rtr_link); 913 } 914 915 lasttype = lsa->hdr.type; 916 break; 917 case IMSG_CTL_SHOW_DB_INTRA: 918 lsa = imsg->data; 919 if (lsa->hdr.type != lasttype) 920 show_database_head(area_id, ifname, lsa->hdr.type); 921 show_db_hdr_msg_detail(&lsa->hdr); 922 printf("Referenced LS Type: %s\n", 923 print_ls_type(lsa->data.pref_intra.ref_type)); 924 addr.s_addr = lsa->data.pref_intra.ref_ls_id; 925 printf("Referenced Link State ID: %s\n", inet_ntoa(addr)); 926 addr.s_addr = lsa->data.pref_intra.ref_adv_rtr; 927 printf("Referenced Advertising Router: %s\n", inet_ntoa(addr)); 928 nlinks = ntohs(lsa->data.pref_intra.numprefix); 929 printf("Number of Prefixes: %d\n", nlinks); 930 931 off = sizeof(lsa->hdr) + sizeof(struct lsa_intra_prefix); 932 933 for (i = 0; i < nlinks; i++) { 934 prefix = (struct lsa_prefix *)((char *)lsa + off); 935 bzero(&ia6, sizeof(ia6)); 936 bcopy(prefix + 1, &ia6, 937 LSA_PREFIXSIZE(prefix->prefixlen)); 938 939 printf(" Prefix: %s/%d%s\n", log_in6addr(&ia6), 940 prefix->prefixlen, 941 print_prefix_opt(prefix->options)); 942 943 off += sizeof(struct lsa_prefix) 944 + LSA_PREFIXSIZE(prefix->prefixlen); 945 } 946 947 printf("\n"); 948 lasttype = lsa->hdr.type; 949 break; 950 case IMSG_CTL_SHOW_DB_SUM: 951 lsa = imsg->data; 952 if (lsa->hdr.type != lasttype) 953 show_database_head(area_id, ifname, lsa->hdr.type); 954 show_db_hdr_msg_detail(&lsa->hdr); 955 printf("Prefix: XXX\n"); 956 printf("Metric: %d\n", ntohl(lsa->data.pref_sum.metric) & 957 LSA_METRIC_MASK); 958 lasttype = lsa->hdr.type; 959 break; 960 case IMSG_CTL_SHOW_DB_ASBR: 961 lsa = imsg->data; 962 if (lsa->hdr.type != lasttype) 963 show_database_head(area_id, ifname, lsa->hdr.type); 964 show_db_hdr_msg_detail(&lsa->hdr); 965 966 addr.s_addr = lsa->data.rtr_sum.dest_rtr_id; 967 printf("Destination Router ID: %s\n", inet_ntoa(addr)); 968 printf("Options: %s\n", 969 print_ospf_options(ntohl(lsa->data.rtr_sum.opts))); 970 printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) & 971 LSA_METRIC_MASK); 972 case IMSG_CTL_AREA: 973 area = imsg->data; 974 area_id = area->id; 975 lasttype = 0; 976 break; 977 case IMSG_CTL_IFACE: 978 iface = imsg->data; 979 strlcpy(ifname, iface->name, sizeof(ifname)); 980 lasttype = 0; 981 break; 982 case IMSG_CTL_END: 983 return (1); 984 default: 985 break; 986 } 987 988 return (0); 989 } 990 991 int 992 show_nbr_msg(struct imsg *imsg) 993 { 994 struct ctl_nbr *nbr; 995 char *state; 996 997 switch (imsg->hdr.type) { 998 case IMSG_CTL_SHOW_NBR: 999 nbr = imsg->data; 1000 if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state), 1001 if_state_name(nbr->iface_state)) == -1) 1002 err(1, NULL); 1003 printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id), 1004 nbr->priority, state, fmt_timeframe_core(nbr->dead_timer)); 1005 printf("%-11s %s\n", nbr->name, 1006 nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime)); 1007 free(state); 1008 break; 1009 case IMSG_CTL_END: 1010 printf("\n"); 1011 return (1); 1012 default: 1013 break; 1014 } 1015 1016 return (0); 1017 } 1018 1019 const char * 1020 print_ospf_options(u_int32_t opts) 1021 { 1022 static char optbuf[32]; 1023 1024 snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|*|%s|%s", 1025 opts & OSPF_OPTION_DC ? "DC" : "-", 1026 opts & OSPF_OPTION_R ? "R" : "-", 1027 opts & OSPF_OPTION_N ? "N" : "-", 1028 opts & OSPF_OPTION_E ? "E" : "-", 1029 opts & OSPF_OPTION_V6 ? "V6" : "-"); 1030 return (optbuf); 1031 } 1032 1033 int 1034 show_nbr_detail_msg(struct imsg *imsg) 1035 { 1036 struct ctl_nbr *nbr; 1037 1038 switch (imsg->hdr.type) { 1039 case IMSG_CTL_SHOW_NBR: 1040 nbr = imsg->data; 1041 printf("\nNeighbor %s, ", inet_ntoa(nbr->id)); 1042 printf("interface address %s\n", log_in6addr(&nbr->addr)); 1043 printf(" Area %s, interface %s\n", inet_ntoa(nbr->area), 1044 nbr->name); 1045 printf(" Neighbor priority is %d, " 1046 "State is %s, %d state changes\n", 1047 nbr->priority, nbr_state_name(nbr->nbr_state), 1048 nbr->state_chng_cnt); 1049 printf(" DR is %s, ", inet_ntoa(nbr->dr)); 1050 printf("BDR is %s\n", inet_ntoa(nbr->bdr)); 1051 printf(" Options %s\n", print_ospf_options(nbr->options)); 1052 printf(" Dead timer due in %s\n", 1053 fmt_timeframe_core(nbr->dead_timer)); 1054 printf(" Uptime %s\n", fmt_timeframe_core(nbr->uptime)); 1055 printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt); 1056 printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt); 1057 printf(" Link State Retransmission List %d\n", 1058 nbr->ls_retrans_lst_cnt); 1059 break; 1060 case IMSG_CTL_END: 1061 printf("\n"); 1062 return (1); 1063 default: 1064 break; 1065 } 1066 1067 return (0); 1068 } 1069 1070 int 1071 show_rib_msg(struct imsg *imsg) 1072 { 1073 struct ctl_rt *rt; 1074 char *dstnet; 1075 1076 switch (imsg->hdr.type) { 1077 case IMSG_CTL_SHOW_RIB: 1078 rt = imsg->data; 1079 switch (rt->d_type) { 1080 case DT_NET: 1081 if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix), 1082 rt->prefixlen) == -1) 1083 err(1, NULL); 1084 break; 1085 case DT_RTR: 1086 if (asprintf(&dstnet, "%s", 1087 log_in6addr(&rt->prefix)) == -1) 1088 err(1, NULL); 1089 break; 1090 default: 1091 errx(1, "Invalid route type"); 1092 } 1093 1094 printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet, 1095 log_in6addr_scope(&rt->nexthop, rt->ifindex), 1096 path_type_name(rt->p_type), dst_type_name(rt->d_type), 1097 rt->cost, 1098 rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime)); 1099 free(dstnet); 1100 break; 1101 case IMSG_CTL_END: 1102 printf("\n"); 1103 return (1); 1104 default: 1105 break; 1106 } 1107 1108 return (0); 1109 } 1110 1111 void 1112 show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type) 1113 { 1114 char *header, *format, *format2; 1115 1116 switch (p_type) { 1117 case PT_INTRA_AREA: 1118 case PT_INTER_AREA: 1119 switch (d_type) { 1120 case DT_NET: 1121 format = "Network Routing Table"; 1122 format2 = ""; 1123 break; 1124 case DT_RTR: 1125 format = "Router Routing Table"; 1126 format2 = "Type"; 1127 break; 1128 default: 1129 errx(1, "unknown route type"); 1130 } 1131 break; 1132 case PT_TYPE1_EXT: 1133 case PT_TYPE2_EXT: 1134 format = NULL; 1135 format2 = "Cost 2"; 1136 if ((header = strdup("External Routing Table")) == NULL) 1137 err(1, NULL); 1138 break; 1139 default: 1140 errx(1, "unknown route type"); 1141 } 1142 1143 if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT) 1144 if (asprintf(&header, "%s (Area %s)", format, 1145 inet_ntoa(aid)) == -1) 1146 err(1, NULL); 1147 1148 printf("\n%-18s %s\n", "", header); 1149 free(header); 1150 1151 printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination", 1152 "Nexthop", "Adv Router", "Path type", "Cost", format2); 1153 } 1154 1155 const char * 1156 print_ospf_rtr_flags(u_int8_t opts) 1157 { 1158 static char optbuf[32]; 1159 1160 snprintf(optbuf, sizeof(optbuf), "%s%s%s", 1161 opts & OSPF_RTR_E ? "AS" : "", 1162 opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "", 1163 opts & OSPF_RTR_B ? "ABR" : ""); 1164 return (optbuf); 1165 } 1166 1167 int 1168 show_rib_detail_msg(struct imsg *imsg) 1169 { 1170 static struct in_addr area_id; 1171 struct ctl_rt *rt; 1172 struct area *area; 1173 char *dstnet; 1174 static u_int8_t lasttype; 1175 1176 switch (imsg->hdr.type) { 1177 case IMSG_CTL_SHOW_RIB: 1178 rt = imsg->data; 1179 1180 switch (rt->p_type) { 1181 case PT_INTRA_AREA: 1182 case PT_INTER_AREA: 1183 switch (rt->d_type) { 1184 case DT_NET: 1185 if (lasttype != RIB_NET) 1186 show_rib_head(rt->area, rt->d_type, 1187 rt->p_type); 1188 if (asprintf(&dstnet, "%s/%d", 1189 log_in6addr(&rt->prefix), 1190 rt->prefixlen) == -1) 1191 err(1, NULL); 1192 lasttype = RIB_NET; 1193 break; 1194 case DT_RTR: 1195 if (lasttype != RIB_RTR) 1196 show_rib_head(rt->area, rt->d_type, 1197 rt->p_type); 1198 if (asprintf(&dstnet, "%s", 1199 log_in6addr(&rt->prefix)) == -1) 1200 err(1, NULL); 1201 lasttype = RIB_RTR; 1202 break; 1203 default: 1204 errx(1, "unknown route type"); 1205 } 1206 printf("%-18s %-15s ", dstnet, 1207 log_in6addr_scope(&rt->nexthop, rt->ifindex)); 1208 printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr), 1209 path_type_name(rt->p_type), rt->cost); 1210 free(dstnet); 1211 1212 if (rt->d_type == DT_RTR) 1213 printf(" %-7s", 1214 print_ospf_rtr_flags(rt->flags)); 1215 1216 printf("\n"); 1217 break; 1218 case PT_TYPE1_EXT: 1219 case PT_TYPE2_EXT: 1220 if (lasttype != RIB_EXT) 1221 show_rib_head(rt->area, rt->d_type, rt->p_type); 1222 1223 if (asprintf(&dstnet, "%s/%d", 1224 log_in6addr(&rt->prefix), rt->prefixlen) == -1) 1225 err(1, NULL); 1226 1227 printf("%-18s %-15s ", dstnet, 1228 log_in6addr_scope(&rt->nexthop, rt->ifindex)); 1229 printf("%-15s %-12s %-7d %-7d\n", 1230 inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type), 1231 rt->cost, rt->cost2); 1232 free(dstnet); 1233 1234 lasttype = RIB_EXT; 1235 break; 1236 default: 1237 errx(1, "unknown route type"); 1238 } 1239 break; 1240 case IMSG_CTL_AREA: 1241 area = imsg->data; 1242 area_id = area->id; 1243 break; 1244 case IMSG_CTL_END: 1245 printf("\n"); 1246 return (1); 1247 default: 1248 break; 1249 } 1250 1251 return (0); 1252 } 1253 1254 void 1255 show_fib_head(void) 1256 { 1257 printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n"); 1258 printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop"); 1259 } 1260 1261 int 1262 show_fib_msg(struct imsg *imsg) 1263 { 1264 struct kroute *k; 1265 char *p; 1266 1267 switch (imsg->hdr.type) { 1268 case IMSG_CTL_KROUTE: 1269 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 1270 errx(1, "wrong imsg len"); 1271 k = imsg->data; 1272 1273 if (k->flags & F_DOWN) 1274 printf(" "); 1275 else 1276 printf("*"); 1277 1278 if (!(k->flags & F_KERNEL)) 1279 printf("O"); 1280 else if (k->flags & F_CONNECTED) 1281 printf("C"); 1282 else if (k->flags & F_STATIC) 1283 printf("S"); 1284 else 1285 printf(" "); 1286 1287 printf(" "); 1288 if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix), 1289 k->prefixlen) == -1) 1290 err(1, NULL); 1291 printf("%-20s ", p); 1292 free(p); 1293 1294 if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop)) 1295 printf("%s", log_in6addr_scope(&k->nexthop, k->scope)); 1296 else if (k->flags & F_CONNECTED) 1297 printf("link#%u", k->ifindex); 1298 printf("\n"); 1299 1300 break; 1301 case IMSG_CTL_END: 1302 printf("\n"); 1303 return (1); 1304 default: 1305 break; 1306 } 1307 1308 return (0); 1309 } 1310 1311 const struct if_status_description 1312 if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; 1313 const struct ifmedia_description 1314 ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 1315 1316 const char * 1317 get_media_descr(uint64_t media_type) 1318 { 1319 const struct ifmedia_description *p; 1320 1321 for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 1322 if (media_type == p->ifmt_word) 1323 return (p->ifmt_string); 1324 1325 return ("unknown"); 1326 } 1327 1328 const char * 1329 get_linkstate(uint8_t if_type, int link_state) 1330 { 1331 const struct if_status_description *p; 1332 static char buf[8]; 1333 1334 for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 1335 if (LINK_STATE_DESC_MATCH(p, if_type, link_state)) 1336 return (p->ifs_string); 1337 } 1338 snprintf(buf, sizeof(buf), "[#%d]", link_state); 1339 return (buf); 1340 } 1341 1342 void 1343 print_baudrate(u_int64_t baudrate) 1344 { 1345 if (baudrate > IF_Gbps(1)) 1346 printf("%llu GBit/s", baudrate / IF_Gbps(1)); 1347 else if (baudrate > IF_Mbps(1)) 1348 printf("%llu MBit/s", baudrate / IF_Mbps(1)); 1349 else if (baudrate > IF_Kbps(1)) 1350 printf("%llu KBit/s", baudrate / IF_Kbps(1)); 1351 else 1352 printf("%llu Bit/s", baudrate); 1353 } 1354