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