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