1 /* 2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 22 */ 23 24 #ifndef lint 25 static const char rcsid[] _U_ = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-ospf6.c,v 1.13 2003/11/16 09:36:31 guy Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <tcpdump-stdinc.h> 34 35 #include <stdio.h> 36 #include <string.h> 37 38 #include "interface.h" 39 #include "addrtoname.h" 40 #include "extract.h" 41 42 #include "ospf6.h" 43 44 struct bits { 45 u_int32_t bit; 46 const char *str; 47 }; 48 49 static const struct bits ospf6_option_bits[] = { 50 { OSPF6_OPTION_V6, "V6" }, 51 { OSPF6_OPTION_E, "E" }, 52 { OSPF6_OPTION_MC, "MC" }, 53 { OSPF6_OPTION_N, "N" }, 54 { OSPF6_OPTION_R, "R" }, 55 { OSPF6_OPTION_DC, "DC" }, 56 { 0, NULL } 57 }; 58 59 static const struct bits ospf6_rla_flag_bits[] = { 60 { RLA_FLAG_B, "B" }, 61 { RLA_FLAG_E, "E" }, 62 { RLA_FLAG_V, "V" }, 63 { RLA_FLAG_W, "W" }, 64 { 0, NULL } 65 }; 66 67 static const struct bits ospf6_asla_flag_bits[] = { 68 { ASLA_FLAG_EXTERNAL, "E" }, 69 { ASLA_FLAG_FWDADDR, "F" }, 70 { ASLA_FLAG_ROUTETAG, "T" }, 71 { 0, NULL } 72 }; 73 74 static struct tok type2str[] = { 75 { OSPF_TYPE_UMD, "umd" }, 76 { OSPF_TYPE_HELLO, "hello" }, 77 { OSPF_TYPE_DB, "dd" }, 78 { OSPF_TYPE_LSR, "ls_req" }, 79 { OSPF_TYPE_LSU, "ls_upd" }, 80 { OSPF_TYPE_LSA, "ls_ack" }, 81 { 0, NULL } 82 }; 83 84 static char tstr[] = " [|ospf]"; 85 86 #ifdef WIN32 87 #define inline __inline 88 #endif /* WIN32 */ 89 90 /* Forwards */ 91 static inline void ospf6_print_seqage(u_int32_t, time_t); 92 static inline void ospf6_print_bits(const struct bits *, u_char); 93 static void ospf6_print_ls_type(u_int, const rtrid_t *, 94 const rtrid_t *, const char *); 95 static int ospf6_print_lshdr(const struct lsa_hdr *); 96 static int ospf6_print_lsa(const struct lsa *); 97 static int ospf6_decode_v3(const struct ospf6hdr *, const u_char *); 98 99 static inline void 100 ospf6_print_seqage(register u_int32_t seq, register time_t us) 101 { 102 register time_t sec = us % 60; 103 register time_t mins = (us / 60) % 60; 104 register time_t hour = us / 3600; 105 106 printf(" S %X age ", seq); 107 if (hour) 108 printf("%u:%02u:%02u", 109 (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec); 110 else if (mins) 111 printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec); 112 else 113 printf("%u", (u_int32_t) sec); 114 } 115 116 117 static inline void 118 ospf6_print_bits(register const struct bits *bp, register u_char options) 119 { 120 register char sep = ' '; 121 122 do { 123 if (options & bp->bit) { 124 printf("%c%s", sep, bp->str); 125 sep = '/'; 126 } 127 } while ((++bp)->bit); 128 } 129 130 static void 131 ospf6_print_ls_type(register u_int ls_type, 132 register const rtrid_t *ls_stateid, 133 register const rtrid_t *ls_router, register const char *fmt) 134 { 135 const char *scope; 136 137 switch (ls_type & LS_SCOPE_MASK) { 138 case LS_SCOPE_LINKLOCAL: 139 scope = "linklocal-"; 140 break; 141 case LS_SCOPE_AREA: 142 scope = "area-"; 143 break; 144 case LS_SCOPE_AS: 145 scope = "AS-"; 146 break; 147 default: 148 scope = ""; 149 break; 150 } 151 152 switch (ls_type & LS_TYPE_MASK) { 153 case LS_TYPE_ROUTER: 154 printf(" %srtr %s", scope, ipaddr_string(ls_router)); 155 break; 156 157 case LS_TYPE_NETWORK: 158 printf(" %snet dr %s if %s", scope, 159 ipaddr_string(ls_router), 160 ipaddr_string(ls_stateid)); 161 break; 162 163 case LS_TYPE_INTER_AP: 164 printf(" %sinter-area-prefix %s abr %s", scope, 165 ipaddr_string(ls_stateid), 166 ipaddr_string(ls_router)); 167 break; 168 169 case LS_TYPE_INTER_AR: 170 printf(" %sinter-area-router %s rtr %s", scope, 171 ipaddr_string(ls_router), 172 ipaddr_string(ls_stateid)); 173 break; 174 175 case LS_TYPE_ASE: 176 printf(" %sase %s asbr %s", scope, 177 ipaddr_string(ls_stateid), 178 ipaddr_string(ls_router)); 179 break; 180 181 case LS_TYPE_GROUP: 182 printf(" %sgroup %s rtr %s", scope, 183 ipaddr_string(ls_stateid), 184 ipaddr_string(ls_router)); 185 break; 186 187 case LS_TYPE_TYPE7: 188 printf(" %stype7 %s rtr %s", scope, 189 ipaddr_string(ls_stateid), 190 ipaddr_string(ls_router)); 191 break; 192 193 case LS_TYPE_LINK: 194 printf(" %slink %s rtr %s", scope, 195 ipaddr_string(ls_stateid), 196 ipaddr_string(ls_router)); 197 break; 198 199 case LS_TYPE_INTRA_AP: 200 printf(" %sintra-area-prefix %s rtr %s", scope, 201 ipaddr_string(ls_stateid), 202 ipaddr_string(ls_router)); 203 break; 204 205 default: 206 printf(" %s", scope); 207 printf(fmt, ls_type); 208 break; 209 } 210 211 } 212 213 static int 214 ospf6_print_lshdr(register const struct lsa_hdr *lshp) 215 { 216 217 TCHECK(lshp->ls_type); 218 printf(" {"); /* } (ctags) */ 219 220 TCHECK(lshp->ls_seq); 221 ospf6_print_seqage(EXTRACT_32BITS(&lshp->ls_seq), EXTRACT_16BITS(&lshp->ls_age)); 222 ospf6_print_ls_type(EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid, 223 &lshp->ls_router, "ls_type %d"); 224 225 return (0); 226 trunc: 227 return (1); 228 } 229 230 static int 231 ospf6_print_lsaprefix(register const struct lsa_prefix *lsapp) 232 { 233 u_int k; 234 struct in6_addr prefix; 235 236 TCHECK(*lsapp); 237 k = (lsapp->lsa_p_len + 31) / 32; 238 if (k * 4 > sizeof(struct in6_addr)) { 239 printf("??prefixlen %d??", lsapp->lsa_p_len); 240 goto trunc; 241 } 242 memset(&prefix, 0, sizeof(prefix)); 243 memcpy(&prefix, lsapp->lsa_p_prefix, k * 4); 244 printf(" %s/%d", ip6addr_string(&prefix), 245 lsapp->lsa_p_len); 246 if (lsapp->lsa_p_opt) 247 printf("(opt=%x)", lsapp->lsa_p_opt); 248 if (lsapp->lsa_p_mbz) 249 printf("(mbz=%x)", EXTRACT_16BITS(&lsapp->lsa_p_mbz)); /* XXX */ 250 return sizeof(*lsapp) - 4 + k * 4; 251 252 trunc: 253 return -1; 254 } 255 256 257 /* 258 * Print a single link state advertisement. If truncated return 1, else 0. 259 */ 260 static int 261 ospf6_print_lsa(register const struct lsa *lsap) 262 { 263 register const u_char *ls_end, *ls_opt; 264 register const struct rlalink *rlp; 265 #if 0 266 register const struct tos_metric *tosp; 267 #endif 268 register const rtrid_t *ap; 269 #if 0 270 register const struct aslametric *almp; 271 register const struct mcla *mcp; 272 #endif 273 register const struct llsa *llsap; 274 register const struct lsa_prefix *lsapp; 275 #if 0 276 register const u_int32_t *lp; 277 #endif 278 register u_int j; 279 register int k; 280 u_int32_t flags32; 281 282 if (ospf6_print_lshdr(&lsap->ls_hdr)) 283 return (1); 284 TCHECK(lsap->ls_hdr.ls_length); 285 ls_end = (u_char *)lsap + EXTRACT_16BITS(&lsap->ls_hdr.ls_length); 286 switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { 287 case LS_TYPE_ROUTER | LS_SCOPE_AREA: 288 TCHECK(lsap->lsa_un.un_rla.rla_flags); 289 ospf6_print_bits(ospf6_rla_flag_bits, 290 lsap->lsa_un.un_rla.rla_flags); 291 TCHECK(lsap->lsa_un.un_rla.rla_options); 292 ospf6_print_bits(ospf6_option_bits, 293 EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options)); 294 295 TCHECK(lsap->lsa_un.un_rla.rla_link); 296 rlp = lsap->lsa_un.un_rla.rla_link; 297 while (rlp + sizeof(*rlp) <= (struct rlalink *)ls_end) { 298 TCHECK(*rlp); 299 printf(" {"); /* } (ctags) */ 300 switch (rlp->link_type) { 301 302 case RLA_TYPE_VIRTUAL: 303 printf(" virt"); 304 /* Fall through */ 305 306 case RLA_TYPE_ROUTER: 307 printf(" nbrid %s nbrif %s if %s", 308 ipaddr_string(&rlp->link_nrtid), 309 ipaddr_string(&rlp->link_nifid), 310 ipaddr_string(&rlp->link_ifid)); 311 break; 312 313 case RLA_TYPE_TRANSIT: 314 printf(" dr %s drif %s if %s", 315 ipaddr_string(&rlp->link_nrtid), 316 ipaddr_string(&rlp->link_nifid), 317 ipaddr_string(&rlp->link_ifid)); 318 break; 319 320 default: 321 /* { (ctags) */ 322 printf(" ??RouterLinksType 0x%02x?? }", 323 rlp->link_type); 324 return (0); 325 } 326 printf(" metric %d", EXTRACT_16BITS(&rlp->link_metric)); 327 /* { (ctags) */ 328 printf(" }"); 329 rlp++; 330 } 331 break; 332 333 case LS_TYPE_NETWORK | LS_SCOPE_AREA: 334 TCHECK(lsap->lsa_un.un_nla.nla_options); 335 ospf6_print_bits(ospf6_option_bits, 336 EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options)); 337 printf(" rtrs"); 338 ap = lsap->lsa_un.un_nla.nla_router; 339 while ((u_char *)ap < ls_end) { 340 TCHECK(*ap); 341 printf(" %s", ipaddr_string(ap)); 342 ++ap; 343 } 344 break; 345 346 case LS_TYPE_INTER_AP | LS_SCOPE_AREA: 347 TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); 348 printf(" metric %u", 349 EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC); 350 lsapp = lsap->lsa_un.un_inter_ap.inter_ap_prefix; 351 while (lsapp + sizeof(lsapp) <= (struct lsa_prefix *)ls_end) { 352 k = ospf6_print_lsaprefix(lsapp); 353 if (k) 354 goto trunc; 355 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k); 356 } 357 break; 358 case LS_SCOPE_AS | LS_TYPE_ASE: 359 TCHECK(lsap->lsa_un.un_asla.asla_metric); 360 flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); 361 ospf6_print_bits(ospf6_asla_flag_bits, flags32); 362 printf(" metric %u", 363 EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & 364 ASLA_MASK_METRIC); 365 lsapp = lsap->lsa_un.un_asla.asla_prefix; 366 k = ospf6_print_lsaprefix(lsapp); 367 if (k < 0) 368 goto trunc; 369 if ((ls_opt = (u_char *)(((u_char *)lsapp) + k)) < ls_end) { 370 struct in6_addr *fwdaddr6; 371 372 if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { 373 fwdaddr6 = (struct in6_addr *)ls_opt; 374 TCHECK(*fwdaddr6); 375 printf(" forward %s", 376 ip6addr_string(fwdaddr6)); 377 378 ls_opt += sizeof(struct in6_addr); 379 } 380 381 if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { 382 TCHECK(*(u_int32_t *)ls_opt); 383 printf(" tag %s", 384 ipaddr_string((u_int32_t *)ls_opt)); 385 386 ls_opt += sizeof(u_int32_t); 387 } 388 389 if (lsapp->lsa_p_mbz) { 390 TCHECK(*(u_int32_t *)ls_opt); 391 printf(" RefLSID: %s", 392 ipaddr_string((u_int32_t *)ls_opt)); 393 394 ls_opt += sizeof(u_int32_t); 395 } 396 } 397 break; 398 #if 0 399 case LS_TYPE_SUM_ABR: 400 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 401 lp = lsap->lsa_un.un_sla.sla_tosmetric; 402 while ((u_char *)lp < ls_end) { 403 register u_int32_t ul; 404 405 TCHECK(*lp); 406 ul = EXTRACT_32BITS(lp); 407 printf(" tos %d metric %d", 408 (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, 409 ul & SLA_MASK_METRIC); 410 ++lp; 411 } 412 break; 413 414 case LS_TYPE_GROUP: 415 /* Multicast extensions as of 23 July 1991 */ 416 mcp = lsap->lsa_un.un_mcla; 417 while ((u_char *)mcp < ls_end) { 418 TCHECK(mcp->mcla_vid); 419 switch (EXTRACT_32BITS(&mcp->mcla_vtype)) { 420 421 case MCLA_VERTEX_ROUTER: 422 printf(" rtr rtrid %s", 423 ipaddr_string(&mcp->mcla_vid)); 424 break; 425 426 case MCLA_VERTEX_NETWORK: 427 printf(" net dr %s", 428 ipaddr_string(&mcp->mcla_vid)); 429 break; 430 431 default: 432 printf(" ??VertexType %u??", 433 EXTRACT_32BITS(&mcp->mcla_vtype)); 434 break; 435 } 436 ++mcp; 437 } 438 #endif 439 440 case LS_TYPE_LINK: 441 /* Link LSA */ 442 llsap = &lsap->lsa_un.un_llsa; 443 TCHECK(llsap->llsa_options); 444 ospf6_print_bits(ospf6_option_bits, EXTRACT_32BITS(&llsap->llsa_options)); 445 TCHECK(llsap->llsa_nprefix); 446 printf(" pri %d lladdr %s npref %d", llsap->llsa_priority, 447 ip6addr_string(&llsap->llsa_lladdr), 448 EXTRACT_32BITS(&llsap->llsa_nprefix)); 449 lsapp = llsap->llsa_prefix; 450 for (j = 0; j < EXTRACT_32BITS(&llsap->llsa_nprefix); j++) { 451 k = ospf6_print_lsaprefix(lsapp); 452 if (k) 453 goto trunc; 454 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k); 455 } 456 break; 457 458 case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: 459 /* Intra-Area-Prefix LSA */ 460 TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); 461 ospf6_print_ls_type( 462 EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), 463 &lsap->lsa_un.un_intra_ap.intra_ap_lsid, 464 &lsap->lsa_un.un_intra_ap.intra_ap_rtid, 465 "LinkStateType %d"); 466 TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 467 printf(" npref %d", 468 EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix)); 469 470 lsapp = lsap->lsa_un.un_intra_ap.intra_ap_prefix; 471 for (j = 0; 472 j < EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 473 j++) { 474 k = ospf6_print_lsaprefix(lsapp); 475 if (k) 476 goto trunc; 477 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k); 478 } 479 break; 480 481 default: 482 printf(" ??LinkStateType 0x%04x??", 483 EXTRACT_16BITS(&lsap->ls_hdr.ls_type)); 484 } 485 486 /* { (ctags) */ 487 fputs(" }", stdout); 488 return (0); 489 trunc: 490 fputs(" }", stdout); 491 return (1); 492 } 493 494 static int 495 ospf6_decode_v3(register const struct ospf6hdr *op, 496 register const u_char *dataend) 497 { 498 register const rtrid_t *ap; 499 register const struct lsr *lsrp; 500 register const struct lsa_hdr *lshp; 501 register const struct lsa *lsap; 502 register char sep; 503 register int i; 504 505 switch (op->ospf6_type) { 506 507 case OSPF_TYPE_UMD: 508 /* 509 * Rob Coltun's special monitoring packets; 510 * do nothing 511 */ 512 break; 513 514 case OSPF_TYPE_HELLO: 515 if (vflag) { 516 TCHECK(op->ospf6_hello.hello_deadint); 517 ospf6_print_bits(ospf6_option_bits, 518 EXTRACT_32BITS(&op->ospf6_hello.hello_options)); 519 printf(" ifid %s pri %d int %d dead %u", 520 ipaddr_string(&op->ospf6_hello.hello_ifid), 521 op->ospf6_hello.hello_priority, 522 EXTRACT_16BITS(&op->ospf6_hello.hello_helloint), 523 EXTRACT_16BITS(&op->ospf6_hello.hello_deadint)); 524 } 525 TCHECK(op->ospf6_hello.hello_dr); 526 if (op->ospf6_hello.hello_dr != 0) 527 printf(" dr %s", 528 ipaddr_string(&op->ospf6_hello.hello_dr)); 529 TCHECK(op->ospf6_hello.hello_bdr); 530 if (op->ospf6_hello.hello_bdr != 0) 531 printf(" bdr %s", 532 ipaddr_string(&op->ospf6_hello.hello_bdr)); 533 if (vflag) { 534 printf(" nbrs"); 535 ap = op->ospf6_hello.hello_neighbor; 536 while ((u_char *)ap < dataend) { 537 TCHECK(*ap); 538 printf(" %s", ipaddr_string(ap)); 539 ++ap; 540 } 541 } 542 break; /* HELLO */ 543 544 case OSPF_TYPE_DB: 545 TCHECK(op->ospf6_db.db_options); 546 ospf6_print_bits(ospf6_option_bits, 547 EXTRACT_32BITS(&op->ospf6_db.db_options)); 548 sep = ' '; 549 TCHECK(op->ospf6_db.db_flags); 550 if (op->ospf6_db.db_flags & OSPF6_DB_INIT) { 551 printf("%cI", sep); 552 sep = '/'; 553 } 554 if (op->ospf6_db.db_flags & OSPF6_DB_MORE) { 555 printf("%cM", sep); 556 sep = '/'; 557 } 558 if (op->ospf6_db.db_flags & OSPF6_DB_MASTER) { 559 printf("%cMS", sep); 560 sep = '/'; 561 } 562 TCHECK(op->ospf6_db.db_seq); 563 printf(" mtu %u S %X", EXTRACT_16BITS(&op->ospf6_db.db_mtu), 564 EXTRACT_32BITS(&op->ospf6_db.db_seq)); 565 566 if (vflag) { 567 /* Print all the LS adv's */ 568 lshp = op->ospf6_db.db_lshdr; 569 570 while (!ospf6_print_lshdr(lshp)) { 571 /* { (ctags) */ 572 printf(" }"); 573 ++lshp; 574 } 575 } 576 break; 577 578 case OSPF_TYPE_LSR: 579 if (vflag) { 580 lsrp = op->ospf6_lsr; 581 while ((u_char *)lsrp < dataend) { 582 TCHECK(*lsrp); 583 printf(" {"); /* } (ctags) */ 584 ospf6_print_ls_type(EXTRACT_16BITS(&lsrp->ls_type), 585 &lsrp->ls_stateid, 586 &lsrp->ls_router, 587 "LinkStateType %d"); 588 /* { (ctags) */ 589 printf(" }"); 590 ++lsrp; 591 } 592 } 593 break; 594 595 case OSPF_TYPE_LSU: 596 if (vflag) { 597 lsap = op->ospf6_lsu.lsu_lsa; 598 TCHECK(op->ospf6_lsu.lsu_count); 599 i = EXTRACT_32BITS(&op->ospf6_lsu.lsu_count); 600 while (i--) { 601 if (ospf6_print_lsa(lsap)) 602 goto trunc; 603 lsap = (struct lsa *)((u_char *)lsap + 604 EXTRACT_16BITS(&lsap->ls_hdr.ls_length)); 605 } 606 } 607 break; 608 609 610 case OSPF_TYPE_LSA: 611 if (vflag) { 612 lshp = op->ospf6_lsa.lsa_lshdr; 613 614 while (!ospf6_print_lshdr(lshp)) { 615 /* { (ctags) */ 616 printf(" }"); 617 ++lshp; 618 } 619 } 620 break; 621 622 default: 623 printf("v3 type %d", op->ospf6_type); 624 break; 625 } 626 return (0); 627 trunc: 628 return (1); 629 } 630 631 void 632 ospf6_print(register const u_char *bp, register u_int length) 633 { 634 register const struct ospf6hdr *op; 635 register const u_char *dataend; 636 register const char *cp; 637 638 op = (struct ospf6hdr *)bp; 639 640 /* If the type is valid translate it, or just print the type */ 641 /* value. If it's not valid, say so and return */ 642 TCHECK(op->ospf6_type); 643 cp = tok2str(type2str, "type%d", op->ospf6_type); 644 printf("OSPFv%d-%s %d:", op->ospf6_version, cp, length); 645 if (*cp == 't') 646 return; 647 648 TCHECK(op->ospf6_len); 649 if (length != EXTRACT_16BITS(&op->ospf6_len)) { 650 printf(" [len %d]", EXTRACT_16BITS(&op->ospf6_len)); 651 return; 652 } 653 dataend = bp + length; 654 655 /* Print the routerid if it is not the same as the source */ 656 TCHECK(op->ospf6_routerid); 657 printf(" rtrid %s", ipaddr_string(&op->ospf6_routerid)); 658 659 TCHECK(op->ospf6_areaid); 660 if (op->ospf6_areaid != 0) 661 printf(" area %s", ipaddr_string(&op->ospf6_areaid)); 662 else 663 printf(" backbone"); 664 TCHECK(op->ospf6_instanceid); 665 if (op->ospf6_instanceid) 666 printf(" instance %u", op->ospf6_instanceid); 667 668 /* Do rest according to version. */ 669 switch (op->ospf6_version) { 670 671 case 3: 672 /* ospf version 3 */ 673 if (ospf6_decode_v3(op, dataend)) 674 goto trunc; 675 break; 676 677 default: 678 printf(" ospf [version %d]", op->ospf6_version); 679 break; 680 } /* end switch on version */ 681 682 return; 683 trunc: 684 fputs(tstr, stdout); 685 } 686