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