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