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 */ 303340d773SGleb Smirnoff 31cac3dcd5SXin LI #ifdef HAVE_CONFIG_H 32cac3dcd5SXin LI #include "config.h" 33cac3dcd5SXin LI #endif 34cac3dcd5SXin LI 353340d773SGleb Smirnoff #include <netdissect-stdinc.h> 36cac3dcd5SXin LI 37cac3dcd5SXin LI #include <stdio.h> 38cac3dcd5SXin LI #include <string.h> 39cac3dcd5SXin LI 403340d773SGleb Smirnoff #include "netdissect.h" 413c602fabSXin LI #include "addrtoname.h" 42cac3dcd5SXin LI #include "extract.h" 43cac3dcd5SXin LI 443c602fabSXin LI static const char tstr[] = "[|babel]"; 453c602fabSXin LI 463c602fabSXin LI static void babel_print_v2(netdissect_options *, const u_char *cp, u_int length); 47cac3dcd5SXin LI 48cac3dcd5SXin LI void 493c602fabSXin LI babel_print(netdissect_options *ndo, 508bdc5a62SPatrick Kelsey const u_char *cp, u_int length) 518bdc5a62SPatrick Kelsey { 523c602fabSXin LI ND_PRINT((ndo, "babel")); 53cac3dcd5SXin LI 543c602fabSXin LI ND_TCHECK2(*cp, 4); 55cac3dcd5SXin LI 56cac3dcd5SXin LI if(cp[0] != 42) { 573340d773SGleb Smirnoff ND_PRINT((ndo, " invalid header")); 58cac3dcd5SXin LI return; 59cac3dcd5SXin LI } else { 603c602fabSXin LI ND_PRINT((ndo, " %d", cp[1])); 61cac3dcd5SXin LI } 62cac3dcd5SXin LI 63cac3dcd5SXin LI switch(cp[1]) { 64cac3dcd5SXin LI case 2: 653c602fabSXin LI babel_print_v2(ndo, cp, length); 66cac3dcd5SXin LI break; 67cac3dcd5SXin LI default: 683c602fabSXin LI ND_PRINT((ndo, " unknown version")); 69cac3dcd5SXin LI break; 70cac3dcd5SXin LI } 71cac3dcd5SXin LI 72cac3dcd5SXin LI return; 73cac3dcd5SXin LI 74cac3dcd5SXin LI trunc: 753c602fabSXin LI ND_PRINT((ndo, " %s", tstr)); 76cac3dcd5SXin LI return; 77cac3dcd5SXin LI } 78cac3dcd5SXin LI 793c602fabSXin LI /* TLVs */ 80cac3dcd5SXin LI #define MESSAGE_PAD1 0 81cac3dcd5SXin LI #define MESSAGE_PADN 1 82cac3dcd5SXin LI #define MESSAGE_ACK_REQ 2 83cac3dcd5SXin LI #define MESSAGE_ACK 3 84cac3dcd5SXin LI #define MESSAGE_HELLO 4 85cac3dcd5SXin LI #define MESSAGE_IHU 5 86cac3dcd5SXin LI #define MESSAGE_ROUTER_ID 6 87cac3dcd5SXin LI #define MESSAGE_NH 7 88cac3dcd5SXin LI #define MESSAGE_UPDATE 8 89cac3dcd5SXin LI #define MESSAGE_REQUEST 9 90cac3dcd5SXin LI #define MESSAGE_MH_REQUEST 10 91d03c0883SXin LI #define MESSAGE_TSPC 11 92d03c0883SXin LI #define MESSAGE_HMAC 12 933340d773SGleb Smirnoff #define MESSAGE_UPDATE_SRC_SPECIFIC 13 943340d773SGleb Smirnoff #define MESSAGE_REQUEST_SRC_SPECIFIC 14 953340d773SGleb Smirnoff #define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15 96cac3dcd5SXin LI 973c602fabSXin LI /* sub-TLVs */ 983c602fabSXin LI #define MESSAGE_SUB_PAD1 0 993c602fabSXin LI #define MESSAGE_SUB_PADN 1 1003c602fabSXin LI #define MESSAGE_SUB_DIVERSITY 2 1013c602fabSXin LI #define MESSAGE_SUB_TIMESTAMP 3 1023c602fabSXin LI 1033c602fabSXin LI /* Diversity sub-TLV channel codes */ 1043c602fabSXin LI static const struct tok diversity_str[] = { 1053c602fabSXin LI { 0, "reserved" }, 1063c602fabSXin LI { 255, "all" }, 1073c602fabSXin LI { 0, NULL } 1083c602fabSXin LI }; 1093c602fabSXin LI 110cac3dcd5SXin LI static const char * 111cac3dcd5SXin LI format_id(const u_char *id) 112cac3dcd5SXin LI { 113cac3dcd5SXin LI static char buf[25]; 114cac3dcd5SXin LI snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 115cac3dcd5SXin LI id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]); 116cac3dcd5SXin LI buf[24] = '\0'; 117cac3dcd5SXin LI return buf; 118cac3dcd5SXin LI } 119cac3dcd5SXin LI 120cac3dcd5SXin LI static const unsigned char v4prefix[16] = 121cac3dcd5SXin LI {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 122cac3dcd5SXin LI 123cac3dcd5SXin LI static const char * 1243c602fabSXin LI format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen) 125cac3dcd5SXin LI { 126cac3dcd5SXin LI static char buf[50]; 127cac3dcd5SXin LI if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0) 1283c602fabSXin LI snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96); 129cac3dcd5SXin LI else 1303c602fabSXin LI snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen); 131cac3dcd5SXin LI buf[49] = '\0'; 132cac3dcd5SXin LI return buf; 133cac3dcd5SXin LI } 134cac3dcd5SXin LI 135cac3dcd5SXin LI static const char * 1363c602fabSXin LI format_address(netdissect_options *ndo, const u_char *prefix) 137cac3dcd5SXin LI { 138cac3dcd5SXin LI if(memcmp(prefix, v4prefix, 12) == 0) 1393c602fabSXin LI return ipaddr_string(ndo, prefix + 12); 140cac3dcd5SXin LI else 1413c602fabSXin LI return ip6addr_string(ndo, prefix); 142cac3dcd5SXin LI } 143cac3dcd5SXin LI 1443c602fabSXin LI static const char * 1453c602fabSXin LI format_interval(const uint16_t i) 1463c602fabSXin LI { 1473c602fabSXin LI static char buf[sizeof("000.00s")]; 1483c602fabSXin LI 1493c602fabSXin LI if (i == 0) 1503c602fabSXin LI return "0.0s (bogus)"; 1513c602fabSXin LI snprintf(buf, sizeof(buf), "%u.%02us", i / 100, i % 100); 1523c602fabSXin LI return buf; 1533c602fabSXin LI } 1543c602fabSXin LI 1553c602fabSXin LI static const char * 1563c602fabSXin LI format_interval_update(const uint16_t i) 1573c602fabSXin LI { 1583c602fabSXin LI return i == 0xFFFF ? "infinity" : format_interval(i); 1593c602fabSXin LI } 1603c602fabSXin LI 1613c602fabSXin LI static const char * 1623c602fabSXin LI format_timestamp(const uint32_t i) 1633c602fabSXin LI { 1643c602fabSXin LI static char buf[sizeof("0000.000000s")]; 1653c602fabSXin LI snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000); 1663c602fabSXin LI return buf; 1673c602fabSXin LI } 1683c602fabSXin LI 1693c602fabSXin LI /* Return number of octets consumed from the input buffer (not the prefix length 1703c602fabSXin LI * in bytes), or -1 for encoding error. */ 171cac3dcd5SXin LI static int 172cac3dcd5SXin LI network_prefix(int ae, int plen, unsigned int omitted, 173cac3dcd5SXin LI const unsigned char *p, const unsigned char *dp, 174cac3dcd5SXin LI unsigned int len, unsigned char *p_r) 175cac3dcd5SXin LI { 176cac3dcd5SXin LI unsigned pb; 177cac3dcd5SXin LI unsigned char prefix[16]; 1783c602fabSXin LI int consumed = 0; 179cac3dcd5SXin LI 180cac3dcd5SXin LI if(plen >= 0) 181cac3dcd5SXin LI pb = (plen + 7) / 8; 182cac3dcd5SXin LI else if(ae == 1) 183cac3dcd5SXin LI pb = 4; 184cac3dcd5SXin LI else 185cac3dcd5SXin LI pb = 16; 186cac3dcd5SXin LI 187cac3dcd5SXin LI if(pb > 16) 188cac3dcd5SXin LI return -1; 189cac3dcd5SXin LI 190cac3dcd5SXin LI memset(prefix, 0, 16); 191cac3dcd5SXin LI 192cac3dcd5SXin LI switch(ae) { 193cac3dcd5SXin LI case 0: break; 194cac3dcd5SXin LI case 1: 195cac3dcd5SXin LI if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) 196cac3dcd5SXin LI return -1; 197cac3dcd5SXin LI memcpy(prefix, v4prefix, 12); 198cac3dcd5SXin LI if(omitted) { 199cac3dcd5SXin LI if (dp == NULL) return -1; 200cac3dcd5SXin LI memcpy(prefix, dp, 12 + omitted); 201cac3dcd5SXin LI } 2023c602fabSXin LI if(pb > omitted) { 2033c602fabSXin LI memcpy(prefix + 12 + omitted, p, pb - omitted); 2043c602fabSXin LI consumed = pb - omitted; 2053c602fabSXin LI } 206cac3dcd5SXin LI break; 207cac3dcd5SXin LI case 2: 208cac3dcd5SXin LI if(omitted > 16 || (pb > omitted && len < pb - omitted)) 209cac3dcd5SXin LI return -1; 210cac3dcd5SXin LI if(omitted) { 211cac3dcd5SXin LI if (dp == NULL) return -1; 212cac3dcd5SXin LI memcpy(prefix, dp, omitted); 213cac3dcd5SXin LI } 2143c602fabSXin LI if(pb > omitted) { 2153c602fabSXin LI memcpy(prefix + omitted, p, pb - omitted); 2163c602fabSXin LI consumed = pb - omitted; 2173c602fabSXin LI } 218cac3dcd5SXin LI break; 219cac3dcd5SXin LI case 3: 220cac3dcd5SXin LI if(pb > 8 && len < pb - 8) return -1; 221cac3dcd5SXin LI prefix[0] = 0xfe; 222cac3dcd5SXin LI prefix[1] = 0x80; 2233c602fabSXin LI if(pb > 8) { 2243c602fabSXin LI memcpy(prefix + 8, p, pb - 8); 2253c602fabSXin LI consumed = pb - 8; 2263c602fabSXin LI } 227cac3dcd5SXin LI break; 228cac3dcd5SXin LI default: 229cac3dcd5SXin LI return -1; 230cac3dcd5SXin LI } 231cac3dcd5SXin LI 232cac3dcd5SXin LI memcpy(p_r, prefix, 16); 2333c602fabSXin LI return consumed; 234cac3dcd5SXin LI } 235cac3dcd5SXin LI 236cac3dcd5SXin LI static int 237cac3dcd5SXin LI network_address(int ae, const unsigned char *a, unsigned int len, 238cac3dcd5SXin LI unsigned char *a_r) 239cac3dcd5SXin LI { 240cac3dcd5SXin LI return network_prefix(ae, -1, 0, a, NULL, len, a_r); 241cac3dcd5SXin LI } 242cac3dcd5SXin LI 2433c602fabSXin LI /* 2443c602fabSXin LI * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126), 2453c602fabSXin LI * their encoding is similar to the encoding of TLVs, but the type namespace is 2463c602fabSXin LI * different: 2473c602fabSXin LI * 2483c602fabSXin LI * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV. 2493c602fabSXin LI * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV. 2503c602fabSXin LI * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing 2513c602fabSXin LI * data. Its body is a variable-length sequence of 8-bit unsigned integers, 2523c602fabSXin LI * each representing per-hop number of interferring radio channel for the 2533c602fabSXin LI * prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel 2543c602fabSXin LI * 255 interferes with any other channel. 2553c602fabSXin LI * o Type 3 stands for Timestamp sub-TLV, used to compute RTT between 2563c602fabSXin LI * neighbours. In the case of a Hello TLV, the body stores a 32-bits 2573c602fabSXin LI * timestamp, while in the case of a IHU TLV, two 32-bits timestamps are 2583c602fabSXin LI * stored. 2593c602fabSXin LI * 2603c602fabSXin LI * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is 2613c602fabSXin LI * only valid for TLV type 8 (Update). Note that within an Update TLV a missing 2623c602fabSXin LI * Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body. 2633c602fabSXin LI * The former would mean a lack of any claims about the interference, and the 2643c602fabSXin LI * latter would state that interference is definitely absent. 2653c602fabSXin LI * A type 3 sub-TLV is valid both for Hello and IHU TLVs, though the exact 2663c602fabSXin LI * semantic of the sub-TLV is different in each case. 2673c602fabSXin LI */ 2683c602fabSXin LI static void 2693c602fabSXin LI subtlvs_print(netdissect_options *ndo, 2708bdc5a62SPatrick Kelsey const u_char *cp, const u_char *ep, const uint8_t tlv_type) 2718bdc5a62SPatrick Kelsey { 2723c602fabSXin LI uint8_t subtype, sublen; 2733c602fabSXin LI const char *sep; 2743c602fabSXin LI uint32_t t1, t2; 2753c602fabSXin LI 2763c602fabSXin LI while (cp < ep) { 2773c602fabSXin LI subtype = *cp++; 2783c602fabSXin LI if(subtype == MESSAGE_SUB_PAD1) { 2793c602fabSXin LI ND_PRINT((ndo, " sub-pad1")); 2803c602fabSXin LI continue; 2813c602fabSXin LI } 2823c602fabSXin LI if(cp == ep) 2833340d773SGleb Smirnoff goto invalid; 2843c602fabSXin LI sublen = *cp++; 2853c602fabSXin LI if(cp + sublen > ep) 2863340d773SGleb Smirnoff goto invalid; 2873c602fabSXin LI 2883c602fabSXin LI switch(subtype) { 2893c602fabSXin LI case MESSAGE_SUB_PADN: 2903c602fabSXin LI ND_PRINT((ndo, " sub-padn")); 2913c602fabSXin LI cp += sublen; 2923c602fabSXin LI break; 2933c602fabSXin LI case MESSAGE_SUB_DIVERSITY: 2943c602fabSXin LI ND_PRINT((ndo, " sub-diversity")); 2953c602fabSXin LI if (sublen == 0) { 2963c602fabSXin LI ND_PRINT((ndo, " empty")); 2973c602fabSXin LI break; 2983c602fabSXin LI } 2993c602fabSXin LI sep = " "; 3003c602fabSXin LI while(sublen--) { 3013c602fabSXin LI ND_PRINT((ndo, "%s%s", sep, tok2str(diversity_str, "%u", *cp++))); 3023c602fabSXin LI sep = "-"; 3033c602fabSXin LI } 3043340d773SGleb Smirnoff if(tlv_type != MESSAGE_UPDATE && 3053340d773SGleb Smirnoff tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC) 3063c602fabSXin LI ND_PRINT((ndo, " (bogus)")); 3073c602fabSXin LI break; 3083c602fabSXin LI case MESSAGE_SUB_TIMESTAMP: 3093c602fabSXin LI ND_PRINT((ndo, " sub-timestamp")); 3103c602fabSXin LI if(tlv_type == MESSAGE_HELLO) { 3113c602fabSXin LI if(sublen < 4) 3123340d773SGleb Smirnoff goto invalid; 3133c602fabSXin LI t1 = EXTRACT_32BITS(cp); 3143c602fabSXin LI ND_PRINT((ndo, " %s", format_timestamp(t1))); 3153c602fabSXin LI } else if(tlv_type == MESSAGE_IHU) { 3163c602fabSXin LI if(sublen < 8) 3173340d773SGleb Smirnoff goto invalid; 3183c602fabSXin LI t1 = EXTRACT_32BITS(cp); 3193c602fabSXin LI ND_PRINT((ndo, " %s", format_timestamp(t1))); 3203c602fabSXin LI t2 = EXTRACT_32BITS(cp + 4); 3213c602fabSXin LI ND_PRINT((ndo, "|%s", format_timestamp(t2))); 3223c602fabSXin LI } else 3233c602fabSXin LI ND_PRINT((ndo, " (bogus)")); 3243c602fabSXin LI cp += sublen; 3253c602fabSXin LI break; 3263c602fabSXin LI default: 3273c602fabSXin LI ND_PRINT((ndo, " sub-unknown-0x%02x", subtype)); 3283c602fabSXin LI cp += sublen; 3293c602fabSXin LI } /* switch */ 3303c602fabSXin LI } /* while */ 3313c602fabSXin LI return; 3323c602fabSXin LI 3333340d773SGleb Smirnoff invalid: 3343340d773SGleb Smirnoff ND_PRINT((ndo, "%s", istr)); 3353c602fabSXin LI } 3363c602fabSXin LI 337cac3dcd5SXin LI #define ICHECK(i, l) \ 3383340d773SGleb Smirnoff if ((i) + (l) > bodylen || (i) + (l) > length) goto invalid; 339cac3dcd5SXin LI 340cac3dcd5SXin LI static void 3413c602fabSXin LI babel_print_v2(netdissect_options *ndo, 3428bdc5a62SPatrick Kelsey const u_char *cp, u_int length) 3438bdc5a62SPatrick Kelsey { 344cac3dcd5SXin LI u_int i; 345cac3dcd5SXin LI u_short bodylen; 346cac3dcd5SXin LI u_char v4_prefix[16] = 347cac3dcd5SXin LI {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; 348cac3dcd5SXin LI u_char v6_prefix[16] = {0}; 349cac3dcd5SXin LI 3503c602fabSXin LI ND_TCHECK2(*cp, 4); 351cac3dcd5SXin LI if (length < 4) 3523340d773SGleb Smirnoff goto invalid; 353cac3dcd5SXin LI bodylen = EXTRACT_16BITS(cp + 2); 3543c602fabSXin LI ND_PRINT((ndo, " (%u)", bodylen)); 355*39e421e8SCy Schubert if (4U + bodylen > length) 356*39e421e8SCy Schubert goto invalid; 357cac3dcd5SXin LI 358cac3dcd5SXin LI /* Process the TLVs in the body */ 359cac3dcd5SXin LI i = 0; 360cac3dcd5SXin LI while(i < bodylen) { 361cac3dcd5SXin LI const u_char *message; 362d03c0883SXin LI u_int type, len; 363cac3dcd5SXin LI 364cac3dcd5SXin LI message = cp + 4 + i; 3653c602fabSXin LI 3663c602fabSXin LI ND_TCHECK2(*message, 1); 3673c602fabSXin LI if((type = message[0]) == MESSAGE_PAD1) { 3683c602fabSXin LI ND_PRINT((ndo, ndo->ndo_vflag ? "\n\tPad 1" : " pad1")); 3693c602fabSXin LI i += 1; 3703c602fabSXin LI continue; 3713c602fabSXin LI } 3723c602fabSXin LI 3733c602fabSXin LI ND_TCHECK2(*message, 2); 374cac3dcd5SXin LI ICHECK(i, 2); 375cac3dcd5SXin LI len = message[1]; 376cac3dcd5SXin LI 3773c602fabSXin LI ND_TCHECK2(*message, 2 + len); 378cac3dcd5SXin LI ICHECK(i, 2 + len); 379cac3dcd5SXin LI 380cac3dcd5SXin LI switch(type) { 381cac3dcd5SXin LI case MESSAGE_PADN: { 3823c602fabSXin LI if (!ndo->ndo_vflag) 3833c602fabSXin LI ND_PRINT((ndo, " padN")); 384cac3dcd5SXin LI else 3853c602fabSXin LI ND_PRINT((ndo, "\n\tPad %d", len + 2)); 386cac3dcd5SXin LI } 387cac3dcd5SXin LI break; 388cac3dcd5SXin LI 389cac3dcd5SXin LI case MESSAGE_ACK_REQ: { 390cac3dcd5SXin LI u_short nonce, interval; 3913c602fabSXin LI if (!ndo->ndo_vflag) 3923c602fabSXin LI ND_PRINT((ndo, " ack-req")); 393cac3dcd5SXin LI else { 3943c602fabSXin LI ND_PRINT((ndo, "\n\tAcknowledgment Request ")); 3953340d773SGleb Smirnoff if(len < 6) goto invalid; 396cac3dcd5SXin LI nonce = EXTRACT_16BITS(message + 4); 397cac3dcd5SXin LI interval = EXTRACT_16BITS(message + 6); 3983c602fabSXin LI ND_PRINT((ndo, "%04x %s", nonce, format_interval(interval))); 399cac3dcd5SXin LI } 400cac3dcd5SXin LI } 401cac3dcd5SXin LI break; 402cac3dcd5SXin LI 403cac3dcd5SXin LI case MESSAGE_ACK: { 404cac3dcd5SXin LI u_short nonce; 4053c602fabSXin LI if (!ndo->ndo_vflag) 4063c602fabSXin LI ND_PRINT((ndo, " ack")); 407cac3dcd5SXin LI else { 4083c602fabSXin LI ND_PRINT((ndo, "\n\tAcknowledgment ")); 4093340d773SGleb Smirnoff if(len < 2) goto invalid; 410cac3dcd5SXin LI nonce = EXTRACT_16BITS(message + 2); 4113c602fabSXin LI ND_PRINT((ndo, "%04x", nonce)); 412cac3dcd5SXin LI } 413cac3dcd5SXin LI } 414cac3dcd5SXin LI break; 415cac3dcd5SXin LI 416cac3dcd5SXin LI case MESSAGE_HELLO: { 417cac3dcd5SXin LI u_short seqno, interval; 4183c602fabSXin LI if (!ndo->ndo_vflag) 4193c602fabSXin LI ND_PRINT((ndo, " hello")); 420cac3dcd5SXin LI else { 4213c602fabSXin LI ND_PRINT((ndo, "\n\tHello ")); 4223340d773SGleb Smirnoff if(len < 6) goto invalid; 423cac3dcd5SXin LI seqno = EXTRACT_16BITS(message + 4); 424cac3dcd5SXin LI interval = EXTRACT_16BITS(message + 6); 4253c602fabSXin LI ND_PRINT((ndo, "seqno %u interval %s", seqno, format_interval(interval))); 4263c602fabSXin LI /* Extra data. */ 4273c602fabSXin LI if(len > 6) 4283c602fabSXin LI subtlvs_print(ndo, message + 8, message + 2 + len, type); 429cac3dcd5SXin LI } 430cac3dcd5SXin LI } 431cac3dcd5SXin LI break; 432cac3dcd5SXin LI 433cac3dcd5SXin LI case MESSAGE_IHU: { 434cac3dcd5SXin LI unsigned short txcost, interval; 4353c602fabSXin LI if (!ndo->ndo_vflag) 4363c602fabSXin LI ND_PRINT((ndo, " ihu")); 437cac3dcd5SXin LI else { 438cac3dcd5SXin LI u_char address[16]; 439cac3dcd5SXin LI int rc; 4403c602fabSXin LI ND_PRINT((ndo, "\n\tIHU ")); 4413340d773SGleb Smirnoff if(len < 6) goto invalid; 442cac3dcd5SXin LI txcost = EXTRACT_16BITS(message + 4); 443cac3dcd5SXin LI interval = EXTRACT_16BITS(message + 6); 444cac3dcd5SXin LI rc = network_address(message[2], message + 8, len - 6, address); 4453c602fabSXin LI if(rc < 0) { ND_PRINT((ndo, "%s", tstr)); break; } 4463c602fabSXin LI ND_PRINT((ndo, "%s txcost %u interval %s", 4473c602fabSXin LI format_address(ndo, address), txcost, format_interval(interval))); 4483c602fabSXin LI /* Extra data. */ 4493c602fabSXin LI if((u_int)rc < len - 6) 4503c602fabSXin LI subtlvs_print(ndo, message + 8 + rc, message + 2 + len, 4513c602fabSXin LI type); 452cac3dcd5SXin LI } 453cac3dcd5SXin LI } 454cac3dcd5SXin LI break; 455cac3dcd5SXin LI 456cac3dcd5SXin LI case MESSAGE_ROUTER_ID: { 4573c602fabSXin LI if (!ndo->ndo_vflag) 4583c602fabSXin LI ND_PRINT((ndo, " router-id")); 459cac3dcd5SXin LI else { 4603c602fabSXin LI ND_PRINT((ndo, "\n\tRouter Id")); 4613340d773SGleb Smirnoff if(len < 10) goto invalid; 4623c602fabSXin LI ND_PRINT((ndo, " %s", format_id(message + 4))); 463cac3dcd5SXin LI } 464cac3dcd5SXin LI } 465cac3dcd5SXin LI break; 466cac3dcd5SXin LI 467cac3dcd5SXin LI case MESSAGE_NH: { 4683c602fabSXin LI if (!ndo->ndo_vflag) 4693c602fabSXin LI ND_PRINT((ndo, " nh")); 470cac3dcd5SXin LI else { 471cac3dcd5SXin LI int rc; 472cac3dcd5SXin LI u_char nh[16]; 4733c602fabSXin LI ND_PRINT((ndo, "\n\tNext Hop")); 4743340d773SGleb Smirnoff if(len < 2) goto invalid; 475cac3dcd5SXin LI rc = network_address(message[2], message + 4, len - 2, nh); 4763340d773SGleb Smirnoff if(rc < 0) goto invalid; 4773c602fabSXin LI ND_PRINT((ndo, " %s", format_address(ndo, nh))); 478cac3dcd5SXin LI } 479cac3dcd5SXin LI } 480cac3dcd5SXin LI break; 481cac3dcd5SXin LI 482cac3dcd5SXin LI case MESSAGE_UPDATE: { 4833c602fabSXin LI if (!ndo->ndo_vflag) { 4843c602fabSXin LI ND_PRINT((ndo, " update")); 485*39e421e8SCy Schubert if(len < 10) 4863c602fabSXin LI ND_PRINT((ndo, "/truncated")); 487cac3dcd5SXin LI else 4883c602fabSXin LI ND_PRINT((ndo, "%s%s%s", 489cac3dcd5SXin LI (message[3] & 0x80) ? "/prefix": "", 490cac3dcd5SXin LI (message[3] & 0x40) ? "/id" : "", 4913c602fabSXin LI (message[3] & 0x3f) ? "/unknown" : "")); 492cac3dcd5SXin LI } else { 493cac3dcd5SXin LI u_short interval, seqno, metric; 494cac3dcd5SXin LI u_char plen; 495cac3dcd5SXin LI int rc; 496cac3dcd5SXin LI u_char prefix[16]; 4973c602fabSXin LI ND_PRINT((ndo, "\n\tUpdate")); 4983340d773SGleb Smirnoff if(len < 10) goto invalid; 499cac3dcd5SXin LI plen = message[4] + (message[2] == 1 ? 96 : 0); 500cac3dcd5SXin LI rc = network_prefix(message[2], message[4], message[5], 501cac3dcd5SXin LI message + 12, 502cac3dcd5SXin LI message[2] == 1 ? v4_prefix : v6_prefix, 503cac3dcd5SXin LI len - 10, prefix); 5043340d773SGleb Smirnoff if(rc < 0) goto invalid; 505cac3dcd5SXin LI interval = EXTRACT_16BITS(message + 6); 506cac3dcd5SXin LI seqno = EXTRACT_16BITS(message + 8); 507cac3dcd5SXin LI metric = EXTRACT_16BITS(message + 10); 5083c602fabSXin LI ND_PRINT((ndo, "%s%s%s %s metric %u seqno %u interval %s", 509cac3dcd5SXin LI (message[3] & 0x80) ? "/prefix": "", 510cac3dcd5SXin LI (message[3] & 0x40) ? "/id" : "", 511cac3dcd5SXin LI (message[3] & 0x3f) ? "/unknown" : "", 5123c602fabSXin LI format_prefix(ndo, prefix, plen), 5133c602fabSXin LI metric, seqno, format_interval_update(interval))); 514cac3dcd5SXin LI if(message[3] & 0x80) { 515cac3dcd5SXin LI if(message[2] == 1) 516cac3dcd5SXin LI memcpy(v4_prefix, prefix, 16); 517cac3dcd5SXin LI else 518cac3dcd5SXin LI memcpy(v6_prefix, prefix, 16); 519cac3dcd5SXin LI } 5203c602fabSXin LI /* extra data? */ 5213c602fabSXin LI if((u_int)rc < len - 10) 5223c602fabSXin LI subtlvs_print(ndo, message + 12 + rc, message + 2 + len, type); 523cac3dcd5SXin LI } 524cac3dcd5SXin LI } 525cac3dcd5SXin LI break; 526cac3dcd5SXin LI 527cac3dcd5SXin LI case MESSAGE_REQUEST: { 5283c602fabSXin LI if (!ndo->ndo_vflag) 5293c602fabSXin LI ND_PRINT((ndo, " request")); 530cac3dcd5SXin LI else { 531cac3dcd5SXin LI int rc; 532cac3dcd5SXin LI u_char prefix[16], plen; 5333c602fabSXin LI ND_PRINT((ndo, "\n\tRequest ")); 5343340d773SGleb Smirnoff if(len < 2) goto invalid; 535cac3dcd5SXin LI plen = message[3] + (message[2] == 1 ? 96 : 0); 536cac3dcd5SXin LI rc = network_prefix(message[2], message[3], 0, 537cac3dcd5SXin LI message + 4, NULL, len - 2, prefix); 5383340d773SGleb Smirnoff if(rc < 0) goto invalid; 5393c602fabSXin LI ND_PRINT((ndo, "for %s", 5403c602fabSXin LI message[2] == 0 ? "any" : format_prefix(ndo, prefix, plen))); 541cac3dcd5SXin LI } 542cac3dcd5SXin LI } 543cac3dcd5SXin LI break; 544cac3dcd5SXin LI 545cac3dcd5SXin LI case MESSAGE_MH_REQUEST : { 5463c602fabSXin LI if (!ndo->ndo_vflag) 5473c602fabSXin LI ND_PRINT((ndo, " mh-request")); 548cac3dcd5SXin LI else { 549cac3dcd5SXin LI int rc; 550cac3dcd5SXin LI u_short seqno; 551cac3dcd5SXin LI u_char prefix[16], plen; 5523c602fabSXin LI ND_PRINT((ndo, "\n\tMH-Request ")); 5533340d773SGleb Smirnoff if(len < 14) goto invalid; 554cac3dcd5SXin LI seqno = EXTRACT_16BITS(message + 4); 555cac3dcd5SXin LI rc = network_prefix(message[2], message[3], 0, 556cac3dcd5SXin LI message + 16, NULL, len - 14, prefix); 5573340d773SGleb Smirnoff if(rc < 0) goto invalid; 558cac3dcd5SXin LI plen = message[3] + (message[2] == 1 ? 96 : 0); 5593c602fabSXin LI ND_PRINT((ndo, "(%u hops) for %s seqno %u id %s", 5603c602fabSXin LI message[6], format_prefix(ndo, prefix, plen), 5613c602fabSXin LI seqno, format_id(message + 8))); 562cac3dcd5SXin LI } 563cac3dcd5SXin LI } 564cac3dcd5SXin LI break; 565d03c0883SXin LI case MESSAGE_TSPC : 5663c602fabSXin LI if (!ndo->ndo_vflag) 5673c602fabSXin LI ND_PRINT((ndo, " tspc")); 568d03c0883SXin LI else { 5693c602fabSXin LI ND_PRINT((ndo, "\n\tTS/PC ")); 5703340d773SGleb Smirnoff if(len < 6) goto invalid; 5713c602fabSXin LI ND_PRINT((ndo, "timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4), 5723c602fabSXin LI EXTRACT_16BITS(message + 2))); 573d03c0883SXin LI } 574d03c0883SXin LI break; 575d03c0883SXin LI case MESSAGE_HMAC : { 5763c602fabSXin LI if (!ndo->ndo_vflag) 5773c602fabSXin LI ND_PRINT((ndo, " hmac")); 578d03c0883SXin LI else { 579d03c0883SXin LI unsigned j; 5803c602fabSXin LI ND_PRINT((ndo, "\n\tHMAC ")); 5813340d773SGleb Smirnoff if(len < 18) goto invalid; 5823c602fabSXin LI ND_PRINT((ndo, "key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2)); 583d03c0883SXin LI for (j = 0; j < len - 2; j++) 5843c602fabSXin LI ND_PRINT((ndo, "%02X", message[4 + j])); 585d03c0883SXin LI } 586d03c0883SXin LI } 587d03c0883SXin LI break; 5883340d773SGleb Smirnoff 5893340d773SGleb Smirnoff case MESSAGE_UPDATE_SRC_SPECIFIC : { 5903340d773SGleb Smirnoff if(!ndo->ndo_vflag) { 5913340d773SGleb Smirnoff ND_PRINT((ndo, " ss-update")); 5923340d773SGleb Smirnoff } else { 5933340d773SGleb Smirnoff u_char prefix[16], src_prefix[16]; 5943340d773SGleb Smirnoff u_short interval, seqno, metric; 5953340d773SGleb Smirnoff u_char ae, plen, src_plen, omitted; 5963340d773SGleb Smirnoff int rc; 5973340d773SGleb Smirnoff int parsed_len = 10; 5983340d773SGleb Smirnoff ND_PRINT((ndo, "\n\tSS-Update")); 5993340d773SGleb Smirnoff if(len < 10) goto invalid; 6003340d773SGleb Smirnoff ae = message[2]; 6013340d773SGleb Smirnoff src_plen = message[3]; 6023340d773SGleb Smirnoff plen = message[4]; 6033340d773SGleb Smirnoff omitted = message[5]; 6043340d773SGleb Smirnoff interval = EXTRACT_16BITS(message + 6); 6053340d773SGleb Smirnoff seqno = EXTRACT_16BITS(message + 8); 6063340d773SGleb Smirnoff metric = EXTRACT_16BITS(message + 10); 6073340d773SGleb Smirnoff rc = network_prefix(ae, plen, omitted, message + 2 + parsed_len, 6083340d773SGleb Smirnoff ae == 1 ? v4_prefix : v6_prefix, 6093340d773SGleb Smirnoff len - parsed_len, prefix); 6103340d773SGleb Smirnoff if(rc < 0) goto invalid; 6113340d773SGleb Smirnoff if(ae == 1) 6123340d773SGleb Smirnoff plen += 96; 6133340d773SGleb Smirnoff parsed_len += rc; 6143340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 6153340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 6163340d773SGleb Smirnoff if(rc < 0) goto invalid; 6173340d773SGleb Smirnoff if(ae == 1) 6183340d773SGleb Smirnoff src_plen += 96; 6193340d773SGleb Smirnoff parsed_len += rc; 6203340d773SGleb Smirnoff 6213340d773SGleb Smirnoff ND_PRINT((ndo, " %s from", format_prefix(ndo, prefix, plen))); 6223340d773SGleb Smirnoff ND_PRINT((ndo, " %s metric %u seqno %u interval %s", 6233340d773SGleb Smirnoff format_prefix(ndo, src_prefix, src_plen), 6243340d773SGleb Smirnoff metric, seqno, format_interval_update(interval))); 6253340d773SGleb Smirnoff /* extra data? */ 6263340d773SGleb Smirnoff if((u_int)parsed_len < len) 6273340d773SGleb Smirnoff subtlvs_print(ndo, message + 2 + parsed_len, 6283340d773SGleb Smirnoff message + 2 + len, type); 6293340d773SGleb Smirnoff } 6303340d773SGleb Smirnoff } 6313340d773SGleb Smirnoff break; 6323340d773SGleb Smirnoff 6333340d773SGleb Smirnoff case MESSAGE_REQUEST_SRC_SPECIFIC : { 6343340d773SGleb Smirnoff if(!ndo->ndo_vflag) 6353340d773SGleb Smirnoff ND_PRINT((ndo, " ss-request")); 6363340d773SGleb Smirnoff else { 6373340d773SGleb Smirnoff int rc, parsed_len = 3; 6383340d773SGleb Smirnoff u_char ae, plen, src_plen, prefix[16], src_prefix[16]; 6393340d773SGleb Smirnoff ND_PRINT((ndo, "\n\tSS-Request ")); 6403340d773SGleb Smirnoff if(len < 3) goto invalid; 6413340d773SGleb Smirnoff ae = message[2]; 6423340d773SGleb Smirnoff plen = message[3]; 6433340d773SGleb Smirnoff src_plen = message[4]; 6443340d773SGleb Smirnoff rc = network_prefix(ae, plen, 0, message + 2 + parsed_len, 6453340d773SGleb Smirnoff NULL, len - parsed_len, prefix); 6463340d773SGleb Smirnoff if(rc < 0) goto invalid; 6473340d773SGleb Smirnoff if(ae == 1) 6483340d773SGleb Smirnoff plen += 96; 6493340d773SGleb Smirnoff parsed_len += rc; 6503340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 6513340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 6523340d773SGleb Smirnoff if(rc < 0) goto invalid; 6533340d773SGleb Smirnoff if(ae == 1) 6543340d773SGleb Smirnoff src_plen += 96; 6553340d773SGleb Smirnoff parsed_len += rc; 6563340d773SGleb Smirnoff if(ae == 0) { 6573340d773SGleb Smirnoff ND_PRINT((ndo, "for any")); 6583340d773SGleb Smirnoff } else { 6593340d773SGleb Smirnoff ND_PRINT((ndo, "for (%s, ", format_prefix(ndo, prefix, plen))); 6603340d773SGleb Smirnoff ND_PRINT((ndo, "%s)", format_prefix(ndo, src_prefix, src_plen))); 6613340d773SGleb Smirnoff } 6623340d773SGleb Smirnoff } 6633340d773SGleb Smirnoff } 6643340d773SGleb Smirnoff break; 6653340d773SGleb Smirnoff 6663340d773SGleb Smirnoff case MESSAGE_MH_REQUEST_SRC_SPECIFIC : { 6673340d773SGleb Smirnoff if(!ndo->ndo_vflag) 6683340d773SGleb Smirnoff ND_PRINT((ndo, " ss-mh-request")); 6693340d773SGleb Smirnoff else { 6703340d773SGleb Smirnoff int rc, parsed_len = 14; 6713340d773SGleb Smirnoff u_short seqno; 6723340d773SGleb Smirnoff u_char ae, plen, src_plen, prefix[16], src_prefix[16], hopc; 6733340d773SGleb Smirnoff const u_char *router_id = NULL; 6743340d773SGleb Smirnoff ND_PRINT((ndo, "\n\tSS-MH-Request ")); 6753340d773SGleb Smirnoff if(len < 14) goto invalid; 6763340d773SGleb Smirnoff ae = message[2]; 6773340d773SGleb Smirnoff plen = message[3]; 6783340d773SGleb Smirnoff seqno = EXTRACT_16BITS(message + 4); 6793340d773SGleb Smirnoff hopc = message[6]; 6803340d773SGleb Smirnoff src_plen = message[7]; 6813340d773SGleb Smirnoff router_id = message + 8; 6823340d773SGleb Smirnoff rc = network_prefix(ae, plen, 0, message + 2 + parsed_len, 6833340d773SGleb Smirnoff NULL, len - parsed_len, prefix); 6843340d773SGleb Smirnoff if(rc < 0) goto invalid; 6853340d773SGleb Smirnoff if(ae == 1) 6863340d773SGleb Smirnoff plen += 96; 6873340d773SGleb Smirnoff parsed_len += rc; 6883340d773SGleb Smirnoff rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len, 6893340d773SGleb Smirnoff NULL, len - parsed_len, src_prefix); 6903340d773SGleb Smirnoff if(rc < 0) goto invalid; 6913340d773SGleb Smirnoff if(ae == 1) 6923340d773SGleb Smirnoff src_plen += 96; 6933340d773SGleb Smirnoff ND_PRINT((ndo, "(%u hops) for (%s, ", 6943340d773SGleb Smirnoff hopc, format_prefix(ndo, prefix, plen))); 6953340d773SGleb Smirnoff ND_PRINT((ndo, "%s) seqno %u id %s", 6963340d773SGleb Smirnoff format_prefix(ndo, src_prefix, src_plen), 6973340d773SGleb Smirnoff seqno, format_id(router_id))); 6983340d773SGleb Smirnoff } 6993340d773SGleb Smirnoff } 7003340d773SGleb Smirnoff break; 7013340d773SGleb Smirnoff 702cac3dcd5SXin LI default: 7033c602fabSXin LI if (!ndo->ndo_vflag) 7043c602fabSXin LI ND_PRINT((ndo, " unknown")); 705cac3dcd5SXin LI else 7063c602fabSXin LI ND_PRINT((ndo, "\n\tUnknown message type %d", type)); 707cac3dcd5SXin LI } 708cac3dcd5SXin LI i += len + 2; 709cac3dcd5SXin LI } 710cac3dcd5SXin LI return; 711cac3dcd5SXin LI 712cac3dcd5SXin LI trunc: 7133c602fabSXin LI ND_PRINT((ndo, " %s", tstr)); 714cac3dcd5SXin LI return; 715cac3dcd5SXin LI 7163340d773SGleb Smirnoff invalid: 7173340d773SGleb Smirnoff ND_PRINT((ndo, "%s", istr)); 718cac3dcd5SXin LI return; 719cac3dcd5SXin LI } 720