xref: /freebsd/contrib/tcpdump/print-babel.c (revision ee67461e56828dd1f8de165947ba83f6d9148a87)
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