1cac3dcd5SXin LI /* 2cac3dcd5SXin LI * Copyright (c) 2007-2011 Grégoire Henry, Juliusz Chroboczek 3cac3dcd5SXin LI * 4cac3dcd5SXin LI * Redistribution and use in source and binary forms, with or without 5cac3dcd5SXin LI * modification, are permitted provided that the following conditions 6cac3dcd5SXin LI * are met: 7cac3dcd5SXin LI * 1. Redistributions of source code must retain the above copyright 8cac3dcd5SXin LI * notice, this list of conditions and the following disclaimer. 9cac3dcd5SXin LI * 2. Redistributions in binary form must reproduce the above copyright 10cac3dcd5SXin LI * notice, this list of conditions and the following disclaimer in the 11cac3dcd5SXin LI * documentation and/or other materials provided with the distribution. 12cac3dcd5SXin LI * 3. Neither the name of the project nor the names of its contributors 13cac3dcd5SXin LI * may be used to endorse or promote products derived from this software 14cac3dcd5SXin LI * without specific prior written permission. 15cac3dcd5SXin LI * 16cac3dcd5SXin LI * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 17cac3dcd5SXin LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18cac3dcd5SXin LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19cac3dcd5SXin LI * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 20cac3dcd5SXin LI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21cac3dcd5SXin LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22cac3dcd5SXin LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23cac3dcd5SXin LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24cac3dcd5SXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25cac3dcd5SXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26cac3dcd5SXin LI * SUCH DAMAGE. 27cac3dcd5SXin LI */ 28cac3dcd5SXin LI 293340d773SGleb Smirnoff /* \summary: Babel Routing Protocol printer */ 30*ee67461eSJoseph Mingrone /* Specifications: 31*ee67461eSJoseph Mingrone * 32*ee67461eSJoseph Mingrone * RFC 6126 33*ee67461eSJoseph Mingrone * RFC 7298 34*ee67461eSJoseph Mingrone * RFC 7557 35*ee67461eSJoseph Mingrone * draft-ietf-babel-rfc6126bis-17 36*ee67461eSJoseph Mingrone * draft-ietf-babel-hmac-10 37*ee67461eSJoseph Mingrone * draft-ietf-babel-source-specific-0 38*ee67461eSJoseph Mingrone */ 393340d773SGleb Smirnoff 40cac3dcd5SXin LI #ifdef HAVE_CONFIG_H 41*ee67461eSJoseph Mingrone #include <config.h> 42cac3dcd5SXin LI #endif 43cac3dcd5SXin LI 44*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 45cac3dcd5SXin LI 46cac3dcd5SXin LI #include <stdio.h> 47cac3dcd5SXin LI #include <string.h> 48cac3dcd5SXin LI 493340d773SGleb Smirnoff #include "netdissect.h" 503c602fabSXin LI #include "addrtoname.h" 51cac3dcd5SXin LI #include "extract.h" 52cac3dcd5SXin LI 533c602fabSXin LI static void babel_print_v2(netdissect_options *, const u_char *cp, u_int length); 54cac3dcd5SXin LI 55cac3dcd5SXin LI void 563c602fabSXin LI babel_print(netdissect_options *ndo, 578bdc5a62SPatrick Kelsey const u_char *cp, u_int length) 588bdc5a62SPatrick Kelsey { 59*ee67461eSJoseph Mingrone ndo->ndo_protocol = "babel"; 60*ee67461eSJoseph Mingrone ND_PRINT("babel"); 61cac3dcd5SXin LI 62*ee67461eSJoseph Mingrone ND_TCHECK_4(cp); 63cac3dcd5SXin LI 64*ee67461eSJoseph Mingrone if(GET_U_1(cp) != 42) { 65*ee67461eSJoseph Mingrone ND_PRINT(" invalid header"); 66cac3dcd5SXin LI return; 67cac3dcd5SXin LI } else { 68*ee67461eSJoseph Mingrone ND_PRINT(" %u", GET_U_1(cp + 1)); 69cac3dcd5SXin LI } 70cac3dcd5SXin LI 71*ee67461eSJoseph Mingrone switch(GET_U_1(cp + 1)) { 72cac3dcd5SXin LI case 2: 733c602fabSXin LI babel_print_v2(ndo, cp, length); 74cac3dcd5SXin LI break; 75cac3dcd5SXin LI default: 76*ee67461eSJoseph Mingrone ND_PRINT(" unknown version"); 77cac3dcd5SXin LI break; 78cac3dcd5SXin LI } 79cac3dcd5SXin LI 80cac3dcd5SXin LI return; 81cac3dcd5SXin LI 82cac3dcd5SXin LI trunc: 83*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 84cac3dcd5SXin LI } 85cac3dcd5SXin LI 863c602fabSXin LI /* TLVs */ 87cac3dcd5SXin LI #define MESSAGE_PAD1 0 88cac3dcd5SXin LI #define MESSAGE_PADN 1 89cac3dcd5SXin LI #define MESSAGE_ACK_REQ 2 90cac3dcd5SXin LI #define MESSAGE_ACK 3 91cac3dcd5SXin LI #define MESSAGE_HELLO 4 92cac3dcd5SXin LI #define MESSAGE_IHU 5 93cac3dcd5SXin LI #define MESSAGE_ROUTER_ID 6 94cac3dcd5SXin LI #define MESSAGE_NH 7 95cac3dcd5SXin LI #define MESSAGE_UPDATE 8 96*ee67461eSJoseph Mingrone #define MESSAGE_ROUTE_REQUEST 9 97*ee67461eSJoseph Mingrone #define MESSAGE_SEQNO_REQUEST 10 98d03c0883SXin LI #define MESSAGE_TSPC 11 99d03c0883SXin LI #define MESSAGE_HMAC 12 100*ee67461eSJoseph Mingrone #define MESSAGE_UPDATE_SRC_SPECIFIC 13 /* last appearance in draft-boutier-babel-source-specific-01 */ 101*ee67461eSJoseph Mingrone #define MESSAGE_REQUEST_SRC_SPECIFIC 14 /* idem */ 102*ee67461eSJoseph Mingrone #define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15 /* idem */ 103*ee67461eSJoseph Mingrone #define MESSAGE_MAC 16 104*ee67461eSJoseph Mingrone #define MESSAGE_PC 17 105*ee67461eSJoseph Mingrone #define MESSAGE_CHALLENGE_REQUEST 18 106*ee67461eSJoseph Mingrone #define MESSAGE_CHALLENGE_REPLY 19 107cac3dcd5SXin LI 1083c602fabSXin LI /* sub-TLVs */ 1093c602fabSXin LI #define MESSAGE_SUB_PAD1 0 1103c602fabSXin LI #define MESSAGE_SUB_PADN 1 1113c602fabSXin LI #define MESSAGE_SUB_DIVERSITY 2 1123c602fabSXin LI #define MESSAGE_SUB_TIMESTAMP 3 1133c602fabSXin LI 114*ee67461eSJoseph Mingrone /* "Mandatory" bit in sub-TLV types */ 115*ee67461eSJoseph Mingrone #define MANDATORY_MASK 0x80 116*ee67461eSJoseph Mingrone 117*ee67461eSJoseph Mingrone /* Flags for the Hello TLV */ 118*ee67461eSJoseph Mingrone #define UNICAST_MASK 0x8000 119*ee67461eSJoseph Mingrone 1203c602fabSXin LI /* Diversity sub-TLV channel codes */ 1213c602fabSXin LI static const struct tok diversity_str[] = { 1223c602fabSXin LI { 0, "reserved" }, 1233c602fabSXin LI { 255, "all" }, 1243c602fabSXin LI { 0, NULL } 1253c602fabSXin LI }; 1263c602fabSXin LI 127cac3dcd5SXin LI static const char * 128*ee67461eSJoseph Mingrone format_id(netdissect_options *ndo, const u_char *id) 129cac3dcd5SXin LI { 130cac3dcd5SXin LI static char buf[25]; 131cac3dcd5SXin LI snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 132*ee67461eSJoseph Mingrone GET_U_1(id), GET_U_1(id + 1), GET_U_1(id + 2), 133*ee67461eSJoseph Mingrone GET_U_1(id + 3), GET_U_1(id + 4), GET_U_1(id + 5), 134*ee67461eSJoseph Mingrone GET_U_1(id + 6), GET_U_1(id + 7)); 135cac3dcd5SXin LI buf[24] = '\0'; 136cac3dcd5SXin LI return buf; 137cac3dcd5SXin LI } 138cac3dcd5SXin LI 139cac3dcd5SXin LI static const unsigned char v4prefix[16] = 140cac3dcd5SXin LI {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 141cac3dcd5SXin LI 142cac3dcd5SXin LI static const char * 1433c602fabSXin LI format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen) 144cac3dcd5SXin LI { 145cac3dcd5SXin LI static char buf[50]; 146*ee67461eSJoseph Mingrone 147*ee67461eSJoseph Mingrone /* 148*ee67461eSJoseph Mingrone * prefix points to a buffer on the stack into which the prefix has 149*ee67461eSJoseph Mingrone * been placed, so we can't use GET_IPADDR_STRING() or 150*ee67461eSJoseph Mingrone * GET_IP6ADDR_STRING() on it. 151*ee67461eSJoseph Mingrone */ 152cac3dcd5SXin LI if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0) 1533c602fabSXin LI snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96); 154cac3dcd5SXin LI else 1553c602fabSXin LI snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen); 156cac3dcd5SXin LI buf[49] = '\0'; 157cac3dcd5SXin LI return buf; 158cac3dcd5SXin LI } 159cac3dcd5SXin LI 160cac3dcd5SXin LI static const char * 1613c602fabSXin LI format_address(netdissect_options *ndo, const u_char *prefix) 162cac3dcd5SXin LI { 163*ee67461eSJoseph Mingrone /* 164*ee67461eSJoseph Mingrone * prefix points to a buffer on the stack into which the prefix has 165*ee67461eSJoseph Mingrone * been placed, so we can't use GET_IPADDR_STRING() or 166*ee67461eSJoseph Mingrone * GET_IP6ADDR_STRING() on it. 167*ee67461eSJoseph Mingrone */ 168cac3dcd5SXin LI if(memcmp(prefix, v4prefix, 12) == 0) 1693c602fabSXin LI return ipaddr_string(ndo, prefix + 12); 170cac3dcd5SXin LI else 1713c602fabSXin LI return ip6addr_string(ndo, prefix); 172cac3dcd5SXin LI } 173cac3dcd5SXin LI 1743c602fabSXin LI static const char * 1753c602fabSXin LI format_interval(const uint16_t i) 1763c602fabSXin LI { 1773c602fabSXin LI static char buf[sizeof("000.00s")]; 1783c602fabSXin LI 1793c602fabSXin LI if (i == 0) 1803c602fabSXin LI return "0.0s (bogus)"; 1813c602fabSXin LI snprintf(buf, sizeof(buf), "%u.%02us", i / 100, i % 100); 1823c602fabSXin LI return buf; 1833c602fabSXin LI } 1843c602fabSXin LI 1853c602fabSXin LI static const char * 1863c602fabSXin LI format_interval_update(const uint16_t i) 1873c602fabSXin LI { 1883c602fabSXin LI return i == 0xFFFF ? "infinity" : format_interval(i); 1893c602fabSXin LI } 1903c602fabSXin LI 1913c602fabSXin LI static const char * 1923c602fabSXin LI format_timestamp(const uint32_t i) 1933c602fabSXin LI { 1943c602fabSXin LI static char buf[sizeof("0000.000000s")]; 1953c602fabSXin LI snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000); 1963c602fabSXin LI return buf; 1973c602fabSXin LI } 1983c602fabSXin LI 1993c602fabSXin LI /* Return number of octets consumed from the input buffer (not the prefix length 2003c602fabSXin LI * in bytes), or -1 for encoding error. */ 201cac3dcd5SXin LI static int 202cac3dcd5SXin LI network_prefix(int ae, int plen, unsigned int omitted, 203cac3dcd5SXin LI const unsigned char *p, const unsigned char *dp, 204cac3dcd5SXin LI unsigned int len, unsigned char *p_r) 205cac3dcd5SXin LI { 206cac3dcd5SXin LI unsigned pb; 207cac3dcd5SXin LI unsigned char prefix[16]; 2083c602fabSXin LI int consumed = 0; 209cac3dcd5SXin LI 210cac3dcd5SXin LI if(plen >= 0) 211cac3dcd5SXin LI pb = (plen + 7) / 8; 212cac3dcd5SXin LI else if(ae == 1) 213cac3dcd5SXin LI pb = 4; 214cac3dcd5SXin LI else 215cac3dcd5SXin LI pb = 16; 216cac3dcd5SXin LI 217cac3dcd5SXin LI if(pb > 16) 218cac3dcd5SXin LI return -1; 219cac3dcd5SXin LI 220cac3dcd5SXin LI memset(prefix, 0, 16); 221cac3dcd5SXin LI 222cac3dcd5SXin LI switch(ae) { 223cac3dcd5SXin LI case 0: break; 224cac3dcd5SXin LI case 1: 225cac3dcd5SXin LI if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) 226cac3dcd5SXin LI return -1; 227cac3dcd5SXin LI memcpy(prefix, v4prefix, 12); 228cac3dcd5SXin LI if(omitted) { 229cac3dcd5SXin LI if (dp == NULL) return -1; 230cac3dcd5SXin LI memcpy(prefix, dp, 12 + omitted); 231cac3dcd5SXin LI } 2323c602fabSXin LI if(pb > omitted) { 2333c602fabSXin LI memcpy(prefix + 12 + omitted, p, pb - omitted); 2343c602fabSXin LI consumed = pb - omitted; 2353c602fabSXin LI } 236cac3dcd5SXin LI break; 237cac3dcd5SXin LI case 2: 238cac3dcd5SXin LI if(omitted > 16 || (pb > omitted && len < pb - omitted)) 239cac3dcd5SXin LI return -1; 240cac3dcd5SXin LI if(omitted) { 241cac3dcd5SXin LI if (dp == NULL) return -1; 242cac3dcd5SXin LI memcpy(prefix, dp, omitted); 243cac3dcd5SXin LI } 2443c602fabSXin LI if(pb > omitted) { 2453c602fabSXin LI memcpy(prefix + omitted, p, pb - omitted); 2463c602fabSXin LI consumed = pb - omitted; 2473c602fabSXin LI } 248cac3dcd5SXin LI break; 249cac3dcd5SXin LI case 3: 250cac3dcd5SXin LI if(pb > 8 && len < pb - 8) return -1; 251cac3dcd5SXin LI prefix[0] = 0xfe; 252cac3dcd5SXin LI prefix[1] = 0x80; 2533c602fabSXin LI if(pb > 8) { 2543c602fabSXin LI memcpy(prefix + 8, p, pb - 8); 2553c602fabSXin LI consumed = pb - 8; 2563c602fabSXin LI } 257cac3dcd5SXin LI break; 258cac3dcd5SXin LI default: 259cac3dcd5SXin LI return -1; 260cac3dcd5SXin LI } 261cac3dcd5SXin LI 262cac3dcd5SXin LI memcpy(p_r, prefix, 16); 2633c602fabSXin LI return consumed; 264cac3dcd5SXin LI } 265cac3dcd5SXin LI 266cac3dcd5SXin LI static int 267cac3dcd5SXin LI network_address(int ae, const unsigned char *a, unsigned int len, 268cac3dcd5SXin LI unsigned char *a_r) 269cac3dcd5SXin LI { 270cac3dcd5SXin LI return network_prefix(ae, -1, 0, a, NULL, len, a_r); 271cac3dcd5SXin LI } 272cac3dcd5SXin LI 2733c602fabSXin LI /* 2743c602fabSXin LI * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126), 2753c602fabSXin LI * their encoding is similar to the encoding of TLVs, but the type namespace is 2763c602fabSXin LI * different: 2773c602fabSXin LI * 2783c602fabSXin LI * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV. 2793c602fabSXin LI * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV. 2803c602fabSXin LI * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing 2813c602fabSXin LI * data. Its body is a variable-length sequence of 8-bit unsigned integers, 282*ee67461eSJoseph Mingrone * each representing per-hop number of interfering radio channel for the 2833c602fabSXin LI * prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel 2843c602fabSXin LI * 255 interferes with any other channel. 2853c602fabSXin LI * o Type 3 stands for Timestamp sub-TLV, used to compute RTT between 2863c602fabSXin LI * neighbours. In the case of a Hello TLV, the body stores a 32-bits 2873c602fabSXin LI * timestamp, while in the case of a IHU TLV, two 32-bits timestamps are 2883c602fabSXin LI * stored. 2893c602fabSXin LI * 2903c602fabSXin LI * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is 2913c602fabSXin LI * only valid for TLV type 8 (Update). Note that within an Update TLV a missing 2923c602fabSXin LI * Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body. 2933c602fabSXin LI * The former would mean a lack of any claims about the interference, and the 2943c602fabSXin LI * latter would state that interference is definitely absent. 2953c602fabSXin LI * A type 3 sub-TLV is valid both for Hello and IHU TLVs, though the exact 2963c602fabSXin LI * semantic of the sub-TLV is different in each case. 2973c602fabSXin LI */ 2983c602fabSXin LI static void 2993c602fabSXin LI subtlvs_print(netdissect_options *ndo, 3008bdc5a62SPatrick Kelsey const u_char *cp, const u_char *ep, const uint8_t tlv_type) 3018bdc5a62SPatrick Kelsey { 3023c602fabSXin LI uint8_t subtype, sublen; 3033c602fabSXin LI const char *sep; 3043c602fabSXin LI uint32_t t1, t2; 3053c602fabSXin LI 3063c602fabSXin LI while (cp < ep) { 307*ee67461eSJoseph Mingrone subtype = GET_U_1(cp); 308*ee67461eSJoseph Mingrone cp++; 3093c602fabSXin LI if(subtype == MESSAGE_SUB_PAD1) { 310*ee67461eSJoseph Mingrone ND_PRINT(" sub-pad1"); 3113c602fabSXin LI continue; 3123c602fabSXin LI } 313*ee67461eSJoseph Mingrone if ((MANDATORY_MASK & subtype) != 0) 314*ee67461eSJoseph Mingrone ND_PRINT(" (M)"); 3153c602fabSXin LI if(cp == ep) 3163340d773SGleb Smirnoff goto invalid; 317*ee67461eSJoseph Mingrone sublen = GET_U_1(cp); 318*ee67461eSJoseph Mingrone cp++; 3193c602fabSXin LI if(cp + sublen > ep) 3203340d773SGleb Smirnoff goto invalid; 3213c602fabSXin LI 3223c602fabSXin LI switch(subtype) { 3233c602fabSXin LI case MESSAGE_SUB_PADN: 324*ee67461eSJoseph Mingrone ND_PRINT(" sub-padn"); 3253c602fabSXin LI cp += sublen; 3263c602fabSXin LI break; 3273c602fabSXin LI case MESSAGE_SUB_DIVERSITY: 328*ee67461eSJoseph Mingrone ND_PRINT(" sub-diversity"); 3293c602fabSXin LI if (sublen == 0) { 330*ee67461eSJoseph Mingrone ND_PRINT(" empty"); 3313c602fabSXin LI break; 3323c602fabSXin LI } 3333c602fabSXin LI sep = " "; 334*ee67461eSJoseph Mingrone while (sublen) { 335*ee67461eSJoseph Mingrone ND_PRINT("%s%s", sep, 336*ee67461eSJoseph Mingrone tok2str(diversity_str, "%u", GET_U_1(cp))); 337*ee67461eSJoseph Mingrone cp++; 3383c602fabSXin LI sep = "-"; 339*ee67461eSJoseph Mingrone sublen--; 3403c602fabSXin LI } 3413340d773SGleb Smirnoff if(tlv_type != MESSAGE_UPDATE && 3423340d773SGleb Smirnoff tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC) 343*ee67461eSJoseph Mingrone ND_PRINT(" (bogus)"); 3443c602fabSXin LI break; 3453c602fabSXin LI case MESSAGE_SUB_TIMESTAMP: 346*ee67461eSJoseph Mingrone ND_PRINT(" sub-timestamp"); 3473c602fabSXin LI if(tlv_type == MESSAGE_HELLO) { 3483c602fabSXin LI if(sublen < 4) 3493340d773SGleb Smirnoff goto invalid; 350*ee67461eSJoseph Mingrone t1 = GET_BE_U_4(cp); 351*ee67461eSJoseph Mingrone ND_PRINT(" %s", format_timestamp(t1)); 3523c602fabSXin LI } else if(tlv_type == MESSAGE_IHU) { 3533c602fabSXin LI if(sublen < 8) 3543340d773SGleb Smirnoff goto invalid; 355*ee67461eSJoseph Mingrone t1 = GET_BE_U_4(cp); 356*ee67461eSJoseph Mingrone ND_PRINT(" %s", format_timestamp(t1)); 357*ee67461eSJoseph Mingrone t2 = GET_BE_U_4(cp + 4); 358*ee67461eSJoseph Mingrone ND_PRINT("|%s", format_timestamp(t2)); 3593c602fabSXin LI } else 360*ee67461eSJoseph Mingrone ND_PRINT(" (bogus)"); 3613c602fabSXin LI cp += sublen; 3623c602fabSXin LI break; 3633c602fabSXin LI default: 364*ee67461eSJoseph Mingrone ND_PRINT(" sub-unknown-0x%02x", subtype); 3653c602fabSXin LI cp += sublen; 3663c602fabSXin LI } /* switch */ 3673c602fabSXin LI } /* while */ 3683c602fabSXin LI return; 3693c602fabSXin LI 3703340d773SGleb Smirnoff invalid: 371*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 3723c602fabSXin LI } 3733c602fabSXin LI 374cac3dcd5SXin LI #define ICHECK(i, l) \ 375*ee67461eSJoseph Mingrone if ((i) + (l) > tlvs_length || (i) + (l) > packet_length_remaining) \ 376*ee67461eSJoseph Mingrone goto invalid; 377cac3dcd5SXin LI 378*ee67461eSJoseph Mingrone static int 379*ee67461eSJoseph Mingrone babel_print_v2_tlvs(netdissect_options *ndo, 380*ee67461eSJoseph Mingrone const u_char *cp, u_int tlvs_length, 381*ee67461eSJoseph Mingrone u_int packet_length_remaining) 3828bdc5a62SPatrick Kelsey { 383cac3dcd5SXin LI u_int i; 384cac3dcd5SXin LI u_char v4_prefix[16] = 385cac3dcd5SXin LI {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 386cac3dcd5SXin LI u_char v6_prefix[16] = {0}; 387cac3dcd5SXin LI 388cac3dcd5SXin LI i = 0; 389*ee67461eSJoseph Mingrone while(i < tlvs_length) { 390cac3dcd5SXin LI const u_char *message; 391*ee67461eSJoseph Mingrone uint8_t type; 392*ee67461eSJoseph Mingrone u_int len; 393cac3dcd5SXin LI 394*ee67461eSJoseph Mingrone message = cp + i; 3953c602fabSXin LI 396*ee67461eSJoseph Mingrone ICHECK(i, 1); 397*ee67461eSJoseph Mingrone if((type = GET_U_1(message)) == MESSAGE_PAD1) { 398*ee67461eSJoseph Mingrone ND_PRINT(ndo->ndo_vflag ? "\n\tPad 1" : " pad1"); 3993c602fabSXin LI i += 1; 4003c602fabSXin LI continue; 4013c602fabSXin LI } 4023c602fabSXin LI 403cac3dcd5SXin LI ICHECK(i, 2); 404*ee67461eSJoseph Mingrone ND_TCHECK_2(message); 405*ee67461eSJoseph Mingrone len = GET_U_1(message + 1); 406cac3dcd5SXin LI 407cac3dcd5SXin LI ICHECK(i, 2 + len); 408*ee67461eSJoseph Mingrone ND_TCHECK_LEN(message, 2 + len); 409cac3dcd5SXin LI 410cac3dcd5SXin LI switch(type) { 411cac3dcd5SXin LI case MESSAGE_PADN: { 4123c602fabSXin LI if (!ndo->ndo_vflag) 413*ee67461eSJoseph Mingrone ND_PRINT(" padN"); 414cac3dcd5SXin LI else 415*ee67461eSJoseph Mingrone ND_PRINT("\n\tPad %u", len + 2); 416cac3dcd5SXin LI } 417cac3dcd5SXin LI break; 418cac3dcd5SXin LI 419cac3dcd5SXin LI case MESSAGE_ACK_REQ: { 420cac3dcd5SXin LI u_short nonce, interval; 4213c602fabSXin LI if (!ndo->ndo_vflag) 422*ee67461eSJoseph Mingrone ND_PRINT(" ack-req"); 423cac3dcd5SXin LI else { 424*ee67461eSJoseph Mingrone ND_PRINT("\n\tAcknowledgment Request "); 4253340d773SGleb Smirnoff if(len < 6) goto invalid; 426*ee67461eSJoseph Mingrone nonce = GET_BE_U_2(message + 4); 427*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 428*ee67461eSJoseph Mingrone ND_PRINT("%04x %s", nonce, format_interval(interval)); 429cac3dcd5SXin LI } 430cac3dcd5SXin LI } 431cac3dcd5SXin LI break; 432cac3dcd5SXin LI 433cac3dcd5SXin LI case MESSAGE_ACK: { 434cac3dcd5SXin LI u_short nonce; 4353c602fabSXin LI if (!ndo->ndo_vflag) 436*ee67461eSJoseph Mingrone ND_PRINT(" ack"); 437cac3dcd5SXin LI else { 438*ee67461eSJoseph Mingrone ND_PRINT("\n\tAcknowledgment "); 4393340d773SGleb Smirnoff if(len < 2) goto invalid; 440*ee67461eSJoseph Mingrone nonce = GET_BE_U_2(message + 2); 441*ee67461eSJoseph Mingrone ND_PRINT("%04x", nonce); 442cac3dcd5SXin LI } 443cac3dcd5SXin LI } 444cac3dcd5SXin LI break; 445cac3dcd5SXin LI 446cac3dcd5SXin LI case MESSAGE_HELLO: { 447*ee67461eSJoseph Mingrone u_short seqno, interval, unicast; 4483c602fabSXin LI if (!ndo->ndo_vflag) 449*ee67461eSJoseph Mingrone ND_PRINT(" hello"); 450cac3dcd5SXin LI else { 451*ee67461eSJoseph Mingrone ND_PRINT("\n\tHello "); 4523340d773SGleb Smirnoff if(len < 6) goto invalid; 453*ee67461eSJoseph Mingrone unicast = (GET_BE_U_2(message + 2) & UNICAST_MASK); 454*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 4); 455*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 456*ee67461eSJoseph Mingrone if(unicast) 457*ee67461eSJoseph Mingrone ND_PRINT("(Unicast) "); 458*ee67461eSJoseph Mingrone ND_PRINT("seqno %u ", seqno); 459*ee67461eSJoseph Mingrone if(interval!=0) 460*ee67461eSJoseph Mingrone ND_PRINT("interval %s", format_interval(interval)); 461*ee67461eSJoseph Mingrone else 462*ee67461eSJoseph Mingrone ND_PRINT("unscheduled"); 4633c602fabSXin LI /* Extra data. */ 4643c602fabSXin LI if(len > 6) 4653c602fabSXin LI subtlvs_print(ndo, message + 8, message + 2 + len, type); 466cac3dcd5SXin LI } 467cac3dcd5SXin LI } 468cac3dcd5SXin LI break; 469cac3dcd5SXin LI 470cac3dcd5SXin LI case MESSAGE_IHU: { 471*ee67461eSJoseph Mingrone unsigned short rxcost, interval; 4723c602fabSXin LI if (!ndo->ndo_vflag) 473*ee67461eSJoseph Mingrone ND_PRINT(" ihu"); 474cac3dcd5SXin LI else { 475cac3dcd5SXin LI u_char address[16]; 476*ee67461eSJoseph Mingrone u_char ae; 477cac3dcd5SXin LI int rc; 478*ee67461eSJoseph Mingrone ND_PRINT("\n\tIHU "); 4793340d773SGleb Smirnoff if(len < 6) goto invalid; 480*ee67461eSJoseph Mingrone rxcost = GET_BE_U_2(message + 4); 481*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 482*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 483*ee67461eSJoseph Mingrone rc = network_address(ae, message + 8, 484*ee67461eSJoseph Mingrone len - 6, address); 485*ee67461eSJoseph Mingrone if(rc < 0) { nd_print_trunc(ndo); break; } 486*ee67461eSJoseph Mingrone ND_PRINT("%s rxcost %u interval %s", 487*ee67461eSJoseph Mingrone ae == 0 ? "any" : format_address(ndo, address), 488*ee67461eSJoseph Mingrone rxcost, format_interval(interval)); 4893c602fabSXin LI /* Extra data. */ 4903c602fabSXin LI if((u_int)rc < len - 6) 4913c602fabSXin LI subtlvs_print(ndo, message + 8 + rc, message + 2 + len, 4923c602fabSXin LI type); 493cac3dcd5SXin LI } 494cac3dcd5SXin LI } 495cac3dcd5SXin LI break; 496cac3dcd5SXin LI 497cac3dcd5SXin LI case MESSAGE_ROUTER_ID: { 4983c602fabSXin LI if (!ndo->ndo_vflag) 499*ee67461eSJoseph Mingrone ND_PRINT(" router-id"); 500cac3dcd5SXin LI else { 501*ee67461eSJoseph Mingrone ND_PRINT("\n\tRouter Id"); 5023340d773SGleb Smirnoff if(len < 10) goto invalid; 503*ee67461eSJoseph Mingrone ND_PRINT(" %s", format_id(ndo, message + 4)); 504cac3dcd5SXin LI } 505cac3dcd5SXin LI } 506cac3dcd5SXin LI break; 507cac3dcd5SXin LI 508cac3dcd5SXin LI case MESSAGE_NH: { 5093c602fabSXin LI if (!ndo->ndo_vflag) 510*ee67461eSJoseph Mingrone ND_PRINT(" nh"); 511cac3dcd5SXin LI else { 512cac3dcd5SXin LI int rc; 513*ee67461eSJoseph Mingrone u_char ae; 514cac3dcd5SXin LI u_char nh[16]; 515*ee67461eSJoseph Mingrone ND_PRINT("\n\tNext Hop"); 5163340d773SGleb Smirnoff if(len < 2) goto invalid; 517*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 518*ee67461eSJoseph Mingrone rc = network_address(ae, message + 4, 519*ee67461eSJoseph Mingrone len - 2, nh); 5203340d773SGleb Smirnoff if(rc < 0) goto invalid; 521*ee67461eSJoseph Mingrone ND_PRINT(" %s", ae == 0 ? "invalid AE 0" : format_address(ndo, nh)); 522cac3dcd5SXin LI } 523cac3dcd5SXin LI } 524cac3dcd5SXin LI break; 525cac3dcd5SXin LI 526cac3dcd5SXin LI case MESSAGE_UPDATE: { 5273c602fabSXin LI if (!ndo->ndo_vflag) { 528*ee67461eSJoseph Mingrone ND_PRINT(" update"); 52939e421e8SCy Schubert if(len < 10) 530*ee67461eSJoseph Mingrone goto invalid; 531cac3dcd5SXin LI else 532*ee67461eSJoseph Mingrone ND_PRINT("%s%s%s", 533*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x80) ? "/prefix": "", 534*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x40) ? "/id" : "", 535*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x3f) ? "/unknown" : ""); 536cac3dcd5SXin LI } else { 537cac3dcd5SXin LI u_short interval, seqno, metric; 538*ee67461eSJoseph Mingrone u_char ae, plen; 539cac3dcd5SXin LI int rc; 540cac3dcd5SXin LI u_char prefix[16]; 541*ee67461eSJoseph Mingrone ND_PRINT("\n\tUpdate"); 5423340d773SGleb Smirnoff if(len < 10) goto invalid; 543*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 544*ee67461eSJoseph Mingrone plen = GET_U_1(message + 4) + (GET_U_1(message + 2) == 1 ? 96 : 0); 545*ee67461eSJoseph Mingrone rc = network_prefix(ae, 546*ee67461eSJoseph Mingrone GET_U_1(message + 4), 547*ee67461eSJoseph Mingrone GET_U_1(message + 5), 548cac3dcd5SXin LI message + 12, 549*ee67461eSJoseph Mingrone GET_U_1(message + 2) == 1 ? v4_prefix : v6_prefix, 550cac3dcd5SXin LI len - 10, prefix); 5513340d773SGleb Smirnoff if(rc < 0) goto invalid; 552*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 553*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 8); 554*ee67461eSJoseph Mingrone metric = GET_BE_U_2(message + 10); 555*ee67461eSJoseph Mingrone ND_PRINT("%s%s%s %s metric %u seqno %u interval %s", 556*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x80) ? "/prefix": "", 557*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x40) ? "/id" : "", 558*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x3f) ? "/unknown" : "", 559*ee67461eSJoseph Mingrone ae == 0 ? "any" : format_prefix(ndo, prefix, plen), 560*ee67461eSJoseph Mingrone metric, seqno, format_interval_update(interval)); 561*ee67461eSJoseph Mingrone if(GET_U_1(message + 3) & 0x80) { 562*ee67461eSJoseph Mingrone if(GET_U_1(message + 2) == 1) 563cac3dcd5SXin LI memcpy(v4_prefix, prefix, 16); 564cac3dcd5SXin LI else 565cac3dcd5SXin LI memcpy(v6_prefix, prefix, 16); 566cac3dcd5SXin LI } 5673c602fabSXin LI /* extra data? */ 5683c602fabSXin LI if((u_int)rc < len - 10) 5693c602fabSXin LI subtlvs_print(ndo, message + 12 + rc, message + 2 + len, type); 570cac3dcd5SXin LI } 571cac3dcd5SXin LI } 572cac3dcd5SXin LI break; 573cac3dcd5SXin LI 574*ee67461eSJoseph Mingrone case MESSAGE_ROUTE_REQUEST: { 5753c602fabSXin LI if (!ndo->ndo_vflag) 576*ee67461eSJoseph Mingrone ND_PRINT(" route-request"); 577cac3dcd5SXin LI else { 578cac3dcd5SXin LI int rc; 579*ee67461eSJoseph Mingrone u_char prefix[16], ae, plen; 580*ee67461eSJoseph Mingrone ND_PRINT("\n\tRoute Request "); 5813340d773SGleb Smirnoff if(len < 2) goto invalid; 582*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 583*ee67461eSJoseph Mingrone plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0); 584*ee67461eSJoseph Mingrone rc = network_prefix(ae, 585*ee67461eSJoseph Mingrone GET_U_1(message + 3), 0, 586cac3dcd5SXin LI message + 4, NULL, len - 2, prefix); 5873340d773SGleb Smirnoff if(rc < 0) goto invalid; 588*ee67461eSJoseph Mingrone ND_PRINT("for %s", 589*ee67461eSJoseph Mingrone ae == 0 ? "any" : format_prefix(ndo, prefix, plen)); 590cac3dcd5SXin LI } 591cac3dcd5SXin LI } 592cac3dcd5SXin LI break; 593cac3dcd5SXin LI 594*ee67461eSJoseph Mingrone case MESSAGE_SEQNO_REQUEST : { 5953c602fabSXin LI if (!ndo->ndo_vflag) 596*ee67461eSJoseph Mingrone ND_PRINT(" seqno-request"); 597cac3dcd5SXin LI else { 598cac3dcd5SXin LI int rc; 599cac3dcd5SXin LI u_short seqno; 600*ee67461eSJoseph Mingrone u_char prefix[16], ae, plen; 601*ee67461eSJoseph Mingrone ND_PRINT("\n\tSeqno Request "); 6023340d773SGleb Smirnoff if(len < 14) goto invalid; 603*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 604*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 4); 605*ee67461eSJoseph Mingrone rc = network_prefix(ae, 606*ee67461eSJoseph Mingrone GET_U_1(message + 3), 0, 607cac3dcd5SXin LI message + 16, NULL, len - 14, prefix); 6083340d773SGleb Smirnoff if(rc < 0) goto invalid; 609*ee67461eSJoseph Mingrone plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0); 610*ee67461eSJoseph Mingrone ND_PRINT("(%u hops) for %s seqno %u id %s", 611*ee67461eSJoseph Mingrone GET_U_1(message + 6), 612*ee67461eSJoseph Mingrone ae == 0 ? "invalid AE 0" : format_prefix(ndo, prefix, plen), 613*ee67461eSJoseph Mingrone seqno, format_id(ndo, message + 8)); 614cac3dcd5SXin LI } 615cac3dcd5SXin LI } 616cac3dcd5SXin LI break; 617d03c0883SXin LI case MESSAGE_TSPC : 6183c602fabSXin LI if (!ndo->ndo_vflag) 619*ee67461eSJoseph Mingrone ND_PRINT(" tspc"); 620d03c0883SXin LI else { 621*ee67461eSJoseph Mingrone ND_PRINT("\n\tTS/PC "); 6223340d773SGleb Smirnoff if(len < 6) goto invalid; 623*ee67461eSJoseph Mingrone ND_PRINT("timestamp %u packetcounter %u", 624*ee67461eSJoseph Mingrone GET_BE_U_4(message + 4), 625*ee67461eSJoseph Mingrone GET_BE_U_2(message + 2)); 626d03c0883SXin LI } 627d03c0883SXin LI break; 628d03c0883SXin LI case MESSAGE_HMAC : { 6293c602fabSXin LI if (!ndo->ndo_vflag) 630*ee67461eSJoseph Mingrone ND_PRINT(" hmac"); 631d03c0883SXin LI else { 632d03c0883SXin LI unsigned j; 633*ee67461eSJoseph Mingrone ND_PRINT("\n\tHMAC "); 6343340d773SGleb Smirnoff if(len < 18) goto invalid; 635*ee67461eSJoseph Mingrone ND_PRINT("key-id %u digest-%u ", GET_BE_U_2(message + 2), 636*ee67461eSJoseph Mingrone len - 2); 637d03c0883SXin LI for (j = 0; j < len - 2; j++) 638*ee67461eSJoseph Mingrone ND_PRINT("%02X", GET_U_1(message + j + 4)); 639d03c0883SXin LI } 640d03c0883SXin LI } 641d03c0883SXin LI break; 6423340d773SGleb Smirnoff 6433340d773SGleb Smirnoff case MESSAGE_UPDATE_SRC_SPECIFIC : { 6443340d773SGleb Smirnoff if(!ndo->ndo_vflag) { 645*ee67461eSJoseph Mingrone ND_PRINT(" ss-update"); 6463340d773SGleb Smirnoff } else { 6473340d773SGleb Smirnoff u_char prefix[16], src_prefix[16]; 6483340d773SGleb Smirnoff u_short interval, seqno, metric; 6493340d773SGleb Smirnoff u_char ae, plen, src_plen, omitted; 6503340d773SGleb Smirnoff int rc; 6513340d773SGleb Smirnoff int parsed_len = 10; 652*ee67461eSJoseph Mingrone ND_PRINT("\n\tSS-Update"); 6533340d773SGleb Smirnoff if(len < 10) goto invalid; 654*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 655*ee67461eSJoseph Mingrone src_plen = GET_U_1(message + 3); 656*ee67461eSJoseph Mingrone plen = GET_U_1(message + 4); 657*ee67461eSJoseph Mingrone omitted = GET_U_1(message + 5); 658*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 659*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 8); 660*ee67461eSJoseph Mingrone metric = GET_BE_U_2(message + 10); 6613340d773SGleb Smirnoff rc = network_prefix(ae, plen, omitted, message + 2 + parsed_len, 6623340d773SGleb Smirnoff ae == 1 ? v4_prefix : v6_prefix, 6633340d773SGleb Smirnoff len - parsed_len, prefix); 6643340d773SGleb Smirnoff if(rc < 0) goto invalid; 6653340d773SGleb Smirnoff if(ae == 1) 6663340d773SGleb Smirnoff plen += 96; 6673340d773SGleb Smirnoff parsed_len += rc; 6683340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 6693340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 6703340d773SGleb Smirnoff if(rc < 0) goto invalid; 6713340d773SGleb Smirnoff if(ae == 1) 6723340d773SGleb Smirnoff src_plen += 96; 6733340d773SGleb Smirnoff parsed_len += rc; 6743340d773SGleb Smirnoff 675*ee67461eSJoseph Mingrone ND_PRINT(" %s from", format_prefix(ndo, prefix, plen)); 676*ee67461eSJoseph Mingrone ND_PRINT(" %s metric %u seqno %u interval %s", 6773340d773SGleb Smirnoff format_prefix(ndo, src_prefix, src_plen), 678*ee67461eSJoseph Mingrone metric, seqno, format_interval_update(interval)); 6793340d773SGleb Smirnoff /* extra data? */ 6803340d773SGleb Smirnoff if((u_int)parsed_len < len) 6813340d773SGleb Smirnoff subtlvs_print(ndo, message + 2 + parsed_len, 6823340d773SGleb Smirnoff message + 2 + len, type); 6833340d773SGleb Smirnoff } 6843340d773SGleb Smirnoff } 6853340d773SGleb Smirnoff break; 6863340d773SGleb Smirnoff 6873340d773SGleb Smirnoff case MESSAGE_REQUEST_SRC_SPECIFIC : { 6883340d773SGleb Smirnoff if(!ndo->ndo_vflag) 689*ee67461eSJoseph Mingrone ND_PRINT(" ss-request"); 6903340d773SGleb Smirnoff else { 6913340d773SGleb Smirnoff int rc, parsed_len = 3; 6923340d773SGleb Smirnoff u_char ae, plen, src_plen, prefix[16], src_prefix[16]; 693*ee67461eSJoseph Mingrone ND_PRINT("\n\tSS-Request "); 6943340d773SGleb Smirnoff if(len < 3) goto invalid; 695*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 696*ee67461eSJoseph Mingrone plen = GET_U_1(message + 3); 697*ee67461eSJoseph Mingrone src_plen = GET_U_1(message + 4); 6983340d773SGleb Smirnoff rc = network_prefix(ae, plen, 0, message + 2 + parsed_len, 6993340d773SGleb Smirnoff NULL, len - parsed_len, prefix); 7003340d773SGleb Smirnoff if(rc < 0) goto invalid; 7013340d773SGleb Smirnoff if(ae == 1) 7023340d773SGleb Smirnoff plen += 96; 7033340d773SGleb Smirnoff parsed_len += rc; 7043340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 7053340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 7063340d773SGleb Smirnoff if(rc < 0) goto invalid; 7073340d773SGleb Smirnoff if(ae == 1) 7083340d773SGleb Smirnoff src_plen += 96; 7093340d773SGleb Smirnoff parsed_len += rc; 7103340d773SGleb Smirnoff if(ae == 0) { 711*ee67461eSJoseph Mingrone ND_PRINT("for any"); 7123340d773SGleb Smirnoff } else { 713*ee67461eSJoseph Mingrone ND_PRINT("for (%s, ", format_prefix(ndo, prefix, plen)); 714*ee67461eSJoseph Mingrone ND_PRINT("%s)", format_prefix(ndo, src_prefix, src_plen)); 7153340d773SGleb Smirnoff } 7163340d773SGleb Smirnoff } 7173340d773SGleb Smirnoff } 7183340d773SGleb Smirnoff break; 7193340d773SGleb Smirnoff 7203340d773SGleb Smirnoff case MESSAGE_MH_REQUEST_SRC_SPECIFIC : { 7213340d773SGleb Smirnoff if(!ndo->ndo_vflag) 722*ee67461eSJoseph Mingrone ND_PRINT(" ss-mh-request"); 7233340d773SGleb Smirnoff else { 7243340d773SGleb Smirnoff int rc, parsed_len = 14; 7253340d773SGleb Smirnoff u_short seqno; 7263340d773SGleb Smirnoff u_char ae, plen, src_plen, prefix[16], src_prefix[16], hopc; 7273340d773SGleb Smirnoff const u_char *router_id = NULL; 728*ee67461eSJoseph Mingrone ND_PRINT("\n\tSS-MH-Request "); 7293340d773SGleb Smirnoff if(len < 14) goto invalid; 730*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 731*ee67461eSJoseph Mingrone plen = GET_U_1(message + 3); 732*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 4); 733*ee67461eSJoseph Mingrone hopc = GET_U_1(message + 6); 734*ee67461eSJoseph Mingrone src_plen = GET_U_1(message + 7); 7353340d773SGleb Smirnoff router_id = message + 8; 7363340d773SGleb Smirnoff rc = network_prefix(ae, plen, 0, message + 2 + parsed_len, 7373340d773SGleb Smirnoff NULL, len - parsed_len, prefix); 7383340d773SGleb Smirnoff if(rc < 0) goto invalid; 7393340d773SGleb Smirnoff if(ae == 1) 7403340d773SGleb Smirnoff plen += 96; 7413340d773SGleb Smirnoff parsed_len += rc; 7423340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 7433340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 7443340d773SGleb Smirnoff if(rc < 0) goto invalid; 7453340d773SGleb Smirnoff if(ae == 1) 7463340d773SGleb Smirnoff src_plen += 96; 747*ee67461eSJoseph Mingrone ND_PRINT("(%u hops) for (%s, ", 748*ee67461eSJoseph Mingrone hopc, format_prefix(ndo, prefix, plen)); 749*ee67461eSJoseph Mingrone ND_PRINT("%s) seqno %u id %s", 7503340d773SGleb Smirnoff format_prefix(ndo, src_prefix, src_plen), 751*ee67461eSJoseph Mingrone seqno, format_id(ndo, router_id)); 752*ee67461eSJoseph Mingrone } 753*ee67461eSJoseph Mingrone } 754*ee67461eSJoseph Mingrone break; 755*ee67461eSJoseph Mingrone 756*ee67461eSJoseph Mingrone case MESSAGE_MAC: { 757*ee67461eSJoseph Mingrone if (!ndo->ndo_vflag) 758*ee67461eSJoseph Mingrone ND_PRINT(" mac"); 759*ee67461eSJoseph Mingrone else { 760*ee67461eSJoseph Mingrone ND_PRINT("\n\tMAC "); 761*ee67461eSJoseph Mingrone ND_PRINT("len %u", len); 762*ee67461eSJoseph Mingrone } 763*ee67461eSJoseph Mingrone } 764*ee67461eSJoseph Mingrone break; 765*ee67461eSJoseph Mingrone 766*ee67461eSJoseph Mingrone case MESSAGE_PC: { 767*ee67461eSJoseph Mingrone if (!ndo->ndo_vflag) 768*ee67461eSJoseph Mingrone ND_PRINT(" pc"); 769*ee67461eSJoseph Mingrone else { 770*ee67461eSJoseph Mingrone ND_PRINT("\n\tPC"); 771*ee67461eSJoseph Mingrone if(len < 4) goto invalid; 772*ee67461eSJoseph Mingrone ND_PRINT(" value %u", 773*ee67461eSJoseph Mingrone GET_BE_U_4(message + 2)); 774*ee67461eSJoseph Mingrone ND_PRINT(" index len %u", len-4); 775*ee67461eSJoseph Mingrone } 776*ee67461eSJoseph Mingrone } 777*ee67461eSJoseph Mingrone break; 778*ee67461eSJoseph Mingrone 779*ee67461eSJoseph Mingrone case MESSAGE_CHALLENGE_REQUEST: { 780*ee67461eSJoseph Mingrone if (!ndo->ndo_vflag) 781*ee67461eSJoseph Mingrone ND_PRINT(" challenge_request"); 782*ee67461eSJoseph Mingrone else { 783*ee67461eSJoseph Mingrone ND_PRINT("\n\tChallenge Request"); 784*ee67461eSJoseph Mingrone if(len > 192) goto invalid; 785*ee67461eSJoseph Mingrone ND_PRINT(" len %u", len); 786*ee67461eSJoseph Mingrone } 787*ee67461eSJoseph Mingrone } 788*ee67461eSJoseph Mingrone break; 789*ee67461eSJoseph Mingrone 790*ee67461eSJoseph Mingrone case MESSAGE_CHALLENGE_REPLY: { 791*ee67461eSJoseph Mingrone if (!ndo->ndo_vflag) 792*ee67461eSJoseph Mingrone ND_PRINT(" challenge_reply"); 793*ee67461eSJoseph Mingrone else { 794*ee67461eSJoseph Mingrone ND_PRINT("\n\tChallenge Reply"); 795*ee67461eSJoseph Mingrone if (len > 192) goto invalid; 796*ee67461eSJoseph Mingrone ND_PRINT(" len %u", len); 7973340d773SGleb Smirnoff } 7983340d773SGleb Smirnoff } 7993340d773SGleb Smirnoff break; 8003340d773SGleb Smirnoff 801cac3dcd5SXin LI default: 8023c602fabSXin LI if (!ndo->ndo_vflag) 803*ee67461eSJoseph Mingrone ND_PRINT(" unknown"); 804cac3dcd5SXin LI else 805*ee67461eSJoseph Mingrone ND_PRINT("\n\tUnknown message type %u", type); 806cac3dcd5SXin LI } 807cac3dcd5SXin LI i += len + 2; 808cac3dcd5SXin LI } 809*ee67461eSJoseph Mingrone 810*ee67461eSJoseph Mingrone return 0; /* OK */ 811*ee67461eSJoseph Mingrone 812*ee67461eSJoseph Mingrone trunc: 813*ee67461eSJoseph Mingrone return -1; /* packet truncated by capture process */ 814*ee67461eSJoseph Mingrone 815*ee67461eSJoseph Mingrone invalid: 816*ee67461eSJoseph Mingrone return -2; /* packet is invalid */ 817*ee67461eSJoseph Mingrone } 818*ee67461eSJoseph Mingrone 819*ee67461eSJoseph Mingrone static void 820*ee67461eSJoseph Mingrone babel_print_v2(netdissect_options *ndo, 821*ee67461eSJoseph Mingrone const u_char *cp, u_int length) 822*ee67461eSJoseph Mingrone { 823*ee67461eSJoseph Mingrone u_short bodylen; 824*ee67461eSJoseph Mingrone int ret; 825*ee67461eSJoseph Mingrone 826*ee67461eSJoseph Mingrone ND_TCHECK_4(cp); 827*ee67461eSJoseph Mingrone if (length < 4) 828*ee67461eSJoseph Mingrone goto invalid; 829*ee67461eSJoseph Mingrone bodylen = GET_BE_U_2(cp + 2); 830*ee67461eSJoseph Mingrone ND_PRINT(" (%u)", bodylen); 831*ee67461eSJoseph Mingrone length -= 4; 832*ee67461eSJoseph Mingrone cp += 4; 833*ee67461eSJoseph Mingrone 834*ee67461eSJoseph Mingrone /* Process the TLVs in the body */ 835*ee67461eSJoseph Mingrone if (length < bodylen) 836*ee67461eSJoseph Mingrone goto invalid; 837*ee67461eSJoseph Mingrone ret = babel_print_v2_tlvs(ndo, cp, bodylen, length); 838*ee67461eSJoseph Mingrone if (ret == -1) 839*ee67461eSJoseph Mingrone goto trunc; 840*ee67461eSJoseph Mingrone if (ret == -2) 841*ee67461eSJoseph Mingrone goto invalid; 842*ee67461eSJoseph Mingrone length -= bodylen; 843*ee67461eSJoseph Mingrone cp += bodylen; 844*ee67461eSJoseph Mingrone 845*ee67461eSJoseph Mingrone /* If there's a trailer, process the TLVs in the trailer */ 846*ee67461eSJoseph Mingrone if (length != 0) { 847*ee67461eSJoseph Mingrone if(ndo->ndo_vflag) ND_PRINT("\n\t----"); 848*ee67461eSJoseph Mingrone else ND_PRINT(" |"); 849*ee67461eSJoseph Mingrone ret = babel_print_v2_tlvs(ndo, cp, length, length); 850*ee67461eSJoseph Mingrone if (ret == -1) 851*ee67461eSJoseph Mingrone goto trunc; 852*ee67461eSJoseph Mingrone if (ret == -2) 853*ee67461eSJoseph Mingrone goto invalid; 854*ee67461eSJoseph Mingrone } 855cac3dcd5SXin LI return; 856cac3dcd5SXin LI 857cac3dcd5SXin LI trunc: 858*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 859cac3dcd5SXin LI return; 860cac3dcd5SXin LI 8613340d773SGleb Smirnoff invalid: 862*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 863cac3dcd5SXin LI } 864