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