print-ospf6.c revision 1.6
1/* 2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 22 */ 23 24#include <sys/cdefs.h> 25#ifndef lint 26__RCSID("$NetBSD: print-ospf6.c,v 1.6 2017/01/24 23:29:14 christos Exp $"); 27#endif 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include <netdissect-stdinc.h> 34 35#include <string.h> 36 37#include "netdissect.h" 38#include "addrtoname.h" 39#include "extract.h" 40 41#include "ospf.h" 42 43#define OSPF_TYPE_HELLO 1 /* Hello */ 44#define OSPF_TYPE_DD 2 /* Database Description */ 45#define OSPF_TYPE_LS_REQ 3 /* Link State Request */ 46#define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */ 47#define OSPF_TYPE_LS_ACK 5 /* Link State Ack */ 48 49/* Options *_options */ 50#define OSPF6_OPTION_V6 0x01 /* V6 bit: A bit for peeping tom */ 51#define OSPF6_OPTION_E 0x02 /* E bit: External routes advertised */ 52#define OSPF6_OPTION_MC 0x04 /* MC bit: Multicast capable */ 53#define OSPF6_OPTION_N 0x08 /* N bit: For type-7 LSA */ 54#define OSPF6_OPTION_R 0x10 /* R bit: Router bit */ 55#define OSPF6_OPTION_DC 0x20 /* DC bit: Demand circuits */ 56/* The field is actually 24-bit (RFC5340 Section A.2). */ 57#define OSPF6_OPTION_AF 0x0100 /* AF bit: Multiple address families */ 58#define OSPF6_OPTION_L 0x0200 /* L bit: Link-local signaling (LLS) */ 59#define OSPF6_OPTION_AT 0x0400 /* AT bit: Authentication trailer */ 60 61 62/* db_flags */ 63#define OSPF6_DB_INIT 0x04 /* */ 64#define OSPF6_DB_MORE 0x02 65#define OSPF6_DB_MASTER 0x01 66#define OSPF6_DB_M6 0x10 /* IPv6 MTU */ 67 68/* ls_type */ 69#define LS_TYPE_ROUTER 1 /* router link */ 70#define LS_TYPE_NETWORK 2 /* network link */ 71#define LS_TYPE_INTER_AP 3 /* Inter-Area-Prefix */ 72#define LS_TYPE_INTER_AR 4 /* Inter-Area-Router */ 73#define LS_TYPE_ASE 5 /* ASE */ 74#define LS_TYPE_GROUP 6 /* Group membership */ 75#define LS_TYPE_NSSA 7 /* NSSA */ 76#define LS_TYPE_LINK 8 /* Link LSA */ 77#define LS_TYPE_INTRA_AP 9 /* Intra-Area-Prefix */ 78#define LS_TYPE_INTRA_ATE 10 /* Intra-Area-TE */ 79#define LS_TYPE_GRACE 11 /* Grace LSA */ 80#define LS_TYPE_RI 12 /* Router information */ 81#define LS_TYPE_INTER_ASTE 13 /* Inter-AS-TE */ 82#define LS_TYPE_L1VPN 14 /* L1VPN */ 83#define LS_TYPE_MASK 0x1fff 84 85#define LS_SCOPE_LINKLOCAL 0x0000 86#define LS_SCOPE_AREA 0x2000 87#define LS_SCOPE_AS 0x4000 88#define LS_SCOPE_MASK 0x6000 89#define LS_SCOPE_U 0x8000 90 91/* rla_link.link_type */ 92#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */ 93#define RLA_TYPE_TRANSIT 2 /* connection to transit network */ 94#define RLA_TYPE_VIRTUAL 4 /* virtual link */ 95 96/* rla_flags */ 97#define RLA_FLAG_B 0x01 98#define RLA_FLAG_E 0x02 99#define RLA_FLAG_V 0x04 100#define RLA_FLAG_W 0x08 101#define RLA_FLAG_N 0x10 102 103/* lsa_prefix options */ 104#define LSA_PREFIX_OPT_NU 0x01 105#define LSA_PREFIX_OPT_LA 0x02 106#define LSA_PREFIX_OPT_MC 0x04 107#define LSA_PREFIX_OPT_P 0x08 108#define LSA_PREFIX_OPT_DN 0x10 109 110/* sla_tosmetric breakdown */ 111#define SLA_MASK_TOS 0x7f000000 112#define SLA_MASK_METRIC 0x00ffffff 113#define SLA_SHIFT_TOS 24 114 115/* asla_metric */ 116#define ASLA_FLAG_FWDADDR 0x02000000 117#define ASLA_FLAG_ROUTETAG 0x01000000 118#define ASLA_MASK_METRIC 0x00ffffff 119 120/* RFC6506 Section 4.1 */ 121#define OSPF6_AT_HDRLEN 16U 122#define OSPF6_AUTH_TYPE_HMAC 0x0001 123 124typedef uint32_t rtrid_t; 125 126/* link state advertisement header */ 127struct lsa6_hdr { 128 uint16_t ls_age; 129 uint16_t ls_type; 130 rtrid_t ls_stateid; 131 rtrid_t ls_router; 132 uint32_t ls_seq; 133 uint16_t ls_chksum; 134 uint16_t ls_length; 135}; 136 137/* Length of an IPv6 address, in bytes. */ 138#define IPV6_ADDR_LEN_BYTES (128/8) 139 140struct lsa6_prefix { 141 uint8_t lsa_p_len; 142 uint8_t lsa_p_opt; 143 uint16_t lsa_p_metric; 144 uint8_t lsa_p_prefix[IPV6_ADDR_LEN_BYTES]; /* maximum length */ 145}; 146 147/* link state advertisement */ 148struct lsa6 { 149 struct lsa6_hdr ls_hdr; 150 151 /* Link state types */ 152 union { 153 /* Router links advertisements */ 154 struct { 155 union { 156 uint8_t flg; 157 uint32_t opt; 158 } rla_flgandopt; 159#define rla_flags rla_flgandopt.flg 160#define rla_options rla_flgandopt.opt 161 struct rlalink6 { 162 uint8_t link_type; 163 uint8_t link_zero[1]; 164 uint16_t link_metric; 165 uint32_t link_ifid; 166 uint32_t link_nifid; 167 rtrid_t link_nrtid; 168 } rla_link[1]; /* may repeat */ 169 } un_rla; 170 171 /* Network links advertisements */ 172 struct { 173 uint32_t nla_options; 174 rtrid_t nla_router[1]; /* may repeat */ 175 } un_nla; 176 177 /* Inter Area Prefix LSA */ 178 struct { 179 uint32_t inter_ap_metric; 180 struct lsa6_prefix inter_ap_prefix[1]; 181 } un_inter_ap; 182 183 /* AS external links advertisements */ 184 struct { 185 uint32_t asla_metric; 186 struct lsa6_prefix asla_prefix[1]; 187 /* some optional fields follow */ 188 } un_asla; 189 190#if 0 191 /* Summary links advertisements */ 192 struct { 193 struct in_addr sla_mask; 194 uint32_t sla_tosmetric[1]; /* may repeat */ 195 } un_sla; 196 197 /* Multicast group membership */ 198 struct mcla { 199 uint32_t mcla_vtype; 200 struct in_addr mcla_vid; 201 } un_mcla[1]; 202#endif 203 204 /* Type 7 LSA */ 205 206 /* Link LSA */ 207 struct llsa { 208 union { 209 uint8_t pri; 210 uint32_t opt; 211 } llsa_priandopt; 212#define llsa_priority llsa_priandopt.pri 213#define llsa_options llsa_priandopt.opt 214 struct in6_addr llsa_lladdr; 215 uint32_t llsa_nprefix; 216 struct lsa6_prefix llsa_prefix[1]; 217 } un_llsa; 218 219 /* Intra-Area-Prefix */ 220 struct { 221 uint16_t intra_ap_nprefix; 222 uint16_t intra_ap_lstype; 223 rtrid_t intra_ap_lsid; 224 rtrid_t intra_ap_rtid; 225 struct lsa6_prefix intra_ap_prefix[1]; 226 } un_intra_ap; 227 } lsa_un; 228}; 229 230/* 231 * the main header 232 */ 233struct ospf6hdr { 234 uint8_t ospf6_version; 235 uint8_t ospf6_type; 236 uint16_t ospf6_len; 237 rtrid_t ospf6_routerid; 238 rtrid_t ospf6_areaid; 239 uint16_t ospf6_chksum; 240 uint8_t ospf6_instanceid; 241 uint8_t ospf6_rsvd; 242}; 243 244/* 245 * The OSPF6 header length is 16 bytes, regardless of how your compiler 246 * might choose to pad the above structure. 247 */ 248#define OSPF6HDR_LEN 16 249 250/* Hello packet */ 251struct hello6 { 252 uint32_t hello_ifid; 253 union { 254 uint8_t pri; 255 uint32_t opt; 256 } hello_priandopt; 257#define hello_priority hello_priandopt.pri 258#define hello_options hello_priandopt.opt 259 uint16_t hello_helloint; 260 uint16_t hello_deadint; 261 rtrid_t hello_dr; 262 rtrid_t hello_bdr; 263 rtrid_t hello_neighbor[1]; /* may repeat */ 264}; 265 266/* Database Description packet */ 267struct dd6 { 268 uint32_t db_options; 269 uint16_t db_mtu; 270 uint8_t db_mbz; 271 uint8_t db_flags; 272 uint32_t db_seq; 273 struct lsa6_hdr db_lshdr[1]; /* may repeat */ 274}; 275 276/* Link State Request */ 277struct lsr6 { 278 uint16_t ls_mbz; 279 uint16_t ls_type; 280 rtrid_t ls_stateid; 281 rtrid_t ls_router; 282}; 283 284/* Link State Update */ 285struct lsu6 { 286 uint32_t lsu_count; 287 struct lsa6 lsu_lsa[1]; /* may repeat */ 288}; 289 290static const char tstr[] = " [|ospf3]"; 291 292static const struct tok ospf6_option_values[] = { 293 { OSPF6_OPTION_V6, "V6" }, 294 { OSPF6_OPTION_E, "External" }, 295 { OSPF6_OPTION_MC, "Deprecated" }, 296 { OSPF6_OPTION_N, "NSSA" }, 297 { OSPF6_OPTION_R, "Router" }, 298 { OSPF6_OPTION_DC, "Demand Circuit" }, 299 { OSPF6_OPTION_AF, "AFs Support" }, 300 { OSPF6_OPTION_L, "LLS" }, 301 { OSPF6_OPTION_AT, "Authentication Trailer" }, 302 { 0, NULL } 303}; 304 305static const struct tok ospf6_rla_flag_values[] = { 306 { RLA_FLAG_B, "ABR" }, 307 { RLA_FLAG_E, "External" }, 308 { RLA_FLAG_V, "Virtual-Link Endpoint" }, 309 { RLA_FLAG_W, "Wildcard Receiver" }, 310 { RLA_FLAG_N, "NSSA Translator" }, 311 { 0, NULL } 312}; 313 314static const struct tok ospf6_asla_flag_values[] = { 315 { ASLA_FLAG_EXTERNAL, "External Type 2" }, 316 { ASLA_FLAG_FWDADDR, "Forwarding" }, 317 { ASLA_FLAG_ROUTETAG, "Tag" }, 318 { 0, NULL } 319}; 320 321static const struct tok ospf6_type_values[] = { 322 { OSPF_TYPE_HELLO, "Hello" }, 323 { OSPF_TYPE_DD, "Database Description" }, 324 { OSPF_TYPE_LS_REQ, "LS-Request" }, 325 { OSPF_TYPE_LS_UPDATE, "LS-Update" }, 326 { OSPF_TYPE_LS_ACK, "LS-Ack" }, 327 { 0, NULL } 328}; 329 330static const struct tok ospf6_lsa_values[] = { 331 { LS_TYPE_ROUTER, "Router" }, 332 { LS_TYPE_NETWORK, "Network" }, 333 { LS_TYPE_INTER_AP, "Inter-Area Prefix" }, 334 { LS_TYPE_INTER_AR, "Inter-Area Router" }, 335 { LS_TYPE_ASE, "External" }, 336 { LS_TYPE_GROUP, "Deprecated" }, 337 { LS_TYPE_NSSA, "NSSA" }, 338 { LS_TYPE_LINK, "Link" }, 339 { LS_TYPE_INTRA_AP, "Intra-Area Prefix" }, 340 { LS_TYPE_INTRA_ATE, "Intra-Area TE" }, 341 { LS_TYPE_GRACE, "Grace" }, 342 { LS_TYPE_RI, "Router Information" }, 343 { LS_TYPE_INTER_ASTE, "Inter-AS-TE" }, 344 { LS_TYPE_L1VPN, "Layer 1 VPN" }, 345 { 0, NULL } 346}; 347 348static const struct tok ospf6_ls_scope_values[] = { 349 { LS_SCOPE_LINKLOCAL, "Link Local" }, 350 { LS_SCOPE_AREA, "Area Local" }, 351 { LS_SCOPE_AS, "Domain Wide" }, 352 { 0, NULL } 353}; 354 355static const struct tok ospf6_dd_flag_values[] = { 356 { OSPF6_DB_INIT, "Init" }, 357 { OSPF6_DB_MORE, "More" }, 358 { OSPF6_DB_MASTER, "Master" }, 359 { OSPF6_DB_M6, "IPv6 MTU" }, 360 { 0, NULL } 361}; 362 363static const struct tok ospf6_lsa_prefix_option_values[] = { 364 { LSA_PREFIX_OPT_NU, "No Unicast" }, 365 { LSA_PREFIX_OPT_LA, "Local address" }, 366 { LSA_PREFIX_OPT_MC, "Deprecated" }, 367 { LSA_PREFIX_OPT_P, "Propagate" }, 368 { LSA_PREFIX_OPT_DN, "Down" }, 369 { 0, NULL } 370}; 371 372static const struct tok ospf6_auth_type_str[] = { 373 { OSPF6_AUTH_TYPE_HMAC, "HMAC" }, 374 { 0, NULL } 375}; 376 377static void 378ospf6_print_ls_type(netdissect_options *ndo, 379 register u_int ls_type, register const rtrid_t *ls_stateid) 380{ 381 ND_PRINT((ndo, "\n\t %s LSA (%d), %s Scope%s, LSA-ID %s", 382 tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK), 383 ls_type & LS_TYPE_MASK, 384 tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK), 385 ls_type &0x8000 ? ", transitive" : "", /* U-bit */ 386 ipaddr_string(ndo, ls_stateid))); 387} 388 389static int 390ospf6_print_lshdr(netdissect_options *ndo, 391 register const struct lsa6_hdr *lshp, const u_char *dataend) 392{ 393 if ((const u_char *)(lshp + 1) > dataend) 394 goto trunc; 395 ND_TCHECK(lshp->ls_type); 396 ND_TCHECK(lshp->ls_seq); 397 398 ND_PRINT((ndo, "\n\t Advertising Router %s, seq 0x%08x, age %us, length %u", 399 ipaddr_string(ndo, &lshp->ls_router), 400 EXTRACT_32BITS(&lshp->ls_seq), 401 EXTRACT_16BITS(&lshp->ls_age), 402 EXTRACT_16BITS(&lshp->ls_length)-(u_int)sizeof(struct lsa6_hdr))); 403 404 ospf6_print_ls_type(ndo, EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid); 405 406 return (0); 407trunc: 408 return (1); 409} 410 411static int 412ospf6_print_lsaprefix(netdissect_options *ndo, 413 const uint8_t *tptr, u_int lsa_length) 414{ 415 const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr; 416 u_int wordlen; 417 struct in6_addr prefix; 418 419 if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES) 420 goto trunc; 421 lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES; 422 ND_TCHECK2(*lsapp, sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES); 423 wordlen = (lsapp->lsa_p_len + 31) / 32; 424 if (wordlen * 4 > sizeof(struct in6_addr)) { 425 ND_PRINT((ndo, " bogus prefixlen /%d", lsapp->lsa_p_len)); 426 goto trunc; 427 } 428 if (lsa_length < wordlen * 4) 429 goto trunc; 430 lsa_length -= wordlen * 4; 431 ND_TCHECK2(lsapp->lsa_p_prefix, wordlen * 4); 432 memset(&prefix, 0, sizeof(prefix)); 433 memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4); 434 ND_PRINT((ndo, "\n\t\t%s/%d", ip6addr_string(ndo, &prefix), 435 lsapp->lsa_p_len)); 436 if (lsapp->lsa_p_opt) { 437 ND_PRINT((ndo, ", Options [%s]", 438 bittok2str(ospf6_lsa_prefix_option_values, 439 "none", lsapp->lsa_p_opt))); 440 } 441 ND_PRINT((ndo, ", metric %u", EXTRACT_16BITS(&lsapp->lsa_p_metric))); 442 return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4; 443 444trunc: 445 return -1; 446} 447 448 449/* 450 * Print a single link state advertisement. If truncated return 1, else 0. 451 */ 452static int 453ospf6_print_lsa(netdissect_options *ndo, 454 register const struct lsa6 *lsap, const u_char *dataend) 455{ 456 register const struct rlalink6 *rlp; 457#if 0 458 register const struct tos_metric *tosp; 459#endif 460 register const rtrid_t *ap; 461#if 0 462 register const struct aslametric *almp; 463 register const struct mcla *mcp; 464#endif 465 register const struct llsa *llsap; 466 register const struct lsa6_prefix *lsapp; 467#if 0 468 register const uint32_t *lp; 469#endif 470 register u_int prefixes; 471 register int bytelen; 472 register u_int length, lsa_length; 473 uint32_t flags32; 474 const uint8_t *tptr; 475 476 if (ospf6_print_lshdr(ndo, &lsap->ls_hdr, dataend)) 477 return (1); 478 ND_TCHECK(lsap->ls_hdr.ls_length); 479 length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length); 480 481 /* 482 * The LSA length includes the length of the header; 483 * it must have a value that's at least that length. 484 * If it does, find the length of what follows the 485 * header. 486 */ 487 if (length < sizeof(struct lsa6_hdr) || (const u_char *)lsap + length > dataend) 488 return (1); 489 lsa_length = length - sizeof(struct lsa6_hdr); 490 tptr = (const uint8_t *)lsap+sizeof(struct lsa6_hdr); 491 492 switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { 493 case LS_TYPE_ROUTER | LS_SCOPE_AREA: 494 if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options)) 495 return (1); 496 lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options); 497 ND_TCHECK(lsap->lsa_un.un_rla.rla_options); 498 ND_PRINT((ndo, "\n\t Options [%s]", 499 bittok2str(ospf6_option_values, "none", 500 EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options)))); 501 ND_PRINT((ndo, ", RLA-Flags [%s]", 502 bittok2str(ospf6_rla_flag_values, "none", 503 lsap->lsa_un.un_rla.rla_flags))); 504 505 rlp = lsap->lsa_un.un_rla.rla_link; 506 while (lsa_length != 0) { 507 if (lsa_length < sizeof (*rlp)) 508 return (1); 509 lsa_length -= sizeof (*rlp); 510 ND_TCHECK(*rlp); 511 switch (rlp->link_type) { 512 513 case RLA_TYPE_VIRTUAL: 514 ND_PRINT((ndo, "\n\t Virtual Link: Neighbor Router-ID %s" 515 "\n\t Neighbor Interface-ID %s, Interface %s", 516 ipaddr_string(ndo, &rlp->link_nrtid), 517 ipaddr_string(ndo, &rlp->link_nifid), 518 ipaddr_string(ndo, &rlp->link_ifid))); 519 break; 520 521 case RLA_TYPE_ROUTER: 522 ND_PRINT((ndo, "\n\t Neighbor Router-ID %s" 523 "\n\t Neighbor Interface-ID %s, Interface %s", 524 ipaddr_string(ndo, &rlp->link_nrtid), 525 ipaddr_string(ndo, &rlp->link_nifid), 526 ipaddr_string(ndo, &rlp->link_ifid))); 527 break; 528 529 case RLA_TYPE_TRANSIT: 530 ND_PRINT((ndo, "\n\t Neighbor Network-ID %s" 531 "\n\t Neighbor Interface-ID %s, Interface %s", 532 ipaddr_string(ndo, &rlp->link_nrtid), 533 ipaddr_string(ndo, &rlp->link_nifid), 534 ipaddr_string(ndo, &rlp->link_ifid))); 535 break; 536 537 default: 538 ND_PRINT((ndo, "\n\t Unknown Router Links Type 0x%02x", 539 rlp->link_type)); 540 return (0); 541 } 542 ND_PRINT((ndo, ", metric %d", EXTRACT_16BITS(&rlp->link_metric))); 543 rlp++; 544 } 545 break; 546 547 case LS_TYPE_NETWORK | LS_SCOPE_AREA: 548 if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options)) 549 return (1); 550 lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options); 551 ND_TCHECK(lsap->lsa_un.un_nla.nla_options); 552 ND_PRINT((ndo, "\n\t Options [%s]", 553 bittok2str(ospf6_option_values, "none", 554 EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options)))); 555 556 ND_PRINT((ndo, "\n\t Connected Routers:")); 557 ap = lsap->lsa_un.un_nla.nla_router; 558 while (lsa_length != 0) { 559 if (lsa_length < sizeof (*ap)) 560 return (1); 561 lsa_length -= sizeof (*ap); 562 ND_TCHECK(*ap); 563 ND_PRINT((ndo, "\n\t\t%s", ipaddr_string(ndo, ap))); 564 ++ap; 565 } 566 break; 567 568 case LS_TYPE_INTER_AP | LS_SCOPE_AREA: 569 if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric)) 570 return (1); 571 lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric); 572 ND_TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); 573 ND_PRINT((ndo, ", metric %u", 574 EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC)); 575 576 tptr = (const uint8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix; 577 while (lsa_length != 0) { 578 bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 579 if (bytelen < 0) 580 goto trunc; 581 lsa_length -= bytelen; 582 tptr += bytelen; 583 } 584 break; 585 586 case LS_TYPE_ASE | LS_SCOPE_AS: 587 if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric)) 588 return (1); 589 lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric); 590 ND_TCHECK(lsap->lsa_un.un_asla.asla_metric); 591 flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); 592 ND_PRINT((ndo, "\n\t Flags [%s]", 593 bittok2str(ospf6_asla_flag_values, "none", flags32))); 594 ND_PRINT((ndo, " metric %u", 595 EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & 596 ASLA_MASK_METRIC)); 597 598 tptr = (const uint8_t *)lsap->lsa_un.un_asla.asla_prefix; 599 lsapp = (const struct lsa6_prefix *)tptr; 600 bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 601 if (bytelen < 0) 602 goto trunc; 603 lsa_length -= bytelen; 604 tptr += bytelen; 605 606 if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { 607 const struct in6_addr *fwdaddr6; 608 609 fwdaddr6 = (const struct in6_addr *)tptr; 610 if (lsa_length < sizeof (*fwdaddr6)) 611 return (1); 612 lsa_length -= sizeof (*fwdaddr6); 613 ND_TCHECK(*fwdaddr6); 614 ND_PRINT((ndo, " forward %s", 615 ip6addr_string(ndo, fwdaddr6))); 616 tptr += sizeof(*fwdaddr6); 617 } 618 619 if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { 620 if (lsa_length < sizeof (uint32_t)) 621 return (1); 622 lsa_length -= sizeof (uint32_t); 623 ND_TCHECK(*(const uint32_t *)tptr); 624 ND_PRINT((ndo, " tag %s", 625 ipaddr_string(ndo, (const uint32_t *)tptr))); 626 tptr += sizeof(uint32_t); 627 } 628 629 if (lsapp->lsa_p_metric) { 630 if (lsa_length < sizeof (uint32_t)) 631 return (1); 632 lsa_length -= sizeof (uint32_t); 633 ND_TCHECK(*(const uint32_t *)tptr); 634 ND_PRINT((ndo, " RefLSID: %s", 635 ipaddr_string(ndo, (const uint32_t *)tptr))); 636 tptr += sizeof(uint32_t); 637 } 638 break; 639 640 case LS_TYPE_LINK: 641 /* Link LSA */ 642 llsap = &lsap->lsa_un.un_llsa; 643 if (lsa_length < sizeof (llsap->llsa_priandopt)) 644 return (1); 645 lsa_length -= sizeof (llsap->llsa_priandopt); 646 ND_TCHECK(llsap->llsa_priandopt); 647 ND_PRINT((ndo, "\n\t Options [%s]", 648 bittok2str(ospf6_option_values, "none", 649 EXTRACT_32BITS(&llsap->llsa_options)))); 650 651 if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) 652 return (1); 653 lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); 654 prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); 655 ND_PRINT((ndo, "\n\t Priority %d, Link-local address %s, Prefixes %d:", 656 llsap->llsa_priority, 657 ip6addr_string(ndo, &llsap->llsa_lladdr), 658 prefixes)); 659 660 tptr = (const uint8_t *)llsap->llsa_prefix; 661 while (prefixes > 0) { 662 bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 663 if (bytelen < 0) 664 goto trunc; 665 prefixes--; 666 lsa_length -= bytelen; 667 tptr += bytelen; 668 } 669 break; 670 671 case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: 672 /* Intra-Area-Prefix LSA */ 673 if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid)) 674 return (1); 675 lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid); 676 ND_TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); 677 ospf6_print_ls_type(ndo, 678 EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), 679 &lsap->lsa_un.un_intra_ap.intra_ap_lsid); 680 681 if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix)) 682 return (1); 683 lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 684 ND_TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 685 prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 686 ND_PRINT((ndo, "\n\t Prefixes %d:", prefixes)); 687 688 tptr = (const uint8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; 689 while (prefixes > 0) { 690 bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 691 if (bytelen < 0) 692 goto trunc; 693 prefixes--; 694 lsa_length -= bytelen; 695 tptr += bytelen; 696 } 697 break; 698 699 case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: 700 if (ospf_print_grace_lsa(ndo, tptr, lsa_length) == -1) { 701 return 1; 702 } 703 break; 704 705 case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: 706 if (ospf_print_te_lsa(ndo, tptr, lsa_length) == -1) { 707 return 1; 708 } 709 break; 710 711 default: 712 if(!print_unknown_data(ndo,tptr, 713 "\n\t ", 714 lsa_length)) { 715 return (1); 716 } 717 break; 718 } 719 720 return (0); 721trunc: 722 return (1); 723} 724 725static int 726ospf6_decode_v3(netdissect_options *ndo, 727 register const struct ospf6hdr *op, 728 register const u_char *dataend) 729{ 730 register const rtrid_t *ap; 731 register const struct lsr6 *lsrp; 732 register const struct lsa6_hdr *lshp; 733 register const struct lsa6 *lsap; 734 register int i; 735 736 switch (op->ospf6_type) { 737 738 case OSPF_TYPE_HELLO: { 739 register const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); 740 741 ND_PRINT((ndo, "\n\tOptions [%s]", 742 bittok2str(ospf6_option_values, "none", 743 EXTRACT_32BITS(&hellop->hello_options)))); 744 745 ND_TCHECK(hellop->hello_deadint); 746 ND_PRINT((ndo, "\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u", 747 EXTRACT_16BITS(&hellop->hello_helloint), 748 EXTRACT_16BITS(&hellop->hello_deadint), 749 ipaddr_string(ndo, &hellop->hello_ifid), 750 hellop->hello_priority)); 751 752 ND_TCHECK(hellop->hello_dr); 753 if (EXTRACT_32BITS(&hellop->hello_dr) != 0) 754 ND_PRINT((ndo, "\n\t Designated Router %s", 755 ipaddr_string(ndo, &hellop->hello_dr))); 756 ND_TCHECK(hellop->hello_bdr); 757 if (EXTRACT_32BITS(&hellop->hello_bdr) != 0) 758 ND_PRINT((ndo, ", Backup Designated Router %s", 759 ipaddr_string(ndo, &hellop->hello_bdr))); 760 if (ndo->ndo_vflag > 1) { 761 ND_PRINT((ndo, "\n\t Neighbor List:")); 762 ap = hellop->hello_neighbor; 763 while ((const u_char *)ap < dataend) { 764 ND_TCHECK(*ap); 765 ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap))); 766 ++ap; 767 } 768 } 769 break; /* HELLO */ 770 } 771 772 case OSPF_TYPE_DD: { 773 register const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); 774 775 ND_TCHECK(ddp->db_options); 776 ND_PRINT((ndo, "\n\tOptions [%s]", 777 bittok2str(ospf6_option_values, "none", 778 EXTRACT_32BITS(&ddp->db_options)))); 779 ND_TCHECK(ddp->db_flags); 780 ND_PRINT((ndo, ", DD Flags [%s]", 781 bittok2str(ospf6_dd_flag_values,"none",ddp->db_flags))); 782 783 ND_TCHECK(ddp->db_seq); 784 ND_PRINT((ndo, ", MTU %u, DD-Sequence 0x%08x", 785 EXTRACT_16BITS(&ddp->db_mtu), 786 EXTRACT_32BITS(&ddp->db_seq))); 787 if (ndo->ndo_vflag > 1) { 788 /* Print all the LS adv's */ 789 lshp = ddp->db_lshdr; 790 while ((const u_char *)lshp < dataend) { 791 if (ospf6_print_lshdr(ndo, lshp++, dataend)) 792 goto trunc; 793 } 794 } 795 break; 796 } 797 798 case OSPF_TYPE_LS_REQ: 799 if (ndo->ndo_vflag > 1) { 800 lsrp = (const struct lsr6 *)((const uint8_t *)op + OSPF6HDR_LEN); 801 while ((const u_char *)lsrp < dataend) { 802 ND_TCHECK(*lsrp); 803 ND_PRINT((ndo, "\n\t Advertising Router %s", 804 ipaddr_string(ndo, &lsrp->ls_router))); 805 ospf6_print_ls_type(ndo, EXTRACT_16BITS(&lsrp->ls_type), 806 &lsrp->ls_stateid); 807 ++lsrp; 808 } 809 } 810 break; 811 812 case OSPF_TYPE_LS_UPDATE: 813 if (ndo->ndo_vflag > 1) { 814 register const struct lsu6 *lsup = (const struct lsu6 *)((const uint8_t *)op + OSPF6HDR_LEN); 815 816 ND_TCHECK(lsup->lsu_count); 817 i = EXTRACT_32BITS(&lsup->lsu_count); 818 lsap = lsup->lsu_lsa; 819 while ((const u_char *)lsap < dataend && i--) { 820 if (ospf6_print_lsa(ndo, lsap, dataend)) 821 goto trunc; 822 lsap = (const struct lsa6 *)((const u_char *)lsap + 823 EXTRACT_16BITS(&lsap->ls_hdr.ls_length)); 824 } 825 } 826 break; 827 828 case OSPF_TYPE_LS_ACK: 829 if (ndo->ndo_vflag > 1) { 830 lshp = (const struct lsa6_hdr *)((const uint8_t *)op + OSPF6HDR_LEN); 831 while ((const u_char *)lshp < dataend) { 832 if (ospf6_print_lshdr(ndo, lshp++, dataend)) 833 goto trunc; 834 } 835 } 836 break; 837 838 default: 839 break; 840 } 841 return (0); 842trunc: 843 return (1); 844} 845 846/* RFC5613 Section 2.2 (w/o the TLVs) */ 847static int 848ospf6_print_lls(netdissect_options *ndo, 849 const u_char *cp, const u_int len) 850{ 851 uint16_t llsdatalen; 852 853 if (len == 0) 854 return 0; 855 if (len < OSPF_LLS_HDRLEN) 856 goto trunc; 857 /* Checksum */ 858 ND_TCHECK2(*cp, 2); 859 ND_PRINT((ndo, "\n\tLLS Checksum 0x%04x", EXTRACT_16BITS(cp))); 860 cp += 2; 861 /* LLS Data Length */ 862 ND_TCHECK2(*cp, 2); 863 llsdatalen = EXTRACT_16BITS(cp); 864 ND_PRINT((ndo, ", Data Length %u", llsdatalen)); 865 if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len) 866 goto trunc; 867 cp += 2; 868 /* LLS TLVs */ 869 ND_TCHECK2(*cp, llsdatalen - OSPF_LLS_HDRLEN); 870 /* FIXME: code in print-ospf.c can be reused to decode the TLVs */ 871 872 return llsdatalen; 873trunc: 874 return -1; 875} 876 877/* RFC6506 Section 4.1 */ 878static int 879ospf6_decode_at(netdissect_options *ndo, 880 const u_char *cp, const u_int len) 881{ 882 uint16_t authdatalen; 883 884 if (len == 0) 885 return 0; 886 if (len < OSPF6_AT_HDRLEN) 887 goto trunc; 888 /* Authentication Type */ 889 ND_TCHECK2(*cp, 2); 890 ND_PRINT((ndo, "\n\tAuthentication Type %s", tok2str(ospf6_auth_type_str, "unknown (0x%04x)", EXTRACT_16BITS(cp)))); 891 cp += 2; 892 /* Auth Data Len */ 893 ND_TCHECK2(*cp, 2); 894 authdatalen = EXTRACT_16BITS(cp); 895 ND_PRINT((ndo, ", Length %u", authdatalen)); 896 if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len) 897 goto trunc; 898 cp += 2; 899 /* Reserved */ 900 ND_TCHECK2(*cp, 2); 901 cp += 2; 902 /* Security Association ID */ 903 ND_TCHECK2(*cp, 2); 904 ND_PRINT((ndo, ", SAID %u", EXTRACT_16BITS(cp))); 905 cp += 2; 906 /* Cryptographic Sequence Number (High-Order 32 Bits) */ 907 ND_TCHECK2(*cp, 4); 908 ND_PRINT((ndo, ", CSN 0x%08x", EXTRACT_32BITS(cp))); 909 cp += 4; 910 /* Cryptographic Sequence Number (Low-Order 32 Bits) */ 911 ND_TCHECK2(*cp, 4); 912 ND_PRINT((ndo, ":%08x", EXTRACT_32BITS(cp))); 913 cp += 4; 914 /* Authentication Data */ 915 ND_TCHECK2(*cp, authdatalen - OSPF6_AT_HDRLEN); 916 if (ndo->ndo_vflag > 1) 917 print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN); 918 return 0; 919 920trunc: 921 return 1; 922} 923 924/* The trailing data may include LLS and/or AT data (in this specific order). 925 * LLS data may be present only in Hello and DBDesc packets with the L-bit set. 926 * AT data may be present in Hello and DBDesc packets with the AT-bit set or in 927 * any other packet type, thus decode the AT data regardless of the AT-bit. 928 */ 929static int 930ospf6_decode_v3_trailer(netdissect_options *ndo, 931 const struct ospf6hdr *op, const u_char *cp, const unsigned len) 932{ 933 int llslen = 0; 934 int lls_hello = 0; 935 int lls_dd = 0; 936 937 if (op->ospf6_type == OSPF_TYPE_HELLO) { 938 const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); 939 if (EXTRACT_32BITS(&hellop->hello_options) & OSPF6_OPTION_L) 940 lls_hello = 1; 941 } else if (op->ospf6_type == OSPF_TYPE_DD) { 942 const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); 943 if (EXTRACT_32BITS(&ddp->db_options) & OSPF6_OPTION_L) 944 lls_dd = 1; 945 } 946 if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(ndo, cp, len)) < 0) 947 goto trunc; 948 return ospf6_decode_at(ndo, cp + llslen, len - llslen); 949 950trunc: 951 return 1; 952} 953 954void 955ospf6_print(netdissect_options *ndo, 956 register const u_char *bp, register u_int length) 957{ 958 register const struct ospf6hdr *op; 959 register const u_char *dataend; 960 register const char *cp; 961 uint16_t datalen; 962 963 op = (const struct ospf6hdr *)bp; 964 965 /* If the type is valid translate it, or just print the type */ 966 /* value. If it's not valid, say so and return */ 967 ND_TCHECK(op->ospf6_type); 968 cp = tok2str(ospf6_type_values, "unknown packet type (%u)", op->ospf6_type); 969 ND_PRINT((ndo, "OSPFv%u, %s, length %d", op->ospf6_version, cp, length)); 970 if (*cp == 'u') { 971 return; 972 } 973 974 if(!ndo->ndo_vflag) { /* non verbose - so lets bail out here */ 975 return; 976 } 977 978 /* OSPFv3 data always comes first and optional trailing data may follow. */ 979 ND_TCHECK(op->ospf6_len); 980 datalen = EXTRACT_16BITS(&op->ospf6_len); 981 if (datalen > length) { 982 ND_PRINT((ndo, " [len %d]", datalen)); 983 return; 984 } 985 dataend = bp + datalen; 986 987 ND_TCHECK(op->ospf6_routerid); 988 ND_PRINT((ndo, "\n\tRouter-ID %s", ipaddr_string(ndo, &op->ospf6_routerid))); 989 990 ND_TCHECK(op->ospf6_areaid); 991 if (EXTRACT_32BITS(&op->ospf6_areaid) != 0) 992 ND_PRINT((ndo, ", Area %s", ipaddr_string(ndo, &op->ospf6_areaid))); 993 else 994 ND_PRINT((ndo, ", Backbone Area")); 995 ND_TCHECK(op->ospf6_instanceid); 996 if (op->ospf6_instanceid) 997 ND_PRINT((ndo, ", Instance %u", op->ospf6_instanceid)); 998 999 /* Do rest according to version. */ 1000 switch (op->ospf6_version) { 1001 1002 case 3: 1003 /* ospf version 3 */ 1004 if (ospf6_decode_v3(ndo, op, dataend) || 1005 ospf6_decode_v3_trailer(ndo, op, dataend, length - datalen)) 1006 goto trunc; 1007 break; 1008 } /* end switch on version */ 1009 1010 return; 1011trunc: 1012 ND_PRINT((ndo, "%s", tstr)); 1013} 1014