Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-bfd.c
Line
Count
Source
1
/* packet-bfd.c
2
 * Routines for Bidirectional Forwarding Detection (BFD) message dissection
3
 * RFCs
4
 *   5880: Bidirectional Forwarding Detection (BFD)
5
 *   5881: Bidirectional Forwarding Detection (BFD) for IPv4 and IPv6 (Single Hop)
6
 *   5882: Generic Application of Bidirectional Forwarding Detection (BFD)
7
 *   5883: Bidirectional Forwarding Detection (BFD) for Multihop Paths
8
 *   5884: Bidirectional Forwarding Detection (BFD) for MPLS Label Switched Paths (LSPs)
9
 *   5885: Bidirectional Forwarding Detection (BFD) for the Pseudowire Virtual Circuit Connectivity Verification (VCCV)
10
 *   7130: Bidirectional Forwarding Detection (BFD) on Link Aggregation Group (LAG) Interfaces
11
 *   7881: Seamless Bidirectional Forwarding Detection (S-BFD) for IPv4, IPv6, and MPLS
12
 * (and https://tools.ietf.org/html/draft-ietf-bfd-base-01 for version 0)
13
 *
14
 * Copyright 2003, Hannes Gredler <hannes@juniper.net>
15
 * Copyright 2006, Balint Reczey <Balint.Reczey@ericsson.com>
16
 * Copyright 2007, Todd J Martin <todd.martin@acm.org>
17
 *
18
 * Copyright 2011, Jaihari Kalijanakiraman <jaiharik@ipinfusion.com>
19
 *                 Krishnamurthy Mayya <krishnamurthy.mayya@ipinfusion.com>
20
 *                 Nikitha Malgi       <malgi.nikitha@ipinfusion.com>
21
 *                  - support for MPLS-TP BFD Proactive CV Message Format as per RFC 6428
22
 *                  - includes decoding support for Section MEP-ID, LSP MEP-ID, PW MEP-ID
23
 *
24
 * Wireshark - Network traffic analyzer
25
 * By Gerald Combs <gerald@wireshark.org>
26
 * Copyright 1998 Gerald Combs
27
 *
28
 * SPDX-License-Identifier: GPL-2.0-or-later
29
 */
30
31
#include "config.h"
32
33
#include <epan/packet.h>
34
#include <epan/expert.h>
35
#include <epan/tfs.h>
36
#include <epan/unit_strings.h>
37
38
#include "packet-bfd.h"
39
#include "packet-mpls.h"
40
41
void proto_register_bfd(void);
42
void proto_reg_handoff_bfd(void);
43
44
static dissector_handle_t bfd_control_handle;
45
static dissector_handle_t bfd_echo_handle;
46
47
/* 3784: BFD control, 3785: BFD echo, 4784: BFD multi hop control */
48
/* 6784: BFD on LAG, 7784: seamless BFD */
49
/* https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=bfd */
50
14
#define UDP_PORT_RANGE_BFD_CTRL  "3784,4784,6784,7784"
51
14
#define UDP_PORT_BFD_ECHO  3785
52
53
/* As per RFC 6428 : https://tools.ietf.org/html/rfc6428
54
   Section: 3.5 */
55
1
#define TLV_TYPE_MPLSTP_SECTION_MEP   0
56
0
#define TLV_TYPE_MPLSTP_LSP_MEP       1
57
0
#define TLV_TYPE_MPLSTP_PW_MEP        2
58
59
static const value_string mplstp_mep_tlv_type_values [] = {
60
    { TLV_TYPE_MPLSTP_SECTION_MEP, "Section MEP-ID" },
61
    { TLV_TYPE_MPLSTP_LSP_MEP,     "LSP MEP-ID" },
62
    { TLV_TYPE_MPLSTP_PW_MEP,      "PW MEP-ID" },
63
    { 0, NULL}
64
};
65
static const value_string bfd_control_v0_diag_values[] = {
66
    { 0, "No Diagnostic" },
67
    { 1, "Control Detection Time Expired" },
68
    { 2, "Echo Function Failed" },
69
    { 3, "Neighbor Signaled Session Down" },
70
    { 4, "Forwarding Plane Reset" },
71
    { 5, "Path Down" },
72
    { 6, "Concatenated Path Down" },
73
    { 7, "Administratively Down" },
74
    { 0, NULL }
75
};
76
77
static const value_string bfd_control_v1_diag_values[] = {
78
    { 0, "No Diagnostic" },
79
    { 1, "Control Detection Time Expired" },
80
    { 2, "Echo Function Failed" },
81
    { 3, "Neighbor Signaled Session Down" },
82
    { 4, "Forwarding Plane Reset" },
83
    { 5, "Path Down" },
84
    { 6, "Concatenated Path Down" },
85
    { 7, "Administratively Down" },
86
    { 8, "Reverse Concatenated Path Down" },
87
    { 9, "Mis-Connectivity Defect" },
88
    { 0, NULL }
89
};
90
91
static const value_string bfd_control_sta_values[] = {
92
    { 0, "AdminDown" },
93
    { 1, "Down" },
94
    { 2, "Init" },
95
    { 3, "Up" },
96
    { 0, NULL }
97
};
98
99
2
#define BFD_AUTH_SIMPLE    1
100
3
#define BFD_AUTH_MD5       2
101
6
#define BFD_AUTH_MET_MD5   3
102
4
#define BFD_AUTH_SHA1      4
103
6
#define BFD_AUTH_MET_SHA1  5
104
static const value_string bfd_control_auth_type_values[] = {
105
    { BFD_AUTH_SIMPLE      , "Simple Password" },
106
    { BFD_AUTH_MD5         , "Keyed MD5" },
107
    { BFD_AUTH_MET_MD5     , "Meticulous Keyed MD5" },
108
    { BFD_AUTH_SHA1        , "Keyed SHA1" },
109
    { BFD_AUTH_MET_SHA1    , "Meticulous Keyed SHA1" },
110
    { 0, NULL }
111
};
112
/* Per the standard, the simple password must by 1-16 bytes in length */
113
#define MAX_PASSWORD_LEN 16
114
/* Per the standard, the length of the MD5 authentication packets must be 24
115
 * bytes and the checksum is 16 bytes */
