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