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.15 2006-09-13 06:31:11 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 "ospf.h" 43 #include "ospf6.h" 44 45 static const struct tok ospf6_option_values[] = { 46 { OSPF6_OPTION_V6, "V6" }, 47 { OSPF6_OPTION_E, "External" }, 48 { OSPF6_OPTION_MC, "Multicast" }, 49 { OSPF6_OPTION_N, "NSSA" }, 50 { OSPF6_OPTION_R, "Router" }, 51 { OSPF6_OPTION_DC, "Demand Circuit" }, 52 { 0, NULL } 53 }; 54 55 static const struct tok ospf6_rla_flag_values[] = { 56 { RLA_FLAG_B, "ABR" }, 57 { RLA_FLAG_E, "External" }, 58 { RLA_FLAG_V, "Virtual-Link Endpoint" }, 59 { RLA_FLAG_W, "Wildcard Receiver" }, 60 { RLA_FLAG_N, "NSSA Translator" }, 61 { 0, NULL } 62 }; 63 64 static const struct tok ospf6_asla_flag_values[] = { 65 { ASLA_FLAG_EXTERNAL, "External Type 2" }, 66 { ASLA_FLAG_FWDADDR, "Fforwarding" }, 67 { ASLA_FLAG_ROUTETAG, "Tag" }, 68 { 0, NULL } 69 }; 70 71 static struct tok ospf6_type_values[] = { 72 { OSPF_TYPE_HELLO, "Hello" }, 73 { OSPF_TYPE_DD, "Database Description" }, 74 { OSPF_TYPE_LS_REQ, "LS-Request" }, 75 { OSPF_TYPE_LS_UPDATE, "LS-Update" }, 76 { OSPF_TYPE_LS_ACK, "LS-Ack" }, 77 { 0, NULL } 78 }; 79 80 static struct tok ospf6_lsa_values[] = { 81 { LS_TYPE_ROUTER, "Router" }, 82 { LS_TYPE_NETWORK, "Network" }, 83 { LS_TYPE_INTER_AP, "Inter-Area Prefix" }, 84 { LS_TYPE_INTER_AR, "Inter-Area Router" }, 85 { LS_TYPE_ASE, "External" }, 86 { LS_TYPE_GROUP, "Multicast Group" }, 87 { LS_TYPE_NSSA, "NSSA" }, 88 { LS_TYPE_LINK, "Link" }, 89 { LS_TYPE_INTRA_AP, "Intra-Area Prefix" }, 90 { LS_TYPE_INTRA_ATE, "Intra-Area TE" }, 91 { LS_TYPE_GRACE, "Grace" }, 92 { 0, NULL } 93 }; 94 95 static struct tok ospf6_ls_scope_values[] = { 96 { LS_SCOPE_LINKLOCAL, "Link Local" }, 97 { LS_SCOPE_AREA, "Area Local" }, 98 { LS_SCOPE_AS, "Domain Wide" }, 99 { 0, NULL } 100 }; 101 102 static struct tok ospf6_dd_flag_values[] = { 103 { OSPF6_DB_INIT, "Init" }, 104 { OSPF6_DB_MORE, "More" }, 105 { OSPF6_DB_MASTER, "Master" }, 106 { 0, NULL } 107 }; 108 109 static struct tok ospf6_lsa_prefix_option_values[] = { 110 { LSA_PREFIX_OPT_NU, "No Unicast" }, 111 { LSA_PREFIX_OPT_LA, "Local address" }, 112 { LSA_PREFIX_OPT_MC, "Multicast" }, 113 { LSA_PREFIX_OPT_P, "Propagate" }, 114 { LSA_PREFIX_OPT_DN, "Down" }, 115 { 0, NULL } 116 }; 117 118 static char tstr[] = " [|ospf3]"; 119 120 #ifdef WIN32 121 #define inline __inline 122 #endif /* WIN32 */ 123 124 /* Forwards */ 125 static void ospf6_print_ls_type(u_int, const rtrid_t *); 126 static int ospf6_print_lshdr(const struct lsa6_hdr *); 127 static int ospf6_print_lsa(const struct lsa6 *); 128 static int ospf6_decode_v3(const struct ospf6hdr *, const u_char *); 129 130 131 static void 132 ospf6_print_ls_type(register u_int ls_type, register const rtrid_t *ls_stateid) 133 { 134 printf("\n\t %s LSA (%d), %s Scope%s, LSA-ID %s", 135 tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK), 136 ls_type & LS_TYPE_MASK, 137 tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK), 138 ls_type &0x8000 ? ", transitive" : "", /* U-bit */ 139 ipaddr_string(ls_stateid)); 140 } 141 142 static int 143 ospf6_print_lshdr(register const struct lsa6_hdr *lshp) 144 { 145 146 TCHECK(lshp->ls_type); 147 TCHECK(lshp->ls_seq); 148 149 printf("\n\t Advertising Router %s, seq 0x%08x, age %us, length %u", 150 ipaddr_string(&lshp->ls_router), 151 EXTRACT_32BITS(&lshp->ls_seq), 152 EXTRACT_16BITS(&lshp->ls_age), 153 EXTRACT_16BITS(&lshp->ls_length)-(u_int)sizeof(struct lsa6_hdr)); 154 155 ospf6_print_ls_type(EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid); 156 157 return (0); 158 trunc: 159 return (1); 160 } 161 162 static int 163 ospf6_print_lsaprefix(register const struct lsa6_prefix *lsapp) 164 { 165 u_int wordlen; 166 struct in6_addr prefix; 167 168 TCHECK(*lsapp); 169 wordlen = (lsapp->lsa_p_len + 31) / 32; 170 if (wordlen * 4 > sizeof(struct in6_addr)) { 171 printf(" bogus prefixlen /%d", lsapp->lsa_p_len); 172 goto trunc; 173 } 174 memset(&prefix, 0, sizeof(prefix)); 175 memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4); 176 printf("\n\t\t%s/%d", ip6addr_string(&prefix), 177 lsapp->lsa_p_len); 178 if (lsapp->lsa_p_opt) { 179 printf(", Options [%s]", 180 bittok2str(ospf6_lsa_prefix_option_values, 181 "none", lsapp->lsa_p_opt)); 182 } 183 printf(", metric %u", EXTRACT_16BITS(&lsapp->lsa_p_metric)); 184 return sizeof(*lsapp) - 4 + wordlen * 4; 185 186 trunc: 187 return -1; 188 } 189 190 191 /* 192 * Print a single link state advertisement. If truncated return 1, else 0. 193 */ 194 static int 195 ospf6_print_lsa(register const struct lsa6 *lsap) 196 { 197 register const u_char *ls_end, *ls_opt; 198 register const struct rlalink6 *rlp; 199 #if 0 200 register const struct tos_metric *tosp; 201 #endif 202 register const rtrid_t *ap; 203 #if 0 204 register const struct aslametric *almp; 205 register const struct mcla *mcp; 206 #endif 207 register const struct llsa *llsap; 208 register const struct lsa6_prefix *lsapp; 209 #if 0 210 register const u_int32_t *lp; 211 #endif 212 register u_int prefixes; 213 register int bytelen, length, lsa_length; 214 u_int32_t flags32; 215 u_int8_t *tptr; 216 217 if (ospf6_print_lshdr(&lsap->ls_hdr)) 218 return (1); 219 TCHECK(lsap->ls_hdr.ls_length); 220 length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length); 221 lsa_length = length - sizeof(struct lsa6_hdr); 222 ls_end = (u_char *)lsap + length; 223 tptr = (u_int8_t *)lsap+sizeof(struct lsa6_hdr); 224 225 switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { 226 case LS_TYPE_ROUTER | LS_SCOPE_AREA: 227 TCHECK(lsap->lsa_un.un_rla.rla_options); 228 printf("\n\t Options [%s]", 229 bittok2str(ospf6_option_values, "none", 230 EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options))); 231 232 TCHECK(lsap->lsa_un.un_rla.rla_flags); 233 printf(", RLA-Flags [%s]", 234 bittok2str(ospf6_rla_flag_values, "none", 235 lsap->lsa_un.un_rla.rla_flags)); 236 237 238 TCHECK(lsap->lsa_un.un_rla.rla_link); 239 rlp = lsap->lsa_un.un_rla.rla_link; 240 while (rlp + 1 <= (struct rlalink6 *)ls_end) { 241 TCHECK(*rlp); 242 switch (rlp->link_type) { 243 244 case RLA_TYPE_VIRTUAL: 245 printf("\n\t Virtual Link: Neighbor Router-ID %s" 246 "\n\t Neighbor Interface-ID %s, Interface %s", 247 ipaddr_string(&rlp->link_nrtid), 248 ipaddr_string(&rlp->link_nifid), 249 ipaddr_string(&rlp->link_ifid)); 250 break; 251 252 case RLA_TYPE_ROUTER: 253 printf("\n\t Neighbor Router-ID %s" 254 "\n\t Neighbor Interface-ID %s, Interface %s", 255 ipaddr_string(&rlp->link_nrtid), 256 ipaddr_string(&rlp->link_nifid), 257 ipaddr_string(&rlp->link_ifid)); 258 break; 259 260 case RLA_TYPE_TRANSIT: 261 printf("\n\t Neighbor Network-ID %s" 262 "\n\t Neighbor Interface-ID %s, Interface %s", 263 ipaddr_string(&rlp->link_nrtid), 264 ipaddr_string(&rlp->link_nifid), 265 ipaddr_string(&rlp->link_ifid)); 266 break; 267 268 default: 269 printf("\n\t Unknown Router Links Type 0x%02x", 270 rlp->link_type); 271 return (0); 272 } 273 printf(", metric %d", EXTRACT_16BITS(&rlp->link_metric)); 274 rlp++; 275 } 276 break; 277 278 case LS_TYPE_NETWORK | LS_SCOPE_AREA: 279 TCHECK(lsap->lsa_un.un_nla.nla_options); 280 printf("\n\t Options [%s]", 281 bittok2str(ospf6_option_values, "none", 282 EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options))); 283 printf("\n\t Connected Routers:"); 284 ap = lsap->lsa_un.un_nla.nla_router; 285 while ((u_char *)ap < ls_end) { 286 TCHECK(*ap); 287 printf("\n\t\t%s", ipaddr_string(ap)); 288 ++ap; 289 } 290 break; 291 292 case LS_TYPE_INTER_AP | LS_SCOPE_AREA: 293 TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); 294 printf(", metric %u", 295 EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC); 296 lsapp = lsap->lsa_un.un_inter_ap.inter_ap_prefix; 297 while (lsapp + sizeof(lsapp) <= (struct lsa6_prefix *)ls_end) { 298 bytelen = ospf6_print_lsaprefix(lsapp); 299 if (bytelen) 300 goto trunc; 301 lsapp = (struct lsa6_prefix *)(((u_char *)lsapp) + bytelen); 302 } 303 break; 304 case LS_SCOPE_AS | LS_TYPE_ASE: 305 TCHECK(lsap->lsa_un.un_asla.asla_metric); 306 flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); 307 printf("\n\t Flags [%s]", 308 bittok2str(ospf6_asla_flag_values, "none", flags32)); 309 printf(" metric %u", 310 EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & 311 ASLA_MASK_METRIC); 312 lsapp = lsap->lsa_un.un_asla.asla_prefix; 313 bytelen = ospf6_print_lsaprefix(lsapp); 314 if (bytelen < 0) 315 goto trunc; 316 if ((ls_opt = (u_char *)(((u_char *)lsapp) + bytelen)) < ls_end) { 317 struct in6_addr *fwdaddr6; 318 319 if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { 320 fwdaddr6 = (struct in6_addr *)ls_opt; 321 TCHECK(*fwdaddr6); 322 printf(" forward %s", 323 ip6addr_string(fwdaddr6)); 324 325 ls_opt += sizeof(struct in6_addr); 326 } 327 328 if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { 329 TCHECK(*(u_int32_t *)ls_opt); 330 printf(" tag %s", 331 ipaddr_string((u_int32_t *)ls_opt)); 332 333 ls_opt += sizeof(u_int32_t); 334 } 335 336 if (lsapp->lsa_p_metric) { 337 TCHECK(*(u_int32_t *)ls_opt); 338 printf(" RefLSID: %s", 339 ipaddr_string((u_int32_t *)ls_opt)); 340 341 ls_opt += sizeof(u_int32_t); 342 } 343 } 344 break; 345 346 case LS_TYPE_LINK: 347 /* Link LSA */ 348 llsap = &lsap->lsa_un.un_llsa; 349 TCHECK(llsap->llsa_options); 350 printf("\n\t Options [%s]", 351 bittok2str(ospf6_option_values, "none", 352 EXTRACT_32BITS(&llsap->llsa_options))); 353 TCHECK(llsap->llsa_nprefix); 354 prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); 355 printf("\n\t Priority %d, Link-local address %s, Prefixes %d:", 356 llsap->llsa_priority, 357 ip6addr_string(&llsap->llsa_lladdr), 358 prefixes); 359 360 tptr = (u_int8_t *)llsap->llsa_prefix; 361 while (prefixes > 0) { 362 lsapp = (struct lsa6_prefix *)tptr; 363 if ((bytelen = ospf6_print_lsaprefix(lsapp)) == -1) { 364 goto trunc; 365 } 366 prefixes--; 367 tptr += bytelen; 368 } 369 break; 370 371 case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: 372 /* Intra-Area-Prefix LSA */ 373 TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); 374 ospf6_print_ls_type( 375 EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), 376 &lsap->lsa_un.un_intra_ap.intra_ap_lsid); 377 TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 378 prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 379 printf("\n\t Prefixes %d:", prefixes); 380 381 tptr = (u_int8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; 382 383 while (prefixes > 0) { 384 lsapp = (struct lsa6_prefix *)tptr; 385 if ((bytelen = ospf6_print_lsaprefix(lsapp)) == -1) { 386 goto trunc; 387 } 388 prefixes--; 389 tptr += bytelen; 390 } 391 break; 392 393 case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: 394 if (ospf_print_grace_lsa(tptr, lsa_length) == -1) { 395 return 1; 396 } 397 398 break; 399 400 case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: 401 if (ospf_print_te_lsa(tptr, lsa_length) == -1) { 402 return 1; 403 } 404 break; 405 406 default: 407 if(!print_unknown_data(tptr, 408 "\n\t ", 409 lsa_length)) { 410 return (1); 411 } 412 } 413 414 return (0); 415 trunc: 416 return (1); 417 } 418 419 static int 420 ospf6_decode_v3(register const struct ospf6hdr *op, 421 register const u_char *dataend) 422 { 423 register const rtrid_t *ap; 424 register const struct lsr6 *lsrp; 425 register const struct lsa6_hdr *lshp; 426 register const struct lsa6 *lsap; 427 register int i; 428 429 switch (op->ospf6_type) { 430 431 case OSPF_TYPE_HELLO: 432 printf("\n\tOptions [%s]", 433 bittok2str(ospf6_option_values, "none", 434 EXTRACT_32BITS(&op->ospf6_hello.hello_options))); 435 436 TCHECK(op->ospf6_hello.hello_deadint); 437 printf("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u", 438 EXTRACT_16BITS(&op->ospf6_hello.hello_helloint), 439 EXTRACT_16BITS(&op->ospf6_hello.hello_deadint), 440 ipaddr_string(&op->ospf6_hello.hello_ifid), 441 op->ospf6_hello.hello_priority); 442 443 TCHECK(op->ospf6_hello.hello_dr); 444 if (op->ospf6_hello.hello_dr != 0) 445 printf("\n\t Designated Router %s", 446 ipaddr_string(&op->ospf6_hello.hello_dr)); 447 TCHECK(op->ospf6_hello.hello_bdr); 448 if (op->ospf6_hello.hello_bdr != 0) 449 printf(", Backup Designated Router %s", 450 ipaddr_string(&op->ospf6_hello.hello_bdr)); 451 if (vflag) { 452 printf("\n\t Neighbor List:"); 453 ap = op->ospf6_hello.hello_neighbor; 454 while ((u_char *)ap < dataend) { 455 TCHECK(*ap); 456 printf("\n\t %s", ipaddr_string(ap)); 457 ++ap; 458 } 459 } 460 break; /* HELLO */ 461 462 case OSPF_TYPE_DD: 463 TCHECK(op->ospf6_db.db_options); 464 printf("\n\tOptions [%s]", 465 bittok2str(ospf6_option_values, "none", 466 EXTRACT_32BITS(&op->ospf6_db.db_options))); 467 TCHECK(op->ospf6_db.db_flags); 468 printf(", DD Flags [%s]", 469 bittok2str(ospf6_dd_flag_values,"none",op->ospf6_db.db_flags)); 470 471 TCHECK(op->ospf6_db.db_seq); 472 printf(", MTU %u, DD-Sequence 0x%08x", 473 EXTRACT_16BITS(&op->ospf6_db.db_mtu), 474 EXTRACT_32BITS(&op->ospf6_db.db_seq)); 475 476 /* Print all the LS adv's */ 477 lshp = op->ospf6_db.db_lshdr; 478 while (!ospf6_print_lshdr(lshp)) { 479 ++lshp; 480 } 481 break; 482 483 case OSPF_TYPE_LS_REQ: 484 if (vflag) { 485 lsrp = op->ospf6_lsr; 486 while ((u_char *)lsrp < dataend) { 487 TCHECK(*lsrp); 488 printf("\n\t Advertising Router %s", 489 ipaddr_string(&lsrp->ls_router)); 490 ospf6_print_ls_type(EXTRACT_16BITS(&lsrp->ls_type), 491 &lsrp->ls_stateid); 492 ++lsrp; 493 } 494 } 495 break; 496 497 case OSPF_TYPE_LS_UPDATE: 498 if (vflag) { 499 lsap = op->ospf6_lsu.lsu_lsa; 500 TCHECK(op->ospf6_lsu.lsu_count); 501 i = EXTRACT_32BITS(&op->ospf6_lsu.lsu_count); 502 while (i--) { 503 if (ospf6_print_lsa(lsap)) 504 goto trunc; 505 lsap = (struct lsa6 *)((u_char *)lsap + 506 EXTRACT_16BITS(&lsap->ls_hdr.ls_length)); 507 } 508 } 509 break; 510 511 512 case OSPF_TYPE_LS_ACK: 513 if (vflag) { 514 lshp = op->ospf6_lsa.lsa_lshdr; 515 516 while (!ospf6_print_lshdr(lshp)) { 517 ++lshp; 518 } 519 } 520 break; 521 522 default: 523 break; 524 } 525 return (0); 526 trunc: 527 return (1); 528 } 529 530 void 531 ospf6_print(register const u_char *bp, register u_int length) 532 { 533 register const struct ospf6hdr *op; 534 register const u_char *dataend; 535 register const char *cp; 536 537 op = (struct ospf6hdr *)bp; 538 539 /* If the type is valid translate it, or just print the type */ 540 /* value. If it's not valid, say so and return */ 541 TCHECK(op->ospf6_type); 542 cp = tok2str(ospf6_type_values, "unknown LS-type", op->ospf6_type); 543 printf("OSPFv%u, %s, length %d", op->ospf6_version, cp, length); 544 if (*cp == 'u') { 545 return; 546 } 547 548 if(!vflag) { /* non verbose - so lets bail out here */ 549 return; 550 } 551 552 TCHECK(op->ospf6_len); 553 if (length != EXTRACT_16BITS(&op->ospf6_len)) { 554 printf(" [len %d]", EXTRACT_16BITS(&op->ospf6_len)); 555 return; 556 } 557 dataend = bp + length; 558 559 /* Print the routerid if it is not the same as the source */ 560 TCHECK(op->ospf6_routerid); 561 printf("\n\tRouter-ID %s", ipaddr_string(&op->ospf6_routerid)); 562 563 TCHECK(op->ospf6_areaid); 564 if (op->ospf6_areaid != 0) 565 printf(", Area %s", ipaddr_string(&op->ospf6_areaid)); 566 else 567 printf(", Backbone Area"); 568 TCHECK(op->ospf6_instanceid); 569 if (op->ospf6_instanceid) 570 printf(", Instance %u", op->ospf6_instanceid); 571 572 /* Do rest according to version. */ 573 switch (op->ospf6_version) { 574 575 case 3: 576 /* ospf version 3 */ 577 if (ospf6_decode_v3(op, dataend)) 578 goto trunc; 579 break; 580 581 default: 582 printf(" ospf [version %d]", op->ospf6_version); 583 break; 584 } /* end switch on version */ 585 586 return; 587 trunc: 588 fputs(tstr, stdout); 589 } 590