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