116
2
#define MD5_AUTH_LEN 24
117
2
#define MD5_CHECKSUM_LEN 16
118
/* Per the standard, the length of the SHA1 authentication packets must be 28
119
 * bytes and the checksum is 20 bytes */
120
2
#define SHA1_AUTH_LEN 28
121
0
#define SHA1_CHECKSUM_LEN 20
122
123
static int proto_bfd;
124
static int proto_bfd_echo;
125
126
static int hf_bfd_version;
127
static int hf_bfd_diag;
128
static int hf_bfd_sta;
129
static int hf_bfd_flags;
130
static int hf_bfd_flags_h;
131
static int hf_bfd_flags_p;
132
static int hf_bfd_flags_f;
133
static int hf_bfd_flags_c;
134
static int hf_bfd_flags_a;
135
static int hf_bfd_flags_d;
136
static int hf_bfd_flags_m;
137
static int hf_bfd_flags_d_v0;
138
static int hf_bfd_flags_p_v0;
139
static int hf_bfd_flags_f_v0;
140
static int hf_bfd_detect_time_multiplier;
141
static int hf_bfd_message_length;
142
static int hf_bfd_my_discriminator;
143
static int hf_bfd_your_discriminator;
144
static int hf_bfd_desired_min_tx_interval;
145
static int hf_bfd_required_min_rx_interval;
146
static int hf_bfd_required_min_echo_interval;
147
static int hf_bfd_checksum;
148
149
static int hf_bfd_auth_type;
150
static int hf_bfd_auth_len;
151
static int hf_bfd_auth_key;
152
static int hf_bfd_auth_password;
153
static int hf_bfd_auth_seq_num;
154
155
static int hf_bfd_echo;
156
157
static int ett_bfd;
158
static int ett_bfd_flags;
159
static int ett_bfd_auth;
160
161
static int ett_bfd_echo;
162
163
static expert_field ei_bfd_auth_len_invalid;
164
static expert_field ei_bfd_auth_no_data;
165
166
static int hf_mep_type;
167
static int hf_mep_len;
168
static int hf_mep_global_id;
169
static int hf_mep_node_id;
170
/* static int hf_mep_interface_no; */
171
static int hf_mep_tunnel_no;
172
static int hf_mep_lsp_no;
173
static int hf_mep_ac_id;
174
static int hf_mep_agi_type;
175
static int hf_mep_agi_len;
176
static int hf_mep_agi_val;
177
static int hf_section_interface_no;
178
/*
179
 * Control packet version 0, draft-katz-ward-bfd-01.txt
180
 *
181
 *     0                   1                   2                   3
182
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
183
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
184
 *    |Vers |  Diag   |H|D|P|F| Rsvd  |  Detect Mult  |    Length     |
185
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
186
 *    |                       My Discriminator                        |
187
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
188
 *    |                      Your Discriminator                       |
189
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
190
 *    |                    Desired Min TX Interval                    |
191
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
192
 *    |                   Required Min RX Interval                    |
193
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
194
 *    |                 Required Min Echo RX Interval                 |
195
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
196
 */
197
198
/*
199
 * Control packet version 1, RFC 5880
200
 *
201
 *     0                   1                   2                   3
202
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
203
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204
 *    |Vers |  Diag   |Sta|P|F|C|A|D|M|  Detect Mult  |    Length     |
205
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206
 *    |                       My Discriminator                        |
207
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208
 *    |                      Your Discriminator                       |
209
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210
 *    |                    Desired Min TX Interval                    |
211
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212
 *    |                   Required Min RX Interval                    |
213
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
214
 *    |                 Required Min Echo RX Interval                 |
215
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
216
 *
217
 *    An optional Authentication Section may be present:
218
 *     0                   1                   2                   3
219
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
220
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
221
 *    |   Auth Type   |   Auth Len    |    Authentication Data...     |
222
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
223
 *
224
 *    There are 5 types of authentication defined:
225
 *      1 - Simple Password
226
 *      2 - Keyed MD5
227
 *      3 - Meticulous Keyed MD5
228
 *      4 - Keyed SHA1
229
 *      5 - Meticulous Keyed SHA1
230
 *
231
 *     The format for Simple Password authentication is:
232
 *     0                   1                   2                   3
233
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
234
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
235
 *    |   Auth Type   |   Auth Len    |  Auth Key ID  |  Password...  |
236
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
237
 *    |                              ...                              |
238
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
239
 *
240
 *    The format for Keyed MD5 and Meticulous Keyed MD5 authentication is:
241
 *     0                   1                   2                   3
242
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
243
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
244
 *    |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
245
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
246
 *    |                        Sequence Number                        |
247
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
248
 *    |                     Auth Key/Checksum...                      |
249
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
250
 *    |                              ...                              |
251
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
252
 *
253
 *    The format for Keyed SHA1 and Meticulous Keyed SHA1 authentication is:
254
 *     0                   1                   2                   3
255
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
256
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
257
 *    |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
258
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
259
 *    |                        Sequence Number                        |
260
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
261
 *    |                     Auth Key/Checksum...                      |
262
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263
 *    |                              ...                              |
264
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265
 *
266
 *
267
 */
