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