1235427Sdelphij/*
2235427Sdelphij * Copyright (c) 2007-2011 Gr��goire Henry, Juliusz Chroboczek
3235427Sdelphij *
4235427Sdelphij * Redistribution and use in source and binary forms, with or without
5235427Sdelphij * modification, are permitted provided that the following conditions
6235427Sdelphij * are met:
7235427Sdelphij * 1. Redistributions of source code must retain the above copyright
8235427Sdelphij *    notice, this list of conditions and the following disclaimer.
9235427Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
10235427Sdelphij *    notice, this list of conditions and the following disclaimer in the
11235427Sdelphij *    documentation and/or other materials provided with the distribution.
12235427Sdelphij * 3. Neither the name of the project nor the names of its contributors
13235427Sdelphij *    may be used to endorse or promote products derived from this software
14235427Sdelphij *    without specific prior written permission.
15235427Sdelphij *
16235427Sdelphij * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17235427Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18235427Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19235427Sdelphij * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20235427Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21235427Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22235427Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23235427Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24235427Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25235427Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26235427Sdelphij * SUCH DAMAGE.
27235427Sdelphij */
28235427Sdelphij
29235427Sdelphij#ifdef HAVE_CONFIG_H
30235427Sdelphij#include "config.h"
31235427Sdelphij#endif
32235427Sdelphij
33235427Sdelphij#include <tcpdump-stdinc.h>
34235427Sdelphij
35235427Sdelphij#include <stdio.h>
36235427Sdelphij#include <string.h>
37235427Sdelphij
38235427Sdelphij#include "addrtoname.h"
39235427Sdelphij#include "interface.h"
40235427Sdelphij#include "extract.h"
41235427Sdelphij
42235427Sdelphijstatic void babel_print_v2(const u_char *cp, u_int length);
43235427Sdelphij
44235427Sdelphijvoid
45235427Sdelphijbabel_print(const u_char *cp, u_int length) {
46235427Sdelphij    printf("babel");
47235427Sdelphij
48235427Sdelphij    TCHECK2(*cp, 4);
49235427Sdelphij
50235427Sdelphij    if(cp[0] != 42) {
51235427Sdelphij        printf(" malformed header");
52235427Sdelphij        return;
53235427Sdelphij    } else {
54235427Sdelphij        printf(" %d", cp[1]);
55235427Sdelphij    }
56235427Sdelphij
57235427Sdelphij    switch(cp[1]) {
58235427Sdelphij    case 2:
59235427Sdelphij        babel_print_v2(cp,length);
60235427Sdelphij        break;
61235427Sdelphij    default:
62235427Sdelphij        printf(" unknown version");
63235427Sdelphij        break;
64235427Sdelphij    }
65235427Sdelphij
66235427Sdelphij    return;
67235427Sdelphij
68235427Sdelphij trunc:
69235427Sdelphij    printf(" [|babel]");
70235427Sdelphij    return;
71235427Sdelphij}
72235427Sdelphij
73235427Sdelphij#define MESSAGE_PAD1 0
74235427Sdelphij#define MESSAGE_PADN 1
75235427Sdelphij#define MESSAGE_ACK_REQ 2
76235427Sdelphij#define MESSAGE_ACK 3
77235427Sdelphij#define MESSAGE_HELLO 4
78235427Sdelphij#define MESSAGE_IHU 5
79235427Sdelphij#define MESSAGE_ROUTER_ID 6
80235427Sdelphij#define MESSAGE_NH 7
81235427Sdelphij#define MESSAGE_UPDATE 8
82235427Sdelphij#define MESSAGE_REQUEST 9
83235427Sdelphij#define MESSAGE_MH_REQUEST 10
84251158Sdelphij#define MESSAGE_TSPC 11
85251158Sdelphij#define MESSAGE_HMAC 12
86235427Sdelphij
87235427Sdelphijstatic const char *
88235427Sdelphijformat_id(const u_char *id)
89235427Sdelphij{
90235427Sdelphij    static char buf[25];
91235427Sdelphij    snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
92235427Sdelphij             id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
93235427Sdelphij    buf[24] = '\0';
94235427Sdelphij    return buf;
95235427Sdelphij}
96235427Sdelphij
97235427Sdelphijstatic const unsigned char v4prefix[16] =
98235427Sdelphij    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
99235427Sdelphij
100235427Sdelphijstatic const char *
101235427Sdelphijformat_prefix(const u_char *prefix, unsigned char plen)
102235427Sdelphij{
103235427Sdelphij    static char buf[50];
104235427Sdelphij    if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
105235427Sdelphij        snprintf(buf, 50, "%s/%u", ipaddr_string(prefix + 12), plen - 96);
106235427Sdelphij    else
107251158Sdelphij#ifdef INET6
108235427Sdelphij        snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen);
109251158Sdelphij#else
110251158Sdelphij        snprintf(buf, 50, "IPv6 addresses not supported");
111251158Sdelphij#endif
112235427Sdelphij    buf[49] = '\0';
113235427Sdelphij    return buf;
114235427Sdelphij}
115235427Sdelphij
116235427Sdelphijstatic const char *
117235427Sdelphijformat_address(const u_char *prefix)
118235427Sdelphij{
119235427Sdelphij    if(memcmp(prefix, v4prefix, 12) == 0)
120235427Sdelphij        return ipaddr_string(prefix + 12);
121235427Sdelphij    else
122251158Sdelphij#ifdef INET6
123235427Sdelphij        return ip6addr_string(prefix);
124251158Sdelphij#else
125251158Sdelphij        return "IPv6 addresses not supported";
126251158Sdelphij#endif
127235427Sdelphij}
128235427Sdelphij
129235427Sdelphijstatic int
130235427Sdelphijnetwork_prefix(int ae, int plen, unsigned int omitted,
131235427Sdelphij               const unsigned char *p, const unsigned char *dp,
132235427Sdelphij               unsigned int len, unsigned char *p_r)
133235427Sdelphij{
134235427Sdelphij    unsigned pb;
135235427Sdelphij    unsigned char prefix[16];
136235427Sdelphij
137235427Sdelphij    if(plen >= 0)
138235427Sdelphij        pb = (plen + 7) / 8;
139235427Sdelphij    else if(ae == 1)
140235427Sdelphij        pb = 4;
141235427Sdelphij    else
142235427Sdelphij        pb = 16;
143235427Sdelphij
144235427Sdelphij    if(pb > 16)
145235427Sdelphij        return -1;
146235427Sdelphij
147235427Sdelphij    memset(prefix, 0, 16);
148235427Sdelphij
149235427Sdelphij    switch(ae) {
150235427Sdelphij    case 0: break;
151235427Sdelphij    case 1:
152235427Sdelphij        if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
153235427Sdelphij            return -1;
154235427Sdelphij        memcpy(prefix, v4prefix, 12);
155235427Sdelphij        if(omitted) {
156235427Sdelphij            if (dp == NULL) return -1;
157235427Sdelphij            memcpy(prefix, dp, 12 + omitted);
158235427Sdelphij        }
159235427Sdelphij        if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted);
160235427Sdelphij        break;
161235427Sdelphij    case 2:
162235427Sdelphij        if(omitted > 16 || (pb > omitted && len < pb - omitted))
163235427Sdelphij            return -1;
164235427Sdelphij        if(omitted) {
165235427Sdelphij            if (dp == NULL) return -1;
166235427Sdelphij            memcpy(prefix, dp, omitted);
167235427Sdelphij        }
168235427Sdelphij        if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
169235427Sdelphij        break;
170235427Sdelphij    case 3:
171235427Sdelphij        if(pb > 8 && len < pb - 8) return -1;
172235427Sdelphij        prefix[0] = 0xfe;
173235427Sdelphij        prefix[1] = 0x80;
174235427Sdelphij        if(pb > 8) memcpy(prefix + 8, p, pb - 8);
175235427Sdelphij        break;
176235427Sdelphij    default:
177235427Sdelphij        return -1;
178235427Sdelphij    }
179235427Sdelphij
180235427Sdelphij    memcpy(p_r, prefix, 16);
181235427Sdelphij    return 1;
182235427Sdelphij}
183235427Sdelphij
184235427Sdelphijstatic int
185235427Sdelphijnetwork_address(int ae, const unsigned char *a, unsigned int len,
186235427Sdelphij                unsigned char *a_r)
187235427Sdelphij{
188235427Sdelphij    return network_prefix(ae, -1, 0, a, NULL, len, a_r);
189235427Sdelphij}
190235427Sdelphij
191235427Sdelphij#define ICHECK(i, l) \
192235427Sdelphij	if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt;
193235427Sdelphij
194235427Sdelphijstatic void
195235427Sdelphijbabel_print_v2(const u_char *cp, u_int length) {
196235427Sdelphij    u_int i;
197235427Sdelphij    u_short bodylen;
198235427Sdelphij    u_char v4_prefix[16] =
199235427Sdelphij        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
200235427Sdelphij    u_char v6_prefix[16] = {0};
201235427Sdelphij
202235427Sdelphij    TCHECK2(*cp, 4);
203235427Sdelphij    if (length < 4)
204235427Sdelphij        goto corrupt;
205235427Sdelphij    bodylen = EXTRACT_16BITS(cp + 2);
206235427Sdelphij    printf(" (%u)", bodylen);
207235427Sdelphij
208235427Sdelphij    /* Process the TLVs in the body */
209235427Sdelphij    i = 0;
210235427Sdelphij    while(i < bodylen) {
211235427Sdelphij        const u_char *message;
212251158Sdelphij        u_int type, len;
213235427Sdelphij
214235427Sdelphij        message = cp + 4 + i;
215235427Sdelphij        TCHECK2(*message, 2);
216235427Sdelphij        ICHECK(i, 2);
217235427Sdelphij        type = message[0];
218235427Sdelphij        len = message[1];
219235427Sdelphij
220235427Sdelphij        TCHECK2(*message, 2 + len);
221235427Sdelphij        ICHECK(i, 2 + len);
222235427Sdelphij
223235427Sdelphij        switch(type) {
224235427Sdelphij        case MESSAGE_PAD1: {
225235427Sdelphij            if(!vflag)
226235427Sdelphij                printf(" pad1");
227235427Sdelphij            else
228235427Sdelphij                printf("\n\tPad 1");
229235427Sdelphij        }
230235427Sdelphij            break;
231235427Sdelphij
232235427Sdelphij        case MESSAGE_PADN: {
233235427Sdelphij            if(!vflag)
234235427Sdelphij                printf(" padN");
235235427Sdelphij            else
236235427Sdelphij                printf("\n\tPad %d", len + 2);
237235427Sdelphij        }
238235427Sdelphij            break;
239235427Sdelphij
240235427Sdelphij        case MESSAGE_ACK_REQ: {
241235427Sdelphij            u_short nonce, interval;
242235427Sdelphij            if(!vflag)
243235427Sdelphij                printf(" ack-req");
244235427Sdelphij            else {
245235427Sdelphij                printf("\n\tAcknowledgment Request ");
246235427Sdelphij                if(len < 6) goto corrupt;
247235427Sdelphij                nonce = EXTRACT_16BITS(message + 4);
248235427Sdelphij                interval = EXTRACT_16BITS(message + 6);
249235427Sdelphij                printf("%04x %d", nonce, interval);
250235427Sdelphij            }
251235427Sdelphij        }
252235427Sdelphij            break;
253235427Sdelphij
254235427Sdelphij        case MESSAGE_ACK: {
255235427Sdelphij            u_short nonce;
256235427Sdelphij            if(!vflag)
257235427Sdelphij                printf(" ack");
258235427Sdelphij            else {
259235427Sdelphij                printf("\n\tAcknowledgment ");
260235427Sdelphij                if(len < 2) goto corrupt;
261235427Sdelphij                nonce = EXTRACT_16BITS(message + 2);
262235427Sdelphij                printf("%04x", nonce);
263235427Sdelphij            }
264235427Sdelphij        }
265235427Sdelphij            break;
266235427Sdelphij
267235427Sdelphij        case MESSAGE_HELLO:  {
268235427Sdelphij            u_short seqno, interval;
269235427Sdelphij            if(!vflag)
270235427Sdelphij                printf(" hello");
271235427Sdelphij            else {
272235427Sdelphij                printf("\n\tHello ");
273235427Sdelphij                if(len < 6) goto corrupt;
274235427Sdelphij                seqno = EXTRACT_16BITS(message + 4);
275235427Sdelphij                interval = EXTRACT_16BITS(message + 6);
276235427Sdelphij                printf("seqno %u interval %u", seqno, interval);
277235427Sdelphij            }
278235427Sdelphij        }
279235427Sdelphij            break;
280235427Sdelphij
281235427Sdelphij        case MESSAGE_IHU: {
282235427Sdelphij            unsigned short txcost, interval;
283235427Sdelphij            if(!vflag)
284235427Sdelphij                printf(" ihu");
285235427Sdelphij            else {
286235427Sdelphij                u_char address[16];
287235427Sdelphij                int rc;
288235427Sdelphij                printf("\n\tIHU ");
289235427Sdelphij                if(len < 6) goto corrupt;
290235427Sdelphij                txcost = EXTRACT_16BITS(message + 4);
291235427Sdelphij                interval = EXTRACT_16BITS(message + 6);
292235427Sdelphij                rc = network_address(message[2], message + 8, len - 6, address);
293235427Sdelphij                if(rc < 0) { printf("[|babel]"); break; }
294235427Sdelphij                printf("%s txcost %u interval %d",
295235427Sdelphij                       format_address(address), txcost, interval);
296235427Sdelphij            }
297235427Sdelphij        }
298235427Sdelphij            break;
299235427Sdelphij
300235427Sdelphij        case MESSAGE_ROUTER_ID: {
301235427Sdelphij            if(!vflag)
302235427Sdelphij                printf(" router-id");
303235427Sdelphij            else {
304235427Sdelphij                printf("\n\tRouter Id");
305235427Sdelphij                if(len < 10) goto corrupt;
306235427Sdelphij                printf(" %s", format_id(message + 4));
307235427Sdelphij            }
308235427Sdelphij        }
309235427Sdelphij            break;
310235427Sdelphij
311235427Sdelphij        case MESSAGE_NH: {
312235427Sdelphij            if(!vflag)
313235427Sdelphij                printf(" nh");
314235427Sdelphij            else {
315235427Sdelphij                int rc;
316235427Sdelphij                u_char nh[16];
317235427Sdelphij                printf("\n\tNext Hop");
318235427Sdelphij                if(len < 2) goto corrupt;
319235427Sdelphij                rc = network_address(message[2], message + 4, len - 2, nh);
320235427Sdelphij                if(rc < 0) goto corrupt;
321235427Sdelphij                printf(" %s", format_address(nh));
322235427Sdelphij            }
323235427Sdelphij        }
324235427Sdelphij            break;
325235427Sdelphij
326235427Sdelphij        case MESSAGE_UPDATE: {
327235427Sdelphij            if(!vflag) {
328235427Sdelphij                printf(" update");
329235427Sdelphij                if(len < 1)
330235427Sdelphij                    printf("/truncated");
331235427Sdelphij                else
332235427Sdelphij                    printf("%s%s%s",
333235427Sdelphij                           (message[3] & 0x80) ? "/prefix": "",
334235427Sdelphij                           (message[3] & 0x40) ? "/id" : "",
335235427Sdelphij                           (message[3] & 0x3f) ? "/unknown" : "");
336235427Sdelphij            } else {
337235427Sdelphij                u_short interval, seqno, metric;
338235427Sdelphij                u_char plen;
339235427Sdelphij                int rc;
340235427Sdelphij                u_char prefix[16];
341235427Sdelphij                printf("\n\tUpdate");
342235427Sdelphij                if(len < 10) goto corrupt;
343235427Sdelphij                plen = message[4] + (message[2] == 1 ? 96 : 0);
344235427Sdelphij                rc = network_prefix(message[2], message[4], message[5],
345235427Sdelphij                                    message + 12,
346235427Sdelphij                                    message[2] == 1 ? v4_prefix : v6_prefix,
347235427Sdelphij                                    len - 10, prefix);
348235427Sdelphij                if(rc < 0) goto corrupt;
349235427Sdelphij                interval = EXTRACT_16BITS(message + 6);
350235427Sdelphij                seqno = EXTRACT_16BITS(message + 8);
351235427Sdelphij                metric = EXTRACT_16BITS(message + 10);
352235427Sdelphij                printf("%s%s%s %s metric %u seqno %u interval %u",
353235427Sdelphij                       (message[3] & 0x80) ? "/prefix": "",
354235427Sdelphij                       (message[3] & 0x40) ? "/id" : "",
355235427Sdelphij                       (message[3] & 0x3f) ? "/unknown" : "",
356235427Sdelphij                       format_prefix(prefix, plen),
357235427Sdelphij                       metric, seqno, interval);
358235427Sdelphij                if(message[3] & 0x80) {
359235427Sdelphij                    if(message[2] == 1)
360235427Sdelphij                        memcpy(v4_prefix, prefix, 16);
361235427Sdelphij                    else
362235427Sdelphij                        memcpy(v6_prefix, prefix, 16);
363235427Sdelphij                }
364235427Sdelphij            }
365235427Sdelphij        }
366235427Sdelphij            break;
367235427Sdelphij
368235427Sdelphij        case MESSAGE_REQUEST: {
369235427Sdelphij            if(!vflag)
370235427Sdelphij                printf(" request");
371235427Sdelphij            else {
372235427Sdelphij                int rc;
373235427Sdelphij                u_char prefix[16], plen;
374235427Sdelphij                printf("\n\tRequest ");
375235427Sdelphij                if(len < 2) goto corrupt;
376235427Sdelphij                plen = message[3] + (message[2] == 1 ? 96 : 0);
377235427Sdelphij                rc = network_prefix(message[2], message[3], 0,
378235427Sdelphij                                    message + 4, NULL, len - 2, prefix);
379235427Sdelphij                if(rc < 0) goto corrupt;
380235427Sdelphij                plen = message[3] + (message[2] == 1 ? 96 : 0);
381235427Sdelphij                printf("for %s",
382235427Sdelphij                       message[2] == 0 ? "any" : format_prefix(prefix, plen));
383235427Sdelphij            }
384235427Sdelphij        }
385235427Sdelphij            break;
386235427Sdelphij
387235427Sdelphij        case MESSAGE_MH_REQUEST : {
388235427Sdelphij            if(!vflag)
389235427Sdelphij                printf(" mh-request");
390235427Sdelphij            else {
391235427Sdelphij                int rc;
392235427Sdelphij                u_short seqno;
393235427Sdelphij                u_char prefix[16], plen;
394235427Sdelphij                printf("\n\tMH-Request ");
395235427Sdelphij                if(len < 14) goto corrupt;
396235427Sdelphij                seqno = EXTRACT_16BITS(message + 4);
397235427Sdelphij                rc = network_prefix(message[2], message[3], 0,
398235427Sdelphij                                    message + 16, NULL, len - 14, prefix);
399235427Sdelphij                if(rc < 0) goto corrupt;
400235427Sdelphij                plen = message[3] + (message[2] == 1 ? 96 : 0);
401235427Sdelphij                printf("(%u hops) for %s seqno %u id %s",
402235427Sdelphij                       message[6], format_prefix(prefix, plen),
403235427Sdelphij                       seqno, format_id(message + 8));
404235427Sdelphij            }
405235427Sdelphij        }
406235427Sdelphij            break;
407251158Sdelphij        case MESSAGE_TSPC :
408251158Sdelphij            if(!vflag)
409251158Sdelphij                printf(" tspc");
410251158Sdelphij            else {
411251158Sdelphij                printf("\n\tTS/PC ");
412251158Sdelphij                if(len < 6) goto corrupt;
413251158Sdelphij                printf("timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4),
414251158Sdelphij                       EXTRACT_16BITS(message + 2));
415251158Sdelphij            }
416251158Sdelphij            break;
417251158Sdelphij        case MESSAGE_HMAC : {
418251158Sdelphij            if(!vflag)
419251158Sdelphij                printf(" hmac");
420251158Sdelphij            else {
421251158Sdelphij                unsigned j;
422251158Sdelphij                printf("\n\tHMAC ");
423251158Sdelphij                if(len < 18) goto corrupt;
424251158Sdelphij                printf("key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2);
425251158Sdelphij                for (j = 0; j < len - 2; j++)
426251158Sdelphij                    printf ("%02X", message[4 + j]);
427251158Sdelphij            }
428251158Sdelphij        }
429251158Sdelphij            break;
430235427Sdelphij        default:
431235427Sdelphij            if(!vflag)
432235427Sdelphij                printf(" unknown");
433235427Sdelphij            else
434235427Sdelphij                printf("\n\tUnknown message type %d", type);
435235427Sdelphij        }
436235427Sdelphij        i += len + 2;
437235427Sdelphij    }
438235427Sdelphij    return;
439235427Sdelphij
440235427Sdelphij trunc:
441235427Sdelphij    printf(" [|babel]");
442235427Sdelphij    return;
443235427Sdelphij
444235427Sdelphij corrupt:
445235427Sdelphij    printf(" (corrupt)");
446235427Sdelphij    return;
447235427Sdelphij}
448