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