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