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