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