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