268
269
270
/* Given the type of authentication being used, return the required length of
271
 * the authentication header
272
 */
273
static uint8_t
274
get_bfd_required_auth_len(uint8_t auth_type)
275
4
{
276
4
    uint8_t auth_len = 0;
277
278
4
    switch (auth_type) {
279
1
        case BFD_AUTH_MD5:
280
2
        case BFD_AUTH_MET_MD5:
281
2
            auth_len = MD5_AUTH_LEN;
282
2
            break;
283
1
        case BFD_AUTH_SHA1:
284
2
        case BFD_AUTH_MET_SHA1:
285
2
            auth_len = SHA1_AUTH_LEN;
286
2
            break;
287
0
        default:
288
0
            break;
289
4
    }
290
4
    return auth_len;
291
4
}
292
293
/* Given the type of authentication being used, return the length of
294
 * checksum field
295
 */
296
static uint8_t
297
get_bfd_checksum_len(uint8_t auth_type)
298
2
{
299
2
    uint8_t checksum_len = 0;
300
2
    switch (auth_type) {
301
1
        case BFD_AUTH_MD5:
302
2
        case BFD_AUTH_MET_MD5:
303
2
            checksum_len = MD5_CHECKSUM_LEN;
304
2
            break;
305
0
        case BFD_AUTH_SHA1:
306
0
        case BFD_AUTH_MET_SHA1:
307
0
            checksum_len = SHA1_CHECKSUM_LEN;
308
0
            break;
309
0
        default:
310
0
            break;
311
2
    }
312
2
    return checksum_len;
313
2
}
314
315
static void
316
dissect_bfd_authentication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
317
9
{
318
9
    int           offset    = 24;
319
9
    uint8_t       auth_type;
320
9
    uint8_t       auth_len;
321
9
    proto_item   *auth_item = NULL;
322
9
    proto_tree   *auth_tree = NULL;
323
9
    const uint8_t *password;
324
325
9
    auth_type = tvb_get_uint8(tvb, offset);
326
9
    auth_len  = tvb_get_uint8(tvb, offset + 1);
327
328
9
    if (tree) {
329
9
        auth_tree = proto_tree_add_subtree_format(tree, tvb, offset, auth_len,
330
9
                                        ett_bfd_auth, NULL, "Authentication: %s",
331
9
                                        val_to_str(pinfo->pool, auth_type,
332
9
                                                   bfd_control_auth_type_values,
333
9
                                                   "Unknown Authentication Type (%d)") );
334
335
9
        proto_tree_add_item(auth_tree, hf_bfd_auth_type, tvb, offset, 1, ENC_BIG_ENDIAN);
336
337
9
        proto_tree_add_item(auth_tree, hf_bfd_auth_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
338
339
9
        proto_tree_add_item(auth_tree, hf_bfd_auth_key, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
340
9
    }
341
342
9
    switch (auth_type) {
343
2
        case BFD_AUTH_SIMPLE:
344
2
            proto_tree_add_item_ret_string(auth_tree, hf_bfd_auth_password, tvb, offset+3,
345
2
                                    auth_len-3, ENC_ASCII|ENC_NA, pinfo->pool, &password);
346
2
            proto_item_append_text(auth_item, ": %s", password);
347
2
            break;
348
1
        case BFD_AUTH_MD5:
349
2
        case BFD_AUTH_MET_MD5:
350
3
        case BFD_AUTH_SHA1:
351
4
        case BFD_AUTH_MET_SHA1:
352
4
            if (auth_len != get_bfd_required_auth_len(auth_type)) {
353
4
                proto_tree_add_expert_format(auth_tree, pinfo, &ei_bfd_auth_len_invalid, tvb, offset, auth_len,
354
4
                        "Length of authentication section (%d) is invalid for Authentication Type: %s",
355
4
                        auth_len, val_to_str(pinfo->pool, auth_type, bfd_control_auth_type_values, "Unknown Authentication Type (%d)") );
356
357
4
                proto_item_append_text(auth_item, ": Invalid Authentication Section");
358
4
            }
359
360
4
            if (tree) {
361
2
                proto_tree_add_item(auth_tree, hf_bfd_auth_seq_num, tvb, offset+4, 4, ENC_BIG_ENDIAN);
362
363
2
                proto_tree_add_item(auth_tree, hf_bfd_checksum, tvb, offset+8, get_bfd_checksum_len(auth_type), ENC_NA);
364
2
            }
365
4
            break;
366
1
        default:
367
1
            break;
368
9
    }
369
9
}
370
371
static int
372
dissect_bfd_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
373
0
{
374
0
    proto_tree *bfd_tree = NULL;
375
0
    unsigned bfd_length = tvb_reported_length_remaining(tvb, 0);
376
377
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "BFD Echo");
378
    /* XXX Add direction */
379
0
    col_set_str(pinfo->cinfo, COL_INFO, "Originator specific content");
380
381
0
    if (tree) {
382
0
        proto_item *ti;
383
384
0
        ti = proto_tree_add_protocol_format(tree, proto_bfd_echo, tvb, 0, bfd_length,
385
0
                                            "BFD Echo message");
386
387
0
        bfd_tree = proto_item_add_subtree(ti, ett_bfd_echo);
388
389
0
        proto_tree_add_item(bfd_tree, hf_bfd_echo, tvb, 0, bfd_length, ENC_NA);
390
0
    }
391
392
0
    return bfd_length;
393
0
}
394
395
static int
396
dissect_bfd_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
397
19
{
398
19
    unsigned flags;
399
19
    unsigned bfd_version;
400
19
    unsigned bfd_diag;
401
19
    unsigned bfd_sta        = 0;
402
19
    unsigned bfd_flags;
403
19
    unsigned bfd_flags_a    = 0;
404
19
    unsigned bfd_detect_time_multiplier;
405
19
    unsigned bfd_length;
406
19
    unsigned bfd_my_discriminator;
407
19
    unsigned bfd_your_discriminator;
408
19
    unsigned bfd_desired_min_tx_interval;
409
19
    unsigned bfd_required_min_rx_interval;
410
19
    unsigned bfd_required_min_echo_interval;
411
19
    proto_tree *bfd_tree = NULL;
412
413
19
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "BFD Control");
414
19
    col_clear(pinfo->cinfo, COL_INFO);
415
416
19
    bfd_version = (tvb_get_uint8(tvb, 0) & 0xe0) >> 5;
417
19
    bfd_diag    = (tvb_get_uint8(tvb, 0) & 0x1f);
418
19
    flags       = tvb_get_uint8(tvb, 1);
419
19
    switch (bfd_version) {
420
4
        case 0:
421
4
            bfd_flags      = flags;
422
4
            break;
423
3
        case 1:
424
15
        default:
425
15
            bfd_sta        = flags & 0xc0;
426
15
            bfd_flags      = flags & 0x3e;
427
15
            bfd_flags_a    = flags & 0x04;
428
15
            break;
429
19
    }
430
431
19
    bfd_detect_time_multiplier     = tvb_get_uint8(tvb, 2);
432
19
    bfd_length                     = tvb_get_uint8(tvb, 3);
433
19
    bfd_my_discriminator           = tvb_get_ntohl(tvb, 4);
434
19
    bfd_your_discriminator         = tvb_get_ntohl(tvb, 8);
435
19
    bfd_desired_min_tx_interval    = tvb_get_ntohl(tvb, 12);
436
19
    bfd_required_min_rx_interval   = tvb_get_ntohl(tvb, 16);
437
19
    bfd_required_min_echo_interval = tvb_get_ntohl(tvb, 20);
438
439
19
    switch (bfd_version) {
440
2
        case 0:
441
2
            col_add_fstr(pinfo->cinfo, COL_INFO, "Diag: %s, Flags: 0x%02x",
442
2
                         val_to_str_const(bfd_diag, bfd_control_v0_diag_values, "Unknown"),
443
2
                         bfd_flags);
444
2
            break;
445
3
        case 1:
446
14
        default:
447
14
            col_add_fstr(pinfo->cinfo, COL_INFO, "Diag: %s, State: %s, Flags: 0x%02x",
448
14
                         val_to_str_const(bfd_diag, bfd_control_v1_diag_values, "Unknown"),
449
14
                         val_to_str_const(bfd_sta >> 6 , bfd_control_sta_values, "Unknown"),
450
14
                         bfd_flags);
451
14
            break;
452
19
    }
453
454
16
    if (tree) {
455
16
        proto_item *ti;
456
457
16
        ti = proto_tree_add_protocol_format(tree, proto_bfd, tvb, 0, bfd_length,
458
16
                                            "BFD Control message");
459
460
16
        bfd_tree = proto_item_add_subtree(ti, ett_bfd);
461
462
16
        proto_tree_add_uint(bfd_tree, hf_bfd_version, tvb, 0,
463
16
                                 1, bfd_version << 5);
464
465
16
        proto_tree_add_uint(bfd_tree, hf_bfd_diag, tvb, 0,
466
16
                                 1, bfd_diag);
467
468
16
        switch (bfd_version) {
469
2
            case 0:
470
2
                break;
471
3
            case 1:
472
14
            default:
473
14
                proto_tree_add_uint(bfd_tree, hf_bfd_sta, tvb, 1,
474
14
                                    1, bfd_sta);
475
476
14
                break;
477
16
        }
478
16
        switch (bfd_version) {
479
2
            case 0:
480
2
                {
481
2
                static int * const bfd_message_flags[] = {
482
2
                    &hf_bfd_flags_h,
483
2
                    &hf_bfd_flags_d_v0,
484
2
                    &hf_bfd_flags_p_v0,
485
2
                    &hf_bfd_flags_f_v0,
486
2
                    NULL
487
2
                };
488
2
                proto_tree_add_bitmask_with_flags(bfd_tree, tvb, 1, hf_bfd_flags, ett_bfd_flags, bfd_message_flags, ENC_NA, BMT_NO_FALSE);
489
2
                }
490
2
                break;
491
3
            case 1:
492
14
            default:
493
14
                {
494
14
                static int * const bfd_message_flags[] = {
495
14
                    &hf_bfd_flags_p,
496
14
                    &hf_bfd_flags_f,
497
14
                    &hf_bfd_flags_c,
498
14
                    &hf_bfd_flags_a,
499
14
                    &hf_bfd_flags_d,
500
14
                    &hf_bfd_flags_m,
501
14
                    NULL
502
14
                };
503
14
                proto_tree_add_bitmask_with_flags(bfd_tree, tvb, 1, hf_bfd_flags, ett_bfd_flags, bfd_message_flags, ENC_NA, BMT_NO_FALSE);
504
14
                }
505
14
                break;
506
16
        }
507
508
16
        proto_tree_add_uint_format_value(bfd_tree, hf_bfd_detect_time_multiplier, tvb, 2,
509
16
                                         1, bfd_detect_time_multiplier,
510
16
                                         "%u (= %u ms Detection time)",
511
16
                                         bfd_detect_time_multiplier,
512
16
                                         bfd_detect_time_multiplier * (bfd_desired_min_tx_interval/1000));
513
514
16
        proto_tree_add_uint(bfd_tree, hf_bfd_message_length, tvb, 3, 1, bfd_length);
515
516
16
        proto_tree_add_uint(bfd_tree, hf_bfd_my_discriminator, tvb, 4,
517
16
                                 4, bfd_my_discriminator);
518
519
16
        proto_tree_add_uint(bfd_tree, hf_bfd_your_discriminator, tvb, 8,
520
16
                                 4, bfd_your_discriminator);
521
522
16
        proto_tree_add_uint_format_value(bfd_tree, hf_bfd_desired_min_tx_interval, tvb, 12,
523
16
                                              4, bfd_desired_min_tx_interval,
524
16
                                              "%4u ms (%u us)",
525
16
                                              bfd_desired_min_tx_interval/1000,
526
16
                                              bfd_desired_min_tx_interval);
527
528
16
        proto_tree_add_uint_format_value(bfd_tree, hf_bfd_required_min_rx_interval, tvb, 16,
529
16
                                              4, bfd_required_min_rx_interval,
530
16
                                              "%4u ms (%u us)",
531
16
                                              bfd_required_min_rx_interval/1000,
532
16
                                              bfd_required_min_rx_interval);
533
534
16
        proto_tree_add_uint_format_value(bfd_tree, hf_bfd_required_min_echo_interval, tvb, 20,
535
16
                                              4, bfd_required_min_echo_interval,
536
16
                                              "%4u ms (%u us)",
537
16
                                              bfd_required_min_echo_interval/1000,
538
16
                                              bfd_required_min_echo_interval);
539
16
    } /* if (tree) */
540
541
    /* Dissect the authentication fields if the Authentication flag has
542
     * been set
543
     */
544
16
    if (bfd_version && bfd_flags_a) {
545
11
        if (bfd_length >= 28) {
546
9
            dissect_bfd_authentication(tvb, pinfo, bfd_tree);
547
9
        } else {
548
2
            proto_tree_add_expert_format(bfd_tree, pinfo, &ei_bfd_auth_no_data, tvb, 24, bfd_length-24,
549
2
                                         "Authentication: Length of the BFD frame is invalid (%d)", bfd_length);
550
2
        }
551
11
    }
552
553
16
    return tvb_captured_length(tvb);
554
16
}
555
556
/* BFD CV Source MEP-ID TLV Decoder,
557
   As per RFC 6428 : https://tools.ietf.org/html/rfc6428
558
   sections - 3.5.1, 3.5.2, 3.5.3 */
