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*3340d773SGleb Smirnoff /* \summary: IPv6 Open Shortest Path First (OSPFv3) printer */ 25*3340d773SGleb Smirnoff 26b0453382SBill Fenner #ifdef HAVE_CONFIG_H 27b0453382SBill Fenner #include "config.h" 28b0453382SBill Fenner #endif 29b0453382SBill Fenner 30*3340d773SGleb Smirnoff #include <netdissect-stdinc.h> 31b0453382SBill Fenner 32b0453382SBill Fenner #include <string.h> 33b0453382SBill Fenner 34*3340d773SGleb Smirnoff #include "netdissect.h" 35b0453382SBill Fenner #include "addrtoname.h" 365b0fe478SBruce M Simpson #include "extract.h" 37b0453382SBill Fenner 38a5779b6eSRui Paulo #include "ospf.h" 393c602fabSXin LI 403c602fabSXin LI #define OSPF_TYPE_HELLO 1 /* Hello */ 413c602fabSXin LI #define OSPF_TYPE_DD 2 /* Database Description */ 423c602fabSXin LI #define OSPF_TYPE_LS_REQ 3 /* Link State Request */ 433c602fabSXin LI #define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */ 443c602fabSXin LI #define OSPF_TYPE_LS_ACK 5 /* Link State Ack */ 453c602fabSXin LI 463c602fabSXin LI /* Options *_options */ 473c602fabSXin LI #define OSPF6_OPTION_V6 0x01 /* V6 bit: A bit for peeping tom */ 483c602fabSXin LI #define OSPF6_OPTION_E 0x02 /* E bit: External routes advertised */ 493c602fabSXin LI #define OSPF6_OPTION_MC 0x04 /* MC bit: Multicast capable */ 503c602fabSXin LI #define OSPF6_OPTION_N 0x08 /* N bit: For type-7 LSA */ 513c602fabSXin LI #define OSPF6_OPTION_R 0x10 /* R bit: Router bit */ 523c602fabSXin LI #define OSPF6_OPTION_DC 0x20 /* DC bit: Demand circuits */ 533c602fabSXin LI /* The field is actually 24-bit (RFC5340 Section A.2). */ 543c602fabSXin LI #define OSPF6_OPTION_AF 0x0100 /* AF bit: Multiple address families */ 553c602fabSXin LI #define OSPF6_OPTION_L 0x0200 /* L bit: Link-local signaling (LLS) */ 563c602fabSXin LI #define OSPF6_OPTION_AT 0x0400 /* AT bit: Authentication trailer */ 573c602fabSXin LI 583c602fabSXin LI 593c602fabSXin LI /* db_flags */ 603c602fabSXin LI #define OSPF6_DB_INIT 0x04 /* */ 613c602fabSXin LI #define OSPF6_DB_MORE 0x02 623c602fabSXin LI #define OSPF6_DB_MASTER 0x01 633c602fabSXin LI #define OSPF6_DB_M6 0x10 /* IPv6 MTU */ 643c602fabSXin LI 653c602fabSXin LI /* ls_type */ 663c602fabSXin LI #define LS_TYPE_ROUTER 1 /* router link */ 673c602fabSXin LI #define LS_TYPE_NETWORK 2 /* network link */ 683c602fabSXin LI #define LS_TYPE_INTER_AP 3 /* Inter-Area-Prefix */ 693c602fabSXin LI #define LS_TYPE_INTER_AR 4 /* Inter-Area-Router */ 703c602fabSXin LI #define LS_TYPE_ASE 5 /* ASE */ 713c602fabSXin LI #define LS_TYPE_GROUP 6 /* Group membership */ 723c602fabSXin LI #define LS_TYPE_NSSA 7 /* NSSA */ 733c602fabSXin LI #define LS_TYPE_LINK 8 /* Link LSA */ 743c602fabSXin LI #define LS_TYPE_INTRA_AP 9 /* Intra-Area-Prefix */ 753c602fabSXin LI #define LS_TYPE_INTRA_ATE 10 /* Intra-Area-TE */ 763c602fabSXin LI #define LS_TYPE_GRACE 11 /* Grace LSA */ 773c602fabSXin LI #define LS_TYPE_RI 12 /* Router information */ 783c602fabSXin LI #define LS_TYPE_INTER_ASTE 13 /* Inter-AS-TE */ 793c602fabSXin LI #define LS_TYPE_L1VPN 14 /* L1VPN */ 803c602fabSXin LI #define LS_TYPE_MASK 0x1fff 813c602fabSXin LI 823c602fabSXin LI #define LS_SCOPE_LINKLOCAL 0x0000 833c602fabSXin LI #define LS_SCOPE_AREA 0x2000 843c602fabSXin LI #define LS_SCOPE_AS 0x4000 853c602fabSXin LI #define LS_SCOPE_MASK 0x6000 863c602fabSXin LI #define LS_SCOPE_U 0x8000 873c602fabSXin LI 883c602fabSXin LI /* rla_link.link_type */ 893c602fabSXin LI #define RLA_TYPE_ROUTER 1 /* point-to-point to another router */ 903c602fabSXin LI #define RLA_TYPE_TRANSIT 2 /* connection to transit network */ 913c602fabSXin LI #define RLA_TYPE_VIRTUAL 4 /* virtual link */ 923c602fabSXin LI 933c602fabSXin LI /* rla_flags */ 943c602fabSXin LI #define RLA_FLAG_B 0x01 953c602fabSXin LI #define RLA_FLAG_E 0x02 963c602fabSXin LI #define RLA_FLAG_V 0x04 973c602fabSXin LI #define RLA_FLAG_W 0x08 983c602fabSXin LI #define RLA_FLAG_N 0x10 993c602fabSXin LI 1003c602fabSXin LI /* lsa_prefix options */ 1013c602fabSXin LI #define LSA_PREFIX_OPT_NU 0x01 1023c602fabSXin LI #define LSA_PREFIX_OPT_LA 0x02 1033c602fabSXin LI #define LSA_PREFIX_OPT_MC 0x04 1043c602fabSXin LI #define LSA_PREFIX_OPT_P 0x08 1053c602fabSXin LI #define LSA_PREFIX_OPT_DN 0x10 1063c602fabSXin LI 1073c602fabSXin LI /* sla_tosmetric breakdown */ 1083c602fabSXin LI #define SLA_MASK_TOS 0x7f000000 1093c602fabSXin LI #define SLA_MASK_METRIC 0x00ffffff 1103c602fabSXin LI #define SLA_SHIFT_TOS 24 1113c602fabSXin LI 1123c602fabSXin LI /* asla_metric */ 1133c602fabSXin LI #define ASLA_FLAG_FWDADDR 0x02000000 1143c602fabSXin LI #define ASLA_FLAG_ROUTETAG 0x01000000 1153c602fabSXin LI #define ASLA_MASK_METRIC 0x00ffffff 1163c602fabSXin LI 1173c602fabSXin LI /* RFC6506 Section 4.1 */ 1183c602fabSXin LI #define OSPF6_AT_HDRLEN 16U 1193c602fabSXin LI #define OSPF6_AUTH_TYPE_HMAC 0x0001 1203c602fabSXin LI 1213c602fabSXin LI typedef uint32_t rtrid_t; 1223c602fabSXin LI 1233c602fabSXin LI /* link state advertisement header */ 1243c602fabSXin LI struct lsa6_hdr { 1253c602fabSXin LI uint16_t ls_age; 1263c602fabSXin LI uint16_t ls_type; 1273c602fabSXin LI rtrid_t ls_stateid; 1283c602fabSXin LI rtrid_t ls_router; 1293c602fabSXin LI uint32_t ls_seq; 1303c602fabSXin LI uint16_t ls_chksum; 1313c602fabSXin LI uint16_t ls_length; 1323c602fabSXin LI }; 1333c602fabSXin LI 1343c602fabSXin LI /* Length of an IPv6 address, in bytes. */ 1353c602fabSXin LI #define IPV6_ADDR_LEN_BYTES (128/8) 1363c602fabSXin LI 1373c602fabSXin LI struct lsa6_prefix { 1383c602fabSXin LI uint8_t lsa_p_len; 1393c602fabSXin LI uint8_t lsa_p_opt; 1403c602fabSXin LI uint16_t lsa_p_metric; 1413c602fabSXin LI uint8_t lsa_p_prefix[IPV6_ADDR_LEN_BYTES]; /* maximum length */ 1423c602fabSXin LI }; 1433c602fabSXin LI 1443c602fabSXin LI /* link state advertisement */ 1453c602fabSXin LI struct lsa6 { 1463c602fabSXin LI struct lsa6_hdr ls_hdr; 1473c602fabSXin LI 1483c602fabSXin LI /* Link state types */ 1493c602fabSXin LI union { 1503c602fabSXin LI /* Router links advertisements */ 1513c602fabSXin LI struct { 1523c602fabSXin LI union { 1533c602fabSXin LI uint8_t flg; 1543c602fabSXin LI uint32_t opt; 1553c602fabSXin LI } rla_flgandopt; 1563c602fabSXin LI #define rla_flags rla_flgandopt.flg 1573c602fabSXin LI #define rla_options rla_flgandopt.opt 1583c602fabSXin LI struct rlalink6 { 1593c602fabSXin LI uint8_t link_type; 1603c602fabSXin LI uint8_t link_zero[1]; 1613c602fabSXin LI uint16_t link_metric; 1623c602fabSXin LI uint32_t link_ifid; 1633c602fabSXin LI uint32_t link_nifid; 1643c602fabSXin LI rtrid_t link_nrtid; 1653c602fabSXin LI } rla_link[1]; /* may repeat */ 1663c602fabSXin LI } un_rla; 1673c602fabSXin LI 1683c602fabSXin LI /* Network links advertisements */ 1693c602fabSXin LI struct { 1703c602fabSXin LI uint32_t nla_options; 1713c602fabSXin LI rtrid_t nla_router[1]; /* may repeat */ 1723c602fabSXin LI } un_nla; 1733c602fabSXin LI 1743c602fabSXin LI /* Inter Area Prefix LSA */ 1753c602fabSXin LI struct { 1763c602fabSXin LI uint32_t inter_ap_metric; 1773c602fabSXin LI struct lsa6_prefix inter_ap_prefix[1]; 1783c602fabSXin LI } un_inter_ap; 1793c602fabSXin LI 1803c602fabSXin LI /* AS external links advertisements */ 1813c602fabSXin LI struct { 1823c602fabSXin LI uint32_t asla_metric; 1833c602fabSXin LI struct lsa6_prefix asla_prefix[1]; 1843c602fabSXin LI /* some optional fields follow */ 1853c602fabSXin LI } un_asla; 1863c602fabSXin LI 1873c602fabSXin LI #if 0 1883c602fabSXin LI /* Summary links advertisements */ 1893c602fabSXin LI struct { 1903c602fabSXin LI struct in_addr sla_mask; 1913c602fabSXin LI uint32_t sla_tosmetric[1]; /* may repeat */ 1923c602fabSXin LI } un_sla; 1933c602fabSXin LI 1943c602fabSXin LI /* Multicast group membership */ 1953c602fabSXin LI struct mcla { 1963c602fabSXin LI uint32_t mcla_vtype; 1973c602fabSXin LI struct in_addr mcla_vid; 1983c602fabSXin LI } un_mcla[1]; 1993c602fabSXin LI #endif 2003c602fabSXin LI 2013c602fabSXin LI /* Type 7 LSA */ 2023c602fabSXin LI 2033c602fabSXin LI /* Link LSA */ 2043c602fabSXin LI struct llsa { 2053c602fabSXin LI union { 2063c602fabSXin LI uint8_t pri; 2073c602fabSXin LI uint32_t opt; 2083c602fabSXin LI } llsa_priandopt; 2093c602fabSXin LI #define llsa_priority llsa_priandopt.pri 2103c602fabSXin LI #define llsa_options llsa_priandopt.opt 2113c602fabSXin LI struct in6_addr llsa_lladdr; 2123c602fabSXin LI uint32_t llsa_nprefix; 2133c602fabSXin LI struct lsa6_prefix llsa_prefix[1]; 2143c602fabSXin LI } un_llsa; 2153c602fabSXin LI 2163c602fabSXin LI /* Intra-Area-Prefix */ 2173c602fabSXin LI struct { 2183c602fabSXin LI uint16_t intra_ap_nprefix; 2193c602fabSXin LI uint16_t intra_ap_lstype; 2203c602fabSXin LI rtrid_t intra_ap_lsid; 2213c602fabSXin LI rtrid_t intra_ap_rtid; 2223c602fabSXin LI struct lsa6_prefix intra_ap_prefix[1]; 2233c602fabSXin LI } un_intra_ap; 2243c602fabSXin LI } lsa_un; 2253c602fabSXin LI }; 2263c602fabSXin LI 2273c602fabSXin LI /* 2283c602fabSXin LI * the main header 2293c602fabSXin LI */ 2303c602fabSXin LI struct ospf6hdr { 2313c602fabSXin LI uint8_t ospf6_version; 2323c602fabSXin LI uint8_t ospf6_type; 2333c602fabSXin LI uint16_t ospf6_len; 2343c602fabSXin LI rtrid_t ospf6_routerid; 2353c602fabSXin LI rtrid_t ospf6_areaid; 2363c602fabSXin LI uint16_t ospf6_chksum; 2373c602fabSXin LI uint8_t ospf6_instanceid; 2383c602fabSXin LI uint8_t ospf6_rsvd; 2393c602fabSXin LI }; 2403c602fabSXin LI 2413c602fabSXin LI /* 2423c602fabSXin LI * The OSPF6 header length is 16 bytes, regardless of how your compiler 2433c602fabSXin LI * might choose to pad the above structure. 2443c602fabSXin LI */ 2453c602fabSXin LI #define OSPF6HDR_LEN 16 2463c602fabSXin LI 2473c602fabSXin LI /* Hello packet */ 2483c602fabSXin LI struct hello6 { 2493c602fabSXin LI uint32_t hello_ifid; 2503c602fabSXin LI union { 2513c602fabSXin LI uint8_t pri; 2523c602fabSXin LI uint32_t opt; 2533c602fabSXin LI } hello_priandopt; 2543c602fabSXin LI #define hello_priority hello_priandopt.pri 2553c602fabSXin LI #define hello_options hello_priandopt.opt 2563c602fabSXin LI uint16_t hello_helloint; 2573c602fabSXin LI uint16_t hello_deadint; 2583c602fabSXin LI rtrid_t hello_dr; 2593c602fabSXin LI rtrid_t hello_bdr; 2603c602fabSXin LI rtrid_t hello_neighbor[1]; /* may repeat */ 2613c602fabSXin LI }; 2623c602fabSXin LI 2633c602fabSXin LI /* Database Description packet */ 2643c602fabSXin LI struct dd6 { 2653c602fabSXin LI uint32_t db_options; 2663c602fabSXin LI uint16_t db_mtu; 2673c602fabSXin LI uint8_t db_mbz; 2683c602fabSXin LI uint8_t db_flags; 2693c602fabSXin LI uint32_t db_seq; 2703c602fabSXin LI struct lsa6_hdr db_lshdr[1]; /* may repeat */ 2713c602fabSXin LI }; 2723c602fabSXin LI 2733c602fabSXin LI /* Link State Request */ 2743c602fabSXin LI struct lsr6 { 2753c602fabSXin LI uint16_t ls_mbz; 2763c602fabSXin LI uint16_t ls_type; 2773c602fabSXin LI rtrid_t ls_stateid; 2783c602fabSXin LI rtrid_t ls_router; 2793c602fabSXin LI }; 2803c602fabSXin LI 2813c602fabSXin LI /* Link State Update */ 2823c602fabSXin LI struct lsu6 { 2833c602fabSXin LI uint32_t lsu_count; 2843c602fabSXin LI struct lsa6 lsu_lsa[1]; /* may repeat */ 2853c602fabSXin LI }; 2863c602fabSXin LI 2873c602fabSXin LI static const char tstr[] = " [|ospf3]"; 288b0453382SBill Fenner 289a5779b6eSRui Paulo static const struct tok ospf6_option_values[] = { 290b0453382SBill Fenner { OSPF6_OPTION_V6, "V6" }, 291a5779b6eSRui Paulo { OSPF6_OPTION_E, "External" }, 2923c602fabSXin LI { OSPF6_OPTION_MC, "Deprecated" }, 293a5779b6eSRui Paulo { OSPF6_OPTION_N, "NSSA" }, 294a5779b6eSRui Paulo { OSPF6_OPTION_R, "Router" }, 295a5779b6eSRui Paulo { OSPF6_OPTION_DC, "Demand Circuit" }, 2963c602fabSXin LI { OSPF6_OPTION_AF, "AFs Support" }, 2973c602fabSXin LI { OSPF6_OPTION_L, "LLS" }, 2983c602fabSXin LI { OSPF6_OPTION_AT, "Authentication Trailer" }, 299b0453382SBill Fenner { 0, NULL } 300b0453382SBill Fenner }; 301b0453382SBill Fenner 302a5779b6eSRui Paulo static const struct tok ospf6_rla_flag_values[] = { 303a5779b6eSRui Paulo { RLA_FLAG_B, "ABR" }, 304a5779b6eSRui Paulo { RLA_FLAG_E, "External" }, 305a5779b6eSRui Paulo { RLA_FLAG_V, "Virtual-Link Endpoint" }, 306a5779b6eSRui Paulo { RLA_FLAG_W, "Wildcard Receiver" }, 307a5779b6eSRui Paulo { RLA_FLAG_N, "NSSA Translator" }, 308b0453382SBill Fenner { 0, NULL } 309b0453382SBill Fenner }; 310b0453382SBill Fenner 311a5779b6eSRui Paulo static const struct tok ospf6_asla_flag_values[] = { 312a5779b6eSRui Paulo { ASLA_FLAG_EXTERNAL, "External Type 2" }, 3133c602fabSXin LI { ASLA_FLAG_FWDADDR, "Forwarding" }, 314a5779b6eSRui Paulo { ASLA_FLAG_ROUTETAG, "Tag" }, 315685295f4SBill Fenner { 0, NULL } 316685295f4SBill Fenner }; 317685295f4SBill Fenner 3183c602fabSXin LI static const struct tok ospf6_type_values[] = { 319a5779b6eSRui Paulo { OSPF_TYPE_HELLO, "Hello" }, 320a5779b6eSRui Paulo { OSPF_TYPE_DD, "Database Description" }, 321a5779b6eSRui Paulo { OSPF_TYPE_LS_REQ, "LS-Request" }, 322a5779b6eSRui Paulo { OSPF_TYPE_LS_UPDATE, "LS-Update" }, 323a5779b6eSRui Paulo { OSPF_TYPE_LS_ACK, "LS-Ack" }, 324b0453382SBill Fenner { 0, NULL } 325b0453382SBill Fenner }; 326b0453382SBill Fenner 3273c602fabSXin LI static const struct tok ospf6_lsa_values[] = { 328a5779b6eSRui Paulo { LS_TYPE_ROUTER, "Router" }, 329a5779b6eSRui Paulo { LS_TYPE_NETWORK, "Network" }, 330a5779b6eSRui Paulo { LS_TYPE_INTER_AP, "Inter-Area Prefix" }, 331a5779b6eSRui Paulo { LS_TYPE_INTER_AR, "Inter-Area Router" }, 332a5779b6eSRui Paulo { LS_TYPE_ASE, "External" }, 3333c602fabSXin LI { LS_TYPE_GROUP, "Deprecated" }, 334a5779b6eSRui Paulo { LS_TYPE_NSSA, "NSSA" }, 335a5779b6eSRui Paulo { LS_TYPE_LINK, "Link" }, 336a5779b6eSRui Paulo { LS_TYPE_INTRA_AP, "Intra-Area Prefix" }, 337a5779b6eSRui Paulo { LS_TYPE_INTRA_ATE, "Intra-Area TE" }, 338a5779b6eSRui Paulo { LS_TYPE_GRACE, "Grace" }, 3393c602fabSXin LI { LS_TYPE_RI, "Router Information" }, 3403c602fabSXin LI { LS_TYPE_INTER_ASTE, "Inter-AS-TE" }, 3413c602fabSXin LI { LS_TYPE_L1VPN, "Layer 1 VPN" }, 342a5779b6eSRui Paulo { 0, NULL } 343a5779b6eSRui Paulo }; 344a5779b6eSRui Paulo 3453c602fabSXin LI static const struct tok ospf6_ls_scope_values[] = { 346a5779b6eSRui Paulo { LS_SCOPE_LINKLOCAL, "Link Local" }, 347a5779b6eSRui Paulo { LS_SCOPE_AREA, "Area Local" }, 348a5779b6eSRui Paulo { LS_SCOPE_AS, "Domain Wide" }, 349a5779b6eSRui Paulo { 0, NULL } 350a5779b6eSRui Paulo }; 351a5779b6eSRui Paulo 3523c602fabSXin LI static const struct tok ospf6_dd_flag_values[] = { 353a5779b6eSRui Paulo { OSPF6_DB_INIT, "Init" }, 354a5779b6eSRui Paulo { OSPF6_DB_MORE, "More" }, 355a5779b6eSRui Paulo { OSPF6_DB_MASTER, "Master" }, 3563c602fabSXin LI { OSPF6_DB_M6, "IPv6 MTU" }, 357a5779b6eSRui Paulo { 0, NULL } 358a5779b6eSRui Paulo }; 359a5779b6eSRui Paulo 3603c602fabSXin LI static const struct tok ospf6_lsa_prefix_option_values[] = { 361a5779b6eSRui Paulo { LSA_PREFIX_OPT_NU, "No Unicast" }, 362a5779b6eSRui Paulo { LSA_PREFIX_OPT_LA, "Local address" }, 3633c602fabSXin LI { LSA_PREFIX_OPT_MC, "Deprecated" }, 364a5779b6eSRui Paulo { LSA_PREFIX_OPT_P, "Propagate" }, 365a5779b6eSRui Paulo { LSA_PREFIX_OPT_DN, "Down" }, 366a5779b6eSRui Paulo { 0, NULL } 367a5779b6eSRui Paulo }; 368a5779b6eSRui Paulo 3693c602fabSXin LI static const struct tok ospf6_auth_type_str[] = { 3703c602fabSXin LI { OSPF6_AUTH_TYPE_HMAC, "HMAC" }, 3713c602fabSXin LI { 0, NULL } 3723c602fabSXin LI }; 373b0453382SBill Fenner 374b0453382SBill Fenner static void 3753c602fabSXin LI ospf6_print_ls_type(netdissect_options *ndo, 3763c602fabSXin LI register u_int ls_type, register const rtrid_t *ls_stateid) 377b0453382SBill Fenner { 3783c602fabSXin LI ND_PRINT((ndo, "\n\t %s LSA (%d), %s Scope%s, LSA-ID %s", 379a5779b6eSRui Paulo tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK), 380a5779b6eSRui Paulo ls_type & LS_TYPE_MASK, 381a5779b6eSRui Paulo tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK), 382a5779b6eSRui Paulo ls_type &0x8000 ? ", transitive" : "", /* U-bit */ 3833c602fabSXin LI ipaddr_string(ndo, ls_stateid))); 384b0453382SBill Fenner } 385b0453382SBill Fenner 386b0453382SBill Fenner static int 3873c602fabSXin LI ospf6_print_lshdr(netdissect_options *ndo, 3883c602fabSXin LI register const struct lsa6_hdr *lshp, const u_char *dataend) 389b0453382SBill Fenner { 390*3340d773SGleb Smirnoff if ((const u_char *)(lshp + 1) > dataend) 3913c602fabSXin LI goto trunc; 3923c602fabSXin LI ND_TCHECK(lshp->ls_type); 3933c602fabSXin LI ND_TCHECK(lshp->ls_seq); 394b0453382SBill Fenner 3953c602fabSXin LI ND_PRINT((ndo, "\n\t Advertising Router %s, seq 0x%08x, age %us, length %u", 3963c602fabSXin LI ipaddr_string(ndo, &lshp->ls_router), 397a5779b6eSRui Paulo EXTRACT_32BITS(&lshp->ls_seq), 398a5779b6eSRui Paulo EXTRACT_16BITS(&lshp->ls_age), 3993c602fabSXin LI EXTRACT_16BITS(&lshp->ls_length)-(u_int)sizeof(struct lsa6_hdr))); 400a5779b6eSRui Paulo 4013c602fabSXin LI ospf6_print_ls_type(ndo, EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid); 402b0453382SBill Fenner 403b0453382SBill Fenner return (0); 404b0453382SBill Fenner trunc: 405b0453382SBill Fenner return (1); 406b0453382SBill Fenner } 407b0453382SBill Fenner 408b0453382SBill Fenner static int 4093c602fabSXin LI ospf6_print_lsaprefix(netdissect_options *ndo, 4103c602fabSXin LI const uint8_t *tptr, u_int lsa_length) 411b0453382SBill Fenner { 412*3340d773SGleb Smirnoff const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr; 413a5779b6eSRui Paulo u_int wordlen; 414b0453382SBill Fenner struct in6_addr prefix; 415b0453382SBill Fenner 4163c602fabSXin LI if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES) 417d09a7e67SXin LI goto trunc; 4183c602fabSXin LI lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES; 4193c602fabSXin LI ND_TCHECK2(*lsapp, sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES); 420a5779b6eSRui Paulo wordlen = (lsapp->lsa_p_len + 31) / 32; 421a5779b6eSRui Paulo if (wordlen * 4 > sizeof(struct in6_addr)) { 4223c602fabSXin LI ND_PRINT((ndo, " bogus prefixlen /%d", lsapp->lsa_p_len)); 423b0453382SBill Fenner goto trunc; 424b0453382SBill Fenner } 425d09a7e67SXin LI if (lsa_length < wordlen * 4) 426d09a7e67SXin LI goto trunc; 427d09a7e67SXin LI lsa_length -= wordlen * 4; 4283c602fabSXin LI ND_TCHECK2(lsapp->lsa_p_prefix, wordlen * 4); 429b0453382SBill Fenner memset(&prefix, 0, sizeof(prefix)); 430a5779b6eSRui Paulo memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4); 4313c602fabSXin LI ND_PRINT((ndo, "\n\t\t%s/%d", ip6addr_string(ndo, &prefix), 4323c602fabSXin LI lsapp->lsa_p_len)); 433a5779b6eSRui Paulo if (lsapp->lsa_p_opt) { 4343c602fabSXin LI ND_PRINT((ndo, ", Options [%s]", 435a5779b6eSRui Paulo bittok2str(ospf6_lsa_prefix_option_values, 4363c602fabSXin LI "none", lsapp->lsa_p_opt))); 437a5779b6eSRui Paulo } 4383c602fabSXin LI ND_PRINT((ndo, ", metric %u", EXTRACT_16BITS(&lsapp->lsa_p_metric))); 4393c602fabSXin LI return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4; 440b0453382SBill Fenner 441b0453382SBill Fenner trunc: 442b0453382SBill Fenner return -1; 443b0453382SBill Fenner } 444b0453382SBill Fenner 445b0453382SBill Fenner 446b0453382SBill Fenner /* 447b0453382SBill Fenner * Print a single link state advertisement. If truncated return 1, else 0. 448b0453382SBill Fenner */ 449b0453382SBill Fenner static int 4503c602fabSXin LI ospf6_print_lsa(netdissect_options *ndo, 4513c602fabSXin LI register const struct lsa6 *lsap, const u_char *dataend) 452b0453382SBill Fenner { 453a5779b6eSRui Paulo register const struct rlalink6 *rlp; 454b0453382SBill Fenner #if 0 455b0453382SBill Fenner register const struct tos_metric *tosp; 456b0453382SBill Fenner #endif 457b0453382SBill Fenner register const rtrid_t *ap; 458b0453382SBill Fenner #if 0 459b0453382SBill Fenner register const struct aslametric *almp; 460b0453382SBill Fenner register const struct mcla *mcp; 461b0453382SBill Fenner #endif 462b0453382SBill Fenner register const struct llsa *llsap; 463a5779b6eSRui Paulo register const struct lsa6_prefix *lsapp; 464b0453382SBill Fenner #if 0 4653c602fabSXin LI register const uint32_t *lp; 466b0453382SBill Fenner #endif 467a5779b6eSRui Paulo register u_int prefixes; 468d09a7e67SXin LI register int bytelen; 469d09a7e67SXin LI register u_int length, lsa_length; 4703c602fabSXin LI uint32_t flags32; 4713c602fabSXin LI const uint8_t *tptr; 472b0453382SBill Fenner 4733c602fabSXin LI if (ospf6_print_lshdr(ndo, &lsap->ls_hdr, dataend)) 474b0453382SBill Fenner return (1); 4753c602fabSXin LI ND_TCHECK(lsap->ls_hdr.ls_length); 476a5779b6eSRui Paulo length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length); 477d09a7e67SXin LI 478d09a7e67SXin LI /* 479d09a7e67SXin LI * The LSA length includes the length of the header; 480d09a7e67SXin LI * it must have a value that's at least that length. 481d09a7e67SXin LI * If it does, find the length of what follows the 482d09a7e67SXin LI * header. 483d09a7e67SXin LI */ 484*3340d773SGleb Smirnoff if (length < sizeof(struct lsa6_hdr) || (const u_char *)lsap + length > dataend) 485d09a7e67SXin LI return (1); 486a5779b6eSRui Paulo lsa_length = length - sizeof(struct lsa6_hdr); 487*3340d773SGleb Smirnoff tptr = (const uint8_t *)lsap+sizeof(struct lsa6_hdr); 488a5779b6eSRui Paulo 4895b0fe478SBruce M Simpson switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { 490b0453382SBill Fenner case LS_TYPE_ROUTER | LS_SCOPE_AREA: 491d09a7e67SXin LI if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options)) 492d09a7e67SXin LI return (1); 493d09a7e67SXin LI lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options); 4943c602fabSXin LI ND_TCHECK(lsap->lsa_un.un_rla.rla_options); 4953c602fabSXin LI ND_PRINT((ndo, "\n\t Options [%s]", 496a5779b6eSRui Paulo bittok2str(ospf6_option_values, "none", 4973c602fabSXin LI EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options)))); 4983c602fabSXin LI ND_PRINT((ndo, ", RLA-Flags [%s]", 499a5779b6eSRui Paulo bittok2str(ospf6_rla_flag_values, "none", 5003c602fabSXin LI lsap->lsa_un.un_rla.rla_flags))); 501a5779b6eSRui Paulo 502b0453382SBill Fenner rlp = lsap->lsa_un.un_rla.rla_link; 503d09a7e67SXin LI while (lsa_length != 0) { 504d09a7e67SXin LI if (lsa_length < sizeof (*rlp)) 505d09a7e67SXin LI return (1); 506d09a7e67SXin LI lsa_length -= sizeof (*rlp); 5073c602fabSXin LI ND_TCHECK(*rlp); 508b0453382SBill Fenner switch (rlp->link_type) { 509b0453382SBill Fenner 510b0453382SBill Fenner case RLA_TYPE_VIRTUAL: 5113c602fabSXin LI ND_PRINT((ndo, "\n\t Virtual Link: Neighbor Router-ID %s" 512a5779b6eSRui Paulo "\n\t Neighbor Interface-ID %s, Interface %s", 5133c602fabSXin LI ipaddr_string(ndo, &rlp->link_nrtid), 5143c602fabSXin LI ipaddr_string(ndo, &rlp->link_nifid), 5153c602fabSXin LI ipaddr_string(ndo, &rlp->link_ifid))); 516a5779b6eSRui Paulo break; 517b0453382SBill Fenner 518b0453382SBill Fenner case RLA_TYPE_ROUTER: 5193c602fabSXin LI ND_PRINT((ndo, "\n\t Neighbor Router-ID %s" 520a5779b6eSRui Paulo "\n\t Neighbor Interface-ID %s, Interface %s", 5213c602fabSXin LI ipaddr_string(ndo, &rlp->link_nrtid), 5223c602fabSXin LI ipaddr_string(ndo, &rlp->link_nifid), 5233c602fabSXin LI ipaddr_string(ndo, &rlp->link_ifid))); 524b0453382SBill Fenner break; 525b0453382SBill Fenner 526b0453382SBill Fenner case RLA_TYPE_TRANSIT: 5273c602fabSXin LI ND_PRINT((ndo, "\n\t Neighbor Network-ID %s" 528a5779b6eSRui Paulo "\n\t Neighbor Interface-ID %s, Interface %s", 5293c602fabSXin LI ipaddr_string(ndo, &rlp->link_nrtid), 5303c602fabSXin LI ipaddr_string(ndo, &rlp->link_nifid), 5313c602fabSXin LI ipaddr_string(ndo, &rlp->link_ifid))); 532b0453382SBill Fenner break; 533b0453382SBill Fenner 534b0453382SBill Fenner default: 5353c602fabSXin LI ND_PRINT((ndo, "\n\t Unknown Router Links Type 0x%02x", 5363c602fabSXin LI rlp->link_type)); 537b0453382SBill Fenner return (0); 538b0453382SBill Fenner } 5393c602fabSXin LI ND_PRINT((ndo, ", metric %d", EXTRACT_16BITS(&rlp->link_metric))); 540b0453382SBill Fenner rlp++; 541b0453382SBill Fenner } 542b0453382SBill Fenner break; 543b0453382SBill Fenner 544b0453382SBill Fenner case LS_TYPE_NETWORK | LS_SCOPE_AREA: 545d09a7e67SXin LI if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options)) 546d09a7e67SXin LI return (1); 547d09a7e67SXin LI lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options); 5483c602fabSXin LI ND_TCHECK(lsap->lsa_un.un_nla.nla_options); 5493c602fabSXin LI ND_PRINT((ndo, "\n\t Options [%s]", 550a5779b6eSRui Paulo bittok2str(ospf6_option_values, "none", 5513c602fabSXin LI EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options)))); 552d09a7e67SXin LI 5533c602fabSXin LI ND_PRINT((ndo, "\n\t Connected Routers:")); 554b0453382SBill Fenner ap = lsap->lsa_un.un_nla.nla_router; 555d09a7e67SXin LI while (lsa_length != 0) { 556d09a7e67SXin LI if (lsa_length < sizeof (*ap)) 557d09a7e67SXin LI return (1); 558d09a7e67SXin LI lsa_length -= sizeof (*ap); 5593c602fabSXin LI ND_TCHECK(*ap); 5603c602fabSXin LI ND_PRINT((ndo, "\n\t\t%s", ipaddr_string(ndo, ap))); 561b0453382SBill Fenner ++ap; 562b0453382SBill Fenner } 563b0453382SBill Fenner break; 564b0453382SBill Fenner 565b0453382SBill Fenner case LS_TYPE_INTER_AP | LS_SCOPE_AREA: 566d09a7e67SXin LI if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric)) 567d09a7e67SXin LI return (1); 568d09a7e67SXin LI lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric); 5693c602fabSXin LI ND_TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); 5703c602fabSXin LI ND_PRINT((ndo, ", metric %u", 5713c602fabSXin LI EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC)); 572d09a7e67SXin LI 573*3340d773SGleb Smirnoff tptr = (const uint8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix; 574d09a7e67SXin LI while (lsa_length != 0) { 5753c602fabSXin LI bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 576d09a7e67SXin LI if (bytelen < 0) 577b0453382SBill Fenner goto trunc; 578d09a7e67SXin LI lsa_length -= bytelen; 579d09a7e67SXin LI tptr += bytelen; 580b0453382SBill Fenner } 581b0453382SBill Fenner break; 582d09a7e67SXin LI 583d09a7e67SXin LI case LS_TYPE_ASE | LS_SCOPE_AS: 584d09a7e67SXin LI if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric)) 585d09a7e67SXin LI return (1); 586d09a7e67SXin LI lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric); 5873c602fabSXin LI ND_TCHECK(lsap->lsa_un.un_asla.asla_metric); 5885b0fe478SBruce M Simpson flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); 5893c602fabSXin LI ND_PRINT((ndo, "\n\t Flags [%s]", 5903c602fabSXin LI bittok2str(ospf6_asla_flag_values, "none", flags32))); 5913c602fabSXin LI ND_PRINT((ndo, " metric %u", 5925b0fe478SBruce M Simpson EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & 5933c602fabSXin LI ASLA_MASK_METRIC)); 594d09a7e67SXin LI 595*3340d773SGleb Smirnoff tptr = (const uint8_t *)lsap->lsa_un.un_asla.asla_prefix; 596*3340d773SGleb Smirnoff lsapp = (const struct lsa6_prefix *)tptr; 5973c602fabSXin LI bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 598a5779b6eSRui Paulo if (bytelen < 0) 599685295f4SBill Fenner goto trunc; 600d09a7e67SXin LI lsa_length -= bytelen; 601d09a7e67SXin LI tptr += bytelen; 602b0453382SBill Fenner 603685295f4SBill Fenner if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { 604*3340d773SGleb Smirnoff const struct in6_addr *fwdaddr6; 605d09a7e67SXin LI 606*3340d773SGleb Smirnoff fwdaddr6 = (const struct in6_addr *)tptr; 607d09a7e67SXin LI if (lsa_length < sizeof (*fwdaddr6)) 608d09a7e67SXin LI return (1); 609d09a7e67SXin LI lsa_length -= sizeof (*fwdaddr6); 6103c602fabSXin LI ND_TCHECK(*fwdaddr6); 6113c602fabSXin LI ND_PRINT((ndo, " forward %s", 6123c602fabSXin LI ip6addr_string(ndo, fwdaddr6))); 613d09a7e67SXin LI tptr += sizeof(*fwdaddr6); 614685295f4SBill Fenner } 615685295f4SBill Fenner 616685295f4SBill Fenner if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { 6173c602fabSXin LI if (lsa_length < sizeof (uint32_t)) 618d09a7e67SXin LI return (1); 6193c602fabSXin LI lsa_length -= sizeof (uint32_t); 620*3340d773SGleb Smirnoff ND_TCHECK(*(const uint32_t *)tptr); 6213c602fabSXin LI ND_PRINT((ndo, " tag %s", 622*3340d773SGleb Smirnoff ipaddr_string(ndo, (const uint32_t *)tptr))); 6233c602fabSXin LI tptr += sizeof(uint32_t); 624685295f4SBill Fenner } 625685295f4SBill Fenner 626a5779b6eSRui Paulo if (lsapp->lsa_p_metric) { 6273c602fabSXin LI if (lsa_length < sizeof (uint32_t)) 628d09a7e67SXin LI return (1); 6293c602fabSXin LI lsa_length -= sizeof (uint32_t); 630*3340d773SGleb Smirnoff ND_TCHECK(*(const uint32_t *)tptr); 6313c602fabSXin LI ND_PRINT((ndo, " RefLSID: %s", 632*3340d773SGleb Smirnoff ipaddr_string(ndo, (const uint32_t *)tptr))); 6333c602fabSXin LI tptr += sizeof(uint32_t); 634685295f4SBill Fenner } 635685295f4SBill Fenner break; 636b0453382SBill Fenner 637b0453382SBill Fenner case LS_TYPE_LINK: 638b0453382SBill Fenner /* Link LSA */ 639b0453382SBill Fenner llsap = &lsap->lsa_un.un_llsa; 640d09a7e67SXin LI if (lsa_length < sizeof (llsap->llsa_priandopt)) 641d09a7e67SXin LI return (1); 642d09a7e67SXin LI lsa_length -= sizeof (llsap->llsa_priandopt); 6433c602fabSXin LI ND_TCHECK(llsap->llsa_priandopt); 6443c602fabSXin LI ND_PRINT((ndo, "\n\t Options [%s]", 645a5779b6eSRui Paulo bittok2str(ospf6_option_values, "none", 6463c602fabSXin LI EXTRACT_32BITS(&llsap->llsa_options)))); 647d09a7e67SXin LI 648d09a7e67SXin LI if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) 649d09a7e67SXin LI return (1); 650d09a7e67SXin LI lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); 651a5779b6eSRui Paulo prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); 6523c602fabSXin LI ND_PRINT((ndo, "\n\t Priority %d, Link-local address %s, Prefixes %d:", 653a5779b6eSRui Paulo llsap->llsa_priority, 6543c602fabSXin LI ip6addr_string(ndo, &llsap->llsa_lladdr), 6553c602fabSXin LI prefixes)); 656a5779b6eSRui Paulo 657*3340d773SGleb Smirnoff tptr = (const uint8_t *)llsap->llsa_prefix; 658a5779b6eSRui Paulo while (prefixes > 0) { 6593c602fabSXin LI bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 660d09a7e67SXin LI if (bytelen < 0) 661b0453382SBill Fenner goto trunc; 662a5779b6eSRui Paulo prefixes--; 663d09a7e67SXin LI lsa_length -= bytelen; 664a5779b6eSRui Paulo tptr += bytelen; 665b0453382SBill Fenner } 666b0453382SBill Fenner break; 667b0453382SBill Fenner 668b0453382SBill Fenner case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: 669b0453382SBill Fenner /* Intra-Area-Prefix LSA */ 670d09a7e67SXin LI if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid)) 671d09a7e67SXin LI return (1); 672d09a7e67SXin LI lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid); 6733c602fabSXin LI ND_TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); 6743c602fabSXin LI ospf6_print_ls_type(ndo, 6755b0fe478SBruce M Simpson EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), 676a5779b6eSRui Paulo &lsap->lsa_un.un_intra_ap.intra_ap_lsid); 677d09a7e67SXin LI 678d09a7e67SXin LI if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix)) 679d09a7e67SXin LI return (1); 680d09a7e67SXin LI lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 6813c602fabSXin LI ND_TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 682a5779b6eSRui Paulo prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 6833c602fabSXin LI ND_PRINT((ndo, "\n\t Prefixes %d:", prefixes)); 684b0453382SBill Fenner 685*3340d773SGleb Smirnoff tptr = (const uint8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; 686a5779b6eSRui Paulo while (prefixes > 0) { 6873c602fabSXin LI bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); 688d09a7e67SXin LI if (bytelen < 0) 689b0453382SBill Fenner goto trunc; 690a5779b6eSRui Paulo prefixes--; 691d09a7e67SXin LI lsa_length -= bytelen; 692a5779b6eSRui Paulo tptr += bytelen; 693a5779b6eSRui Paulo } 694a5779b6eSRui Paulo break; 695a5779b6eSRui Paulo 696a5779b6eSRui Paulo case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: 6973c602fabSXin LI if (ospf_print_grace_lsa(ndo, tptr, lsa_length) == -1) { 698a5779b6eSRui Paulo return 1; 699a5779b6eSRui Paulo } 700a5779b6eSRui Paulo break; 701a5779b6eSRui Paulo 702a5779b6eSRui Paulo case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: 7033c602fabSXin LI if (ospf_print_te_lsa(ndo, tptr, lsa_length) == -1) { 704a5779b6eSRui Paulo return 1; 705b0453382SBill Fenner } 706b0453382SBill Fenner break; 707b0453382SBill Fenner 708b0453382SBill Fenner default: 7093c602fabSXin LI if(!print_unknown_data(ndo,tptr, 710a5779b6eSRui Paulo "\n\t ", 711a5779b6eSRui Paulo lsa_length)) { 712a5779b6eSRui Paulo return (1); 713a5779b6eSRui Paulo } 714d09a7e67SXin LI break; 715b0453382SBill Fenner } 716b0453382SBill Fenner 717b0453382SBill Fenner return (0); 718b0453382SBill Fenner trunc: 719b0453382SBill Fenner return (1); 720b0453382SBill Fenner } 721b0453382SBill Fenner 722b0453382SBill Fenner static int 7233c602fabSXin LI ospf6_decode_v3(netdissect_options *ndo, 7243c602fabSXin LI register const struct ospf6hdr *op, 725b0453382SBill Fenner register const u_char *dataend) 726b0453382SBill Fenner { 727b0453382SBill Fenner register const rtrid_t *ap; 728a5779b6eSRui Paulo register const struct lsr6 *lsrp; 729a5779b6eSRui Paulo register const struct lsa6_hdr *lshp; 730a5779b6eSRui Paulo register const struct lsa6 *lsap; 731b0453382SBill Fenner register int i; 732b0453382SBill Fenner 733b0453382SBill Fenner switch (op->ospf6_type) { 734b0453382SBill Fenner 7353c602fabSXin LI case OSPF_TYPE_HELLO: { 736*3340d773SGleb Smirnoff register const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); 7373c602fabSXin LI 7383c602fabSXin LI ND_PRINT((ndo, "\n\tOptions [%s]", 739a5779b6eSRui Paulo bittok2str(ospf6_option_values, "none", 7403c602fabSXin LI EXTRACT_32BITS(&hellop->hello_options)))); 741a5779b6eSRui Paulo 7423c602fabSXin LI ND_TCHECK(hellop->hello_deadint); 7433c602fabSXin LI ND_PRINT((ndo, "\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u", 7443c602fabSXin LI EXTRACT_16BITS(&hellop->hello_helloint), 7453c602fabSXin LI EXTRACT_16BITS(&hellop->hello_deadint), 7463c602fabSXin LI ipaddr_string(ndo, &hellop->hello_ifid), 7473c602fabSXin LI hellop->hello_priority)); 748a5779b6eSRui Paulo 7493c602fabSXin LI ND_TCHECK(hellop->hello_dr); 7503c602fabSXin LI if (EXTRACT_32BITS(&hellop->hello_dr) != 0) 7513c602fabSXin LI ND_PRINT((ndo, "\n\t Designated Router %s", 7523c602fabSXin LI ipaddr_string(ndo, &hellop->hello_dr))); 7533c602fabSXin LI ND_TCHECK(hellop->hello_bdr); 7543c602fabSXin LI if (EXTRACT_32BITS(&hellop->hello_bdr) != 0) 7553c602fabSXin LI ND_PRINT((ndo, ", Backup Designated Router %s", 7563c602fabSXin LI ipaddr_string(ndo, &hellop->hello_bdr))); 7573c602fabSXin LI if (ndo->ndo_vflag > 1) { 7583c602fabSXin LI ND_PRINT((ndo, "\n\t Neighbor List:")); 7593c602fabSXin LI ap = hellop->hello_neighbor; 760*3340d773SGleb Smirnoff while ((const u_char *)ap < dataend) { 7613c602fabSXin LI ND_TCHECK(*ap); 7623c602fabSXin LI ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap))); 763b0453382SBill Fenner ++ap; 764b0453382SBill Fenner } 765b0453382SBill Fenner } 766b0453382SBill Fenner break; /* HELLO */ 7673c602fabSXin LI } 768b0453382SBill Fenner 7693c602fabSXin LI case OSPF_TYPE_DD: { 770*3340d773SGleb Smirnoff register const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); 7713c602fabSXin LI 7723c602fabSXin LI ND_TCHECK(ddp->db_options); 7733c602fabSXin LI ND_PRINT((ndo, "\n\tOptions [%s]", 774a5779b6eSRui Paulo bittok2str(ospf6_option_values, "none", 7753c602fabSXin LI EXTRACT_32BITS(&ddp->db_options)))); 7763c602fabSXin LI ND_TCHECK(ddp->db_flags); 7773c602fabSXin LI ND_PRINT((ndo, ", DD Flags [%s]", 7783c602fabSXin LI bittok2str(ospf6_dd_flag_values,"none",ddp->db_flags))); 779a5779b6eSRui Paulo 7803c602fabSXin LI ND_TCHECK(ddp->db_seq); 7813c602fabSXin LI ND_PRINT((ndo, ", MTU %u, DD-Sequence 0x%08x", 7823c602fabSXin LI EXTRACT_16BITS(&ddp->db_mtu), 7833c602fabSXin LI EXTRACT_32BITS(&ddp->db_seq))); 7843c602fabSXin LI if (ndo->ndo_vflag > 1) { 785b0453382SBill Fenner /* Print all the LS adv's */ 7863c602fabSXin LI lshp = ddp->db_lshdr; 787*3340d773SGleb Smirnoff while ((const u_char *)lshp < dataend) { 7883c602fabSXin LI if (ospf6_print_lshdr(ndo, lshp++, dataend)) 7893c602fabSXin LI goto trunc; 7903c602fabSXin LI } 791b0453382SBill Fenner } 792b0453382SBill Fenner break; 7933c602fabSXin LI } 794b0453382SBill Fenner 795a5779b6eSRui Paulo case OSPF_TYPE_LS_REQ: 7963c602fabSXin LI if (ndo->ndo_vflag > 1) { 797*3340d773SGleb Smirnoff lsrp = (const struct lsr6 *)((const uint8_t *)op + OSPF6HDR_LEN); 798*3340d773SGleb Smirnoff while ((const u_char *)lsrp < dataend) { 7993c602fabSXin LI ND_TCHECK(*lsrp); 8003c602fabSXin LI ND_PRINT((ndo, "\n\t Advertising Router %s", 8013c602fabSXin LI ipaddr_string(ndo, &lsrp->ls_router))); 8023c602fabSXin LI ospf6_print_ls_type(ndo, EXTRACT_16BITS(&lsrp->ls_type), 803a5779b6eSRui Paulo &lsrp->ls_stateid); 804b0453382SBill Fenner ++lsrp; 805b0453382SBill Fenner } 806b0453382SBill Fenner } 807b0453382SBill Fenner break; 808b0453382SBill Fenner 809a5779b6eSRui Paulo case OSPF_TYPE_LS_UPDATE: 8103c602fabSXin LI if (ndo->ndo_vflag > 1) { 811*3340d773SGleb Smirnoff register const struct lsu6 *lsup = (const struct lsu6 *)((const uint8_t *)op + OSPF6HDR_LEN); 8123c602fabSXin LI 8133c602fabSXin LI ND_TCHECK(lsup->lsu_count); 8143c602fabSXin LI i = EXTRACT_32BITS(&lsup->lsu_count); 8153c602fabSXin LI lsap = lsup->lsu_lsa; 816*3340d773SGleb Smirnoff while ((const u_char *)lsap < dataend && i--) { 8173c602fabSXin LI if (ospf6_print_lsa(ndo, lsap, dataend)) 818b0453382SBill Fenner goto trunc; 819*3340d773SGleb Smirnoff lsap = (const struct lsa6 *)((const u_char *)lsap + 8205b0fe478SBruce M Simpson EXTRACT_16BITS(&lsap->ls_hdr.ls_length)); 821b0453382SBill Fenner } 822b0453382SBill Fenner } 823b0453382SBill Fenner break; 824b0453382SBill Fenner 825a5779b6eSRui Paulo case OSPF_TYPE_LS_ACK: 8263c602fabSXin LI if (ndo->ndo_vflag > 1) { 827*3340d773SGleb Smirnoff lshp = (const struct lsa6_hdr *)((const uint8_t *)op + OSPF6HDR_LEN); 828*3340d773SGleb Smirnoff while ((const u_char *)lshp < dataend) { 8293c602fabSXin LI if (ospf6_print_lshdr(ndo, lshp++, dataend)) 8303c602fabSXin LI goto trunc; 831b0453382SBill Fenner } 832b0453382SBill Fenner } 833b0453382SBill Fenner break; 834b0453382SBill Fenner 835b0453382SBill Fenner default: 836b0453382SBill Fenner break; 837b0453382SBill Fenner } 838b0453382SBill Fenner return (0); 839b0453382SBill Fenner trunc: 840b0453382SBill Fenner return (1); 841b0453382SBill Fenner } 842b0453382SBill Fenner 8433c602fabSXin LI /* RFC5613 Section 2.2 (w/o the TLVs) */ 8443c602fabSXin LI static int 8453c602fabSXin LI ospf6_print_lls(netdissect_options *ndo, 8463c602fabSXin LI const u_char *cp, const u_int len) 8473c602fabSXin LI { 8483c602fabSXin LI uint16_t llsdatalen; 8493c602fabSXin LI 8503c602fabSXin LI if (len == 0) 8513c602fabSXin LI return 0; 8523c602fabSXin LI if (len < OSPF_LLS_HDRLEN) 8533c602fabSXin LI goto trunc; 8543c602fabSXin LI /* Checksum */ 8553c602fabSXin LI ND_TCHECK2(*cp, 2); 8563c602fabSXin LI ND_PRINT((ndo, "\n\tLLS Checksum 0x%04x", EXTRACT_16BITS(cp))); 8573c602fabSXin LI cp += 2; 8583c602fabSXin LI /* LLS Data Length */ 8593c602fabSXin LI ND_TCHECK2(*cp, 2); 8603c602fabSXin LI llsdatalen = EXTRACT_16BITS(cp); 8613c602fabSXin LI ND_PRINT((ndo, ", Data Length %u", llsdatalen)); 8623c602fabSXin LI if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len) 8633c602fabSXin LI goto trunc; 8643c602fabSXin LI cp += 2; 8653c602fabSXin LI /* LLS TLVs */ 8663c602fabSXin LI ND_TCHECK2(*cp, llsdatalen - OSPF_LLS_HDRLEN); 8673c602fabSXin LI /* FIXME: code in print-ospf.c can be reused to decode the TLVs */ 8683c602fabSXin LI 8693c602fabSXin LI return llsdatalen; 8703c602fabSXin LI trunc: 8713c602fabSXin LI return -1; 8723c602fabSXin LI } 8733c602fabSXin LI 8743c602fabSXin LI /* RFC6506 Section 4.1 */ 8753c602fabSXin LI static int 8763c602fabSXin LI ospf6_decode_at(netdissect_options *ndo, 8773c602fabSXin LI const u_char *cp, const u_int len) 8783c602fabSXin LI { 8793c602fabSXin LI uint16_t authdatalen; 8803c602fabSXin LI 8813c602fabSXin LI if (len == 0) 8823c602fabSXin LI return 0; 8833c602fabSXin LI if (len < OSPF6_AT_HDRLEN) 8843c602fabSXin LI goto trunc; 8853c602fabSXin LI /* Authentication Type */ 8863c602fabSXin LI ND_TCHECK2(*cp, 2); 8873c602fabSXin LI ND_PRINT((ndo, "\n\tAuthentication Type %s", tok2str(ospf6_auth_type_str, "unknown (0x%04x)", EXTRACT_16BITS(cp)))); 8883c602fabSXin LI cp += 2; 8893c602fabSXin LI /* Auth Data Len */ 8903c602fabSXin LI ND_TCHECK2(*cp, 2); 8913c602fabSXin LI authdatalen = EXTRACT_16BITS(cp); 8923c602fabSXin LI ND_PRINT((ndo, ", Length %u", authdatalen)); 8933c602fabSXin LI if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len) 8943c602fabSXin LI goto trunc; 8953c602fabSXin LI cp += 2; 8963c602fabSXin LI /* Reserved */ 8973c602fabSXin LI ND_TCHECK2(*cp, 2); 8983c602fabSXin LI cp += 2; 8993c602fabSXin LI /* Security Association ID */ 9003c602fabSXin LI ND_TCHECK2(*cp, 2); 9013c602fabSXin LI ND_PRINT((ndo, ", SAID %u", EXTRACT_16BITS(cp))); 9023c602fabSXin LI cp += 2; 9033c602fabSXin LI /* Cryptographic Sequence Number (High-Order 32 Bits) */ 9043c602fabSXin LI ND_TCHECK2(*cp, 4); 9053c602fabSXin LI ND_PRINT((ndo, ", CSN 0x%08x", EXTRACT_32BITS(cp))); 9063c602fabSXin LI cp += 4; 9073c602fabSXin LI /* Cryptographic Sequence Number (Low-Order 32 Bits) */ 9083c602fabSXin LI ND_TCHECK2(*cp, 4); 9093c602fabSXin LI ND_PRINT((ndo, ":%08x", EXTRACT_32BITS(cp))); 9103c602fabSXin LI cp += 4; 9113c602fabSXin LI /* Authentication Data */ 9123c602fabSXin LI ND_TCHECK2(*cp, authdatalen - OSPF6_AT_HDRLEN); 9133c602fabSXin LI if (ndo->ndo_vflag > 1) 9143c602fabSXin LI print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN); 9153c602fabSXin LI return 0; 9163c602fabSXin LI 9173c602fabSXin LI trunc: 9183c602fabSXin LI return 1; 9193c602fabSXin LI } 9203c602fabSXin LI 9213c602fabSXin LI /* The trailing data may include LLS and/or AT data (in this specific order). 9223c602fabSXin LI * LLS data may be present only in Hello and DBDesc packets with the L-bit set. 9233c602fabSXin LI * AT data may be present in Hello and DBDesc packets with the AT-bit set or in 9243c602fabSXin LI * any other packet type, thus decode the AT data regardless of the AT-bit. 9253c602fabSXin LI */ 9263c602fabSXin LI static int 9273c602fabSXin LI ospf6_decode_v3_trailer(netdissect_options *ndo, 9283c602fabSXin LI const struct ospf6hdr *op, const u_char *cp, const unsigned len) 9293c602fabSXin LI { 9303c602fabSXin LI int llslen = 0; 9313c602fabSXin LI int lls_hello = 0; 9323c602fabSXin LI int lls_dd = 0; 9333c602fabSXin LI 9343c602fabSXin LI if (op->ospf6_type == OSPF_TYPE_HELLO) { 935*3340d773SGleb Smirnoff const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); 9363c602fabSXin LI if (EXTRACT_32BITS(&hellop->hello_options) & OSPF6_OPTION_L) 9373c602fabSXin LI lls_hello = 1; 9383c602fabSXin LI } else if (op->ospf6_type == OSPF_TYPE_DD) { 939*3340d773SGleb Smirnoff const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); 9403c602fabSXin LI if (EXTRACT_32BITS(&ddp->db_options) & OSPF6_OPTION_L) 9413c602fabSXin LI lls_dd = 1; 9423c602fabSXin LI } 9433c602fabSXin LI if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(ndo, cp, len)) < 0) 9443c602fabSXin LI goto trunc; 9453c602fabSXin LI return ospf6_decode_at(ndo, cp + llslen, len - llslen); 9463c602fabSXin LI 9473c602fabSXin LI trunc: 9483c602fabSXin LI return 1; 9493c602fabSXin LI } 9503c602fabSXin LI 951b0453382SBill Fenner void 9523c602fabSXin LI ospf6_print(netdissect_options *ndo, 9533c602fabSXin LI register const u_char *bp, register u_int length) 954b0453382SBill Fenner { 955b0453382SBill Fenner register const struct ospf6hdr *op; 956b0453382SBill Fenner register const u_char *dataend; 957b0453382SBill Fenner register const char *cp; 9583c602fabSXin LI uint16_t datalen; 959b0453382SBill Fenner 960*3340d773SGleb Smirnoff op = (const struct ospf6hdr *)bp; 961b0453382SBill Fenner 962b0453382SBill Fenner /* If the type is valid translate it, or just print the type */ 963b0453382SBill Fenner /* value. If it's not valid, say so and return */ 9643c602fabSXin LI ND_TCHECK(op->ospf6_type); 9653c602fabSXin LI cp = tok2str(ospf6_type_values, "unknown packet type (%u)", op->ospf6_type); 9663c602fabSXin LI ND_PRINT((ndo, "OSPFv%u, %s, length %d", op->ospf6_version, cp, length)); 967a5779b6eSRui Paulo if (*cp == 'u') { 968b0453382SBill Fenner return; 969a5779b6eSRui Paulo } 970a5779b6eSRui Paulo 9713c602fabSXin LI if(!ndo->ndo_vflag) { /* non verbose - so lets bail out here */ 972a5779b6eSRui Paulo return; 973a5779b6eSRui Paulo } 974b0453382SBill Fenner 9753c602fabSXin LI /* OSPFv3 data always comes first and optional trailing data may follow. */ 9763c602fabSXin LI ND_TCHECK(op->ospf6_len); 9773c602fabSXin LI datalen = EXTRACT_16BITS(&op->ospf6_len); 9783c602fabSXin LI if (datalen > length) { 9793c602fabSXin LI ND_PRINT((ndo, " [len %d]", datalen)); 980b0453382SBill Fenner return; 981b0453382SBill Fenner } 9823c602fabSXin LI dataend = bp + datalen; 983b0453382SBill Fenner 9843c602fabSXin LI ND_TCHECK(op->ospf6_routerid); 9853c602fabSXin LI ND_PRINT((ndo, "\n\tRouter-ID %s", ipaddr_string(ndo, &op->ospf6_routerid))); 986b0453382SBill Fenner 9873c602fabSXin LI ND_TCHECK(op->ospf6_areaid); 9883c602fabSXin LI if (EXTRACT_32BITS(&op->ospf6_areaid) != 0) 9893c602fabSXin LI ND_PRINT((ndo, ", Area %s", ipaddr_string(ndo, &op->ospf6_areaid))); 990b0453382SBill Fenner else 9913c602fabSXin LI ND_PRINT((ndo, ", Backbone Area")); 9923c602fabSXin LI ND_TCHECK(op->ospf6_instanceid); 993b0453382SBill Fenner if (op->ospf6_instanceid) 9943c602fabSXin LI ND_PRINT((ndo, ", Instance %u", op->ospf6_instanceid)); 995b0453382SBill Fenner 996b0453382SBill Fenner /* Do rest according to version. */ 997b0453382SBill Fenner switch (op->ospf6_version) { 998b0453382SBill Fenner 999b0453382SBill Fenner case 3: 1000b0453382SBill Fenner /* ospf version 3 */ 10013c602fabSXin LI if (ospf6_decode_v3(ndo, op, dataend) || 10023c602fabSXin LI ospf6_decode_v3_trailer(ndo, op, dataend, length - datalen)) 1003b0453382SBill Fenner goto trunc; 1004b0453382SBill Fenner break; 1005b0453382SBill Fenner } /* end switch on version */ 1006b0453382SBill Fenner 1007b0453382SBill Fenner return; 1008b0453382SBill Fenner trunc: 10093c602fabSXin LI ND_PRINT((ndo, "%s", tstr)); 1010b0453382SBill Fenner } 1011