wireshark  2.2.0
About: Wireshark is a network protocol analyzer. It lets you capture and interactively browse the traffic running on a computer network.
  Fossies Dox: wireshark-2.2.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

packet-vxlan.c
Go to the documentation of this file.
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://www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-02.txt)
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27 
28 #include "config.h"
29 
30 #include <epan/packet.h>
31 #include <epan/tfs.h>
32 #include "packet-vxlan.h"
33 
34 #define UDP_PORT_VXLAN 4789
35 #define UDP_PORT_VXLAN_GPE 4790
36 
37 void proto_register_vxlan(void);
38 void proto_reg_handoff_vxlan(void);
39 
40 static int proto_vxlan = -1;
41 static int proto_vxlan_gpe = -1;
42 
43 static int hf_vxlan_flags = -1;
44 static int hf_vxlan_gpe_flags = -1;
45 static int hf_vxlan_flags_reserved = -1;
46 static int hf_vxlan_reserved_8 = -1;
47 static int hf_vxlan_flag_a = -1;
48 static int hf_vxlan_flag_d = -1;
49 static int hf_vxlan_flag_i = -1;
50 static int hf_vxlan_flag_g = -1;
51 static int hf_vxlan_gbp = -1;
52 static int hf_vxlan_vni = -1;
53 static int hf_vxlan_gpe_flag_i = -1;
54 static int hf_vxlan_gpe_flag_p = -1;
55 static int hf_vxlan_gpe_flag_o = -1;
56 static int hf_vxlan_gpe_flag_ver = -1;
57 static int hf_vxlan_gpe_flag_reserved = -1;
58 static int hf_vxlan_gpe_reserved_16 = -1;
59 static int hf_vxlan_next_proto = -1;
60 static int ett_vxlan = -1;
61 static int ett_vxlan_flags = -1;
62 
63 static const int *flags_fields[] = {
64  &hf_vxlan_flag_g,
65  &hf_vxlan_flag_d,
66  &hf_vxlan_flag_i,
67  &hf_vxlan_flag_a,
68  &hf_vxlan_flags_reserved,
69  NULL
70  };
71 
72 static const int *gpe_flags_fields[] = {
73  &hf_vxlan_gpe_flag_ver,
74  &hf_vxlan_gpe_flag_i,
75  &hf_vxlan_gpe_flag_p,
76  &hf_vxlan_gpe_flag_o,
77  &hf_vxlan_gpe_flag_reserved,
78  NULL
79 
80  };
81 
82 static const value_string vxlan_next_protocols[] = {
83  { VXLAN_IPV4, "IPv4" },
84  { VXLAN_IPV6, "IPv6" },
85  { VXLAN_ETHERNET, "Ethernet" },
86  { VXLAN_NSH, "Network Service Header" },
87  { VXLAN_MPLS, "MPLS"},
88  { 0, NULL }
89  };
90 
91 static dissector_handle_t eth_handle;
92 static dissector_table_t vxlan_dissector_table;
93 
94 static int
95 dissect_vxlan_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int is_gpe)
96 {
97  proto_tree *vxlan_tree;
98  proto_item *ti;
99  tvbuff_t *next_tvb;
100  int offset = 0;
101  guint32 vxlan_next_proto;
102 
103  col_set_str(pinfo->cinfo, COL_PROTOCOL, "VxLAN");
104  col_clear(pinfo->cinfo, COL_INFO);
105 
106 
107  ti = proto_tree_add_item(tree, proto_vxlan, tvb, offset, 8, ENC_NA);
108  vxlan_tree = proto_item_add_subtree(ti, ett_vxlan);
109 
110  if(is_gpe) {
111  proto_tree_add_bitmask(vxlan_tree, tvb, offset, hf_vxlan_gpe_flags, ett_vxlan_flags, gpe_flags_fields, ENC_BIG_ENDIAN);
112  offset += 1;
113 
114  proto_tree_add_item(vxlan_tree, hf_vxlan_gpe_reserved_16, tvb, offset, 2, ENC_BIG_ENDIAN);
115  offset += 2;
116 
117  proto_tree_add_item_ret_uint(vxlan_tree, hf_vxlan_next_proto, tvb, offset, 1, ENC_BIG_ENDIAN, &vxlan_next_proto);
118  offset += 1;
119  } else {
120  proto_tree_add_bitmask(vxlan_tree, tvb, offset, hf_vxlan_flags, ett_vxlan_flags, flags_fields, ENC_BIG_ENDIAN);
121  offset += 2;
122 
123  proto_tree_add_item(vxlan_tree, hf_vxlan_gbp, tvb, offset, 2, ENC_BIG_ENDIAN);
124  offset += 2;
125  }
126 
127  proto_tree_add_item(vxlan_tree, hf_vxlan_vni, tvb, offset, 3, ENC_BIG_ENDIAN);
128  offset += 3;
129 
130  proto_tree_add_item(vxlan_tree, hf_vxlan_reserved_8, tvb, offset, 1, ENC_BIG_ENDIAN);
131  offset += 1;
132 
133  next_tvb = tvb_new_subset_remaining(tvb, offset);
134 
135  if(is_gpe){
136  if(!dissector_try_uint(vxlan_dissector_table, vxlan_next_proto, next_tvb, pinfo, tree)) {
137  call_data_dissector(next_tvb, pinfo, vxlan_tree);
138  }
139  } else {
140  call_dissector(eth_handle, next_tvb, pinfo, tree);
141  }
142 
143  return tvb_captured_length(tvb);
144 }
145 
146 static int
147 dissect_vxlan_gpe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
148 {
149  return dissect_vxlan_common(tvb, pinfo, tree, TRUE);
150 }
151 
152 
153 static int
154 dissect_vxlan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
155 {
156  return dissect_vxlan_common(tvb, pinfo, tree, FALSE);
157 }
158 
159 
160 
161 
162 /* Register VxLAN with Wireshark */
163 void
165 {
166  static hf_register_info hf[] = {
167  { &hf_vxlan_flags,
168  { "Flags", "vxlan.flags",
169  FT_UINT16, BASE_HEX, NULL, 0x00,
170  NULL, HFILL
171  },
172  },
173  { &hf_vxlan_gpe_flags,
174  { "Flags", "vxlan.flags",
175  FT_UINT8, BASE_HEX, NULL, 0x00,
176  NULL, HFILL
177  },
178  },
179  { &hf_vxlan_flags_reserved,
180  { "Reserved(R)", "vxlan.flags_reserved",
181  FT_BOOLEAN, 16, NULL, 0x77b7,
182  NULL, HFILL,
183  },
184  },
185  { &hf_vxlan_gpe_flag_reserved,
186  { "Reserved(R)", "vxlan.flags_reserved",
187  FT_UINT8, BASE_DEC, NULL, 0xC2,
188  NULL, HFILL,
189  },
190  },
191  { &hf_vxlan_flag_g,
192  { "GBP Extension", "vxlan.flag_g",
193  FT_BOOLEAN, 16, TFS(&tfs_defined_not_defined), 0x8000,
194  NULL, HFILL,
195  },
196  },
197  { &hf_vxlan_flag_i,
198  { "VXLAN Network ID (VNI)", "vxlan.flag_i",
199  FT_BOOLEAN, 16, NULL, 0x0800,
200  NULL, HFILL,
201  },
202  },
203  { &hf_vxlan_flag_d,
204  { "Don't Learn", "vxlan.flag_d",
205  FT_BOOLEAN, 16, NULL, 0x0040,
206  NULL, HFILL,
207  },
208  },
209  { &hf_vxlan_flag_a,
210  { "Policy Applied", "vxlan.flag_a",
211  FT_BOOLEAN, 16, NULL, 0x0008,
212  NULL, HFILL,
213  },
214  },
215  { &hf_vxlan_gpe_flag_ver,
216  { "Version", "vxlan.ver",
217  FT_UINT8, BASE_DEC, NULL, 0x30,
218  NULL, HFILL,
219  },
220  },
221  { &hf_vxlan_gpe_flag_i,
222  { "Instance", "vxlan.i_bit",
223  FT_UINT8, BASE_DEC, NULL, 0x08,
224  NULL, HFILL,
225  },
226  },
227  { &hf_vxlan_gpe_flag_p,
228  { "Next Protocol Bit", "vxlan.p_bit",
229  FT_UINT8, BASE_DEC, NULL, 0x04,
230  NULL, HFILL,
231  },
232  },
233  { &hf_vxlan_gpe_flag_o,
234  { "OAM bit", "vxlan.o_bit",
235  FT_UINT8, BASE_DEC, NULL, 0x01,
236  NULL, HFILL,
237  },
238  },
239  { &hf_vxlan_gbp,
240  { "Group Policy ID", "vxlan.gbp",
241  FT_UINT16, BASE_DEC, NULL, 0x00,
242  NULL, HFILL
243  },
244  },
245  { &hf_vxlan_vni,
246  { "VXLAN Network Identifier (VNI)", "vxlan.vni",
247  FT_UINT24, BASE_DEC, NULL, 0x00,
248  NULL, HFILL
249  },
250  },
251  { &hf_vxlan_reserved_8,
252  { "Reserved", "vxlan.reserved8",
253  FT_UINT8, BASE_DEC, NULL, 0x00,
254  NULL, HFILL
255  },
256  },
257  { &hf_vxlan_gpe_reserved_16,
258  { "Reserved", "vxlan.reserved_16",
259  FT_UINT16, BASE_DEC, NULL, 0x0000,
260  NULL, HFILL
261  },
262  },
263  { &hf_vxlan_next_proto,
264  { "Next Protocol", "vxlan.next_proto",
265  FT_UINT8, BASE_DEC, VALS(vxlan_next_protocols), 0x00,
266  NULL, HFILL
267  },
268  },
269  };
270 
271  /* Setup protocol subtree array */
272  static gint *ett[] = {
273  &ett_vxlan,
274  &ett_vxlan_flags,
275  };
276 
277  /* Register the protocol name and description */
278  proto_vxlan = proto_register_protocol("Virtual eXtensible Local Area Network", "VXLAN", "vxlan");
279 
280  /* Protocol registered just for Decode As */
281  proto_vxlan_gpe = proto_register_protocol("Virtual eXtensible Local Area Network (GPE)", "VXLAN (GPE)", "vxlan_gpe");
282 
283  /* Required function calls to register the header fields and subtrees used */
284  proto_register_field_array(proto_vxlan, hf, array_length(hf));
286  vxlan_dissector_table = register_dissector_table("vxlan.next_proto", "VXLAN Next Protocol", proto_vxlan, FT_UINT8, BASE_DEC);
287 
288 
289 }
290 
291 void
293 {
294  dissector_handle_t vxlan_handle;
295  dissector_handle_t vxlan_gpe_handle;
296 
297  /*
298  * RFC 7348 Figures 1 and 2, in the Payload section, say
299  *
300  * "(Note that the original Ethernet Frame's FCS is not included)"
301  *
302  * meaning that the inner Ethernet frame does *not* include an
303  * FCS.
304  */
305  eth_handle = find_dissector_add_dependency("eth_withoutfcs", proto_vxlan);
306 
307  vxlan_handle = create_dissector_handle(dissect_vxlan, proto_vxlan);
308  vxlan_gpe_handle = create_dissector_handle(dissect_vxlan_gpe, proto_vxlan_gpe);
309  dissector_add_uint("udp.port", UDP_PORT_VXLAN, vxlan_handle);
310  dissector_add_uint("udp.port", UDP_PORT_VXLAN_GPE, vxlan_gpe_handle);
311 }
312 
313 /*
314  * Editor modelines - http://www.wireshark.org/tools/modelines.html
315  *
316  * Local variables:
317  * c-basic-offset: 4
318  * tab-width: 8
319  * indent-tabs-mode: nil
320  * End:
321  *
322  * vi: set shiftwidth=4 tabstop=8 expandtab:
323  * :indentSize=4:tabSize=8:noTabs=true:
324  */
#define VXLAN_NSH
Definition: packet-vxlan.h:34
proto_item * proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start, gint length, const guint encoding)
Definition: proto.c:2524
void col_set_str(column_info *cinfo, const gint el, const gchar *str)
Definition: column-utils.c:672
#define TFS(x)
Definition: proto.h:85
proto_item * proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset, const int hf_hdr, const gint ett, const int **fields, const guint encoding)
Definition: proto.c:9081
#define UDP_PORT_VXLAN
Definition: packet-vxlan.c:34
void proto_register_subtree_array(gint *const *indices, const int num_indices)
Definition: proto.c:6901
void proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
Definition: proto.c:6130
const true_false_string tfs_defined_not_defined
Definition: tfs.c:91
dissector_handle_t find_dissector_add_dependency(const char *name, const int parent_proto)
Definition: packet.c:2673
tvbuff_t guint32 packet_info *pinfo _U_
Definition: packet-wsp.c:2844
#define NULL
Definition: resample.c:91
proto_item * proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start, gint length, const guint encoding, guint32 *retval)
Definition: proto.c:2339
#define TRUE
void proto_reg_handoff_vxlan(void)
Definition: packet-vxlan.c:292
#define UDP_PORT_VXLAN_GPE
Definition: packet-vxlan.c:35
struct epan_column_info * cinfo
Definition: packet_info.h:56
#define VXLAN_ETHERNET
Definition: packet-vxlan.h:33
#define VXLAN_MPLS
Definition: packet-vxlan.h:35
const char * data
Definition: packet-ntp.c:190
proto_tree * proto_item_add_subtree(proto_item *pi, const gint idx)
Definition: proto.c:5501
void dissector_add_uint(const char *name, const guint32 pattern, dissector_handle_t handle)
Definition: packet.c:914
dissector_handle_t create_dissector_handle(dissector_t dissector, const int proto)
Definition: packet.c:2696
#define FALSE
void proto_register_vxlan(void)
Definition: packet-vxlan.c:164
proto_item * ti
Definition: packet-wsp.c:2848
WS_DLL_PUBLIC tvbuff_t * tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
#define VALS(x)
Definition: proto.h:76
int call_data_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
Definition: packet.c:2837
void col_clear(column_info *cinfo, const gint el)
Definition: column-utils.c:268
#define ENC_NA
Definition: proto.h:452
dissector_table_t register_dissector_table(const char *name, const char *ui_name, const int proto, const ftenum_t type, const int param)
Definition: packet.c:2114
#define array_length(x)
#define VXLAN_IPV6
Definition: packet-vxlan.h:32
int dissector_try_uint(dissector_table_t sub_dissectors, const guint32 uint_val, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
Definition: packet.c:1210
guint tvb_captured_length(const tvbuff_t *tvb)
Definition: tvbuff.c:421
#define HFILL
Definition: proto.h:593
int call_dissector(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
Definition: packet.c:2830
#define VXLAN_IPV4
Definition: packet-vxlan.h:31
tvbuff_t * tvb
Definition: packet-wsp.c:2843
int proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
Definition: proto.c:5653
#define ENC_BIG_ENDIAN
Definition: proto.h:356