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