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