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