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