1 /* $OpenBSD: ospf6ctl.c,v 1.12 2007/12/13 08:57:32 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_int8_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> [arg [...]]\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_DBNET: 160 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, NULL, 0); 161 break; 162 case SHOW_DBRTR: 163 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, NULL, 0); 164 break; 165 case SHOW_DBSELF: 166 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, NULL, 0); 167 break; 168 case SHOW_DBSUM: 169 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, NULL, 0); 170 break; 171 case SHOW_DBASBR: 172 imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, NULL, 0); 173 break; 174 case SHOW_RIB: 175 printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination", 176 "Nexthop", "Path Type", "Type", "Cost", "Uptime"); 177 /*FALLTHROUGH*/ 178 case SHOW_RIB_DTAIL: 179 imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, NULL, 0); 180 break; 181 case SHOW_FIB: 182 if (IN6_IS_ADDR_UNSPECIFIED(&res->addr)) 183 imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, 184 &res->flags, sizeof(res->flags)); 185 else 186 imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, 187 &res->addr, sizeof(res->addr)); 188 show_fib_head(); 189 break; 190 case FIB: 191 errx(1, "fib couple|decouple"); 192 break; 193 case FIB_COUPLE: 194 imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, NULL, 0); 195 printf("couple request sent.\n"); 196 done = 1; 197 break; 198 case FIB_DECOUPLE: 199 imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, NULL, 0); 200 printf("decouple request sent.\n"); 201 done = 1; 202 break; 203 case RELOAD: 204 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, NULL, 0); 205 printf("reload request sent.\n"); 206 done = 1; 207 break; 208 } 209 210 while (ibuf->w.queued) 211 if (msgbuf_write(&ibuf->w) < 0) 212 err(1, "write error"); 213 214 while (!done) { 215 if ((n = imsg_read(ibuf)) == -1) 216 errx(1, "imsg_read error"); 217 if (n == 0) 218 errx(1, "pipe closed"); 219 220 while (!done) { 221 if ((n = imsg_get(ibuf, &imsg)) == -1) 222 errx(1, "imsg_get error"); 223 if (n == 0) 224 break; 225 switch (res->action) { 226 case SHOW: 227 case SHOW_SUM: 228 done = show_summary_msg(&imsg); 229 break; 230 case SHOW_IFACE: 231 done = show_interface_msg(&imsg); 232 break; 233 case SHOW_IFACE_DTAIL: 234 done = show_interface_detail_msg(&imsg); 235 break; 236 case SHOW_NBR: 237 done = show_nbr_msg(&imsg); 238 break; 239 case SHOW_NBR_DTAIL: 240 done = show_nbr_detail_msg(&imsg); 241 break; 242 case SHOW_DB: 243 case SHOW_DBBYAREA: 244 case SHOW_DBSELF: 245 done = show_database_msg(&imsg); 246 break; 247 case SHOW_DBEXT: 248 case SHOW_DBNET: 249 case SHOW_DBRTR: 250 case SHOW_DBSUM: 251 case SHOW_DBASBR: 252 done = show_db_msg_detail(&imsg); 253 break; 254 case SHOW_RIB: 255 done = show_rib_msg(&imsg); 256 break; 257 case SHOW_RIB_DTAIL: 258 done = show_rib_detail_msg(&imsg); 259 break; 260 case SHOW_FIB: 261 done = show_fib_msg(&imsg); 262 break; 263 case NONE: 264 case FIB: 265 case FIB_COUPLE: 266 case FIB_DECOUPLE: 267 case RELOAD: 268 break; 269 } 270 imsg_free(&imsg); 271 } 272 } 273 close(ctl_sock); 274 free(ibuf); 275 276 return (0); 277 } 278 279 int 280 show_summary_msg(struct imsg *imsg) 281 { 282 struct ctl_sum *sum; 283 struct ctl_sum_area *sumarea; 284 285 switch (imsg->hdr.type) { 286 case IMSG_CTL_SHOW_SUM: 287 sum = imsg->data; 288 printf("Router ID: %s\n", inet_ntoa(sum->rtr_id)); 289 printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime)); 290 291 printf("SPF delay is %d sec(s), hold time between two SPFs " 292 "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time); 293 printf("Number of external LSA(s) %d\n", sum->num_ext_lsa); 294 printf("Number of areas attached to this router: %d\n", 295 sum->num_area); 296 break; 297 case IMSG_CTL_SHOW_SUM_AREA: 298 sumarea = imsg->data; 299 printf("\nArea ID: %s\n", inet_ntoa(sumarea->area)); 300 printf(" Number of interfaces in this area: %d\n", 301 sumarea->num_iface); 302 printf(" Number of fully adjacent neighbors in this " 303 "area: %d\n", sumarea->num_adj_nbr); 304 printf(" SPF algorithm executed %d time(s)\n", 305 sumarea->num_spf_calc); 306 printf(" Number LSA(s) %d\n", sumarea->num_lsa); 307 break; 308 case IMSG_CTL_END: 309 printf("\n"); 310 return (1); 311 default: 312 break; 313 } 314 315 return (0); 316 } 317 318 int 319 get_ifms_type(int mediatype) 320 { 321 switch (mediatype) { 322 case IFT_ETHER: 323 return (IFM_ETHER); 324 case IFT_FDDI: 325 return (IFM_FDDI); 326 case IFT_CARP: 327 return (IFM_CARP); 328 case IFT_PPP: 329 return (IFM_TDM); 330 default: 331 return (0); 332 } 333 } 334 335 int 336 show_interface_msg(struct imsg *imsg) 337 { 338 struct ctl_iface *iface; 339 char *netid; 340 341 switch (imsg->hdr.type) { 342 case IMSG_CTL_SHOW_INTERFACE: 343 iface = imsg->data; 344 345 if (asprintf(&netid, "%s", log_in6addr(&iface->addr)) == -1) 346 err(1, NULL); 347 printf("%-11s %-29s %-6s %-10s %-10s %s\n", 348 iface->name, netid, if_state_name(iface->state), 349 fmt_timeframe_core(iface->hello_timer), 350 get_linkstate(get_ifms_type(iface->mediatype), 351 iface->linkstate), fmt_timeframe_core(iface->uptime)); 352 free(netid); 353 break; 354 case IMSG_CTL_END: 355 printf("\n"); 356 return (1); 357 default: 358 break; 359 } 360 361 return (0); 362 } 363 364 int 365 show_interface_detail_msg(struct imsg *imsg) 366 { 367 struct ctl_iface *iface; 368 369 switch (imsg->hdr.type) { 370 case IMSG_CTL_SHOW_INTERFACE: 371 iface = imsg->data; 372 printf("\n"); 373 printf("Interface %s, line protocol is %s\n", 374 iface->name, print_link(iface->flags)); 375 printf(" Internet address %s Area %s\n", 376 log_in6addr(&iface->addr), inet_ntoa(iface->area)); 377 printf(" Link type %s, state %s", 378 get_media_descr(get_ifms_type(iface->mediatype)), 379 get_linkstate(get_ifms_type(iface->mediatype), 380 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 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 = "Router 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_int8_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 //XXX printf("Options: %s\n", print_ospf_options(lsa->opts)); 634 printf("LS Type: %s\n", print_ls_type(lsa->type)); 635 636 switch (ntohs(lsa->type)) { 637 case LSA_TYPE_LINK: 638 printf("Link State ID: %s\n", log_id(lsa->ls_id)); 639 break; 640 case LSA_TYPE_ROUTER: 641 printf("Link State ID: %s\n", log_id(lsa->ls_id)); 642 break; 643 case LSA_TYPE_NETWORK: 644 printf("Link State ID: %s (address of Designated Router)\n", 645 log_id(lsa->ls_id)); 646 break; 647 case LSA_TYPE_INTER_A_PREFIX: 648 printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id)); 649 break; 650 case LSA_TYPE_INTER_A_ROUTER: 651 printf("Link State ID: %s (ASBR Router ID)\n", 652 log_id(lsa->ls_id)); 653 break; 654 case LSA_TYPE_INTRA_A_PREFIX: 655 printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id)); 656 break; 657 case LSA_TYPE_EXTERNAL: 658 printf("Link State ID: %s (External Network Number)\n", 659 log_id(lsa->ls_id)); 660 break; 661 } 662 663 printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr)); 664 printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num)); 665 printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum)); 666 printf("Length: %d\n", ntohs(lsa->len)); 667 } 668 669 char * 670 print_rtr_link_type(u_int8_t type) 671 { 672 switch (type) { 673 case LINK_TYPE_POINTTOPOINT: 674 return ("Point-to-Point"); 675 case LINK_TYPE_TRANSIT_NET: 676 return ("Transit Network"); 677 case LINK_TYPE_RESERVED: 678 return ("Reserved"); 679 case LINK_TYPE_VIRTUAL: 680 return ("Virtual Link"); 681 default: 682 return ("Unknown"); 683 } 684 } 685 686 const char * 687 print_ospf_flags(u_int8_t opts) 688 { 689 static char optbuf[32]; 690 691 snprintf(optbuf, sizeof(optbuf), "*|*|*|*|%s|%s|%s|%s", 692 opts & OSPF_RTR_W ? "W" : "-", 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_asext *asext; 711 u_int16_t i, nlinks, off; 712 713 /* XXX sanity checks! */ 714 715 switch (imsg->hdr.type) { 716 case IMSG_CTL_SHOW_DB_EXT: 717 lsa = imsg->data; 718 if (lsa->hdr.type != lasttype) 719 show_database_head(area_id, ifname, lsa->hdr.type); 720 show_db_hdr_msg_detail(&lsa->hdr); 721 addr.s_addr = lsa->data.asext.mask; 722 printf("Network Mask: %s\n", inet_ntoa(addr)); 723 724 asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr)); 725 726 printf(" Metric type: "); 727 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG) 728 printf("2\n"); 729 else 730 printf("1\n"); 731 printf(" Metric: %d\n", ntohl(asext->metric) 732 & LSA_METRIC_MASK); 733 addr.s_addr = asext->fw_addr; 734 printf(" Forwarding Address: %s\n", inet_ntoa(addr)); 735 printf(" External Route Tag: %d\n\n", ntohl(asext->ext_tag)); 736 737 lasttype = lsa->hdr.type; 738 break; 739 case IMSG_CTL_SHOW_DB_NET: 740 lsa = imsg->data; 741 if (lsa->hdr.type != lasttype) 742 show_database_head(area_id, ifname, lsa->hdr.type); 743 show_db_hdr_msg_detail(&lsa->hdr); 744 addr.s_addr = lsa->data.net.mask; 745 printf("Network Mask: %s\n", inet_ntoa(addr)); 746 747 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) 748 - sizeof(u_int32_t)) / sizeof(struct lsa_net_link); 749 off = sizeof(lsa->hdr) + sizeof(u_int32_t); 750 751 for (i = 0; i < nlinks; i++) { 752 addr.s_addr = lsa->data.net.att_rtr[i]; 753 printf(" Attached Router: %s\n", inet_ntoa(addr)); 754 } 755 756 printf("\n"); 757 lasttype = lsa->hdr.type; 758 break; 759 case IMSG_CTL_SHOW_DB_RTR: 760 lsa = imsg->data; 761 if (lsa->hdr.type != lasttype) 762 show_database_head(area_id, ifname, lsa->hdr.type); 763 show_db_hdr_msg_detail(&lsa->hdr); 764 printf("Flags: %s\n", 765 print_ospf_flags(ntohl(lsa->data.rtr.opts) >> 24)); 766 printf("Options: %s\n", 767 print_ospf_options(ntohl(lsa->data.rtr.opts))); 768 769 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) 770 - sizeof(u_int32_t)) / sizeof(struct lsa_rtr_link); 771 printf("Number of Links: %d\n\n", nlinks); 772 773 off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr); 774 775 for (i = 0; i < nlinks; i++) { 776 rtr_link = (struct lsa_rtr_link *)((char *)lsa + off); 777 778 printf(" Link connected to: %s\n", 779 print_rtr_link_type(rtr_link->type)); 780 781 addr.s_addr = rtr_link->nbr_rtr_id; 782 data.s_addr = rtr_link->iface_id; 783 784 switch (rtr_link->type) { 785 case LINK_TYPE_POINTTOPOINT: 786 case LINK_TYPE_VIRTUAL: 787 printf(" Router ID: %s\n", inet_ntoa(addr)); 788 printf(" Interface ID: %s\n", 789 inet_ntoa(data)); 790 break; 791 case LINK_TYPE_TRANSIT_NET: 792 printf(" Designated Router ID: %s\n", 793 inet_ntoa(addr)); 794 printf(" DR Interface ID: %s\n", 795 inet_ntoa(data)); 796 break; 797 default: 798 printf(" Link ID (Unknown type %d): %s\n", 799 rtr_link->type, inet_ntoa(addr)); 800 printf(" Link Data (Unknown): %s\n", 801 inet_ntoa(data)); 802 break; 803 } 804 805 printf(" Metric: %d\n\n", ntohs(rtr_link->metric)); 806 807 off += sizeof(struct lsa_rtr_link); 808 } 809 810 lasttype = lsa->hdr.type; 811 break; 812 case IMSG_CTL_SHOW_DB_SUM: 813 lsa = imsg->data; 814 if (lsa->hdr.type != lasttype) 815 show_database_head(area_id, ifname, lsa->hdr.type); 816 show_db_hdr_msg_detail(&lsa->hdr); 817 printf("Prefix: XXX\n"); 818 printf("Metric: %d\n\n", ntohl(lsa->data.pref_sum.metric) & 819 LSA_METRIC_MASK); 820 lasttype = lsa->hdr.type; 821 break; 822 case IMSG_CTL_SHOW_DB_ASBR: 823 lsa = imsg->data; 824 if (lsa->hdr.type != lasttype) 825 show_database_head(area_id, ifname, lsa->hdr.type); 826 show_db_hdr_msg_detail(&lsa->hdr); 827 828 addr.s_addr = lsa->data.rtr_sum.dest_rtr_id; 829 printf("Destination Router ID: %s\n", inet_ntoa(addr)); 830 printf("Options: %s\n", 831 print_ospf_options(ntohl(lsa->data.rtr_sum.options))); 832 printf("Metric: %d\n\n", ntohl(lsa->data.rtr_sum.metric) & 833 LSA_METRIC_MASK); 834 case IMSG_CTL_AREA: 835 area = imsg->data; 836 area_id = area->id; 837 lasttype = 0; 838 break; 839 case IMSG_CTL_IFACE: 840 iface = imsg->data; 841 strlcpy(ifname, iface->name, sizeof(ifname)); 842 lasttype = 0; 843 break; 844 case IMSG_CTL_END: 845 return (1); 846 default: 847 break; 848 } 849 850 return (0); 851 } 852 853 int 854 show_nbr_msg(struct imsg *imsg) 855 { 856 struct ctl_nbr *nbr; 857 char *state; 858 859 switch (imsg->hdr.type) { 860 case IMSG_CTL_SHOW_NBR: 861 nbr = imsg->data; 862 if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state), 863 if_state_name(nbr->iface_state)) == -1) 864 err(1, NULL); 865 printf("%-15s %-3d %-12s %-10s", inet_ntoa(nbr->id), 866 nbr->priority, state, fmt_timeframe_core(nbr->dead_timer)); 867 printf("%-11s %s\n", nbr->name, 868 nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime)); 869 free(state); 870 break; 871 case IMSG_CTL_END: 872 printf("\n"); 873 return (1); 874 default: 875 break; 876 } 877 878 return (0); 879 } 880 881 const char * 882 print_ospf_options(u_int8_t opts) 883 { 884 static char optbuf[32]; 885 886 snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|%s|%s|%s", 887 opts & OSPF_OPTION_DC ? "DC" : "-", 888 opts & OSPF_OPTION_R ? "R" : "-", 889 opts & OSPF_OPTION_N ? "N" : "-", 890 opts & OSPF_OPTION_MC ? "MC" : "-", 891 opts & OSPF_OPTION_E ? "E" : "-", 892 opts & OSPF_OPTION_V6 ? "V6" : "-"); 893 return (optbuf); 894 } 895 896 int 897 show_nbr_detail_msg(struct imsg *imsg) 898 { 899 struct ctl_nbr *nbr; 900 901 switch (imsg->hdr.type) { 902 case IMSG_CTL_SHOW_NBR: 903 nbr = imsg->data; 904 printf("\nNeighbor %s, ", inet_ntoa(nbr->id)); 905 printf("interface address %s\n", log_in6addr(&nbr->addr)); 906 printf(" Area %s, interface %s\n", inet_ntoa(nbr->area), 907 nbr->name); 908 printf(" Neighbor priority is %d, " 909 "State is %s, %d state changes\n", 910 nbr->priority, nbr_state_name(nbr->nbr_state), 911 nbr->state_chng_cnt); 912 printf(" DR is %s, ", inet_ntoa(nbr->dr)); 913 printf("BDR is %s\n", inet_ntoa(nbr->bdr)); 914 printf(" Options %s\n", print_ospf_options(nbr->options)); 915 printf(" Dead timer due in %s\n", 916 fmt_timeframe_core(nbr->dead_timer)); 917 printf(" Uptime %s\n", fmt_timeframe_core(nbr->uptime)); 918 printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt); 919 printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt); 920 printf(" Link State Retransmission List %d\n", 921 nbr->ls_retrans_lst_cnt); 922 break; 923 case IMSG_CTL_END: 924 printf("\n"); 925 return (1); 926 default: 927 break; 928 } 929 930 return (0); 931 } 932 933 int 934 show_rib_msg(struct imsg *imsg) 935 { 936 struct ctl_rt *rt; 937 char *dstnet; 938 939 switch (imsg->hdr.type) { 940 case IMSG_CTL_SHOW_RIB: 941 rt = imsg->data; 942 switch (rt->d_type) { 943 case DT_NET: 944 if (asprintf(&dstnet, "%s/%d", log_in6addr(&rt->prefix), 945 rt->prefixlen) == -1) 946 err(1, NULL); 947 break; 948 case DT_RTR: 949 if (asprintf(&dstnet, "%s", 950 log_in6addr(&rt->prefix)) == -1) 951 err(1, NULL); 952 break; 953 default: 954 errx(1, "Invalid route type"); 955 } 956 957 printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet, 958 log_in6addr(&rt->nexthop), path_type_name(rt->p_type), 959 dst_type_name(rt->d_type), rt->cost, 960 rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime)); 961 free(dstnet); 962 break; 963 case IMSG_CTL_END: 964 printf("\n"); 965 return (1); 966 default: 967 break; 968 } 969 970 return (0); 971 } 972 973 void 974 show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type) 975 { 976 char *header, *format, *format2; 977 978 switch (p_type) { 979 case PT_INTRA_AREA: 980 case PT_INTER_AREA: 981 switch (d_type) { 982 case DT_NET: 983 format = "Network Routing Table"; 984 format2 = ""; 985 break; 986 case DT_RTR: 987 format = "Router Routing Table"; 988 format2 = "Type"; 989 break; 990 default: 991 errx(1, "unknown route type"); 992 } 993 break; 994 case PT_TYPE1_EXT: 995 case PT_TYPE2_EXT: 996 format = NULL; 997 format2 = "Cost 2"; 998 if ((header = strdup("External Routing Table")) == NULL) 999 err(1, NULL); 1000 break; 1001 default: 1002 errx(1, "unknown route type"); 1003 } 1004 1005 if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT) 1006 if (asprintf(&header, "%s (Area %s)", format, 1007 inet_ntoa(aid)) == -1) 1008 err(1, NULL); 1009 1010 printf("\n%-18s %s\n", "", header); 1011 free(header); 1012 1013 printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination", 1014 "Nexthop", "Adv Router", "Path type", "Cost", format2); 1015 } 1016 1017 const char * 1018 print_ospf_rtr_flags(u_int8_t opts) 1019 { 1020 static char optbuf[32]; 1021 1022 snprintf(optbuf, sizeof(optbuf), "%s%s%s", 1023 opts & OSPF_RTR_E ? "AS" : "", 1024 opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "", 1025 opts & OSPF_RTR_B ? "ABR" : ""); 1026 return (optbuf); 1027 } 1028 1029 int 1030 show_rib_detail_msg(struct imsg *imsg) 1031 { 1032 static struct in_addr area_id; 1033 struct ctl_rt *rt; 1034 struct area *area; 1035 char *dstnet; 1036 static u_int8_t lasttype; 1037 1038 switch (imsg->hdr.type) { 1039 case IMSG_CTL_SHOW_RIB: 1040 rt = imsg->data; 1041 1042 switch (rt->p_type) { 1043 case PT_INTRA_AREA: 1044 case PT_INTER_AREA: 1045 switch (rt->d_type) { 1046 case DT_NET: 1047 if (lasttype != RIB_NET) 1048 show_rib_head(rt->area, rt->d_type, 1049 rt->p_type); 1050 if (asprintf(&dstnet, "%s/%d", 1051 log_in6addr(&rt->prefix), 1052 rt->prefixlen) == -1) 1053 err(1, NULL); 1054 lasttype = RIB_NET; 1055 break; 1056 case DT_RTR: 1057 if (lasttype != RIB_RTR) 1058 show_rib_head(rt->area, rt->d_type, 1059 rt->p_type); 1060 if (asprintf(&dstnet, "%s", 1061 log_in6addr(&rt->prefix)) == -1) 1062 err(1, NULL); 1063 lasttype = RIB_RTR; 1064 break; 1065 default: 1066 errx(1, "unknown route type"); 1067 } 1068 printf("%-18s %-15s ", dstnet, 1069 log_in6addr(&rt->nexthop)); 1070 printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr), 1071 path_type_name(rt->p_type), rt->cost); 1072 free(dstnet); 1073 1074 if (rt->d_type == DT_RTR) 1075 printf(" %-7s", 1076 print_ospf_rtr_flags(rt->flags)); 1077 1078 printf("\n"); 1079 break; 1080 case PT_TYPE1_EXT: 1081 case PT_TYPE2_EXT: 1082 if (lasttype != RIB_EXT) 1083 show_rib_head(rt->area, rt->d_type, rt->p_type); 1084 1085 if (asprintf(&dstnet, "%s/%d", 1086 log_in6addr(&rt->prefix), rt->prefixlen) == -1) 1087 err(1, NULL); 1088 1089 printf("%-18s %-15s ", dstnet, 1090 log_in6addr(&rt->nexthop)); 1091 printf("%-15s %-12s %-7d %-7d\n", 1092 inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type), 1093 rt->cost, rt->cost2); 1094 1095 lasttype = RIB_EXT; 1096 break; 1097 default: 1098 errx(1, "unknown route type"); 1099 } 1100 break; 1101 case IMSG_CTL_AREA: 1102 area = imsg->data; 1103 area_id = area->id; 1104 break; 1105 case IMSG_CTL_END: 1106 printf("\n"); 1107 return (1); 1108 default: 1109 break; 1110 } 1111 1112 return (0); 1113 } 1114 1115 void 1116 show_fib_head(void) 1117 { 1118 printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n"); 1119 printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop"); 1120 } 1121 1122 int 1123 show_fib_msg(struct imsg *imsg) 1124 { 1125 struct kroute *k; 1126 char *p; 1127 1128 switch (imsg->hdr.type) { 1129 case IMSG_CTL_KROUTE: 1130 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 1131 errx(1, "wrong imsg len"); 1132 k = imsg->data; 1133 1134 if (k->flags & F_DOWN) 1135 printf(" "); 1136 else 1137 printf("*"); 1138 1139 if (!(k->flags & F_KERNEL)) 1140 printf("O"); 1141 else if (k->flags & F_CONNECTED) 1142 printf("C"); 1143 else if (k->flags & F_STATIC) 1144 printf("S"); 1145 else 1146 printf(" "); 1147 1148 printf(" "); 1149 if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix), 1150 k->prefixlen) == -1) 1151 err(1, NULL); 1152 printf("%-20s ", p); 1153 free(p); 1154 1155 if (!IN6_IS_ADDR_UNSPECIFIED(&k->nexthop)) 1156 printf("%s", log_in6addr(&k->nexthop)); 1157 else if (k->flags & F_CONNECTED) 1158 printf("link#%u", k->ifindex); 1159 printf("\n"); 1160 1161 break; 1162 case IMSG_CTL_END: 1163 printf("\n"); 1164 return (1); 1165 default: 1166 break; 1167 } 1168 1169 return (0); 1170 } 1171 1172 const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 1173 const struct ifmedia_status_description 1174 ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS; 1175 const struct ifmedia_description 1176 ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 1177 1178 const char * 1179 get_media_descr(int media_type) 1180 { 1181 const struct ifmedia_description *p; 1182 1183 for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 1184 if (media_type == p->ifmt_word) 1185 return (p->ifmt_string); 1186 1187 return ("unknown"); 1188 } 1189 1190 const char * 1191 get_linkstate(int media_type, int link_state) 1192 { 1193 const struct ifmedia_status_description *p; 1194 int i; 1195 1196 if (link_state == LINK_STATE_UNKNOWN) 1197 return ("unknown"); 1198 1199 for (i = 0; ifm_status_valid_list[i] != 0; i++) 1200 for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) { 1201 if (p->ifms_type != media_type || 1202 p->ifms_valid != ifm_status_valid_list[i]) 1203 continue; 1204 if (LINK_STATE_IS_UP(link_state)) 1205 return (p->ifms_string[1]); 1206 return (p->ifms_string[0]); 1207 } 1208 1209 return ("unknown"); 1210 } 1211 1212 void 1213 print_baudrate(u_int64_t baudrate) 1214 { 1215 if (baudrate > IF_Gbps(1)) 1216 printf("%llu GBit/s", baudrate / IF_Gbps(1)); 1217 else if (baudrate > IF_Mbps(1)) 1218 printf("%llu MBit/s", baudrate / IF_Mbps(1)); 1219 else if (baudrate > IF_Kbps(1)) 1220 printf("%llu KBit/s", baudrate / IF_Kbps(1)); 1221 else 1222 printf("%llu Bit/s", baudrate); 1223 } 1224