/src/wireshark/epan/dissectors/packet-ieee8021ah.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-ieee8021ah.c |
2 | | * Routines for 802.1ah ethernet header disassembly |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * SPDX-License-Identifier: GPL-2.0-or-later |
9 | | */ |
10 | | |
11 | | #include "config.h" |
12 | | |
13 | | #include <epan/packet.h> |
14 | | #include <epan/capture_dissectors.h> |
15 | | #include <wsutil/pint.h> |
16 | | #include <epan/addr_resolv.h> |
17 | | |
18 | | #include "packet-ipx.h" |
19 | | #include "packet-llc.h" |
20 | | #include <epan/etypes.h> |
21 | | #include <epan/prefs.h> |
22 | | |
23 | | void proto_register_ieee8021ah(void); |
24 | | void proto_reg_handoff_ieee8021ah(void); |
25 | | |
26 | | static dissector_handle_t ieee8021ah_handle; |
27 | | static dissector_handle_t ieee8021ad_handle; |
28 | | static dissector_handle_t ethertype_handle; |
29 | | |
30 | | static capture_dissector_handle_t ipx_cap_handle; |
31 | | static capture_dissector_handle_t llc_cap_handle; |
32 | | |
33 | | static void dissect_ieee8021ah_common(tvbuff_t *tvb, packet_info *pinfo, |
34 | | proto_tree *tree, proto_tree *parent, int tree_index); |
35 | | |
36 | | /* GLOBALS ************************************************************/ |
37 | | |
38 | | /* ethertype for 802.1ah tag - encapsulating an Ethernet packet */ |
39 | | static unsigned int ieee8021ah_ethertype = ETHERTYPE_IEEE_802_1AH; |
40 | | |
41 | | static int proto_ieee8021ah; |
42 | | static int proto_ieee8021ad; |
43 | | |
44 | | /* dot1ad B-tag fields */ |
45 | | static int hf_ieee8021ad_priority; |
46 | | static int hf_ieee8021ad_cfi; |
47 | | static int hf_ieee8021ad_id; |
48 | | static int hf_ieee8021ad_svid; |
49 | | static int hf_ieee8021ad_cvid; |
50 | | |
51 | | /* dot1ah C-tag fields */ |
52 | | static int hf_ieee8021ah_priority; |
53 | | static int hf_ieee8021ah_drop; /* drop eligibility */ |
54 | | static int hf_ieee8021ah_nca; /* no customer addresses (c_daddr & c_saddr are 0) */ |
55 | | static int hf_ieee8021ah_res1; /* 2 bits reserved; ignored on receive */ |
56 | | static int hf_ieee8021ah_res2; /* 2 bits reserved; delete frame if non-zero */ |
57 | | static int hf_ieee8021ah_isid; /* I-SID */ |
58 | | static int hf_ieee8021ah_c_daddr; /* encapsulated customer dest addr */ |
59 | | static int hf_ieee8021ah_c_saddr; /* encapsulated customer src addr */ |
60 | | |
61 | | static int hf_ieee8021ah_etype; |
62 | | /* static int hf_ieee8021ah_len; */ |
63 | | static int hf_ieee8021ah_trailer; |
64 | | |
65 | | static int ett_ieee8021ah; |
66 | | static int ett_ieee8021ad; |
67 | | |
68 | 7 | #define IEEE8021AD_LEN 4 |
69 | 9 | #define IEEE8021AH_LEN 18 |
70 | 9 | #define IEEE8021AH_ISIDMASK 0x00FFFFFF |
71 | | |
72 | | /* FUNCTIONS ************************************************************/ |
73 | | |
74 | | |
75 | | static bool |
76 | | capture_ieee8021ah(const unsigned char *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_) |
77 | 0 | { |
78 | 0 | uint16_t encap_proto; |
79 | |
|
80 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, IEEE8021AH_LEN + 1)) |
81 | 0 | return false; |
82 | | |
83 | 0 | encap_proto = pntoh16( &pd[offset + IEEE8021AH_LEN - 2] ); |
84 | 0 | if (encap_proto <= IEEE_802_3_MAX_LEN) { |
85 | 0 | if ( pd[offset + IEEE8021AH_LEN] == 0xff |
86 | 0 | && pd[offset + IEEE8021AH_LEN + 1] == 0xff ) { |
87 | 0 | return call_capture_dissector(ipx_cap_handle, pd, offset + IEEE8021AH_LEN, len, cpinfo, pseudo_header); |
88 | 0 | } |
89 | 0 | else { |
90 | 0 | return call_capture_dissector(llc_cap_handle, pd, offset + IEEE8021AH_LEN, len, cpinfo, pseudo_header); |
91 | 0 | } |
92 | 0 | } |
93 | | |
94 | 0 | return try_capture_dissector("ethertype", encap_proto, pd, offset + IEEE8021AH_LEN, len, cpinfo, pseudo_header); |
95 | 0 | } |
96 | | |
97 | | /* Dissector *************************************************************/ |
98 | | static |
99 | | int dissect_ieee8021ad(tvbuff_t *tvb, packet_info *pinfo, |
100 | | proto_tree *tree, void* data _U_) |
101 | 1 | { |
102 | 1 | proto_tree *ptree = NULL; |
103 | 1 | proto_tree *tagtree = NULL; |
104 | 1 | uint32_t tci, ctci; |
105 | 1 | uint16_t encap_proto; |
106 | 1 | int proto_tree_index; |
107 | 1 | ethertype_data_t ethertype_data; |
108 | | |
109 | 1 | tvbuff_t *next_tvb = NULL; |
110 | 1 | proto_tree *ieee8021ad_tree; |
111 | 1 | proto_tree *ieee8021ad_tag_tree; |
112 | | |
113 | | /* set tree index */ |
114 | 1 | proto_tree_index = proto_ieee8021ad; |
115 | | |
116 | | /* add info to column display */ |
117 | 1 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "802.1ad"); |
118 | 1 | col_clear(pinfo->cinfo, COL_INFO); |
119 | | |
120 | 1 | tci = tvb_get_ntohs( tvb, 0 ); |
121 | | |
122 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, |
123 | 1 | "PRI: %d DROP: %d ID: %d", |
124 | 1 | (tci >> 13), ((tci >> 12) & 1), (tci & 0xFFF)); |
125 | | |
126 | | /* create the protocol tree */ |
127 | 1 | ptree = proto_tree_add_item(tree, proto_tree_index, tvb, 0, IEEE8021AD_LEN, ENC_NA); |
128 | 1 | ieee8021ad_tree = proto_item_add_subtree(ptree, ett_ieee8021ad); |
129 | | |
130 | 1 | encap_proto = tvb_get_ntohs(tvb, IEEE8021AD_LEN - 2); |
131 | 1 | ethertype_data.fh_tree = ieee8021ad_tree; |
132 | 1 | ethertype_data.trailer_id = hf_ieee8021ah_trailer; |
133 | 1 | ethertype_data.fcs_len = 0; |
134 | | |
135 | | /* If it's a 1ah frame, create subtree for B-Tag, rename overall |
136 | | tree to 802.1ah, pass to 1ah dissector */ |
137 | 1 | if (encap_proto == ETHERTYPE_IEEE_802_1AH) { |
138 | 0 | if (tree) { |
139 | 0 | tagtree = proto_tree_add_item(ptree, proto_tree_index, tvb, 0, 2, ENC_NA); |
140 | 0 | ieee8021ad_tag_tree = proto_item_add_subtree(tagtree, ett_ieee8021ad); |
141 | | |
142 | | /* add fields */ |
143 | 0 | proto_tree_add_uint(ieee8021ad_tag_tree, hf_ieee8021ad_priority, tvb, |
144 | 0 | 0, 1, tci); |
145 | 0 | proto_tree_add_uint(ieee8021ad_tag_tree, hf_ieee8021ad_cfi, tvb, 0, 1, tci); |
146 | 0 | proto_tree_add_uint(ieee8021ad_tag_tree, hf_ieee8021ad_id, tvb, 0, 2, tci); |
147 | | |
148 | | /* set label of B-tag subtree */ |
149 | 0 | proto_item_set_text(ieee8021ad_tag_tree, "B-Tag, B-VID: %d", tci & 0x0FFF); |
150 | 0 | } |
151 | |
|
152 | 0 | next_tvb = tvb_new_subset_remaining(tvb, IEEE8021AD_LEN); |
153 | |
|
154 | 0 | if (ptree) { |
155 | | /* add bvid to label */ |
156 | 0 | proto_item_set_text(ptree, "IEEE 802.1ah, B-VID: %d", tci & 0x0FFF); |
157 | |
|
158 | 0 | dissect_ieee8021ah_common(next_tvb, pinfo, ptree, tree, proto_tree_index); |
159 | 0 | } |
160 | 0 | else { |
161 | 0 | dissect_ieee8021ah_common(next_tvb, pinfo, tree, NULL, proto_tree_index); |
162 | 0 | } |
163 | |
|
164 | 1 | } else if (encap_proto == ETHERTYPE_IEEE_802_1AD) { |
165 | | /* two VLAN tags (i.e. Q-in-Q) */ |
166 | 0 | ctci = tvb_get_ntohs(tvb, IEEE8021AD_LEN); |
167 | |
|
168 | 0 | if (tree) { |
169 | | /* add fields */ |
170 | 0 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_priority, tvb, |
171 | 0 | 0, 1, tci); |
172 | 0 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_cfi, tvb, 0, 1, tci); |
173 | 0 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_svid, tvb, 0, 2, tci); |
174 | 0 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_priority, tvb, |
175 | 0 | IEEE8021AD_LEN, 1, ctci); |
176 | 0 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_cfi, tvb, |
177 | 0 | IEEE8021AD_LEN, 1, ctci); |
178 | 0 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_cvid, tvb, IEEE8021AD_LEN, |
179 | 0 | 2, ctci); |
180 | 0 | } |
181 | |
|
182 | 0 | proto_item_set_text(ptree, "IEEE 802.1ad, S-VID: %d, C-VID: %d", tci & 0x0FFF, |
183 | 0 | ctci & 0x0FFF); |
184 | |
|
185 | 0 | ethertype_data.etype = tvb_get_ntohs(tvb, IEEE8021AD_LEN * 2 - 2); |
186 | 0 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ah_etype, tvb, |
187 | 0 | IEEE8021AD_LEN * 2 - 2, 2, ethertype_data.etype); |
188 | |
|
189 | 0 | ethertype_data.payload_offset = IEEE8021AD_LEN * 2; |
190 | | |
191 | | /* 802.1ad tags are always followed by an ethertype; call next |
192 | | dissector based on ethertype */ |
193 | 0 | call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, ðertype_data); |
194 | 1 | } else { |
195 | | /* Something else (shouldn't really happen, but we'll support it anyways) */ |
196 | 1 | if (tree) { |
197 | | /* add fields */ |
198 | 1 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_priority, tvb, |
199 | 1 | 0, 1, tci); |
200 | 1 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_cfi, tvb, 0, 1, tci); |
201 | 1 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ad_id, tvb, 0, 2, tci); |
202 | 1 | } |
203 | | |
204 | | /* label should be 802.1ad not .1ah */ |
205 | 1 | proto_item_set_text(ptree, "IEEE 802.1ad, ID: %d", tci & 0x0FFF); |
206 | | |
207 | | /* Add the Ethernet type to the protocol tree */ |
208 | 1 | proto_tree_add_uint(ieee8021ad_tree, hf_ieee8021ah_etype, tvb, |
209 | 1 | IEEE8021AD_LEN - 2, 2, encap_proto); |
210 | | |
211 | 1 | ethertype_data.etype = encap_proto; |
212 | 1 | ethertype_data.payload_offset = IEEE8021AD_LEN; |
213 | | |
214 | | /* 802.1ad tags are always followed by an ethertype; call next |
215 | | dissector based on ethertype */ |
216 | 1 | call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, ðertype_data); |
217 | 1 | } |
218 | 1 | return tvb_captured_length(tvb); |
219 | 1 | } |
220 | | |
221 | | static void |
222 | | dissect_ieee8021ah_common(tvbuff_t *tvb, packet_info *pinfo, |
223 | 3 | proto_tree *tree, proto_tree *parent, int tree_index) { |
224 | 3 | uint32_t tci; |
225 | 3 | uint16_t encap_proto; |
226 | 3 | proto_tree *ptree; |
227 | 3 | ethertype_data_t ethertype_data; |
228 | | |
229 | 3 | proto_tree *ieee8021ah_tag_tree; |
230 | | |
231 | 3 | tci = tvb_get_ntohl( tvb, 0 ); |
232 | | |
233 | 3 | col_add_fstr(pinfo->cinfo, COL_INFO, |
234 | 3 | "PRI: %d Drop: %d NCA: %d Res1: %d Res2: %d I-SID: %d", |
235 | 3 | (tci >> 29), ((tci >> 28) & 1), ((tci >> 27) & 1), |
236 | 3 | ((tci >> 26) & 1), ((tci >> 24) & 3), tci & IEEE8021AH_ISIDMASK); |
237 | | |
238 | | /* create the protocol tree */ |
239 | 3 | ptree = NULL; |
240 | 3 | ieee8021ah_tag_tree = NULL; |
241 | | |
242 | 3 | if (tree) { |
243 | | /* 802.1ah I-Tag */ |
244 | 3 | ptree = proto_tree_add_item(tree, tree_index, tvb, 0, 4, ENC_NA); |
245 | 3 | ieee8021ah_tag_tree = proto_item_add_subtree(ptree, ett_ieee8021ah); |
246 | | |
247 | | /* add fields */ |
248 | 3 | proto_tree_add_uint(ieee8021ah_tag_tree, hf_ieee8021ah_priority, tvb, |
249 | 3 | 0, 1, tci); |
250 | 3 | proto_tree_add_uint(ieee8021ah_tag_tree, hf_ieee8021ah_drop, tvb, 0, 1, tci); |
251 | 3 | proto_tree_add_uint(ieee8021ah_tag_tree, hf_ieee8021ah_nca, tvb, 0, 1, tci); |
252 | 3 | proto_tree_add_uint(ieee8021ah_tag_tree, hf_ieee8021ah_res1, tvb, 0, 1, tci); |
253 | 3 | proto_tree_add_uint(ieee8021ah_tag_tree, hf_ieee8021ah_res2, tvb, 0, 1, tci); |
254 | 3 | proto_tree_add_uint(ieee8021ah_tag_tree, hf_ieee8021ah_isid, tvb, 1, 3, tci); |
255 | | |
256 | 3 | proto_item_set_text(ieee8021ah_tag_tree, "I-Tag, I-SID: %d", |
257 | 3 | tci & IEEE8021AH_ISIDMASK); |
258 | | |
259 | 3 | proto_tree_add_item(tree, hf_ieee8021ah_c_daddr, tvb, 4, 6, ENC_NA); |
260 | 3 | proto_tree_add_item(tree, hf_ieee8021ah_c_saddr, tvb, 10, 6, ENC_NA); |
261 | | |
262 | | /* add text to 802.1ad label */ |
263 | 3 | if (parent) { |
264 | 3 | proto_item_append_text(tree, ", I-SID: %d, C-Src: %s, C-Dst: %s", |
265 | 3 | tci & IEEE8021AH_ISIDMASK, |
266 | 3 | tvb_address_with_resolution_to_str(pinfo->pool, tvb, AT_ETHER, 10), |
267 | 3 | tvb_address_with_resolution_to_str(pinfo->pool, tvb, AT_ETHER, 4)); |
268 | 3 | } |
269 | 3 | } |
270 | | |
271 | 3 | encap_proto = tvb_get_ntohs(tvb, IEEE8021AH_LEN - 2); |
272 | 3 | proto_tree_add_uint(tree, hf_ieee8021ah_etype, tvb, |
273 | 3 | IEEE8021AD_LEN - 2, 2, encap_proto); |
274 | | |
275 | | /* 802.1ah I-tags are always followed by an ethertype; call next |
276 | | dissector based on ethertype */ |
277 | | |
278 | | /* If this was preceded by a 802.1ad tag, must pass original tree |
279 | | to next dissector, not 802.1ad tree */ |
280 | 3 | ethertype_data.etype = encap_proto; |
281 | 3 | ethertype_data.fh_tree = tree; |
282 | 3 | ethertype_data.payload_offset = IEEE8021AH_LEN; |
283 | 3 | ethertype_data.trailer_id = hf_ieee8021ah_trailer; |
284 | 3 | ethertype_data.fcs_len = 0; |
285 | | |
286 | 3 | if (parent) { |
287 | 3 | call_dissector_with_data(ethertype_handle, tvb, pinfo, parent, ðertype_data); |
288 | 3 | } |
289 | 0 | else { |
290 | 0 | call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, ðertype_data); |
291 | 0 | } |
292 | 3 | } |
293 | | |
294 | | static |
295 | | int dissect_ieee8021ah(tvbuff_t *tvb, packet_info *pinfo, |
296 | | proto_tree *tree, void* data _U_) |
297 | 3 | { |
298 | 3 | proto_item *pi; |
299 | 3 | uint32_t tci; |
300 | 3 | int proto_tree_index; |
301 | 3 | proto_tree *ieee8021ah_tree; |
302 | | |
303 | | /* set tree index */ |
304 | 3 | proto_tree_index = proto_ieee8021ah; |
305 | | |
306 | | /* add info to column display */ |
307 | 3 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "802.1ah"); |
308 | 3 | col_clear(pinfo->cinfo, COL_INFO); |
309 | | |
310 | 3 | tci = tvb_get_ntohl( tvb, 0 ); |
311 | | |
312 | 3 | col_add_fstr(pinfo->cinfo, COL_INFO, |
313 | 3 | "PRI: %d Drop: %d NCA: %d Res1: %d Res2: %d I-SID: %d", |
314 | 3 | (tci >> 29), ((tci >> 28) & 1), ((tci >> 27) & 1), |
315 | 3 | ((tci >> 26) & 1), ((tci >> 24) & 3), (tci & 0x00FFFFFF)); |
316 | | |
317 | 3 | pi = proto_tree_add_item(tree, proto_tree_index, tvb, 0, IEEE8021AH_LEN, ENC_NA); |
318 | 3 | ieee8021ah_tree = proto_item_add_subtree(pi, ett_ieee8021ah); |
319 | | |
320 | 3 | if (ieee8021ah_tree) { |
321 | 3 | dissect_ieee8021ah_common(tvb, pinfo, ieee8021ah_tree, tree, proto_tree_index); |
322 | 3 | } else { |
323 | 0 | dissect_ieee8021ah_common(tvb, pinfo, tree, NULL, proto_tree_index); |
324 | 0 | } |
325 | 3 | return tvb_captured_length(tvb); |
326 | 3 | } |
327 | | |
328 | | /* Protocol Registration **************************************************/ |
329 | | |
330 | | void |
331 | | proto_register_ieee8021ah(void) |
332 | 14 | { |
333 | 14 | static hf_register_info hf[] = { |
334 | 14 | { &hf_ieee8021ah_priority, { |
335 | 14 | "Priority", "ieee8021ah.priority", FT_UINT32, BASE_DEC, |
336 | 14 | 0, 0xE0000000, NULL, HFILL }}, |
337 | 14 | { &hf_ieee8021ah_drop, { |
338 | 14 | "DROP", "ieee8021ah.drop", FT_UINT32, BASE_DEC, |
339 | 14 | 0, 0x10000000, NULL, HFILL }}, |
340 | 14 | { &hf_ieee8021ah_nca, { |
341 | 14 | "NCA", "ieee8021ah.nca", FT_UINT32, BASE_DEC, |
342 | 14 | 0, 0x08000000, "No Customer Addresses", HFILL }}, |
343 | 14 | { &hf_ieee8021ah_res1, { |
344 | 14 | "RES1", "ieee8021ah.res1", FT_UINT32, BASE_DEC, |
345 | 14 | 0, 0x04000000, "Reserved1", HFILL }}, |
346 | 14 | { &hf_ieee8021ah_res2, { |
347 | 14 | "RES2", "ieee8021ah.res2", FT_UINT32, BASE_DEC, |
348 | 14 | 0, 0x03000000, "Reserved2", HFILL }}, |
349 | 14 | { &hf_ieee8021ah_isid, { |
350 | 14 | "I-SID", "ieee8021ah.isid", FT_UINT32, BASE_DEC, |
351 | 14 | 0, 0x00FFFFFF, NULL, HFILL }}, |
352 | 14 | { &hf_ieee8021ah_c_daddr, { |
353 | 14 | "C-Destination", "ieee8021ah.cdst", FT_ETHER, BASE_NONE, |
354 | 14 | NULL, 0x0, "Customer Destination Address", HFILL }}, |
355 | 14 | { &hf_ieee8021ah_c_saddr, { |
356 | 14 | "C-Source", "ieee8021ah.csrc", FT_ETHER, BASE_NONE, |
357 | 14 | NULL, 0x0, "Customer Source Address", HFILL }}, |
358 | 14 | { &hf_ieee8021ah_etype, { |
359 | 14 | "Type", "ieee8021ah.etype", FT_UINT16, BASE_HEX, |
360 | 14 | VALS(etype_vals), 0x0, NULL, HFILL }}, |
361 | | #if 0 |
362 | | { &hf_ieee8021ah_len, { |
363 | | "Length", "ieee8021ah.len", FT_UINT16, BASE_DEC, |
364 | | NULL, 0x0, NULL, HFILL }}, |
365 | | #endif |
366 | 14 | { &hf_ieee8021ah_trailer, { |
367 | 14 | "Trailer", "ieee8021ah.trailer", FT_BYTES, BASE_NONE, |
368 | 14 | NULL, 0x0, "802.1ah Trailer", HFILL }} |
369 | 14 | }; |
370 | | |
371 | 14 | static hf_register_info hf_1ad[] = { |
372 | 14 | { &hf_ieee8021ad_priority, { |
373 | 14 | "Priority", "ieee8021ad.priority", FT_UINT16, BASE_DEC, |
374 | 14 | 0, 0xE000, NULL, HFILL }}, |
375 | 14 | { &hf_ieee8021ad_cfi, { |
376 | 14 | "DEI", "ieee8021ad.dei", FT_UINT16, BASE_DEC, |
377 | 14 | 0, 0x1000, "Drop Eligibility", HFILL }}, |
378 | 14 | { &hf_ieee8021ad_id, { |
379 | 14 | "ID", "ieee8021ad.id", FT_UINT16, BASE_DEC, |
380 | 14 | 0, 0x0FFF, "Vlan ID", HFILL }}, |
381 | 14 | { &hf_ieee8021ad_svid, { |
382 | 14 | "ID", "ieee8021ad.svid", FT_UINT16, BASE_DEC, |
383 | 14 | 0, 0x0FFF, "S-Vlan ID", HFILL }}, |
384 | 14 | { &hf_ieee8021ad_cvid, { |
385 | 14 | "ID", "ieee8021ad.cvid", FT_UINT16, BASE_DEC, |
386 | 14 | 0, 0x0FFF, "C-Vlan ID", HFILL }}, |
387 | 14 | }; |
388 | | |
389 | 14 | static int *ett[] = { |
390 | 14 | &ett_ieee8021ah, |
391 | 14 | &ett_ieee8021ad |
392 | 14 | }; |
393 | | |
394 | | |
395 | 14 | module_t *ieee8021ah_module; |
396 | | |
397 | | /* registration */ |
398 | | /* dot1ah */ |
399 | 14 | proto_ieee8021ah = proto_register_protocol("IEEE 802.1ah", "IEEE 802.1AH", |
400 | 14 | "ieee8021ah"); |
401 | 14 | ieee8021ah_handle = register_dissector("ieee8021ah", dissect_ieee8021ah, |
402 | 14 | proto_ieee8021ah); |
403 | 14 | proto_register_field_array(proto_ieee8021ah, hf, array_length(hf)); |
404 | | |
405 | 14 | proto_ieee8021ad = proto_register_protocol("IEEE 802.1ad", "IEEE 802.1AD", |
406 | 14 | "ieee8021ad"); |
407 | 14 | ieee8021ad_handle = register_dissector("ieee8021ad", dissect_ieee8021ad, |
408 | 14 | proto_ieee8021ad); |
409 | 14 | proto_register_field_array(proto_ieee8021ad, hf_1ad, array_length(hf_1ad)); |
410 | | |
411 | | /* register subtree array for both */ |
412 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
413 | | |
414 | | /* add a user preference to set the 802.1ah ethertype */ |
415 | 14 | ieee8021ah_module = prefs_register_protocol(proto_ieee8021ah, |
416 | 14 | proto_reg_handoff_ieee8021ah); |
417 | 14 | prefs_register_uint_preference(ieee8021ah_module, "8021ah_ethertype", |
418 | 14 | "802.1ah Ethertype (in hex)", |
419 | 14 | "(Hexadecimal) Ethertype used to indicate IEEE 802.1ah tag.", |
420 | 14 | 16, &ieee8021ah_ethertype); |
421 | 14 | } |
422 | | |
423 | | void |
424 | | proto_reg_handoff_ieee8021ah(void) |
425 | 14 | { |
426 | 14 | static bool prefs_initialized = false; |
427 | 14 | static unsigned int old_ieee8021ah_ethertype; |
428 | 14 | static capture_dissector_handle_t ieee8021ah_cap_handle; |
429 | | |
430 | 14 | if (!prefs_initialized){ |
431 | 14 | dissector_add_uint("ethertype", ETHERTYPE_IEEE_802_1AD, ieee8021ad_handle); |
432 | 14 | ethertype_handle = find_dissector_add_dependency("ethertype", proto_ieee8021ah); |
433 | 14 | find_dissector_add_dependency("ethertype", proto_ieee8021ad); |
434 | 14 | ieee8021ah_cap_handle = create_capture_dissector_handle(capture_ieee8021ah, proto_ieee8021ah); |
435 | 14 | capture_dissector_add_uint("ethertype", ETHERTYPE_IEEE_802_1AD, ieee8021ah_cap_handle); |
436 | 14 | capture_dissector_add_uint("ethertype", ETHERTYPE_IEEE_802_1AH, ieee8021ah_cap_handle); |
437 | | |
438 | 14 | ipx_cap_handle = find_capture_dissector("ipx"); |
439 | 14 | llc_cap_handle = find_capture_dissector("llc"); |
440 | | |
441 | 14 | prefs_initialized = true; |
442 | 14 | } |
443 | 0 | else { |
444 | 0 | dissector_delete_uint("ethertype", old_ieee8021ah_ethertype, ieee8021ah_handle); |
445 | 0 | } |
446 | | |
447 | 14 | old_ieee8021ah_ethertype = ieee8021ah_ethertype; |
448 | 14 | dissector_add_uint("ethertype", ieee8021ah_ethertype, ieee8021ah_handle); |
449 | 14 | } |
450 | | |
451 | | /* |
452 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
453 | | * |
454 | | * Local variables: |
455 | | * c-basic-offset: 4 |
456 | | * tab-width: 8 |
457 | | * indent-tabs-mode: nil |
458 | | * End: |
459 | | * |
460 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
461 | | * :indentSize=4:tabSize=8:noTabs=true: |
462 | | */ |