Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-babel.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-babel.c
2
 * Routines for Babel dissection (RFC 6126)
3
 * Copyright 2011 by Juliusz Chroboczek <jch@pps.jussieu.fr>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
#include <epan/to_str.h>
16
void proto_register_babel(void);
17
void proto_reg_handoff_babel(void);
18
19
static dissector_handle_t babel_handle;
20
21
static int proto_babel;
22
23
static int ett_babel;
24
static int hf_babel_magic;
25
static int hf_babel_version;
26
static int hf_babel_bodylen;
27
28
static int hf_babel_message;
29
static int ett_message;
30
static int hf_babel_message_type;
31
static int hf_babel_message_length;
32
static int hf_babel_message_nonce;
33
static int hf_babel_message_interval;
34
static int hf_babel_message_seqno;
35
static int hf_babel_message_ae;
36
static int hf_babel_message_prefix;
37
static int hf_babel_message_rxcost;
38
static int hf_babel_message_routerid;
39
static int hf_babel_message_flags;
40
static int hf_babel_message_plen;
41
static int hf_babel_message_omitted;
42
static int hf_babel_message_metric;
43
static int hf_babel_message_hopcount;
44
static int hf_babel_message_index;
45
static int hf_babel_subtlv;
46
static int hf_babel_subtlv_type;
47
static int hf_babel_subtlv_len;
48
static int hf_babel_subtlv_diversity;
49
50
static int ett_subtree;
51
static int ett_packet_trailer;
52
static int ett_unicast;
53
static int ett_subtlv;
54
static int ett_timestamp;
55
static int ett_mandatory;
56
57
14
#define UDP_PORT_RANGE_BABEL "6696"
58
59
2.64k
#define MESSAGE_PAD1        0
60
503
#define MESSAGE_PADN        1
61
345
#define MESSAGE_ACK_REQ     2
62
231
#define MESSAGE_ACK         3
63
204
#define MESSAGE_HELLO       4
64
185
#define MESSAGE_IHU         5
65
146
#define MESSAGE_ROUTER_ID   6
66
140
#define MESSAGE_NH          7
67
129
#define MESSAGE_UPDATE      8
68
125
#define MESSAGE_REQUEST     9
69
122
#define MESSAGE_MH_REQUEST 10
70
#define MESSAGE_TS_PC      11
71
#define MESSAGE_HMAC_OLD   12
72
#define MESSAGE_SRC_UPDATE 13
73
#define MESSAGE_SRC_REQUEST 14
74
#define MESSAGE_SRC_SEQNO   15
75
#define MESSAGE_HMAC    16
76
119
#define MESSAGE_PC      17
77
#define MESSAGE_CHALLENGE_REQUEST 18
78
#define MESSAGE_CHALLENGE_REPLY 19
79
80
/** sub-TLVs */
81
915
#define MESSAGE_SUB_PAD1 0
82
87
#define MESSAGE_SUB_PADN 1
83
27
#define MESSAGE_SUB_DIVERSITY 2
84
6
#define MESSAGE_SUB_TIMESTAMP 3
85
86
/** mask for bits */
87
#define UNICAST_FLAG 0x80
88
194
#define MANDATORY_FLAG 128
89
90
/** message string values listed in rfc7557 */
91
static const value_string messages[] = {
92
    { MESSAGE_PAD1,         "pad1"},
93
    { MESSAGE_PADN,         "padn"},
94
    { MESSAGE_ACK_REQ,      "ack-req"},
95
    { MESSAGE_ACK,          "ack"},
96
    { MESSAGE_HELLO,        "hello"},
97
    { MESSAGE_IHU,          "ihu"},
98
    { MESSAGE_ROUTER_ID,    "router-id"},
99
    { MESSAGE_NH,           "nh"},
100
    { MESSAGE_UPDATE,       "update"},
101
    { MESSAGE_REQUEST,      "request"},
102
    { MESSAGE_MH_REQUEST,   "mh-request"},
103
    { MESSAGE_TS_PC,        "ts/pc (obsolete)"},
104
    { MESSAGE_HMAC_OLD,     "hmac" },
105
    { MESSAGE_SRC_UPDATE,   "source-specific-update"},
106
    { MESSAGE_SRC_REQUEST,  "source-specific-req"},
107
    { MESSAGE_SRC_SEQNO,    "source-specific-seqno"},
108
    { MESSAGE_HMAC,         "hmac"},
109
    { MESSAGE_PC,           "pc"},
110
    { MESSAGE_CHALLENGE_REQUEST,  "challenge-request"},
111
    { MESSAGE_CHALLENGE_REPLY,    "challenge-reply"},
112
    { 0, NULL}
113
};
114
115
static const value_string subtlvs[] = {
116
    { MESSAGE_SUB_PAD1,       "sub-pad1"},
117
    { MESSAGE_SUB_PADN,       "sub-padn"},
118
    { MESSAGE_SUB_DIVERSITY,  "diversity"},
119
    { MESSAGE_SUB_TIMESTAMP,  "timestamp"},
120
    { 0, NULL}
121
};
122
123
static const value_string aes[] = {
124
    { 0, "Wildcard" },
125
    { 1, "IPv4" },
126
    { 2, "IPv6" },
127
    { 3, "Link-Local IPv6"},
128
    { 0, NULL }
129
};
130
131
/* The prefix for v6-mapped IPv4 addresses.  Format_address below
132
   returns IPv4 addresses in that format. */
