Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-bier.c
Line
Count
Source
1
/* @file
2
 * Routines for Bit Index Explicit Replication (BIER) dissection
3
 *
4
 * Copyright 2024, John Thacker <johnthacker@gmail.com>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 *
12
 * RFC 8296: https://www.rfc-editor.org/rfc/rfc8296.html
13
 */
14
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <epan/expert.h>
19
#include <epan/prefs.h>
20
21
void proto_register_bier(void);
22
void proto_reg_handoff_bier(void);
23
24
static int proto_bier;
25
26
static int hf_bier_nibble;
27
static int hf_bier_ver;
28
static int hf_bier_bsl;
29
static int hf_bier_entropy;
30
static int hf_bier_oam;
31
static int hf_bier_rsv;
32
static int hf_bier_dscp;
33
static int hf_bier_proto;
34
static int hf_bier_bfir_id;
35
static int hf_bier_bitstring;
36
37
static int ett_bier;
38
39
static expert_field ei_bier_too_deep;
40
41
static dissector_table_t bier_subdissector_table;
42
43
static dissector_handle_t bier_handle;
44
45
static const value_string bier_bsl_vals[] = {
46
    { 1, "64 bits" },
47
    { 2, "128 bits" },
48
    { 3, "256 bits" },
49
    { 4, "512 bits" },
50
    { 5, "1024 bits" },
51
    { 6, "2048 bits" },
52
    { 7, "4096 bits" },
53
    { 0, NULL }
54
};
55
56
// https://www.iana.org/assignments/bier/bier.xhtml#bier-next-protocol-identifiers
57
static const value_string bier_proto_vals[] = {
58
    { 0, "Reserved" },
59
    { 1, "MPLS packet with downstream-assigned label at top of stack" },
60
    { 2, "MPLS packet with upstream-assigned label at top of stack" },
61
    { 3, "Ethernet frame" },
62
    { 4, "IPv4 packet" },
63
    { 5, "OAM packet" },
64
    { 6, "IPv6 packet" },
65
    { 7, "Payload is VXLAN encapsulated (no IP/UDP header)" },
66
    { 8, "Payload is NVGRE encapsulated (no IP header)" },
67
    { 9, "Payload is GENEVE encapsulated (no IP/UDP header)" },
68
    { 63, "Reserved" },
69
    { 0, NULL }
70
};
71
72
static int
73
dissect_bier(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
74
43
{
75
43
    proto_item *ti;
76
43
    proto_tree *bier_tree;
77
78
43
    unsigned offset = 0;
79
43
    uint32_t proto;
80
43
    tvbuff_t *next_tvb;
81
82
43
    if (tvb_reported_length(tvb) < 16) {
83
9
        return 0;
84
9
    }
85
86
34
    if (tvb_captured_length(tvb) < 2) {
87
1
        return 0;
88
1
    }
89
90
    /* This nibble is ignored in non-MPLS */
91
33
    if (((tvb_get_uint8(tvb, 0) >> 4) & 0xF) != 0x5) {
92
0
        return 0;
93
0
    }
94
95
33
    uint8_t bsl = (tvb_get_uint8(tvb, 1) >> 4) & 0xF;
96
33
    if (bsl == 0 || bsl > 7) {
97
13
        return 0;
98
13
    }
99
100
20
    unsigned bitstring_length = 1 << (bsl + 2);
101
102
20
    if (tvb_reported_length_remaining(tvb, 8) < bitstring_length) {
103
5
        return 0;
104
5
    }
105
106
15
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "BIER");
107
15
    col_clear(pinfo->cinfo, COL_INFO);
108
109
15
    ti = proto_tree_add_item(tree, proto_bier, tvb, offset, 8 + bitstring_length, ENC_NA);
110
111
15
    bier_tree = proto_item_add_subtree(ti, ett_bier);
112
113
15
    proto_tree_add_item(bier_tree, hf_bier_nibble, tvb, offset, 1, ENC_NA);
114
15
    proto_tree_add_item(bier_tree, hf_bier_ver, tvb, offset, 1, ENC_NA);
115
15
    offset += 1;
116
117
15
    proto_tree_add_item(bier_tree, hf_bier_bsl, tvb, offset, 1, ENC_NA);
118
15
    proto_tree_add_item(bier_tree, hf_bier_entropy, tvb, offset, 3, ENC_BIG_ENDIAN);
119
15
    offset += 3;
120
121
15
    proto_tree_add_item(bier_tree, hf_bier_oam, tvb, offset, 1, ENC_NA);
122
15
    proto_tree_add_item(bier_tree, hf_bier_rsv, tvb, offset, 1, ENC_NA);
123
    /* DSCP field unused in MPLS; may be as IP DSCP in non-MPLS. */
124
15
    proto_tree_add_item(bier_tree, hf_bier_dscp, tvb, offset, 2, ENC_BIG_ENDIAN);
125
15
    offset += 1;
126
127
15
    proto_tree_add_item_ret_uint(bier_tree, hf_bier_proto, tvb, offset, 1, ENC_NA, &proto);
128
15
    col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, proto, bier_proto_vals, "Unknown (0x%02x)"));
