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