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