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-ospf.c,v 1.31 2001/06/28 04:34:51 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 39 #include <ctype.h> 40 #include <stdio.h> 41 42 #include "interface.h" 43 #include "addrtoname.h" 44 45 #include "ospf.h" 46 47 #include "ip.h" 48 49 struct bits { 50 u_int32_t bit; 51 const char *str; 52 }; 53 54 static const struct bits ospf_option_bits[] = { 55 { OSPF_OPTION_T, "T" }, 56 { OSPF_OPTION_E, "E" }, 57 { OSPF_OPTION_MC, "MC" }, 58 { 0, NULL } 59 }; 60 61 static const struct bits ospf_rla_flag_bits[] = { 62 { RLA_FLAG_B, "B" }, 63 { RLA_FLAG_E, "E" }, 64 { RLA_FLAG_W1, "W1" }, 65 { RLA_FLAG_W2, "W2" }, 66 { 0, NULL } 67 }; 68 69 static struct tok type2str[] = { 70 { OSPF_TYPE_UMD, "umd" }, 71 { OSPF_TYPE_HELLO, "hello" }, 72 { OSPF_TYPE_DB, "dd" }, 73 { OSPF_TYPE_LSR, "ls_req" }, 74 { OSPF_TYPE_LSU, "ls_upd" }, 75 { OSPF_TYPE_LSA, "ls_ack" }, 76 { 0, NULL } 77 }; 78 79 static char tstr[] = " [|ospf]"; 80 81 /* Forwards */ 82 static inline void ospf_print_seqage(u_int32_t, time_t); 83 static inline void ospf_print_bits(const struct bits *, u_char); 84 static void ospf_print_ls_type(u_int, const struct in_addr *, 85 const struct in_addr *, const char *); 86 static int ospf_print_lshdr(const struct lsa_hdr *); 87 static int ospf_print_lsa(const struct lsa *); 88 static int ospf_decode_v2(const struct ospfhdr *, const u_char *); 89 90 static inline void 91 ospf_print_seqage(register u_int32_t seq, register time_t us) 92 { 93 register time_t sec = us % 60; 94 register time_t mins = (us / 60) % 60; 95 register time_t hour = us / 3600; 96 97 printf(" S %X age ", seq); 98 if (hour) 99 printf("%u:%02u:%02u", 100 (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec); 101 else if (mins) 102 printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec); 103 else 104 printf("%u", (u_int32_t) sec); 105 } 106 107 108 static inline void 109 ospf_print_bits(register const struct bits *bp, register u_char options) 110 { 111 register char sep = ' '; 112 113 do { 114 if (options & bp->bit) { 115 printf("%c%s", sep, bp->str); 116 sep = '/'; 117 } 118 } while ((++bp)->bit); 119 } 120 121 static void 122 ospf_print_ls_type(register u_int ls_type, 123 register const struct in_addr *ls_stateid, 124 register const struct in_addr *ls_router, register const char *fmt) 125 { 126 127 switch (ls_type) { 128 129 case LS_TYPE_ROUTER: 130 printf(" rtr %s ", ipaddr_string(ls_router)); 131 break; 132 133 case LS_TYPE_NETWORK: 134 printf(" net dr %s if %s", 135 ipaddr_string(ls_router), 136 ipaddr_string(ls_stateid)); 137 break; 138 139 case LS_TYPE_SUM_IP: 140 printf(" sum %s abr %s", 141 ipaddr_string(ls_stateid), 142 ipaddr_string(ls_router)); 143 break; 144 145 case LS_TYPE_SUM_ABR: 146 printf(" abr %s rtr %s", 147 ipaddr_string(ls_router), 148 ipaddr_string(ls_stateid)); 149 break; 150 151 case LS_TYPE_ASE: 152 printf(" ase %s asbr %s", 153 ipaddr_string(ls_stateid), 154 ipaddr_string(ls_router)); 155 break; 156 157 case LS_TYPE_GROUP: 158 printf(" group %s rtr %s", 159 ipaddr_string(ls_stateid), 160 ipaddr_string(ls_router)); 161 break; 162 163 default: 164 putchar(' '); 165 printf(fmt, ls_type); 166 break; 167 } 168 } 169 170 static int 171 ospf_print_lshdr(register const struct lsa_hdr *lshp) 172 { 173 174 TCHECK(lshp->ls_type); 175 printf(" {"); /* } (ctags) */ 176 177 TCHECK(lshp->ls_options); 178 ospf_print_bits(ospf_option_bits, lshp->ls_options); 179 TCHECK(lshp->ls_seq); 180 ospf_print_seqage(ntohl(lshp->ls_seq), ntohs(lshp->ls_age)); 181 ospf_print_ls_type(lshp->ls_type, &lshp->ls_stateid, &lshp->ls_router, 182 "ls_type %d"); 183 184 return (0); 185 trunc: 186 return (1); 187 } 188 189 190 /* 191 * Print a single link state advertisement. If truncated return 1, else 0. 192 */ 193 static int 194 ospf_print_lsa(register const struct lsa *lsap) 195 { 196 register const u_char *ls_end; 197 register const struct rlalink *rlp; 198 register const struct tos_metric *tosp; 199 register const struct in_addr *ap; 200 register const struct aslametric *almp; 201 register const struct mcla *mcp; 202 register const u_int32_t *lp; 203 register int j, k; 204 205 if (ospf_print_lshdr(&lsap->ls_hdr)) 206 return (1); 207 TCHECK(lsap->ls_hdr.ls_length); 208 ls_end = (u_char *)lsap + ntohs(lsap->ls_hdr.ls_length); 209 switch (lsap->ls_hdr.ls_type) { 210 211 case LS_TYPE_ROUTER: 212 TCHECK(lsap->lsa_un.un_rla.rla_flags); 213 ospf_print_bits(ospf_rla_flag_bits, 214 lsap->lsa_un.un_rla.rla_flags); 215 216 TCHECK(lsap->lsa_un.un_rla.rla_count); 217 j = ntohs(lsap->lsa_un.un_rla.rla_count); 218 TCHECK(lsap->lsa_un.un_rla.rla_link); 219 rlp = lsap->lsa_un.un_rla.rla_link; 220 while (j--) { 221 TCHECK(*rlp); 222 printf(" {"); /* } (ctags) */ 223 switch (rlp->link_type) { 224 225 case RLA_TYPE_VIRTUAL: 226 printf(" virt"); 227 /* Fall through */ 228 229 case RLA_TYPE_ROUTER: 230 printf(" nbrid %s if %s", 231 ipaddr_string(&rlp->link_id), 232 ipaddr_string(&rlp->link_data)); 233 break; 234 235 case RLA_TYPE_TRANSIT: 236 printf(" dr %s if %s", 237 ipaddr_string(&rlp->link_id), 238 ipaddr_string(&rlp->link_data)); 239 break; 240 241 case RLA_TYPE_STUB: 242 printf(" net %s mask %s", 243 ipaddr_string(&rlp->link_id), 244 ipaddr_string(&rlp->link_data)); 245 break; 246 247 default: 248 /* { (ctags) */ 249 printf(" ??RouterLinksType %d?? }", 250 rlp->link_type); 251 return (0); 252 } 253 printf(" tos 0 metric %d", ntohs(rlp->link_tos0metric)); 254 tosp = (struct tos_metric *) 255 ((sizeof rlp->link_tos0metric) + (u_char *) rlp); 256 for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) { 257 TCHECK(*tosp); 258 printf(" tos %d metric %d", 259 tosp->tos_type, 260 ntohs(tosp->tos_metric)); 261 } 262 /* { (ctags) */ 263 printf(" }"); 264 rlp = (struct rlalink *)((u_char *)(rlp + 1) + 265 ((rlp->link_toscount) * sizeof(*tosp))); 266 } 267 break; 268 269 case LS_TYPE_NETWORK: 270 TCHECK(lsap->lsa_un.un_nla.nla_mask); 271 printf(" mask %s rtrs", 272 ipaddr_string(&lsap->lsa_un.un_nla.nla_mask)); 273 ap = lsap->lsa_un.un_nla.nla_router; 274 while ((u_char *)ap < ls_end) { 275 TCHECK(*ap); 276 printf(" %s", ipaddr_string(ap)); 277 ++ap; 278 } 279 break; 280 281 case LS_TYPE_SUM_IP: 282 TCHECK(lsap->lsa_un.un_nla.nla_mask); 283 printf(" mask %s", 284 ipaddr_string(&lsap->lsa_un.un_sla.sla_mask)); 285 /* Fall through */ 286 287 case LS_TYPE_SUM_ABR: 288 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 289 lp = lsap->lsa_un.un_sla.sla_tosmetric; 290 while ((u_char *)lp < ls_end) { 291 register u_int32_t ul; 292 293 TCHECK(*lp); 294 ul = ntohl(*lp); 295 printf(" tos %d metric %d", 296 (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, 297 ul & SLA_MASK_METRIC); 298 ++lp; 299 } 300 break; 301 302 case LS_TYPE_ASE: 303 TCHECK(lsap->lsa_un.un_nla.nla_mask); 304 printf(" mask %s", 305 ipaddr_string(&lsap->lsa_un.un_asla.asla_mask)); 306 307 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 308 almp = lsap->lsa_un.un_asla.asla_metric; 309 while ((u_char *)almp < ls_end) { 310 register u_int32_t ul; 311 312 TCHECK(almp->asla_tosmetric); 313 ul = ntohl(almp->asla_tosmetric); 314 printf(" type %d tos %d metric %d", 315 (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1, 316 (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS, 317 (ul & ASLA_MASK_METRIC)); 318 TCHECK(almp->asla_forward); 319 if (almp->asla_forward.s_addr) { 320 printf(" forward %s", 321 ipaddr_string(&almp->asla_forward)); 322 } 323 TCHECK(almp->asla_tag); 324 if (almp->asla_tag.s_addr) { 325 printf(" tag %s", 326 ipaddr_string(&almp->asla_tag)); 327 } 328 ++almp; 329 } 330 break; 331 332 case LS_TYPE_GROUP: 333 /* Multicast extensions as of 23 July 1991 */ 334 mcp = lsap->lsa_un.un_mcla; 335 while ((u_char *)mcp < ls_end) { 336 TCHECK(mcp->mcla_vid); 337 switch (ntohl(mcp->mcla_vtype)) { 338 339 case MCLA_VERTEX_ROUTER: 340 printf(" rtr rtrid %s", 341 ipaddr_string(&mcp->mcla_vid)); 342 break; 343 344 case MCLA_VERTEX_NETWORK: 345 printf(" net dr %s", 346 ipaddr_string(&mcp->mcla_vid)); 347 break; 348 349 default: 350 printf(" ??VertexType %u??", 351 (u_int32_t)ntohl(mcp->mcla_vtype)); 352 break; 353 } 354 ++mcp; 355 } 356 } 357 358 /* { (ctags) */ 359 fputs(" }", stdout); 360 return (0); 361 trunc: 362 fputs(" }", stdout); 363 return (1); 364 } 365 366 static int 367 ospf_decode_v2(register const struct ospfhdr *op, 368 register const u_char *dataend) 369 { 370 register const struct in_addr *ap; 371 register const struct lsr *lsrp; 372 register const struct lsa_hdr *lshp; 373 register const struct lsa *lsap; 374 register char sep; 375 register int i; 376 377 switch (op->ospf_type) { 378 379 case OSPF_TYPE_UMD: 380 /* 381 * Rob Coltun's special monitoring packets; 382 * do nothing 383 */ 384 break; 385 386 case OSPF_TYPE_HELLO: 387 if (vflag) { 388 TCHECK(op->ospf_hello.hello_deadint); 389 ospf_print_bits(ospf_option_bits, 390 op->ospf_hello.hello_options); 391 printf(" mask %s int %d pri %d dead %u", 392 ipaddr_string(&op->ospf_hello.hello_mask), 393 ntohs(op->ospf_hello.hello_helloint), 394 op->ospf_hello.hello_priority, 395 (u_int32_t)ntohl(op->ospf_hello.hello_deadint)); 396 } 397 TCHECK(op->ospf_hello.hello_dr); 398 if (op->ospf_hello.hello_dr.s_addr != 0) 399 printf(" dr %s", 400 ipaddr_string(&op->ospf_hello.hello_dr)); 401 TCHECK(op->ospf_hello.hello_bdr); 402 if (op->ospf_hello.hello_bdr.s_addr != 0) 403 printf(" bdr %s", 404 ipaddr_string(&op->ospf_hello.hello_bdr)); 405 if (vflag) { 406 ap = op->ospf_hello.hello_neighbor; 407 if ((u_char *)ap < dataend) 408 printf(" nbrs"); 409 while ((u_char *)ap < dataend) { 410 TCHECK(*ap); 411 printf(" %s", ipaddr_string(ap)); 412 ++ap; 413 } 414 } 415 break; /* HELLO */ 416 417 case OSPF_TYPE_DB: 418 TCHECK(op->ospf_db.db_options); 419 ospf_print_bits(ospf_option_bits, op->ospf_db.db_options); 420 sep = ' '; 421 TCHECK(op->ospf_db.db_flags); 422 if (op->ospf_db.db_flags & OSPF_DB_INIT) { 423 printf("%cI", sep); 424 sep = '/'; 425 } 426 if (op->ospf_db.db_flags & OSPF_DB_MORE) { 427 printf("%cM", sep); 428 sep = '/'; 429 } 430 if (op->ospf_db.db_flags & OSPF_DB_MASTER) { 431 printf("%cMS", sep); 432 sep = '/'; 433 } 434 TCHECK(op->ospf_db.db_seq); 435 printf(" S %X", (u_int32_t)ntohl(op->ospf_db.db_seq)); 436 437 if (vflag) { 438 /* Print all the LS adv's */ 439 lshp = op->ospf_db.db_lshdr; 440 441 while (!ospf_print_lshdr(lshp)) { 442 /* { (ctags) */ 443 printf(" }"); 444 ++lshp; 445 } 446 } 447 break; 448 449 case OSPF_TYPE_LSR: 450 if (vflag) { 451 lsrp = op->ospf_lsr; 452 while ((u_char *)lsrp < dataend) { 453 TCHECK(*lsrp); 454 printf(" {"); /* } (ctags) */ 455 ospf_print_ls_type(ntohl(lsrp->ls_type), 456 &lsrp->ls_stateid, 457 &lsrp->ls_router, 458 "LinkStateType %d"); 459 /* { (ctags) */ 460 printf(" }"); 461 ++lsrp; 462 } 463 } 464 break; 465 466 case OSPF_TYPE_LSU: 467 if (vflag) { 468 lsap = op->ospf_lsu.lsu_lsa; 469 TCHECK(op->ospf_lsu.lsu_count); 470 i = ntohl(op->ospf_lsu.lsu_count); 471 while (i--) { 472 if (ospf_print_lsa(lsap)) 473 goto trunc; 474 lsap = (struct lsa *)((u_char *)lsap + 475 ntohs(lsap->ls_hdr.ls_length)); 476 } 477 } 478 break; 479 480 481 case OSPF_TYPE_LSA: 482 if (vflag) { 483 lshp = op->ospf_lsa.lsa_lshdr; 484 485 while (!ospf_print_lshdr(lshp)) { 486 /* { (ctags) */ 487 printf(" }"); 488 ++lshp; 489 } 490 } 491 break; 492 493 default: 494 printf("v2 type %d", op->ospf_type); 495 break; 496 } 497 return (0); 498 trunc: 499 return (1); 500 } 501 502 void 503 ospf_print(register const u_char *bp, register u_int length, 504 register const u_char *bp2) 505 { 506 register const struct ospfhdr *op; 507 register const struct ip *ip; 508 register const u_char *dataend; 509 register const char *cp; 510 511 op = (struct ospfhdr *)bp; 512 ip = (struct ip *)bp2; 513 514 /* XXX Before we do anything else, strip off the MD5 trailer */ 515 TCHECK(op->ospf_authtype); 516 if (ntohs(op->ospf_authtype) == OSPF_AUTH_MD5) { 517 length -= OSPF_AUTH_MD5_LEN; 518 snapend -= OSPF_AUTH_MD5_LEN; 519 } 520 521 /* If the type is valid translate it, or just print the type */ 522 /* value. If it's not valid, say so and return */ 523 TCHECK(op->ospf_type); 524 cp = tok2str(type2str, "type%d", op->ospf_type); 525 printf("OSPFv%d-%s %d:", op->ospf_version, cp, length); 526 if (*cp == 't') 527 return; 528 529 TCHECK(op->ospf_len); 530 if (length != ntohs(op->ospf_len)) { 531 printf(" [len %d]", ntohs(op->ospf_len)); 532 return; 533 } 534 dataend = bp + length; 535 536 /* Print the routerid if it is not the same as the source */ 537 TCHECK(op->ospf_routerid); 538 if (ip->ip_src.s_addr != op->ospf_routerid.s_addr) 539 printf(" rtrid %s", ipaddr_string(&op->ospf_routerid)); 540 541 TCHECK(op->ospf_areaid); 542 if (op->ospf_areaid.s_addr != 0) 543 printf(" area %s", ipaddr_string(&op->ospf_areaid)); 544 else 545 printf(" backbone"); 546 547 if (vflag) { 548 /* Print authentication data (should we really do this?) */ 549 TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); 550 switch (ntohs(op->ospf_authtype)) { 551 552 case OSPF_AUTH_NONE: 553 break; 554 555 case OSPF_AUTH_SIMPLE: 556 printf(" auth \""); 557 (void)fn_printn(op->ospf_authdata, 558 sizeof(op->ospf_authdata), NULL); 559 printf("\""); 560 break; 561 562 case OSPF_AUTH_MD5: 563 printf(" auth MD5"); 564 break; 565 566 default: 567 printf(" ??authtype-%d??", ntohs(op->ospf_authtype)); 568 return; 569 } 570 } 571 /* Do rest according to version. */ 572 switch (op->ospf_version) { 573 574 case 2: 575 /* ospf version 2 */ 576 if (ospf_decode_v2(op, dataend)) 577 goto trunc; 578 break; 579 580 default: 581 printf(" ospf [version %d]", op->ospf_version); 582 break; 583 } /* end switch on version */ 584 585 return; 586 trunc: 587 fputs(tstr, stdout); 588 } 589