559
void
560
dissect_bfd_mep (tvbuff_t *tvb, proto_tree *tree, const int hfindex)
561
2
{
562
2
    proto_item *ti;
563
2
    proto_tree *bfd_tree;
564
2
    int         offset = 0;
565
2
    int         mep_type;
566
2
    int         mep_len;
567
2
    int         mep_agi_len;
568
569
2
    if (!tree)
570
0
        return;
571
572
    /* Fetch the BFD control message length and move the offset
573
       to point to the data portion after the control message */
574
575
    /* The parameter hfindex is used for determining the tree under which MEP-ID TLV
576
       has to be determined. Since according to RFC 6428, MEP-ID TLV can be used by any
577
       OAM function, if hfindex is 0, as per this function the MEP-TLV is a part of
578
       BFD-CV payload. If a non-zero hfindex comes, then tht TLV info will be displayed
579
       under a particular protocol-tree. */
580
2
    if (!hfindex)
581
0
      {
582
0
        offset   = tvb_get_uint8(tvb, 3);
583
0
        mep_type = tvb_get_ntohs (tvb, offset);
584
0
        mep_len  = tvb_get_ntohs (tvb, (offset + 2));
585
0
        ti       = proto_tree_add_protocol_format (tree, proto_bfd, tvb, offset, (mep_len + 4),
586
0
                                                   "MPLS-TP SOURCE MEP-ID TLV");
587
0
      }
588
2
    else
589
2
      {
590
2
        mep_type = tvb_get_ntohs (tvb, offset);
591
2
        mep_len  = tvb_get_ntohs (tvb, (offset + 2));
592
2
        ti       = proto_tree_add_protocol_format (tree, hfindex, tvb, offset, (mep_len + 4),
593
2
                                                   "MPLS-TP SOURCE MEP-ID TLV");
594
2
      }
595
596
2
    switch (mep_type) {
597
1
        case TLV_TYPE_MPLSTP_SECTION_MEP:
598
599
1
            bfd_tree = proto_item_add_subtree (ti, ett_bfd);
600
1
            proto_tree_add_uint (bfd_tree, hf_mep_type , tvb, offset,
601
1
                                 2, mep_type);
602
1
            proto_tree_add_uint (bfd_tree, hf_mep_len, tvb, (offset + 2),
603
1
                                 2, mep_len);
604
1
            proto_tree_add_item (bfd_tree, hf_mep_global_id, tvb, (offset + 4),
605
1
                                 4, ENC_BIG_ENDIAN);
606
1
            proto_tree_add_item (bfd_tree, hf_mep_node_id, tvb, (offset + 8),
607
1
                                 4, ENC_BIG_ENDIAN);
608
1
            proto_tree_add_item (bfd_tree, hf_section_interface_no, tvb, (offset + 12),
609
1
                                 4, ENC_BIG_ENDIAN);
610
611
1
            break;
612
613
0
        case TLV_TYPE_MPLSTP_LSP_MEP:
614
615
0
            bfd_tree = proto_item_add_subtree (ti, ett_bfd);
616
0
            proto_tree_add_uint (bfd_tree, hf_mep_type , tvb, offset,
617
0
                                 2, mep_type);
618
0
            proto_tree_add_uint (bfd_tree, hf_mep_len, tvb, (offset + 2),
619
0
                                 2, mep_len);
620
0
            proto_tree_add_item (bfd_tree, hf_mep_global_id, tvb, (offset + 4),
621
0
                                 4, ENC_BIG_ENDIAN);
622
0
            proto_tree_add_item (bfd_tree, hf_mep_node_id, tvb, (offset + 8),
623
0
                                 4, ENC_BIG_ENDIAN);
624
0
            proto_tree_add_item (bfd_tree, hf_mep_tunnel_no, tvb, (offset + 12),
625
0
                                 2, ENC_BIG_ENDIAN);
626
0
            proto_tree_add_item (bfd_tree, hf_mep_lsp_no, tvb, (offset + 14),
627
0
                                 2, ENC_BIG_ENDIAN);
628
629
0
            break;
630
631
0
        case TLV_TYPE_MPLSTP_PW_MEP:
632
633
0
            mep_agi_len   = tvb_get_uint8 (tvb, (offset + 17));
634
0
            bfd_tree = proto_item_add_subtree (ti, ett_bfd);
635
0
            proto_tree_add_uint (bfd_tree, hf_mep_type, tvb, offset,
636
0
                                 2, (mep_type));
637
0
            proto_tree_add_uint (bfd_tree, hf_mep_len, tvb, (offset + 2),
638
0
                                 2, mep_len);
639
0
            proto_tree_add_item (bfd_tree, hf_mep_global_id, tvb, (offset + 4),
640
0
                                 4, ENC_BIG_ENDIAN);
641
0
            proto_tree_add_item (bfd_tree, hf_mep_node_id, tvb, (offset + 8),
642
0
                                 4, ENC_BIG_ENDIAN);
643
0
            proto_tree_add_item (bfd_tree, hf_mep_ac_id, tvb, (offset + 12),
644
0
                                 4, ENC_BIG_ENDIAN);
645
0
            proto_tree_add_item (bfd_tree, hf_mep_agi_type, tvb, (offset + 16),
646
0
                                 1, ENC_BIG_ENDIAN);
647
0
            proto_tree_add_uint (bfd_tree, hf_mep_agi_len, tvb, (offset + 17),
648
0
                                 1, mep_agi_len);
649
0
            proto_tree_add_item (bfd_tree, hf_mep_agi_val, tvb, (offset + 18),
650
0
                                 mep_agi_len, ENC_ASCII);
651
652
0
            break;
653
654
1
        default:
655
1
            break;
656
2
    }
657
2
    return;
658
2
}
659
660
/* Register the protocol with Wireshark */
661
void
662
proto_register_bfd(void)
663
14
{
664
665
    /* Setup list of header fields */
666
14
    static hf_register_info hf[] = {
667
14
        { &hf_bfd_version,
668
14
          { "Protocol Version", "bfd.version",
669
14
            FT_UINT8, BASE_DEC, NULL , 0xe0,
670
14
            "The version number of the BFD protocol", HFILL }
671
14
        },
672
14
        { &hf_bfd_diag,
673
14
          { "Diagnostic Code", "bfd.diag",
674
14
            FT_UINT8, BASE_HEX, VALS(bfd_control_v1_diag_values), 0x1f,
675
14
            "This field give the reason for a BFD session failure", HFILL }
676
14
        },
677
14
        { &hf_bfd_sta,
678
14
          { "Session State", "bfd.sta",
679
14
            FT_UINT8, BASE_HEX, VALS(bfd_control_sta_values), 0xc0,
680
14
            "The BFD state as seen by the transmitting system", HFILL }
681
14
        },
682
14
        { &hf_bfd_flags,
683
14
          { "Message Flags", "bfd.flags",
684
14
            FT_UINT8, BASE_HEX, NULL, 0x00,
685
14
            NULL, HFILL }
686
14
        },
687
14
        { &hf_bfd_flags_h,
688
14
          { "I hear you", "bfd.flags.h",
689
14
            FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
690
14
            NULL, HFILL }
691
14
        },
692
14
        { &hf_bfd_flags_d_v0,
693
14
          { "Demand", "bfd.flags.d",
694
14
            FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x40,
695
14
            NULL, HFILL }
696
14
        },
697
14
        { &hf_bfd_flags_p_v0,
698
14
          { "Poll", "bfd.flags.p",
699
14
            FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x20,
700
14
            NULL, HFILL }
701
14
        },
702
14
        { &hf_bfd_flags_f_v0,
703
14
          { "Final", "bfd.flags.f",
704
14
            FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x10,
705
14
            NULL, HFILL }
706
14
        },
707
14
        { &hf_bfd_flags_p,
708
14
          { "Poll", "bfd.flags.p",
709
14
            FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x20, /* 6 flag bits; Sta is shown separately */
710
14
            "If set, the transmitting system is expecting a packet with the Final (F) bit in reply",
711
14
            HFILL }
712
14
        },
713
14
        { &hf_bfd_flags_f,
714
14
          { "Final", "bfd.flags.f",
715
14
            FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x10, /* 6 flag bits; Sta is shown separately */
716
14
            "If set, the transmitting system is replying to a packet with the Poll (P) bit set",
717
14
            HFILL }
718
14
        },
719
14
        { &hf_bfd_flags_c,
720
14
          { "Control Plane Independent", "bfd.flags.c",
721
14
            FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x08, /* 6 flag bits; Sta is shown separately */
722
14
            "If set, the BFD implementation is implemented in the forwarding plane", HFILL }
723
14
        },
724
14
        { &hf_bfd_flags_a,
725
14
          { "Authentication Present", "bfd.flags.a",
726
14
            FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x04, /* 6 flag bits; Sta is shown separately */
727
14
            "The Authentication Section is present", HFILL }
728
14
        },
729
14
        { &hf_bfd_flags_d,
730
14
          { "Demand", "bfd.flags.d",
731
14
            FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x02, /* 6 flag bits; Sta is shown separately */
732
14
            "If set, Demand mode is active in the transmitting system", HFILL }
733
14
        },
734
14
        { &hf_bfd_flags_m,
735
14
          { "Multipoint", "bfd.flags.m",
736
14
            FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x01, /* 6 flag bits; Sta is shown separately */
737
14
            "Reserved for future point-to-multipoint extensions", HFILL }
738
14
        },
739
14
        { &hf_bfd_detect_time_multiplier,
740
14
          { "Detect Time Multiplier", "bfd.detect_time_multiplier",
741
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
742
14
            "The transmit interval multiplied by this value is the failure detection time", HFILL }
743
14
        },
744
14
        { &hf_bfd_message_length,
745
14
          { "Message Length", "bfd.message_length",
746
14
            FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
747
14
            "Length of the BFD Control packet, in bytes", HFILL }
748
14
        },
749
14
        { &hf_bfd_my_discriminator,
750
14
          { "My Discriminator", "bfd.my_discriminator",
751
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
752
14
            NULL, HFILL }
753
14
        },
754
14
        { &hf_bfd_your_discriminator,
755
14
          { "Your Discriminator", "bfd.your_discriminator",
756
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
757
14
            NULL, HFILL }
758
14
        },
759
14
        { &hf_bfd_desired_min_tx_interval,
760
14
          { "Desired Min TX Interval", "bfd.desired_min_tx_interval",
761
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
762
14
            "The minimum interval to use when transmitting BFD Control packets", HFILL }
763
14
        },
764
14
        { &hf_bfd_required_min_rx_interval,
765
14
          { "Required Min RX Interval", "bfd.required_min_rx_interval",
766
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
767
14
            "The minimum interval between received BFD Control packets that this system can support", HFILL }
768
14
        },
769
14
        { &hf_bfd_required_min_echo_interval,
770
14
          { "Required Min Echo Interval", "bfd.required_min_echo_interval",
771
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
772
14
            "The minimum interval between received BFD Echo packets that this system can support", HFILL }
773
14
        },
774
14
        { &hf_bfd_checksum,
775
14
          { "Checksum", "bfd.checksum",
776
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
777
14
            NULL, HFILL }
778
14
        },
779
14
        { &hf_bfd_auth_type,
780
14
          { "Authentication Type", "bfd.auth.type",
781
14
            FT_UINT8, BASE_DEC, VALS(bfd_control_auth_type_values), 0x0,
782
14
            "The type of authentication in use on this session", HFILL }
783
14
        },
784
14
        { &hf_bfd_auth_len,
785
14
          { "Authentication Length", "bfd.auth.len",
786
14
            FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
787
14
            "The length, in bytes, of the authentication section", HFILL }
788
14
        },
789
14
        { &hf_bfd_auth_key,
790
14
          { "Authentication Key ID", "bfd.auth.key",
791
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
792
14
            "The Authentication Key ID, identifies which password is in use for this packet", HFILL }
793
14
        },
794
14
        { &hf_bfd_auth_password,
795
14
          { "Password", "bfd.auth.password",
796
14
            FT_STRING, BASE_NONE, NULL, 0x0,
797
14
            "The simple password in use on this session", HFILL }
798
14
        },
799
14
        { &hf_bfd_auth_seq_num,
800
14
          { "Sequence Number", "bfd.auth.seq_num",
801
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
802
14
            "The Sequence Number is periodically incremented to prevent replay attacks", HFILL }
803
14
          },
804
14
         { &hf_mep_type,
805
14
          { "Type", "bfd.mep.type",
806
14
            FT_UINT16, BASE_DEC, VALS(mplstp_mep_tlv_type_values), 0x0,
807
14
            "The type of the MEP Id", HFILL }
808
14
        },
809
14
        { &hf_mep_len,
810
14
          { "Length", "bfd.mep.len",
811
14
            FT_UINT16, BASE_DEC, NULL , 0x0,
812
14
            "The length of the MEP Id", HFILL }
813
14
        },
814
14
        { &hf_mep_global_id,
815
14
          { "Global Id", "bfd.mep.global.id",
816
14
            FT_UINT32, BASE_DEC, NULL , 0x0,
817
14
            "MPLS-TP  Global  MEP Id", HFILL }
818
14
        },
819
14
        { &hf_mep_node_id,
820
14
          { "Node Id", "bfd.mep.node.id",
821
14
            FT_IPv4, BASE_NONE, NULL , 0x0,
822
14
            "MPLS-TP Node Identifier", HFILL }
823
14
        },
824
#if 0
825
        { &hf_mep_interface_no,
826
          { "Interface  Number", "bfd.mep.interface.no",
827
            FT_UINT32, BASE_DEC, NULL , 0x0,
828
            "MPLS-TP Interface Number", HFILL }
829
        },
830
#endif
831
14
        { &hf_mep_tunnel_no,
832
14
          { "Tunnel Number", "bfd.mep.tunnel.no",
833
14
            FT_UINT16, BASE_DEC, NULL , 0x0,
834
14
            NULL, HFILL }
835
14
        },
836
14
        { &hf_mep_lsp_no,
837
14
          { "LSP Number", "bfd.mep.lsp.no",
838
14
            FT_UINT16, BASE_DEC, NULL , 0x0,
839
14
            NULL, HFILL }
840
14
        },
841
14
        { &hf_mep_ac_id,
842
14
          { "AC Id", "bfd.mep.ac.id",
843
14
            FT_UINT32, BASE_DEC, NULL , 0x0,
844
14
            NULL, HFILL }
845
14
        },
846
14
        { &hf_mep_agi_type,
847
14
          { "AGI TYPE", "bfd.mep.agi.type",
848
14
            FT_UINT8, BASE_DEC, NULL , 0x0,
849
14
            NULL, HFILL }
850
14
        },
851
14
        { &hf_mep_agi_len,
852
14
          { "AGI Length", "bfd.mep.agi.len",
853
14
            FT_UINT8, BASE_DEC, NULL , 0x0,
854
14
            NULL, HFILL }
855
14
        },
856
14
        { &hf_mep_agi_val,
857
14
           { "AGI value", "bfd.mep.agi.val",
858
14
             FT_STRING, BASE_NONE, NULL , 0x0,
859
14
             NULL, HFILL }
860
14
        },
861
14
        { &hf_section_interface_no,
862
14
          { "Interface Number", "bfd.mep.interface.no",
863
14
            FT_UINT32, BASE_DEC, NULL , 0x0,
864
14
            "MPLS-TP Interface Number", HFILL }
865
14
        }
866
14
    };
867
    /* BFD Echo */
868
14
    static hf_register_info hf_echo[] = {
869
14
        { &hf_bfd_echo,
870
14
          { "Echo", "bfd_echo.packet",
871
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
872
14
            "Originator specific echo packet", HFILL }
873
14
        }
874
14
    };
875
876
    /* Setup protocol subtree array */
877
14
    static int *ett[] = {
878
14
        &ett_bfd,
879
14
        &ett_bfd_flags,
880
14
        &ett_bfd_auth,
881
14
        &ett_bfd_echo
882
14
    };
883
884
14
    static ei_register_info ei[] = {
885
14
        { &ei_bfd_auth_len_invalid, { "bfd.auth.len.invalid", PI_MALFORMED, PI_WARN, "Length of authentication section is invalid", EXPFILL }},
886
14
        { &ei_bfd_auth_no_data, { "bfd.auth.no_data", PI_MALFORMED, PI_WARN, "Authentication flag is set in a BFD packet, but no authentication data is present", EXPFILL }},
887
14
    };
888
889
14
    expert_module_t* expert_bfd;
890
891
    /* Register the protocol name and description */
892
14
    proto_bfd = proto_register_protocol("Bidirectional Forwarding Detection Control Message",
893
14
                                        "BFD Control",
894
14
                                        "bfd");
895
14
    proto_bfd_echo = proto_register_protocol("Bidirectional Forwarding Detection Echo Packet",
896
14
                                        "BFD Echo",
897
14
                                        "bfd_echo");
898
899
    /* Required function calls to register the header fields and subtrees used */
900
14
    proto_register_field_array(proto_bfd, hf, array_length(hf));
901
14
    proto_register_field_array(proto_bfd_echo, hf_echo, array_length(hf_echo));
902
14
    proto_register_subtree_array(ett, array_length(ett));
903
14
    expert_bfd = expert_register_protocol(proto_bfd);
904
14
    expert_register_field_array(expert_bfd, ei, array_length(ei));
905
906
    /* Register dissectors */
907
14
    bfd_control_handle = register_dissector("bfd", dissect_bfd_control, proto_bfd);
908
14
    bfd_echo_handle = register_dissector("bfd_echo", dissect_bfd_echo, proto_bfd_echo);
909
14
}
910
911
void
912
proto_reg_handoff_bfd(void)
913
14
{
914
14
    dissector_add_uint_range_with_preference("udp.port", UDP_PORT_RANGE_BFD_CTRL, bfd_control_handle);
915
14
    dissector_add_uint("udp.port", UDP_PORT_BFD_ECHO, bfd_echo_handle);
916
917
14
    dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_BFD_CC, bfd_control_handle);
918
14
    dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_BFD_CV, bfd_control_handle);
919
14
    dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_BFD, bfd_control_handle);
920
14
}
921
922
/*
923
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
924
 *
925
 * Local variables:
926
 * c-basic-offset: 4
927
 * tab-width: 8
928
 * indent-tabs-mode: nil
929
 * End:
930
 *
931
 * vi: set shiftwidth=4 tabstop=8 expandtab:
932
 * :indentSize=4:tabSize=8:noTabs=true:
933
 */