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