xref: /dflybsd-src/contrib/tcpdump/print-babel.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
127bfbee1SPeter Avalos /*
227bfbee1SPeter Avalos  * Copyright (c) 2007-2011 Grégoire Henry, Juliusz Chroboczek
327bfbee1SPeter Avalos  *
427bfbee1SPeter Avalos  * Redistribution and use in source and binary forms, with or without
527bfbee1SPeter Avalos  * modification, are permitted provided that the following conditions
627bfbee1SPeter Avalos  * are met:
727bfbee1SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
827bfbee1SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
927bfbee1SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
1027bfbee1SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
1127bfbee1SPeter Avalos  *    documentation and/or other materials provided with the distribution.
1227bfbee1SPeter Avalos  * 3. Neither the name of the project nor the names of its contributors
1327bfbee1SPeter Avalos  *    may be used to endorse or promote products derived from this software
1427bfbee1SPeter Avalos  *    without specific prior written permission.
1527bfbee1SPeter Avalos  *
1627bfbee1SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1727bfbee1SPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1827bfbee1SPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1927bfbee1SPeter Avalos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2027bfbee1SPeter Avalos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2127bfbee1SPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2227bfbee1SPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2327bfbee1SPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2427bfbee1SPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2527bfbee1SPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2627bfbee1SPeter Avalos  * SUCH DAMAGE.
2727bfbee1SPeter Avalos  */
2827bfbee1SPeter Avalos 
29411677aeSAaron LI /* \summary: Babel Routing Protocol printer */
30*ed775ee7SAntonio Huete Jimenez /* Specifications:
31*ed775ee7SAntonio Huete Jimenez  *
32*ed775ee7SAntonio Huete Jimenez  * RFC 6126
33*ed775ee7SAntonio Huete Jimenez  * RFC 7298
34*ed775ee7SAntonio Huete Jimenez  * RFC 7557
35*ed775ee7SAntonio Huete Jimenez  * draft-ietf-babel-rfc6126bis-17
36*ed775ee7SAntonio Huete Jimenez  * draft-ietf-babel-hmac-10
37*ed775ee7SAntonio Huete Jimenez  * draft-ietf-babel-source-specific-0
38*ed775ee7SAntonio Huete Jimenez  */
39411677aeSAaron LI 
4027bfbee1SPeter Avalos #ifdef HAVE_CONFIG_H
41*ed775ee7SAntonio Huete Jimenez #include <config.h>
4227bfbee1SPeter Avalos #endif
4327bfbee1SPeter Avalos 
44*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
4527bfbee1SPeter Avalos 
4627bfbee1SPeter Avalos #include <stdio.h>
4727bfbee1SPeter Avalos #include <string.h>
4827bfbee1SPeter Avalos 
49411677aeSAaron LI #include "netdissect.h"
5027bfbee1SPeter Avalos #include "addrtoname.h"
5127bfbee1SPeter Avalos #include "extract.h"
5227bfbee1SPeter Avalos 
53411677aeSAaron LI static void babel_print_v2(netdissect_options *, const u_char *cp, u_int length);
5427bfbee1SPeter Avalos 
5527bfbee1SPeter Avalos void
babel_print(netdissect_options * ndo,const u_char * cp,u_int length)56411677aeSAaron LI babel_print(netdissect_options *ndo,
57411677aeSAaron LI             const u_char *cp, u_int length)
58411677aeSAaron LI {
59*ed775ee7SAntonio Huete Jimenez     ndo->ndo_protocol = "babel";
60*ed775ee7SAntonio Huete Jimenez     ND_PRINT("babel");
6127bfbee1SPeter Avalos 
62*ed775ee7SAntonio Huete Jimenez     ND_TCHECK_4(cp);
6327bfbee1SPeter Avalos 
64*ed775ee7SAntonio Huete Jimenez     if(GET_U_1(cp) != 42) {
65*ed775ee7SAntonio Huete Jimenez         ND_PRINT(" invalid header");
6627bfbee1SPeter Avalos         return;
6727bfbee1SPeter Avalos     } else {
68*ed775ee7SAntonio Huete Jimenez         ND_PRINT(" %u", GET_U_1(cp + 1));
6927bfbee1SPeter Avalos     }
7027bfbee1SPeter Avalos 
71*ed775ee7SAntonio Huete Jimenez     switch(GET_U_1(cp + 1)) {
7227bfbee1SPeter Avalos     case 2:
73411677aeSAaron LI         babel_print_v2(ndo, cp, length);
7427bfbee1SPeter Avalos         break;
7527bfbee1SPeter Avalos     default:
76*ed775ee7SAntonio Huete Jimenez         ND_PRINT(" unknown version");
7727bfbee1SPeter Avalos         break;
7827bfbee1SPeter Avalos     }
7927bfbee1SPeter Avalos 
8027bfbee1SPeter Avalos     return;
8127bfbee1SPeter Avalos 
8227bfbee1SPeter Avalos  trunc:
83*ed775ee7SAntonio Huete Jimenez     nd_print_trunc(ndo);
8427bfbee1SPeter Avalos }
8527bfbee1SPeter Avalos 
86411677aeSAaron LI /* TLVs */
8727bfbee1SPeter Avalos #define MESSAGE_PAD1 0
8827bfbee1SPeter Avalos #define MESSAGE_PADN 1
8927bfbee1SPeter Avalos #define MESSAGE_ACK_REQ 2
9027bfbee1SPeter Avalos #define MESSAGE_ACK 3
9127bfbee1SPeter Avalos #define MESSAGE_HELLO 4
9227bfbee1SPeter Avalos #define MESSAGE_IHU 5
9327bfbee1SPeter Avalos #define MESSAGE_ROUTER_ID 6
9427bfbee1SPeter Avalos #define MESSAGE_NH 7
9527bfbee1SPeter Avalos #define MESSAGE_UPDATE 8
96*ed775ee7SAntonio Huete Jimenez #define MESSAGE_ROUTE_REQUEST 9
97*ed775ee7SAntonio Huete Jimenez #define MESSAGE_SEQNO_REQUEST 10
98411677aeSAaron LI #define MESSAGE_TSPC 11
99411677aeSAaron LI #define MESSAGE_HMAC 12
100*ed775ee7SAntonio Huete Jimenez #define MESSAGE_UPDATE_SRC_SPECIFIC 13 /* last appearance in draft-boutier-babel-source-specific-01 */
101*ed775ee7SAntonio Huete Jimenez #define MESSAGE_REQUEST_SRC_SPECIFIC 14 /* idem */
102*ed775ee7SAntonio Huete Jimenez #define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15 /* idem */
103*ed775ee7SAntonio Huete Jimenez #define MESSAGE_MAC 16
104*ed775ee7SAntonio Huete Jimenez #define MESSAGE_PC 17
105*ed775ee7SAntonio Huete Jimenez #define MESSAGE_CHALLENGE_REQUEST 18
106*ed775ee7SAntonio Huete Jimenez #define MESSAGE_CHALLENGE_REPLY 19
107411677aeSAaron LI 
108411677aeSAaron LI /* sub-TLVs */
109411677aeSAaron LI #define MESSAGE_SUB_PAD1 0
110411677aeSAaron LI #define MESSAGE_SUB_PADN 1
111411677aeSAaron LI #define MESSAGE_SUB_DIVERSITY 2
112411677aeSAaron LI #define MESSAGE_SUB_TIMESTAMP 3
113411677aeSAaron LI 
114*ed775ee7SAntonio Huete Jimenez /* "Mandatory" bit in sub-TLV types */
115*ed775ee7SAntonio Huete Jimenez #define MANDATORY_MASK 0x80
116*ed775ee7SAntonio Huete Jimenez 
117*ed775ee7SAntonio Huete Jimenez /* Flags for the Hello TLV */
118*ed775ee7SAntonio Huete Jimenez #define UNICAST_MASK 0x8000
119*ed775ee7SAntonio Huete Jimenez 
120411677aeSAaron LI /* Diversity sub-TLV channel codes */
121411677aeSAaron LI static const struct tok diversity_str[] = {
122411677aeSAaron LI     { 0,   "reserved" },
123411677aeSAaron LI     { 255, "all"      },
124411677aeSAaron LI     { 0, NULL }
125411677aeSAaron LI };
12627bfbee1SPeter Avalos 
12727bfbee1SPeter Avalos static const char *
format_id(netdissect_options * ndo,const u_char * id)128*ed775ee7SAntonio Huete Jimenez format_id(netdissect_options *ndo, const u_char *id)
12927bfbee1SPeter Avalos {
13027bfbee1SPeter Avalos     static char buf[25];
13127bfbee1SPeter Avalos     snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
132*ed775ee7SAntonio Huete Jimenez              GET_U_1(id), GET_U_1(id + 1), GET_U_1(id + 2),
133*ed775ee7SAntonio Huete Jimenez              GET_U_1(id + 3), GET_U_1(id + 4), GET_U_1(id + 5),
134*ed775ee7SAntonio Huete Jimenez              GET_U_1(id + 6), GET_U_1(id + 7));
13527bfbee1SPeter Avalos     buf[24] = '\0';
13627bfbee1SPeter Avalos     return buf;
13727bfbee1SPeter Avalos }
13827bfbee1SPeter Avalos 
13927bfbee1SPeter Avalos static const unsigned char v4prefix[16] =
14027bfbee1SPeter Avalos     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
14127bfbee1SPeter Avalos 
14227bfbee1SPeter Avalos static const char *
format_prefix(netdissect_options * ndo,const u_char * prefix,unsigned char plen)143411677aeSAaron LI format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen)
14427bfbee1SPeter Avalos {
14527bfbee1SPeter Avalos     static char buf[50];
146*ed775ee7SAntonio Huete Jimenez 
147*ed775ee7SAntonio Huete Jimenez     /*
148*ed775ee7SAntonio Huete Jimenez      * prefix points to a buffer on the stack into which the prefix has
149*ed775ee7SAntonio Huete Jimenez      * been placed, so we can't use GET_IPADDR_STRING() or
150*ed775ee7SAntonio Huete Jimenez      * GET_IP6ADDR_STRING() on it.
151*ed775ee7SAntonio Huete Jimenez      */
15227bfbee1SPeter Avalos     if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
153411677aeSAaron LI         snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96);
15427bfbee1SPeter Avalos     else
155411677aeSAaron LI         snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen);
15627bfbee1SPeter Avalos     buf[49] = '\0';
15727bfbee1SPeter Avalos     return buf;
15827bfbee1SPeter Avalos }
15927bfbee1SPeter Avalos 
16027bfbee1SPeter Avalos static const char *
format_address(netdissect_options * ndo,const u_char * prefix)161411677aeSAaron LI format_address(netdissect_options *ndo, const u_char *prefix)
16227bfbee1SPeter Avalos {
163*ed775ee7SAntonio Huete Jimenez     /*
164*ed775ee7SAntonio Huete Jimenez      * prefix points to a buffer on the stack into which the prefix has
165*ed775ee7SAntonio Huete Jimenez      * been placed, so we can't use GET_IPADDR_STRING() or
166*ed775ee7SAntonio Huete Jimenez      * GET_IP6ADDR_STRING() on it.
167*ed775ee7SAntonio Huete Jimenez      */
16827bfbee1SPeter Avalos     if(memcmp(prefix, v4prefix, 12) == 0)
169411677aeSAaron LI         return ipaddr_string(ndo, prefix + 12);
17027bfbee1SPeter Avalos     else
171411677aeSAaron LI         return ip6addr_string(ndo, prefix);
17227bfbee1SPeter Avalos }
17327bfbee1SPeter Avalos 
174411677aeSAaron LI static const char *
format_interval(const uint16_t i)175411677aeSAaron LI format_interval(const uint16_t i)
176411677aeSAaron LI {
177411677aeSAaron LI     static char buf[sizeof("000.00s")];
178411677aeSAaron LI 
179411677aeSAaron LI     if (i == 0)
180411677aeSAaron LI         return "0.0s (bogus)";
181411677aeSAaron LI     snprintf(buf, sizeof(buf), "%u.%02us", i / 100, i % 100);
182411677aeSAaron LI     return buf;
183411677aeSAaron LI }
184411677aeSAaron LI 
185411677aeSAaron LI static const char *
format_interval_update(const uint16_t i)186411677aeSAaron LI format_interval_update(const uint16_t i)
187411677aeSAaron LI {
188411677aeSAaron LI     return i == 0xFFFF ? "infinity" : format_interval(i);
189411677aeSAaron LI }
190411677aeSAaron LI 
191411677aeSAaron LI static const char *
format_timestamp(const uint32_t i)192411677aeSAaron LI format_timestamp(const uint32_t i)
193411677aeSAaron LI {
194411677aeSAaron LI     static char buf[sizeof("0000.000000s")];
195411677aeSAaron LI     snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000);
196411677aeSAaron LI     return buf;
197411677aeSAaron LI }
198411677aeSAaron LI 
199411677aeSAaron LI /* Return number of octets consumed from the input buffer (not the prefix length
200411677aeSAaron LI  * in bytes), or -1 for encoding error. */
20127bfbee1SPeter Avalos static int
network_prefix(int ae,int plen,unsigned int omitted,const unsigned char * p,const unsigned char * dp,unsigned int len,unsigned char * p_r)20227bfbee1SPeter Avalos network_prefix(int ae, int plen, unsigned int omitted,
20327bfbee1SPeter Avalos                const unsigned char *p, const unsigned char *dp,
20427bfbee1SPeter Avalos                unsigned int len, unsigned char *p_r)
20527bfbee1SPeter Avalos {
20627bfbee1SPeter Avalos     unsigned pb;
20727bfbee1SPeter Avalos     unsigned char prefix[16];
208411677aeSAaron LI     int consumed = 0;
20927bfbee1SPeter Avalos 
21027bfbee1SPeter Avalos     if(plen >= 0)
21127bfbee1SPeter Avalos         pb = (plen + 7) / 8;
21227bfbee1SPeter Avalos     else if(ae == 1)
21327bfbee1SPeter Avalos         pb = 4;
21427bfbee1SPeter Avalos     else
21527bfbee1SPeter Avalos         pb = 16;
21627bfbee1SPeter Avalos 
21727bfbee1SPeter Avalos     if(pb > 16)
21827bfbee1SPeter Avalos         return -1;
21927bfbee1SPeter Avalos 
22027bfbee1SPeter Avalos     memset(prefix, 0, 16);
22127bfbee1SPeter Avalos 
22227bfbee1SPeter Avalos     switch(ae) {
22327bfbee1SPeter Avalos     case 0: break;
22427bfbee1SPeter Avalos     case 1:
22527bfbee1SPeter Avalos         if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
22627bfbee1SPeter Avalos             return -1;
22727bfbee1SPeter Avalos         memcpy(prefix, v4prefix, 12);
22827bfbee1SPeter Avalos         if(omitted) {
22927bfbee1SPeter Avalos             if (dp == NULL) return -1;
23027bfbee1SPeter Avalos             memcpy(prefix, dp, 12 + omitted);
23127bfbee1SPeter Avalos         }
232411677aeSAaron LI         if(pb > omitted) {
233411677aeSAaron LI             memcpy(prefix + 12 + omitted, p, pb - omitted);
234411677aeSAaron LI             consumed = pb - omitted;
235411677aeSAaron LI         }
23627bfbee1SPeter Avalos         break;
23727bfbee1SPeter Avalos     case 2:
23827bfbee1SPeter Avalos         if(omitted > 16 || (pb > omitted && len < pb - omitted))
23927bfbee1SPeter Avalos             return -1;
24027bfbee1SPeter Avalos         if(omitted) {
24127bfbee1SPeter Avalos             if (dp == NULL) return -1;
24227bfbee1SPeter Avalos             memcpy(prefix, dp, omitted);
24327bfbee1SPeter Avalos         }
244411677aeSAaron LI         if(pb > omitted) {
245411677aeSAaron LI             memcpy(prefix + omitted, p, pb - omitted);
246411677aeSAaron LI             consumed = pb - omitted;
247411677aeSAaron LI         }
24827bfbee1SPeter Avalos         break;
24927bfbee1SPeter Avalos     case 3:
25027bfbee1SPeter Avalos         if(pb > 8 && len < pb - 8) return -1;
25127bfbee1SPeter Avalos         prefix[0] = 0xfe;
25227bfbee1SPeter Avalos         prefix[1] = 0x80;
253411677aeSAaron LI         if(pb > 8) {
254411677aeSAaron LI             memcpy(prefix + 8, p, pb - 8);
255411677aeSAaron LI             consumed = pb - 8;
256411677aeSAaron LI         }
25727bfbee1SPeter Avalos         break;
25827bfbee1SPeter Avalos     default:
25927bfbee1SPeter Avalos         return -1;
26027bfbee1SPeter Avalos     }
26127bfbee1SPeter Avalos 
26227bfbee1SPeter Avalos     memcpy(p_r, prefix, 16);
263411677aeSAaron LI     return consumed;
26427bfbee1SPeter Avalos }
26527bfbee1SPeter Avalos 
26627bfbee1SPeter Avalos static int
network_address(int ae,const unsigned char * a,unsigned int len,unsigned char * a_r)26727bfbee1SPeter Avalos network_address(int ae, const unsigned char *a, unsigned int len,
26827bfbee1SPeter Avalos                 unsigned char *a_r)
26927bfbee1SPeter Avalos {
27027bfbee1SPeter Avalos     return network_prefix(ae, -1, 0, a, NULL, len, a_r);
27127bfbee1SPeter Avalos }
27227bfbee1SPeter Avalos 
273411677aeSAaron LI /*
274411677aeSAaron LI  * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126),
275411677aeSAaron LI  * their encoding is similar to the encoding of TLVs, but the type namespace is
276411677aeSAaron LI  * different:
277411677aeSAaron LI  *
278411677aeSAaron LI  * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV.
279411677aeSAaron LI  * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV.
280411677aeSAaron LI  * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing
281411677aeSAaron LI  *   data. Its body is a variable-length sequence of 8-bit unsigned integers,
282*ed775ee7SAntonio Huete Jimenez  *   each representing per-hop number of interfering radio channel for the
283411677aeSAaron LI  *   prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel
284411677aeSAaron LI  *   255 interferes with any other channel.
285411677aeSAaron LI  * o Type 3 stands for Timestamp sub-TLV, used to compute RTT between
286411677aeSAaron LI  *   neighbours. In the case of a Hello TLV, the body stores a 32-bits
287411677aeSAaron LI  *   timestamp, while in the case of a IHU TLV, two 32-bits timestamps are
288411677aeSAaron LI  *   stored.
289411677aeSAaron LI  *
290411677aeSAaron LI  * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is
291411677aeSAaron LI  * only valid for TLV type 8 (Update). Note that within an Update TLV a missing
292411677aeSAaron LI  * Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body.
293411677aeSAaron LI  * The former would mean a lack of any claims about the interference, and the
294411677aeSAaron LI  * latter would state that interference is definitely absent.
295411677aeSAaron LI  * A type 3 sub-TLV is valid both for Hello and IHU TLVs, though the exact
296411677aeSAaron LI  * semantic of the sub-TLV is different in each case.
297411677aeSAaron LI  */
298411677aeSAaron LI static void
subtlvs_print(netdissect_options * ndo,const u_char * cp,const u_char * ep,const uint8_t tlv_type)299411677aeSAaron LI subtlvs_print(netdissect_options *ndo,
300411677aeSAaron LI               const u_char *cp, const u_char *ep, const uint8_t tlv_type)
301411677aeSAaron LI {
302411677aeSAaron LI     uint8_t subtype, sublen;
303411677aeSAaron LI     const char *sep;
304411677aeSAaron LI     uint32_t t1, t2;
305411677aeSAaron LI 
306411677aeSAaron LI     while (cp < ep) {
307*ed775ee7SAntonio Huete Jimenez         subtype = GET_U_1(cp);
308*ed775ee7SAntonio Huete Jimenez         cp++;
309411677aeSAaron LI         if(subtype == MESSAGE_SUB_PAD1) {
310*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" sub-pad1");
311411677aeSAaron LI             continue;
312411677aeSAaron LI         }
313*ed775ee7SAntonio Huete Jimenez         if ((MANDATORY_MASK & subtype) != 0)
314*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" (M)");
315411677aeSAaron LI         if(cp == ep)
316411677aeSAaron LI             goto invalid;
317*ed775ee7SAntonio Huete Jimenez         sublen = GET_U_1(cp);
318*ed775ee7SAntonio Huete Jimenez         cp++;
319411677aeSAaron LI         if(cp + sublen > ep)
320411677aeSAaron LI             goto invalid;
321411677aeSAaron LI 
322411677aeSAaron LI         switch(subtype) {
323411677aeSAaron LI         case MESSAGE_SUB_PADN:
324*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" sub-padn");
325411677aeSAaron LI             cp += sublen;
326411677aeSAaron LI             break;
327411677aeSAaron LI         case MESSAGE_SUB_DIVERSITY:
328*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" sub-diversity");
329411677aeSAaron LI             if (sublen == 0) {
330*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" empty");
331411677aeSAaron LI                 break;
332411677aeSAaron LI             }
333411677aeSAaron LI             sep = " ";
334*ed775ee7SAntonio Huete Jimenez             while (sublen) {
335*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("%s%s", sep,
336*ed775ee7SAntonio Huete Jimenez                          tok2str(diversity_str, "%u", GET_U_1(cp)));
337*ed775ee7SAntonio Huete Jimenez                 cp++;
338411677aeSAaron LI                 sep = "-";
339*ed775ee7SAntonio Huete Jimenez                 sublen--;
340411677aeSAaron LI             }
341411677aeSAaron LI             if(tlv_type != MESSAGE_UPDATE &&
342411677aeSAaron LI                tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC)
343*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" (bogus)");
344411677aeSAaron LI             break;
345411677aeSAaron LI         case MESSAGE_SUB_TIMESTAMP:
346*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" sub-timestamp");
347411677aeSAaron LI             if(tlv_type == MESSAGE_HELLO) {
348411677aeSAaron LI                 if(sublen < 4)
349411677aeSAaron LI                     goto invalid;
350*ed775ee7SAntonio Huete Jimenez                 t1 = GET_BE_U_4(cp);
351*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" %s", format_timestamp(t1));
352411677aeSAaron LI             } else if(tlv_type == MESSAGE_IHU) {
353411677aeSAaron LI                 if(sublen < 8)
354411677aeSAaron LI                     goto invalid;
355*ed775ee7SAntonio Huete Jimenez                 t1 = GET_BE_U_4(cp);
356*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" %s", format_timestamp(t1));
357*ed775ee7SAntonio Huete Jimenez                 t2 = GET_BE_U_4(cp + 4);
358*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("|%s", format_timestamp(t2));
359411677aeSAaron LI             } else
360*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" (bogus)");
361411677aeSAaron LI             cp += sublen;
362411677aeSAaron LI             break;
363411677aeSAaron LI         default:
364*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" sub-unknown-0x%02x", subtype);
365411677aeSAaron LI             cp += sublen;
366411677aeSAaron LI         } /* switch */
367411677aeSAaron LI     } /* while */
368411677aeSAaron LI     return;
369411677aeSAaron LI 
370411677aeSAaron LI  invalid:
371*ed775ee7SAntonio Huete Jimenez     nd_print_invalid(ndo);
372411677aeSAaron LI }
373411677aeSAaron LI 
37427bfbee1SPeter Avalos #define ICHECK(i, l) \
375*ed775ee7SAntonio Huete Jimenez 	if ((i) + (l) > tlvs_length || (i) + (l) > packet_length_remaining) \
376*ed775ee7SAntonio Huete Jimenez 	    goto invalid;
37727bfbee1SPeter Avalos 
378*ed775ee7SAntonio Huete Jimenez static int
babel_print_v2_tlvs(netdissect_options * ndo,const u_char * cp,u_int tlvs_length,u_int packet_length_remaining)379*ed775ee7SAntonio Huete Jimenez babel_print_v2_tlvs(netdissect_options *ndo,
380*ed775ee7SAntonio Huete Jimenez                     const u_char *cp, u_int tlvs_length,
381*ed775ee7SAntonio Huete Jimenez                     u_int packet_length_remaining)
382411677aeSAaron LI {
38327bfbee1SPeter Avalos     u_int i;
38427bfbee1SPeter Avalos     u_char v4_prefix[16] =
38527bfbee1SPeter Avalos         {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
38627bfbee1SPeter Avalos     u_char v6_prefix[16] = {0};
38727bfbee1SPeter Avalos 
38827bfbee1SPeter Avalos     i = 0;
389*ed775ee7SAntonio Huete Jimenez     while(i < tlvs_length) {
39027bfbee1SPeter Avalos         const u_char *message;
391*ed775ee7SAntonio Huete Jimenez         uint8_t type;
392*ed775ee7SAntonio Huete Jimenez         u_int len;
39327bfbee1SPeter Avalos 
394*ed775ee7SAntonio Huete Jimenez         message = cp + i;
395411677aeSAaron LI 
396*ed775ee7SAntonio Huete Jimenez         ICHECK(i, 1);
397*ed775ee7SAntonio Huete Jimenez         if((type = GET_U_1(message)) == MESSAGE_PAD1) {
398*ed775ee7SAntonio Huete Jimenez             ND_PRINT(ndo->ndo_vflag ? "\n\tPad 1" : " pad1");
399411677aeSAaron LI             i += 1;
400411677aeSAaron LI             continue;
401411677aeSAaron LI         }
402411677aeSAaron LI 
40327bfbee1SPeter Avalos         ICHECK(i, 2);
404*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_2(message);
405*ed775ee7SAntonio Huete Jimenez         len = GET_U_1(message + 1);
40627bfbee1SPeter Avalos 
40727bfbee1SPeter Avalos         ICHECK(i, 2 + len);
408*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_LEN(message, 2 + len);
40927bfbee1SPeter Avalos 
41027bfbee1SPeter Avalos         switch(type) {
41127bfbee1SPeter Avalos         case MESSAGE_PADN: {
412411677aeSAaron LI             if (!ndo->ndo_vflag)
413*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" padN");
41427bfbee1SPeter Avalos             else
415*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tPad %u", len + 2);
41627bfbee1SPeter Avalos         }
41727bfbee1SPeter Avalos             break;
41827bfbee1SPeter Avalos 
41927bfbee1SPeter Avalos         case MESSAGE_ACK_REQ: {
42027bfbee1SPeter Avalos             u_short nonce, interval;
421411677aeSAaron LI             if (!ndo->ndo_vflag)
422*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" ack-req");
42327bfbee1SPeter Avalos             else {
424*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tAcknowledgment Request ");
425411677aeSAaron LI                 if(len < 6) goto invalid;
426*ed775ee7SAntonio Huete Jimenez                 nonce = GET_BE_U_2(message + 4);
427*ed775ee7SAntonio Huete Jimenez                 interval = GET_BE_U_2(message + 6);
428*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("%04x %s", nonce, format_interval(interval));
42927bfbee1SPeter Avalos             }
43027bfbee1SPeter Avalos         }
43127bfbee1SPeter Avalos             break;
43227bfbee1SPeter Avalos 
43327bfbee1SPeter Avalos         case MESSAGE_ACK: {
43427bfbee1SPeter Avalos             u_short nonce;
435411677aeSAaron LI             if (!ndo->ndo_vflag)
436*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" ack");
43727bfbee1SPeter Avalos             else {
438*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tAcknowledgment ");
439411677aeSAaron LI                 if(len < 2) goto invalid;
440*ed775ee7SAntonio Huete Jimenez                 nonce = GET_BE_U_2(message + 2);
441*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("%04x", nonce);
44227bfbee1SPeter Avalos             }
44327bfbee1SPeter Avalos         }
44427bfbee1SPeter Avalos             break;
44527bfbee1SPeter Avalos 
44627bfbee1SPeter Avalos         case MESSAGE_HELLO:  {
447*ed775ee7SAntonio Huete Jimenez             u_short seqno, interval, unicast;
448411677aeSAaron LI             if (!ndo->ndo_vflag)
449*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" hello");
45027bfbee1SPeter Avalos             else {
451*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tHello ");
452411677aeSAaron LI                 if(len < 6) goto invalid;
453*ed775ee7SAntonio Huete Jimenez                 unicast = (GET_BE_U_2(message + 2) & UNICAST_MASK);
454*ed775ee7SAntonio Huete Jimenez                 seqno = GET_BE_U_2(message + 4);
455*ed775ee7SAntonio Huete Jimenez                 interval = GET_BE_U_2(message + 6);
456*ed775ee7SAntonio Huete Jimenez                 if(unicast)
457*ed775ee7SAntonio Huete Jimenez                      ND_PRINT("(Unicast) ");
458*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("seqno %u ", seqno);
459*ed775ee7SAntonio Huete Jimenez                 if(interval!=0)
460*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("interval %s", format_interval(interval));
461*ed775ee7SAntonio Huete Jimenez                 else
462*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("unscheduled");
463411677aeSAaron LI                 /* Extra data. */
464411677aeSAaron LI                 if(len > 6)
465411677aeSAaron LI                     subtlvs_print(ndo, message + 8, message + 2 + len, type);
46627bfbee1SPeter Avalos             }
46727bfbee1SPeter Avalos         }
46827bfbee1SPeter Avalos             break;
46927bfbee1SPeter Avalos 
47027bfbee1SPeter Avalos         case MESSAGE_IHU: {
471*ed775ee7SAntonio Huete Jimenez             unsigned short rxcost, interval;
472411677aeSAaron LI             if (!ndo->ndo_vflag)
473*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" ihu");
47427bfbee1SPeter Avalos             else {
47527bfbee1SPeter Avalos                 u_char address[16];
476*ed775ee7SAntonio Huete Jimenez                 u_char ae;
47727bfbee1SPeter Avalos                 int rc;
478*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tIHU ");
479411677aeSAaron LI                 if(len < 6) goto invalid;
480*ed775ee7SAntonio Huete Jimenez                 rxcost = GET_BE_U_2(message + 4);
481*ed775ee7SAntonio Huete Jimenez                 interval = GET_BE_U_2(message + 6);
482*ed775ee7SAntonio Huete Jimenez                 ae = GET_U_1(message + 2);
483*ed775ee7SAntonio Huete Jimenez                 rc = network_address(ae, message + 8,
484*ed775ee7SAntonio Huete Jimenez                                      len - 6, address);
485*ed775ee7SAntonio Huete Jimenez                 if(rc < 0) { nd_print_trunc(ndo); break; }
486*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("%s rxcost %u interval %s",
487*ed775ee7SAntonio Huete Jimenez                        ae == 0 ? "any" : format_address(ndo, address),
488*ed775ee7SAntonio Huete Jimenez                        rxcost, format_interval(interval));
489411677aeSAaron LI                 /* Extra data. */
490411677aeSAaron LI                 if((u_int)rc < len - 6)
491411677aeSAaron LI                     subtlvs_print(ndo, message + 8 + rc, message + 2 + len,
492411677aeSAaron LI                                   type);
49327bfbee1SPeter Avalos             }
49427bfbee1SPeter Avalos         }
49527bfbee1SPeter Avalos             break;
49627bfbee1SPeter Avalos 
49727bfbee1SPeter Avalos         case MESSAGE_ROUTER_ID: {
498411677aeSAaron LI             if (!ndo->ndo_vflag)
499*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" router-id");
50027bfbee1SPeter Avalos             else {
501*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tRouter Id");
502411677aeSAaron LI                 if(len < 10) goto invalid;
503*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" %s", format_id(ndo, message + 4));
50427bfbee1SPeter Avalos             }
50527bfbee1SPeter Avalos         }
50627bfbee1SPeter Avalos             break;
50727bfbee1SPeter Avalos 
50827bfbee1SPeter Avalos         case MESSAGE_NH: {
509411677aeSAaron LI             if (!ndo->ndo_vflag)
510*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" nh");
51127bfbee1SPeter Avalos             else {
51227bfbee1SPeter Avalos                 int rc;
513*ed775ee7SAntonio Huete Jimenez                 u_char ae;
51427bfbee1SPeter Avalos                 u_char nh[16];
515*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tNext Hop");
516411677aeSAaron LI                 if(len < 2) goto invalid;
517*ed775ee7SAntonio Huete Jimenez                 ae = GET_U_1(message + 2);
518*ed775ee7SAntonio Huete Jimenez                 rc = network_address(ae, message + 4,
519*ed775ee7SAntonio Huete Jimenez                                      len - 2, nh);
520411677aeSAaron LI                 if(rc < 0) goto invalid;
521*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" %s", ae == 0 ? "invalid AE 0" : format_address(ndo, nh));
52227bfbee1SPeter Avalos             }
52327bfbee1SPeter Avalos         }
52427bfbee1SPeter Avalos             break;
52527bfbee1SPeter Avalos 
52627bfbee1SPeter Avalos         case MESSAGE_UPDATE: {
527411677aeSAaron LI             if (!ndo->ndo_vflag) {
528*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" update");
529411677aeSAaron LI                 if(len < 10)
530*ed775ee7SAntonio Huete Jimenez                     goto invalid;
53127bfbee1SPeter Avalos                 else
532*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("%s%s%s",
533*ed775ee7SAntonio Huete Jimenez                            (GET_U_1(message + 3) & 0x80) ? "/prefix": "",
534*ed775ee7SAntonio Huete Jimenez                            (GET_U_1(message + 3) & 0x40) ? "/id" : "",
535*ed775ee7SAntonio Huete Jimenez                            (GET_U_1(message + 3) & 0x3f) ? "/unknown" : "");
53627bfbee1SPeter Avalos             } else {
53727bfbee1SPeter Avalos                 u_short interval, seqno, metric;
538*ed775ee7SAntonio Huete Jimenez                 u_char ae, plen;
53927bfbee1SPeter Avalos                 int rc;
54027bfbee1SPeter Avalos                 u_char prefix[16];
541*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tUpdate");
542411677aeSAaron LI                 if(len < 10) goto invalid;
543*ed775ee7SAntonio Huete Jimenez                 ae = GET_U_1(message + 2);
544*ed775ee7SAntonio Huete Jimenez                 plen = GET_U_1(message + 4) + (GET_U_1(message + 2) == 1 ? 96 : 0);
545*ed775ee7SAntonio Huete Jimenez                 rc = network_prefix(ae,
546*ed775ee7SAntonio Huete Jimenez                                     GET_U_1(message + 4),
547*ed775ee7SAntonio Huete Jimenez                                     GET_U_1(message + 5),
54827bfbee1SPeter Avalos                                     message + 12,
549*ed775ee7SAntonio Huete Jimenez                                     GET_U_1(message + 2) == 1 ? v4_prefix : v6_prefix,
55027bfbee1SPeter Avalos                                     len - 10, prefix);
551411677aeSAaron LI                 if(rc < 0) goto invalid;
552*ed775ee7SAntonio Huete Jimenez                 interval = GET_BE_U_2(message + 6);
553*ed775ee7SAntonio Huete Jimenez                 seqno = GET_BE_U_2(message + 8);
554*ed775ee7SAntonio Huete Jimenez                 metric = GET_BE_U_2(message + 10);
555*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("%s%s%s %s metric %u seqno %u interval %s",
556*ed775ee7SAntonio Huete Jimenez                        (GET_U_1(message + 3) & 0x80) ? "/prefix": "",
557*ed775ee7SAntonio Huete Jimenez                        (GET_U_1(message + 3) & 0x40) ? "/id" : "",
558*ed775ee7SAntonio Huete Jimenez                        (GET_U_1(message + 3) & 0x3f) ? "/unknown" : "",
559*ed775ee7SAntonio Huete Jimenez                        ae == 0 ? "any" : format_prefix(ndo, prefix, plen),
560*ed775ee7SAntonio Huete Jimenez                        metric, seqno, format_interval_update(interval));
561*ed775ee7SAntonio Huete Jimenez                 if(GET_U_1(message + 3) & 0x80) {
562*ed775ee7SAntonio Huete Jimenez                     if(GET_U_1(message + 2) == 1)
56327bfbee1SPeter Avalos                         memcpy(v4_prefix, prefix, 16);
56427bfbee1SPeter Avalos                     else
56527bfbee1SPeter Avalos                         memcpy(v6_prefix, prefix, 16);
56627bfbee1SPeter Avalos                 }
567411677aeSAaron LI                 /* extra data? */
568411677aeSAaron LI                 if((u_int)rc < len - 10)
569411677aeSAaron LI                     subtlvs_print(ndo, message + 12 + rc, message + 2 + len, type);
57027bfbee1SPeter Avalos             }
57127bfbee1SPeter Avalos         }
57227bfbee1SPeter Avalos             break;
57327bfbee1SPeter Avalos 
574*ed775ee7SAntonio Huete Jimenez         case MESSAGE_ROUTE_REQUEST: {
575411677aeSAaron LI             if (!ndo->ndo_vflag)
576*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" route-request");
57727bfbee1SPeter Avalos             else {
57827bfbee1SPeter Avalos                 int rc;
579*ed775ee7SAntonio Huete Jimenez                 u_char prefix[16], ae, plen;
580*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tRoute Request ");
581411677aeSAaron LI                 if(len < 2) goto invalid;
582*ed775ee7SAntonio Huete Jimenez                 ae = GET_U_1(message + 2);
583*ed775ee7SAntonio Huete Jimenez                 plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0);
584*ed775ee7SAntonio Huete Jimenez                 rc = network_prefix(ae,
585*ed775ee7SAntonio Huete Jimenez                                     GET_U_1(message + 3), 0,
58627bfbee1SPeter Avalos                                     message + 4, NULL, len - 2, prefix);
587411677aeSAaron LI                 if(rc < 0) goto invalid;
588*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("for %s",
589*ed775ee7SAntonio Huete Jimenez                        ae == 0 ? "any" : format_prefix(ndo, prefix, plen));
59027bfbee1SPeter Avalos             }
59127bfbee1SPeter Avalos         }
59227bfbee1SPeter Avalos             break;
59327bfbee1SPeter Avalos 
594*ed775ee7SAntonio Huete Jimenez         case MESSAGE_SEQNO_REQUEST : {
595411677aeSAaron LI             if (!ndo->ndo_vflag)
596*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" seqno-request");
59727bfbee1SPeter Avalos             else {
59827bfbee1SPeter Avalos                 int rc;
59927bfbee1SPeter Avalos                 u_short seqno;
600*ed775ee7SAntonio Huete Jimenez                 u_char prefix[16], ae, plen;
601*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tSeqno Request ");
602411677aeSAaron LI                 if(len < 14) goto invalid;
603*ed775ee7SAntonio Huete Jimenez                 ae = GET_U_1(message + 2);
604*ed775ee7SAntonio Huete Jimenez                 seqno = GET_BE_U_2(message + 4);
605*ed775ee7SAntonio Huete Jimenez                 rc = network_prefix(ae,
606*ed775ee7SAntonio Huete Jimenez                                     GET_U_1(message + 3), 0,
60727bfbee1SPeter Avalos                                     message + 16, NULL, len - 14, prefix);
608411677aeSAaron LI                 if(rc < 0) goto invalid;
609*ed775ee7SAntonio Huete Jimenez                 plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0);
610*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("(%u hops) for %s seqno %u id %s",
611*ed775ee7SAntonio Huete Jimenez                        GET_U_1(message + 6),
612*ed775ee7SAntonio Huete Jimenez                        ae == 0 ? "invalid AE 0" : format_prefix(ndo, prefix, plen),
613*ed775ee7SAntonio Huete Jimenez                        seqno, format_id(ndo, message + 8));
61427bfbee1SPeter Avalos             }
61527bfbee1SPeter Avalos         }
61627bfbee1SPeter Avalos             break;
617411677aeSAaron LI         case MESSAGE_TSPC :
618411677aeSAaron LI             if (!ndo->ndo_vflag)
619*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" tspc");
620411677aeSAaron LI             else {
621*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tTS/PC ");
622411677aeSAaron LI                 if(len < 6) goto invalid;
623*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("timestamp %u packetcounter %u",
624*ed775ee7SAntonio Huete Jimenez                           GET_BE_U_4(message + 4),
625*ed775ee7SAntonio Huete Jimenez                           GET_BE_U_2(message + 2));
626411677aeSAaron LI             }
627411677aeSAaron LI             break;
628411677aeSAaron LI         case MESSAGE_HMAC : {
629411677aeSAaron LI             if (!ndo->ndo_vflag)
630*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" hmac");
631411677aeSAaron LI             else {
632411677aeSAaron LI                 unsigned j;
633*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tHMAC ");
634411677aeSAaron LI                 if(len < 18) goto invalid;
635*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("key-id %u digest-%u ", GET_BE_U_2(message + 2),
636*ed775ee7SAntonio Huete Jimenez                          len - 2);
637411677aeSAaron LI                 for (j = 0; j < len - 2; j++)
638*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("%02X", GET_U_1(message + j + 4));
639411677aeSAaron LI             }
640411677aeSAaron LI         }
641411677aeSAaron LI             break;
642411677aeSAaron LI 
643411677aeSAaron LI         case MESSAGE_UPDATE_SRC_SPECIFIC : {
644411677aeSAaron LI             if(!ndo->ndo_vflag) {
645*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" ss-update");
646411677aeSAaron LI             } else {
647411677aeSAaron LI                 u_char prefix[16], src_prefix[16];
648411677aeSAaron LI                 u_short interval, seqno, metric;
649411677aeSAaron LI                 u_char ae, plen, src_plen, omitted;
650411677aeSAaron LI                 int rc;
651411677aeSAaron LI                 int parsed_len = 10;
652*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tSS-Update");
653411677aeSAaron LI                 if(len < 10) goto invalid;
654*ed775ee7SAntonio Huete Jimenez                 ae = GET_U_1(message + 2);
655*ed775ee7SAntonio Huete Jimenez                 src_plen = GET_U_1(message + 3);
656*ed775ee7SAntonio Huete Jimenez                 plen = GET_U_1(message + 4);
657*ed775ee7SAntonio Huete Jimenez                 omitted = GET_U_1(message + 5);
658*ed775ee7SAntonio Huete Jimenez                 interval = GET_BE_U_2(message + 6);
659*ed775ee7SAntonio Huete Jimenez                 seqno = GET_BE_U_2(message + 8);
660*ed775ee7SAntonio Huete Jimenez                 metric = GET_BE_U_2(message + 10);
661411677aeSAaron LI                 rc = network_prefix(ae, plen, omitted, message + 2 + parsed_len,
662411677aeSAaron LI                                     ae == 1 ? v4_prefix : v6_prefix,
663411677aeSAaron LI                                     len - parsed_len, prefix);
664411677aeSAaron LI                 if(rc < 0) goto invalid;
665411677aeSAaron LI                 if(ae == 1)
666411677aeSAaron LI                     plen += 96;
667411677aeSAaron LI                 parsed_len += rc;
668411677aeSAaron LI                 rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
669411677aeSAaron LI                                     NULL, len - parsed_len, src_prefix);
670411677aeSAaron LI                 if(rc < 0) goto invalid;
671411677aeSAaron LI                 if(ae == 1)
672411677aeSAaron LI                     src_plen += 96;
673411677aeSAaron LI                 parsed_len += rc;
674411677aeSAaron LI 
675*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" %s from", format_prefix(ndo, prefix, plen));
676*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" %s metric %u seqno %u interval %s",
677411677aeSAaron LI                           format_prefix(ndo, src_prefix, src_plen),
678*ed775ee7SAntonio Huete Jimenez                           metric, seqno, format_interval_update(interval));
679411677aeSAaron LI                 /* extra data? */
680411677aeSAaron LI                 if((u_int)parsed_len < len)
681411677aeSAaron LI                     subtlvs_print(ndo, message + 2 + parsed_len,
682411677aeSAaron LI                                   message + 2 + len, type);
683411677aeSAaron LI             }
684411677aeSAaron LI         }
685411677aeSAaron LI             break;
686411677aeSAaron LI 
687411677aeSAaron LI         case MESSAGE_REQUEST_SRC_SPECIFIC : {
688411677aeSAaron LI             if(!ndo->ndo_vflag)
689*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" ss-request");
690411677aeSAaron LI             else {
691411677aeSAaron LI                 int rc, parsed_len = 3;
692411677aeSAaron LI                 u_char ae, plen, src_plen, prefix[16], src_prefix[16];
693*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tSS-Request ");
694411677aeSAaron LI                 if(len < 3) goto invalid;
695*ed775ee7SAntonio Huete Jimenez                 ae = GET_U_1(message + 2);
696*ed775ee7SAntonio Huete Jimenez                 plen = GET_U_1(message + 3);
697*ed775ee7SAntonio Huete Jimenez                 src_plen = GET_U_1(message + 4);
698411677aeSAaron LI                 rc = network_prefix(ae, plen, 0, message + 2 + parsed_len,
699411677aeSAaron LI                                     NULL, len - parsed_len, prefix);
700411677aeSAaron LI                 if(rc < 0) goto invalid;
701411677aeSAaron LI                 if(ae == 1)
702411677aeSAaron LI                     plen += 96;
703411677aeSAaron LI                 parsed_len += rc;
704411677aeSAaron LI                 rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
705411677aeSAaron LI                                     NULL, len - parsed_len, src_prefix);
706411677aeSAaron LI                 if(rc < 0) goto invalid;
707411677aeSAaron LI                 if(ae == 1)
708411677aeSAaron LI                     src_plen += 96;
709411677aeSAaron LI                 parsed_len += rc;
710411677aeSAaron LI                 if(ae == 0) {
711*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("for any");
712411677aeSAaron LI                 } else {
713*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("for (%s, ", format_prefix(ndo, prefix, plen));
714*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("%s)", format_prefix(ndo, src_prefix, src_plen));
715411677aeSAaron LI                 }
716411677aeSAaron LI             }
717411677aeSAaron LI         }
718411677aeSAaron LI             break;
719411677aeSAaron LI 
720411677aeSAaron LI         case MESSAGE_MH_REQUEST_SRC_SPECIFIC : {
721411677aeSAaron LI             if(!ndo->ndo_vflag)
722*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" ss-mh-request");
723411677aeSAaron LI             else {
724411677aeSAaron LI                 int rc, parsed_len = 14;
725411677aeSAaron LI                 u_short seqno;
726411677aeSAaron LI                 u_char ae, plen, src_plen, prefix[16], src_prefix[16], hopc;
727411677aeSAaron LI                 const u_char *router_id = NULL;
728*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tSS-MH-Request ");
729411677aeSAaron LI                 if(len < 14) goto invalid;
730*ed775ee7SAntonio Huete Jimenez                 ae = GET_U_1(message + 2);
731*ed775ee7SAntonio Huete Jimenez                 plen = GET_U_1(message + 3);
732*ed775ee7SAntonio Huete Jimenez                 seqno = GET_BE_U_2(message + 4);
733*ed775ee7SAntonio Huete Jimenez                 hopc = GET_U_1(message + 6);
734*ed775ee7SAntonio Huete Jimenez                 src_plen = GET_U_1(message + 7);
735411677aeSAaron LI                 router_id = message + 8;
736411677aeSAaron LI                 rc = network_prefix(ae, plen, 0, message + 2 + parsed_len,
737411677aeSAaron LI                                     NULL, len - parsed_len, prefix);
738411677aeSAaron LI                 if(rc < 0) goto invalid;
739411677aeSAaron LI                 if(ae == 1)
740411677aeSAaron LI                     plen += 96;
741411677aeSAaron LI                 parsed_len += rc;
742411677aeSAaron LI                 rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
743411677aeSAaron LI                                     NULL, len - parsed_len, src_prefix);
744411677aeSAaron LI                 if(rc < 0) goto invalid;
745411677aeSAaron LI                 if(ae == 1)
746411677aeSAaron LI                     src_plen += 96;
747*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("(%u hops) for (%s, ",
748*ed775ee7SAntonio Huete Jimenez                           hopc, format_prefix(ndo, prefix, plen));
749*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("%s) seqno %u id %s",
750411677aeSAaron LI                           format_prefix(ndo, src_prefix, src_plen),
751*ed775ee7SAntonio Huete Jimenez                           seqno, format_id(ndo, router_id));
752*ed775ee7SAntonio Huete Jimenez             }
753*ed775ee7SAntonio Huete Jimenez         }
754*ed775ee7SAntonio Huete Jimenez             break;
755*ed775ee7SAntonio Huete Jimenez 
756*ed775ee7SAntonio Huete Jimenez         case MESSAGE_MAC: {
757*ed775ee7SAntonio Huete Jimenez             if (!ndo->ndo_vflag)
758*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" mac");
759*ed775ee7SAntonio Huete Jimenez             else {
760*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tMAC ");
761*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("len %u", len);
762*ed775ee7SAntonio Huete Jimenez             }
763*ed775ee7SAntonio Huete Jimenez         }
764*ed775ee7SAntonio Huete Jimenez             break;
765*ed775ee7SAntonio Huete Jimenez 
766*ed775ee7SAntonio Huete Jimenez         case MESSAGE_PC: {
767*ed775ee7SAntonio Huete Jimenez             if (!ndo->ndo_vflag)
768*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" pc");
769*ed775ee7SAntonio Huete Jimenez             else {
770*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tPC");
771*ed775ee7SAntonio Huete Jimenez                 if(len < 4) goto invalid;
772*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" value %u",
773*ed775ee7SAntonio Huete Jimenez                     GET_BE_U_4(message + 2));
774*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" index len %u", len-4);
775*ed775ee7SAntonio Huete Jimenez             }
776*ed775ee7SAntonio Huete Jimenez         }
777*ed775ee7SAntonio Huete Jimenez             break;
778*ed775ee7SAntonio Huete Jimenez 
779*ed775ee7SAntonio Huete Jimenez         case MESSAGE_CHALLENGE_REQUEST: {
780*ed775ee7SAntonio Huete Jimenez             if (!ndo->ndo_vflag)
781*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" challenge_request");
782*ed775ee7SAntonio Huete Jimenez             else {
783*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tChallenge Request");
784*ed775ee7SAntonio Huete Jimenez                 if(len > 192) goto invalid;
785*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" len %u", len);
786*ed775ee7SAntonio Huete Jimenez             }
787*ed775ee7SAntonio Huete Jimenez         }
788*ed775ee7SAntonio Huete Jimenez             break;
789*ed775ee7SAntonio Huete Jimenez 
790*ed775ee7SAntonio Huete Jimenez         case MESSAGE_CHALLENGE_REPLY: {
791*ed775ee7SAntonio Huete Jimenez             if (!ndo->ndo_vflag)
792*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" challenge_reply");
793*ed775ee7SAntonio Huete Jimenez             else {
794*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tChallenge Reply");
795*ed775ee7SAntonio Huete Jimenez                 if (len > 192) goto invalid;
796*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" len %u", len);
797411677aeSAaron LI             }
798411677aeSAaron LI         }
799411677aeSAaron LI             break;
800411677aeSAaron LI 
80127bfbee1SPeter Avalos         default:
802411677aeSAaron LI             if (!ndo->ndo_vflag)
803*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" unknown");
80427bfbee1SPeter Avalos             else
805*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\tUnknown message type %u", type);
80627bfbee1SPeter Avalos         }
80727bfbee1SPeter Avalos         i += len + 2;
80827bfbee1SPeter Avalos     }
809*ed775ee7SAntonio Huete Jimenez 
810*ed775ee7SAntonio Huete Jimenez     return 0; /* OK */
811*ed775ee7SAntonio Huete Jimenez 
812*ed775ee7SAntonio Huete Jimenez trunc:
813*ed775ee7SAntonio Huete Jimenez     return -1; /* packet truncated by capture process */
814*ed775ee7SAntonio Huete Jimenez 
815*ed775ee7SAntonio Huete Jimenez invalid:
816*ed775ee7SAntonio Huete Jimenez     return -2; /* packet is invalid */
817*ed775ee7SAntonio Huete Jimenez }
818*ed775ee7SAntonio Huete Jimenez 
819*ed775ee7SAntonio Huete Jimenez static void
babel_print_v2(netdissect_options * ndo,const u_char * cp,u_int length)820*ed775ee7SAntonio Huete Jimenez babel_print_v2(netdissect_options *ndo,
821*ed775ee7SAntonio Huete Jimenez                const u_char *cp, u_int length)
822*ed775ee7SAntonio Huete Jimenez {
823*ed775ee7SAntonio Huete Jimenez     u_short bodylen;
824*ed775ee7SAntonio Huete Jimenez     int ret;
825*ed775ee7SAntonio Huete Jimenez 
826*ed775ee7SAntonio Huete Jimenez     ND_TCHECK_4(cp);
827*ed775ee7SAntonio Huete Jimenez     if (length < 4)
828*ed775ee7SAntonio Huete Jimenez         goto invalid;
829*ed775ee7SAntonio Huete Jimenez     bodylen = GET_BE_U_2(cp + 2);
830*ed775ee7SAntonio Huete Jimenez     ND_PRINT(" (%u)", bodylen);
831*ed775ee7SAntonio Huete Jimenez     length -= 4;
832*ed775ee7SAntonio Huete Jimenez     cp += 4;
833*ed775ee7SAntonio Huete Jimenez 
834*ed775ee7SAntonio Huete Jimenez     /* Process the TLVs in the body */
835*ed775ee7SAntonio Huete Jimenez     if (length < bodylen)
836*ed775ee7SAntonio Huete Jimenez         goto invalid;
837*ed775ee7SAntonio Huete Jimenez     ret = babel_print_v2_tlvs(ndo, cp, bodylen, length);
838*ed775ee7SAntonio Huete Jimenez     if (ret == -1)
839*ed775ee7SAntonio Huete Jimenez         goto trunc;
840*ed775ee7SAntonio Huete Jimenez     if (ret == -2)
841*ed775ee7SAntonio Huete Jimenez         goto invalid;
842*ed775ee7SAntonio Huete Jimenez     length -= bodylen;
843*ed775ee7SAntonio Huete Jimenez     cp += bodylen;
844*ed775ee7SAntonio Huete Jimenez 
845*ed775ee7SAntonio Huete Jimenez     /* If there's a trailer, process the TLVs in the trailer */
846*ed775ee7SAntonio Huete Jimenez     if (length != 0) {
847*ed775ee7SAntonio Huete Jimenez 	if(ndo->ndo_vflag) ND_PRINT("\n\t----");
848*ed775ee7SAntonio Huete Jimenez 	else ND_PRINT(" |");
849*ed775ee7SAntonio Huete Jimenez         ret = babel_print_v2_tlvs(ndo, cp, length, length);
850*ed775ee7SAntonio Huete Jimenez         if (ret == -1)
851*ed775ee7SAntonio Huete Jimenez             goto trunc;
852*ed775ee7SAntonio Huete Jimenez         if (ret == -2)
853*ed775ee7SAntonio Huete Jimenez             goto invalid;
854*ed775ee7SAntonio Huete Jimenez     }
85527bfbee1SPeter Avalos     return;
85627bfbee1SPeter Avalos 
85727bfbee1SPeter Avalos  trunc:
858*ed775ee7SAntonio Huete Jimenez     nd_print_trunc(ndo);
85927bfbee1SPeter Avalos     return;
86027bfbee1SPeter Avalos 
861411677aeSAaron LI  invalid:
862*ed775ee7SAntonio Huete Jimenez     nd_print_invalid(ndo);
86327bfbee1SPeter Avalos }
864