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