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