133
134
static const unsigned char v4prefix[16] =
135
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
136
137
/* The following two functions return ephemeral or constant strings, no
138
   need to call free. */
139
140
static const char *
141
format_address(wmem_allocator_t *scope, const unsigned char *prefix)
142
54
{
143
54
    address addr;
144
145
54
    if (prefix == NULL)
146
44
        return "corrupt";
147
10
    else if (memcmp(prefix, v4prefix, 12) == 0)
148
3
    {
149
3
        addr.type = AT_IPv4;
150
3
        addr.len  = 4;
151
3
        addr.data = prefix + 12;
152
153
3
        return address_to_str(scope, &addr);
154
3
    }
155
7
    else
156
7
    {
157
7
        addr.type = AT_IPv6;
158
7
        addr.len  = 16;
159
7
        addr.data = prefix;
160
161
7
        return address_to_str(scope, &addr);
162
7
    }
163
54
}
164
165
static const char *
166
format_prefix(wmem_allocator_t *scope, const unsigned char *prefix, unsigned char plen)
167
10
{
168
10
    return wmem_strdup_printf(scope, "%s/%u", format_address(scope, prefix), plen);
169
10
}
170
171
static int
172
network_prefix(int ae, int plen, unsigned int omitted,
173
               tvbuff_t *tvb, int offset, const unsigned char *dp,
174
               unsigned int len, unsigned char *p_r)
175
54
{
176
54
    unsigned   pb;
177
54
    unsigned char prefix[16];
178
54
    int consumed = 0;
179
180
54
    if (plen >= 0)
181
10
        pb = (plen + 7) / 8;
182
44
    else if (ae == 1)
183
3
        pb = 4;
184
41
    else
185
41
        pb = 16;
186
187
54
    if (pb > 16)
188
3
        return -1;
189
190
51
    memset(prefix, 0, 16);
191
192
51
    switch(ae) {
193
5
    case 0: break;
194
3
    case 1:
195
3
        if (omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
196
0
            return -1;
197
3
        memcpy(prefix, v4prefix, 12);
198
3
        if (omitted) {
199
0
            if (dp == NULL) return -1;
200
0
            memcpy(prefix, dp, 12 + omitted);
201
0
        }
202
3
        if (pb > omitted) {
203
3
            tvb_memcpy(tvb, prefix + 12 + omitted, offset, pb - omitted);
204
3
            consumed = pb - omitted;
205
3
        }
206
3
        break;
207
2
    case 2:
208
2
        if (omitted > 16 || (pb > omitted && len < pb - omitted))
209
0
            return -1;
210
2
        if (omitted) {
211
0
            if (dp == NULL) return -1;
212
0
            memcpy(prefix, dp, omitted);
213
0
        }
214
2
        if (pb > omitted) {
215
2
            tvb_memcpy(tvb, prefix + omitted, offset, pb - omitted);
216
2
            consumed = pb - omitted;
217
2
        }
218
2
        break;
219
10
    case 3:
220
10
        if (pb > 8 && len < pb - 8) return -1;
221
0
        prefix[0] = 0xfe;
222
0
        prefix[1] = 0x80;
223
0
        if (pb > 8) {
224
0
            tvb_memcpy(tvb, prefix + 8, offset, pb - 8);
225
0
            consumed = pb - 8;
226
0
        }
227
0
        break;
228
31
    default:
229
31
        return -1;
230
51
    }
231
232
10
    memcpy(p_r, prefix, 16);
233
10
    return consumed;
234
51
}
235
236
static int
237
network_address(int ae, tvbuff_t *tvb, int offset, unsigned int len,
238
                unsigned char *a_r)
239
44
{
240
44
    return network_prefix(ae, -1, 0, tvb, offset, NULL, len, a_r);
241
44
}
242
243
static const char *
244
format_timestamp(const uint32_t i)
245
12
{
246
12
    static char buf[sizeof("0000.000000s")];
247
12
    snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000);
248
12
    return buf;
249
12
}
250
251
static int
252
dissect_babel_subtlvs(tvbuff_t * tvb, uint8_t type, uint16_t beg,
253
                      uint16_t end, proto_tree *message_tree)
