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