Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-vxlan.c
Line
Count
Source
1
/* packet-vxlan.c
2
 *
3
 * Routines for Virtual eXtensible Local Area Network (VXLAN) packet dissection
4
 * RFC 7348 plus draft-smith-vxlan-group-policy-01
5
 *
6
 * (c) Copyright 2016, Sumit Kumar Jha <sjha3@ncsu.edu>
7
 * Support for VXLAN GPE (https://datatracker.ietf.org/doc/html/draft-ietf-nvo3-vxlan-gpe-02)
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
16
#include "config.h"
17
18
#include <epan/packet.h>
19
#include <epan/tfs.h>
20
#include "packet-vxlan.h"
21
22
14
#define UDP_PORT_VXLAN  "4789,8472" /* The IANA assigned port is 4789, but Linux default is 8472 for compatibility with early adopters */
23
14
#define UDP_PORT_VXLAN_GPE  4790
24
25
void proto_register_vxlan(void);
26
void proto_reg_handoff_vxlan(void);
27
28
static dissector_handle_t vxlan_handle;
29
static dissector_handle_t vxlan_gpe_handle;
30
31
static int proto_vxlan;
32
static int proto_vxlan_gpe;
33
34
static int hf_vxlan_flags;
35
static int hf_vxlan_gpe_flags;
36
static int hf_vxlan_flags_reserved;
37
static int hf_vxlan_reserved_8;
38
static int hf_vxlan_flag_a;
39
static int hf_vxlan_flag_d;
40
static int hf_vxlan_flag_i;
41
static int hf_vxlan_flag_g;
42
static int hf_vxlan_gbp;
43
static int hf_vxlan_vni;
44
static int hf_vxlan_gpe_flag_i;
45
static int hf_vxlan_gpe_flag_p;
46
static int hf_vxlan_gpe_flag_o;
47
static int hf_vxlan_gpe_flag_ver;
48
static int hf_vxlan_gpe_flag_reserved;
49
static int hf_vxlan_gpe_reserved_16;
50
static int hf_vxlan_next_proto;
51
static int ett_vxlan;
52
static int ett_vxlan_flags;
53
54
static int * const flags_fields[] = {
55
        &hf_vxlan_flag_g,
56
        &hf_vxlan_flag_i,
57
        &hf_vxlan_flag_d,
58
        &hf_vxlan_flag_a,
59
        &hf_vxlan_flags_reserved,
60
        NULL
61
    };
62
63
static int * const gpe_flags_fields[] = {
64
        &hf_vxlan_gpe_flag_ver,
65
        &hf_vxlan_gpe_flag_i,
66
        &hf_vxlan_gpe_flag_p,
67
        &hf_vxlan_gpe_flag_o,
68
        &hf_vxlan_gpe_flag_reserved,
69
        NULL
70
71
   };
72
73
static const value_string vxlan_next_protocols[] = {
74
        { VXLAN_IPV4, "IPv4" },
75
        { VXLAN_IPV6, "IPv6" },
76
        { VXLAN_ETHERNET, "Ethernet" },
77
        { VXLAN_NSH, "Network Service Header" },
78
        { VXLAN_MPLS, "MPLS"},
79
        { 0, NULL }
80
 };
81
82
static dissector_handle_t eth_handle;
83
static dissector_table_t vxlan_dissector_table;
84
85
static int
86
dissect_vxlan_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int is_gpe)
87
137
{
88
137
    proto_tree *vxlan_tree;
89
137
    proto_item *ti;
90
137
    tvbuff_t *next_tvb;
91
137
    int offset = 0;
92
137
    uint32_t vxlan_next_proto;
93
94
137
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "VxLAN");
95
137
    col_clear(pinfo->cinfo, COL_INFO);
96
97
98
137
    ti = proto_tree_add_item(tree, proto_vxlan, tvb, offset, 8, ENC_NA);
99
137
    vxlan_tree = proto_item_add_subtree(ti, ett_vxlan);
