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