129
15
    offset += 1;
130
131
15
    proto_tree_add_item(bier_tree, hf_bier_bfir_id, tvb, offset, 2, ENC_BIG_ENDIAN);
132
15
    offset += 2;
133
134
15
    proto_tree_add_item(bier_tree, hf_bier_bitstring, tvb, offset, bitstring_length, ENC_NA);
135
15
    offset += bitstring_length;
136
137
15
    next_tvb = tvb_new_subset_remaining(tvb, offset);
138
    /* MPLS can carry BIER again; stop before the layer limit */
139
15
    if (wmem_list_count(pinfo->layers) + 16 >= prefs.gui_max_tree_depth) {
140
0
        proto_tree_add_expert_remaining(bier_tree, pinfo, &ei_bier_too_deep, next_tvb, 0);
141
0
        return tvb_captured_length(tvb);
142
0
    }
143
15
    if (!dissector_try_uint(bier_subdissector_table, proto, next_tvb, pinfo, tree)) {
144
2
        call_data_dissector(next_tvb, pinfo, tree);
145
2
    }
146
147
15
    return tvb_captured_length(tvb);
148
15
}
149
150
void
151
proto_register_bier(void)
152
16
{
153
16
    static hf_register_info hf[] = {
154
16
        {
155
16
            &hf_bier_nibble,
156
16
            {
157
16
                "Nibble", "bier.nibble", FT_UINT8,
158
16
                BASE_HEX, NULL, 0xF0, NULL, HFILL
159
16
            }
160
16
        },
161
16
        {
162
16
            &hf_bier_ver,
163
16
            {
164
16
                "Version", "bier.ver", FT_UINT8,
165
16
                BASE_DEC, NULL, 0x0F, NULL, HFILL
166
16
            }
167
16
        },
168
16
        {
169
16
            &hf_bier_bsl,
170
16
            {
171
16
                "BitString Length", "bier.bsl", FT_UINT8,
172
16
                BASE_DEC, VALS(bier_bsl_vals), 0xF0, NULL, HFILL
173
16
            }
174
16
        },
175
16
        {
176
16
            &hf_bier_entropy,
177
16
            {
178
16
                "Entropy", "bier.entropy", FT_UINT24,
179
16
                BASE_HEX, NULL, 0x0FFFFF, NULL, HFILL
180
16
            }
181
16
        },
182
16
        {
183
16
            &hf_bier_oam,
184
16
            {
185
16
                "OAM", "bier.oam", FT_UINT8,
186
16
                BASE_HEX, NULL, 0xC0, NULL, HFILL
187
16
            }
188
16
        },
189
16
        {
190
16
            &hf_bier_rsv,
191
16
            {
192
16
                "Rsv", "bier.rsv", FT_UINT8,
193
16
                BASE_HEX, NULL, 0x30, NULL, HFILL
194
16
            }
195
16
        },
196
16
        {
197
16
            &hf_bier_dscp,
198
16
            {
199
16
                "DSCP", "bier.dscp", FT_UINT16,
200
16
                BASE_HEX, NULL, 0x0FC0, NULL, HFILL
201
16
            }
202
16
        },
203
16
        {
204
16
            &hf_bier_proto,
205
16
            {
206
16
                "Next Protocol", "bier.proto", FT_UINT8,
207
16
                BASE_HEX, VALS(bier_proto_vals), 0x3F, NULL, HFILL
208
16
            }
209
16
        },
210
16
        {
211
16
            &hf_bier_bfir_id,
212
16
            {
213
16
                "BFIR-id", "bier.bfir-id", FT_UINT16,
214
16
                BASE_DEC, NULL, 0x0, NULL, HFILL
215
16
            }
216
16
        },
217
16
        {
218
16
            &hf_bier_bitstring,
219
16
            {
220
16
                "BitString", "bier.bitstring", FT_BYTES,
221
16
                BASE_NONE, NULL, 0x0, NULL, HFILL
222
16
            }
223
16
        },
224
16
    };
225
226
16
    static int *ett[] = {
227
16
        &ett_bier
228
16
    };
229
230
16
    static ei_register_info ei[] = {
231
16
        { &ei_bier_too_deep, { "bier.too_deep", PI_UNDECODED, PI_WARN, "Payload nested too deep, not dissected", EXPFILL }},
232
16
    };
233
234
16
    expert_module_t *expert_bier;
235
236
16
    proto_bier =
237
16
        proto_register_protocol("Bit Index Explicit Replication", "BIER", "bier");
238
239
16
    proto_register_field_array(proto_bier, hf, array_length(hf));
240
16
    proto_register_subtree_array(ett, array_length(ett));
241
16
    expert_bier = expert_register_protocol(proto_bier);
242
16
    expert_register_field_array(expert_bier, ei, array_length(ei));
243
16
    bier_handle = register_dissector_with_description("bier.mpls", "BIER encapsulated in MPLS", dissect_bier, proto_bier);
244
245
16
    bier_subdissector_table = register_dissector_table("bier.proto",
246
16
        "BIER Next Protocol", proto_bier, FT_UINT8, BASE_DEC);
247
16
}
248
249
void
250
proto_reg_handoff_bier(void)
251
16
{
252
16
    dissector_handle_t mpls_handle = find_dissector_add_dependency("mpls", proto_bier);
253
254
16
    dissector_add_for_decode_as("mpls.label", bier_handle);
255
256
16
    dissector_add_uint("mpls.pfn", 5, bier_handle);
257
258
16
    dissector_add_uint("bier.proto", 1, mpls_handle);
259
16
    dissector_add_uint("bier.proto", 2, mpls_handle);
260
16
    dissector_add_uint("bier.proto", 3, find_dissector_add_dependency("eth_maybefcs", proto_bier));
261
16
    dissector_add_uint("bier.proto", 4, find_dissector_add_dependency("ip", proto_bier));
262
    /* 5 is BIER OAM - https://datatracker.ietf.org/doc/draft-ietf-bier-ping/ */
263
16
    dissector_add_uint("bier.proto", 6, find_dissector_add_dependency("ipv6", proto_bier));
264
16
    dissector_add_uint("bier.proto", 7, find_dissector_add_dependency("vxlan", proto_bier));
265
16
    dissector_add_uint("bier.proto", 8, find_dissector_add_dependency("gre", proto_bier));
266
16
    dissector_add_uint("bier.proto", 9, find_dissector_add_dependency("geneve", proto_bier));
267
16
}