156893Sfenner/* 256893Sfenner * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 356893Sfenner * The Regents of the University of California. All rights reserved. 456893Sfenner * 556893Sfenner * Redistribution and use in source and binary forms, with or without 656893Sfenner * modification, are permitted provided that: (1) source code distributions 756893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 856893Sfenner * distributions including binary code include the above copyright notice and 956893Sfenner * this paragraph in its entirety in the documentation or other materials 1056893Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1156893Sfenner * features or use of this software display the following acknowledgement: 1256893Sfenner * ``This product includes software developed by the University of California, 1356893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1456893Sfenner * the University nor the names of its contributors may be used to endorse 1556893Sfenner * or promote products derived from this software without specific prior 1656893Sfenner * written permission. 1756893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1856893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1956893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2056893Sfenner * 2156893Sfenner * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 2256893Sfenner */ 2356893Sfenner 24313537Sglebius/* \summary: IPv6 Open Shortest Path First (OSPFv3) printer */ 25313537Sglebius 2656893Sfenner#ifdef HAVE_CONFIG_H 2756893Sfenner#include "config.h" 2856893Sfenner#endif 2956893Sfenner 30313537Sglebius#include <netdissect-stdinc.h> 3156893Sfenner 3256893Sfenner#include <string.h> 3356893Sfenner 34313537Sglebius#include "netdissect.h" 3556893Sfenner#include "addrtoname.h" 36127668Sbms#include "extract.h" 3756893Sfenner 38190207Srpaulo#include "ospf.h" 3956893Sfenner 40276788Sdelphij#define OSPF_TYPE_HELLO 1 /* Hello */ 41276788Sdelphij#define OSPF_TYPE_DD 2 /* Database Description */ 42276788Sdelphij#define OSPF_TYPE_LS_REQ 3 /* Link State Request */ 43276788Sdelphij#define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */ 44276788Sdelphij#define OSPF_TYPE_LS_ACK 5 /* Link State Ack */ 45276788Sdelphij 46276788Sdelphij/* Options *_options */ 47276788Sdelphij#define OSPF6_OPTION_V6 0x01 /* V6 bit: A bit for peeping tom */ 48276788Sdelphij#define OSPF6_OPTION_E 0x02 /* E bit: External routes advertised */ 49276788Sdelphij#define OSPF6_OPTION_MC 0x04 /* MC bit: Multicast capable */ 50276788Sdelphij#define OSPF6_OPTION_N 0x08 /* N bit: For type-7 LSA */ 51276788Sdelphij#define OSPF6_OPTION_R 0x10 /* R bit: Router bit */ 52276788Sdelphij#define OSPF6_OPTION_DC 0x20 /* DC bit: Demand circuits */ 53276788Sdelphij/* The field is actually 24-bit (RFC5340 Section A.2). */ 54276788Sdelphij#define OSPF6_OPTION_AF 0x0100 /* AF bit: Multiple address families */ 55276788Sdelphij#define OSPF6_OPTION_L 0x0200 /* L bit: Link-local signaling (LLS) */ 56276788Sdelphij#define OSPF6_OPTION_AT 0x0400 /* AT bit: Authentication trailer */ 57276788Sdelphij 58276788Sdelphij 59276788Sdelphij/* db_flags */ 60276788Sdelphij#define OSPF6_DB_INIT 0x04 /* */ 61276788Sdelphij#define OSPF6_DB_MORE 0x02 62276788Sdelphij#define OSPF6_DB_MASTER 0x01 63276788Sdelphij#define OSPF6_DB_M6 0x10 /* IPv6 MTU */ 64276788Sdelphij 65276788Sdelphij/* ls_type */ 66276788Sdelphij#define LS_TYPE_ROUTER 1 /* router link */ 67276788Sdelphij#define LS_TYPE_NETWORK 2 /* network link */ 68276788Sdelphij#define LS_TYPE_INTER_AP 3 /* Inter-Area-Prefix */ 69276788Sdelphij#define LS_TYPE_INTER_AR 4 /* Inter-Area-Router */ 70276788Sdelphij#define LS_TYPE_ASE 5 /* ASE */ 71276788Sdelphij#define LS_TYPE_GROUP 6 /* Group membership */ 72276788Sdelphij#define LS_TYPE_NSSA 7 /* NSSA */ 73276788Sdelphij#define LS_TYPE_LINK 8 /* Link LSA */ 74276788Sdelphij#define LS_TYPE_INTRA_AP 9 /* Intra-Area-Prefix */ 75276788Sdelphij#define LS_TYPE_INTRA_ATE 10 /* Intra-Area-TE */ 76276788Sdelphij#define LS_TYPE_GRACE 11 /* Grace LSA */ 77276788Sdelphij#define LS_TYPE_RI 12 /* Router information */ 78276788Sdelphij#define LS_TYPE_INTER_ASTE 13 /* Inter-AS-TE */ 79276788Sdelphij#define LS_TYPE_L1VPN 14 /* L1VPN */ 80276788Sdelphij#define LS_TYPE_MASK 0x1fff 81276788Sdelphij 82276788Sdelphij#define LS_SCOPE_LINKLOCAL 0x0000 83276788Sdelphij#define LS_SCOPE_AREA 0x2000 84276788Sdelphij#define LS_SCOPE_AS 0x4000 85276788Sdelphij#define LS_SCOPE_MASK 0x6000 86276788Sdelphij#define LS_SCOPE_U 0x8000 87276788Sdelphij 88276788Sdelphij/* rla_link.link_type */ 89276788Sdelphij#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */ 90276788Sdelphij#define RLA_TYPE_TRANSIT 2 /* connection to transit network */ 91276788Sdelphij#define RLA_TYPE_VIRTUAL 4 /* virtual link */ 92276788Sdelphij 93276788Sdelphij/* rla_flags */ 94276788Sdelphij#define RLA_FLAG_B 0x01 95276788Sdelphij#define RLA_FLAG_E 0x02 96276788Sdelphij#define RLA_FLAG_V 0x04 97276788Sdelphij#define RLA_FLAG_W 0x08 98276788Sdelphij#define RLA_FLAG_N 0x10 99276788Sdelphij 100276788Sdelphij/* lsa_prefix options */ 101276788Sdelphij#define LSA_PREFIX_OPT_NU 0x01 102276788Sdelphij#define LSA_PREFIX_OPT_LA 0x02 103276788Sdelphij#define LSA_PREFIX_OPT_MC 0x04 104276788Sdelphij#define LSA_PREFIX_OPT_P 0x08 105276788Sdelphij#define LSA_PREFIX_OPT_DN 0x10 106276788Sdelphij 107276788Sdelphij/* sla_tosmetric breakdown */ 108276788Sdelphij#define SLA_MASK_TOS 0x7f000000 109276788Sdelphij#define SLA_MASK_METRIC 0x00ffffff 110276788Sdelphij#define SLA_SHIFT_TOS 24 111276788Sdelphij 112276788Sdelphij/* asla_metric */ 113276788Sdelphij#define ASLA_FLAG_FWDADDR 0x02000000 114276788Sdelphij#define ASLA_FLAG_ROUTETAG 0x01000000 115276788Sdelphij#define ASLA_MASK_METRIC 0x00ffffff 116276788Sdelphij 117276788Sdelphij/* RFC6506 Section 4.1 */ 118276788Sdelphij#define OSPF6_AT_HDRLEN 16U 119276788Sdelphij#define OSPF6_AUTH_TYPE_HMAC 0x0001 120276788Sdelphij 121276788Sdelphijtypedef uint32_t rtrid_t; 122276788Sdelphij 123276788Sdelphij/* link state advertisement header */ 124276788Sdelphijstruct lsa6_hdr { 125276788Sdelphij uint16_t ls_age; 126276788Sdelphij uint16_t ls_type; 127276788Sdelphij rtrid_t ls_stateid; 128276788Sdelphij rtrid_t ls_router; 129276788Sdelphij uint32_t ls_seq; 130276788Sdelphij uint16_t ls_chksum; 131276788Sdelphij uint16_t ls_length; 132276788Sdelphij}; 133276788Sdelphij 134276788Sdelphij/* Length of an IPv6 address, in bytes. */ 135276788Sdelphij#define IPV6_ADDR_LEN_BYTES (128/8) 136276788Sdelphij 137276788Sdelphijstruct lsa6_prefix { 138276788Sdelphij uint8_t lsa_p_len; 139276788Sdelphij uint8_t lsa_p_opt; 140276788Sdelphij uint16_t lsa_p_metric; 141276788Sdelphij uint8_t lsa_p_prefix[IPV6_ADDR_LEN_BYTES]; /* maximum length */ 142276788Sdelphij}; 143276788Sdelphij 144276788Sdelphij/* link state advertisement */ 145276788Sdelphijstruct lsa6 { 146276788Sdelphij struct lsa6_hdr ls_hdr; 147276788Sdelphij 148276788Sdelphij /* Link state types */ 149276788Sdelphij union { 150276788Sdelphij /* Router links advertisements */ 151276788Sdelphij struct { 152276788Sdelphij union { 153276788Sdelphij uint8_t flg; 154276788Sdelphij uint32_t opt; 155276788Sdelphij } rla_flgandopt; 156276788Sdelphij#define rla_flags rla_flgandopt.flg 157276788Sdelphij#define rla_options rla_flgandopt.opt 158276788Sdelphij struct rlalink6 { 159276788Sdelphij uint8_t link_type; 160276788Sdelphij uint8_t link_zero[1]; 161276788Sdelphij uint16_t link_metric; 162276788Sdelphij uint32_t link_ifid; 163276788Sdelphij uint32_t link_nifid; 164276788Sdelphij rtrid_t link_nrtid; 165276788Sdelphij } rla_link[1]; /* may repeat */ 166276788Sdelphij } un_rla; 167276788Sdelphij 168276788Sdelphij /* Network links advertisements */ 169276788Sdelphij struct { 170276788Sdelphij uint32_t nla_options; 171276788Sdelphij rtrid_t nla_router[1]; /* may repeat */ 172276788Sdelphij } un_nla; 173276788Sdelphij 174276788Sdelphij /* Inter Area Prefix LSA */ 175276788Sdelphij struct { 176276788Sdelphij uint32_t inter_ap_metric; 177276788Sdelphij struct lsa6_prefix inter_ap_prefix[1]; 178276788Sdelphij } un_inter_ap; 179276788Sdelphij 180276788Sdelphij /* AS external links advertisements */ 181276788Sdelphij struct { 182276788Sdelphij uint32_t asla_metric; 183276788Sdelphij struct lsa6_prefix asla_prefix[1]; 184276788Sdelphij /* some optional fields follow */ 185276788Sdelphij } un_asla; 186276788Sdelphij 187276788Sdelphij#if 0 188276788Sdelphij /* Summary links advertisements */ 189276788Sdelphij struct { 190276788Sdelphij struct in_addr sla_mask; 191276788Sdelphij uint32_t sla_tosmetric[1]; /* may repeat */ 192276788Sdelphij } un_sla; 193276788Sdelphij 194276788Sdelphij /* Multicast group membership */ 195276788Sdelphij struct mcla { 196276788Sdelphij uint32_t mcla_vtype; 197276788Sdelphij struct in_addr mcla_vid; 198276788Sdelphij } un_mcla[1]; 199276788Sdelphij#endif 200276788Sdelphij 201276788Sdelphij /* Type 7 LSA */ 202276788Sdelphij 203276788Sdelphij /* Link LSA */ 204276788Sdelphij struct llsa { 205276788Sdelphij union { 206276788Sdelphij uint8_t pri; 207276788Sdelphij uint32_t opt; 208276788Sdelphij } llsa_priandopt; 209276788Sdelphij#define llsa_priority llsa_priandopt.pri 210276788Sdelphij#define llsa_options llsa_priandopt.opt 211276788Sdelphij struct in6_addr llsa_lladdr; 212276788Sdelphij uint32_t llsa_nprefix; 213276788Sdelphij struct lsa6_prefix llsa_prefix[1]; 214276788Sdelphij } un_llsa; 215276788Sdelphij 216276788Sdelphij /* Intra-Area-Prefix */ 217276788Sdelphij struct { 218276788Sdelphij uint16_t intra_ap_nprefix; 219276788Sdelphij uint16_t intra_ap_lstype; 220276788Sdelphij rtrid_t intra_ap_lsid; 221276788Sdelphij rtrid_t intra_ap_rtid; 222276788Sdelphij struct lsa6_prefix intra_ap_prefix[1]; 223276788Sdelphij } un_intra_ap; 224276788Sdelphij } lsa_un; 225276788Sdelphij}; 226276788Sdelphij 227276788Sdelphij/* 228276788Sdelphij * the main header 229276788Sdelphij */ 230276788Sdelphijstruct ospf6hdr { 231276788Sdelphij uint8_t ospf6_version; 232276788Sdelphij uint8_t ospf6_type; 233276788Sdelphij uint16_t ospf6_len; 234276788Sdelphij rtrid_t ospf6_routerid; 235276788Sdelphij rtrid_t ospf6_areaid; 236276788Sdelphij uint16_t ospf6_chksum; 237276788Sdelphij uint8_t ospf6_instanceid; 238276788Sdelphij uint8_t ospf6_rsvd; 239276788Sdelphij}; 240276788Sdelphij 241276788Sdelphij/* 242276788Sdelphij * The OSPF6 header length is 16 bytes, regardless of how your compiler 243276788Sdelphij * might choose to pad the above structure. 244276788Sdelphij */ 245276788Sdelphij#define OSPF6HDR_LEN 16 246276788Sdelphij 247276788Sdelphij/* Hello packet */ 248276788Sdelphijstruct hello6 { 249276788Sdelphij uint32_t hello_ifid; 250276788Sdelphij union { 251276788Sdelphij uint8_t pri; 252276788Sdelphij uint32_t opt; 253276788Sdelphij } hello_priandopt; 254276788Sdelphij#define hello_priority hello_priandopt.pri 255276788Sdelphij#define hello_options hello_priandopt.opt 256276788Sdelphij uint16_t hello_helloint; 257276788Sdelphij uint16_t hello_deadint; 258276788Sdelphij rtrid_t hello_dr; 259276788Sdelphij rtrid_t hello_bdr; 260276788Sdelphij rtrid_t hello_neighbor[1]; /* may repeat */ 261276788Sdelphij}; 262276788Sdelphij 263276788Sdelphij/* Database Description packet */ 264276788Sdelphijstruct dd6 { 265276788Sdelphij uint32_t db_options; 266276788Sdelphij uint16_t db_mtu; 267276788Sdelphij uint8_t db_mbz; 268276788Sdelphij uint8_t db_flags; 269276788Sdelphij uint32_t db_seq; 270276788Sdelphij struct lsa6_hdr db_lshdr[1]; /* may repeat */ 271276788Sdelphij}; 272276788Sdelphij 273276788Sdelphij/* Link State Request */ 274276788Sdelphijstruct lsr6 { 275276788Sdelphij uint16_t ls_mbz; 276276788Sdelphij uint16_t ls_type; 277276788Sdelphij rtrid_t ls_stateid; 278276788Sdelphij rtrid_t ls_router; 279276788Sdelphij}; 280276788Sdelphij 281276788Sdelphij/* Link State Update */ 282276788Sdelphijstruct lsu6 { 283276788Sdelphij uint32_t lsu_count; 284276788Sdelphij struct lsa6 lsu_lsa[1]; /* may repeat */ 285276788Sdelphij}; 286276788Sdelphij 287276788Sdelphijstatic const char tstr[] = " [|ospf3]"; 288276788Sdelphij 289190207Srpaulostatic const struct tok ospf6_option_values[] = { 290190207Srpaulo { OSPF6_OPTION_V6, "V6" }, 291190207Srpaulo { OSPF6_OPTION_E, "External" }, 292276788Sdelphij { OSPF6_OPTION_MC, "Deprecated" }, 293190207Srpaulo { OSPF6_OPTION_N, "NSSA" }, 294190207Srpaulo { OSPF6_OPTION_R, "Router" }, 295190207Srpaulo { OSPF6_OPTION_DC, "Demand Circuit" }, 296276788Sdelphij { OSPF6_OPTION_AF, "AFs Support" }, 297276788Sdelphij { OSPF6_OPTION_L, "LLS" }, 298276788Sdelphij { OSPF6_OPTION_AT, "Authentication Trailer" }, 299190207Srpaulo { 0, NULL } 30056893Sfenner}; 30156893Sfenner 302190207Srpaulostatic const struct tok ospf6_rla_flag_values[] = { 303190207Srpaulo { RLA_FLAG_B, "ABR" }, 304190207Srpaulo { RLA_FLAG_E, "External" }, 305190207Srpaulo { RLA_FLAG_V, "Virtual-Link Endpoint" }, 306190207Srpaulo { RLA_FLAG_W, "Wildcard Receiver" }, 307190207Srpaulo { RLA_FLAG_N, "NSSA Translator" }, 30856893Sfenner { 0, NULL } 30956893Sfenner}; 31056893Sfenner 311190207Srpaulostatic const struct tok ospf6_asla_flag_values[] = { 312190207Srpaulo { ASLA_FLAG_EXTERNAL, "External Type 2" }, 313276788Sdelphij { ASLA_FLAG_FWDADDR, "Forwarding" }, 314190207Srpaulo { ASLA_FLAG_ROUTETAG, "Tag" }, 31556893Sfenner { 0, NULL } 31656893Sfenner}; 31756893Sfenner 318276788Sdelphijstatic const struct tok ospf6_type_values[] = { 319190207Srpaulo { OSPF_TYPE_HELLO, "Hello" }, 320190207Srpaulo { OSPF_TYPE_DD, "Database Description" }, 321190207Srpaulo { OSPF_TYPE_LS_REQ, "LS-Request" }, 322190207Srpaulo { OSPF_TYPE_LS_UPDATE, "LS-Update" }, 323190207Srpaulo { OSPF_TYPE_LS_ACK, "LS-Ack" }, 32475115Sfenner { 0, NULL } 32575115Sfenner}; 32675115Sfenner 327276788Sdelphijstatic const struct tok ospf6_lsa_values[] = { 328190207Srpaulo { LS_TYPE_ROUTER, "Router" }, 329190207Srpaulo { LS_TYPE_NETWORK, "Network" }, 330190207Srpaulo { LS_TYPE_INTER_AP, "Inter-Area Prefix" }, 331190207Srpaulo { LS_TYPE_INTER_AR, "Inter-Area Router" }, 332190207Srpaulo { LS_TYPE_ASE, "External" }, 333276788Sdelphij { LS_TYPE_GROUP, "Deprecated" }, 334190207Srpaulo { LS_TYPE_NSSA, "NSSA" }, 335190207Srpaulo { LS_TYPE_LINK, "Link" }, 336190207Srpaulo { LS_TYPE_INTRA_AP, "Intra-Area Prefix" }, 337190207Srpaulo { LS_TYPE_INTRA_ATE, "Intra-Area TE" }, 338190207Srpaulo { LS_TYPE_GRACE, "Grace" }, 339276788Sdelphij { LS_TYPE_RI, "Router Information" }, 340276788Sdelphij { LS_TYPE_INTER_ASTE, "Inter-AS-TE" }, 341276788Sdelphij { LS_TYPE_L1VPN, "Layer 1 VPN" }, 34256893Sfenner { 0, NULL } 34356893Sfenner}; 34456893Sfenner 345276788Sdelphijstatic const struct tok ospf6_ls_scope_values[] = { 346190207Srpaulo { LS_SCOPE_LINKLOCAL, "Link Local" }, 347190207Srpaulo { LS_SCOPE_AREA, "Area Local" }, 348190207Srpaulo { LS_SCOPE_AS, "Domain Wide" }, 349190207Srpaulo { 0, NULL } 350190207Srpaulo}; 35156893Sfenner 352276788Sdelphijstatic const struct tok ospf6_dd_flag_values[] = { 353190207Srpaulo { OSPF6_DB_INIT, "Init" }, 354190207Srpaulo { OSPF6_DB_MORE, "More" }, 355190207Srpaulo { OSPF6_DB_MASTER, "Master" }, 356276788Sdelphij { OSPF6_DB_M6, "IPv6 MTU" }, 357190207Srpaulo { 0, NULL } 358190207Srpaulo}; 359190207Srpaulo 360276788Sdelphijstatic const struct tok ospf6_lsa_prefix_option_values[] = { 361190207Srpaulo { LSA_PREFIX_OPT_NU, "No Unicast" }, 362190207Srpaulo { LSA_PREFIX_OPT_LA, "Local address" }, 363276788Sdelphij { LSA_PREFIX_OPT_MC, "Deprecated" }, 364190207Srpaulo { LSA_PREFIX_OPT_P, "Propagate" }, 365190207Srpaulo { LSA_PREFIX_OPT_DN, "Down" }, 366190207Srpaulo { 0, NULL } 367190207Srpaulo}; 368190207Srpaulo 369276788Sdelphijstatic const struct tok ospf6_auth_type_str[] = { 370276788Sdelphij { OSPF6_AUTH_TYPE_HMAC, "HMAC" }, 371276788Sdelphij { 0, NULL } 372276788Sdelphij}; 373190207Srpaulo 37456893Sfennerstatic void 375276788Sdelphijospf6_print_ls_type(netdissect_options *ndo, 376276788Sdelphij register u_int ls_type, register const rtrid_t *ls_stateid) 37756893Sfenner{ 378276788Sdelphij ND_PRINT((ndo, "\n\t %s LSA (%d), %s Scope%s, LSA-ID %s", 379190207Srpaulo tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK), 380190207Srpaulo ls_type & LS_TYPE_MASK, 381190207Srpaulo tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK), 382190207Srpaulo ls_type &0x8000 ? ", transitive" : "", /* U-bit */ 383276788Sdelphij ipaddr_string(ndo, ls_stateid))); 38456893Sfenner} 38556893Sfenner 38656893Sfennerstatic int 387276788Sdelphijospf6_print_lshdr(netdissect_options *ndo, 388276788Sdelphij register const struct lsa6_hdr *lshp, const u_char *dataend) 38956893Sfenner{ 390313537Sglebius if ((const u_char *)(lshp + 1) > dataend) 391276788Sdelphij goto trunc; 392356341Scy ND_TCHECK(lshp->ls_length); /* last field of struct lsa6_hdr */ 39356893Sfenner 394276788Sdelphij ND_PRINT((ndo, "\n\t Advertising Router %s, seq 0x%08x, age %us, length %u", 395276788Sdelphij ipaddr_string(ndo, &lshp->ls_router), 396190207Srpaulo EXTRACT_32BITS(&lshp->ls_seq), 397190207Srpaulo EXTRACT_16BITS(&lshp->ls_age), 398276788Sdelphij EXTRACT_16BITS(&lshp->ls_length)-(u_int)sizeof(struct lsa6_hdr))); 399190207Srpaulo 400276788Sdelphij ospf6_print_ls_type(ndo, EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid); 401190207Srpaulo 40256893Sfenner return (0); 40356893Sfennertrunc: 40456893Sfenner return (1); 40556893Sfenner} 40656893Sfenner 40756893Sfennerstatic int 408276788Sdelphijospf6_print_lsaprefix(netdissect_options *ndo, 409276788Sdelphij const uint8_t *tptr, u_int lsa_length) 41056893Sfenner{ 411313537Sglebius const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr; 412190207Srpaulo u_int wordlen; 41356893Sfenner struct in6_addr prefix; 41456893Sfenner 415276788Sdelphij if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES) 416241235Sdelphij goto trunc; 417276788Sdelphij lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES; 418276788Sdelphij ND_TCHECK2(*lsapp, sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES); 419190207Srpaulo wordlen = (lsapp->lsa_p_len + 31) / 32; 420190207Srpaulo if (wordlen * 4 > sizeof(struct in6_addr)) { 421276788Sdelphij ND_PRINT((ndo, " bogus prefixlen /%d", lsapp->lsa_p_len)); 42256893Sfenner goto trunc; 42356893Sfenner } 424241235Sdelphij if (lsa_length < wordlen * 4) 425241235Sdelphij goto trunc; 426241235Sdelphij lsa_length -= wordlen * 4; 427276788Sdelphij ND_TCHECK2(lsapp->lsa_p_prefix, wordlen * 4); 42856893Sfenner memset(&prefix, 0, sizeof(prefix)); 429190207Srpaulo memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4); 430276788Sdelphij ND_PRINT((ndo, "\n\t\t%s/%d", ip6addr_string(ndo, &prefix), 431276788Sdelphij lsapp->lsa_p_len)); 432190207Srpaulo if (lsapp->lsa_p_opt) { 433276788Sdelphij ND_PRINT((ndo, ", Options [%s]", 434190207Srpaulo bittok2str(ospf6_lsa_prefix_option_values, 435276788Sdelphij "none", lsapp->lsa_p_opt))); 436190207Srpaulo } 437276788Sdelphij ND_PRINT((ndo, ", metric %u", EXTRACT_16BITS(&lsapp->lsa_p_metric))); 438276788Sdelphij return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4; 43956893Sfenner 44056893Sfennertrunc: 44156893Sfenner return -1; 44256893Sfenner} 44356893Sfenner 44456893Sfenner 44556893Sfenner/* 44656893Sfenner * Print a single link state advertisement. If truncated return 1, else 0. 44756893Sfenner */ 44856893Sfennerstatic int 449276788Sdelphijospf6_print_lsa(netdissect_options *ndo, 450276788Sdelphij register const struct lsa6 *lsap, const u_char *dataend) 45156893Sfenner{ 452190207Srpaulo register const struct rlalink6 *rlp; 45356893Sfenner#if 0 45456893Sfenner register const struct tos_metric *tosp; 45556893Sfenner#endif 45656893Sfenner register const rtrid_t *ap; 45756893Sfenner#if 0 45856893Sfenner register const struct aslametric *almp; 45956893Sfenner register const struct mcla *mcp; 46056893Sfenner#endif 46156893Sfenner register const struct llsa *llsap; 462190207Srpaulo register const struct lsa6_prefix *lsapp; 46356893Sfenner#if 0 464276788Sdelphij register const uint32_t *lp; 46556893Sfenner#endif 466190207Srpaulo register u_int prefixes; 467241235Sdelphij register int bytelen; 468241235Sdelphij register u_int length, lsa_length; 469276788Sdelphij uint32_t flags32; 470276788Sdelphij const uint8_t *tptr; 47156893Sfenner 472276788Sdelphij if (ospf6_print_lshdr(ndo, &lsap->ls_hdr, dataend)) 47356893Sfenner return (1); 474276788Sdelphij ND_TCHECK(lsap->ls_hdr.ls_length); 475190207Srpaulo length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length); 476241235Sdelphij 477241235Sdelphij /* 478241235Sdelphij * The LSA length includes the length of the header; 479241235Sdelphij * it must have a value that's at least that length. 480241235Sdelphij * If it does, find the length of what follows the 481241235Sdelphij * header. 482241235Sdelphij */ 483313537Sglebius if (length < sizeof(struct lsa6_hdr) || (const u_char *)lsap + length > dataend) 484241235Sdelphij return (1); 485190207Srpaulo lsa_length = length - sizeof(struct lsa6_hdr); 486313537Sglebius tptr = (const uint8_t *)lsap+sizeof(struct lsa6_hdr); 487190207Srpaulo 488127668Sbms switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { 48956893Sfenner case LS_TYPE_ROUTER | LS_SCOPE_AREA: 490241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options)) 491241235Sdelphij return (1); 492241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options); 493276788Sdelphij ND_TCHECK(lsap->lsa_un.un_rla.rla_options); 494276788Sdelphij ND_PRINT((ndo, "\n\t Options [%s]", 495276788Sdelphij bittok2str(ospf6_option_values, "none", 496276788Sdelphij EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options)))); 497276788Sdelphij ND_PRINT((ndo, ", RLA-Flags [%s]", 498276788Sdelphij bittok2str(ospf6_rla_flag_values, "none", 499276788Sdelphij lsap->lsa_un.un_rla.rla_flags))); 500190207Srpaulo 50156893Sfenner rlp = lsap->lsa_un.un_rla.rla_link; 502241235Sdelphij while (lsa_length != 0) { 503241235Sdelphij if (lsa_length < sizeof (*rlp)) 504241235Sdelphij return (1); 505241235Sdelphij lsa_length -= sizeof (*rlp); 506276788Sdelphij ND_TCHECK(*rlp); 50756893Sfenner switch (rlp->link_type) { 50856893Sfenner 50956893Sfenner case RLA_TYPE_VIRTUAL: 510276788Sdelphij ND_PRINT((ndo, "\n\t Virtual Link: Neighbor Router-ID %s" 511190207Srpaulo "\n\t Neighbor Interface-ID %s, Interface %s", 512276788Sdelphij ipaddr_string(ndo, &rlp->link_nrtid), 513276788Sdelphij ipaddr_string(ndo, &rlp->link_nifid), 514276788Sdelphij ipaddr_string(ndo, &rlp->link_ifid))); 515190207Srpaulo break; 51656893Sfenner 51756893Sfenner case RLA_TYPE_ROUTER: 518276788Sdelphij ND_PRINT((ndo, "\n\t Neighbor Router-ID %s" 519190207Srpaulo "\n\t Neighbor Interface-ID %s, Interface %s", 520276788Sdelphij ipaddr_string(ndo, &rlp->link_nrtid), 521276788Sdelphij ipaddr_string(ndo, &rlp->link_nifid), 522276788Sdelphij ipaddr_string(ndo, &rlp->link_ifid))); 52356893Sfenner break; 52456893Sfenner 52556893Sfenner case RLA_TYPE_TRANSIT: 526276788Sdelphij ND_PRINT((ndo, "\n\t Neighbor Network-ID %s" 527190207Srpaulo "\n\t Neighbor Interface-ID %s, Interface %s", 528276788Sdelphij ipaddr_string(ndo, &rlp->link_nrtid), 529276788Sdelphij ipaddr_string(ndo, &rlp->link_nifid), 530276788Sdelphij ipaddr_string(ndo, &rlp->link_ifid))); 53156893Sfenner break; 53256893Sfenner 53356893Sfenner default: 534276788Sdelphij ND_PRINT((ndo, "\n\t Unknown Router Links Type 0x%02x", 535276788Sdelphij rlp->link_type)); 53656893Sfenner return (0); 53756893Sfenner } 538276788Sdelphij ND_PRINT((ndo, ", metric %d", EXTRACT_16BITS(&rlp->link_metric))); 53956893Sfenner rlp++; 54056893Sfenner } 54156893Sfenner break; 54256893Sfenner 54356893Sfenner case LS_TYPE_NETWORK | LS_SCOPE_AREA: 544241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options)) 545241235Sdelphij return (1); 546241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options); 547276788Sdelphij ND_TCHECK(lsap->lsa_un.un_nla.nla_options); 548276788Sdelphij ND_PRINT((ndo, "\n\t Options [%s]", 549276788Sdelphij bittok2str(ospf6_option_values, "none", 550276788Sdelphij EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options)))); 551241235Sdelphij 552276788Sdelphij ND_PRINT((ndo, "\n\t Connected Routers:")); 55356893Sfenner ap = lsap->lsa_un.un_nla.nla_router; 554241235Sdelphij while (lsa_length != 0) { 555241235Sdelphij if (lsa_length < sizeof (*ap)) 556241235Sdelphij return (1); 557241235Sdelphij lsa_length -= sizeof (*ap); 558276788Sdelphij ND_TCHECK(*ap); 559276788Sdelphij ND_PRINT((ndo, "\n\t\t%s", ipaddr_string(ndo, ap))); 56056893Sfenner ++ap; 56156893Sfenner } 56256893Sfenner break; 56356893Sfenner 56456893Sfenner case LS_TYPE_INTER_AP | LS_SCOPE_AREA: 565241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric)) 566241235Sdelphij return (1); 567241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric); 568276788Sdelphij ND_TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); 569276788Sdelphij ND_PRINT((ndo, ", metric %u", 570276788Sdelphij EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC)); 571241235Sdelphij 572313537Sglebius tptr = (const uint8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix; 573241235Sdelphij while (lsa_length != 0) { 574276788Sdelphij bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 575241235Sdelphij if (bytelen < 0) 57656893Sfenner goto trunc; 577241235Sdelphij lsa_length -= bytelen; 578241235Sdelphij tptr += bytelen; 57956893Sfenner } 58056893Sfenner break; 581241235Sdelphij 582241235Sdelphij case LS_TYPE_ASE | LS_SCOPE_AS: 583241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric)) 584241235Sdelphij return (1); 585241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric); 586276788Sdelphij ND_TCHECK(lsap->lsa_un.un_asla.asla_metric); 587127668Sbms flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); 588276788Sdelphij ND_PRINT((ndo, "\n\t Flags [%s]", 589276788Sdelphij bittok2str(ospf6_asla_flag_values, "none", flags32))); 590276788Sdelphij ND_PRINT((ndo, " metric %u", 591127668Sbms EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & 592276788Sdelphij ASLA_MASK_METRIC)); 593241235Sdelphij 594313537Sglebius tptr = (const uint8_t *)lsap->lsa_un.un_asla.asla_prefix; 595313537Sglebius lsapp = (const struct lsa6_prefix *)tptr; 596276788Sdelphij bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 597190207Srpaulo if (bytelen < 0) 59875115Sfenner goto trunc; 599241235Sdelphij lsa_length -= bytelen; 600241235Sdelphij tptr += bytelen; 601241235Sdelphij 602241235Sdelphij if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { 603313537Sglebius const struct in6_addr *fwdaddr6; 60456893Sfenner 605313537Sglebius fwdaddr6 = (const struct in6_addr *)tptr; 606241235Sdelphij if (lsa_length < sizeof (*fwdaddr6)) 607241235Sdelphij return (1); 608241235Sdelphij lsa_length -= sizeof (*fwdaddr6); 609276788Sdelphij ND_TCHECK(*fwdaddr6); 610276788Sdelphij ND_PRINT((ndo, " forward %s", 611276788Sdelphij ip6addr_string(ndo, fwdaddr6))); 612241235Sdelphij tptr += sizeof(*fwdaddr6); 613241235Sdelphij } 61475115Sfenner 615241235Sdelphij if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { 616276788Sdelphij if (lsa_length < sizeof (uint32_t)) 617241235Sdelphij return (1); 618276788Sdelphij lsa_length -= sizeof (uint32_t); 619313537Sglebius ND_TCHECK(*(const uint32_t *)tptr); 620276788Sdelphij ND_PRINT((ndo, " tag %s", 621313537Sglebius ipaddr_string(ndo, (const uint32_t *)tptr))); 622276788Sdelphij tptr += sizeof(uint32_t); 623241235Sdelphij } 62475115Sfenner 625241235Sdelphij if (lsapp->lsa_p_metric) { 626276788Sdelphij if (lsa_length < sizeof (uint32_t)) 627241235Sdelphij return (1); 628276788Sdelphij lsa_length -= sizeof (uint32_t); 629313537Sglebius ND_TCHECK(*(const uint32_t *)tptr); 630276788Sdelphij ND_PRINT((ndo, " RefLSID: %s", 631313537Sglebius ipaddr_string(ndo, (const uint32_t *)tptr))); 632276788Sdelphij tptr += sizeof(uint32_t); 63375115Sfenner } 63475115Sfenner break; 63556893Sfenner 63656893Sfenner case LS_TYPE_LINK: 63756893Sfenner /* Link LSA */ 63856893Sfenner llsap = &lsap->lsa_un.un_llsa; 639241235Sdelphij if (lsa_length < sizeof (llsap->llsa_priandopt)) 640241235Sdelphij return (1); 641241235Sdelphij lsa_length -= sizeof (llsap->llsa_priandopt); 642276788Sdelphij ND_TCHECK(llsap->llsa_priandopt); 643276788Sdelphij ND_PRINT((ndo, "\n\t Options [%s]", 644276788Sdelphij bittok2str(ospf6_option_values, "none", 645276788Sdelphij EXTRACT_32BITS(&llsap->llsa_options)))); 646241235Sdelphij 647241235Sdelphij if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) 648241235Sdelphij return (1); 649241235Sdelphij lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); 650327234Semaste ND_TCHECK(llsap->llsa_nprefix); 651190207Srpaulo prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); 652276788Sdelphij ND_PRINT((ndo, "\n\t Priority %d, Link-local address %s, Prefixes %d:", 653190207Srpaulo llsap->llsa_priority, 654276788Sdelphij ip6addr_string(ndo, &llsap->llsa_lladdr), 655276788Sdelphij prefixes)); 656190207Srpaulo 657313537Sglebius tptr = (const uint8_t *)llsap->llsa_prefix; 658241235Sdelphij while (prefixes > 0) { 659276788Sdelphij bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 660241235Sdelphij if (bytelen < 0) 661241235Sdelphij goto trunc; 662241235Sdelphij prefixes--; 663241235Sdelphij lsa_length -= bytelen; 664241235Sdelphij tptr += bytelen; 665241235Sdelphij } 66656893Sfenner break; 66756893Sfenner 66856893Sfenner case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: 66956893Sfenner /* Intra-Area-Prefix LSA */ 670241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid)) 671241235Sdelphij return (1); 672241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid); 673276788Sdelphij ND_TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); 674276788Sdelphij ospf6_print_ls_type(ndo, 675127668Sbms EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), 676190207Srpaulo &lsap->lsa_un.un_intra_ap.intra_ap_lsid); 677241235Sdelphij 678241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix)) 679241235Sdelphij return (1); 680241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 681276788Sdelphij ND_TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 682190207Srpaulo prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 683276788Sdelphij ND_PRINT((ndo, "\n\t Prefixes %d:", prefixes)); 68456893Sfenner 685313537Sglebius tptr = (const uint8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; 686241235Sdelphij while (prefixes > 0) { 687276788Sdelphij bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 688241235Sdelphij if (bytelen < 0) 689241235Sdelphij goto trunc; 690241235Sdelphij prefixes--; 691241235Sdelphij lsa_length -= bytelen; 692241235Sdelphij tptr += bytelen; 693241235Sdelphij } 69456893Sfenner break; 69556893Sfenner 696190207Srpaulo case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: 697276788Sdelphij if (ospf_print_grace_lsa(ndo, tptr, lsa_length) == -1) { 698190207Srpaulo return 1; 699190207Srpaulo } 700241235Sdelphij break; 701190207Srpaulo 702190207Srpaulo case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: 703276788Sdelphij if (ospf_print_te_lsa(ndo, tptr, lsa_length) == -1) { 704241235Sdelphij return 1; 705241235Sdelphij } 706241235Sdelphij break; 707190207Srpaulo 70856893Sfenner default: 709276788Sdelphij if(!print_unknown_data(ndo,tptr, 710241235Sdelphij "\n\t ", 711241235Sdelphij lsa_length)) { 712241235Sdelphij return (1); 713241235Sdelphij } 714241235Sdelphij break; 71556893Sfenner } 71656893Sfenner 71756893Sfenner return (0); 71856893Sfennertrunc: 71956893Sfenner return (1); 72056893Sfenner} 72156893Sfenner 72256893Sfennerstatic int 723276788Sdelphijospf6_decode_v3(netdissect_options *ndo, 724276788Sdelphij register const struct ospf6hdr *op, 725276788Sdelphij register const u_char *dataend) 72656893Sfenner{ 72756893Sfenner register const rtrid_t *ap; 728190207Srpaulo register const struct lsr6 *lsrp; 729190207Srpaulo register const struct lsa6_hdr *lshp; 730190207Srpaulo register const struct lsa6 *lsap; 73156893Sfenner register int i; 73256893Sfenner 73356893Sfenner switch (op->ospf6_type) { 73456893Sfenner 735276788Sdelphij case OSPF_TYPE_HELLO: { 736313537Sglebius register const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); 73756893Sfenner 738327234Semaste ND_TCHECK_32BITS(&hellop->hello_options); 739276788Sdelphij ND_PRINT((ndo, "\n\tOptions [%s]", 740276788Sdelphij bittok2str(ospf6_option_values, "none", 741276788Sdelphij EXTRACT_32BITS(&hellop->hello_options)))); 742190207Srpaulo 743276788Sdelphij ND_TCHECK(hellop->hello_deadint); 744276788Sdelphij ND_PRINT((ndo, "\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u", 745276788Sdelphij EXTRACT_16BITS(&hellop->hello_helloint), 746276788Sdelphij EXTRACT_16BITS(&hellop->hello_deadint), 747276788Sdelphij ipaddr_string(ndo, &hellop->hello_ifid), 748276788Sdelphij hellop->hello_priority)); 749276788Sdelphij 750276788Sdelphij ND_TCHECK(hellop->hello_dr); 751276788Sdelphij if (EXTRACT_32BITS(&hellop->hello_dr) != 0) 752276788Sdelphij ND_PRINT((ndo, "\n\t Designated Router %s", 753276788Sdelphij ipaddr_string(ndo, &hellop->hello_dr))); 754276788Sdelphij ND_TCHECK(hellop->hello_bdr); 755276788Sdelphij if (EXTRACT_32BITS(&hellop->hello_bdr) != 0) 756276788Sdelphij ND_PRINT((ndo, ", Backup Designated Router %s", 757276788Sdelphij ipaddr_string(ndo, &hellop->hello_bdr))); 758276788Sdelphij if (ndo->ndo_vflag > 1) { 759276788Sdelphij ND_PRINT((ndo, "\n\t Neighbor List:")); 760276788Sdelphij ap = hellop->hello_neighbor; 761313537Sglebius while ((const u_char *)ap < dataend) { 762276788Sdelphij ND_TCHECK(*ap); 763276788Sdelphij ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap))); 76456893Sfenner ++ap; 76556893Sfenner } 76656893Sfenner } 76756893Sfenner break; /* HELLO */ 768276788Sdelphij } 76956893Sfenner 770276788Sdelphij case OSPF_TYPE_DD: { 771313537Sglebius register const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); 772190207Srpaulo 773276788Sdelphij ND_TCHECK(ddp->db_options); 774276788Sdelphij ND_PRINT((ndo, "\n\tOptions [%s]", 775276788Sdelphij bittok2str(ospf6_option_values, "none", 776276788Sdelphij EXTRACT_32BITS(&ddp->db_options)))); 777276788Sdelphij ND_TCHECK(ddp->db_flags); 778276788Sdelphij ND_PRINT((ndo, ", DD Flags [%s]", 779276788Sdelphij bittok2str(ospf6_dd_flag_values,"none",ddp->db_flags))); 78056893Sfenner 781276788Sdelphij ND_TCHECK(ddp->db_seq); 782276788Sdelphij ND_PRINT((ndo, ", MTU %u, DD-Sequence 0x%08x", 783276788Sdelphij EXTRACT_16BITS(&ddp->db_mtu), 784276788Sdelphij EXTRACT_32BITS(&ddp->db_seq))); 785276788Sdelphij if (ndo->ndo_vflag > 1) { 786276788Sdelphij /* Print all the LS adv's */ 787276788Sdelphij lshp = ddp->db_lshdr; 788313537Sglebius while ((const u_char *)lshp < dataend) { 789276788Sdelphij if (ospf6_print_lshdr(ndo, lshp++, dataend)) 790276788Sdelphij goto trunc; 791276788Sdelphij } 792276788Sdelphij } 79356893Sfenner break; 794276788Sdelphij } 79556893Sfenner 796190207Srpaulo case OSPF_TYPE_LS_REQ: 797276788Sdelphij if (ndo->ndo_vflag > 1) { 798313537Sglebius lsrp = (const struct lsr6 *)((const uint8_t *)op + OSPF6HDR_LEN); 799313537Sglebius while ((const u_char *)lsrp < dataend) { 800276788Sdelphij ND_TCHECK(*lsrp); 801276788Sdelphij ND_PRINT((ndo, "\n\t Advertising Router %s", 802276788Sdelphij ipaddr_string(ndo, &lsrp->ls_router))); 803276788Sdelphij ospf6_print_ls_type(ndo, EXTRACT_16BITS(&lsrp->ls_type), 804190207Srpaulo &lsrp->ls_stateid); 80556893Sfenner ++lsrp; 80656893Sfenner } 80756893Sfenner } 80856893Sfenner break; 80956893Sfenner 810190207Srpaulo case OSPF_TYPE_LS_UPDATE: 811276788Sdelphij if (ndo->ndo_vflag > 1) { 812313537Sglebius register const struct lsu6 *lsup = (const struct lsu6 *)((const uint8_t *)op + OSPF6HDR_LEN); 813276788Sdelphij 814276788Sdelphij ND_TCHECK(lsup->lsu_count); 815276788Sdelphij i = EXTRACT_32BITS(&lsup->lsu_count); 816276788Sdelphij lsap = lsup->lsu_lsa; 817313537Sglebius while ((const u_char *)lsap < dataend && i--) { 818276788Sdelphij if (ospf6_print_lsa(ndo, lsap, dataend)) 81956893Sfenner goto trunc; 820313537Sglebius lsap = (const struct lsa6 *)((const u_char *)lsap + 821127668Sbms EXTRACT_16BITS(&lsap->ls_hdr.ls_length)); 82256893Sfenner } 82356893Sfenner } 82456893Sfenner break; 82556893Sfenner 826190207Srpaulo case OSPF_TYPE_LS_ACK: 827276788Sdelphij if (ndo->ndo_vflag > 1) { 828313537Sglebius lshp = (const struct lsa6_hdr *)((const uint8_t *)op + OSPF6HDR_LEN); 829313537Sglebius while ((const u_char *)lshp < dataend) { 830276788Sdelphij if (ospf6_print_lshdr(ndo, lshp++, dataend)) 831276788Sdelphij goto trunc; 83256893Sfenner } 83356893Sfenner } 83456893Sfenner break; 83556893Sfenner 83656893Sfenner default: 83756893Sfenner break; 83856893Sfenner } 83956893Sfenner return (0); 84056893Sfennertrunc: 84156893Sfenner return (1); 84256893Sfenner} 84356893Sfenner 844276788Sdelphij/* RFC5613 Section 2.2 (w/o the TLVs) */ 845276788Sdelphijstatic int 846276788Sdelphijospf6_print_lls(netdissect_options *ndo, 847276788Sdelphij const u_char *cp, const u_int len) 848276788Sdelphij{ 849276788Sdelphij uint16_t llsdatalen; 850276788Sdelphij 851276788Sdelphij if (len == 0) 852276788Sdelphij return 0; 853276788Sdelphij if (len < OSPF_LLS_HDRLEN) 854276788Sdelphij goto trunc; 855276788Sdelphij /* Checksum */ 856276788Sdelphij ND_TCHECK2(*cp, 2); 857276788Sdelphij ND_PRINT((ndo, "\n\tLLS Checksum 0x%04x", EXTRACT_16BITS(cp))); 858276788Sdelphij cp += 2; 859276788Sdelphij /* LLS Data Length */ 860276788Sdelphij ND_TCHECK2(*cp, 2); 861276788Sdelphij llsdatalen = EXTRACT_16BITS(cp); 862276788Sdelphij ND_PRINT((ndo, ", Data Length %u", llsdatalen)); 863276788Sdelphij if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len) 864276788Sdelphij goto trunc; 865276788Sdelphij cp += 2; 866276788Sdelphij /* LLS TLVs */ 867276788Sdelphij ND_TCHECK2(*cp, llsdatalen - OSPF_LLS_HDRLEN); 868276788Sdelphij /* FIXME: code in print-ospf.c can be reused to decode the TLVs */ 869276788Sdelphij 870276788Sdelphij return llsdatalen; 871276788Sdelphijtrunc: 872276788Sdelphij return -1; 873276788Sdelphij} 874276788Sdelphij 875276788Sdelphij/* RFC6506 Section 4.1 */ 876276788Sdelphijstatic int 877276788Sdelphijospf6_decode_at(netdissect_options *ndo, 878276788Sdelphij const u_char *cp, const u_int len) 879276788Sdelphij{ 880276788Sdelphij uint16_t authdatalen; 881276788Sdelphij 882276788Sdelphij if (len == 0) 883276788Sdelphij return 0; 884276788Sdelphij if (len < OSPF6_AT_HDRLEN) 885276788Sdelphij goto trunc; 886276788Sdelphij /* Authentication Type */ 887276788Sdelphij ND_TCHECK2(*cp, 2); 888276788Sdelphij ND_PRINT((ndo, "\n\tAuthentication Type %s", tok2str(ospf6_auth_type_str, "unknown (0x%04x)", EXTRACT_16BITS(cp)))); 889276788Sdelphij cp += 2; 890276788Sdelphij /* Auth Data Len */ 891276788Sdelphij ND_TCHECK2(*cp, 2); 892276788Sdelphij authdatalen = EXTRACT_16BITS(cp); 893276788Sdelphij ND_PRINT((ndo, ", Length %u", authdatalen)); 894276788Sdelphij if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len) 895276788Sdelphij goto trunc; 896276788Sdelphij cp += 2; 897276788Sdelphij /* Reserved */ 898276788Sdelphij ND_TCHECK2(*cp, 2); 899276788Sdelphij cp += 2; 900276788Sdelphij /* Security Association ID */ 901276788Sdelphij ND_TCHECK2(*cp, 2); 902276788Sdelphij ND_PRINT((ndo, ", SAID %u", EXTRACT_16BITS(cp))); 903276788Sdelphij cp += 2; 904276788Sdelphij /* Cryptographic Sequence Number (High-Order 32 Bits) */ 905276788Sdelphij ND_TCHECK2(*cp, 4); 906276788Sdelphij ND_PRINT((ndo, ", CSN 0x%08x", EXTRACT_32BITS(cp))); 907276788Sdelphij cp += 4; 908276788Sdelphij /* Cryptographic Sequence Number (Low-Order 32 Bits) */ 909276788Sdelphij ND_TCHECK2(*cp, 4); 910276788Sdelphij ND_PRINT((ndo, ":%08x", EXTRACT_32BITS(cp))); 911276788Sdelphij cp += 4; 912276788Sdelphij /* Authentication Data */ 913276788Sdelphij ND_TCHECK2(*cp, authdatalen - OSPF6_AT_HDRLEN); 914276788Sdelphij if (ndo->ndo_vflag > 1) 915276788Sdelphij print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN); 916276788Sdelphij return 0; 917276788Sdelphij 918276788Sdelphijtrunc: 919276788Sdelphij return 1; 920276788Sdelphij} 921276788Sdelphij 922276788Sdelphij/* The trailing data may include LLS and/or AT data (in this specific order). 923276788Sdelphij * LLS data may be present only in Hello and DBDesc packets with the L-bit set. 924276788Sdelphij * AT data may be present in Hello and DBDesc packets with the AT-bit set or in 925276788Sdelphij * any other packet type, thus decode the AT data regardless of the AT-bit. 926276788Sdelphij */ 927276788Sdelphijstatic int 928276788Sdelphijospf6_decode_v3_trailer(netdissect_options *ndo, 929276788Sdelphij const struct ospf6hdr *op, const u_char *cp, const unsigned len) 930276788Sdelphij{ 931276788Sdelphij int llslen = 0; 932276788Sdelphij int lls_hello = 0; 933276788Sdelphij int lls_dd = 0; 934276788Sdelphij 935276788Sdelphij if (op->ospf6_type == OSPF_TYPE_HELLO) { 936313537Sglebius const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); 937327234Semaste ND_TCHECK(hellop->hello_options); 938276788Sdelphij if (EXTRACT_32BITS(&hellop->hello_options) & OSPF6_OPTION_L) 939276788Sdelphij lls_hello = 1; 940276788Sdelphij } else if (op->ospf6_type == OSPF_TYPE_DD) { 941313537Sglebius const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); 942327234Semaste ND_TCHECK(ddp->db_options); 943276788Sdelphij if (EXTRACT_32BITS(&ddp->db_options) & OSPF6_OPTION_L) 944276788Sdelphij lls_dd = 1; 945276788Sdelphij } 946276788Sdelphij if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(ndo, cp, len)) < 0) 947276788Sdelphij goto trunc; 948276788Sdelphij return ospf6_decode_at(ndo, cp + llslen, len - llslen); 949276788Sdelphij 950276788Sdelphijtrunc: 951276788Sdelphij return 1; 952276788Sdelphij} 953276788Sdelphij 95456893Sfennervoid 955276788Sdelphijospf6_print(netdissect_options *ndo, 956276788Sdelphij register const u_char *bp, register u_int length) 95756893Sfenner{ 95856893Sfenner register const struct ospf6hdr *op; 95956893Sfenner register const u_char *dataend; 96056893Sfenner register const char *cp; 961276788Sdelphij uint16_t datalen; 96256893Sfenner 963313537Sglebius op = (const struct ospf6hdr *)bp; 96456893Sfenner 96556893Sfenner /* If the type is valid translate it, or just print the type */ 96656893Sfenner /* value. If it's not valid, say so and return */ 967276788Sdelphij ND_TCHECK(op->ospf6_type); 968276788Sdelphij cp = tok2str(ospf6_type_values, "unknown packet type (%u)", op->ospf6_type); 969276788Sdelphij ND_PRINT((ndo, "OSPFv%u, %s, length %d", op->ospf6_version, cp, length)); 970190207Srpaulo if (*cp == 'u') { 97156893Sfenner return; 972276788Sdelphij } 97356893Sfenner 974276788Sdelphij if(!ndo->ndo_vflag) { /* non verbose - so lets bail out here */ 975276788Sdelphij return; 976276788Sdelphij } 977190207Srpaulo 978276788Sdelphij /* OSPFv3 data always comes first and optional trailing data may follow. */ 979276788Sdelphij ND_TCHECK(op->ospf6_len); 980276788Sdelphij datalen = EXTRACT_16BITS(&op->ospf6_len); 981276788Sdelphij if (datalen > length) { 982276788Sdelphij ND_PRINT((ndo, " [len %d]", datalen)); 98356893Sfenner return; 98456893Sfenner } 985276788Sdelphij dataend = bp + datalen; 98656893Sfenner 987276788Sdelphij ND_TCHECK(op->ospf6_routerid); 988276788Sdelphij ND_PRINT((ndo, "\n\tRouter-ID %s", ipaddr_string(ndo, &op->ospf6_routerid))); 98956893Sfenner 990276788Sdelphij ND_TCHECK(op->ospf6_areaid); 991276788Sdelphij if (EXTRACT_32BITS(&op->ospf6_areaid) != 0) 992276788Sdelphij ND_PRINT((ndo, ", Area %s", ipaddr_string(ndo, &op->ospf6_areaid))); 99356893Sfenner else 994276788Sdelphij ND_PRINT((ndo, ", Backbone Area")); 995276788Sdelphij ND_TCHECK(op->ospf6_instanceid); 99656893Sfenner if (op->ospf6_instanceid) 997276788Sdelphij ND_PRINT((ndo, ", Instance %u", op->ospf6_instanceid)); 99856893Sfenner 99956893Sfenner /* Do rest according to version. */ 100056893Sfenner switch (op->ospf6_version) { 100156893Sfenner 100256893Sfenner case 3: 100356893Sfenner /* ospf version 3 */ 1004276788Sdelphij if (ospf6_decode_v3(ndo, op, dataend) || 1005276788Sdelphij ospf6_decode_v3_trailer(ndo, op, dataend, length - datalen)) 100656893Sfenner goto trunc; 100756893Sfenner break; 100856893Sfenner } /* end switch on version */ 100956893Sfenner 101056893Sfenner return; 101156893Sfennertrunc: 1012276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 101356893Sfenner} 1014