100
101
137
    if(is_gpe) {
102
109
        proto_tree_add_bitmask(vxlan_tree, tvb, offset, hf_vxlan_gpe_flags, ett_vxlan_flags, gpe_flags_fields, ENC_BIG_ENDIAN);
103
109
        offset += 1;
104
105
109
        proto_tree_add_item(vxlan_tree, hf_vxlan_gpe_reserved_16, tvb, offset, 2, ENC_BIG_ENDIAN);
106
109
        offset += 2;
107
108
109
        proto_tree_add_item_ret_uint(vxlan_tree, hf_vxlan_next_proto, tvb, offset, 1, ENC_BIG_ENDIAN, &vxlan_next_proto);
109
109
        offset += 1;
110
109
    } else {
111
28
        proto_tree_add_bitmask(vxlan_tree, tvb, offset, hf_vxlan_flags, ett_vxlan_flags, flags_fields, ENC_BIG_ENDIAN);
112
28
        offset += 2;
113
114
28
        proto_tree_add_item(vxlan_tree, hf_vxlan_gbp, tvb, offset, 2, ENC_BIG_ENDIAN);
115
28
        offset += 2;
116
28
    }
117
118
137
    proto_tree_add_item(vxlan_tree, hf_vxlan_vni, tvb, offset, 3, ENC_BIG_ENDIAN);
119
137
    offset += 3;
120
121
137
    proto_tree_add_item(vxlan_tree, hf_vxlan_reserved_8, tvb, offset, 1, ENC_BIG_ENDIAN);
122
137
    offset += 1;
123
124
137
    next_tvb = tvb_new_subset_remaining(tvb, offset);
125
126
137
    if(is_gpe){
127
109
        if(!dissector_try_uint(vxlan_dissector_table, vxlan_next_proto, next_tvb, pinfo, tree)) {
128
1
            call_data_dissector(next_tvb, pinfo, tree);
129
1
        }
130
109
    } else {
131
28
        call_dissector(eth_handle, next_tvb, pinfo, tree);
132
28
    }
133
134
137
    return tvb_captured_length(tvb);
