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