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