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