254
23
{
255
23
    proto_tree *channel_tree = NULL;
256
23
    proto_item *sub_item;
257
23
    uint8_t     subtype, sublen;
258
23
    int i = 0;
259
260
327
    while(beg < end) {
261
305
        proto_tree *subtlv_tree;
262
305
        subtype = tvb_get_uint8(tvb, beg);
263
305
        if (subtype != MESSAGE_SUB_PAD1) {
264
194
            sublen = tvb_get_uint8(tvb, beg+1);
265
194
        } else {
266
111
            sublen = 0;
267
111
        }
268
269
305
        sub_item =
270
305
          proto_tree_add_uint_format(message_tree, hf_babel_subtlv,
271
305
                                     tvb, beg, sublen + ((subtype == MESSAGE_SUB_PAD1) ? 1 : 2),
272
305
                                     subtype, "Sub TLV %s (%u)",
273
305
                                     val_to_str_const(subtype, subtlvs, "unknown"),
274
305
                                     subtype);
275
305
        subtlv_tree = proto_item_add_subtree(sub_item, ett_subtlv);
276
277
305
        proto_tree_add_item(subtlv_tree, hf_babel_subtlv_type,
278
305
                            tvb, beg, 1, ENC_BIG_ENDIAN);
279
305
        if(subtype == MESSAGE_SUB_PAD1){
280
111
            beg += 1;
281
111
            continue;
282
111
        }
283
194
        proto_tree_add_item(subtlv_tree, hf_babel_subtlv_len,
284
194
                            tvb, beg+1, 1, ENC_BIG_ENDIAN);
285
286
194
        if ((MANDATORY_FLAG & subtype) != 0) {
287
31
            proto_tree_add_subtree_format(subtlv_tree, tvb, beg+2, sublen,
288
31
                                          ett_mandatory, NULL, "Mandatory");
289
31
        }
290
291
194
        switch(subtype) {
292
87
            case MESSAGE_SUB_PADN:
293
87
                break;
294
27
            case MESSAGE_SUB_DIVERSITY: {
295
27
                i = 0;
296
27
                channel_tree = proto_tree_add_subtree_format(subtlv_tree, tvb,
297
27
                                                             beg+2, 0, ett_subtlv,
298
27
                                                             NULL, "Channel");
299
333
                while(i < sublen) {
300
306
                    proto_tree_add_item(channel_tree, hf_babel_subtlv_diversity,
301
306
                                        tvb, beg+2+i, 1, ENC_BIG_ENDIAN);
302
306
                    i++;
303
306
                }
304
27
            }
305
27
                break;
306
6
            case MESSAGE_SUB_TIMESTAMP:  {
307
6
                if (type == MESSAGE_HELLO) {
308
0
                    uint32_t t1 = tvb_get_uint32(tvb, beg+2, ENC_BIG_ENDIAN);
309
0
                    proto_tree_add_subtree_format(subtlv_tree, tvb, beg+2,
310
0
                                                  sublen, ett_timestamp, NULL,
311
0
                                                  "Timestamp : %s",
312
0
                                                  format_timestamp(t1));
313
6
                } else if (type == MESSAGE_IHU) {
314
6
                    uint32_t t1 = tvb_get_uint32(tvb, beg+2, ENC_BIG_ENDIAN);
315
6
                    uint32_t t2 = tvb_get_uint32(tvb, beg+6, ENC_BIG_ENDIAN);
316
6
                    proto_tree_add_subtree_format(subtlv_tree, tvb, beg+2,
317
6
                                                  sublen, ett_timestamp, NULL,
318
6
                                                  "Timestamp origin : %s",
319
6
                                                  format_timestamp(t1));
320
6
                    proto_tree_add_subtree_format(subtlv_tree, tvb, beg+6,
321
6
                                                  sublen, ett_timestamp, NULL,
322
6
                                                  "Timestamp receive: %s",
323
6
                                                  format_timestamp(t2));
324
6
                } else {
325
0
                    proto_tree_add_subtree_format(subtlv_tree, tvb, beg+2, sublen,
326
0
                                                  ett_timestamp, NULL, "Bogus");
327
0
                }
328
6
            }
329
6
              break;
330
194
        }
331
193
        beg += (sublen+2);
332
193
    }
333
22
    return end-beg;
334
23
}
335
336
337
/* The following function is used to read the packet body and
338
 the packet trailer */
