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