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