Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-vlan.c
bloba599934eab30b9f1e319105f9cba605139aab751
1 /* packet-vlan.c
2 * Routines for VLAN 802.1Q ethernet header disassembly
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 #include "config.h"
12 #include <epan/packet.h>
13 #include <epan/capture_dissectors.h>
14 #include <wsutil/pint.h>
15 #include <epan/expert.h>
16 #include "packet-ieee8023.h"
17 #include <epan/etypes.h>
18 #include <epan/prefs.h>
19 #include <epan/to_str.h>
20 #include <epan/addr_resolv.h>
21 #include <epan/proto_data.h>
22 #include <epan/conversation_table.h>
23 #include <epan/tfs.h>
24 #include <wsutil/array.h>
26 void proto_register_vlan(void);
27 void proto_reg_handoff_vlan(void);
29 static unsigned int q_in_q_ethertype = ETHERTYPE_QINQ_OLD;
31 static bool vlan_summary_in_tree = true;
33 enum version_value {
34 IEEE_8021Q_1998,
35 IEEE_8021Q_2005,
36 IEEE_8021Q_2011
39 static int vlan_version = (int)IEEE_8021Q_2011;
41 enum priority_drop_value {
42 Priority_Drop_8P0D,
43 Priority_Drop_7P1D,
44 Priority_Drop_6P2D,
45 Priority_Drop_5P3D,
48 static int vlan_priority_drop = (int)Priority_Drop_8P0D;
50 static dissector_handle_t vlan_handle;
51 static dissector_handle_t ethertype_handle;
53 static capture_dissector_handle_t llc_cap_handle;
54 static capture_dissector_handle_t ipx_cap_handle;
56 static int proto_vlan;
58 static int hf_vlan_cfi;
59 static int hf_vlan_dei;
60 static int hf_vlan_etype;
61 static int hf_vlan_id;
62 static int hf_vlan_id_name;
63 static int hf_vlan_len;
64 static int hf_vlan_priority;
65 static int hf_vlan_priority_5;
66 static int hf_vlan_priority_6;
67 static int hf_vlan_priority_7;
68 static int hf_vlan_priority_old;
69 static int hf_vlan_trailer;
71 static int ett_vlan;
73 static expert_field ei_vlan_len;
74 static expert_field ei_vlan_too_many_tags;
76 /* From Table G-2 of IEEE standard 802.1D-2004 */
77 /* Note that 0 is the default priority, but is above 1 and 2.
78 * Priority order from lowest to highest is 1,2,0,3,4,5,6,7 */
79 static const value_string pri_vals_old[] = {
80 { 0, "Best Effort (default)" },
81 { 1, "Background" },
82 { 2, "Spare" },
83 { 3, "Excellent Effort" },
84 { 4, "Controlled Load" },
85 { 5, "Video, < 100ms latency and jitter" },
86 { 6, "Voice, < 10ms latency and jitter" },
87 { 7, "Network Control" },
88 { 0, NULL }
91 /* From Table G-2 of IEEE standard 802.1Q-2005 (and I-2 of 2011 and 2014 revisions) */
92 /* Note that 0 is still the default, but priority 2 was moved from below 0 to
93 * above it. The new order from lowest to highest is 1,0,2,3,4,5,6,7 */
94 static const value_string pri_vals[] = {
95 { 0, "Best Effort (default)" },
96 { 1, "Background" },
97 { 2, "Excellent Effort" },
98 { 3, "Critical Applications" },
99 { 4, "Video, < 100ms latency and jitter" },
100 { 5, "Voice, < 10ms latency and jitter" },
101 { 6, "Internetwork Control" },
102 { 7, "Network Control" },
103 { 0, NULL }
106 /* From Tables G-2,3 of IEEE standard 802.1Q-2005 (and I-2,3,7 of 2011 and 2014 revisions) */
107 static const value_string pri_vals_7[] = {
108 { 0, "Best Effort (default)" },
109 { 1, "Background" },
110 { 2, "Excellent Effort" },
111 { 3, "Critical Applications" },
112 { 4, "Voice, < 10ms latency and jitter, Drop Eligible" },
113 { 5, "Voice, < 10ms latency and jitter" },
114 { 6, "Internetwork Control" },
115 { 7, "Network Control" },
116 { 0, NULL }
119 /* From Tables G-2,3 of IEEE standard 802.1Q-2005 (and I-2,3,7 of 2011 and 2015 revisions) */
120 static const value_string pri_vals_6[] = {
121 { 0, "Best Effort (default)" },
122 { 1, "Background" },
123 { 2, "Critical Applications, Drop Eligible" },
124 { 3, "Critical Applications" },
125 { 4, "Voice, < 10ms latency and jitter, Drop Eligible" },
126 { 5, "Voice, < 10ms latency and jitter" },
127 { 6, "Internetwork Control" },
128 { 7, "Network Control" },
129 { 0, NULL }
132 /* From Tables G-2,3 of IEEE standard 802.1Q-2005 (and I-2,3,7 of 2011 and 2015 revisions) */
133 static const value_string pri_vals_5[] = {
134 { 0, "Best Effort (default), Drop Eligible" },
135 { 1, "Best Effort (default)" },
136 { 2, "Critical Applications, Drop Eligible" },
137 { 3, "Critical Applications" },
138 { 4, "Voice, < 10ms latency and jitter, Drop Eligible" },
139 { 5, "Voice, < 10ms latency and jitter" },
140 { 6, "Internetwork Control" },
141 { 7, "Network Control" },
142 { 0, NULL }
145 /* True is non-canonical (i.e., bit-reversed MACs like Token Ring) since usually 0 and canonical. */
146 static const true_false_string tfs_noncanonical_canonical = { "Non-canonical", "Canonical" };
148 static const true_false_string tfs_eligible_ineligible = { "Eligible", "Ineligible" };
150 #define VLAN_MAX_NESTED_TAGS 20
152 static bool
153 capture_vlan(const unsigned char *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_ ) {
154 uint16_t encap_proto;
155 if ( !BYTES_ARE_IN_FRAME(offset,len,5) )
156 return false;
158 encap_proto = pntoh16( &pd[offset+2] );
159 if ( encap_proto <= IEEE_802_3_MAX_LEN) {
160 if ( pd[offset+4] == 0xff && pd[offset+5] == 0xff ) {
161 return call_capture_dissector(ipx_cap_handle, pd,offset+4,len, cpinfo, pseudo_header);
162 } else {
163 return call_capture_dissector(llc_cap_handle, pd,offset+4,len, cpinfo, pseudo_header);
167 return try_capture_dissector("ethertype", encap_proto, pd, offset+4, len, cpinfo, pseudo_header);
170 static void
171 columns_set_vlan(column_info *cinfo, uint16_t tci)
173 char id_str[16];
175 uint32_to_str_buf(tci & 0xFFF, id_str, sizeof(id_str));
177 if (vlan_version < IEEE_8021Q_2011) {
178 col_add_fstr(cinfo, COL_INFO,
179 "PRI: %d CFI: %d ID: %s",
180 (tci >> 13), ((tci >> 12) & 1), id_str);
181 } else {
182 col_add_fstr(cinfo, COL_INFO,
183 "PRI: %d DEI: %d ID: %s",
184 (tci >> 13), ((tci >> 12) & 1), id_str);
188 static int
189 dissect_vlan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
191 proto_item *ti;
192 uint16_t tci, vlan_id;
193 uint16_t encap_proto;
194 bool is_802_2;
195 proto_tree *vlan_tree;
196 proto_item *item;
197 unsigned vlan_nested_count;
198 int hf1, hf2;
200 int * const flags[] = {
201 &hf1,
202 &hf2,
203 &hf_vlan_id,
204 NULL
207 col_set_str(pinfo->cinfo, COL_PROTOCOL, "VLAN");
208 col_clear(pinfo->cinfo, COL_INFO);
210 tci = tvb_get_ntohs( tvb, 0 );
211 vlan_id = tci & 0xFFF;
212 /* Add the VLAN Id if it's the first one*/
213 if (pinfo->vlan_id == 0) {
214 pinfo->vlan_id = vlan_id;
217 columns_set_vlan(pinfo->cinfo, tci);
219 vlan_tree = NULL;
221 ti = proto_tree_add_item(tree, proto_vlan, tvb, 0, 4, ENC_NA);
222 vlan_nested_count = p_get_proto_depth(pinfo, proto_vlan);
223 if (++vlan_nested_count > VLAN_MAX_NESTED_TAGS) {
224 expert_add_info(pinfo, ti, &ei_vlan_too_many_tags);
225 return tvb_captured_length(tvb);
227 p_set_proto_depth(pinfo, proto_vlan, vlan_nested_count);
229 if (tree) {
231 if (vlan_summary_in_tree) {
232 if (vlan_version < IEEE_8021Q_2011) {
233 proto_item_append_text(ti, ", PRI: %u, CFI: %u, ID: %u",
234 (tci >> 13), ((tci >> 12) & 1), vlan_id);
235 } else {
236 proto_item_append_text(ti, ", PRI: %u, DEI: %u, ID: %u",
237 (tci >> 13), ((tci >> 12) & 1), vlan_id);
241 vlan_tree = proto_item_add_subtree(ti, ett_vlan);
243 if (vlan_version == IEEE_8021Q_1998) {
244 hf1 = hf_vlan_priority_old;
245 hf2 = hf_vlan_cfi;
246 } else {
247 switch (vlan_priority_drop) {
249 case Priority_Drop_8P0D:
250 hf1 = hf_vlan_priority;
251 break;
253 case Priority_Drop_7P1D:
254 hf1 = hf_vlan_priority_7;
255 break;
257 case Priority_Drop_6P2D:
258 hf1 = hf_vlan_priority_6;
259 break;
261 case Priority_Drop_5P3D:
262 hf1 = hf_vlan_priority_5;
263 break;
265 if (vlan_version == IEEE_8021Q_2005) {
266 hf2 = hf_vlan_cfi;
267 } else {
268 hf2 = hf_vlan_dei;
272 proto_tree_add_bitmask_list(vlan_tree, tvb, 0, 2, flags, ENC_BIG_ENDIAN);
274 if (gbl_resolv_flags.vlan_name) {
275 item = proto_tree_add_string(vlan_tree, hf_vlan_id_name, tvb, 0, 2,
276 get_vlan_name(pinfo->pool, vlan_id));
277 proto_item_set_generated(item);
281 /* TODO: If the CFI is set on Ethernet (or FDDI MAC and not source routed,
282 * i.e. the RII bit in the source MAC address is 0, then a E-RIF follows.
283 * Only true before version 2011 since the CFI was replaced with DEI
284 * (Since who needs VLANs that bridge Token Ring and FDDI these days?) */
287 encap_proto = tvb_get_ntohs(tvb, 2);
288 if (encap_proto <= IEEE_802_3_MAX_LEN) {
289 /* Is there an 802.2 layer? I can tell by looking at the first 2
290 bytes after the VLAN header. If they are 0xffff, then what
291 follows the VLAN header is an IPX payload, meaning no 802.2.
292 (IPX/SPX is they only thing that can be contained inside a
293 straight 802.3 packet, so presumably the same applies for
294 Ethernet VLAN packets). A non-0xffff value means that there's an
295 802.2 layer inside the VLAN layer */
296 is_802_2 = true;
298 /* Don't throw an exception for this check (even a BoundsError) */
299 if (tvb_captured_length_remaining(tvb, 4) >= 2) {
300 if (tvb_get_ntohs(tvb, 4) == 0xffff) {
301 is_802_2 = false;
305 dissect_802_3(encap_proto, is_802_2, tvb, 4, pinfo, tree, vlan_tree,
306 hf_vlan_len, hf_vlan_trailer, &ei_vlan_len, 0);
307 } else {
308 ethertype_data_t ethertype_data;
310 proto_tree_add_uint(vlan_tree, hf_vlan_etype, tvb, 2, 2, encap_proto);
312 ethertype_data.etype = encap_proto;
313 ethertype_data.payload_offset = 4;
314 ethertype_data.fh_tree = vlan_tree;
315 ethertype_data.trailer_id = hf_vlan_trailer;
316 ethertype_data.fcs_len = 0;
318 /* deinterlacing requested */
319 if(prefs.conversation_deinterlacing_key>0) {
320 conversation_t *conv;
321 unsigned conv_type;
322 uint32_t dtlc_iface = 0;
323 uint32_t dtlc_vlan = 0;
325 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_INTERFACE &&
326 pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) {
328 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN &&
329 pinfo->vlan_id>0) {
331 conv_type = CONVERSATION_ETH_IV;
332 dtlc_iface = pinfo->rec->rec_header.packet_header.interface_id;
333 dtlc_vlan = pinfo->vlan_id;
335 /* look for existing conv, create one if none found */
336 conv = find_conversation_deinterlacer(pinfo->num, &pinfo->src, &pinfo->dst, conv_type,
337 dtlc_iface, dtlc_vlan, 0);
339 if(!conv) {
340 /* ETH _IN moulting into _IV */
341 conversation_new_deinterlacer(pinfo->num, &pinfo->src, &pinfo->dst,
342 conv_type, dtlc_iface, pinfo->vlan_id, 0);
345 // else : vlan id == 0, such thing is not expected
347 else {
348 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN &&
349 pinfo->vlan_id>0) {
351 conv_type = CONVERSATION_ETH_NV;
353 /* look for existing conv, create one if none found */
354 conv = find_conversation_deinterlacer(pinfo->num, &pinfo->src, &pinfo->dst, conv_type,
355 dtlc_iface, pinfo->vlan_id, 0);
357 if(!conv) {
358 /* ETH _NN moulting into _NV */
359 conversation_new_deinterlacer(pinfo->num, &pinfo->src, &pinfo->dst,
360 conv_type, dtlc_iface, pinfo->vlan_id, 0);
363 // else : vlan id == 0, such thing is not expected
368 call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, &ethertype_data);
370 return tvb_captured_length(tvb);
373 void
374 proto_register_vlan(void)
376 static hf_register_info hf[] = {
377 { &hf_vlan_priority_old,
378 { "Priority", "vlan.priority",
379 FT_UINT16, BASE_DEC, VALS(pri_vals_old), 0xE000,
380 "Descriptions are recommendations from IEEE standard 802.1D-2004", HFILL }
382 { &hf_vlan_priority,
383 { "Priority", "vlan.priority",
384 FT_UINT16, BASE_DEC, VALS(pri_vals), 0xE000,
385 "Descriptions are recommendations from IEEE standard 802.1Q-2014", HFILL }
387 { &hf_vlan_priority_7,
388 { "Priority", "vlan.priority",
389 FT_UINT16, BASE_DEC, VALS(pri_vals_7), 0xE000,
390 "Descriptions are recommendations from IEEE standard 802.1Q-2014", HFILL }
392 { &hf_vlan_priority_6,
393 { "Priority", "vlan.priority",
394 FT_UINT16, BASE_DEC, VALS(pri_vals_6), 0xE000,
395 "Descriptions are recommendations from IEEE standard 802.1Q-2014", HFILL }
397 { &hf_vlan_priority_5,
398 { "Priority", "vlan.priority",
399 FT_UINT16, BASE_DEC, VALS(pri_vals_5), 0xE000,
400 "Descriptions are recommendations from IEEE standard 802.1Q-2014", HFILL }
402 { &hf_vlan_cfi,
403 { "CFI", "vlan.cfi",
404 FT_BOOLEAN, 16, TFS(&tfs_noncanonical_canonical), 0x1000,
405 "Canonical Format Identifier", HFILL }
407 { &hf_vlan_dei,
408 { "DEI", "vlan.dei",
409 FT_BOOLEAN, 16, TFS(&tfs_eligible_ineligible), 0x1000,
410 "Drop Eligible Indicator", HFILL }
412 { &hf_vlan_id,
413 { "ID", "vlan.id",
414 FT_UINT16, BASE_DEC, NULL, 0x0FFF,
415 "VLAN ID", HFILL }
417 { &hf_vlan_id_name,
418 { "Name", "vlan.id_name",
419 FT_STRING, BASE_NONE, NULL, 0x0,
420 "VLAN ID Name", HFILL }
422 { &hf_vlan_etype,
423 { "Type", "vlan.etype",
424 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
425 "Ethertype", HFILL }
427 { &hf_vlan_len,
428 { "Length", "vlan.len",
429 FT_UINT16, BASE_DEC, NULL, 0x0,
430 NULL, HFILL }
432 { &hf_vlan_trailer,
433 { "Trailer", "vlan.trailer",
434 FT_BYTES, BASE_NONE, NULL, 0x0,
435 "VLAN Trailer", HFILL }
439 static int *ett[] = {
440 &ett_vlan
443 static ei_register_info ei[] = {
444 { &ei_vlan_len, { "vlan.len.past_end", PI_MALFORMED, PI_ERROR, "Length field value goes past the end of the payload", EXPFILL }},
445 { &ei_vlan_too_many_tags, { "vlan.too_many_tags", PI_UNDECODED, PI_WARN, "Too many nested VLAN tags", EXPFILL }},
448 static const enum_val_t version_vals[] = {
449 {"1998", "IEEE 802.1Q-1998", IEEE_8021Q_1998},
450 {"2005", "IEEE 802.1Q-2005", IEEE_8021Q_2005},
451 {"2011", "IEEE 802.1Q-2011", IEEE_8021Q_2011},
452 {NULL, NULL, -1}
455 static const enum_val_t priority_drop_vals[] = {
456 {"8p0d", "8 Priorities, 0 Drop Eligible", Priority_Drop_8P0D},
457 {"7p1d", "7 Priorities, 1 Drop Eligible", Priority_Drop_7P1D},
458 {"6p2d", "6 Priorities, 2 Drop Eligible", Priority_Drop_6P2D},
459 {"5p3d", "5 Priorities, 3 Drop Eligible", Priority_Drop_5P3D},
460 {NULL, NULL, -1}
463 module_t *vlan_module;
464 expert_module_t* expert_vlan;
466 proto_vlan = proto_register_protocol("802.1Q Virtual LAN", "VLAN", "vlan");
467 proto_register_field_array(proto_vlan, hf, array_length(hf));
468 proto_register_subtree_array(ett, array_length(ett));
469 expert_vlan = expert_register_protocol(proto_vlan);
470 expert_register_field_array(expert_vlan, ei, array_length(ei));
472 vlan_module = prefs_register_protocol(proto_vlan, proto_reg_handoff_vlan);
473 prefs_register_bool_preference(vlan_module, "summary_in_tree",
474 "Show vlan summary in protocol tree",
475 "Whether the vlan summary line should be shown in the protocol tree",
476 &vlan_summary_in_tree);
477 prefs_register_uint_preference(vlan_module, "qinq_ethertype",
478 "802.1QinQ Ethertype (in hex)",
479 "The (hexadecimal) Ethertype used to indicate 802.1QinQ VLAN in VLAN tunneling.",
480 16, &q_in_q_ethertype);
481 prefs_register_enum_preference(vlan_module, "version",
482 "IEEE 802.1Q version",
483 "IEEE 802.1Q specification version used (802.1Q-1998 uses 802.1D-2004 for PRI values)",
484 &vlan_version, version_vals, true);
485 prefs_register_enum_preference(vlan_module, "priority_drop",
486 "Priorities and drop eligibility",
487 "Number of priorities supported, and number of those drop eligible (not used for 802.1Q-1998)",
488 &vlan_priority_drop, priority_drop_vals, false);
489 vlan_handle = register_dissector("vlan", dissect_vlan, proto_vlan);
492 void
493 proto_reg_handoff_vlan(void)
495 static bool prefs_initialized = false;
496 static unsigned int old_q_in_q_ethertype;
497 capture_dissector_handle_t vlan_cap_handle;
499 if (!prefs_initialized)
501 dissector_add_uint("ethertype", ETHERTYPE_VLAN, vlan_handle);
502 vlan_cap_handle = create_capture_dissector_handle(capture_vlan, proto_vlan);
503 capture_dissector_add_uint("ethertype", ETHERTYPE_VLAN, vlan_cap_handle);
505 prefs_initialized = true;
507 else
509 dissector_delete_uint("ethertype", old_q_in_q_ethertype, vlan_handle);
512 old_q_in_q_ethertype = q_in_q_ethertype;
513 ethertype_handle = find_dissector_add_dependency("ethertype", proto_vlan);
515 dissector_add_uint("ethertype", q_in_q_ethertype, vlan_handle);
517 llc_cap_handle = find_capture_dissector("llc");
518 ipx_cap_handle = find_capture_dissector("ipx");
522 * Editor modelines - https://www.wireshark.org/tools/modelines.html
524 * Local Variables:
525 * c-basic-offset: 2
526 * tab-width: 8
527 * indent-tabs-mode: nil
528 * End:
530 * ex: set shiftwidth=2 tabstop=8 expandtab:
531 * :indentSize=2:tabSize=8:noTabs=true: