1 /* $OpenBSD: print-ospf6.c,v 1.5 2009/10/27 23:59:55 deraadt Exp $ */ 2 3 4 /* 5 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that: (1) source code distributions 10 * retain the above copyright notice and this paragraph in its entirety, (2) 11 * distributions including binary code include the above copyright notice and 12 * this paragraph in its entirety in the documentation or other materials 13 * provided with the distribution, and (3) all advertising materials mentioning 14 * features or use of this software display the following acknowledgement: 15 * ``This product includes software developed by the University of California, 16 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 17 * the University nor the names of its contributors may be used to endorse 18 * or promote products derived from this software without specific prior 19 * written permission. 20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 21 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 23 * 24 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 25 */ 26 27 #ifdef INET6 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 #include <string.h> 41 42 #include "interface.h" 43 #include "addrtoname.h" 44 45 #include "ospf6.h" 46 47 struct bits { 48 u_int32_t bit; 49 const char *str; 50 }; 51 52 static const struct bits ospf6_option_bits[] = { 53 { OSPF6_OPTION_V6, "V6" }, 54 { OSPF6_OPTION_E, "E" }, 55 { OSPF6_OPTION_MC, "MC" }, 56 { OSPF6_OPTION_N, "N" }, 57 { OSPF6_OPTION_R, "R" }, 58 { OSPF6_OPTION_DC, "DC" }, 59 { 0, NULL } 60 }; 61 62 static const struct bits ospf6_rla_flag_bits[] = { 63 { RLA_FLAG_B, "B" }, 64 { RLA_FLAG_E, "E" }, 65 { RLA_FLAG_V, "V" }, 66 { RLA_FLAG_W, "W" }, 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 ospf6_print_seqage(u_int32_t, time_t); 84 static inline void ospf6_print_bits(const struct bits *, u_char); 85 static void ospf6_print_ls_type(u_int, const rtrid_t *, 86 const rtrid_t *, const char *); 87 static int ospf6_print_lshdr(const struct lsa_hdr *); 88 static int ospf6_print_lsa(const struct lsa *); 89 static int ospf6_decode_v3(const struct ospf6hdr *, const u_char *); 90 91 static inline void 92 ospf6_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 ospf6_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 ospf6_print_ls_type(register u_int ls_type, 124 register const rtrid_t *ls_stateid, 125 register const rtrid_t *ls_router, register const char *fmt) 126 { 127 char *scope; 128 129 switch (ls_type & LS_SCOPE_MASK) { 130 case LS_SCOPE_LINKLOCAL: 131 scope = "linklocal-"; 132 break; 133 case LS_SCOPE_AREA: 134 scope = "area-"; 135 break; 136 case LS_SCOPE_AS: 137 scope = "AS-"; 138 break; 139 default: 140 scope = ""; 141 break; 142 } 143 144 switch (ls_type & LS_TYPE_MASK) { 145 case LS_TYPE_ROUTER: 146 printf(" %srtr %s", scope, ipaddr_string(ls_router)); 147 break; 148 149 case LS_TYPE_NETWORK: 150 printf(" %snet dr %s if %s", scope, 151 ipaddr_string(ls_router), 152 ipaddr_string(ls_stateid)); 153 break; 154 155 case LS_TYPE_INTER_AP: 156 printf(" %sinter-area-prefix %s abr %s", scope, 157 ipaddr_string(ls_stateid), 158 ipaddr_string(ls_router)); 159 break; 160 161 case LS_TYPE_INTER_AR: 162 printf(" %sinter-area-router %s rtr %s", scope, 163 ipaddr_string(ls_router), 164 ipaddr_string(ls_stateid)); 165 break; 166 167 case LS_TYPE_ASE: 168 printf(" %sase %s asbr %s", scope, 169 ipaddr_string(ls_stateid), 170 ipaddr_string(ls_router)); 171 break; 172 173 case LS_TYPE_GROUP: 174 printf(" %sgroup %s rtr %s", scope, 175 ipaddr_string(ls_stateid), 176 ipaddr_string(ls_router)); 177 break; 178 179 case LS_TYPE_TYPE7: 180 printf(" %stype7 %s rtr %s", scope, 181 ipaddr_string(ls_stateid), 182 ipaddr_string(ls_router)); 183 break; 184 185 case LS_TYPE_LINK: 186 printf(" %slink %s rtr %s", scope, 187 ipaddr_string(ls_stateid), 188 ipaddr_string(ls_router)); 189 break; 190 191 case LS_TYPE_INTRA_AP: 192 printf(" %sintra-area-prefix %s rtr %s", scope, 193 ipaddr_string(ls_stateid), 194 ipaddr_string(ls_router)); 195 break; 196 197 default: 198 printf(" %s", scope); 199 printf(fmt, ls_type); 200 break; 201 } 202 203 } 204 205 static int 206 ospf6_print_lshdr(register const struct lsa_hdr *lshp) 207 { 208 209 TCHECK(lshp->ls_type); 210 printf(" {"); /* } (ctags) */ 211 212 TCHECK(lshp->ls_seq); 213 ospf6_print_seqage(ntohl(lshp->ls_seq), ntohs(lshp->ls_age)); 214 ospf6_print_ls_type(ntohs(lshp->ls_type), &lshp->ls_stateid, 215 &lshp->ls_router, "ls_type %d"); 216 217 return (0); 218 trunc: 219 return (1); 220 } 221 222 static int 223 ospf6_print_lsaprefix(register const struct lsa_prefix *lsapp) 224 { 225 int k; 226 struct in6_addr prefix; 227 228 TCHECK(*lsapp); 229 k = (lsapp->lsa_p_len + 31) / 32; 230 if (k * 4 > sizeof(struct in6_addr)) { 231 printf("??prefixlen %d??", lsapp->lsa_p_len); 232 goto trunc; 233 } 234 memset(&prefix, 0, sizeof(prefix)); 235 memcpy(&prefix, lsapp->lsa_p_prefix, k * 4); 236 printf(" %s/%d", ip6addr_string(&prefix), 237 lsapp->lsa_p_len); 238 if (lsapp->lsa_p_opt) 239 printf("(opt=%x)", lsapp->lsa_p_opt); 240 return sizeof(*lsapp) - 4 + k * 4; 241 242 trunc: 243 return -1; 244 } 245 246 247 /* 248 * Print a single link state advertisement. If truncated return 1, else 0. 249 */ 250 static int 251 ospf6_print_lsa(register const struct lsa *lsap) 252 { 253 register const u_char *ls_end; 254 register const struct rlalink *rlp; 255 #if 0 256 register const struct tos_metric *tosp; 257 #endif 258 register const rtrid_t *ap; 259 #if 0 260 register const struct aslametric *almp; 261 register const struct mcla *mcp; 262 #endif 263 register const struct llsa *llsap; 264 register const struct lsa_prefix *lsapp; 265 #if 0 266 register const u_int32_t *lp; 267 #endif 268 register int j, k; 269 270 if (ospf6_print_lshdr(&lsap->ls_hdr)) 271 return (1); 272 TCHECK(lsap->ls_hdr.ls_length); 273 ls_end = (u_char *)lsap + ntohs(lsap->ls_hdr.ls_length); 274 switch (ntohs(lsap->ls_hdr.ls_type)) { 275 case LS_TYPE_ROUTER | LS_SCOPE_AREA: 276 TCHECK(lsap->lsa_un.un_rla.rla_flags); 277 ospf6_print_bits(ospf6_rla_flag_bits, 278 lsap->lsa_un.un_rla.rla_flags); 279 TCHECK(lsap->lsa_un.un_rla.rla_options); 280 ospf6_print_bits(ospf6_option_bits, 281 ntohl(lsap->lsa_un.un_rla.rla_options)); 282 283 TCHECK(lsap->lsa_un.un_rla.rla_link); 284 rlp = lsap->lsa_un.un_rla.rla_link; 285 while (rlp + sizeof(*rlp) <= (struct rlalink *)ls_end) { 286 TCHECK(*rlp); 287 printf(" {"); /* } (ctags) */ 288 switch (rlp->link_type) { 289 290 case RLA_TYPE_VIRTUAL: 291 printf(" virt"); 292 /* FALLTHROUGH */ 293 294 case RLA_TYPE_ROUTER: 295 printf(" nbrid %s nbrif %s if %s", 296 ipaddr_string(&rlp->link_nrtid), 297 ipaddr_string(&rlp->link_nifid), 298 ipaddr_string(&rlp->link_ifid)); 299 break; 300 301 case RLA_TYPE_TRANSIT: 302 printf(" dr %s drif %s if %s", 303 ipaddr_string(&rlp->link_nrtid), 304 ipaddr_string(&rlp->link_nifid), 305 ipaddr_string(&rlp->link_ifid)); 306 break; 307 308 default: 309 /* { (ctags) */ 310 printf(" ??RouterLinksType 0x%02x?? }", 311 rlp->link_type); 312 return (0); 313 } 314 printf(" metric %d", ntohs(rlp->link_metric)); 315 /* { (ctags) */ 316 printf(" }"); 317 rlp++; 318 } 319 break; 320 321 case LS_TYPE_NETWORK | LS_SCOPE_AREA: 322 TCHECK(lsap->lsa_un.un_nla.nla_options); 323 ospf6_print_bits(ospf6_option_bits, 324 ntohl(lsap->lsa_un.un_nla.nla_options)); 325 printf(" rtrs"); 326 ap = lsap->lsa_un.un_nla.nla_router; 327 while ((u_char *)ap < ls_end) { 328 TCHECK(*ap); 329 printf(" %s", ipaddr_string(ap)); 330 ++ap; 331 } 332 break; 333 334 case LS_TYPE_INTER_AP | LS_SCOPE_AREA: 335 TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); 336 printf(" metric %u", 337 (u_int32_t)ntohl(lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC); 338 lsapp = lsap->lsa_un.un_inter_ap.inter_ap_prefix; 339 while (lsapp + sizeof(lsapp) <= (struct lsa_prefix *)ls_end) { 340 k = ospf6_print_lsaprefix(lsapp); 341 if (k < 0) 342 goto trunc; 343 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k); 344 } 345 break; 346 347 #if 0 348 case LS_TYPE_SUM_ABR: 349 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 350 lp = lsap->lsa_un.un_sla.sla_tosmetric; 351 while ((u_char *)lp < ls_end) { 352 register u_int32_t ul; 353 354 TCHECK(*lp); 355 ul = ntohl(*lp); 356 printf(" tos %d metric %d", 357 (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, 358 ul & SLA_MASK_METRIC); 359 ++lp; 360 } 361 break; 362 363 case LS_TYPE_ASE: 364 TCHECK(lsap->lsa_un.un_nla.nla_mask); 365 printf(" mask %s", 366 ipaddr_string(&lsap->lsa_un.un_asla.asla_mask)); 367 368 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 369 almp = lsap->lsa_un.un_asla.asla_metric; 370 while ((u_char *)almp < ls_end) { 371 register u_int32_t ul; 372 373 TCHECK(almp->asla_tosmetric); 374 ul = ntohl(almp->asla_tosmetric); 375 printf(" type %d tos %d metric %d", 376 (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1, 377 (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS, 378 (ul & ASLA_MASK_METRIC)); 379 TCHECK(almp->asla_forward); 380 if (almp->asla_forward.s_addr) { 381 printf(" forward %s", 382 ipaddr_string(&almp->asla_forward)); 383 } 384 TCHECK(almp->asla_tag); 385 if (almp->asla_tag.s_addr) { 386 printf(" tag %s", 387 ipaddr_string(&almp->asla_tag)); 388 } 389 ++almp; 390 } 391 break; 392 393 case LS_TYPE_GROUP: 394 /* Multicast extensions as of 23 July 1991 */ 395 mcp = lsap->lsa_un.un_mcla; 396 while ((u_char *)mcp < ls_end) { 397 TCHECK(mcp->mcla_vid); 398 switch (ntohl(mcp->mcla_vtype)) { 399 400 case MCLA_VERTEX_ROUTER: 401 printf(" rtr rtrid %s", 402 ipaddr_string(&mcp->mcla_vid)); 403 break; 404 405 case MCLA_VERTEX_NETWORK: 406 printf(" net dr %s", 407 ipaddr_string(&mcp->mcla_vid)); 408 break; 409 410 default: 411 printf(" ??VertexType %u??", 412 (u_int32_t)ntohl(mcp->mcla_vtype)); 413 break; 414 } 415 ++mcp; 416 } 417 #endif 418 419 case LS_TYPE_LINK: 420 /* Link LSA */ 421 llsap = &lsap->lsa_un.un_llsa; 422 TCHECK(llsap->llsa_options); 423 ospf6_print_bits(ospf6_option_bits, ntohl(llsap->llsa_options)); 424 TCHECK(llsap->llsa_nprefix); 425 printf(" pri %d lladdr %s npref %d", llsap->llsa_priority, 426 ip6addr_string(&llsap->llsa_lladdr), 427 (u_int32_t)ntohl(llsap->llsa_nprefix)); 428 lsapp = llsap->llsa_prefix; 429 for (j = 0; j < ntohl(llsap->llsa_nprefix); j++) { 430 k = ospf6_print_lsaprefix(lsapp); 431 if (k < 0) 432 goto trunc; 433 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k); 434 } 435 break; 436 437 case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: 438 /* Intra-Area-Prefix LSA */ 439 TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); 440 ospf6_print_ls_type( 441 ntohs(lsap->lsa_un.un_intra_ap.intra_ap_lstype), 442 &lsap->lsa_un.un_intra_ap.intra_ap_lsid, 443 &lsap->lsa_un.un_intra_ap.intra_ap_rtid, 444 "LinkStateType %d"); 445 TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 446 printf(" npref %d", 447 ntohs(lsap->lsa_un.un_intra_ap.intra_ap_nprefix)); 448 449 lsapp = lsap->lsa_un.un_intra_ap.intra_ap_prefix; 450 for (j = 0; 451 j < ntohs(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 452 j++) { 453 k = ospf6_print_lsaprefix(lsapp); 454 if (k < 0) 455 goto trunc; 456 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k); 457 } 458 break; 459 460 default: 461 printf(" ??LinkStateType 0x%04x??", 462 ntohs(lsap->ls_hdr.ls_type)); 463 } 464 465 /* { (ctags) */ 466 fputs(" }", stdout); 467 return (0); 468 trunc: 469 fputs(" }", stdout); 470 return (1); 471 } 472 473 static int 474 ospf6_decode_v3(register const struct ospf6hdr *op, 475 register const u_char *dataend) 476 { 477 register const rtrid_t *ap; 478 register const struct lsr *lsrp; 479 register const struct lsa_hdr *lshp; 480 register const struct lsa *lsap; 481 register char sep; 482 register int i; 483 484 switch (op->ospf6_type) { 485 486 case OSPF_TYPE_UMD: 487 /* 488 * Rob Coltun's special monitoring packets; 489 * do nothing 490 */ 491 break; 492 493 case OSPF_TYPE_HELLO: 494 if (vflag) { 495 TCHECK(op->ospf6_hello.hello_deadint); 496 ospf6_print_bits(ospf6_option_bits, 497 ntohl(op->ospf6_hello.hello_options)); 498 printf(" ifid %s pri %d int %d dead %u", 499 ipaddr_string(&op->ospf6_hello.hello_ifid), 500 op->ospf6_hello.hello_priority, 501 ntohs(op->ospf6_hello.hello_helloint), 502 ntohs(op->ospf6_hello.hello_deadint)); 503 } 504 TCHECK(op->ospf6_hello.hello_dr); 505 if (op->ospf6_hello.hello_dr != 0) 506 printf(" dr %s", 507 ipaddr_string(&op->ospf6_hello.hello_dr)); 508 TCHECK(op->ospf6_hello.hello_bdr); 509 if (op->ospf6_hello.hello_bdr != 0) 510 printf(" bdr %s", 511 ipaddr_string(&op->ospf6_hello.hello_bdr)); 512 if (vflag) { 513 printf(" nbrs"); 514 ap = op->ospf6_hello.hello_neighbor; 515 while ((u_char *)ap < dataend) { 516 TCHECK(*ap); 517 printf(" %s", ipaddr_string(ap)); 518 ++ap; 519 } 520 } 521 break; /* HELLO */ 522 523 case OSPF_TYPE_DB: 524 TCHECK(op->ospf6_db.db_options); 525 ospf6_print_bits(ospf6_option_bits, 526 ntohl(op->ospf6_db.db_options)); 527 sep = ' '; 528 TCHECK(op->ospf6_db.db_flags); 529 if (op->ospf6_db.db_flags & OSPF6_DB_INIT) { 530 printf("%cI", sep); 531 sep = '/'; 532 } 533 if (op->ospf6_db.db_flags & OSPF6_DB_MORE) { 534 printf("%cM", sep); 535 sep = '/'; 536 } 537 if (op->ospf6_db.db_flags & OSPF6_DB_MASTER) { 538 printf("%cMS", sep); 539 sep = '/'; 540 } 541 TCHECK(op->ospf6_db.db_seq); 542 printf(" mtu %u S %X", ntohs(op->ospf6_db.db_mtu), 543 (u_int32_t)ntohl(op->ospf6_db.db_seq)); 544 545 if (vflag) { 546 /* Print all the LS adv's */ 547 lshp = op->ospf6_db.db_lshdr; 548 549 while (!ospf6_print_lshdr(lshp)) { 550 /* { (ctags) */ 551 printf(" }"); 552 ++lshp; 553 } 554 } 555 break; 556 557 case OSPF_TYPE_LSR: 558 if (vflag) { 559 lsrp = op->ospf6_lsr; 560 while ((u_char *)lsrp < dataend) { 561 TCHECK(*lsrp); 562 printf(" {"); /* } (ctags) */ 563 ospf6_print_ls_type(ntohs(lsrp->ls_type), 564 &lsrp->ls_stateid, 565 &lsrp->ls_router, 566 "LinkStateType %d"); 567 /* { (ctags) */ 568 printf(" }"); 569 ++lsrp; 570 } 571 } 572 break; 573 574 case OSPF_TYPE_LSU: 575 if (vflag) { 576 lsap = op->ospf6_lsu.lsu_lsa; 577 TCHECK(op->ospf6_lsu.lsu_count); 578 i = ntohl(op->ospf6_lsu.lsu_count); 579 while (i--) { 580 if (ospf6_print_lsa(lsap)) 581 goto trunc; 582 lsap = (struct lsa *)((u_char *)lsap + 583 ntohs(lsap->ls_hdr.ls_length)); 584 } 585 } 586 break; 587 588 589 case OSPF_TYPE_LSA: 590 if (vflag) { 591 lshp = op->ospf6_lsa.lsa_lshdr; 592 593 while (!ospf6_print_lshdr(lshp)) { 594 /* { (ctags) */ 595 printf(" }"); 596 ++lshp; 597 } 598 } 599 break; 600 601 default: 602 printf("v3 type %d", op->ospf6_type); 603 break; 604 } 605 return (0); 606 trunc: 607 return (1); 608 } 609 610 void 611 ospf6_print(register const u_char *bp, register u_int length) 612 { 613 register const struct ospf6hdr *op; 614 register const u_char *dataend; 615 register const char *cp; 616 617 op = (struct ospf6hdr *)bp; 618 619 /* If the type is valid translate it, or just print the type */ 620 /* value. If it's not valid, say so and return */ 621 TCHECK(op->ospf6_type); 622 cp = tok2str(type2str, "type%d", op->ospf6_type); 623 printf(" OSPFv%d-%s %d:", op->ospf6_version, cp, length); 624 if (*cp == 't') 625 return; 626 627 TCHECK(op->ospf6_len); 628 if (length != ntohs(op->ospf6_len)) { 629 printf(" [len %d]", ntohs(op->ospf6_len)); 630 return; 631 } 632 dataend = bp + length; 633 634 /* Print the routerid if it is not the same as the source */ 635 TCHECK(op->ospf6_routerid); 636 printf(" rtrid %s", ipaddr_string(&op->ospf6_routerid)); 637 638 TCHECK(op->ospf6_areaid); 639 if (op->ospf6_areaid != 0) 640 printf(" area %s", ipaddr_string(&op->ospf6_areaid)); 641 else 642 printf(" backbone"); 643 TCHECK(op->ospf6_instanceid); 644 if (op->ospf6_instanceid) 645 printf(" instance %u", op->ospf6_instanceid); 646 647 /* Do rest according to version. */ 648 switch (op->ospf6_version) { 649 650 case 3: 651 /* ospf version 3 */ 652 if (ospf6_decode_v3(op, dataend)) 653 goto trunc; 654 break; 655 656 default: 657 printf(" ospf [version %d]", op->ospf6_version); 658 break; 659 } /* end switch on version */ 660 661 return; 662 trunc: 663 fputs(tstr, stdout); 664 } 665 666 #endif /* INET6 */ 667