Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-gmhdr.c
blob30ac984e392a2856e56948f9e823f60e31e467e3
1 /* packet-gmhdr.c
2 * Routines for Gigamon header disassembly (modified from packet-vlan.c)
4 * Dissector for Gigamon Header and Trailer
5 * Copyright Gigamon 2010
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/etypes.h>
18 #include <epan/prefs.h>
19 #include <epan/in_cksum.h>
20 #include <epan/crc32-tvb.h>
21 #include <wsutil/crc32.h>
22 #include <wsutil/pint.h>
23 #include <epan/expert.h>
25 #include "packet-ieee8023.h"
27 void proto_register_gmhdr(void);
28 void proto_reg_handoff_gmhdr(void);
30 static dissector_handle_t gmhdr_handle;
32 #define GMHDR_FTYPE_PKTSIZE 1
33 #define GMHDR_FTYPE_SRCPORT_G 2
34 #define GMHDR_FTYPE_TIMESTAMP_LOCAL 3
35 #define GMHDR_FTYPE_TIMESTAMP_NTP 4
36 #define GMHDR_FTYPE_TIMESTAMP_GPS 5
37 #define GMHDR_FTYPE_TIMESTAMP_1588 6
38 #define GMHDR_FTYPE_FCS 7
39 #define GMHDR_FTYPE_SRCPORT_H 8
41 static const value_string gmhdr_ftype_timestamp[] = {
42 { GMHDR_FTYPE_TIMESTAMP_LOCAL, "Local" },
43 { GMHDR_FTYPE_TIMESTAMP_NTP, "NTP" },
44 { GMHDR_FTYPE_TIMESTAMP_GPS, "GPS" },
45 { GMHDR_FTYPE_TIMESTAMP_1588, "1588" },
46 { 0, NULL }
49 #define GMHDR_SRCPORT_G_PLFM_MASK 0xf80000
50 #define GMHDR_SRCPORT_G_GID_MASK 0x078000
51 #define GMHDR_SRCPORT_G_BID_MASK 0x007c00
52 #define GMHDR_SRCPORT_G_PID_MASK 0x0003ff
53 #define GMHDR_SRCPORT_G_PLFM_SHFT 19
54 #define GMHDR_SRCPORT_G_GID_SHFT 15
55 #define GMHDR_SRCPORT_G_BID_SHFT 10
56 #define GMHDR_SRCPORT_G_PID_SHFT 0
58 #define GMHDR_SRCPORT_H_PLFM_MASK 0xFC000000
59 #define GMHDR_SRCPORT_H_GID_MASK 0x03C00000
60 #define GMHDR_SRCPORT_H_BID_MASK 0x003F0000
61 #define GMHDR_SRCPORT_H_SID_MASK 0x0000FC00
62 #define GMHDR_SRCPORT_H_PID_MASK 0x000003FF
63 #define GMHDR_SRCPORT_H_PLFM_SHFT 26
64 #define GMHDR_SRCPORT_H_GID_SHFT 20
65 #define GMHDR_SRCPORT_H_BID_SHFT 16
66 #define GMHDR_SRCPORT_H_SID_SHFT 10
67 #define GMHDR_SRCPORT_H_PID_SHFT 0
69 static const value_string gmhdr_plfm_str[] = {
70 { 0, "Reserved" },
71 { 1, "GV-2404" },
72 { 2, "GV-420" },
73 { 3, "GV-MP" },
74 { 4, "HD4" },
75 { 5, "HD8" },
76 { 6, "GV-212" },
77 { 7, "HB1" },
78 { 8, "HC2" },
79 { 9, "TA1" },
80 { 10, "TA10" },
81 { 11, "TA40" },
82 { 12, "LY2" },
83 { 13, "TA100" },
84 { 14, "TACX" },
85 { 15, "HC1" },
86 { 16, "HC3" },
87 { 0, NULL }
90 static dissector_handle_t ethertype_handle;
92 static bool gmhdr_summary_in_tree = true;
93 static bool gmtrailer_summary_in_tree = true;
94 static bool gmhdr_decode_timestamp_trailer = true;
96 static int proto_gmhdr;
97 static int proto_gmtrailer;
98 static int hf_gmhdr_srcport_g;
99 static int hf_gmhdr_srcport_g_plfm;
100 static int hf_gmhdr_srcport_g_gid;
101 static int hf_gmhdr_srcport_g_bid;
102 static int hf_gmhdr_srcport_g_pid;
103 static int hf_gmhdr_pktsize;
104 static int hf_gmhdr_timestamp;
105 static int hf_gmhdr_generic;
106 static int hf_gmhdr_etype;
107 static int hf_gmhdr_len;
108 static int hf_gmhdr_trailer;
109 static int hf_gmhdr_origcrc;
110 static int hf_gmhdr_srcport_h;
111 static int hf_gmhdr_srcport_h_plfm;
112 static int hf_gmhdr_srcport_h_gid;
113 static int hf_gmhdr_srcport_h_bid;
114 static int hf_gmhdr_srcport_h_sid;
115 static int hf_gmhdr_srcport_h_pid;
117 static int hf_gmtrailer_origcrc;
118 static int hf_gmtrailer_portid;
119 static int hf_gmtrailer_timestamp;
121 static int ett_gmhdr;
122 static int ett_srcport;
123 static int ett_gmtrailer;
125 static expert_field ei_gmhdr_field_length_invalid;
126 static expert_field ei_gmhdr_len;
128 static void
129 dissect_gmtlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gmhdr_tree, unsigned offset, uint16_t length)
131 proto_tree *ti;
132 proto_tree *srcport_tree;
133 uint16_t fl;
135 while (length > 1) {
136 uint16_t tl = tvb_get_ntohs(tvb, offset);
137 offset += 2; /* type + len */
138 length -= 2;
140 fl = tl & 0xff;
141 switch (tl >> 8) {
142 case GMHDR_FTYPE_SRCPORT_G: {
143 uint16_t pid;
144 uint32_t tv = tvb_get_ntohl(tvb, offset) >> 8; /* Only 24-bit field */
146 if (fl != 3) {
147 expert_add_info_format(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
148 break;
150 ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_srcport_g, tvb, offset, fl, ENC_BIG_ENDIAN);
151 srcport_tree = proto_item_add_subtree(ti, ett_srcport);
152 proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_g_plfm, tvb, offset, fl, ENC_BIG_ENDIAN);
153 proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_g_gid, tvb, offset, fl, ENC_BIG_ENDIAN);
154 proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_g_bid, tvb, offset, fl, ENC_BIG_ENDIAN);
155 ti = proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_g_pid, tvb, offset, fl, ENC_BIG_ENDIAN);
156 /* If not GV-2404, we need different formula here */
157 pid = ((tv & GMHDR_SRCPORT_G_PID_MASK) >> GMHDR_SRCPORT_G_PID_SHFT) - 24;
158 if (pid >= 1 && pid <= 4) {
159 proto_item_append_text(ti, " (g%d)", pid);
161 break;
163 case GMHDR_FTYPE_PKTSIZE:
164 if (fl != 2) {
165 expert_add_info_format(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
166 break;
168 proto_tree_add_item(gmhdr_tree, hf_gmhdr_pktsize, tvb, offset, fl, ENC_BIG_ENDIAN);
169 break;
170 case GMHDR_FTYPE_TIMESTAMP_LOCAL:
171 case GMHDR_FTYPE_TIMESTAMP_NTP:
172 case GMHDR_FTYPE_TIMESTAMP_GPS:
173 case GMHDR_FTYPE_TIMESTAMP_1588:
174 if (fl != 8) {
175 expert_add_info_format(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
176 break;
178 ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_timestamp, tvb, offset, fl, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
179 proto_item_append_text(ti, "; Source: %s", val_to_str_const(tl>>8, gmhdr_ftype_timestamp, "Unknown"));
180 break;
181 case GMHDR_FTYPE_FCS: {
182 if (fl != 4) {
183 expert_add_info_format(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
184 break;
186 ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_origcrc, tvb, offset, 4, ENC_BIG_ENDIAN);
187 proto_item_append_text(ti, ", CRC (Not Verified)");
188 break;
190 case GMHDR_FTYPE_SRCPORT_H: {
191 if (fl != 4) {
192 expert_add_info_format(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
193 break;
195 ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_srcport_h, tvb, offset, fl, ENC_BIG_ENDIAN);
196 srcport_tree = proto_item_add_subtree(ti, ett_srcport);
197 proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_plfm, tvb, offset, fl, ENC_BIG_ENDIAN);
198 proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_gid, tvb, offset, fl, ENC_BIG_ENDIAN);
199 proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_bid, tvb, offset, fl, ENC_BIG_ENDIAN);
200 proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_sid, tvb, offset, fl, ENC_BIG_ENDIAN);
201 proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_pid, tvb, offset, fl, ENC_BIG_ENDIAN);
202 break;
204 default:
205 ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_generic, tvb, offset, fl, ENC_NA);
206 proto_item_append_text(ti, " [Id: %u, Length: %u]", tl >> 8, fl);
207 break;
209 /* Adjust for the field length */
210 offset += fl;
211 length -= fl;
217 static int
218 dissect_gmhdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
220 proto_tree *ti;
221 int16_t length;
222 uint16_t encap_proto;
223 bool is_802_2;
224 proto_tree *gmhdr_tree = NULL;
225 unsigned offset = 0;
227 length = tvb_get_uint8(tvb, offset); /* Length of the Gigamon header */
229 if (tree) {
230 ti = proto_tree_add_item(tree, proto_gmhdr, tvb, offset, length, ENC_NA);
232 if (gmhdr_summary_in_tree) {
233 proto_item_append_text(ti, ", Length: %u", length);
236 gmhdr_tree = proto_item_add_subtree(ti, ett_gmhdr);
237 dissect_gmtlv(tvb, pinfo, gmhdr_tree, offset+1, length-1);
239 } /* if (tree) */
241 offset += length;
242 encap_proto = tvb_get_ntohs(tvb, offset);
243 offset += 2;
244 if (encap_proto <= IEEE_802_3_MAX_LEN) {
245 /* Is there an 802.2 layer? I can tell by looking at the first 2
246 bytes after the GMHDR header. If they are 0xffff, then what
247 follows the GMHDR header is an IPX payload, meaning no 802.2.
248 (IPX/SPX is they only thing that can be contained inside a
249 straight 802.3 packet, so presumably the same applies for
250 Ethernet GMHDR packets). A non-0xffff value means that there's an
251 802.2 layer inside the GMHDR layer */
252 is_802_2 = true;
254 /* Don't throw an exception for this check (even a BoundsError) */
255 if (tvb_captured_length_remaining(tvb, offset) >= 2) {
256 if (tvb_get_ntohs(tvb, offset) == 0xffff) {
257 is_802_2 = false;
261 dissect_802_3(encap_proto, is_802_2, tvb, offset, pinfo, tree, gmhdr_tree,
262 hf_gmhdr_len, hf_gmhdr_trailer, &ei_gmhdr_len, 0);
263 } else {
264 ethertype_data_t ethertype_data;
266 proto_tree_add_uint(gmhdr_tree, hf_gmhdr_etype, tvb, offset - 2, 2,
267 encap_proto);
269 ethertype_data.etype = encap_proto;
270 ethertype_data.payload_offset = offset;
271 ethertype_data.fh_tree = gmhdr_tree;
272 ethertype_data.trailer_id = hf_gmhdr_trailer;
273 ethertype_data.fcs_len = 0;
275 call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, &ethertype_data);
277 return tvb_captured_length(tvb);
280 static int
281 dissect_gmtimestamp_trailer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
283 proto_tree *ti;
284 unsigned tvblen, trailer_len = 18;
285 proto_tree *gmtrailer_tree = NULL;
286 unsigned offset = 0;
287 uint32_t orig_crc, new_crc, comp_crc;
288 uint16_t port_num;
289 nstime_t gmtimev;
291 struct tm *tm = NULL;
293 if ( ! gmhdr_decode_timestamp_trailer)
294 return 0;
296 /* See if this packet has a Gigamon trailer, if yes, then decode it */
297 /* (Don't throw any exceptions while checking for the trailer). */
298 tvblen = tvb_captured_length(tvb); /* end+1 */
299 if (tvblen < trailer_len)
300 return 0;
302 orig_crc = tvb_get_ntohl(tvb, offset);
303 new_crc = tvb_get_ntohl(tvb, tvblen - 4);
305 /* Verify the checksum; if not valid, it means that the trailer is not valid */
306 comp_crc = CRC32C_SWAP(crc32_ccitt_tvb_seed(tvb, 14, CRC32C_SWAP(~orig_crc)));
307 if (comp_crc != new_crc)
308 return 0;
310 /* OK: We appear to have a Gigamon trailer */
311 if (tree) {
312 ti = proto_tree_add_item(tree, proto_gmtrailer, tvb, offset, trailer_len - 4, ENC_NA);
314 if (gmtrailer_summary_in_tree) {
315 offset += 4;
316 port_num = tvb_get_ntohs(tvb, offset);
317 proto_item_append_text(ti, ", Port: %d, Timestamp: ", port_num);
318 offset += 2;
320 gmtimev.secs = tvb_get_ntohl(tvb, offset);
321 offset += 4;
322 gmtimev.nsecs = tvb_get_ntohl(tvb, offset);
324 tm = localtime(&gmtimev.secs);
325 if (tm)
326 proto_item_append_text(ti, "%d:%02d:%02d.%09d", tm->tm_hour, tm->tm_min, tm->tm_sec, gmtimev.nsecs);
327 else
328 proto_item_append_text(ti, "<Not representable>");
331 offset = 0;
332 gmtrailer_tree = proto_item_add_subtree(ti, ett_gmtrailer);
333 proto_tree_add_item(gmtrailer_tree, hf_gmtrailer_origcrc, tvb, offset, 4, ENC_BIG_ENDIAN);
334 proto_tree_add_item(gmtrailer_tree, hf_gmtrailer_portid, tvb, offset+4, 2, ENC_BIG_ENDIAN);
335 proto_tree_add_item(gmtrailer_tree, hf_gmtrailer_timestamp, tvb, offset+6, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
338 return 14;
341 static bool
342 dissect_gmtimestamp_trailer_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
344 return dissect_gmtimestamp_trailer(tvb, pinfo, tree, data) > 0;
347 static int
348 dissect_gmtrailer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
350 proto_tree *ti;
351 unsigned tvblen, length;
352 proto_tree *gmhdr_tree = NULL;
353 unsigned offset;
354 uint16_t cksum, comp_cksum, extra_trailer;
356 /* See if this packet has a Gigamon trailer, if yes, then decode it */
357 /* (Don't throw any exceptions while checking for the trailer). */
358 tvblen = tvb_captured_length(tvb); /* end+1 */
359 if (tvblen < 5)
360 return 0;
361 extra_trailer = 0;
362 if (tvb_get_ntohs(tvb, tvblen-4) != ETHERTYPE_GIGAMON) {
363 if (tvblen < 10){
364 return 0;
366 if (tvb_get_ntohs(tvb, tvblen-8) == ETHERTYPE_GIGAMON) {
367 extra_trailer = 4;
368 } else {
369 return 0;
372 length = tvb_get_uint8(tvb, tvblen-extra_trailer-5); /* length of Gigamon header */
373 if ((tvblen-extra_trailer-5) != length)
374 return 0;
376 offset = tvblen - extra_trailer - 5 - length;
378 cksum = tvb_get_ntohs(tvb, tvblen-extra_trailer-2);
380 /* Verify the checksum; if not valid, it means that the trailer is not valid */
382 vec_t vec;
384 SET_CKSUM_VEC_TVB(vec, tvb, offset, length + 3);
386 comp_cksum = in_cksum(&vec, 1);
387 if (pntoh16(&comp_cksum) != cksum) {
388 return 0;
392 /* OK: We appear to have a Gigamon trailer */
393 if (tree) {
394 ti = proto_tree_add_item(tree, proto_gmhdr, tvb, offset, length + 5, ENC_NA);
396 if (gmhdr_summary_in_tree) {
397 proto_item_append_text(ti, ", Length: %u, Checksum: 0x%x", length, cksum);
400 gmhdr_tree = proto_item_add_subtree(ti, ett_gmhdr);
402 dissect_gmtlv(tvb, pinfo, gmhdr_tree, offset, length);
403 if (extra_trailer) {
404 proto_tree_add_item(tree, hf_gmhdr_trailer, tvb, length + 5, extra_trailer, ENC_NA);
407 return tvblen;
410 static bool
411 dissect_gmtrailer_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
413 return dissect_gmtrailer(tvb, pinfo, tree, data) > 0;
416 void
417 proto_register_gmhdr(void)
419 static hf_register_info hf[] = {
420 { &hf_gmhdr_srcport_g, {
421 "Src Port", "gmhdr.srcport_g", FT_UINT24, BASE_HEX,
422 NULL, 0, "Original Source Port", HFILL }},
423 { &hf_gmhdr_srcport_g_plfm, {
424 "Platform Id", "gmhdr.srcport_g_plfm", FT_UINT24, BASE_DEC,
425 VALS(gmhdr_plfm_str), GMHDR_SRCPORT_G_PLFM_MASK, "Original Platform Id", HFILL }},
426 { &hf_gmhdr_srcport_g_gid, {
427 "Group Id", "gmhdr.srcport_g_gid", FT_UINT24, BASE_DEC,
428 NULL, GMHDR_SRCPORT_G_GID_MASK, "Original Source Group Id", HFILL }},
429 { &hf_gmhdr_srcport_g_bid, {
430 "Box Id", "gmhdr.srcport_g_bid", FT_UINT24, BASE_DEC,
431 NULL, GMHDR_SRCPORT_G_BID_MASK, "Original Source Box Id", HFILL }},
432 { &hf_gmhdr_srcport_g_pid, {
433 "Port Id", "gmhdr.srcport_g_pid", FT_UINT24, BASE_DEC,
434 NULL, GMHDR_SRCPORT_G_PID_MASK, "Original Source Port Id", HFILL }},
435 { &hf_gmhdr_pktsize, {
436 "Original Packet Size", "gmhdr.pktsize", FT_UINT16, BASE_DEC,
437 NULL, 0, NULL, HFILL }},
438 { &hf_gmhdr_timestamp, {
439 "Time Stamp", "gmhdr.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
440 NULL, 0x0, NULL, HFILL }},
441 { &hf_gmhdr_generic, {
442 "Generic Field", "gmhdr.generic", FT_BYTES, BASE_NONE,
443 NULL, 0x0, NULL, HFILL }},
444 { &hf_gmhdr_etype, {
445 "Type", "gmhdr.etype", FT_UINT16, BASE_HEX,
446 VALS(etype_vals), 0x0, "Ethertype", HFILL }},
447 { &hf_gmhdr_len, {
448 "Length", "gmhdr.len", FT_UINT16, BASE_DEC,
449 NULL, 0x0, NULL, HFILL }},
450 { &hf_gmhdr_origcrc, {
451 "Original CRC", "gmhdr.crc", FT_UINT32, BASE_HEX,
452 NULL, 0x0, "Original Packet CRC", HFILL }},
453 { &hf_gmhdr_srcport_h, {
454 "Src Port", "gmhdr.srcport", FT_UINT32, BASE_HEX,
455 NULL, 0, "Original Source Port", HFILL }},
456 { &hf_gmhdr_srcport_h_plfm, {
457 "Platform Id", "gmhdr.srcport_plfm", FT_UINT32, BASE_DEC,
458 VALS(gmhdr_plfm_str), GMHDR_SRCPORT_H_PLFM_MASK, "Original Platform Id", HFILL }},
459 { &hf_gmhdr_srcport_h_gid, {
460 "Group Id", "gmhdr.srcport_gid", FT_UINT32, BASE_DEC,
461 NULL, GMHDR_SRCPORT_H_GID_MASK, "Original Source Group Id", HFILL }},
462 { &hf_gmhdr_srcport_h_bid, {
463 "Box Id", "gmhdr.srcport_bid", FT_UINT32, BASE_DEC,
464 NULL, GMHDR_SRCPORT_H_BID_MASK, "Original Source Box Id", HFILL }},
465 { &hf_gmhdr_srcport_h_sid, {
466 "Slot Id", "gmhdr.srcport_sid", FT_UINT32, BASE_DEC,
467 NULL, GMHDR_SRCPORT_H_SID_MASK, "Original Source Slot Id", HFILL }},
468 { &hf_gmhdr_srcport_h_pid, {
469 "Port Id", "gmhdr.srcport_pid", FT_UINT32, BASE_DEC,
470 NULL, GMHDR_SRCPORT_H_PID_MASK, "Original Source Port Id", HFILL }},
471 { &hf_gmhdr_trailer, {
472 "Trailer", "gmhdr.trailer", FT_BYTES, BASE_NONE,
473 NULL, 0x0, "GMHDR Trailer", HFILL }},
475 static hf_register_info gmtrailer_hf[] = {
476 { &hf_gmtrailer_origcrc, {
477 "Original CRC", "gmtrailer.crc", FT_UINT32, BASE_HEX,
478 NULL, 0x0, "Original Packet CRC", HFILL }},
479 { &hf_gmtrailer_portid, {
480 "Src Port", "gmtrailer.portid", FT_UINT16, BASE_HEX,
481 NULL, 0x0, "Origin Source Port", HFILL }},
482 { &hf_gmtrailer_timestamp, {
483 "Time Stamp", "gmtrailer.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
484 NULL, 0x0, NULL, HFILL }},
486 static int *ett[] = {
487 &ett_gmhdr,
488 &ett_srcport
490 static int *gmtrailer_ett[] = {
491 &ett_gmtrailer,
493 static ei_register_info ei[] = {
494 { &ei_gmhdr_field_length_invalid, { "gmhdr.field_length_invalid", PI_MALFORMED, PI_ERROR, "Field length invalid", EXPFILL }},
495 { &ei_gmhdr_len, { "gmhdr.len.past_end", PI_MALFORMED, PI_ERROR, "Length field value goes past the end of the payload", EXPFILL }},
498 module_t *gmhdr_module;
499 module_t *gmtrailer_module;
500 expert_module_t* expert_gmhdr;
502 proto_gmhdr = proto_register_protocol("Gigamon Header", "GMHDR", "gmhdr");
503 proto_register_field_array(proto_gmhdr, hf, array_length(hf));
504 proto_register_subtree_array(ett, array_length(ett));
505 expert_gmhdr = expert_register_protocol(proto_gmhdr);
506 expert_register_field_array(expert_gmhdr, ei, array_length(ei));
507 gmhdr_handle = register_dissector("gmhdr", dissect_gmhdr, proto_gmhdr);
509 proto_gmtrailer = proto_register_protocol("Gigamon Trailer", "GMTRAILER", "gmtrailer");
510 proto_register_field_array(proto_gmtrailer, gmtrailer_hf, array_length(gmtrailer_hf));
511 proto_register_subtree_array(gmtrailer_ett, array_length(gmtrailer_ett));
513 gmhdr_module = prefs_register_protocol(proto_gmhdr, NULL);
514 prefs_register_bool_preference(gmhdr_module, "summary_in_tree",
515 "Show Gigamon header summary in protocol tree",
516 "Whether the Gigamon header summary line should be shown in the protocol tree",
517 &gmhdr_summary_in_tree);
519 gmtrailer_module = prefs_register_protocol(proto_gmtrailer, NULL);
520 prefs_register_bool_preference(gmtrailer_module, "summary_in_tree",
521 "Show Gigamon Trailer summary in protocol tree",
522 "Whether the Gigamon Trailer summary line should be shown in the protocol tree",
523 &gmtrailer_summary_in_tree);
524 prefs_register_bool_preference(gmtrailer_module, "decode_trailer_timestamp",
525 "Decode Gigamon HW timestamp and source id in trailer",
526 "Whether the Gigamon trailer containing HW timestamp, source id and original CRC should be decoded",
527 &gmhdr_decode_timestamp_trailer);
530 void
531 proto_reg_handoff_gmhdr(void)
533 ethertype_handle = find_dissector_add_dependency("ethertype", proto_gmhdr);
535 dissector_add_uint("ethertype", ETHERTYPE_GIGAMON, gmhdr_handle);
536 heur_dissector_add("eth.trailer", dissect_gmtrailer_heur, "Gigamon Ethernet header", "gmhdr_eth", proto_gmhdr, HEURISTIC_ENABLE);
538 heur_dissector_add("eth.trailer", dissect_gmtimestamp_trailer_heur, "Gigamon Ethernet trailer", "gmtrailer_eth", proto_gmtrailer, HEURISTIC_ENABLE);
542 * Editor modelines - https://www.wireshark.org/tools/modelines.html
544 * Local Variables:
545 * c-basic-offset: 2
546 * tab-width: 8
547 * indent-tabs-mode: nil
548 * End:
550 * ex: set shiftwidth=2 tabstop=8 expandtab:
551 * :indentSize=2:tabSize=8:noTabs=true: