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