14edb46e9SPaul Traina /* 24edb46e9SPaul Traina * Copyright (c) 1995, 1996 34edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 44edb46e9SPaul Traina * 54edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 64edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 74edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 84edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 94edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 104edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 114edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 124edb46e9SPaul Traina * ``This product includes software developed by the University of California, 134edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 144edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 154edb46e9SPaul Traina * or promote products derived from this software without specific prior 164edb46e9SPaul Traina * written permission. 174edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 184edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 194edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 204edb46e9SPaul Traina */ 214edb46e9SPaul Traina 223340d773SGleb Smirnoff /* \summary: Protocol Independent Multicast (PIM) printer */ 233340d773SGleb Smirnoff 24b0453382SBill Fenner #ifdef HAVE_CONFIG_H 25*ee67461eSJoseph Mingrone #include <config.h> 264edb46e9SPaul Traina #endif 274edb46e9SPaul Traina 28*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 29cac3dcd5SXin LI 303340d773SGleb Smirnoff #include "netdissect.h" 31cac3dcd5SXin LI #include "addrtoname.h" 32cac3dcd5SXin LI #include "extract.h" 33cac3dcd5SXin LI 34cac3dcd5SXin LI #include "ip.h" 353340d773SGleb Smirnoff #include "ip6.h" 363340d773SGleb Smirnoff #include "ipproto.h" 37c1ad1296SSam Leffler 383c602fabSXin LI #define PIMV1_TYPE_QUERY 0 393c602fabSXin LI #define PIMV1_TYPE_REGISTER 1 403c602fabSXin LI #define PIMV1_TYPE_REGISTER_STOP 2 413c602fabSXin LI #define PIMV1_TYPE_JOIN_PRUNE 3 423c602fabSXin LI #define PIMV1_TYPE_RP_REACHABILITY 4 433c602fabSXin LI #define PIMV1_TYPE_ASSERT 5 443c602fabSXin LI #define PIMV1_TYPE_GRAFT 6 453c602fabSXin LI #define PIMV1_TYPE_GRAFT_ACK 7 463c602fabSXin LI 473c602fabSXin LI static const struct tok pimv1_type_str[] = { 483c602fabSXin LI { PIMV1_TYPE_QUERY, "Query" }, 493c602fabSXin LI { PIMV1_TYPE_REGISTER, "Register" }, 503c602fabSXin LI { PIMV1_TYPE_REGISTER_STOP, "Register-Stop" }, 513c602fabSXin LI { PIMV1_TYPE_JOIN_PRUNE, "Join/Prune" }, 523c602fabSXin LI { PIMV1_TYPE_RP_REACHABILITY, "RP-reachable" }, 533c602fabSXin LI { PIMV1_TYPE_ASSERT, "Assert" }, 543c602fabSXin LI { PIMV1_TYPE_GRAFT, "Graft" }, 553c602fabSXin LI { PIMV1_TYPE_GRAFT_ACK, "Graft-ACK" }, 563c602fabSXin LI { 0, NULL } 573c602fabSXin LI }; 583c602fabSXin LI 59c1ad1296SSam Leffler #define PIMV2_TYPE_HELLO 0 60c1ad1296SSam Leffler #define PIMV2_TYPE_REGISTER 1 61c1ad1296SSam Leffler #define PIMV2_TYPE_REGISTER_STOP 2 62c1ad1296SSam Leffler #define PIMV2_TYPE_JOIN_PRUNE 3 63c1ad1296SSam Leffler #define PIMV2_TYPE_BOOTSTRAP 4 64c1ad1296SSam Leffler #define PIMV2_TYPE_ASSERT 5 65c1ad1296SSam Leffler #define PIMV2_TYPE_GRAFT 6 66c1ad1296SSam Leffler #define PIMV2_TYPE_GRAFT_ACK 7 67c1ad1296SSam Leffler #define PIMV2_TYPE_CANDIDATE_RP 8 68c1ad1296SSam Leffler #define PIMV2_TYPE_PRUNE_REFRESH 9 693c602fabSXin LI #define PIMV2_TYPE_DF_ELECTION 10 703c602fabSXin LI #define PIMV2_TYPE_ECMP_REDIRECT 11 71c1ad1296SSam Leffler 723c602fabSXin LI static const struct tok pimv2_type_values[] = { 73c1ad1296SSam Leffler { PIMV2_TYPE_HELLO, "Hello" }, 74c1ad1296SSam Leffler { PIMV2_TYPE_REGISTER, "Register" }, 75c1ad1296SSam Leffler { PIMV2_TYPE_REGISTER_STOP, "Register Stop" }, 76c1ad1296SSam Leffler { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" }, 77c1ad1296SSam Leffler { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" }, 78c1ad1296SSam Leffler { PIMV2_TYPE_ASSERT, "Assert" }, 79c1ad1296SSam Leffler { PIMV2_TYPE_GRAFT, "Graft" }, 80c1ad1296SSam Leffler { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" }, 81c1ad1296SSam Leffler { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" }, 82c1ad1296SSam Leffler { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" }, 833c602fabSXin LI { PIMV2_TYPE_DF_ELECTION, "DF Election" }, 843c602fabSXin LI { PIMV2_TYPE_ECMP_REDIRECT, "ECMP Redirect" }, 85c1ad1296SSam Leffler { 0, NULL} 86c1ad1296SSam Leffler }; 87c1ad1296SSam Leffler 88c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_HOLDTIME 1 89c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2 90c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18 91c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_DR_PRIORITY 19 92c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_GENID 20 93c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_REFRESH_CAP 21 94c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_BIDIR_CAP 22 95c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_ADDRESS_LIST 24 96c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001 97c1ad1296SSam Leffler 983c602fabSXin LI static const struct tok pimv2_hello_option_values[] = { 99c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" }, 100c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" }, 101c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" }, 102c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" }, 103c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_GENID, "Generation ID" }, 104c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" }, 105c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" }, 106c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" }, 107c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" }, 108c1ad1296SSam Leffler { 0, NULL} 109c1ad1296SSam Leffler }; 110c1ad1296SSam Leffler 111abf25193SMax Laier #define PIMV2_REGISTER_FLAG_LEN 4 112abf25193SMax Laier #define PIMV2_REGISTER_FLAG_BORDER 0x80000000 113abf25193SMax Laier #define PIMV2_REGISTER_FLAG_NULL 0x40000000 114abf25193SMax Laier 1153c602fabSXin LI static const struct tok pimv2_register_flag_values[] = { 116abf25193SMax Laier { PIMV2_REGISTER_FLAG_BORDER, "Border" }, 117abf25193SMax Laier { PIMV2_REGISTER_FLAG_NULL, "Null" }, 118abf25193SMax Laier { 0, NULL} 119abf25193SMax Laier }; 120b0453382SBill Fenner 121*ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_OFFER 1 122*ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_WINNER 2 123*ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_BACKOFF 3 124*ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_PASS 4 125*ee67461eSJoseph Mingrone 126*ee67461eSJoseph Mingrone static const struct tok pimv2_df_election_flag_values[] = { 127*ee67461eSJoseph Mingrone { PIMV2_DF_ELECTION_OFFER, "Offer" }, 128*ee67461eSJoseph Mingrone { PIMV2_DF_ELECTION_WINNER, "Winner" }, 129*ee67461eSJoseph Mingrone { PIMV2_DF_ELECTION_BACKOFF, "Backoff" }, 130*ee67461eSJoseph Mingrone { PIMV2_DF_ELECTION_PASS, "Pass" }, 131*ee67461eSJoseph Mingrone { 0, NULL} 132*ee67461eSJoseph Mingrone }; 133*ee67461eSJoseph Mingrone 134*ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_PASS_BACKOFF_STR(x) ( \ 135*ee67461eSJoseph Mingrone x == PIMV2_DF_ELECTION_BACKOFF ? "offer" : "new winner" ) 136*ee67461eSJoseph Mingrone 137*ee67461eSJoseph Mingrone 138b0453382SBill Fenner /* 139b0453382SBill Fenner * XXX: We consider a case where IPv6 is not ready yet for portability, 140*ee67461eSJoseph Mingrone * but PIM dependent definitions should be independent of IPv6... 141b0453382SBill Fenner */ 142b0453382SBill Fenner 143b0453382SBill Fenner struct pim { 144*ee67461eSJoseph Mingrone nd_uint8_t pim_typever; 1459537d84eSBill Fenner /* upper 4bit: PIM version number; 2 for PIMv2 */ 1469537d84eSBill Fenner /* lower 4bit: the PIM message type, currently they are: 147b0453382SBill Fenner * Hello, Register, Register-Stop, Join/Prune, 148b0453382SBill Fenner * Bootstrap, Assert, Graft (PIM-DM only), 149b0453382SBill Fenner * Graft-Ack (PIM-DM only), C-RP-Adv 150b0453382SBill Fenner */ 1519537d84eSBill Fenner #define PIM_VER(x) (((x) & 0xf0) >> 4) 1529537d84eSBill Fenner #define PIM_TYPE(x) ((x) & 0x0f) 153*ee67461eSJoseph Mingrone nd_uint8_t pim_rsv; /* Reserved in v1, subtype+address length in v2 */ 154*ee67461eSJoseph Mingrone #define PIM_SUBTYPE(x) (((x) & 0xf0) >> 4) 155*ee67461eSJoseph Mingrone nd_uint16_t pim_cksum; /* IP style check sum */ 156b0453382SBill Fenner }; 157b0453382SBill Fenner 158*ee67461eSJoseph Mingrone static void pimv2_print(netdissect_options *, const u_char *bp, u_int len, const u_char *); 159b0453382SBill Fenner 160b0453382SBill Fenner static void 1613c602fabSXin LI pimv1_join_prune_print(netdissect_options *ndo, 162*ee67461eSJoseph Mingrone const u_char *bp, u_int len) 163b0453382SBill Fenner { 164*ee67461eSJoseph Mingrone u_int ngroups, njoin, nprune; 165*ee67461eSJoseph Mingrone u_int njp; 166b0453382SBill Fenner 167b0453382SBill Fenner /* If it's a single group and a single source, use 1-line output. */ 168*ee67461eSJoseph Mingrone if (ND_TTEST_LEN(bp, 30) && GET_U_1(bp + 11) == 1 && 169*ee67461eSJoseph Mingrone ((njoin = GET_BE_U_2(bp + 20)) + GET_BE_U_2(bp + 22)) == 1) { 170*ee67461eSJoseph Mingrone u_int hold; 171b0453382SBill Fenner 172*ee67461eSJoseph Mingrone ND_PRINT(" RPF %s ", GET_IPADDR_STRING(bp)); 173*ee67461eSJoseph Mingrone hold = GET_BE_U_2(bp + 6); 174b0453382SBill Fenner if (hold != 180) { 175*ee67461eSJoseph Mingrone ND_PRINT("Hold "); 1763340d773SGleb Smirnoff unsigned_relts_print(ndo, hold); 177b0453382SBill Fenner } 178*ee67461eSJoseph Mingrone ND_PRINT("%s (%s/%u, %s", njoin ? "Join" : "Prune", 179*ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 26), GET_U_1(bp + 25) & 0x3f, 180*ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 12)); 181*ee67461eSJoseph Mingrone if (GET_BE_U_4(bp + 16) != 0xffffffff) 182*ee67461eSJoseph Mingrone ND_PRINT("/%s", GET_IPADDR_STRING(bp + 16)); 183*ee67461eSJoseph Mingrone ND_PRINT(") %s%s %s", 184*ee67461eSJoseph Mingrone (GET_U_1(bp + 24) & 0x01) ? "Sparse" : "Dense", 185*ee67461eSJoseph Mingrone (GET_U_1(bp + 25) & 0x80) ? " WC" : "", 186*ee67461eSJoseph Mingrone (GET_U_1(bp + 25) & 0x40) ? "RP" : "SPT"); 187b0453382SBill Fenner return; 188b0453382SBill Fenner } 189b0453382SBill Fenner 190*ee67461eSJoseph Mingrone if (len < sizeof(nd_ipv4)) 1910bff6a5aSEd Maste goto trunc; 1923c602fabSXin LI if (ndo->ndo_vflag > 1) 193*ee67461eSJoseph Mingrone ND_PRINT("\n"); 194*ee67461eSJoseph Mingrone ND_PRINT(" Upstream Nbr: %s", GET_IPADDR_STRING(bp)); 1950bff6a5aSEd Maste bp += 4; 1960bff6a5aSEd Maste len -= 4; 1970bff6a5aSEd Maste if (len < 4) 1980bff6a5aSEd Maste goto trunc; 1993c602fabSXin LI if (ndo->ndo_vflag > 1) 200*ee67461eSJoseph Mingrone ND_PRINT("\n"); 201*ee67461eSJoseph Mingrone ND_PRINT(" Hold time: "); 202*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 2)); 2033c602fabSXin LI if (ndo->ndo_vflag < 2) 204a1c2090eSBill Fenner return; 2050bff6a5aSEd Maste bp += 4; 2060bff6a5aSEd Maste len -= 4; 207b0453382SBill Fenner 2080bff6a5aSEd Maste if (len < 4) 2090bff6a5aSEd Maste goto trunc; 210*ee67461eSJoseph Mingrone ngroups = GET_U_1(bp + 3); 211a1c2090eSBill Fenner bp += 4; 212a1c2090eSBill Fenner len -= 4; 213*ee67461eSJoseph Mingrone while (ngroups != 0) { 21429292c17SSam Leffler /* 21529292c17SSam Leffler * XXX - does the address have length "addrlen" and the 21629292c17SSam Leffler * mask length "maddrlen"? 21729292c17SSam Leffler */ 2180bff6a5aSEd Maste if (len < 4) 2190bff6a5aSEd Maste goto trunc; 220*ee67461eSJoseph Mingrone ND_PRINT("\n\tGroup: %s", GET_IPADDR_STRING(bp)); 2210bff6a5aSEd Maste bp += 4; 2220bff6a5aSEd Maste len -= 4; 2230bff6a5aSEd Maste if (len < 4) 2240bff6a5aSEd Maste goto trunc; 225*ee67461eSJoseph Mingrone if (GET_BE_U_4(bp) != 0xffffffff) 226*ee67461eSJoseph Mingrone ND_PRINT("/%s", GET_IPADDR_STRING(bp)); 2270bff6a5aSEd Maste bp += 4; 2280bff6a5aSEd Maste len -= 4; 2290bff6a5aSEd Maste if (len < 4) 2300bff6a5aSEd Maste goto trunc; 231*ee67461eSJoseph Mingrone njoin = GET_BE_U_2(bp); 232*ee67461eSJoseph Mingrone nprune = GET_BE_U_2(bp + 2); 233*ee67461eSJoseph Mingrone ND_PRINT(" joined: %u pruned: %u", njoin, nprune); 2340bff6a5aSEd Maste bp += 4; 2350bff6a5aSEd Maste len -= 4; 236b0453382SBill Fenner for (njp = 0; njp < (njoin + nprune); njp++) { 237cc391cceSBruce M Simpson const char *type; 238b0453382SBill Fenner 239a1c2090eSBill Fenner if (njp < njoin) 240b0453382SBill Fenner type = "Join "; 241a1c2090eSBill Fenner else 242b0453382SBill Fenner type = "Prune"; 2430bff6a5aSEd Maste if (len < 6) 2440bff6a5aSEd Maste goto trunc; 245*ee67461eSJoseph Mingrone ND_PRINT("\n\t%s %s%s%s%s/%u", type, 246*ee67461eSJoseph Mingrone (GET_U_1(bp) & 0x01) ? "Sparse " : "Dense ", 247*ee67461eSJoseph Mingrone (GET_U_1(bp + 1) & 0x80) ? "WC " : "", 248*ee67461eSJoseph Mingrone (GET_U_1(bp + 1) & 0x40) ? "RP " : "SPT ", 249*ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 2), 250*ee67461eSJoseph Mingrone GET_U_1(bp + 1) & 0x3f); 251a1c2090eSBill Fenner bp += 6; 252a1c2090eSBill Fenner len -= 6; 253b0453382SBill Fenner } 254*ee67461eSJoseph Mingrone ngroups--; 255b0453382SBill Fenner } 256b0453382SBill Fenner return; 257b0453382SBill Fenner trunc: 258*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 259b0453382SBill Fenner } 2604edb46e9SPaul Traina 2614edb46e9SPaul Traina void 2623c602fabSXin LI pimv1_print(netdissect_options *ndo, 263*ee67461eSJoseph Mingrone const u_char *bp, u_int len) 2644edb46e9SPaul Traina { 265*ee67461eSJoseph Mingrone u_char type; 2664edb46e9SPaul Traina 267*ee67461eSJoseph Mingrone ndo->ndo_protocol = "pimv1"; 268*ee67461eSJoseph Mingrone type = GET_U_1(bp + 1); 2694edb46e9SPaul Traina 270*ee67461eSJoseph Mingrone ND_PRINT(" %s", tok2str(pimv1_type_str, "[type %u]", type)); 2714edb46e9SPaul Traina switch (type) { 2723c602fabSXin LI case PIMV1_TYPE_QUERY: 273*ee67461eSJoseph Mingrone if (ND_TTEST_1(bp + 8)) { 274*ee67461eSJoseph Mingrone switch (GET_U_1(bp + 8) >> 4) { 275a1c2090eSBill Fenner case 0: 276*ee67461eSJoseph Mingrone ND_PRINT(" Dense-mode"); 277b0453382SBill Fenner break; 278a1c2090eSBill Fenner case 1: 279*ee67461eSJoseph Mingrone ND_PRINT(" Sparse-mode"); 280b0453382SBill Fenner break; 281a1c2090eSBill Fenner case 2: 282*ee67461eSJoseph Mingrone ND_PRINT(" Sparse-Dense-mode"); 283b0453382SBill Fenner break; 284a1c2090eSBill Fenner default: 285*ee67461eSJoseph Mingrone ND_PRINT(" mode-%u", GET_U_1(bp + 8) >> 4); 286b0453382SBill Fenner break; 287b0453382SBill Fenner } 288b0453382SBill Fenner } 2893c602fabSXin LI if (ndo->ndo_vflag) { 290*ee67461eSJoseph Mingrone ND_PRINT(" (Hold-time "); 291*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 10)); 292*ee67461eSJoseph Mingrone ND_PRINT(")"); 293b0453382SBill Fenner } 2944edb46e9SPaul Traina break; 2954edb46e9SPaul Traina 2963c602fabSXin LI case PIMV1_TYPE_REGISTER: 297*ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp + 8, 20); /* ip header */ 298*ee67461eSJoseph Mingrone ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 20), 299*ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 24)); 3004edb46e9SPaul Traina break; 3013c602fabSXin LI case PIMV1_TYPE_REGISTER_STOP: 302*ee67461eSJoseph Mingrone ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 8), 303*ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 12)); 3044edb46e9SPaul Traina break; 3053c602fabSXin LI case PIMV1_TYPE_RP_REACHABILITY: 3063c602fabSXin LI if (ndo->ndo_vflag) { 307*ee67461eSJoseph Mingrone ND_PRINT(" group %s", GET_IPADDR_STRING(bp + 8)); 308*ee67461eSJoseph Mingrone if (GET_BE_U_4(bp + 12) != 0xffffffff) 309*ee67461eSJoseph Mingrone ND_PRINT("/%s", GET_IPADDR_STRING(bp + 12)); 310*ee67461eSJoseph Mingrone ND_PRINT(" RP %s hold ", GET_IPADDR_STRING(bp + 16)); 311*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 22)); 312b0453382SBill Fenner } 3134edb46e9SPaul Traina break; 3143c602fabSXin LI case PIMV1_TYPE_ASSERT: 315*ee67461eSJoseph Mingrone ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 16), 316*ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 8)); 317*ee67461eSJoseph Mingrone if (GET_BE_U_4(bp + 12) != 0xffffffff) 318*ee67461eSJoseph Mingrone ND_PRINT("/%s", GET_IPADDR_STRING(bp + 12)); 319*ee67461eSJoseph Mingrone ND_PRINT(" %s pref %u metric %u", 320*ee67461eSJoseph Mingrone (GET_U_1(bp + 20) & 0x80) ? "RP-tree" : "SPT", 321*ee67461eSJoseph Mingrone GET_BE_U_4(bp + 20) & 0x7fffffff, 322*ee67461eSJoseph Mingrone GET_BE_U_4(bp + 24)); 3234edb46e9SPaul Traina break; 3243c602fabSXin LI case PIMV1_TYPE_JOIN_PRUNE: 3253c602fabSXin LI case PIMV1_TYPE_GRAFT: 3263c602fabSXin LI case PIMV1_TYPE_GRAFT_ACK: 3270bff6a5aSEd Maste if (ndo->ndo_vflag) { 3280bff6a5aSEd Maste if (len < 8) 3290bff6a5aSEd Maste goto trunc; 330*ee67461eSJoseph Mingrone pimv1_join_prune_print(ndo, bp + 8, len - 8); 3310bff6a5aSEd Maste } 3324edb46e9SPaul Traina break; 3334edb46e9SPaul Traina } 334*ee67461eSJoseph Mingrone if ((GET_U_1(bp + 4) >> 4) != 1) 335*ee67461eSJoseph Mingrone ND_PRINT(" [v%u]", GET_U_1(bp + 4) >> 4); 336b0453382SBill Fenner return; 337b0453382SBill Fenner 338b0453382SBill Fenner trunc: 339*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 340b0453382SBill Fenner } 341b0453382SBill Fenner 342b0453382SBill Fenner /* 343b0453382SBill Fenner * auto-RP is a cisco protocol, documented at 344a1c2090eSBill Fenner * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt 345a1c2090eSBill Fenner * 346a1c2090eSBill Fenner * This implements version 1+, dated Sept 9, 1998. 347b0453382SBill Fenner */ 348b0453382SBill Fenner void 3493c602fabSXin LI cisco_autorp_print(netdissect_options *ndo, 350*ee67461eSJoseph Mingrone const u_char *bp, u_int len) 351b0453382SBill Fenner { 352*ee67461eSJoseph Mingrone u_int type; 353*ee67461eSJoseph Mingrone u_int numrps; 354*ee67461eSJoseph Mingrone u_int hold; 355b0453382SBill Fenner 356*ee67461eSJoseph Mingrone ndo->ndo_protocol = "cisco_autorp"; 3570bff6a5aSEd Maste if (len < 8) 3580bff6a5aSEd Maste goto trunc; 359*ee67461eSJoseph Mingrone ND_PRINT(" auto-rp "); 360*ee67461eSJoseph Mingrone type = GET_U_1(bp); 361b0453382SBill Fenner switch (type) { 362b0453382SBill Fenner case 0x11: 363*ee67461eSJoseph Mingrone ND_PRINT("candidate-advert"); 364b0453382SBill Fenner break; 365b0453382SBill Fenner case 0x12: 366*ee67461eSJoseph Mingrone ND_PRINT("mapping"); 367b0453382SBill Fenner break; 368b0453382SBill Fenner default: 369*ee67461eSJoseph Mingrone ND_PRINT("type-0x%02x", type); 370b0453382SBill Fenner break; 371b0453382SBill Fenner } 372b0453382SBill Fenner 373*ee67461eSJoseph Mingrone numrps = GET_U_1(bp + 1); 374b0453382SBill Fenner 375*ee67461eSJoseph Mingrone ND_PRINT(" Hold "); 376*ee67461eSJoseph Mingrone hold = GET_BE_U_2(bp + 2); 377b0453382SBill Fenner if (hold) 378*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 2)); 379b0453382SBill Fenner else 380*ee67461eSJoseph Mingrone ND_PRINT("FOREVER"); 381b0453382SBill Fenner 382b0453382SBill Fenner /* Next 4 bytes are reserved. */ 383b0453382SBill Fenner 384b0453382SBill Fenner bp += 8; len -= 8; 385b0453382SBill Fenner 386b0453382SBill Fenner /*XXX skip unless -v? */ 387b0453382SBill Fenner 388b0453382SBill Fenner /* 389b0453382SBill Fenner * Rest of packet: 390b0453382SBill Fenner * numrps entries of the form: 391b0453382SBill Fenner * 32 bits: RP 392b0453382SBill Fenner * 6 bits: reserved 393b0453382SBill Fenner * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2". 394b0453382SBill Fenner * 8 bits: # of entries for this RP 395b0453382SBill Fenner * each entry: 7 bits: reserved, 1 bit: negative, 396b0453382SBill Fenner * 8 bits: mask 32 bits: source 397b0453382SBill Fenner * lather, rinse, repeat. 398b0453382SBill Fenner */ 399*ee67461eSJoseph Mingrone while (numrps != 0) { 400*ee67461eSJoseph Mingrone u_int nentries; 401b0453382SBill Fenner char s; 402b0453382SBill Fenner 4030bff6a5aSEd Maste if (len < 4) 4040bff6a5aSEd Maste goto trunc; 405*ee67461eSJoseph Mingrone ND_PRINT(" RP %s", GET_IPADDR_STRING(bp)); 4060bff6a5aSEd Maste bp += 4; 4070bff6a5aSEd Maste len -= 4; 4080bff6a5aSEd Maste if (len < 1) 4090bff6a5aSEd Maste goto trunc; 410*ee67461eSJoseph Mingrone switch (GET_U_1(bp) & 0x3) { 411*ee67461eSJoseph Mingrone case 0: ND_PRINT(" PIMv?"); 412b0453382SBill Fenner break; 413*ee67461eSJoseph Mingrone case 1: ND_PRINT(" PIMv1"); 414b0453382SBill Fenner break; 415*ee67461eSJoseph Mingrone case 2: ND_PRINT(" PIMv2"); 416b0453382SBill Fenner break; 417*ee67461eSJoseph Mingrone case 3: ND_PRINT(" PIMv1+2"); 418b0453382SBill Fenner break; 419b0453382SBill Fenner } 420*ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0xfc) 421*ee67461eSJoseph Mingrone ND_PRINT(" [rsvd=0x%02x]", GET_U_1(bp) & 0xfc); 4220bff6a5aSEd Maste bp += 1; 4230bff6a5aSEd Maste len -= 1; 4240bff6a5aSEd Maste if (len < 1) 4250bff6a5aSEd Maste goto trunc; 426*ee67461eSJoseph Mingrone nentries = GET_U_1(bp); 4270bff6a5aSEd Maste bp += 1; 4280bff6a5aSEd Maste len -= 1; 429b0453382SBill Fenner s = ' '; 430*ee67461eSJoseph Mingrone while (nentries != 0) { 4310bff6a5aSEd Maste if (len < 6) 4320bff6a5aSEd Maste goto trunc; 433*ee67461eSJoseph Mingrone ND_PRINT("%c%s%s/%u", s, GET_U_1(bp) & 1 ? "!" : "", 434*ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 2), GET_U_1(bp + 1)); 435*ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0x02) { 436*ee67461eSJoseph Mingrone ND_PRINT(" bidir"); 437cac3dcd5SXin LI } 438*ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0xfc) { 439*ee67461eSJoseph Mingrone ND_PRINT("[rsvd=0x%02x]", GET_U_1(bp) & 0xfc); 440cac3dcd5SXin LI } 441b0453382SBill Fenner s = ','; 442b0453382SBill Fenner bp += 6; len -= 6; 443*ee67461eSJoseph Mingrone nentries--; 444b0453382SBill Fenner } 445*ee67461eSJoseph Mingrone numrps--; 446b0453382SBill Fenner } 447b0453382SBill Fenner return; 448b0453382SBill Fenner 449b0453382SBill Fenner trunc: 450*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 451b0453382SBill Fenner } 452b0453382SBill Fenner 453b0453382SBill Fenner void 4543c602fabSXin LI pim_print(netdissect_options *ndo, 455*ee67461eSJoseph Mingrone const u_char *bp, u_int len, const u_char *bp2) 456b0453382SBill Fenner { 457*ee67461eSJoseph Mingrone const struct pim *pim = (const struct pim *)bp; 458*ee67461eSJoseph Mingrone uint8_t pim_typever; 459b0453382SBill Fenner 460*ee67461eSJoseph Mingrone ndo->ndo_protocol = "pim"; 461b0453382SBill Fenner 462*ee67461eSJoseph Mingrone pim_typever = GET_U_1(pim->pim_typever); 463*ee67461eSJoseph Mingrone switch (PIM_VER(pim_typever)) { 464c1ad1296SSam Leffler case 2: 4653c602fabSXin LI if (!ndo->ndo_vflag) { 466*ee67461eSJoseph Mingrone ND_PRINT("PIMv%u, %s, length %u", 467*ee67461eSJoseph Mingrone PIM_VER(pim_typever), 468*ee67461eSJoseph Mingrone tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim_typever)), 469*ee67461eSJoseph Mingrone len); 470c1ad1296SSam Leffler return; 471c1ad1296SSam Leffler } else { 472*ee67461eSJoseph Mingrone ND_PRINT("PIMv%u, length %u\n\t%s", 473*ee67461eSJoseph Mingrone PIM_VER(pim_typever), 474c1ad1296SSam Leffler len, 475*ee67461eSJoseph Mingrone tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim_typever))); 4763340d773SGleb Smirnoff pimv2_print(ndo, bp, len, bp2); 477c1ad1296SSam Leffler } 478b0453382SBill Fenner break; 479b0453382SBill Fenner default: 480*ee67461eSJoseph Mingrone ND_PRINT("PIMv%u, length %u", 481*ee67461eSJoseph Mingrone PIM_VER(pim_typever), 482*ee67461eSJoseph Mingrone len); 483b0453382SBill Fenner break; 484b0453382SBill Fenner } 485b0453382SBill Fenner } 486b0453382SBill Fenner 487b0453382SBill Fenner /* 488b0453382SBill Fenner * PIMv2 uses encoded address representations. 489b0453382SBill Fenner * 490b0453382SBill Fenner * The last PIM-SM I-D before RFC2117 was published specified the 491b0453382SBill Fenner * following representation for unicast addresses. However, RFC2117 492b0453382SBill Fenner * specified no encoding for unicast addresses with the unicast 493b0453382SBill Fenner * address length specified in the header. Therefore, we have to 494b0453382SBill Fenner * guess which encoding is being used (Cisco's PIMv2 implementation 495b0453382SBill Fenner * uses the non-RFC encoding). RFC2117 turns a previously "Reserved" 496b0453382SBill Fenner * field into a 'unicast-address-length-in-bytes' field. We guess 497b0453382SBill Fenner * that it's the draft encoding if this reserved field is zero. 498b0453382SBill Fenner * 499b0453382SBill Fenner * RFC2362 goes back to the encoded format, and calls the addr length 500b0453382SBill Fenner * field "reserved" again. 501b0453382SBill Fenner * 502b0453382SBill Fenner * The first byte is the address family, from: 503b0453382SBill Fenner * 504b0453382SBill Fenner * 0 Reserved 505b0453382SBill Fenner * 1 IP (IP version 4) 506b0453382SBill Fenner * 2 IP6 (IP version 6) 507b0453382SBill Fenner * 3 NSAP 508b0453382SBill Fenner * 4 HDLC (8-bit multidrop) 509b0453382SBill Fenner * 5 BBN 1822 510b0453382SBill Fenner * 6 802 (includes all 802 media plus Ethernet "canonical format") 511b0453382SBill Fenner * 7 E.163 512b0453382SBill Fenner * 8 E.164 (SMDS, Frame Relay, ATM) 513b0453382SBill Fenner * 9 F.69 (Telex) 514b0453382SBill Fenner * 10 X.121 (X.25, Frame Relay) 515b0453382SBill Fenner * 11 IPX 516b0453382SBill Fenner * 12 Appletalk 517b0453382SBill Fenner * 13 Decnet IV 518b0453382SBill Fenner * 14 Banyan Vines 519b0453382SBill Fenner * 15 E.164 with NSAP format subaddress 520b0453382SBill Fenner * 521b0453382SBill Fenner * In addition, the second byte is an "Encoding". 0 is the default 522b0453382SBill Fenner * encoding for the address family, and no other encodings are currently 523b0453382SBill Fenner * specified. 524b0453382SBill Fenner * 525b0453382SBill Fenner */ 526b0453382SBill Fenner 527b0453382SBill Fenner enum pimv2_addrtype { 528b0453382SBill Fenner pimv2_unicast, pimv2_group, pimv2_source 529b0453382SBill Fenner }; 530b0453382SBill Fenner 531b0453382SBill Fenner /* 0 1 2 3 532b0453382SBill Fenner * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 533b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 534b0453382SBill Fenner * | Addr Family | Encoding Type | Unicast Address | 535b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++ 536b0453382SBill Fenner * 0 1 2 3 537b0453382SBill Fenner * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 538b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 539b0453382SBill Fenner * | Addr Family | Encoding Type | Reserved | Mask Len | 540b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 541b0453382SBill Fenner * | Group multicast Address | 542b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 543b0453382SBill Fenner * 0 1 2 3 544b0453382SBill Fenner * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 545b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 546b0453382SBill Fenner * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len | 547b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 548b0453382SBill Fenner * | Source Address | 549b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 550b0453382SBill Fenner */ 551b0453382SBill Fenner static int 5523c602fabSXin LI pimv2_addr_print(netdissect_options *ndo, 5530bff6a5aSEd Maste const u_char *bp, u_int len, enum pimv2_addrtype at, 5540bff6a5aSEd Maste u_int addr_len, int silent) 555b0453382SBill Fenner { 556*ee67461eSJoseph Mingrone u_int af; 5570bff6a5aSEd Maste int hdrlen; 558b0453382SBill Fenner 5590bff6a5aSEd Maste if (addr_len == 0) { 5600bff6a5aSEd Maste if (len < 2) 5610bff6a5aSEd Maste goto trunc; 562*ee67461eSJoseph Mingrone switch (GET_U_1(bp)) { 563b0453382SBill Fenner case 1: 564b0453382SBill Fenner af = AF_INET; 565*ee67461eSJoseph Mingrone addr_len = (u_int)sizeof(nd_ipv4); 566b0453382SBill Fenner break; 567b0453382SBill Fenner case 2: 568b0453382SBill Fenner af = AF_INET6; 569*ee67461eSJoseph Mingrone addr_len = (u_int)sizeof(nd_ipv6); 570b0453382SBill Fenner break; 571b0453382SBill Fenner default: 572b0453382SBill Fenner return -1; 573b0453382SBill Fenner } 574*ee67461eSJoseph Mingrone if (GET_U_1(bp + 1) != 0) 575b0453382SBill Fenner return -1; 576b0453382SBill Fenner hdrlen = 2; 577b0453382SBill Fenner } else { 5780bff6a5aSEd Maste switch (addr_len) { 579*ee67461eSJoseph Mingrone case sizeof(nd_ipv4): 580b0453382SBill Fenner af = AF_INET; 581b0453382SBill Fenner break; 582*ee67461eSJoseph Mingrone case sizeof(nd_ipv6): 583b0453382SBill Fenner af = AF_INET6; 584b0453382SBill Fenner break; 585b0453382SBill Fenner default: 586b0453382SBill Fenner return -1; 587b0453382SBill Fenner break; 588b0453382SBill Fenner } 589b0453382SBill Fenner hdrlen = 0; 590b0453382SBill Fenner } 591b0453382SBill Fenner 592b0453382SBill Fenner bp += hdrlen; 5930bff6a5aSEd Maste len -= hdrlen; 594b0453382SBill Fenner switch (at) { 595b0453382SBill Fenner case pimv2_unicast: 5960bff6a5aSEd Maste if (len < addr_len) 5970bff6a5aSEd Maste goto trunc; 598*ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, addr_len); 599b0453382SBill Fenner if (af == AF_INET) { 600b0453382SBill Fenner if (!silent) 601*ee67461eSJoseph Mingrone ND_PRINT("%s", GET_IPADDR_STRING(bp)); 602b0453382SBill Fenner } 603b0453382SBill Fenner else if (af == AF_INET6) { 604b0453382SBill Fenner if (!silent) 605*ee67461eSJoseph Mingrone ND_PRINT("%s", GET_IP6ADDR_STRING(bp)); 606b0453382SBill Fenner } 6070bff6a5aSEd Maste return hdrlen + addr_len; 608b0453382SBill Fenner case pimv2_group: 609b0453382SBill Fenner case pimv2_source: 6100bff6a5aSEd Maste if (len < addr_len + 2) 6110bff6a5aSEd Maste goto trunc; 612*ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, addr_len + 2); 613b0453382SBill Fenner if (af == AF_INET) { 614b0453382SBill Fenner if (!silent) { 615*ee67461eSJoseph Mingrone ND_PRINT("%s", GET_IPADDR_STRING(bp + 2)); 616*ee67461eSJoseph Mingrone if (GET_U_1(bp + 1) != 32) 617*ee67461eSJoseph Mingrone ND_PRINT("/%u", GET_U_1(bp + 1)); 618b0453382SBill Fenner } 619b0453382SBill Fenner } 620b0453382SBill Fenner else if (af == AF_INET6) { 621b0453382SBill Fenner if (!silent) { 622*ee67461eSJoseph Mingrone ND_PRINT("%s", GET_IP6ADDR_STRING(bp + 2)); 623*ee67461eSJoseph Mingrone if (GET_U_1(bp + 1) != 128) 624*ee67461eSJoseph Mingrone ND_PRINT("/%u", GET_U_1(bp + 1)); 625b0453382SBill Fenner } 626b0453382SBill Fenner } 627*ee67461eSJoseph Mingrone if (GET_U_1(bp) && !silent) { 628b0453382SBill Fenner if (at == pimv2_group) { 629*ee67461eSJoseph Mingrone ND_PRINT("(0x%02x)", GET_U_1(bp)); 630b0453382SBill Fenner } else { 631*ee67461eSJoseph Mingrone ND_PRINT("(%s%s%s", 632*ee67461eSJoseph Mingrone GET_U_1(bp) & 0x04 ? "S" : "", 633*ee67461eSJoseph Mingrone GET_U_1(bp) & 0x02 ? "W" : "", 634*ee67461eSJoseph Mingrone GET_U_1(bp) & 0x01 ? "R" : ""); 635*ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0xf8) { 636*ee67461eSJoseph Mingrone ND_PRINT("+0x%02x", 637*ee67461eSJoseph Mingrone GET_U_1(bp) & 0xf8); 638b0453382SBill Fenner } 639*ee67461eSJoseph Mingrone ND_PRINT(")"); 640b0453382SBill Fenner } 641b0453382SBill Fenner } 6420bff6a5aSEd Maste return hdrlen + 2 + addr_len; 643b0453382SBill Fenner default: 644b0453382SBill Fenner return -1; 645b0453382SBill Fenner } 646b0453382SBill Fenner trunc: 647b0453382SBill Fenner return -1; 648b0453382SBill Fenner } 649b0453382SBill Fenner 6503340d773SGleb Smirnoff enum checksum_status { 6513340d773SGleb Smirnoff CORRECT, 6523340d773SGleb Smirnoff INCORRECT, 6533340d773SGleb Smirnoff UNVERIFIED 6543340d773SGleb Smirnoff }; 6553340d773SGleb Smirnoff 6563340d773SGleb Smirnoff static enum checksum_status 6573340d773SGleb Smirnoff pimv2_check_checksum(netdissect_options *ndo, const u_char *bp, 6583340d773SGleb Smirnoff const u_char *bp2, u_int len) 6593340d773SGleb Smirnoff { 6603340d773SGleb Smirnoff const struct ip *ip; 6613340d773SGleb Smirnoff u_int cksum; 6623340d773SGleb Smirnoff 663*ee67461eSJoseph Mingrone if (!ND_TTEST_LEN(bp, len)) { 6643340d773SGleb Smirnoff /* We don't have all the data. */ 6653340d773SGleb Smirnoff return (UNVERIFIED); 6663340d773SGleb Smirnoff } 6673340d773SGleb Smirnoff ip = (const struct ip *)bp2; 6683340d773SGleb Smirnoff if (IP_V(ip) == 4) { 6693340d773SGleb Smirnoff struct cksum_vec vec[1]; 6703340d773SGleb Smirnoff 6713340d773SGleb Smirnoff vec[0].ptr = bp; 6723340d773SGleb Smirnoff vec[0].len = len; 6733340d773SGleb Smirnoff cksum = in_cksum(vec, 1); 6743340d773SGleb Smirnoff return (cksum ? INCORRECT : CORRECT); 6753340d773SGleb Smirnoff } else if (IP_V(ip) == 6) { 6763340d773SGleb Smirnoff const struct ip6_hdr *ip6; 6773340d773SGleb Smirnoff 6783340d773SGleb Smirnoff ip6 = (const struct ip6_hdr *)bp2; 6793340d773SGleb Smirnoff cksum = nextproto6_cksum(ndo, ip6, bp, len, len, IPPROTO_PIM); 6803340d773SGleb Smirnoff return (cksum ? INCORRECT : CORRECT); 6813340d773SGleb Smirnoff } else { 6823340d773SGleb Smirnoff return (UNVERIFIED); 6833340d773SGleb Smirnoff } 6843340d773SGleb Smirnoff } 6853340d773SGleb Smirnoff 686b0453382SBill Fenner static void 6873c602fabSXin LI pimv2_print(netdissect_options *ndo, 688*ee67461eSJoseph Mingrone const u_char *bp, u_int len, const u_char *bp2) 689b0453382SBill Fenner { 690*ee67461eSJoseph Mingrone const struct pim *pim = (const struct pim *)bp; 691b0453382SBill Fenner int advance; 692*ee67461eSJoseph Mingrone int subtype; 6933340d773SGleb Smirnoff enum checksum_status cksum_status; 694*ee67461eSJoseph Mingrone u_int pim_typever; 695*ee67461eSJoseph Mingrone u_int pimv2_addr_len; 696b0453382SBill Fenner 697*ee67461eSJoseph Mingrone ndo->ndo_protocol = "pimv2"; 698*ee67461eSJoseph Mingrone if (len < 2) { 699*ee67461eSJoseph Mingrone ND_PRINT("[length %u < 2]", len); 700*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 701*ee67461eSJoseph Mingrone return; 702*ee67461eSJoseph Mingrone } 703*ee67461eSJoseph Mingrone pim_typever = GET_U_1(pim->pim_typever); 704*ee67461eSJoseph Mingrone /* RFC5015 allocates the high 4 bits of pim_rsv for "subtype". */ 705*ee67461eSJoseph Mingrone pimv2_addr_len = GET_U_1(pim->pim_rsv) & 0x0f; 706b0453382SBill Fenner if (pimv2_addr_len != 0) 707*ee67461eSJoseph Mingrone ND_PRINT(", RFC2117-encoding"); 708b0453382SBill Fenner 709*ee67461eSJoseph Mingrone if (len < 4) { 710*ee67461eSJoseph Mingrone ND_PRINT("[length %u < 4]", len); 711*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 712*ee67461eSJoseph Mingrone return; 713*ee67461eSJoseph Mingrone } 714*ee67461eSJoseph Mingrone ND_PRINT(", cksum 0x%04x ", GET_BE_U_2(pim->pim_cksum)); 715*ee67461eSJoseph Mingrone if (GET_BE_U_2(pim->pim_cksum) == 0) { 716*ee67461eSJoseph Mingrone ND_PRINT("(unverified)"); 717abf25193SMax Laier } else { 718*ee67461eSJoseph Mingrone if (PIM_TYPE(pim_typever) == PIMV2_TYPE_REGISTER) { 7193340d773SGleb Smirnoff /* 7203340d773SGleb Smirnoff * The checksum only covers the packet header, 7213340d773SGleb Smirnoff * not the encapsulated packet. 7223340d773SGleb Smirnoff */ 7233340d773SGleb Smirnoff cksum_status = pimv2_check_checksum(ndo, bp, bp2, 8); 7243340d773SGleb Smirnoff if (cksum_status == INCORRECT) { 7253340d773SGleb Smirnoff /* 7263340d773SGleb Smirnoff * To quote RFC 4601, "For interoperability 7273340d773SGleb Smirnoff * reasons, a message carrying a checksum 7283340d773SGleb Smirnoff * calculated over the entire PIM Register 7293340d773SGleb Smirnoff * message should also be accepted." 7303340d773SGleb Smirnoff */ 7313340d773SGleb Smirnoff cksum_status = pimv2_check_checksum(ndo, bp, bp2, len); 7323340d773SGleb Smirnoff } 7333340d773SGleb Smirnoff } else { 7343340d773SGleb Smirnoff /* 7353340d773SGleb Smirnoff * The checksum covers the entire packet. 7363340d773SGleb Smirnoff */ 7373340d773SGleb Smirnoff cksum_status = pimv2_check_checksum(ndo, bp, bp2, len); 7383340d773SGleb Smirnoff } 7393340d773SGleb Smirnoff switch (cksum_status) { 7403340d773SGleb Smirnoff 7413340d773SGleb Smirnoff case CORRECT: 742*ee67461eSJoseph Mingrone ND_PRINT("(correct)"); 7433340d773SGleb Smirnoff break; 7443340d773SGleb Smirnoff 7453340d773SGleb Smirnoff case INCORRECT: 746*ee67461eSJoseph Mingrone ND_PRINT("(incorrect)"); 7473340d773SGleb Smirnoff break; 7483340d773SGleb Smirnoff 7493340d773SGleb Smirnoff case UNVERIFIED: 750*ee67461eSJoseph Mingrone ND_PRINT("(unverified)"); 7513340d773SGleb Smirnoff break; 7523340d773SGleb Smirnoff } 753abf25193SMax Laier } 7540bff6a5aSEd Maste bp += 4; 7550bff6a5aSEd Maste len -= 4; 756abf25193SMax Laier 757*ee67461eSJoseph Mingrone switch (PIM_TYPE(pim_typever)) { 758c1ad1296SSam Leffler case PIMV2_TYPE_HELLO: 759b0453382SBill Fenner { 7603c602fabSXin LI uint16_t otype, olen; 7610bff6a5aSEd Maste while (len > 0) { 7620bff6a5aSEd Maste if (len < 4) 7630bff6a5aSEd Maste goto trunc; 764*ee67461eSJoseph Mingrone otype = GET_BE_U_2(bp); 765*ee67461eSJoseph Mingrone olen = GET_BE_U_2(bp + 2); 766*ee67461eSJoseph Mingrone ND_PRINT("\n\t %s Option (%u), length %u, Value: ", 767c1ad1296SSam Leffler tok2str(pimv2_hello_option_values, "Unknown", otype), 768c1ad1296SSam Leffler otype, 769*ee67461eSJoseph Mingrone olen); 770c1ad1296SSam Leffler bp += 4; 7710bff6a5aSEd Maste len -= 4; 772c1ad1296SSam Leffler 7730bff6a5aSEd Maste if (len < olen) 7740bff6a5aSEd Maste goto trunc; 775*ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, olen); 776b0453382SBill Fenner switch (otype) { 777c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_HOLDTIME: 7780bff6a5aSEd Maste if (olen != 2) { 779*ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 2]", olen); 780*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 781*ee67461eSJoseph Mingrone return; 7820bff6a5aSEd Maste } else { 783*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, 784*ee67461eSJoseph Mingrone GET_BE_U_2(bp)); 7850bff6a5aSEd Maste } 786b0453382SBill Fenner break; 787b0453382SBill Fenner 788c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_LANPRUNEDELAY: 789cc391cceSBruce M Simpson if (olen != 4) { 790*ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 4]", olen); 791*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 792*ee67461eSJoseph Mingrone return; 793cc391cceSBruce M Simpson } else { 794cc391cceSBruce M Simpson char t_bit; 7953c602fabSXin LI uint16_t lan_delay, override_interval; 796*ee67461eSJoseph Mingrone lan_delay = GET_BE_U_2(bp); 797*ee67461eSJoseph Mingrone override_interval = GET_BE_U_2(bp + 2); 798cc391cceSBruce M Simpson t_bit = (lan_delay & 0x8000)? 1 : 0; 799cc391cceSBruce M Simpson lan_delay &= ~0x8000; 800*ee67461eSJoseph Mingrone ND_PRINT("\n\t T-bit=%u, LAN delay %ums, Override interval %ums", 801*ee67461eSJoseph Mingrone t_bit, lan_delay, override_interval); 802cc391cceSBruce M Simpson } 803cc391cceSBruce M Simpson break; 804cc391cceSBruce M Simpson 805c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD: 806c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_DR_PRIORITY: 807c1ad1296SSam Leffler switch (olen) { 808c1ad1296SSam Leffler case 0: 809*ee67461eSJoseph Mingrone ND_PRINT("Bi-Directional Capability (Old)"); 8100e0def19SBill Fenner break; 811c1ad1296SSam Leffler case 4: 812*ee67461eSJoseph Mingrone ND_PRINT("%u", GET_BE_U_4(bp)); 813c1ad1296SSam Leffler break; 814c1ad1296SSam Leffler default: 815*ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 4]", olen); 816*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 817*ee67461eSJoseph Mingrone return; 8180e0def19SBill Fenner break; 8190e0def19SBill Fenner } 820c1ad1296SSam Leffler break; 821c1ad1296SSam Leffler 822c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_GENID: 8230bff6a5aSEd Maste if (olen != 4) { 824*ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 4]", olen); 825*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 826*ee67461eSJoseph Mingrone return; 8270bff6a5aSEd Maste } else { 828*ee67461eSJoseph Mingrone ND_PRINT("0x%08x", GET_BE_U_4(bp)); 8290bff6a5aSEd Maste } 830c1ad1296SSam Leffler break; 831c1ad1296SSam Leffler 832c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_REFRESH_CAP: 8330bff6a5aSEd Maste if (olen != 4) { 834*ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 4]", olen); 835*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 836*ee67461eSJoseph Mingrone return; 8370bff6a5aSEd Maste } else { 838*ee67461eSJoseph Mingrone ND_PRINT("v%u", GET_U_1(bp)); 839*ee67461eSJoseph Mingrone if (GET_U_1(bp + 1) != 0) { 840*ee67461eSJoseph Mingrone ND_PRINT(", interval "); 841*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, 842*ee67461eSJoseph Mingrone GET_U_1(bp + 1)); 843c1ad1296SSam Leffler } 844*ee67461eSJoseph Mingrone if (GET_BE_U_2(bp + 2) != 0) { 845*ee67461eSJoseph Mingrone ND_PRINT(" ?0x%04x?", 846*ee67461eSJoseph Mingrone GET_BE_U_2(bp + 2)); 847a1c2090eSBill Fenner } 8480bff6a5aSEd Maste } 849b0453382SBill Fenner break; 850b0453382SBill Fenner 851c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_BIDIR_CAP: 852b0453382SBill Fenner break; 853b0453382SBill Fenner 854c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD: 855c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_ADDRESS_LIST: 8563c602fabSXin LI if (ndo->ndo_vflag > 1) { 857c1ad1296SSam Leffler const u_char *ptr = bp; 8580bff6a5aSEd Maste u_int plen = len; 859c1ad1296SSam Leffler while (ptr < (bp+olen)) { 860*ee67461eSJoseph Mingrone ND_PRINT("\n\t "); 8610bff6a5aSEd Maste advance = pimv2_addr_print(ndo, ptr, plen, pimv2_unicast, pimv2_addr_len, 0); 8620bff6a5aSEd Maste if (advance < 0) 8630bff6a5aSEd Maste goto trunc; 864cc391cceSBruce M Simpson ptr += advance; 8650bff6a5aSEd Maste plen -= advance; 866cc391cceSBruce M Simpson } 867cc391cceSBruce M Simpson } 868cc391cceSBruce M Simpson break; 869b0453382SBill Fenner default: 8703c602fabSXin LI if (ndo->ndo_vflag <= 1) 8713c602fabSXin LI print_unknown_data(ndo, bp, "\n\t ", olen); 872c1ad1296SSam Leffler break; 873b0453382SBill Fenner } 874c1ad1296SSam Leffler /* do we want to see an additionally hexdump ? */ 8753c602fabSXin LI if (ndo->ndo_vflag> 1) 8763c602fabSXin LI print_unknown_data(ndo, bp, "\n\t ", olen); 877c1ad1296SSam Leffler bp += olen; 8780bff6a5aSEd Maste len -= olen; 879b0453382SBill Fenner } 880b0453382SBill Fenner break; 881b0453382SBill Fenner } 882b0453382SBill Fenner 883c1ad1296SSam Leffler case PIMV2_TYPE_REGISTER: 884b0453382SBill Fenner { 8853340d773SGleb Smirnoff const struct ip *ip; 886b0453382SBill Fenner 8870bff6a5aSEd Maste if (len < 4) 8880bff6a5aSEd Maste goto trunc; 889*ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, PIMV2_REGISTER_FLAG_LEN); 890b0453382SBill Fenner 891*ee67461eSJoseph Mingrone ND_PRINT(", Flags [ %s ]\n\t", 892abf25193SMax Laier tok2str(pimv2_register_flag_values, 893abf25193SMax Laier "none", 894*ee67461eSJoseph Mingrone GET_BE_U_4(bp))); 895abf25193SMax Laier 8960bff6a5aSEd Maste bp += 4; len -= 4; 897b0453382SBill Fenner /* encapsulated multicast packet */ 8980bff6a5aSEd Maste if (len == 0) 8990bff6a5aSEd Maste goto trunc; 9003340d773SGleb Smirnoff ip = (const struct ip *)bp; 901943ee2b1SBill Fenner switch (IP_V(ip)) { 902abf25193SMax Laier case 0: /* Null header */ 903*ee67461eSJoseph Mingrone ND_PRINT("IP-Null-header %s > %s", 904*ee67461eSJoseph Mingrone GET_IPADDR_STRING(ip->ip_src), 905*ee67461eSJoseph Mingrone GET_IPADDR_STRING(ip->ip_dst)); 906abf25193SMax Laier break; 907abf25193SMax Laier 908b0453382SBill Fenner case 4: /* IPv4 */ 9093c602fabSXin LI ip_print(ndo, bp, len); 910b0453382SBill Fenner break; 9118bdc5a62SPatrick Kelsey 912b0453382SBill Fenner case 6: /* IPv6 */ 9133c602fabSXin LI ip6_print(ndo, bp, len); 914b0453382SBill Fenner break; 9158bdc5a62SPatrick Kelsey 916b0453382SBill Fenner default: 917*ee67461eSJoseph Mingrone ND_PRINT("IP ver %u", IP_V(ip)); 918b0453382SBill Fenner break; 919b0453382SBill Fenner } 920b0453382SBill Fenner break; 921b0453382SBill Fenner } 922b0453382SBill Fenner 923c1ad1296SSam Leffler case PIMV2_TYPE_REGISTER_STOP: 924*ee67461eSJoseph Mingrone ND_PRINT(" group="); 9250bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) 9260bff6a5aSEd Maste goto trunc; 927b0453382SBill Fenner bp += advance; len -= advance; 928*ee67461eSJoseph Mingrone ND_PRINT(" source="); 9290bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) 9300bff6a5aSEd Maste goto trunc; 931b0453382SBill Fenner bp += advance; len -= advance; 932b0453382SBill Fenner break; 933b0453382SBill Fenner 934c1ad1296SSam Leffler case PIMV2_TYPE_JOIN_PRUNE: 935c1ad1296SSam Leffler case PIMV2_TYPE_GRAFT: 936c1ad1296SSam Leffler case PIMV2_TYPE_GRAFT_ACK: 937c1ad1296SSam Leffler 938c1ad1296SSam Leffler 939c1ad1296SSam Leffler /* 940c1ad1296SSam Leffler * 0 1 2 3 941c1ad1296SSam Leffler * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 942c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 943c1ad1296SSam Leffler * |PIM Ver| Type | Addr length | Checksum | 944c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 945c1ad1296SSam Leffler * | Unicast-Upstream Neighbor Address | 946c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 947c1ad1296SSam Leffler * | Reserved | Num groups | Holdtime | 948c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 949c1ad1296SSam Leffler * | Encoded-Multicast Group Address-1 | 950c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 951c1ad1296SSam Leffler * | Number of Joined Sources | Number of Pruned Sources | 952c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 953c1ad1296SSam Leffler * | Encoded-Joined Source Address-1 | 954c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 955c1ad1296SSam Leffler * | . | 956c1ad1296SSam Leffler * | . | 957c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 958c1ad1296SSam Leffler * | Encoded-Joined Source Address-n | 959c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 960c1ad1296SSam Leffler * | Encoded-Pruned Source Address-1 | 961c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 962c1ad1296SSam Leffler * | . | 963c1ad1296SSam Leffler * | . | 964c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 965c1ad1296SSam Leffler * | Encoded-Pruned Source Address-n | 966c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 967c1ad1296SSam Leffler * | . | 968c1ad1296SSam Leffler * | . | 969c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 970c1ad1296SSam Leffler * | Encoded-Multicast Group Address-n | 971c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 972c1ad1296SSam Leffler */ 973c1ad1296SSam Leffler 974b0453382SBill Fenner { 9753c602fabSXin LI uint8_t ngroup; 9763c602fabSXin LI uint16_t holdtime; 9773c602fabSXin LI uint16_t njoin; 9783c602fabSXin LI uint16_t nprune; 979*ee67461eSJoseph Mingrone u_int i, j; 980b0453382SBill Fenner 981*ee67461eSJoseph Mingrone if (PIM_TYPE(pim_typever) != 7) { /*not for Graft-ACK*/ 982*ee67461eSJoseph Mingrone ND_PRINT(", upstream-neighbor: "); 9830bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) 9840bff6a5aSEd Maste goto trunc; 985b0453382SBill Fenner bp += advance; len -= advance; 986b0453382SBill Fenner } 9870bff6a5aSEd Maste if (len < 4) 9880bff6a5aSEd Maste goto trunc; 989*ee67461eSJoseph Mingrone ND_TCHECK_4(bp); 990*ee67461eSJoseph Mingrone ngroup = GET_U_1(bp + 1); 991*ee67461eSJoseph Mingrone holdtime = GET_BE_U_2(bp + 2); 992*ee67461eSJoseph Mingrone ND_PRINT("\n\t %u group(s)", ngroup); 993*ee67461eSJoseph Mingrone if (PIM_TYPE(pim_typever) != 7) { /*not for Graft-ACK*/ 994*ee67461eSJoseph Mingrone ND_PRINT(", holdtime: "); 995b0453382SBill Fenner if (holdtime == 0xffff) 996*ee67461eSJoseph Mingrone ND_PRINT("infinite"); 997b0453382SBill Fenner else 9983340d773SGleb Smirnoff unsigned_relts_print(ndo, holdtime); 999b0453382SBill Fenner } 1000b0453382SBill Fenner bp += 4; len -= 4; 1001b0453382SBill Fenner for (i = 0; i < ngroup; i++) { 1002*ee67461eSJoseph Mingrone ND_PRINT("\n\t group #%u: ", i+1); 10030bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) 10040bff6a5aSEd Maste goto trunc; 1005b0453382SBill Fenner bp += advance; len -= advance; 10060bff6a5aSEd Maste if (len < 4) 10070bff6a5aSEd Maste goto trunc; 1008*ee67461eSJoseph Mingrone ND_TCHECK_4(bp); 1009*ee67461eSJoseph Mingrone njoin = GET_BE_U_2(bp); 1010*ee67461eSJoseph Mingrone nprune = GET_BE_U_2(bp + 2); 1011*ee67461eSJoseph Mingrone ND_PRINT(", joined sources: %u, pruned sources: %u", njoin, nprune); 1012b0453382SBill Fenner bp += 4; len -= 4; 1013b0453382SBill Fenner for (j = 0; j < njoin; j++) { 1014*ee67461eSJoseph Mingrone ND_PRINT("\n\t joined source #%u: ", j+1); 10150bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0) 10160bff6a5aSEd Maste goto trunc; 1017b0453382SBill Fenner bp += advance; len -= advance; 1018b0453382SBill Fenner } 1019b0453382SBill Fenner for (j = 0; j < nprune; j++) { 1020*ee67461eSJoseph Mingrone ND_PRINT("\n\t pruned source #%u: ", j+1); 10210bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0) 10220bff6a5aSEd Maste goto trunc; 1023b0453382SBill Fenner bp += advance; len -= advance; 1024b0453382SBill Fenner } 1025b0453382SBill Fenner } 1026b0453382SBill Fenner break; 1027b0453382SBill Fenner } 1028b0453382SBill Fenner 1029c1ad1296SSam Leffler case PIMV2_TYPE_BOOTSTRAP: 1030b0453382SBill Fenner { 1031*ee67461eSJoseph Mingrone u_int i, j, frpcnt; 1032b0453382SBill Fenner 1033b0453382SBill Fenner /* Fragment Tag, Hash Mask len, and BSR-priority */ 10340bff6a5aSEd Maste if (len < 2) 10350bff6a5aSEd Maste goto trunc; 1036*ee67461eSJoseph Mingrone ND_PRINT(" tag=%x", GET_BE_U_2(bp)); 10370bff6a5aSEd Maste bp += 2; 10380bff6a5aSEd Maste len -= 2; 10390bff6a5aSEd Maste if (len < 1) 10400bff6a5aSEd Maste goto trunc; 1041*ee67461eSJoseph Mingrone ND_PRINT(" hashmlen=%u", GET_U_1(bp)); 10420bff6a5aSEd Maste if (len < 2) 10430bff6a5aSEd Maste goto trunc; 1044*ee67461eSJoseph Mingrone ND_TCHECK_1(bp + 2); 1045*ee67461eSJoseph Mingrone ND_PRINT(" BSRprio=%u", GET_U_1(bp + 1)); 1046b0453382SBill Fenner bp += 2; 10470bff6a5aSEd Maste len -= 2; 1048b0453382SBill Fenner 1049b0453382SBill Fenner /* Encoded-Unicast-BSR-Address */ 1050*ee67461eSJoseph Mingrone ND_PRINT(" BSR="); 10510bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) 10520bff6a5aSEd Maste goto trunc; 1053b0453382SBill Fenner bp += advance; 10540bff6a5aSEd Maste len -= advance; 1055b0453382SBill Fenner 10560bff6a5aSEd Maste for (i = 0; len > 0; i++) { 1057b0453382SBill Fenner /* Encoded-Group Address */ 1058*ee67461eSJoseph Mingrone ND_PRINT(" (group%u: ", i); 10590bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) 10600bff6a5aSEd Maste goto trunc; 1061b0453382SBill Fenner bp += advance; 10620bff6a5aSEd Maste len -= advance; 1063b0453382SBill Fenner 1064b0453382SBill Fenner /* RP-Count, Frag RP-Cnt, and rsvd */ 10650bff6a5aSEd Maste if (len < 1) 10660bff6a5aSEd Maste goto trunc; 1067*ee67461eSJoseph Mingrone ND_PRINT(" RPcnt=%u", GET_U_1(bp)); 10680bff6a5aSEd Maste if (len < 2) 10690bff6a5aSEd Maste goto trunc; 1070*ee67461eSJoseph Mingrone frpcnt = GET_U_1(bp + 1); 1071*ee67461eSJoseph Mingrone ND_PRINT(" FRPcnt=%u", frpcnt); 10720bff6a5aSEd Maste if (len < 4) 10730bff6a5aSEd Maste goto trunc; 1074b0453382SBill Fenner bp += 4; 10750bff6a5aSEd Maste len -= 4; 1076b0453382SBill Fenner 10770bff6a5aSEd Maste for (j = 0; j < frpcnt && len > 0; j++) { 1078b0453382SBill Fenner /* each RP info */ 1079*ee67461eSJoseph Mingrone ND_PRINT(" RP%u=", j); 10800bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, 1081b0453382SBill Fenner pimv2_unicast, 10820bff6a5aSEd Maste pimv2_addr_len, 10830bff6a5aSEd Maste 0)) < 0) 10840bff6a5aSEd Maste goto trunc; 1085b0453382SBill Fenner bp += advance; 10860bff6a5aSEd Maste len -= advance; 1087b0453382SBill Fenner 10880bff6a5aSEd Maste if (len < 2) 10890bff6a5aSEd Maste goto trunc; 1090*ee67461eSJoseph Mingrone ND_PRINT(",holdtime="); 1091*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, 1092*ee67461eSJoseph Mingrone GET_BE_U_2(bp)); 10930bff6a5aSEd Maste if (len < 3) 10940bff6a5aSEd Maste goto trunc; 1095*ee67461eSJoseph Mingrone ND_PRINT(",prio=%u", GET_U_1(bp + 2)); 10960bff6a5aSEd Maste if (len < 4) 10970bff6a5aSEd Maste goto trunc; 1098b0453382SBill Fenner bp += 4; 10990bff6a5aSEd Maste len -= 4; 1100b0453382SBill Fenner } 1101*ee67461eSJoseph Mingrone ND_PRINT(")"); 1102b0453382SBill Fenner } 1103b0453382SBill Fenner break; 1104b0453382SBill Fenner } 1105c1ad1296SSam Leffler case PIMV2_TYPE_ASSERT: 1106*ee67461eSJoseph Mingrone ND_PRINT(" group="); 11070bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) 11080bff6a5aSEd Maste goto trunc; 1109b0453382SBill Fenner bp += advance; len -= advance; 1110*ee67461eSJoseph Mingrone ND_PRINT(" src="); 11110bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) 11120bff6a5aSEd Maste goto trunc; 1113b0453382SBill Fenner bp += advance; len -= advance; 11140bff6a5aSEd Maste if (len < 8) 11150bff6a5aSEd Maste goto trunc; 1116*ee67461eSJoseph Mingrone ND_TCHECK_8(bp); 1117*ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0x80) 1118*ee67461eSJoseph Mingrone ND_PRINT(" RPT"); 1119*ee67461eSJoseph Mingrone ND_PRINT(" pref=%u", GET_BE_U_4(bp) & 0x7fffffff); 1120*ee67461eSJoseph Mingrone ND_PRINT(" metric=%u", GET_BE_U_4(bp + 4)); 1121b0453382SBill Fenner break; 1122b0453382SBill Fenner 1123c1ad1296SSam Leffler case PIMV2_TYPE_CANDIDATE_RP: 1124b0453382SBill Fenner { 1125*ee67461eSJoseph Mingrone u_int i, pfxcnt; 1126b0453382SBill Fenner 1127b0453382SBill Fenner /* Prefix-Cnt, Priority, and Holdtime */ 11280bff6a5aSEd Maste if (len < 1) 11290bff6a5aSEd Maste goto trunc; 1130*ee67461eSJoseph Mingrone ND_PRINT(" prefix-cnt=%u", GET_U_1(bp)); 1131*ee67461eSJoseph Mingrone pfxcnt = GET_U_1(bp); 11320bff6a5aSEd Maste if (len < 2) 11330bff6a5aSEd Maste goto trunc; 1134*ee67461eSJoseph Mingrone ND_PRINT(" prio=%u", GET_U_1(bp + 1)); 11350bff6a5aSEd Maste if (len < 4) 11360bff6a5aSEd Maste goto trunc; 1137*ee67461eSJoseph Mingrone ND_PRINT(" holdtime="); 1138*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 2)); 1139b0453382SBill Fenner bp += 4; 11400bff6a5aSEd Maste len -= 4; 1141b0453382SBill Fenner 1142b0453382SBill Fenner /* Encoded-Unicast-RP-Address */ 1143*ee67461eSJoseph Mingrone ND_PRINT(" RP="); 11440bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) 11450bff6a5aSEd Maste goto trunc; 1146b0453382SBill Fenner bp += advance; 11470bff6a5aSEd Maste len -= advance; 1148b0453382SBill Fenner 1149b0453382SBill Fenner /* Encoded-Group Addresses */ 11500bff6a5aSEd Maste for (i = 0; i < pfxcnt && len > 0; i++) { 1151*ee67461eSJoseph Mingrone ND_PRINT(" Group%u=", i); 11520bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) 11530bff6a5aSEd Maste goto trunc; 1154b0453382SBill Fenner bp += advance; 11550bff6a5aSEd Maste len -= advance; 1156b0453382SBill Fenner } 1157b0453382SBill Fenner break; 1158b0453382SBill Fenner } 1159b0453382SBill Fenner 1160c1ad1296SSam Leffler case PIMV2_TYPE_PRUNE_REFRESH: 1161*ee67461eSJoseph Mingrone ND_PRINT(" src="); 11620bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) 11630bff6a5aSEd Maste goto trunc; 1164b0453382SBill Fenner bp += advance; 11650bff6a5aSEd Maste len -= advance; 1166*ee67461eSJoseph Mingrone ND_PRINT(" grp="); 11670bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) 11680bff6a5aSEd Maste goto trunc; 1169b0453382SBill Fenner bp += advance; 11700bff6a5aSEd Maste len -= advance; 1171*ee67461eSJoseph Mingrone ND_PRINT(" forwarder="); 11720bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) 11730bff6a5aSEd Maste goto trunc; 1174b0453382SBill Fenner bp += advance; 11750bff6a5aSEd Maste len -= advance; 11760bff6a5aSEd Maste if (len < 2) 11770bff6a5aSEd Maste goto trunc; 1178*ee67461eSJoseph Mingrone ND_PRINT(" TUNR "); 1179*ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp)); 1180b0453382SBill Fenner break; 1181b0453382SBill Fenner 1182*ee67461eSJoseph Mingrone case PIMV2_TYPE_DF_ELECTION: 1183*ee67461eSJoseph Mingrone subtype = PIM_SUBTYPE(GET_U_1(pim->pim_rsv)); 1184*ee67461eSJoseph Mingrone ND_PRINT("\n\t %s,", tok2str( pimv2_df_election_flag_values, 1185*ee67461eSJoseph Mingrone "Unknown", subtype) ); 1186*ee67461eSJoseph Mingrone 1187*ee67461eSJoseph Mingrone ND_PRINT(" rpa="); 1188*ee67461eSJoseph Mingrone if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) { 1189*ee67461eSJoseph Mingrone goto trunc; 1190*ee67461eSJoseph Mingrone } 1191*ee67461eSJoseph Mingrone bp += advance; 1192*ee67461eSJoseph Mingrone len -= advance; 1193*ee67461eSJoseph Mingrone ND_PRINT(" sender pref=%u", GET_BE_U_4(bp) ); 1194*ee67461eSJoseph Mingrone ND_PRINT(" sender metric=%u", GET_BE_U_4(bp + 4)); 1195*ee67461eSJoseph Mingrone 1196*ee67461eSJoseph Mingrone bp += 8; 1197*ee67461eSJoseph Mingrone len -= 8; 1198*ee67461eSJoseph Mingrone 1199*ee67461eSJoseph Mingrone switch (subtype) { 1200*ee67461eSJoseph Mingrone case PIMV2_DF_ELECTION_BACKOFF: 1201*ee67461eSJoseph Mingrone case PIMV2_DF_ELECTION_PASS: 1202*ee67461eSJoseph Mingrone ND_PRINT("\n\t %s addr=", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype)); 1203*ee67461eSJoseph Mingrone if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) { 1204*ee67461eSJoseph Mingrone goto trunc; 1205*ee67461eSJoseph Mingrone } 1206*ee67461eSJoseph Mingrone bp += advance; 1207*ee67461eSJoseph Mingrone len -= advance; 1208*ee67461eSJoseph Mingrone 1209*ee67461eSJoseph Mingrone ND_PRINT(" %s pref=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp) ); 1210*ee67461eSJoseph Mingrone ND_PRINT(" %s metric=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp + 4)); 1211*ee67461eSJoseph Mingrone 1212*ee67461eSJoseph Mingrone bp += 8; 1213*ee67461eSJoseph Mingrone len -= 8; 1214*ee67461eSJoseph Mingrone 1215*ee67461eSJoseph Mingrone if (subtype == PIMV2_DF_ELECTION_BACKOFF) { 1216*ee67461eSJoseph Mingrone ND_PRINT(" interval %dms", GET_BE_U_2(bp)); 1217*ee67461eSJoseph Mingrone } 1218*ee67461eSJoseph Mingrone 1219*ee67461eSJoseph Mingrone break; 1220*ee67461eSJoseph Mingrone default: 1221*ee67461eSJoseph Mingrone break; 1222*ee67461eSJoseph Mingrone } 1223*ee67461eSJoseph Mingrone break; 1224b0453382SBill Fenner 1225b0453382SBill Fenner default: 1226*ee67461eSJoseph Mingrone ND_PRINT(" [type %u]", PIM_TYPE(pim_typever)); 1227b0453382SBill Fenner break; 1228b0453382SBill Fenner } 1229b0453382SBill Fenner 1230b0453382SBill Fenner return; 1231b0453382SBill Fenner 1232b0453382SBill Fenner trunc: 1233*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 12344edb46e9SPaul Traina } 1235