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 40*ee67461eSJoseph Mingrone #include <config.h> 41cac3dcd5SXin LI 42*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 43cac3dcd5SXin LI 44cac3dcd5SXin LI #include <stdio.h> 45cac3dcd5SXin LI #include <string.h> 46cac3dcd5SXin LI 473340d773SGleb Smirnoff #include "netdissect.h" 483c602fabSXin LI #include "addrtoname.h" 49cac3dcd5SXin LI #include "extract.h" 50cac3dcd5SXin LI 513c602fabSXin LI static void babel_print_v2(netdissect_options *, const u_char *cp, u_int length); 52cac3dcd5SXin LI 53cac3dcd5SXin LI void 543c602fabSXin LI babel_print(netdissect_options *ndo, 558bdc5a62SPatrick Kelsey const u_char *cp, u_int length) 568bdc5a62SPatrick Kelsey { 57*ee67461eSJoseph Mingrone ndo->ndo_protocol = "babel"; 58*ee67461eSJoseph Mingrone ND_PRINT("babel"); 59cac3dcd5SXin LI 60*ee67461eSJoseph Mingrone ND_TCHECK_4(cp); 61cac3dcd5SXin LI 62*ee67461eSJoseph Mingrone if(GET_U_1(cp) != 42) { 63*ee67461eSJoseph Mingrone ND_PRINT(" invalid header"); 64cac3dcd5SXin LI return; 65cac3dcd5SXin LI } else { 66*ee67461eSJoseph Mingrone ND_PRINT(" %u", GET_U_1(cp + 1)); 67cac3dcd5SXin LI } 68cac3dcd5SXin LI 69*ee67461eSJoseph Mingrone switch(GET_U_1(cp + 1)) { 70cac3dcd5SXin LI case 2: 713c602fabSXin LI babel_print_v2(ndo, cp, length); 72cac3dcd5SXin LI break; 73cac3dcd5SXin LI default: 74*ee67461eSJoseph Mingrone ND_PRINT(" unknown version"); 75cac3dcd5SXin LI break; 76cac3dcd5SXin LI } 77cac3dcd5SXin LI 78cac3dcd5SXin LI return; 79cac3dcd5SXin LI 80cac3dcd5SXin LI trunc: 81*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 82cac3dcd5SXin LI } 83cac3dcd5SXin LI 843c602fabSXin LI /* TLVs */ 85cac3dcd5SXin LI #define MESSAGE_PAD1 0 86cac3dcd5SXin LI #define MESSAGE_PADN 1 87cac3dcd5SXin LI #define MESSAGE_ACK_REQ 2 88cac3dcd5SXin LI #define MESSAGE_ACK 3 89cac3dcd5SXin LI #define MESSAGE_HELLO 4 90cac3dcd5SXin LI #define MESSAGE_IHU 5 91cac3dcd5SXin LI #define MESSAGE_ROUTER_ID 6 92cac3dcd5SXin LI #define MESSAGE_NH 7 93cac3dcd5SXin LI #define MESSAGE_UPDATE 8 94*ee67461eSJoseph Mingrone #define MESSAGE_ROUTE_REQUEST 9 95*ee67461eSJoseph Mingrone #define MESSAGE_SEQNO_REQUEST 10 96d03c0883SXin LI #define MESSAGE_TSPC 11 97d03c0883SXin LI #define MESSAGE_HMAC 12 98*ee67461eSJoseph Mingrone #define MESSAGE_UPDATE_SRC_SPECIFIC 13 /* last appearance in draft-boutier-babel-source-specific-01 */ 99*ee67461eSJoseph Mingrone #define MESSAGE_REQUEST_SRC_SPECIFIC 14 /* idem */ 100*ee67461eSJoseph Mingrone #define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15 /* idem */ 101*ee67461eSJoseph Mingrone #define MESSAGE_MAC 16 102*ee67461eSJoseph Mingrone #define MESSAGE_PC 17 103*ee67461eSJoseph Mingrone #define MESSAGE_CHALLENGE_REQUEST 18 104*ee67461eSJoseph Mingrone #define MESSAGE_CHALLENGE_REPLY 19 105cac3dcd5SXin LI 1063c602fabSXin LI /* sub-TLVs */ 1073c602fabSXin LI #define MESSAGE_SUB_PAD1 0 1083c602fabSXin LI #define MESSAGE_SUB_PADN 1 1093c602fabSXin LI #define MESSAGE_SUB_DIVERSITY 2 1103c602fabSXin LI #define MESSAGE_SUB_TIMESTAMP 3 1113c602fabSXin LI 112*ee67461eSJoseph Mingrone /* "Mandatory" bit in sub-TLV types */ 113*ee67461eSJoseph Mingrone #define MANDATORY_MASK 0x80 114*ee67461eSJoseph Mingrone 115*ee67461eSJoseph Mingrone /* Flags for the Hello TLV */ 116*ee67461eSJoseph Mingrone #define UNICAST_MASK 0x8000 117*ee67461eSJoseph Mingrone 1183c602fabSXin LI /* Diversity sub-TLV channel codes */ 1193c602fabSXin LI static const struct tok diversity_str[] = { 1203c602fabSXin LI { 0, "reserved" }, 1213c602fabSXin LI { 255, "all" }, 1223c602fabSXin LI { 0, NULL } 1233c602fabSXin LI }; 1243c602fabSXin LI 125cac3dcd5SXin LI static const char * 126*ee67461eSJoseph Mingrone format_id(netdissect_options *ndo, const u_char *id) 127cac3dcd5SXin LI { 128cac3dcd5SXin LI static char buf[25]; 129cac3dcd5SXin LI snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 130*ee67461eSJoseph Mingrone GET_U_1(id), GET_U_1(id + 1), GET_U_1(id + 2), 131*ee67461eSJoseph Mingrone GET_U_1(id + 3), GET_U_1(id + 4), GET_U_1(id + 5), 132*ee67461eSJoseph Mingrone GET_U_1(id + 6), GET_U_1(id + 7)); 133cac3dcd5SXin LI buf[24] = '\0'; 134cac3dcd5SXin LI return buf; 135cac3dcd5SXin LI } 136cac3dcd5SXin LI 137cac3dcd5SXin LI static const unsigned char v4prefix[16] = 138cac3dcd5SXin LI {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 139cac3dcd5SXin LI 140cac3dcd5SXin LI static const char * 1413c602fabSXin LI format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen) 142cac3dcd5SXin LI { 143cac3dcd5SXin LI static char buf[50]; 144*ee67461eSJoseph Mingrone 145*ee67461eSJoseph Mingrone /* 146*ee67461eSJoseph Mingrone * prefix points to a buffer on the stack into which the prefix has 147*ee67461eSJoseph Mingrone * been placed, so we can't use GET_IPADDR_STRING() or 148*ee67461eSJoseph Mingrone * GET_IP6ADDR_STRING() on it. 149*ee67461eSJoseph Mingrone */ 150cac3dcd5SXin LI if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0) 1513c602fabSXin LI snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96); 152cac3dcd5SXin LI else 1533c602fabSXin LI snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen); 154cac3dcd5SXin LI buf[49] = '\0'; 155cac3dcd5SXin LI return buf; 156cac3dcd5SXin LI } 157cac3dcd5SXin LI 158cac3dcd5SXin LI static const char * 1593c602fabSXin LI format_address(netdissect_options *ndo, const u_char *prefix) 160cac3dcd5SXin LI { 161*ee67461eSJoseph Mingrone /* 162*ee67461eSJoseph Mingrone * prefix points to a buffer on the stack into which the prefix has 163*ee67461eSJoseph Mingrone * been placed, so we can't use GET_IPADDR_STRING() or 164*ee67461eSJoseph Mingrone * GET_IP6ADDR_STRING() on it. 165*ee67461eSJoseph Mingrone */ 166cac3dcd5SXin LI if(memcmp(prefix, v4prefix, 12) == 0) 1673c602fabSXin LI return ipaddr_string(ndo, prefix + 12); 168cac3dcd5SXin LI else 1693c602fabSXin LI return ip6addr_string(ndo, prefix); 170cac3dcd5SXin LI } 171cac3dcd5SXin LI 1723c602fabSXin LI static const char * 1733c602fabSXin LI format_interval(const uint16_t i) 1743c602fabSXin LI { 1753c602fabSXin LI static char buf[sizeof("000.00s")]; 1763c602fabSXin LI 1773c602fabSXin LI if (i == 0) 1783c602fabSXin LI return "0.0s (bogus)"; 1793c602fabSXin LI snprintf(buf, sizeof(buf), "%u.%02us", i / 100, i % 100); 1803c602fabSXin LI return buf; 1813c602fabSXin LI } 1823c602fabSXin LI 1833c602fabSXin LI static const char * 1843c602fabSXin LI format_interval_update(const uint16_t i) 1853c602fabSXin LI { 1863c602fabSXin LI return i == 0xFFFF ? "infinity" : format_interval(i); 1873c602fabSXin LI } 1883c602fabSXin LI 1893c602fabSXin LI static const char * 1903c602fabSXin LI format_timestamp(const uint32_t i) 1913c602fabSXin LI { 1923c602fabSXin LI static char buf[sizeof("0000.000000s")]; 1933c602fabSXin LI snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000); 1943c602fabSXin LI return buf; 1953c602fabSXin LI } 1963c602fabSXin LI 1973c602fabSXin LI /* Return number of octets consumed from the input buffer (not the prefix length 1983c602fabSXin LI * in bytes), or -1 for encoding error. */ 199cac3dcd5SXin LI static int 200cac3dcd5SXin LI network_prefix(int ae, int plen, unsigned int omitted, 201cac3dcd5SXin LI const unsigned char *p, const unsigned char *dp, 202cac3dcd5SXin LI unsigned int len, unsigned char *p_r) 203cac3dcd5SXin LI { 204cac3dcd5SXin LI unsigned pb; 205cac3dcd5SXin LI unsigned char prefix[16]; 2063c602fabSXin LI int consumed = 0; 207cac3dcd5SXin LI 208cac3dcd5SXin LI if(plen >= 0) 209cac3dcd5SXin LI pb = (plen + 7) / 8; 210cac3dcd5SXin LI else if(ae == 1) 211cac3dcd5SXin LI pb = 4; 212cac3dcd5SXin LI else 213cac3dcd5SXin LI pb = 16; 214cac3dcd5SXin LI 215cac3dcd5SXin LI if(pb > 16) 216cac3dcd5SXin LI return -1; 217cac3dcd5SXin LI 218cac3dcd5SXin LI memset(prefix, 0, 16); 219cac3dcd5SXin LI 220cac3dcd5SXin LI switch(ae) { 221cac3dcd5SXin LI case 0: break; 222cac3dcd5SXin LI case 1: 223cac3dcd5SXin LI if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) 224cac3dcd5SXin LI return -1; 225cac3dcd5SXin LI memcpy(prefix, v4prefix, 12); 226cac3dcd5SXin LI if(omitted) { 227cac3dcd5SXin LI if (dp == NULL) return -1; 228cac3dcd5SXin LI memcpy(prefix, dp, 12 + omitted); 229cac3dcd5SXin LI } 2303c602fabSXin LI if(pb > omitted) { 2313c602fabSXin LI memcpy(prefix + 12 + omitted, p, pb - omitted); 2323c602fabSXin LI consumed = pb - omitted; 2333c602fabSXin LI } 234cac3dcd5SXin LI break; 235cac3dcd5SXin LI case 2: 236cac3dcd5SXin LI if(omitted > 16 || (pb > omitted && len < pb - omitted)) 237cac3dcd5SXin LI return -1; 238cac3dcd5SXin LI if(omitted) { 239cac3dcd5SXin LI if (dp == NULL) return -1; 240cac3dcd5SXin LI memcpy(prefix, dp, omitted); 241cac3dcd5SXin LI } 2423c602fabSXin LI if(pb > omitted) { 2433c602fabSXin LI memcpy(prefix + omitted, p, pb - omitted); 2443c602fabSXin LI consumed = pb - omitted; 2453c602fabSXin LI } 246cac3dcd5SXin LI break; 247cac3dcd5SXin LI case 3: 248cac3dcd5SXin LI if(pb > 8 && len < pb - 8) return -1; 249cac3dcd5SXin LI prefix[0] = 0xfe; 250cac3dcd5SXin LI prefix[1] = 0x80; 2513c602fabSXin LI if(pb > 8) { 2523c602fabSXin LI memcpy(prefix + 8, p, pb - 8); 2533c602fabSXin LI consumed = pb - 8; 2543c602fabSXin LI } 255cac3dcd5SXin LI break; 256cac3dcd5SXin LI default: 257cac3dcd5SXin LI return -1; 258cac3dcd5SXin LI } 259cac3dcd5SXin LI 260cac3dcd5SXin LI memcpy(p_r, prefix, 16); 2613c602fabSXin LI return consumed; 262cac3dcd5SXin LI } 263cac3dcd5SXin LI 264cac3dcd5SXin LI static int 265cac3dcd5SXin LI network_address(int ae, const unsigned char *a, unsigned int len, 266cac3dcd5SXin LI unsigned char *a_r) 267cac3dcd5SXin LI { 268cac3dcd5SXin LI return network_prefix(ae, -1, 0, a, NULL, len, a_r); 269cac3dcd5SXin LI } 270cac3dcd5SXin LI 2713c602fabSXin LI /* 2723c602fabSXin LI * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126), 2733c602fabSXin LI * their encoding is similar to the encoding of TLVs, but the type namespace is 2743c602fabSXin LI * different: 2753c602fabSXin LI * 2763c602fabSXin LI * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV. 2773c602fabSXin LI * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV. 2783c602fabSXin LI * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing 2793c602fabSXin LI * data. Its body is a variable-length sequence of 8-bit unsigned integers, 280*ee67461eSJoseph Mingrone * each representing per-hop number of interfering radio channel for the 2813c602fabSXin LI * prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel 2823c602fabSXin LI * 255 interferes with any other channel. 2833c602fabSXin LI * o Type 3 stands for Timestamp sub-TLV, used to compute RTT between 2843c602fabSXin LI * neighbours. In the case of a Hello TLV, the body stores a 32-bits 2853c602fabSXin LI * timestamp, while in the case of a IHU TLV, two 32-bits timestamps are 2863c602fabSXin LI * stored. 2873c602fabSXin LI * 2883c602fabSXin LI * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is 2893c602fabSXin LI * only valid for TLV type 8 (Update). Note that within an Update TLV a missing 2903c602fabSXin LI * Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body. 2913c602fabSXin LI * The former would mean a lack of any claims about the interference, and the 2923c602fabSXin LI * latter would state that interference is definitely absent. 2933c602fabSXin LI * A type 3 sub-TLV is valid both for Hello and IHU TLVs, though the exact 2943c602fabSXin LI * semantic of the sub-TLV is different in each case. 2953c602fabSXin LI */ 2963c602fabSXin LI static void 2973c602fabSXin LI subtlvs_print(netdissect_options *ndo, 2988bdc5a62SPatrick Kelsey const u_char *cp, const u_char *ep, const uint8_t tlv_type) 2998bdc5a62SPatrick Kelsey { 3003c602fabSXin LI uint8_t subtype, sublen; 3013c602fabSXin LI const char *sep; 3023c602fabSXin LI uint32_t t1, t2; 3033c602fabSXin LI 3043c602fabSXin LI while (cp < ep) { 305*ee67461eSJoseph Mingrone subtype = GET_U_1(cp); 306*ee67461eSJoseph Mingrone cp++; 3073c602fabSXin LI if(subtype == MESSAGE_SUB_PAD1) { 308*ee67461eSJoseph Mingrone ND_PRINT(" sub-pad1"); 3093c602fabSXin LI continue; 3103c602fabSXin LI } 311*ee67461eSJoseph Mingrone if ((MANDATORY_MASK & subtype) != 0) 312*ee67461eSJoseph Mingrone ND_PRINT(" (M)"); 3133c602fabSXin LI if(cp == ep) 3143340d773SGleb Smirnoff goto invalid; 315*ee67461eSJoseph Mingrone sublen = GET_U_1(cp); 316*ee67461eSJoseph Mingrone cp++; 3173c602fabSXin LI if(cp + sublen > ep) 3183340d773SGleb Smirnoff goto invalid; 3193c602fabSXin LI 3203c602fabSXin LI switch(subtype) { 3213c602fabSXin LI case MESSAGE_SUB_PADN: 322*ee67461eSJoseph Mingrone ND_PRINT(" sub-padn"); 3233c602fabSXin LI cp += sublen; 3243c602fabSXin LI break; 3253c602fabSXin LI case MESSAGE_SUB_DIVERSITY: 326*ee67461eSJoseph Mingrone ND_PRINT(" sub-diversity"); 3273c602fabSXin LI if (sublen == 0) { 328*ee67461eSJoseph Mingrone ND_PRINT(" empty"); 3293c602fabSXin LI break; 3303c602fabSXin LI } 3313c602fabSXin LI sep = " "; 332*ee67461eSJoseph Mingrone while (sublen) { 333*ee67461eSJoseph Mingrone ND_PRINT("%s%s", sep, 334*ee67461eSJoseph Mingrone tok2str(diversity_str, "%u", GET_U_1(cp))); 335*ee67461eSJoseph Mingrone cp++; 3363c602fabSXin LI sep = "-"; 337*ee67461eSJoseph Mingrone sublen--; 3383c602fabSXin LI } 3393340d773SGleb Smirnoff if(tlv_type != MESSAGE_UPDATE && 3403340d773SGleb Smirnoff tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC) 341*ee67461eSJoseph Mingrone ND_PRINT(" (bogus)"); 3423c602fabSXin LI break; 3433c602fabSXin LI case MESSAGE_SUB_TIMESTAMP: 344*ee67461eSJoseph Mingrone ND_PRINT(" sub-timestamp"); 3453c602fabSXin LI if(tlv_type == MESSAGE_HELLO) { 3463c602fabSXin LI if(sublen < 4) 3473340d773SGleb Smirnoff goto invalid; 348*ee67461eSJoseph Mingrone t1 = GET_BE_U_4(cp); 349*ee67461eSJoseph Mingrone ND_PRINT(" %s", format_timestamp(t1)); 3503c602fabSXin LI } else if(tlv_type == MESSAGE_IHU) { 3513c602fabSXin LI if(sublen < 8) 3523340d773SGleb Smirnoff goto invalid; 353*ee67461eSJoseph Mingrone t1 = GET_BE_U_4(cp); 354*ee67461eSJoseph Mingrone ND_PRINT(" %s", format_timestamp(t1)); 355*ee67461eSJoseph Mingrone t2 = GET_BE_U_4(cp + 4); 356*ee67461eSJoseph Mingrone ND_PRINT("|%s", format_timestamp(t2)); 3573c602fabSXin LI } else 358*ee67461eSJoseph Mingrone ND_PRINT(" (bogus)"); 3593c602fabSXin LI cp += sublen; 3603c602fabSXin LI break; 3613c602fabSXin LI default: 362*ee67461eSJoseph Mingrone ND_PRINT(" sub-unknown-0x%02x", subtype); 3633c602fabSXin LI cp += sublen; 3643c602fabSXin LI } /* switch */ 3653c602fabSXin LI } /* while */ 3663c602fabSXin LI return; 3673c602fabSXin LI 3683340d773SGleb Smirnoff invalid: 369*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 3703c602fabSXin LI } 3713c602fabSXin LI 372cac3dcd5SXin LI #define ICHECK(i, l) \ 373*ee67461eSJoseph Mingrone if ((i) + (l) > tlvs_length || (i) + (l) > packet_length_remaining) \ 374*ee67461eSJoseph Mingrone goto invalid; 375cac3dcd5SXin LI 376*ee67461eSJoseph Mingrone static int 377*ee67461eSJoseph Mingrone babel_print_v2_tlvs(netdissect_options *ndo, 378*ee67461eSJoseph Mingrone const u_char *cp, u_int tlvs_length, 379*ee67461eSJoseph Mingrone u_int packet_length_remaining) 3808bdc5a62SPatrick Kelsey { 381cac3dcd5SXin LI u_int i; 382cac3dcd5SXin LI u_char v4_prefix[16] = 383cac3dcd5SXin LI {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 384cac3dcd5SXin LI u_char v6_prefix[16] = {0}; 385cac3dcd5SXin LI 386cac3dcd5SXin LI i = 0; 387*ee67461eSJoseph Mingrone while(i < tlvs_length) { 388cac3dcd5SXin LI const u_char *message; 389*ee67461eSJoseph Mingrone uint8_t type; 390*ee67461eSJoseph Mingrone u_int len; 391cac3dcd5SXin LI 392*ee67461eSJoseph Mingrone message = cp + i; 3933c602fabSXin LI 394*ee67461eSJoseph Mingrone ICHECK(i, 1); 395*ee67461eSJoseph Mingrone if((type = GET_U_1(message)) == MESSAGE_PAD1) { 396*ee67461eSJoseph Mingrone ND_PRINT(ndo->ndo_vflag ? "\n\tPad 1" : " pad1"); 3973c602fabSXin LI i += 1; 3983c602fabSXin LI continue; 3993c602fabSXin LI } 4003c602fabSXin LI 401cac3dcd5SXin LI ICHECK(i, 2); 402*ee67461eSJoseph Mingrone ND_TCHECK_2(message); 403*ee67461eSJoseph Mingrone len = GET_U_1(message + 1); 404cac3dcd5SXin LI 405cac3dcd5SXin LI ICHECK(i, 2 + len); 406*ee67461eSJoseph Mingrone ND_TCHECK_LEN(message, 2 + len); 407cac3dcd5SXin LI 408cac3dcd5SXin LI switch(type) { 409cac3dcd5SXin LI case MESSAGE_PADN: { 4103c602fabSXin LI if (!ndo->ndo_vflag) 411*ee67461eSJoseph Mingrone ND_PRINT(" padN"); 412cac3dcd5SXin LI else 413*ee67461eSJoseph Mingrone ND_PRINT("\n\tPad %u", len + 2); 414cac3dcd5SXin LI } 415cac3dcd5SXin LI break; 416cac3dcd5SXin LI 417cac3dcd5SXin LI case MESSAGE_ACK_REQ: { 418cac3dcd5SXin LI u_short nonce, interval; 4193c602fabSXin LI if (!ndo->ndo_vflag) 420*ee67461eSJoseph Mingrone ND_PRINT(" ack-req"); 421cac3dcd5SXin LI else { 422*ee67461eSJoseph Mingrone ND_PRINT("\n\tAcknowledgment Request "); 4233340d773SGleb Smirnoff if(len < 6) goto invalid; 424*ee67461eSJoseph Mingrone nonce = GET_BE_U_2(message + 4); 425*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 426*ee67461eSJoseph Mingrone ND_PRINT("%04x %s", nonce, format_interval(interval)); 427cac3dcd5SXin LI } 428cac3dcd5SXin LI } 429cac3dcd5SXin LI break; 430cac3dcd5SXin LI 431cac3dcd5SXin LI case MESSAGE_ACK: { 432cac3dcd5SXin LI u_short nonce; 4333c602fabSXin LI if (!ndo->ndo_vflag) 434*ee67461eSJoseph Mingrone ND_PRINT(" ack"); 435cac3dcd5SXin LI else { 436*ee67461eSJoseph Mingrone ND_PRINT("\n\tAcknowledgment "); 4373340d773SGleb Smirnoff if(len < 2) goto invalid; 438*ee67461eSJoseph Mingrone nonce = GET_BE_U_2(message + 2); 439*ee67461eSJoseph Mingrone ND_PRINT("%04x", nonce); 440cac3dcd5SXin LI } 441cac3dcd5SXin LI } 442cac3dcd5SXin LI break; 443cac3dcd5SXin LI 444cac3dcd5SXin LI case MESSAGE_HELLO: { 445*ee67461eSJoseph Mingrone u_short seqno, interval, unicast; 4463c602fabSXin LI if (!ndo->ndo_vflag) 447*ee67461eSJoseph Mingrone ND_PRINT(" hello"); 448cac3dcd5SXin LI else { 449*ee67461eSJoseph Mingrone ND_PRINT("\n\tHello "); 4503340d773SGleb Smirnoff if(len < 6) goto invalid; 451*ee67461eSJoseph Mingrone unicast = (GET_BE_U_2(message + 2) & UNICAST_MASK); 452*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 4); 453*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 454*ee67461eSJoseph Mingrone if(unicast) 455*ee67461eSJoseph Mingrone ND_PRINT("(Unicast) "); 456*ee67461eSJoseph Mingrone ND_PRINT("seqno %u ", seqno); 457*ee67461eSJoseph Mingrone if(interval!=0) 458*ee67461eSJoseph Mingrone ND_PRINT("interval %s", format_interval(interval)); 459*ee67461eSJoseph Mingrone else 460*ee67461eSJoseph Mingrone ND_PRINT("unscheduled"); 4613c602fabSXin LI /* Extra data. */ 4623c602fabSXin LI if(len > 6) 4633c602fabSXin LI subtlvs_print(ndo, message + 8, message + 2 + len, type); 464cac3dcd5SXin LI } 465cac3dcd5SXin LI } 466cac3dcd5SXin LI break; 467cac3dcd5SXin LI 468cac3dcd5SXin LI case MESSAGE_IHU: { 469*ee67461eSJoseph Mingrone unsigned short rxcost, interval; 4703c602fabSXin LI if (!ndo->ndo_vflag) 471*ee67461eSJoseph Mingrone ND_PRINT(" ihu"); 472cac3dcd5SXin LI else { 473cac3dcd5SXin LI u_char address[16]; 474*ee67461eSJoseph Mingrone u_char ae; 475cac3dcd5SXin LI int rc; 476*ee67461eSJoseph Mingrone ND_PRINT("\n\tIHU "); 4773340d773SGleb Smirnoff if(len < 6) goto invalid; 478*ee67461eSJoseph Mingrone rxcost = GET_BE_U_2(message + 4); 479*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 480*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 481*ee67461eSJoseph Mingrone rc = network_address(ae, message + 8, 482*ee67461eSJoseph Mingrone len - 6, address); 483*ee67461eSJoseph Mingrone if(rc < 0) { nd_print_trunc(ndo); break; } 484*ee67461eSJoseph Mingrone ND_PRINT("%s rxcost %u interval %s", 485*ee67461eSJoseph Mingrone ae == 0 ? "any" : format_address(ndo, address), 486*ee67461eSJoseph Mingrone rxcost, format_interval(interval)); 4873c602fabSXin LI /* Extra data. */ 4883c602fabSXin LI if((u_int)rc < len - 6) 4893c602fabSXin LI subtlvs_print(ndo, message + 8 + rc, message + 2 + len, 4903c602fabSXin LI type); 491cac3dcd5SXin LI } 492cac3dcd5SXin LI } 493cac3dcd5SXin LI break; 494cac3dcd5SXin LI 495cac3dcd5SXin LI case MESSAGE_ROUTER_ID: { 4963c602fabSXin LI if (!ndo->ndo_vflag) 497*ee67461eSJoseph Mingrone ND_PRINT(" router-id"); 498cac3dcd5SXin LI else { 499*ee67461eSJoseph Mingrone ND_PRINT("\n\tRouter Id"); 5003340d773SGleb Smirnoff if(len < 10) goto invalid; 501*ee67461eSJoseph Mingrone ND_PRINT(" %s", format_id(ndo, message + 4)); 502cac3dcd5SXin LI } 503cac3dcd5SXin LI } 504cac3dcd5SXin LI break; 505cac3dcd5SXin LI 506cac3dcd5SXin LI case MESSAGE_NH: { 5073c602fabSXin LI if (!ndo->ndo_vflag) 508*ee67461eSJoseph Mingrone ND_PRINT(" nh"); 509cac3dcd5SXin LI else { 510cac3dcd5SXin LI int rc; 511*ee67461eSJoseph Mingrone u_char ae; 512cac3dcd5SXin LI u_char nh[16]; 513*ee67461eSJoseph Mingrone ND_PRINT("\n\tNext Hop"); 5143340d773SGleb Smirnoff if(len < 2) goto invalid; 515*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 516*ee67461eSJoseph Mingrone rc = network_address(ae, message + 4, 517*ee67461eSJoseph Mingrone len - 2, nh); 5183340d773SGleb Smirnoff if(rc < 0) goto invalid; 519*ee67461eSJoseph Mingrone ND_PRINT(" %s", ae == 0 ? "invalid AE 0" : format_address(ndo, nh)); 520cac3dcd5SXin LI } 521cac3dcd5SXin LI } 522cac3dcd5SXin LI break; 523cac3dcd5SXin LI 524cac3dcd5SXin LI case MESSAGE_UPDATE: { 5253c602fabSXin LI if (!ndo->ndo_vflag) { 526*ee67461eSJoseph Mingrone ND_PRINT(" update"); 52739e421e8SCy Schubert if(len < 10) 528*ee67461eSJoseph Mingrone goto invalid; 529cac3dcd5SXin LI else 530*ee67461eSJoseph Mingrone ND_PRINT("%s%s%s", 531*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x80) ? "/prefix": "", 532*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x40) ? "/id" : "", 533*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x3f) ? "/unknown" : ""); 534cac3dcd5SXin LI } else { 535cac3dcd5SXin LI u_short interval, seqno, metric; 536*ee67461eSJoseph Mingrone u_char ae, plen; 537cac3dcd5SXin LI int rc; 538cac3dcd5SXin LI u_char prefix[16]; 539*ee67461eSJoseph Mingrone ND_PRINT("\n\tUpdate"); 5403340d773SGleb Smirnoff if(len < 10) goto invalid; 541*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 542*ee67461eSJoseph Mingrone plen = GET_U_1(message + 4) + (GET_U_1(message + 2) == 1 ? 96 : 0); 543*ee67461eSJoseph Mingrone rc = network_prefix(ae, 544*ee67461eSJoseph Mingrone GET_U_1(message + 4), 545*ee67461eSJoseph Mingrone GET_U_1(message + 5), 546cac3dcd5SXin LI message + 12, 547*ee67461eSJoseph Mingrone GET_U_1(message + 2) == 1 ? v4_prefix : v6_prefix, 548cac3dcd5SXin LI len - 10, prefix); 5493340d773SGleb Smirnoff if(rc < 0) goto invalid; 550*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 551*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 8); 552*ee67461eSJoseph Mingrone metric = GET_BE_U_2(message + 10); 553*ee67461eSJoseph Mingrone ND_PRINT("%s%s%s %s metric %u seqno %u interval %s", 554*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x80) ? "/prefix": "", 555*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x40) ? "/id" : "", 556*ee67461eSJoseph Mingrone (GET_U_1(message + 3) & 0x3f) ? "/unknown" : "", 557*ee67461eSJoseph Mingrone ae == 0 ? "any" : format_prefix(ndo, prefix, plen), 558*ee67461eSJoseph Mingrone metric, seqno, format_interval_update(interval)); 559*ee67461eSJoseph Mingrone if(GET_U_1(message + 3) & 0x80) { 560*ee67461eSJoseph Mingrone if(GET_U_1(message + 2) == 1) 561cac3dcd5SXin LI memcpy(v4_prefix, prefix, 16); 562cac3dcd5SXin LI else 563cac3dcd5SXin LI memcpy(v6_prefix, prefix, 16); 564cac3dcd5SXin LI } 5653c602fabSXin LI /* extra data? */ 5663c602fabSXin LI if((u_int)rc < len - 10) 5673c602fabSXin LI subtlvs_print(ndo, message + 12 + rc, message + 2 + len, type); 568cac3dcd5SXin LI } 569cac3dcd5SXin LI } 570cac3dcd5SXin LI break; 571cac3dcd5SXin LI 572*ee67461eSJoseph Mingrone case MESSAGE_ROUTE_REQUEST: { 5733c602fabSXin LI if (!ndo->ndo_vflag) 574*ee67461eSJoseph Mingrone ND_PRINT(" route-request"); 575cac3dcd5SXin LI else { 576cac3dcd5SXin LI int rc; 577*ee67461eSJoseph Mingrone u_char prefix[16], ae, plen; 578*ee67461eSJoseph Mingrone ND_PRINT("\n\tRoute Request "); 5793340d773SGleb Smirnoff if(len < 2) goto invalid; 580*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 581*ee67461eSJoseph Mingrone plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0); 582*ee67461eSJoseph Mingrone rc = network_prefix(ae, 583*ee67461eSJoseph Mingrone GET_U_1(message + 3), 0, 584cac3dcd5SXin LI message + 4, NULL, len - 2, prefix); 5853340d773SGleb Smirnoff if(rc < 0) goto invalid; 586*ee67461eSJoseph Mingrone ND_PRINT("for %s", 587*ee67461eSJoseph Mingrone ae == 0 ? "any" : format_prefix(ndo, prefix, plen)); 588cac3dcd5SXin LI } 589cac3dcd5SXin LI } 590cac3dcd5SXin LI break; 591cac3dcd5SXin LI 592*ee67461eSJoseph Mingrone case MESSAGE_SEQNO_REQUEST : { 5933c602fabSXin LI if (!ndo->ndo_vflag) 594*ee67461eSJoseph Mingrone ND_PRINT(" seqno-request"); 595cac3dcd5SXin LI else { 596cac3dcd5SXin LI int rc; 597cac3dcd5SXin LI u_short seqno; 598*ee67461eSJoseph Mingrone u_char prefix[16], ae, plen; 599*ee67461eSJoseph Mingrone ND_PRINT("\n\tSeqno Request "); 6003340d773SGleb Smirnoff if(len < 14) goto invalid; 601*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 602*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 4); 603*ee67461eSJoseph Mingrone rc = network_prefix(ae, 604*ee67461eSJoseph Mingrone GET_U_1(message + 3), 0, 605cac3dcd5SXin LI message + 16, NULL, len - 14, prefix); 6063340d773SGleb Smirnoff if(rc < 0) goto invalid; 607*ee67461eSJoseph Mingrone plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0); 608*ee67461eSJoseph Mingrone ND_PRINT("(%u hops) for %s seqno %u id %s", 609*ee67461eSJoseph Mingrone GET_U_1(message + 6), 610*ee67461eSJoseph Mingrone ae == 0 ? "invalid AE 0" : format_prefix(ndo, prefix, plen), 611*ee67461eSJoseph Mingrone seqno, format_id(ndo, message + 8)); 612cac3dcd5SXin LI } 613cac3dcd5SXin LI } 614cac3dcd5SXin LI break; 615d03c0883SXin LI case MESSAGE_TSPC : 6163c602fabSXin LI if (!ndo->ndo_vflag) 617*ee67461eSJoseph Mingrone ND_PRINT(" tspc"); 618d03c0883SXin LI else { 619*ee67461eSJoseph Mingrone ND_PRINT("\n\tTS/PC "); 6203340d773SGleb Smirnoff if(len < 6) goto invalid; 621*ee67461eSJoseph Mingrone ND_PRINT("timestamp %u packetcounter %u", 622*ee67461eSJoseph Mingrone GET_BE_U_4(message + 4), 623*ee67461eSJoseph Mingrone GET_BE_U_2(message + 2)); 624d03c0883SXin LI } 625d03c0883SXin LI break; 626d03c0883SXin LI case MESSAGE_HMAC : { 6273c602fabSXin LI if (!ndo->ndo_vflag) 628*ee67461eSJoseph Mingrone ND_PRINT(" hmac"); 629d03c0883SXin LI else { 630d03c0883SXin LI unsigned j; 631*ee67461eSJoseph Mingrone ND_PRINT("\n\tHMAC "); 6323340d773SGleb Smirnoff if(len < 18) goto invalid; 633*ee67461eSJoseph Mingrone ND_PRINT("key-id %u digest-%u ", GET_BE_U_2(message + 2), 634*ee67461eSJoseph Mingrone len - 2); 635d03c0883SXin LI for (j = 0; j < len - 2; j++) 636*ee67461eSJoseph Mingrone ND_PRINT("%02X", GET_U_1(message + j + 4)); 637d03c0883SXin LI } 638d03c0883SXin LI } 639d03c0883SXin LI break; 6403340d773SGleb Smirnoff 6413340d773SGleb Smirnoff case MESSAGE_UPDATE_SRC_SPECIFIC : { 6423340d773SGleb Smirnoff if(!ndo->ndo_vflag) { 643*ee67461eSJoseph Mingrone ND_PRINT(" ss-update"); 6443340d773SGleb Smirnoff } else { 6453340d773SGleb Smirnoff u_char prefix[16], src_prefix[16]; 6463340d773SGleb Smirnoff u_short interval, seqno, metric; 6473340d773SGleb Smirnoff u_char ae, plen, src_plen, omitted; 6483340d773SGleb Smirnoff int rc; 6493340d773SGleb Smirnoff int parsed_len = 10; 650*ee67461eSJoseph Mingrone ND_PRINT("\n\tSS-Update"); 6513340d773SGleb Smirnoff if(len < 10) goto invalid; 652*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 653*ee67461eSJoseph Mingrone src_plen = GET_U_1(message + 3); 654*ee67461eSJoseph Mingrone plen = GET_U_1(message + 4); 655*ee67461eSJoseph Mingrone omitted = GET_U_1(message + 5); 656*ee67461eSJoseph Mingrone interval = GET_BE_U_2(message + 6); 657*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 8); 658*ee67461eSJoseph Mingrone metric = GET_BE_U_2(message + 10); 6593340d773SGleb Smirnoff rc = network_prefix(ae, plen, omitted, message + 2 + parsed_len, 6603340d773SGleb Smirnoff ae == 1 ? v4_prefix : v6_prefix, 6613340d773SGleb Smirnoff len - parsed_len, prefix); 6623340d773SGleb Smirnoff if(rc < 0) goto invalid; 6633340d773SGleb Smirnoff if(ae == 1) 6643340d773SGleb Smirnoff plen += 96; 6653340d773SGleb Smirnoff parsed_len += rc; 6663340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 6673340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 6683340d773SGleb Smirnoff if(rc < 0) goto invalid; 6693340d773SGleb Smirnoff if(ae == 1) 6703340d773SGleb Smirnoff src_plen += 96; 6713340d773SGleb Smirnoff parsed_len += rc; 6723340d773SGleb Smirnoff 673*ee67461eSJoseph Mingrone ND_PRINT(" %s from", format_prefix(ndo, prefix, plen)); 674*ee67461eSJoseph Mingrone ND_PRINT(" %s metric %u seqno %u interval %s", 6753340d773SGleb Smirnoff format_prefix(ndo, src_prefix, src_plen), 676*ee67461eSJoseph Mingrone metric, seqno, format_interval_update(interval)); 6773340d773SGleb Smirnoff /* extra data? */ 6783340d773SGleb Smirnoff if((u_int)parsed_len < len) 6793340d773SGleb Smirnoff subtlvs_print(ndo, message + 2 + parsed_len, 6803340d773SGleb Smirnoff message + 2 + len, type); 6813340d773SGleb Smirnoff } 6823340d773SGleb Smirnoff } 6833340d773SGleb Smirnoff break; 6843340d773SGleb Smirnoff 6853340d773SGleb Smirnoff case MESSAGE_REQUEST_SRC_SPECIFIC : { 6863340d773SGleb Smirnoff if(!ndo->ndo_vflag) 687*ee67461eSJoseph Mingrone ND_PRINT(" ss-request"); 6883340d773SGleb Smirnoff else { 6893340d773SGleb Smirnoff int rc, parsed_len = 3; 6903340d773SGleb Smirnoff u_char ae, plen, src_plen, prefix[16], src_prefix[16]; 691*ee67461eSJoseph Mingrone ND_PRINT("\n\tSS-Request "); 6923340d773SGleb Smirnoff if(len < 3) goto invalid; 693*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 694*ee67461eSJoseph Mingrone plen = GET_U_1(message + 3); 695*ee67461eSJoseph Mingrone src_plen = GET_U_1(message + 4); 6963340d773SGleb Smirnoff rc = network_prefix(ae, plen, 0, message + 2 + parsed_len, 6973340d773SGleb Smirnoff NULL, len - parsed_len, prefix); 6983340d773SGleb Smirnoff if(rc < 0) goto invalid; 6993340d773SGleb Smirnoff if(ae == 1) 7003340d773SGleb Smirnoff plen += 96; 7013340d773SGleb Smirnoff parsed_len += rc; 7023340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 7033340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 7043340d773SGleb Smirnoff if(rc < 0) goto invalid; 7053340d773SGleb Smirnoff if(ae == 1) 7063340d773SGleb Smirnoff src_plen += 96; 7073340d773SGleb Smirnoff parsed_len += rc; 7083340d773SGleb Smirnoff if(ae == 0) { 709*ee67461eSJoseph Mingrone ND_PRINT("for any"); 7103340d773SGleb Smirnoff } else { 711*ee67461eSJoseph Mingrone ND_PRINT("for (%s, ", format_prefix(ndo, prefix, plen)); 712*ee67461eSJoseph Mingrone ND_PRINT("%s)", format_prefix(ndo, src_prefix, src_plen)); 7133340d773SGleb Smirnoff } 7143340d773SGleb Smirnoff } 7153340d773SGleb Smirnoff } 7163340d773SGleb Smirnoff break; 7173340d773SGleb Smirnoff 7183340d773SGleb Smirnoff case MESSAGE_MH_REQUEST_SRC_SPECIFIC : { 7193340d773SGleb Smirnoff if(!ndo->ndo_vflag) 720*ee67461eSJoseph Mingrone ND_PRINT(" ss-mh-request"); 7213340d773SGleb Smirnoff else { 7223340d773SGleb Smirnoff int rc, parsed_len = 14; 7233340d773SGleb Smirnoff u_short seqno; 7243340d773SGleb Smirnoff u_char ae, plen, src_plen, prefix[16], src_prefix[16], hopc; 7253340d773SGleb Smirnoff const u_char *router_id = NULL; 726*ee67461eSJoseph Mingrone ND_PRINT("\n\tSS-MH-Request "); 7273340d773SGleb Smirnoff if(len < 14) goto invalid; 728*ee67461eSJoseph Mingrone ae = GET_U_1(message + 2); 729*ee67461eSJoseph Mingrone plen = GET_U_1(message + 3); 730*ee67461eSJoseph Mingrone seqno = GET_BE_U_2(message + 4); 731*ee67461eSJoseph Mingrone hopc = GET_U_1(message + 6); 732*ee67461eSJoseph Mingrone src_plen = GET_U_1(message + 7); 7333340d773SGleb Smirnoff router_id = message + 8; 7343340d773SGleb Smirnoff rc = network_prefix(ae, plen, 0, message + 2 + parsed_len, 7353340d773SGleb Smirnoff NULL, len - parsed_len, prefix); 7363340d773SGleb Smirnoff if(rc < 0) goto invalid; 7373340d773SGleb Smirnoff if(ae == 1) 7383340d773SGleb Smirnoff plen += 96; 7393340d773SGleb Smirnoff parsed_len += rc; 7403340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 7413340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 7423340d773SGleb Smirnoff if(rc < 0) goto invalid; 7433340d773SGleb Smirnoff if(ae == 1) 7443340d773SGleb Smirnoff src_plen += 96; 745*ee67461eSJoseph Mingrone ND_PRINT("(%u hops) for (%s, ", 746*ee67461eSJoseph Mingrone hopc, format_prefix(ndo, prefix, plen)); 747*ee67461eSJoseph Mingrone ND_PRINT("%s) seqno %u id %s", 7483340d773SGleb Smirnoff format_prefix(ndo, src_prefix, src_plen), 749*ee67461eSJoseph Mingrone seqno, format_id(ndo, router_id)); 750*ee67461eSJoseph Mingrone } 751*ee67461eSJoseph Mingrone } 752*ee67461eSJoseph Mingrone break; 753*ee67461eSJoseph Mingrone 754*ee67461eSJoseph Mingrone case MESSAGE_MAC: { 755*ee67461eSJoseph Mingrone if (!ndo->ndo_vflag) 756*ee67461eSJoseph Mingrone ND_PRINT(" mac"); 757*ee67461eSJoseph Mingrone else { 758*ee67461eSJoseph Mingrone ND_PRINT("\n\tMAC "); 759*ee67461eSJoseph Mingrone ND_PRINT("len %u", len); 760*ee67461eSJoseph Mingrone } 761*ee67461eSJoseph Mingrone } 762*ee67461eSJoseph Mingrone break; 763*ee67461eSJoseph Mingrone 764*ee67461eSJoseph Mingrone case MESSAGE_PC: { 765*ee67461eSJoseph Mingrone if (!ndo->ndo_vflag) 766*ee67461eSJoseph Mingrone ND_PRINT(" pc"); 767*ee67461eSJoseph Mingrone else { 768*ee67461eSJoseph Mingrone ND_PRINT("\n\tPC"); 769*ee67461eSJoseph Mingrone if(len < 4) goto invalid; 770*ee67461eSJoseph Mingrone ND_PRINT(" value %u", 771*ee67461eSJoseph Mingrone GET_BE_U_4(message + 2)); 772*ee67461eSJoseph Mingrone ND_PRINT(" index len %u", len-4); 773*ee67461eSJoseph Mingrone } 774*ee67461eSJoseph Mingrone } 775*ee67461eSJoseph Mingrone break; 776*ee67461eSJoseph Mingrone 777*ee67461eSJoseph Mingrone case MESSAGE_CHALLENGE_REQUEST: { 778*ee67461eSJoseph Mingrone if (!ndo->ndo_vflag) 779*ee67461eSJoseph Mingrone ND_PRINT(" challenge_request"); 780*ee67461eSJoseph Mingrone else { 781*ee67461eSJoseph Mingrone ND_PRINT("\n\tChallenge Request"); 782*ee67461eSJoseph Mingrone if(len > 192) goto invalid; 783*ee67461eSJoseph Mingrone ND_PRINT(" len %u", len); 784*ee67461eSJoseph Mingrone } 785*ee67461eSJoseph Mingrone } 786*ee67461eSJoseph Mingrone break; 787*ee67461eSJoseph Mingrone 788*ee67461eSJoseph Mingrone case MESSAGE_CHALLENGE_REPLY: { 789*ee67461eSJoseph Mingrone if (!ndo->ndo_vflag) 790*ee67461eSJoseph Mingrone ND_PRINT(" challenge_reply"); 791*ee67461eSJoseph Mingrone else { 792*ee67461eSJoseph Mingrone ND_PRINT("\n\tChallenge Reply"); 793*ee67461eSJoseph Mingrone if (len > 192) goto invalid; 794*ee67461eSJoseph Mingrone ND_PRINT(" len %u", len); 7953340d773SGleb Smirnoff } 7963340d773SGleb Smirnoff } 7973340d773SGleb Smirnoff break; 7983340d773SGleb Smirnoff 799cac3dcd5SXin LI default: 8003c602fabSXin LI if (!ndo->ndo_vflag) 801*ee67461eSJoseph Mingrone ND_PRINT(" unknown"); 802cac3dcd5SXin LI else 803*ee67461eSJoseph Mingrone ND_PRINT("\n\tUnknown message type %u", type); 804cac3dcd5SXin LI } 805cac3dcd5SXin LI i += len + 2; 806cac3dcd5SXin LI } 807*ee67461eSJoseph Mingrone 808*ee67461eSJoseph Mingrone return 0; /* OK */ 809*ee67461eSJoseph Mingrone 810*ee67461eSJoseph Mingrone trunc: 811*ee67461eSJoseph Mingrone return -1; /* packet truncated by capture process */ 812*ee67461eSJoseph Mingrone 813*ee67461eSJoseph Mingrone invalid: 814*ee67461eSJoseph Mingrone return -2; /* packet is invalid */ 815*ee67461eSJoseph Mingrone } 816*ee67461eSJoseph Mingrone 817*ee67461eSJoseph Mingrone static void 818*ee67461eSJoseph Mingrone babel_print_v2(netdissect_options *ndo, 819*ee67461eSJoseph Mingrone const u_char *cp, u_int length) 820*ee67461eSJoseph Mingrone { 821*ee67461eSJoseph Mingrone u_short bodylen; 822*ee67461eSJoseph Mingrone int ret; 823*ee67461eSJoseph Mingrone 824*ee67461eSJoseph Mingrone ND_TCHECK_4(cp); 825*ee67461eSJoseph Mingrone if (length < 4) 826*ee67461eSJoseph Mingrone goto invalid; 827*ee67461eSJoseph Mingrone bodylen = GET_BE_U_2(cp + 2); 828*ee67461eSJoseph Mingrone ND_PRINT(" (%u)", bodylen); 829*ee67461eSJoseph Mingrone length -= 4; 830*ee67461eSJoseph Mingrone cp += 4; 831*ee67461eSJoseph Mingrone 832*ee67461eSJoseph Mingrone /* Process the TLVs in the body */ 833*ee67461eSJoseph Mingrone if (length < bodylen) 834*ee67461eSJoseph Mingrone goto invalid; 835*ee67461eSJoseph Mingrone ret = babel_print_v2_tlvs(ndo, cp, bodylen, length); 836*ee67461eSJoseph Mingrone if (ret == -1) 837*ee67461eSJoseph Mingrone goto trunc; 838*ee67461eSJoseph Mingrone if (ret == -2) 839*ee67461eSJoseph Mingrone goto invalid; 840*ee67461eSJoseph Mingrone length -= bodylen; 841*ee67461eSJoseph Mingrone cp += bodylen; 842*ee67461eSJoseph Mingrone 843*ee67461eSJoseph Mingrone /* If there's a trailer, process the TLVs in the trailer */ 844*ee67461eSJoseph Mingrone if (length != 0) { 845*ee67461eSJoseph Mingrone if(ndo->ndo_vflag) ND_PRINT("\n\t----"); 846*ee67461eSJoseph Mingrone else ND_PRINT(" |"); 847*ee67461eSJoseph Mingrone ret = babel_print_v2_tlvs(ndo, cp, length, length); 848*ee67461eSJoseph Mingrone if (ret == -1) 849*ee67461eSJoseph Mingrone goto trunc; 850*ee67461eSJoseph Mingrone if (ret == -2) 851*ee67461eSJoseph Mingrone goto invalid; 852*ee67461eSJoseph Mingrone } 853cac3dcd5SXin LI return; 854cac3dcd5SXin LI 855cac3dcd5SXin LI trunc: 856*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 857cac3dcd5SXin LI return; 858cac3dcd5SXin LI 8593340d773SGleb Smirnoff invalid: 860*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 861cac3dcd5SXin LI } 862