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