1/* 2 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 3 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 4 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 5 * Copyright (c) 2020 Richard Chivers <r.chivers@zengenti.com> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/types.h> 21#include <sys/socket.h> 22#include <sys/un.h> 23#include <netinet/in.h> 24#include <arpa/inet.h> 25#include <net/if_media.h> 26#include <net/if_types.h> 27 28#include <err.h> 29#include <errno.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 "ospfctl.h" 38#include "ospfe.h" 39#include "parser.h" 40 41static void 42show_head(struct parse_result *res) 43{ 44 switch (res->action) { 45 case SHOW_IFACE: 46 printf("%-11s %-18s %-6s %-10s %-10s %-8s %3s %3s\n", 47 "Interface", "Address", "State", "HelloTimer", "Linkstate", 48 "Uptime", "nc", "ac"); 49 break; 50 case SHOW_FIB: 51 printf("flags: * = valid, O = OSPF, C = Connected, " 52 "S = Static\n"); 53 printf("%-6s %-4s %-20s %-17s\n", "Flags", "Prio", 54 "Destination", "Nexthop"); 55 break; 56 case SHOW_FIB_IFACE: 57 printf("%-15s%-15s%s\n", "Interface", "Flags", "Link state"); 58 break; 59 case SHOW_NBR: 60 printf("%-15s %-3s %-12s %-8s %-15s %-9s %s\n", "ID", "Pri", 61 "State", "DeadTime", "Address", "Iface","Uptime"); 62 break; 63 case SHOW_RIB: 64 printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination", 65 "Nexthop", "Path Type", "Type", "Cost", "Uptime"); 66 break; 67 default: 68 break; 69 } 70} 71 72static void 73show_summary(struct ctl_sum *sum) 74{ 75 printf("Router ID: %s\n", inet_ntoa(sum->rtr_id)); 76 printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime)); 77 printf("RFC1583 compatibility flag is "); 78 if (sum->rfc1583compat) 79 printf("enabled\n"); 80 else 81 printf("disabled\n"); 82 83 printf("SPF delay is %d msec(s), hold time between two SPFs " 84 "is %d msec(s)\n", sum->spf_delay, sum->spf_hold_time); 85 printf("Number of external LSA(s) %d (Checksum sum 0x%x)\n", 86 sum->num_ext_lsa, sum->ext_lsa_cksum); 87 printf("Number of areas attached to this router: %d\n", 88 sum->num_area); 89} 90 91static void 92show_summary_area(struct ctl_sum_area *sumarea) 93{ 94 printf("\nArea ID: %s\n", inet_ntoa(sumarea->area)); 95 printf(" Number of interfaces in this area: %d\n", 96 sumarea->num_iface); 97 printf(" Number of fully adjacent neighbors in this " 98 "area: %d\n", sumarea->num_adj_nbr); 99 printf(" SPF algorithm executed %d time(s)\n", 100 sumarea->num_spf_calc); 101 printf(" Number LSA(s) %d (Checksum sum 0x%x)\n", 102 sumarea->num_lsa, sumarea->lsa_cksum); 103} 104 105static void 106show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type) 107{ 108 char *header, *format, *format2; 109 110 switch (p_type) { 111 case PT_INTRA_AREA: 112 case PT_INTER_AREA: 113 switch (d_type) { 114 case DT_NET: 115 format = "Network Routing Table"; 116 format2 = ""; 117 break; 118 case DT_RTR: 119 format = "Router Routing Table"; 120 format2 = "Type"; 121 break; 122 default: 123 errx(1, "unknown route type"); 124 } 125 break; 126 case PT_TYPE1_EXT: 127 case PT_TYPE2_EXT: 128 format = NULL; 129 format2 = "Cost 2"; 130 if ((header = strdup("External Routing Table")) == NULL) 131 err(1, NULL); 132 break; 133 default: 134 errx(1, "unknown route type"); 135 } 136 137 if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT) 138 if (asprintf(&header, "%s (Area %s)", format, 139 inet_ntoa(aid)) == -1) 140 err(1, NULL); 141 142 printf("\n%-18s %s\n", "", header); 143 free(header); 144 145 printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination", 146 "Nexthop", "Adv Router", "Path type", "Cost", format2); 147} 148 149static void 150show_interface(struct ctl_iface *iface, int detail) 151{ 152 char *netid; 153 154 /* XXX This wasn't previously executed on detail call */ 155 if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr), 156 mask2prefixlen(iface->mask.s_addr)) == -1) 157 err(1, NULL); 158 159 if (detail) { 160 printf("\n"); 161 printf("Interface %s, line protocol is %s\n", 162 iface->name, print_link(iface->flags)); 163 printf(" Internet address %s/%d, ", 164 inet_ntoa(iface->addr), 165 mask2prefixlen(iface->mask.s_addr)); 166 printf("Area %s\n", inet_ntoa(iface->area)); 167 printf(" Linkstate %s,", 168 get_linkstate(iface->if_type, iface->linkstate)); 169 printf(" mtu %d\n", iface->mtu); 170 printf(" Router ID %s, network type %s, cost: %d\n", 171 inet_ntoa(iface->rtr_id), 172 if_type_name(iface->type), iface->metric); 173 if (iface->dependon[0] != '\0') { 174 printf(" Depends on %s, %s\n", iface->dependon, 175 iface->depend_ok ? "up" : "down"); 176 } 177 printf(" Transmit delay is %d sec(s), state %s, priority %d\n", 178 iface->transmit_delay, if_state_name(iface->state), 179 iface->priority); 180 printf(" Designated Router (ID) %s, ", 181 inet_ntoa(iface->dr_id)); 182 printf("interface address %s\n", inet_ntoa(iface->dr_addr)); 183 printf(" Backup Designated Router (ID) %s, ", 184 inet_ntoa(iface->bdr_id)); 185 printf("interface address %s\n", inet_ntoa(iface->bdr_addr)); 186 if (iface->dead_interval == FAST_RTR_DEAD_TIME) { 187 printf(" Timer intervals configured, " 188 "hello %d msec, dead %d, wait %d, retransmit %d\n", 189 iface->fast_hello_interval, iface->dead_interval, 190 iface->dead_interval, iface->rxmt_interval); 191 192 } else { 193 printf(" Timer intervals configured, " 194 "hello %d, dead %d, wait %d, retransmit %d\n", 195 iface->hello_interval, iface->dead_interval, 196 iface->dead_interval, iface->rxmt_interval); 197 } 198 199 if (iface->passive) 200 printf(" Passive interface (No Hellos)\n"); 201 else if (iface->hello_timer.tv_sec < 0) 202 printf(" Hello timer not running\n"); 203 else 204 printf(" Hello timer due in %s+%ldmsec\n", 205 fmt_timeframe_core(iface->hello_timer.tv_sec), 206 iface->hello_timer.tv_usec / 1000); 207 printf(" Uptime %s\n", fmt_timeframe_core(iface->uptime)); 208 printf(" Neighbor count is %d, adjacent neighbor count is " 209 "%d\n", iface->nbr_cnt, iface->adj_cnt); 210 211 if (iface->auth_type > 0) { 212 switch (iface->auth_type) { 213 case AUTH_SIMPLE: 214 printf(" Simple password authentication " 215 "enabled\n"); 216 break; 217 case AUTH_CRYPT: 218 printf(" Message digest authentication " 219 "enabled\n"); 220 printf(" Primary key id is %d\n", 221 iface->auth_keyid); 222 break; 223 default: 224 break; 225 } 226 } 227 } else { 228 printf("%-11s %-18s %-6s %-10s %-10s %s %3d %3d\n", 229 iface->name, netid, if_state_name(iface->state), 230 iface->hello_timer.tv_sec < 0 ? "-" : 231 fmt_timeframe_core(iface->hello_timer.tv_sec), 232 get_linkstate(iface->if_type, iface->linkstate), 233 fmt_timeframe_core(iface->uptime), 234 iface->nbr_cnt, iface->adj_cnt); 235 } 236 free(netid); 237} 238 239 240static void 241show_neighbor(struct ctl_nbr *nbr, int detail) 242{ 243 char *state; 244 245 if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state), 246 if_state_name(nbr->iface_state)) == -1) 247 err(1, NULL); 248 249 if (detail) { 250 printf("\nNeighbor %s, ", inet_ntoa(nbr->id)); 251 printf("interface address %s\n", inet_ntoa(nbr->addr)); 252 printf(" Area %s, interface %s\n", inet_ntoa(nbr->area), 253 nbr->name); 254 printf(" Neighbor priority is %d, " 255 "State is %s, %d state changes\n", 256 nbr->priority, nbr_state_name(nbr->nbr_state), 257 nbr->state_chng_cnt); 258 printf(" DR is %s, ", inet_ntoa(nbr->dr)); 259 printf("BDR is %s\n", inet_ntoa(nbr->bdr)); 260 printf(" Options %s\n", print_ospf_options(nbr->options)); 261 printf(" Dead timer due in %s\n", 262 fmt_timeframe_core(nbr->dead_timer)); 263 printf(" Uptime %s\n", fmt_timeframe_core(nbr->uptime)); 264 printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt); 265 printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt); 266 printf(" Link State Retransmission List %d\n", 267 nbr->ls_retrans_lst_cnt); 268 } else { 269 printf("%-15s %-3d %-12s %-9s", inet_ntoa(nbr->id), 270 nbr->priority, state, fmt_timeframe_core(nbr->dead_timer)); 271 printf("%-15s %-9s %s\n", inet_ntoa(nbr->addr), nbr->name, 272 nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime)); 273 } 274 free(state); 275} 276 277static void 278show_rib(struct ctl_rt *rt, int detail) 279{ 280 char *dstnet; 281 static u_int8_t lasttype; 282 283 if (detail) { 284 switch (rt->p_type) { 285 case PT_INTRA_AREA: 286 case PT_INTER_AREA: 287 switch (rt->d_type) { 288 case DT_NET: 289 if (lasttype != RIB_NET) 290 show_rib_head(rt->area, rt->d_type, 291 rt->p_type); 292 if (asprintf(&dstnet, "%s/%d", 293 inet_ntoa(rt->prefix), rt->prefixlen) == -1) 294 err(1, NULL); 295 lasttype = RIB_NET; 296 break; 297 case DT_RTR: 298 if (lasttype != RIB_RTR) 299 show_rib_head(rt->area, rt->d_type, 300 rt->p_type); 301 if (asprintf(&dstnet, "%s", 302 inet_ntoa(rt->prefix)) == -1) 303 err(1, NULL); 304 lasttype = RIB_RTR; 305 break; 306 default: 307 errx(1, "unknown route type"); 308 } 309 printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop)); 310 printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr), 311 path_type_name(rt->p_type), rt->cost); 312 free(dstnet); 313 314 if (rt->d_type == DT_RTR) 315 printf(" %-7s", print_ospf_rtr_flags(rt->flags)); 316 317 printf("\n"); 318 break; 319 case PT_TYPE1_EXT: 320 case PT_TYPE2_EXT: 321 if (lasttype != RIB_EXT) 322 show_rib_head(rt->area, rt->d_type, rt->p_type); 323 324 if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix), 325 rt->prefixlen) == -1) 326 err(1, NULL); 327 328 printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop)); 329 printf("%-15s %-12s %-7d %-7d\n", inet_ntoa(rt->adv_rtr), 330 path_type_name(rt->p_type), rt->cost, rt->cost2); 331 332 free(dstnet); 333 334 lasttype = RIB_EXT; 335 break; 336 default: 337 errx(1, "unknown route type"); 338 } 339 } else { 340 switch (rt->d_type) { 341 case DT_NET: 342 if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix), 343 rt->prefixlen) == -1) 344 err(1, NULL); 345 break; 346 case DT_RTR: 347 if (asprintf(&dstnet, "%s", 348 inet_ntoa(rt->prefix)) == -1) 349 err(1, NULL); 350 break; 351 default: 352 errx(1, "Invalid route type"); 353 } 354 355 printf("%-20s %-16s%s %-12s %-9s %-7d %s\n", dstnet, 356 inet_ntoa(rt->nexthop), rt->connected ? "C" : " ", 357 path_type_name(rt->p_type), 358 dst_type_name(rt->d_type), rt->cost, 359 rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime)); 360 361 free(dstnet); 362 } 363} 364 365static void 366show_fib(struct kroute *k) 367{ 368 char *p; 369 370 if (k->flags & F_DOWN) 371 printf(" "); 372 else 373 printf("*"); 374 375 if (!(k->flags & F_KERNEL)) 376 printf("O"); 377 else if (k->flags & F_CONNECTED) 378 printf("C"); 379 else if (k->flags & F_STATIC) 380 printf("S"); 381 else 382 printf(" "); 383 384 printf(" "); 385 printf("%4d ", k->priority); 386 if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) == -1) 387 err(1, NULL); 388 389 printf("%-20s ", p); 390 free(p); 391 392 if (k->nexthop.s_addr) 393 printf("%s", inet_ntoa(k->nexthop)); 394 else if (k->flags & F_CONNECTED) 395 printf("link#%u", k->ifindex); 396 397 printf("\n"); 398} 399 400static void 401show_fib_interface(struct kif *k) 402{ 403 uint64_t ifms_type; 404 405 printf("%-15s", k->ifname); 406 printf("%-15s", k->flags & IFF_UP ? "UP" : ""); 407 ifms_type = get_ifms_type(k->if_type); 408 if (ifms_type) 409 printf("%s, ", get_media_descr(ifms_type)); 410 411 printf("%s", get_linkstate(k->if_type, k->link_state)); 412 413 if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { 414 printf(", "); 415 printf("%s", print_baudrate(k->baudrate)); 416 } 417 printf("\n"); 418} 419 420static void 421show_database_head(struct in_addr aid, char *ifname, u_int8_t type) 422{ 423 char *header, *format; 424 int cleanup = 0; 425 426 switch (type) { 427 case LSA_TYPE_ROUTER: 428 format = "Router Link States"; 429 break; 430 case LSA_TYPE_NETWORK: 431 format = "Net Link States"; 432 break; 433 case LSA_TYPE_SUM_NETWORK: 434 format = "Summary Net Link States"; 435 break; 436 case LSA_TYPE_SUM_ROUTER: 437 format = "Summary Router Link States"; 438 break; 439 case LSA_TYPE_EXTERNAL: 440 format = NULL; 441 if ((header = strdup("Type-5 AS External Link States")) == NULL) 442 err(1, NULL); 443 break; 444 case LSA_TYPE_LINK_OPAQ: 445 format = "Type-9 Link Local Opaque Link States"; 446 break; 447 case LSA_TYPE_AREA_OPAQ: 448 format = "Type-10 Area Local Opaque Link States"; 449 break; 450 case LSA_TYPE_AS_OPAQ: 451 format = NULL; 452 if ((header = strdup("Type-11 AS Wide Opaque Link States")) == 453 NULL) 454 err(1, NULL); 455 break; 456 default: 457 if (asprintf(&format, "LSA type %x", ntohs(type)) == -1) 458 err(1, NULL); 459 cleanup = 1; 460 break; 461 } 462 if (type == LSA_TYPE_LINK_OPAQ) { 463 if (asprintf(&header, "%s (Area %s Interface %s)", format, 464 inet_ntoa(aid), ifname) == -1) 465 err(1, NULL); 466 } else if (type != LSA_TYPE_EXTERNAL && type != LSA_TYPE_AS_OPAQ) 467 if (asprintf(&header, "%s (Area %s)", format, 468 inet_ntoa(aid)) == -1) 469 err(1, NULL); 470 471 printf("\n%-15s %s\n\n", "", header); 472 free(header); 473 if (cleanup) 474 free(format); 475} 476 477static void 478show_db_hdr_msg_detail(struct lsa_hdr *lsa) 479{ 480 printf("LS age: %d\n", ntohs(lsa->age)); 481 printf("Options: %s\n", print_ospf_options(lsa->opts)); 482 printf("LS Type: %s\n", print_ls_type(lsa->type)); 483 484 switch (lsa->type) { 485 case LSA_TYPE_ROUTER: 486 printf("Link State ID: %s\n", log_id(lsa->ls_id)); 487 break; 488 case LSA_TYPE_NETWORK: 489 printf("Link State ID: %s (address of Designated Router)\n", 490 log_id(lsa->ls_id)); 491 break; 492 case LSA_TYPE_SUM_NETWORK: 493 printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id)); 494 break; 495 case LSA_TYPE_SUM_ROUTER: 496 printf("Link State ID: %s (ASBR Router ID)\n", 497 log_id(lsa->ls_id)); 498 break; 499 case LSA_TYPE_EXTERNAL: 500 printf("Link State ID: %s (External Network Number)\n", 501 log_id(lsa->ls_id)); 502 break; 503 case LSA_TYPE_LINK_OPAQ: 504 case LSA_TYPE_AREA_OPAQ: 505 case LSA_TYPE_AS_OPAQ: 506 printf("Link State ID: %s Type %d ID %d\n", log_id(lsa->ls_id), 507 LSA_24_GETHI(ntohl(lsa->ls_id)), 508 LSA_24_GETLO(ntohl(lsa->ls_id))); 509 break; 510 } 511 512 printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr)); 513 printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num)); 514 printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum)); 515 printf("Length: %d\n", ntohs(lsa->len)); 516} 517 518static void 519show_db_simple(struct lsa_hdr *lsa, struct in_addr area_id, u_int8_t lasttype, 520 char *ifname) 521{ 522 if (lsa->type != lasttype) { 523 show_database_head(area_id, ifname, lsa->type); 524 printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID", 525 "Adv Router", "Age", "Seq#", "Checksum"); 526 } 527 printf("%-15s %-15s %-4d 0x%08x 0x%04x\n", 528 log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr), 529 ntohs(lsa->age), ntohl(lsa->seq_num), 530 ntohs(lsa->ls_chksum)); 531} 532static void 533show_db(struct lsa *lsa, struct in_addr area_id, u_int8_t lasttype, 534 char *ifname) 535{ 536 struct in_addr addr, data; 537 struct lsa_asext *asext; 538 struct lsa_rtr_link *rtr_link; 539 u_int16_t i, nlinks, off; 540 541 if (lsa->hdr.type != lasttype) 542 show_database_head(area_id, ifname, lsa->hdr.type); 543 show_db_hdr_msg_detail(&lsa->hdr); 544 545 switch (lsa->hdr.type) { 546 case LSA_TYPE_EXTERNAL: 547 addr.s_addr = lsa->data.asext.mask; 548 printf("Network Mask: %s\n", inet_ntoa(addr)); 549 550 asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr)); 551 552 printf(" Metric type: "); 553 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG) 554 printf("2\n"); 555 else 556 printf("1\n"); 557 printf(" Metric: %d\n", ntohl(asext->metric) & 558 LSA_METRIC_MASK); 559 addr.s_addr = asext->fw_addr; 560 printf(" Forwarding Address: %s\n", inet_ntoa(addr)); 561 printf(" External Route Tag: %d\n\n", ntohl(asext->ext_tag)); 562 break; 563 case LSA_TYPE_NETWORK: 564 addr.s_addr = lsa->data.net.mask; 565 printf("Network Mask: %s\n", inet_ntoa(addr)); 566 567 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) 568 - sizeof(u_int32_t)) / sizeof(struct lsa_net_link); 569 off = sizeof(lsa->hdr) + sizeof(u_int32_t); 570 printf("Number of Routers: %d\n", nlinks); 571 572 for (i = 0; i < nlinks; i++) { 573 addr.s_addr = lsa->data.net.att_rtr[i]; 574 printf(" Attached Router: %s\n", inet_ntoa(addr)); 575 } 576 577 printf("\n"); 578 break; 579 case LSA_TYPE_ROUTER: 580 printf("Flags: %s\n", print_ospf_flags(lsa->data.rtr.flags)); 581 nlinks = ntohs(lsa->data.rtr.nlinks); 582 printf("Number of Links: %d\n\n", nlinks); 583 584 off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr); 585 586 for (i = 0; i < nlinks; i++) { 587 rtr_link = (struct lsa_rtr_link *)((char *)lsa + off); 588 589 printf(" Link connected to: %s\n", 590 print_rtr_link_type(rtr_link->type)); 591 592 addr.s_addr = rtr_link->id; 593 data.s_addr = rtr_link->data; 594 595 switch (rtr_link->type) { 596 case LINK_TYPE_POINTTOPOINT: 597 case LINK_TYPE_VIRTUAL: 598 printf(" Link ID (Neighbors Router ID): " 599 "%s\n", inet_ntoa(addr)); 600 printf(" Link Data (Router Interface " 601 "address): %s\n", inet_ntoa(data)); 602 break; 603 case LINK_TYPE_TRANSIT_NET: 604 printf(" Link ID (Designated Router " 605 "address): %s\n", inet_ntoa(addr)); 606 printf(" Link Data (Router Interface " 607 "address): %s\n", inet_ntoa(data)); 608 break; 609 case LINK_TYPE_STUB_NET: 610 printf(" Link ID (Network ID): %s\n", 611 inet_ntoa(addr)); 612 printf(" Link Data (Network Mask): %s\n", 613 inet_ntoa(data)); 614 break; 615 default: 616 printf(" Link ID (Unknown): %s\n", 617 inet_ntoa(addr)); 618 printf(" Link Data (Unknown): %s\n", 619 inet_ntoa(data)); 620 break; 621 } 622 623 printf(" Metric: %d\n\n", ntohs(rtr_link->metric)); 624 625 off += sizeof(struct lsa_rtr_link) + 626 rtr_link->num_tos * sizeof(u_int32_t); 627 } 628 break; 629 case LSA_TYPE_SUM_ROUTER: 630 if (lsa->hdr.type != lasttype) 631 show_database_head(area_id, ifname, lsa->hdr.type); 632 633 show_db_hdr_msg_detail(&lsa->hdr); 634 addr.s_addr = lsa->data.sum.mask; 635 printf("Network Mask: %s\n", inet_ntoa(addr)); 636 printf("Metric: %d\n\n", ntohl(lsa->data.sum.metric) & 637 LSA_METRIC_MASK); 638 break; 639 case LSA_TYPE_LINK_OPAQ: 640 case LSA_TYPE_AREA_OPAQ: 641 case LSA_TYPE_AS_OPAQ: 642 if (lsa->hdr.type != lasttype) 643 show_database_head(area_id, ifname, lsa->hdr.type); 644 645 show_db_hdr_msg_detail(&lsa->hdr); 646 break; 647 } 648} 649 650static void 651show_tail(void) 652{ 653 /* nothing */ 654} 655 656const struct output show_output = { 657 .head = show_head, 658 .summary = show_summary, 659 .summary_area = show_summary_area, 660 .interface = show_interface, 661 .neighbor = show_neighbor, 662 .rib = show_rib, 663 .fib = show_fib, 664 .fib_interface = show_fib_interface, 665 .db = show_db, 666 .db_simple = show_db_simple, 667 .tail = show_tail 668}; 669