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