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