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