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