1 /* 2 * Copyright (c) 1992, 1993, 1994, 1995, 1996 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.23 96/12/10 23:15: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 register struct rlalink *rln = 219 (struct rlalink *)((u_char *)(rlp + 1) + 220 ((rlp->link_toscount) * sizeof(*tosp))); 221 222 TCHECK(*rln); 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 = rln; 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 printf(" nbrs"); 407 ap = op->ospf_hello.hello_neighbor; 408 while ((u_char *)ap < dataend) { 409 TCHECK(*ap); 410 printf(" %s", ipaddr_string(ap)); 411 ++ap; 412 } 413 } 414 break; /* HELLO */ 415 416 case OSPF_TYPE_DB: 417 TCHECK(op->ospf_db.db_options); 418 ospf_print_bits(ospf_option_bits, op->ospf_db.db_options); 419 sep = ' '; 420 TCHECK(op->ospf_db.db_flags); 421 if (op->ospf_db.db_flags & OSPF_DB_INIT) { 422 printf("%cI", sep); 423 sep = '/'; 424 } 425 if (op->ospf_db.db_flags & OSPF_DB_MORE) { 426 printf("%cM", sep); 427 sep = '/'; 428 } 429 if (op->ospf_db.db_flags & OSPF_DB_MASTER) { 430 printf("%cMS", sep); 431 sep = '/'; 432 } 433 TCHECK(op->ospf_db.db_seq); 434 printf(" S %X", (u_int32_t)ntohl(op->ospf_db.db_seq)); 435 436 if (vflag) { 437 /* Print all the LS adv's */ 438 lshp = op->ospf_db.db_lshdr; 439 440 while (!ospf_print_lshdr(lshp)) { 441 /* { (ctags) */ 442 printf(" }"); 443 ++lshp; 444 } 445 } 446 break; 447 448 case OSPF_TYPE_LSR: 449 if (vflag) { 450 lsrp = op->ospf_lsr; 451 while ((u_char *)lsrp < dataend) { 452 TCHECK(*lsrp); 453 printf(" {"); /* } (ctags) */ 454 ospf_print_ls_type(ntohl(lsrp->ls_type), 455 &lsrp->ls_stateid, 456 &lsrp->ls_router, 457 "LinkStateType %d"); 458 /* { (ctags) */ 459 printf(" }"); 460 ++lsrp; 461 } 462 } 463 break; 464 465 case OSPF_TYPE_LSU: 466 if (vflag) { 467 lsap = op->ospf_lsu.lsu_lsa; 468 TCHECK(op->ospf_lsu.lsu_count); 469 i = ntohl(op->ospf_lsu.lsu_count); 470 while (i--) { 471 if (ospf_print_lsa(lsap)) 472 goto trunc; 473 lsap = (struct lsa *)((u_char *)lsap + 474 ntohs(lsap->ls_hdr.ls_length)); 475 } 476 } 477 break; 478 479 480 case OSPF_TYPE_LSA: 481 if (vflag) { 482 lshp = op->ospf_lsa.lsa_lshdr; 483 484 while (!ospf_print_lshdr(lshp)) { 485 /* { (ctags) */ 486 printf(" }"); 487 ++lshp; 488 } 489 } 490 break; 491 492 default: 493 printf("v2 type %d", op->ospf_type); 494 break; 495 } 496 return (0); 497 trunc: 498 return (1); 499 } 500 501 void 502 ospf_print(register const u_char *bp, register u_int length, 503 register const u_char *bp2) 504 { 505 register const struct ospfhdr *op; 506 register const struct ip *ip; 507 register const u_char *dataend; 508 register const char *cp; 509 510 op = (struct ospfhdr *)bp; 511 ip = (struct ip *)bp2; 512 /* Print the source and destination address */ 513 (void) printf("%s > %s:", 514 ipaddr_string(&ip->ip_src), 515 ipaddr_string(&ip->ip_dst)); 516 517 /* If the type is valid translate it, or just print the type */ 518 /* value. If it's not valid, say so and return */ 519 TCHECK(op->ospf_type); 520 cp = tok2str(type2str, "type%d", op->ospf_type); 521 printf(" OSPFv%d-%s %d:", op->ospf_version, cp, length); 522 if (*cp == 't') 523 return; 524 525 TCHECK(op->ospf_len); 526 if (length != ntohs(op->ospf_len)) { 527 printf(" [len %d]", ntohs(op->ospf_len)); 528 return; 529 } 530 dataend = bp + length; 531 532 /* Print the routerid if it is not the same as the source */ 533 TCHECK(op->ospf_routerid); 534 if (ip->ip_src.s_addr != op->ospf_routerid.s_addr) 535 printf(" rtrid %s", ipaddr_string(&op->ospf_routerid)); 536 537 TCHECK(op->ospf_areaid); 538 if (op->ospf_areaid.s_addr != 0) 539 printf(" area %s", ipaddr_string(&op->ospf_areaid)); 540 else 541 printf(" backbone"); 542 543 if (vflag) { 544 /* Print authentication data (should we really do this?) */ 545 TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); 546 switch (ntohs(op->ospf_authtype)) { 547 548 case OSPF_AUTH_NONE: 549 break; 550 551 case OSPF_AUTH_SIMPLE: 552 printf(" auth \""); 553 (void)fn_printn(op->ospf_authdata, 554 sizeof(op->ospf_authdata), NULL); 555 printf("\""); 556 break; 557 558 default: 559 printf(" ??authtype-%d??", ntohs(op->ospf_authtype)); 560 return; 561 } 562 } 563 /* Do rest according to version. */ 564 switch (op->ospf_version) { 565 566 case 2: 567 /* ospf version 2 */ 568 if (ospf_decode_v2(op, dataend)) 569 goto trunc; 570 break; 571 572 default: 573 printf(" ospf [version %d]", op->ospf_version); 574 break; 575 } /* end switch on version */ 576 577 return; 578 trunc: 579 fputs(tstr, stdout); 580 } 581