eigrpctl.c revision 1.2
1/* $OpenBSD: eigrpctl.c,v 1.2 2015/10/10 05:06:00 renato Exp $ */ 2 3/* 4 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org> 5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 7 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22#include <sys/types.h> 23#include <sys/socket.h> 24#include <sys/un.h> 25#include <netinet/in.h> 26#include <arpa/inet.h> 27#include <net/if_media.h> 28#include <net/if_types.h> 29 30#include <err.h> 31#include <errno.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include <unistd.h> 36 37#include "eigrp.h" 38#include "eigrpd.h" 39#include "eigrpe.h" 40#include "rde.h" 41#include "log.h" 42#include "parser.h" 43 44__dead void usage(void); 45uint64_t get_ifms_type(uint8_t); 46int show_interface_msg(struct imsg *, struct parse_result *); 47int show_interface_detail_msg(struct imsg *, 48 struct parse_result *); 49const char *print_link(int); 50const char *fmt_timeframe_core(time_t); 51int show_nbr_msg(struct imsg *, struct parse_result *); 52int show_topology_msg(struct imsg *, struct parse_result *); 53int show_topology_detail_msg(struct imsg *, 54 struct parse_result *); 55void show_fib_head(void); 56int show_fib_msg(struct imsg *, struct parse_result *); 57void show_interface_head(void); 58const char * get_media_descr(uint64_t); 59const char * get_linkstate(uint8_t, int); 60void print_baudrate(uint64_t); 61int show_fib_interface_msg(struct imsg *); 62 63struct imsgbuf *ibuf; 64 65__dead void 66usage(void) 67{ 68 extern char *__progname; 69 70 fprintf(stderr, "usage: %s command [argument ...]\n", __progname); 71 exit(1); 72} 73 74int 75main(int argc, char *argv[]) 76{ 77 struct sockaddr_un sun; 78 struct parse_result *res; 79 struct imsg imsg; 80 unsigned int ifidx = 0; 81 int ctl_sock; 82 int done = 0; 83 int n, verbose = 0; 84 struct ctl_show_topology_req treq; 85 86 /* parse options */ 87 if ((res = parse(argc - 1, argv + 1)) == NULL) 88 exit(1); 89 90 /* connect to eigrpd control socket */ 91 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 92 err(1, "socket"); 93 94 memset(&sun, 0, sizeof(sun)); 95 sun.sun_family = AF_UNIX; 96 strlcpy(sun.sun_path, EIGRPD_SOCKET, sizeof(sun.sun_path)); 97 if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) 98 err(1, "connect: %s", EIGRPD_SOCKET); 99 100 if (pledge("stdio route", NULL) == -1) 101 err(1, "tame"); 102 103 if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 104 err(1, NULL); 105 imsg_init(ibuf, ctl_sock); 106 done = 0; 107 108 /* process user request */ 109 switch (res->action) { 110 case NONE: 111 usage(); 112 /* not reached */ 113 case SHOW: 114 case SHOW_IFACE: 115 printf("%-4s %-5s %-11s %-18s %-10s %-8s %3s\n", 116 "AF", "AS", "Interface", "Address", "Linkstate", 117 "Uptime", "nc"); 118 /*FALLTHROUGH*/ 119 case SHOW_IFACE_DTAIL: 120 if (*res->ifname) { 121 ifidx = if_nametoindex(res->ifname); 122 if (ifidx == 0) 123 errx(1, "no such interface %s", res->ifname); 124 } 125 imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, 126 &ifidx, sizeof(ifidx)); 127 break; 128 case SHOW_NBR: 129 printf("%-4s %-5s %-18s %-11s %-10s %8s\n", "AF", "AS", 130 "Address", "Iface", "Holdtime", "Uptime"); 131 imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); 132 break; 133 case SHOW_TOPOLOGY: 134 memset(&treq, 0, sizeof(treq)); 135 treq.af = res->family; 136 memcpy(&treq.prefix, &res->addr, sizeof(res->addr)); 137 treq.prefixlen = res->prefixlen; 138 treq.flags = res->flags; 139 140 if (!eigrp_addrisset(res->family, &res->addr)) 141 printf(" %-4s %-5s %-18s %-15s %-12s %s\n", 142 "AF", "AS", "Destination", "Nexthop", "Interface", 143 "Distance"); 144 imsg_compose(ibuf, IMSG_CTL_SHOW_TOPOLOGY, 0, 0, -1, 145 &treq, sizeof(treq)); 146 break; 147 case SHOW_FIB: 148 show_fib_head(); 149 imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1, 150 &res->flags, sizeof(res->flags)); 151 break; 152 case SHOW_FIB_IFACE: 153 if (*res->ifname) 154 imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, 155 res->ifname, sizeof(res->ifname)); 156 else 157 imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0); 158 show_interface_head(); 159 break; 160 case FIB: 161 errx(1, "fib couple|decouple"); 162 break; 163 case FIB_COUPLE: 164 imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0); 165 printf("couple request sent.\n"); 166 done = 1; 167 break; 168 case FIB_DECOUPLE: 169 imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0); 170 printf("decouple request sent.\n"); 171 done = 1; 172 break; 173 case LOG_VERBOSE: 174 verbose = 1; 175 /* FALLTHROUGH */ 176 case LOG_BRIEF: 177 imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, 178 &verbose, sizeof(verbose)); 179 printf("logging request sent.\n"); 180 done = 1; 181 break; 182 case RELOAD: 183 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 184 printf("reload request sent.\n"); 185 done = 1; 186 break; 187 } 188 189 while (ibuf->w.queued) 190 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) 191 err(1, "write error"); 192 193 while (!done) { 194 if ((n = imsg_read(ibuf)) == -1) 195 errx(1, "imsg_read error"); 196 if (n == 0) 197 errx(1, "pipe closed"); 198 199 while (!done) { 200 if ((n = imsg_get(ibuf, &imsg)) == -1) 201 errx(1, "imsg_get error"); 202 if (n == 0) 203 break; 204 switch (res->action) { 205 case SHOW: 206 case SHOW_IFACE: 207 done = show_interface_msg(&imsg, res); 208 break; 209 case SHOW_IFACE_DTAIL: 210 done = show_interface_detail_msg(&imsg, res); 211 break; 212 case SHOW_NBR: 213 done = show_nbr_msg(&imsg, res); 214 break; 215 case SHOW_TOPOLOGY: 216 if (eigrp_addrisset(res->family, &res->addr)) 217 done = show_topology_detail_msg(&imsg, 218 res); 219 else 220 done = show_topology_msg(&imsg, res); 221 break; 222 case SHOW_FIB: 223 done = show_fib_msg(&imsg, res); 224 break; 225 case SHOW_FIB_IFACE: 226 done = show_fib_interface_msg(&imsg); 227 break; 228 case NONE: 229 case FIB: 230 case FIB_COUPLE: 231 case FIB_DECOUPLE: 232 case LOG_VERBOSE: 233 case LOG_BRIEF: 234 case RELOAD: 235 break; 236 } 237 imsg_free(&imsg); 238 } 239 } 240 close(ctl_sock); 241 free(ibuf); 242 243 return (0); 244} 245 246uint64_t 247get_ifms_type(uint8_t if_type) 248{ 249 switch (if_type) { 250 case IFT_ETHER: 251 return (IFM_ETHER); 252 case IFT_FDDI: 253 return (IFM_FDDI); 254 case IFT_CARP: 255 return (IFM_CARP); 256 case IFT_PPP: 257 return (IFM_TDM); 258 default: 259 return (0); 260 } 261} 262 263int 264show_interface_msg(struct imsg *imsg, struct parse_result *res) 265{ 266 struct ctl_iface *iface; 267 char *addr; 268 269 switch (imsg->hdr.type) { 270 case IMSG_CTL_SHOW_INTERFACE: 271 if (imsg->hdr.len < IMSG_HEADER_SIZE + 272 sizeof(struct ctl_iface)) 273 errx(1, "wrong imsg len"); 274 iface = imsg->data; 275 276 if (res->family != AF_UNSPEC && res->family != iface->af) 277 break; 278 if (res->as != 0 && res->as != iface->as) 279 break; 280 281 if (asprintf(&addr, "%s/%d", log_addr(iface->af, &iface->addr), 282 iface->prefixlen) == -1) 283 err(1, NULL); 284 285 printf("%-4s %-5u %-11s %-18s", af_name(iface->af), iface->as, 286 iface->name, addr); 287 if (strlen(addr) > 18) 288 printf("\n%41s", " "); 289 printf(" %-10s %-8s %3u\n", get_linkstate(iface->if_type, 290 iface->linkstate), fmt_timeframe_core(iface->uptime), 291 iface->nbr_cnt); 292 free(addr); 293 break; 294 case IMSG_CTL_END: 295 printf("\n"); 296 return (1); 297 default: 298 break; 299 } 300 301 return (0); 302} 303 304int 305show_interface_detail_msg(struct imsg *imsg, struct parse_result *res) 306{ 307 struct ctl_iface *iface; 308 309 switch (imsg->hdr.type) { 310 case IMSG_CTL_SHOW_INTERFACE: 311 if (imsg->hdr.len < IMSG_HEADER_SIZE + 312 sizeof(struct ctl_iface)) 313 errx(1, "wrong imsg len"); 314 iface = imsg->data; 315 316 if (res->family != AF_UNSPEC && res->family != iface->af) 317 break; 318 if (res->as != 0 && res->as != iface->as) 319 break; 320 321 printf("\n"); 322 printf("Interface %s, line protocol is %s\n", 323 iface->name, print_link(iface->flags)); 324 printf(" Autonomous System %u, Address Family %s\n", 325 iface->as, af_name(iface->af)); 326 printf(" Internet address %s/%d\n", 327 log_addr(iface->af, &iface->addr), iface->prefixlen); 328 printf(" Linkstate %s, network type %s\n", 329 get_linkstate(iface->if_type, iface->linkstate), 330 if_type_name(iface->type)); 331 printf(" Delay %u usec, Bandwidth %u Kbit/sec\n", 332 iface->delay, iface->bandwidth); 333 if (iface->passive) 334 printf(" Passive interface (No Hellos)\n"); 335 else { 336 printf(" Hello interval %u, Hello holdtime %u\n", 337 iface->hello_interval, iface->hello_holdtime); 338 printf(" Split-horizon %s\n", 339 (iface->splithorizon) ? "enabled" : "disabled"); 340 printf(" Neighbor count is %d\n", iface->nbr_cnt); 341 } 342 printf(" Uptime %s\n", fmt_timeframe_core(iface->uptime)); 343 break; 344 case IMSG_CTL_END: 345 printf("\n"); 346 return (1); 347 default: 348 break; 349 } 350 351 return (0); 352} 353 354const char * 355print_link(int state) 356{ 357 if (state & IFF_UP) 358 return ("UP"); 359 else 360 return ("DOWN"); 361} 362 363#define TF_BUFS 8 364#define TF_LEN 9 365 366const char * 367fmt_timeframe_core(time_t t) 368{ 369 char *buf; 370 static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 371 static int idx = 0; 372 unsigned int sec, min, hrs, day; 373 unsigned long long week; 374 375 if (t == 0) 376 return ("00:00:00"); 377 378 buf = tfbuf[idx++]; 379 if (idx == TF_BUFS) 380 idx = 0; 381 382 week = t; 383 384 sec = week % 60; 385 week /= 60; 386 min = week % 60; 387 week /= 60; 388 hrs = week % 24; 389 week /= 24; 390 day = week % 7; 391 week /= 7; 392 393 if (week > 0) 394 snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs); 395 else if (day > 0) 396 snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 397 else 398 snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 399 400 return (buf); 401} 402 403int 404show_nbr_msg(struct imsg *imsg, struct parse_result *res) 405{ 406 struct ctl_nbr *nbr; 407 const char *addr; 408 409 switch (imsg->hdr.type) { 410 case IMSG_CTL_SHOW_NBR: 411 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct ctl_nbr)) 412 errx(1, "wrong imsg len"); 413 nbr = imsg->data; 414 415 if (res->family != AF_UNSPEC && res->family != nbr->af) 416 break; 417 if (res->as != 0 && res->as != nbr->as) 418 break; 419 420 addr = log_addr(nbr->af, &nbr->addr); 421 422 printf("%-4s %-5u %-18s", af_name(nbr->af), nbr->as, addr); 423 if (strlen(addr) > 18) 424 printf("\n%29s", " "); 425 printf(" %-11s %-10u %8s\n", nbr->ifname, nbr->hello_holdtime, 426 fmt_timeframe_core(nbr->uptime)); 427 break; 428 case IMSG_CTL_END: 429 printf("\n"); 430 return (1); 431 default: 432 break; 433 } 434 435 return (0); 436} 437 438static int 439connected_check(int af, union eigrpd_addr *addr) 440{ 441 switch (af) { 442 case AF_INET: 443 if (addr->v4.s_addr == INADDR_ANY) 444 return (1); 445 break; 446 case AF_INET6: 447 if (IN6_IS_ADDR_UNSPECIFIED(&addr->v6)) 448 return (1); 449 break; 450 default: 451 break; 452 } 453 454 return (0); 455} 456 457int 458show_topology_msg(struct imsg *imsg, struct parse_result *res) 459{ 460 struct ctl_rt *rt; 461 char *dstnet, *nexthop, *rdistance; 462 char flag; 463 464 switch (imsg->hdr.type) { 465 case IMSG_CTL_SHOW_TOPOLOGY: 466 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct ctl_rt)) 467 errx(1, "wrong imsg len"); 468 rt = imsg->data; 469 470 if (res->family != AF_UNSPEC && res->family != rt->af) 471 break; 472 if (res->as != 0 && res->as != rt->as) 473 break; 474 475 if (rt->state & DUAL_STA_ACTIVE_ALL) 476 flag = 'A'; 477 else if (rt->flags & F_CTL_RT_SUCCESSOR) 478 flag = 'S'; 479 else if (rt->flags & F_CTL_RT_FSUCCESSOR) 480 flag = 'F'; 481 else 482 flag = ' '; 483 484 if (asprintf(&dstnet, "%s/%d", log_addr(rt->af, &rt->prefix), 485 rt->prefixlen) == -1) 486 err(1, NULL); 487 488 if (connected_check(rt->af, &rt->nexthop)) { 489 if (asprintf(&nexthop, "Connected") == -1) 490 err(1, NULL); 491 if (asprintf(&rdistance, "-") == -1) 492 err(1, NULL); 493 } else { 494 if (asprintf(&nexthop, "%s", log_addr(rt->af, 495 &rt->nexthop)) == -1) 496 err(1, NULL); 497 if (asprintf(&rdistance, "%u", rt->rdistance) == -1) 498 err(1, NULL); 499 } 500 501 printf("%c %-4s %-5u %-18s", flag, af_name(rt->af), rt->as, 502 dstnet); 503 if (strlen(dstnet) > 18) 504 printf("\n%31s", " "); 505 printf(" %-15s", nexthop); 506 if (strlen(nexthop) > 15) 507 printf("\n%47s", " "); 508 printf(" %-12s %u/%s\n", rt->ifname, rt->distance, rdistance); 509 free(dstnet); 510 free(nexthop); 511 free(rdistance); 512 break; 513 case IMSG_CTL_END: 514 printf("\n"); 515 return (1); 516 default: 517 break; 518 } 519 520 return (0); 521} 522 523int 524show_topology_detail_msg(struct imsg *imsg, struct parse_result *res) 525{ 526 struct ctl_rt *rt; 527 char *dstnet = NULL, *state = NULL, *type, *nexthop; 528 struct in_addr addr; 529 530 switch (imsg->hdr.type) { 531 case IMSG_CTL_SHOW_TOPOLOGY: 532 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct ctl_rt)) 533 errx(1, "wrong imsg len"); 534 rt = imsg->data; 535 536 if (res->family != AF_UNSPEC && res->family != rt->af) 537 break; 538 if (res->as != 0 && res->as != rt->as) 539 break; 540 541 if (rt->flags & F_CTL_RT_FIRST) { 542 if (asprintf(&dstnet, "%s/%d", log_addr(rt->af, 543 &rt->prefix), rt->prefixlen) == -1) 544 err(1, NULL); 545 546 if (rt->state & DUAL_STA_ACTIVE_ALL) { 547 if (asprintf(&state, "Active") == -1) 548 err(1, NULL); 549 } else { 550 if (asprintf(&state, "Passive") == -1) 551 err(1, NULL); 552 } 553 } 554 555 if (rt->type == EIGRP_ROUTE_INTERNAL) { 556 if (asprintf(&type, "Internal") == -1) 557 err(1, NULL); 558 } else { 559 if (asprintf(&type, "External") == -1) 560 err(1, NULL); 561 } 562 563 if (connected_check(rt->af, &rt->nexthop)) { 564 if (asprintf(&nexthop, "Connected") == -1) 565 err(1, NULL); 566 } else { 567 if (asprintf(&nexthop, "Neighbor %s", log_addr(rt->af, 568 &rt->nexthop)) == -1) 569 err(1, NULL); 570 } 571 572 if (rt->flags & F_CTL_RT_FIRST) { 573 printf("Network %s\n", dstnet); 574 printf("Autonomous System %u, Address Family %s\n", 575 rt->as, af_name(rt->af)); 576 printf("DUAL State: %s, Feasible Distance: %u\n", state, 577 rt->fdistance); 578 printf("Routes:\n"); 579 } 580 printf(" Interface %s - %s\n", rt->ifname, nexthop); 581 printf(" Distance: %u", rt->distance); 582 if (!connected_check(rt->af, &rt->nexthop)) 583 printf(", Reported Distance: %u", rt->rdistance); 584 printf(", route is %s\n", type); 585 printf(" Vector metric:\n"); 586 printf(" Minimum bandwidth is %u Kbit\n", 587 rt->metric.bandwidth); 588 printf(" Total delay is %u microseconds\n", 589 rt->metric.delay); 590 printf(" Reliability is %u/255\n", rt->metric.reliability); 591 printf(" Load is %u/255\n", rt->metric.load); 592 printf(" Minimum MTU is %u\n", rt->metric.mtu); 593 printf(" Hop count is %u\n", rt->metric.hop_count); 594 if (rt->type == EIGRP_ROUTE_EXTERNAL) { 595 addr.s_addr = htonl(rt->emetric.routerid); 596 printf(" External data:\n"); 597 printf(" Originating router is %s\n", 598 inet_ntoa(addr)); 599 printf(" AS number of route is %u\n", 600 rt->emetric.as); 601 printf(" External protocol is %s\n", 602 ext_proto_name(rt->emetric.protocol)); 603 printf(" External metric is %u\n", 604 rt->emetric.metric); 605 printf(" Administrator tag is %u\n", 606 rt->emetric.tag); 607 } 608 609 printf("\n"); 610 if (dstnet) 611 free(dstnet); 612 if (state) 613 free(state); 614 free(type); 615 free(nexthop); 616 break; 617 case IMSG_CTL_END: 618 return (1); 619 default: 620 break; 621 } 622 623 return (0); 624} 625 626void 627show_fib_head(void) 628{ 629 printf("flags: * = valid, D = EIGRP, C = Connected, S = Static\n"); 630 printf("%-6s %-4s %-20s %-17s\n", "Flags", "Prio", "Destination", 631 "Nexthop"); 632} 633 634int 635show_fib_msg(struct imsg *imsg, struct parse_result *res) 636{ 637 struct kroute *k; 638 char *p; 639 640 switch (imsg->hdr.type) { 641 case IMSG_CTL_KROUTE: 642 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 643 errx(1, "wrong imsg len"); 644 k = imsg->data; 645 646 if (res->family != AF_UNSPEC && res->family != k->af) 647 break; 648 649 if (k->flags & F_DOWN) 650 printf(" "); 651 else 652 printf("*"); 653 654 if (!(k->flags & F_KERNEL)) 655 printf("D"); 656 else if (k->flags & F_CONNECTED) 657 printf("C"); 658 else if (k->flags & F_STATIC) 659 printf("S"); 660 else 661 printf(" "); 662 663 printf("%-5s", (k->flags & F_CTL_EXTERNAL) ? " EX" : ""); 664 printf("%4d ", k->priority); 665 if (asprintf(&p, "%s/%u", log_addr(k->af, &k->prefix), 666 k->prefixlen) == -1) 667 err(1, NULL); 668 printf("%-20s ", p); 669 if (strlen(p) > 20) 670 printf("\n%33s", " "); 671 free(p); 672 673 if (eigrp_addrisset(k->af, &k->nexthop)) { 674 switch (k->af) { 675 case AF_INET: 676 printf("%s", log_addr(k->af, &k->nexthop)); 677 break; 678 case AF_INET6: 679 printf("%s", log_in6addr_scope(&k->nexthop.v6, 680 k->ifindex)); 681 break; 682 default: 683 break; 684 } 685 686 } else if (k->flags & F_CONNECTED) 687 printf("link#%u", k->ifindex); 688 printf("\n"); 689 690 break; 691 case IMSG_CTL_END: 692 printf("\n"); 693 return (1); 694 default: 695 break; 696 } 697 698 return (0); 699} 700 701void 702show_interface_head(void) 703{ 704 printf("%-15s%-15s%s\n", "Interface", "Flags", 705 "Link state"); 706} 707 708const struct if_status_description 709 if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; 710const struct ifmedia_description 711 ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 712 713const char * 714get_media_descr(uint64_t media_type) 715{ 716 const struct ifmedia_description *p; 717 718 for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 719 if (media_type == p->ifmt_word) 720 return (p->ifmt_string); 721 722 return ("unknown"); 723} 724 725const char * 726get_linkstate(uint8_t if_type, int link_state) 727{ 728 const struct if_status_description *p; 729 static char buf[8]; 730 731 for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 732 if (LINK_STATE_DESC_MATCH(p, if_type, link_state)) 733 return (p->ifs_string); 734 } 735 snprintf(buf, sizeof(buf), "[#%d]", link_state); 736 return (buf); 737} 738 739void 740print_baudrate(uint64_t baudrate) 741{ 742 if (baudrate > IF_Gbps(1)) 743 printf("%llu GBit/s", baudrate / IF_Gbps(1)); 744 else if (baudrate > IF_Mbps(1)) 745 printf("%llu MBit/s", baudrate / IF_Mbps(1)); 746 else if (baudrate > IF_Kbps(1)) 747 printf("%llu KBit/s", baudrate / IF_Kbps(1)); 748 else 749 printf("%llu Bit/s", baudrate); 750} 751 752int 753show_fib_interface_msg(struct imsg *imsg) 754{ 755 struct kif *k; 756 uint64_t ifms_type; 757 758 switch (imsg->hdr.type) { 759 case IMSG_CTL_IFINFO: 760 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kif)) 761 errx(1, "wrong imsg len"); 762 k = imsg->data; 763 printf("%-15s", k->ifname); 764 printf("%-15s", k->flags & IFF_UP ? "UP" : ""); 765 ifms_type = get_ifms_type(k->if_type); 766 if (ifms_type) 767 printf("%s, ", get_media_descr(ifms_type)); 768 769 printf("%s", get_linkstate(k->if_type, k->link_state)); 770 771 if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { 772 printf(", "); 773 print_baudrate(k->baudrate); 774 } 775 printf("\n"); 776 break; 777 case IMSG_CTL_END: 778 printf("\n"); 779 return (1); 780 default: 781 break; 782 } 783 784 return (0); 785} 786