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