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