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