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