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