135
137
}
136
137
static int
138
dissect_vxlan_gpe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
139
109
{
140
109
    return dissect_vxlan_common(tvb, pinfo, tree, true);
141
109
}
142
143
144
static int
145
dissect_vxlan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
146
28
{
147
28
    return dissect_vxlan_common(tvb, pinfo, tree, false);
148
28
}
149
150
151
152
153
/* Register VxLAN with Wireshark */
154
void
155
proto_register_vxlan(void)
156
14
{
157
14
    static hf_register_info hf[] = {
158
14
        { &hf_vxlan_flags,
159
14
          { "Flags", "vxlan.flags",
160
14
            FT_UINT16, BASE_HEX, NULL, 0x00,
161
14
            NULL, HFILL
162
14
          },
163
14
        },
164
14
        { &hf_vxlan_gpe_flags,
165
14
          { "Flags", "vxlan.flags",
166
14
            FT_UINT8, BASE_HEX, NULL, 0x00,
167
14
            NULL, HFILL
168
14
          },
169
14
        },
170
14
        { &hf_vxlan_flags_reserved,
171
14
          { "Reserved(R)", "vxlan.flags_reserved",
172
14
            FT_UINT16, BASE_HEX, NULL, 0x77b7,
173
14
            NULL, HFILL,
174
14
          },
175
14
        },
176
14
        { &hf_vxlan_gpe_flag_reserved,
177
14
          { "Reserved(R)", "vxlan.flags_reserved",
178
14
            FT_UINT8, BASE_DEC, NULL, 0xC2,
179
14
            NULL, HFILL,
180
14
          },
181
14
        },
182
14
        { &hf_vxlan_flag_g,
183
14
          { "GBP Extension", "vxlan.flag_g",
184
14
            FT_BOOLEAN, 16, TFS(&tfs_defined_not_defined), 0x8000,
185
14
            NULL, HFILL,
186
14
          },
187
14
        },
188
14
        { &hf_vxlan_flag_i,
189
14
          { "VXLAN Network ID (VNI)", "vxlan.flag_i",
190
14
            FT_BOOLEAN, 16, NULL, 0x0800,
191
14
            NULL, HFILL,
192
14
          },
193
14
        },
194
14
        { &hf_vxlan_flag_d,
195
14
          { "Don't Learn", "vxlan.flag_d",
196
14
            FT_BOOLEAN, 16, NULL, 0x0040,
197
14
            NULL, HFILL,
198
14
          },
199
14
        },
200
14
        { &hf_vxlan_flag_a,
201
14
          { "Policy Applied", "vxlan.flag_a",
202
14
            FT_BOOLEAN, 16, NULL, 0x0008,
203
14
            NULL, HFILL,
204
14
          },
205
14
        },
206
14
        { &hf_vxlan_gpe_flag_ver,
207
14
          { "Version", "vxlan.ver",
208
14
            FT_UINT8, BASE_DEC, NULL, 0x30,
209
14
            NULL, HFILL,
210
14
          },
211
14
        },
212
14
        { &hf_vxlan_gpe_flag_i,
213
14
          { "Instance", "vxlan.i_bit",
214
14
            FT_UINT8, BASE_DEC, NULL, 0x08,
215
14
            NULL, HFILL,
216
14
          },
217
14
        },
218
14
        { &hf_vxlan_gpe_flag_p,
219
14
          { "Next Protocol Bit", "vxlan.p_bit",
220
14
            FT_UINT8, BASE_DEC, NULL, 0x04,
221
14
            NULL, HFILL,
222
14
          },
223
14
        },
224
14
        { &hf_vxlan_gpe_flag_o,
225
14
          { "OAM bit", "vxlan.o_bit",
226
14
            FT_UINT8, BASE_DEC, NULL, 0x01,
227
14
            NULL, HFILL,
228
14
          },
229
14
        },
230
14
        { &hf_vxlan_gbp,
231
14
          { "Group Policy ID", "vxlan.gbp",
232
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
233
14
            NULL, HFILL
234
14
          },
235
14
        },
236
14
        { &hf_vxlan_vni,
237
14
          { "VXLAN Network Identifier (VNI)", "vxlan.vni",
238
14
            FT_UINT24, BASE_DEC, NULL, 0x0,
239
14
            NULL, HFILL
240
14
          },
241
14
        },
242
14
        { &hf_vxlan_reserved_8,
243
14
          { "Reserved", "vxlan.reserved8",
244
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
245
14
            NULL, HFILL
246
14
          },
247
14
        },
248
14
        { &hf_vxlan_gpe_reserved_16,
249
14
          { "Reserved", "vxlan.reserved_16",
250
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
251
14
            NULL, HFILL
252
14
          },
253
14
        },
254
14
        { &hf_vxlan_next_proto,
255
14
          { "Next Protocol", "vxlan.next_proto",
256
14
            FT_UINT8, BASE_DEC, VALS(vxlan_next_protocols), 0x0,
257
14
            NULL, HFILL
258
14
          },
259
14
        },
260
14
    };
261
262
    /* Setup protocol subtree array */
263
14
    static int *ett[] = {
264
14
        &ett_vxlan,
265
14
        &ett_vxlan_flags,
266
14
    };
267
268
    /* Register the protocol name and description */
269
14
    proto_vxlan = proto_register_protocol("Virtual eXtensible Local Area Network", "VXLAN", "vxlan");
270
271
    /* Protocol registered just for Decode As */
272
14
    proto_vxlan_gpe = proto_register_protocol_in_name_only("Virtual eXtensible Local Area Network (GPE)", "VXLAN (GPE)", "vxlan_gpe", proto_vxlan, FT_PROTOCOL);
273
274
    /* Required function calls to register the header fields and subtrees used */
275
14
    proto_register_field_array(proto_vxlan, hf, array_length(hf));
276
14
    proto_register_subtree_array(ett, array_length(ett));
277
14
    vxlan_dissector_table = register_dissector_table("vxlan.next_proto", "VXLAN Next Protocol", proto_vxlan, FT_UINT8, BASE_DEC);
278
279
    /* Register dissector handles */
280
14
    vxlan_handle = register_dissector("vxlan", dissect_vxlan, proto_vxlan);
281
14
    vxlan_gpe_handle = register_dissector("vxlan_gpe", dissect_vxlan_gpe, proto_vxlan_gpe);
282
14
}
283
284
void
285
proto_reg_handoff_vxlan(void)
286
14
{
287
    /*
288
     * RFC 7348 Figures 1 and 2, in the Payload section, say
289
     *
290
     * "(Note that the original Ethernet Frame's FCS is not included)"
291
     *
292
     * meaning that the inner Ethernet frame does *not* include an
293
     * FCS.
294
     */
295
14
    eth_handle = find_dissector_add_dependency("eth_withoutfcs", proto_vxlan);
296
297
14
    dissector_add_uint_range_with_preference("udp.port", UDP_PORT_VXLAN, vxlan_handle);
298
14
    dissector_add_uint_with_preference("udp.port", UDP_PORT_VXLAN_GPE, vxlan_gpe_handle);
299
14
}
300
301
/*
302
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
303
 *
304
 * Local variables:
305
 * c-basic-offset: 4
306
 * tab-width: 8
307
 * indent-tabs-mode: nil
308
 * End:
309
 *
310
 * vi: set shiftwidth=4 tabstop=8 expandtab:
311
 * :indentSize=4:tabSize=8:noTabs=true:
312
 */