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