339
static int
340
// NOLINTNEXTLINE(misc-no-recursion)
341
dissect_babel_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
342
                   int offset, uint16_t bodylen)
343
44
{
344
44
    proto_item *ti = NULL;
345
44
    unsigned char  v4_prefix[16] = {0}, v6_prefix[16] = {0};
346
44
    int            i;
347
348
349
44
    i = offset;
350
1.36k
    while (i-offset < bodylen) {
351
1.32k
        uint8_t     type, len    = 0;
352
1.32k
        uint16_t    total_length;
353
1.32k
        proto_tree *message_tree = NULL;
354
1.32k
        int         message      = 4 + i;
355
356
1.32k
        type = tvb_get_uint8(tvb, message);
357
1.32k
        if (type == MESSAGE_PAD1)
358
803
            total_length = 1;
359
520
        else {
360
520
            len = tvb_get_uint8(tvb, message + 1);
361
520
            total_length = len + 2;
362
520
        }
363
364
1.32k
        col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
365
1.32k
                        val_to_str_const(type, messages, "unknown"));
366
367
1.32k
        ti = proto_tree_add_uint_format(tree, hf_babel_message,
368
1.32k
                                        tvb, message, total_length, type,
369
1.32k
                                        "Message %s (%u)",
370
1.32k
                                        val_to_str_const(type, messages, "unknown"),
371
1.32k
                                        type);
372
373
1.32k
        if (tree) {
374
1.30k
            message_tree = proto_item_add_subtree(ti, ett_message);
375
1.30k
            proto_tree_add_item(message_tree, hf_babel_message_type,
376
1.30k
                                tvb, message, 1, ENC_BIG_ENDIAN);
377
1.30k
        }
378
379
1.32k
        if (type == MESSAGE_PAD1) {
380
803
            i++;
381
803
            continue;
382
803
        }
383
384
520
        if (tree) {
385
503
            proto_tree_add_item(message_tree, hf_babel_message_length,
386
503
                                tvb, message + 1, 1, ENC_BIG_ENDIAN);
387
503
            if (type == MESSAGE_PADN) {
388
345
            } else if (type == MESSAGE_ACK_REQ) {
389
114
                proto_tree_add_item(message_tree, hf_babel_message_nonce,
390
114
                                    tvb, message + 4, 2, ENC_BIG_ENDIAN);
391
114
                proto_tree_add_item(message_tree, hf_babel_message_interval,
392
114
                                    tvb, message + 6, 2, ENC_BIG_ENDIAN);
393
231
            } else if (type == MESSAGE_ACK) {
394
33
                proto_tree_add_item(message_tree, hf_babel_message_nonce,
395
33
                                    tvb, message + 2, 2, ENC_BIG_ENDIAN);
396
198
            } else if (type == MESSAGE_HELLO) {
397
19
                uint8_t unicast = tvb_get_uint8(tvb, 2);
398
19
                proto_tree_add_subtree_format(message_tree,
399
19
                                         tvb, message + 2, 2,
400
19
                                         ett_unicast, NULL,
401
19
                                         "Unicast : %u",
402
19
                                         unicast);
403
19
                proto_tree_add_item(message_tree, hf_babel_message_seqno,
404
19
                                    tvb, message + 4, 2, ENC_BIG_ENDIAN);
405
19
                proto_tree_add_item(message_tree, hf_babel_message_interval,
406
19
                                    tvb, message + 6, 2, ENC_BIG_ENDIAN);
407
19
                if(len > 6)
408
2
                    dissect_babel_subtlvs(tvb, type, message + 8,
409
2
                                          message + 2 + len, message_tree);
410
179
            } else if (type == MESSAGE_IHU) {
411
33
                proto_tree    *subtree;
412
33
                unsigned char  addr_str[16];
413
33
                int rc =
414
33
                    network_address(tvb_get_uint8(tvb, message + 2),
415
33
                                    tvb, message + 8, len - 6, addr_str);
416
33
                proto_tree_add_item(message_tree, hf_babel_message_rxcost,
417
33
                                    tvb, message + 4, 2, ENC_BIG_ENDIAN);
418
33
                proto_tree_add_item(message_tree, hf_babel_message_interval,
419
33
                                    tvb, message + 6, 2, ENC_BIG_ENDIAN);
420
33
                subtree = proto_tree_add_subtree_format(message_tree,
421
33
                                         tvb, message + 4, len - 2,
422
33
                                         ett_subtree, NULL, "Address: %s",
423
33
                                         format_address(pinfo->pool,
424
33
                                                        rc < 0 ? NULL : addr_str));
425
33
                proto_tree_add_item(subtree, hf_babel_message_ae,
426
33
                                    tvb, message + 2, 1, ENC_BIG_ENDIAN);
427
33
                proto_tree_add_item(subtree, hf_babel_message_prefix,
428
33
                                    tvb, message + 4, len - 2, ENC_NA);
429
33
                if (rc < len - 6)
430
21
                    dissect_babel_subtlvs(tvb, type, message + 8 + rc,
431
21
                                          message + 2 + len, message_tree);
432
146
            } else if (type == MESSAGE_ROUTER_ID) {
433
6
                proto_tree_add_item(message_tree, hf_babel_message_routerid,
434
6
                                    tvb, message + 4, 8, ENC_NA);
435
140
            } else if (type == MESSAGE_NH) {
436
11
                proto_tree    *subtree;
437
11
                unsigned char  nh[16];
438
11
                int rc =
439
11
                    network_address(tvb_get_uint8(tvb, message + 2),
440
11
                                    tvb, message + 4, len - 2, nh);
441
11
                subtree = proto_tree_add_subtree_format(message_tree,
442
11
                                         tvb, message + 4, len - 2,
443
11
                                         ett_subtree, NULL,
444
11
                                         "NH: %s",
445
11
                                         format_address(pinfo->pool,
446
11
                                                        rc < 0 ? NULL : nh));
447
11
                proto_tree_add_item(subtree, hf_babel_message_ae,
448
11
                                    tvb, message + 2, 1, ENC_BIG_ENDIAN);
449
11
                proto_tree_add_item(subtree, hf_babel_message_prefix,
450
11
                                    tvb, message + 4, len - 2, ENC_NA);
451
129
            } else if (type == MESSAGE_UPDATE) {
452
4
                proto_tree    *subtree;
453
4
                unsigned char  p[16];
454
4
                uint8_t        ae    = tvb_get_uint8(tvb, message + 2);
455
4
                uint8_t        flags = tvb_get_uint8(tvb, message + 3);
456
4
                uint8_t        plen  = tvb_get_uint8(tvb, message + 4);
457
4
                int rc =
458
4
                    network_prefix(ae, plen,
459
4
                                   tvb_get_uint8(tvb, message + 5),
460
4
                                   tvb, message + 12,
461
4
                                   ae == 1 ? v4_prefix : v6_prefix,
462
4
                                   len - 10, p);
463
4
                if (rc >= 0 && (flags & 0x80)) {
464
0
                    if (ae == 1)
465
0
                        memcpy(v4_prefix, p, 16);
466
0
                    else
467
0
                        memcpy(v6_prefix, p, 16);
468
0
                }
469
470
4
                proto_tree_add_item(message_tree, hf_babel_message_flags,
471
4
                                    tvb, message + 3, 1, ENC_BIG_ENDIAN);
472
4
                proto_tree_add_item(message_tree, hf_babel_message_interval,
473
4
                                    tvb, message + 6, 2, ENC_BIG_ENDIAN);
474
4
                proto_tree_add_item(message_tree, hf_babel_message_seqno,
475
4
                                    tvb, message + 8, 2, ENC_BIG_ENDIAN);
476
4
                proto_tree_add_item(message_tree, hf_babel_message_metric,
477
4
                                    tvb, message + 10, 2, ENC_BIG_ENDIAN);
478
4
                subtree = proto_tree_add_subtree_format(message_tree,
479
4
                                         tvb, message + 12, len - 10,
480
4
                                         ett_subtree, NULL,
481
4
                                         "Prefix: %s",
482
4
                                         format_prefix(pinfo->pool,
483
4
                                                       rc < 0 ? NULL : p,
484
4
                                                       plen));
485
4
                proto_tree_add_item(subtree, hf_babel_message_ae,
486
4
                                    tvb, message + 2, 1, ENC_BIG_ENDIAN);
487
4
                proto_tree_add_item(subtree, hf_babel_message_plen,
488
4
                                    tvb, message + 4, 1, ENC_BIG_ENDIAN);
489
4
                proto_tree_add_item(subtree, hf_babel_message_omitted,
490
4
                                    tvb, message + 5, 1, ENC_BIG_ENDIAN);
491
4
                proto_tree_add_item(subtree, hf_babel_message_prefix,
492
4
                                    tvb, message + 12, len - 10, ENC_NA);
493
4
                if (((uint8_t)rc) < len - 10)
494
0
                    dissect_babel_subtlvs(tvb, type, message + 12 + rc,
495
0
                                          message + 2 + len, message_tree);
496
125
            } else if (type == MESSAGE_REQUEST) {
497
3
                proto_tree    *subtree;
498
3
                unsigned char  p[16];
499
3
                uint8_t        plen = tvb_get_uint8(tvb, message + 3);
500
3
                int rc =
501
3
                    network_prefix(tvb_get_uint8(tvb, message + 2), plen,
502
3
                                   0, tvb, message + 4, NULL,
503
3
                                   len - 2, p);
504
3
                subtree = proto_tree_add_subtree_format(message_tree,
505
3
                                         tvb, message + 4, len - 2,
506
3
                                         ett_subtree, NULL,
507
3
                                         "Prefix: %s",
508
3
                                         format_prefix(pinfo->pool,
509
3
                                                       rc < 0 ? NULL : p,
510
3
                                                       plen));
511
3
                proto_tree_add_item(subtree, hf_babel_message_ae,
512
3
                                    tvb, message + 2, 1, ENC_BIG_ENDIAN);
513
3
                proto_tree_add_item(subtree, hf_babel_message_plen,
514
3
                                    tvb, message + 3, 1, ENC_BIG_ENDIAN);
515
3
                proto_tree_add_item(subtree, hf_babel_message_prefix,
516
3
                                    tvb, message + 4, len - 2, ENC_NA);
517
122
            } else if (type == MESSAGE_MH_REQUEST) {
518
3
                proto_tree    *subtree;
519
3
                unsigned char  p[16];
520
3
                uint8_t        plen = tvb_get_uint8(tvb, message + 3);
521
3
                int rc =
522
3
                    network_prefix(tvb_get_uint8(tvb, message + 2), plen,
523
3
                                   0, tvb, message + 16, NULL,
524
3
                                   len - 14, p);
525
3
                proto_tree_add_item(message_tree, hf_babel_message_seqno,
526
3
                                    tvb, message + 4, 2, ENC_BIG_ENDIAN);
527
3
                proto_tree_add_item(message_tree, hf_babel_message_hopcount,
528
3
                                    tvb, message + 6, 1, ENC_BIG_ENDIAN);
529
3
                proto_tree_add_item(message_tree, hf_babel_message_routerid,
530
3
                                    tvb, message + 8, 8, ENC_NA);
531
3
                subtree = proto_tree_add_subtree_format(message_tree,
532
3
                                         tvb, message + 16, len - 14,
533
3
                                         ett_subtree, NULL,
534
3
                                         "Prefix: %s",
535
3
                                         format_prefix(pinfo->pool,
536
3
                                                       rc < 0 ? NULL : p,
537
3
                                                       plen));
538
3
                proto_tree_add_item(subtree, hf_babel_message_ae,
539
3
                                    tvb, message + 2, 1, ENC_BIG_ENDIAN);
540
3
                proto_tree_add_item(subtree, hf_babel_message_plen,
541
3
                                    tvb, message + 3, 1, ENC_BIG_ENDIAN);
542
3
                proto_tree_add_item(subtree, hf_babel_message_prefix,
543
3
                                    tvb, message + 16, len - 14, ENC_NA);
544
119
            } else if (type == MESSAGE_PC){
545
0
                proto_tree_add_item(message_tree, hf_babel_message_index,
546
0
                                    tvb, message + 2, 4, ENC_NA);
547
0
            }
548
503
        }
549
520
        i += len + 2;
550
520
    }
