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