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