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