551
44
    uint8_t packet_len = tvb_reported_length(tvb) - bodylen - 4;
552
44
    if ((offset == 0) && (packet_len != 0)) {
553
10
        proto_tree * subtree;
554
10
        subtree = proto_tree_add_subtree_format(tree, tvb, 4+bodylen, packet_len,
555
10
                                                ett_packet_trailer, NULL,
556
10
                                                "Packet Trailer (%u)", packet_len);
557
10
        increment_dissection_depth(pinfo);
558
10
        dissect_babel_body(tvb, pinfo, subtree, bodylen, packet_len);
559
10
        decrement_dissection_depth(pinfo);
560
10
    }
561
44
    return i;
562
44
}
563
564
static int
565
dissect_babel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
566
34
{
567
34
    proto_item    *ti;
568
34
    proto_tree    *babel_tree = NULL;
569
34
    uint8_t        version;
570
34
    uint16_t       bodylen;
571
572
34
    if (tvb_captured_length(tvb) < 4)
573
0
        return 0;
574
575
34
    if (tvb_get_uint8(tvb, 0) != 42)
576
0
        return 0;
577
34
    version = tvb_get_uint8(tvb, 1);
578
579
34
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Babel");
580
34
    col_set_str(pinfo->cinfo, COL_INFO, "Babel");
581
582
34
    if (version != 2) {
583
0
        col_add_fstr(pinfo->cinfo, COL_INFO, "Version %u", version);
584
0
        return 2;
585
0
    }
586
587
34
    if (tree) {
588
34
        ti = proto_tree_add_item(tree, proto_babel, tvb, 0, -1, ENC_NA);
589
34
        babel_tree = proto_item_add_subtree(ti, ett_babel);
590
591
34
        proto_tree_add_item(babel_tree, hf_babel_magic, tvb, 0, 1, ENC_BIG_ENDIAN);
592
34
        proto_tree_add_item(babel_tree, hf_babel_version, tvb, 1, 1, ENC_BIG_ENDIAN);
593
34
        proto_tree_add_item(babel_tree, hf_babel_bodylen,
594
34
                            tvb, 2, 2, ENC_BIG_ENDIAN);
595
34
    }
596
34
    bodylen = tvb_get_ntohs(tvb, 2);
597
34
    return dissect_babel_body(tvb, pinfo, babel_tree, 0, bodylen);
598
599
34
}
600
601
void
602
proto_register_babel(void)
603
14
{
604
14
    static hf_register_info hf[] = {
605
14
        { &hf_babel_magic,
606
14
          { "Magic", "babel.magic", FT_UINT8, BASE_DEC,
607
14
            NULL, 0, "Magic value 42", HFILL }
608
14
        },
609
14
        { &hf_babel_version,
610
14
          { "Version", "babel.version", FT_UINT8, BASE_DEC,
611
14
            NULL, 0, "Version of the Babel protocol", HFILL }
612
14
        },
613
14
        { &hf_babel_bodylen,
614
14
          { "Body Length", "babel.bodylen", FT_UINT16, BASE_DEC,
615
14
            NULL, 0, NULL, HFILL }
616
14
        },
617
14
        { &hf_babel_message,
618
14
          { "Message", "babel.message", FT_UINT8, BASE_DEC,
619
14
            NULL, 0, "Babel Message", HFILL }
620
14
        },
621
14
        { &hf_babel_message_type,
622
14
          { "Message Type", "babel.message.type", FT_UINT8, BASE_DEC,
623
14
            VALS(messages), 0, NULL, HFILL }
624
14
        },
625
14
        { &hf_babel_message_length,
626
14
          { "Message Length", "babel.message.length", FT_UINT8, BASE_DEC,
627
14
            NULL, 0, NULL, HFILL }
628
14
        },
629
14
        { &hf_babel_message_nonce,
630
14
          { "Nonce", "babel.message.nonce", FT_UINT16, BASE_HEX,
631
14
           NULL, 0, NULL, HFILL }
632
14
        },
633
14
        { &hf_babel_message_interval,
634
14
          { "Interval", "babel.message.interval", FT_UINT16, BASE_DEC,
635
14
           NULL, 0, "Interval (in centiseconds)", HFILL }
636
14
        },
637
14
        { &hf_babel_message_seqno,
638
14
          { "Seqno", "babel.message.seqno", FT_UINT16, BASE_HEX,
639
14
           NULL, 0, NULL, HFILL }
640
14
        },
641
14
        { &hf_babel_message_ae,
642
14
          { "Address Encoding", "babel.message.ae", FT_UINT8, BASE_DEC,
643
14
            VALS(aes), 0, NULL, HFILL }
644
14
        },
645
14
        { &hf_babel_message_prefix,
646
14
          { "Raw Prefix", "babel.message.prefix", FT_BYTES, BASE_NONE,
647
14
            NULL, 0, NULL, HFILL }
648
14
        },
649
14
        { &hf_babel_message_rxcost,
650
14
          { "Rxcost", "babel.message.rxcost", FT_UINT16, BASE_HEX,
651
14
           NULL, 0, "Rxcost (from the point of vue of the sender)", HFILL }
652
14
        },
653
14
        { &hf_babel_message_routerid,
654
14
          { "Router ID", "babel.message.routerid", FT_BYTES, BASE_NONE,
655
14
           NULL, 0, NULL, HFILL }
656
14
        },
657
14
        { &hf_babel_message_flags,
658
14
          { "Flags", "babel.message.flags", FT_UINT8, BASE_HEX,
659
14
            NULL, 0, NULL, HFILL }
660
14
        },
661
14
        { &hf_babel_message_plen,
662
14
          { "Prefix Length", "babel.message.plen", FT_UINT8, BASE_DEC,
663
14
            NULL, 0, NULL, HFILL }
664
14
        },
665
14
        { &hf_babel_message_omitted,
666
14
          { "Omitted Bytes", "babel.message.omitted", FT_UINT8, BASE_DEC,
667
14
            NULL, 0, "Number of bytes omitted from the prefix", HFILL }
668
14
        },
669
14
        { &hf_babel_message_metric,
670
14
          { "Metric", "babel.message.metric", FT_UINT16, BASE_DEC,
671
14
           NULL, 0, NULL, HFILL }
672
14
        },
673
14
        { &hf_babel_message_hopcount,
674
14
          { "Hop Count", "babel.message.hopcount", FT_UINT8, BASE_DEC,
675
14
            NULL, 0, NULL, HFILL }
676
14
        },
677
14
        { &hf_babel_message_index,
678
14
          { "Index", "babel.message.index", FT_UINT32, BASE_DEC,
679
14
          NULL, 0, NULL, HFILL }
680
14
        },
681
14
        { &hf_babel_subtlv,
682
14
          { "Sub-TLV", "babel.subtlv", FT_UINT8, BASE_DEC,
683
14
          NULL, 0, "Babel Sub-TLV", HFILL }
684
14
        },
685
14
        { &hf_babel_subtlv_type,
686
14
          { "Sub-TLV Type", "babel.subtlv.type", FT_UINT8, BASE_DEC,
687
14
          VALS(subtlvs), 0, NULL, HFILL }
688
14
        },
689
14
        { &hf_babel_subtlv_len,
690
14
          { "Sub-TLV Length", "babel.subtlv.length", FT_UINT8, BASE_DEC,
691
14
          VALS(subtlvs), 0, NULL, HFILL }
692
14
        },
693
14
        { &hf_babel_subtlv_diversity,
694
14
          { "Channel", "babel.subtlv.diversity.channel", FT_UINT8, BASE_DEC,
695
14
          NULL, 0, NULL, HFILL  }
696
14
        }
697
14
    };
698
699
14
    static int *ett[] = {
700
14
        &ett_babel,
701
14
        &ett_message,
702
14
        &ett_subtree,
703
14
        &ett_packet_trailer,
704
14
        &ett_unicast,
705
14
        &ett_subtlv,
706
14
        &ett_timestamp,
707
14
        &ett_mandatory
708
14
    };
709
710
14
    proto_babel =
711
14
        proto_register_protocol("Babel Routing Protocol", "Babel", "babel");
712
713
14
    proto_register_field_array(proto_babel, hf, array_length(hf));
714
14
    proto_register_subtree_array(ett, array_length(ett));
715
716
14
    babel_handle = register_dissector("babel", dissect_babel, proto_babel);
717
14
}
718
719
void
720
proto_reg_handoff_babel(void)
721
14
{
722
14
    dissector_add_uint_range_with_preference("udp.port", UDP_PORT_RANGE_BABEL, babel_handle);
723
14
}
724
725
/*
726
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
727
 *
728
 * Local variables:
729
 * c-basic-offset: 4
730
 * tab-width: 8
731
 * indent-tabs-mode: nil
732
 * End:
733
 *
734
 * vi: set shiftwidth=4 tabstop=8 expandtab:
735
 * :indentSize=4:tabSize=8:noTabs=true:
736
 */