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