2010-06-19 01:43:11 +00:00
|
|
|
/* packet-gmhdr.c
|
|
|
|
* Routines for Gigamon header disassembly (modified from packet-vlan.c)
|
|
|
|
*
|
2010-06-21 11:28:52 +00:00
|
|
|
* Dissector for Gigamon Header and Trailer
|
|
|
|
* Copyright Gigamon 2010
|
|
|
|
*
|
2010-06-19 01:43:11 +00:00
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
2010-06-21 11:28:52 +00:00
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
2010-06-19 01:43:11 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-06-28 22:56:06 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2010-06-19 01:43:11 +00:00
|
|
|
*/
|
|
|
|
|
2012-09-20 02:03:38 +00:00
|
|
|
#include "config.h"
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/etypes.h>
|
|
|
|
#include <epan/prefs.h>
|
|
|
|
#include <epan/in_cksum.h>
|
2012-06-19 06:18:30 +00:00
|
|
|
#include <epan/crc32-tvb.h>
|
|
|
|
#include <wsutil/crc32.h>
|
2010-07-09 20:27:02 +00:00
|
|
|
#include <epan/expert.h>
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
#include "packet-ieee8023.h"
|
|
|
|
|
|
|
|
#define GMHDR_FTYPE_PKTSIZE 1
|
2013-01-11 19:20:39 +00:00
|
|
|
#define GMHDR_FTYPE_SRCPORT_G 2
|
2010-06-19 01:43:11 +00:00
|
|
|
#define GMHDR_FTYPE_TIMESTAMP_LOCAL 3
|
|
|
|
#define GMHDR_FTYPE_TIMESTAMP_NTP 4
|
2010-09-14 14:43:56 +00:00
|
|
|
#define GMHDR_FTYPE_TIMESTAMP_GPS 5
|
|
|
|
#define GMHDR_FTYPE_TIMESTAMP_1588 6
|
2013-01-11 19:20:39 +00:00
|
|
|
#define GMHDR_FTYPE_FCS 7
|
|
|
|
#define GMHDR_FTYPE_SRCPORT_H 8
|
2010-06-19 01:43:11 +00:00
|
|
|
|
2010-06-20 21:18:48 +00:00
|
|
|
static const value_string gmhdr_ftype_timestamp[] = {
|
|
|
|
{ GMHDR_FTYPE_TIMESTAMP_LOCAL, "Local" },
|
|
|
|
{ GMHDR_FTYPE_TIMESTAMP_NTP, "NTP" },
|
2010-09-14 14:43:56 +00:00
|
|
|
{ GMHDR_FTYPE_TIMESTAMP_GPS, "GPS" },
|
|
|
|
{ GMHDR_FTYPE_TIMESTAMP_1588, "1588" },
|
2010-06-20 22:36:32 +00:00
|
|
|
{ 0, NULL }
|
2010-06-20 21:18:48 +00:00
|
|
|
};
|
|
|
|
|
2013-01-11 19:20:39 +00:00
|
|
|
#define GMHDR_SRCPORT_G_PLFM_MASK 0x00f80000
|
|
|
|
#define GMHDR_SRCPORT_G_GID_MASK 0x00078000
|
|
|
|
#define GMHDR_SRCPORT_G_BID_MASK 0x00007c00
|
|
|
|
#define GMHDR_SRCPORT_G_PID_MASK 0x000003ff
|
|
|
|
#define GMHDR_SRCPORT_G_PLFM_SHFT 19
|
|
|
|
#define GMHDR_SRCPORT_G_GID_SHFT 15
|
|
|
|
#define GMHDR_SRCPORT_G_BID_SHFT 10
|
|
|
|
#define GMHDR_SRCPORT_G_PID_SHFT 0
|
|
|
|
|
|
|
|
#define GMHDR_SRCPORT_H_PLFM_MASK 0xFC000000
|
|
|
|
#define GMHDR_SRCPORT_H_GID_MASK 0x03C00000
|
|
|
|
#define GMHDR_SRCPORT_H_BID_MASK 0x003F0000
|
|
|
|
#define GMHDR_SRCPORT_H_SID_MASK 0x0000FC00
|
|
|
|
#define GMHDR_SRCPORT_H_PID_MASK 0x000003FF
|
|
|
|
#define GMHDR_SRCPORT_H_PLFM_SHFT 26
|
|
|
|
#define GMHDR_SRCPORT_H_GID_SHFT 20
|
|
|
|
#define GMHDR_SRCPORT_H_BID_SHFT 16
|
|
|
|
#define GMHDR_SRCPORT_H_SID_SHFT 10
|
|
|
|
#define GMHDR_SRCPORT_H_PID_SHFT 0
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
static const value_string gmhdr_plfm_str[] = {
|
|
|
|
{ 0, "Reserved" },
|
|
|
|
{ 1, "GV-2404" },
|
2013-01-11 19:20:39 +00:00
|
|
|
{ 2, "GV-420" },
|
|
|
|
{ 3, "GV-MP" },
|
|
|
|
{ 4, "HD4" },
|
|
|
|
{ 5, "HD8" },
|
2013-05-02 05:16:09 +00:00
|
|
|
{ 6, "GV-212" },
|
|
|
|
{ 7, "HB1" },
|
|
|
|
{ 8, "HC2" },
|
2010-06-19 01:43:11 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static gboolean gmhdr_summary_in_tree = TRUE;
|
2012-06-19 06:18:30 +00:00
|
|
|
static gboolean gmtrailer_summary_in_tree = TRUE;
|
|
|
|
static gboolean gmhdr_decode_timestamp_trailer = TRUE;
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
static int proto_gmhdr = -1;
|
2012-06-19 06:18:30 +00:00
|
|
|
static int proto_gmtrailer = -1;
|
2013-01-11 19:20:39 +00:00
|
|
|
static int hf_gmhdr_srcport_g = -1;
|
|
|
|
static int hf_gmhdr_srcport_g_plfm = -1;
|
|
|
|
static int hf_gmhdr_srcport_g_gid = -1;
|
|
|
|
static int hf_gmhdr_srcport_g_bid = -1;
|
|
|
|
static int hf_gmhdr_srcport_g_pid = -1;
|
2010-06-19 01:43:11 +00:00
|
|
|
static int hf_gmhdr_pktsize = -1;
|
|
|
|
static int hf_gmhdr_timestamp = -1;
|
|
|
|
static int hf_gmhdr_generic = -1;
|
|
|
|
static int hf_gmhdr_etype = -1;
|
|
|
|
static int hf_gmhdr_len = -1;
|
|
|
|
static int hf_gmhdr_trailer = -1;
|
2013-01-11 19:20:39 +00:00
|
|
|
static int hf_gmhdr_origcrc = -1;
|
|
|
|
static int hf_gmhdr_srcport_h = -1;
|
|
|
|
static int hf_gmhdr_srcport_h_plfm = -1;
|
|
|
|
static int hf_gmhdr_srcport_h_gid = -1;
|
|
|
|
static int hf_gmhdr_srcport_h_bid = -1;
|
|
|
|
static int hf_gmhdr_srcport_h_sid = -1;
|
|
|
|
static int hf_gmhdr_srcport_h_pid = -1;
|
2010-06-19 01:43:11 +00:00
|
|
|
|
2012-06-19 06:18:30 +00:00
|
|
|
static int hf_gmtrailer_origcrc = -1;
|
|
|
|
static int hf_gmtrailer_portid = -1;
|
|
|
|
static int hf_gmtrailer_timestamp = -1;
|
|
|
|
|
2010-06-19 01:43:11 +00:00
|
|
|
static gint ett_gmhdr = -1;
|
|
|
|
static gint ett_srcport = -1;
|
2012-06-19 06:18:30 +00:00
|
|
|
static gint ett_gmtrailer = -1;
|
2010-06-19 01:43:11 +00:00
|
|
|
|
2013-05-26 03:29:07 +00:00
|
|
|
static expert_field ei_gmhdr_field_length_invalid = EI_INIT;
|
2010-06-20 21:18:48 +00:00
|
|
|
|
|
|
|
static void
|
2010-06-20 21:43:52 +00:00
|
|
|
dissect_gmtlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gmhdr_tree, guint offset, guint16 length)
|
2010-06-20 21:18:48 +00:00
|
|
|
{
|
|
|
|
proto_tree *ti;
|
|
|
|
proto_tree *srcport_tree;
|
|
|
|
guint16 fl;
|
|
|
|
|
|
|
|
while (length > 1) {
|
|
|
|
guint16 tl = tvb_get_ntohs(tvb, offset);
|
|
|
|
offset += 2; /* type + len */
|
|
|
|
length -= 2;
|
|
|
|
|
|
|
|
fl = tl & 0xff;
|
|
|
|
switch (tl >> 8) {
|
2013-01-11 19:20:39 +00:00
|
|
|
case GMHDR_FTYPE_SRCPORT_G: {
|
2010-06-20 21:18:48 +00:00
|
|
|
guint16 pid;
|
|
|
|
guint32 tv = tvb_get_ntohl(tvb, offset) >> 8; /* Only 24-bit field */
|
2010-07-09 20:27:02 +00:00
|
|
|
|
|
|
|
if (fl != 3) {
|
2013-05-26 03:29:07 +00:00
|
|
|
expert_add_info_format_text(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
|
2010-07-09 20:27:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-01-11 19:20:39 +00:00
|
|
|
ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_srcport_g, tvb, offset, fl, ENC_BIG_ENDIAN);
|
2010-06-20 21:18:48 +00:00
|
|
|
srcport_tree = proto_item_add_subtree(ti, ett_srcport);
|
2013-01-11 19:20:39 +00:00
|
|
|
proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_g_plfm, tvb, offset, fl, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_g_gid, tvb, offset, fl, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_g_bid, tvb, offset, fl, ENC_BIG_ENDIAN);
|
|
|
|
ti = proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_g_pid, tvb, offset, fl, ENC_BIG_ENDIAN);
|
2010-06-20 21:18:48 +00:00
|
|
|
/* If not GV-2404, we need different formula here */
|
2013-01-11 19:20:39 +00:00
|
|
|
pid = ((tv & GMHDR_SRCPORT_G_PID_MASK) >> GMHDR_SRCPORT_G_PID_SHFT) - 24;
|
2010-06-20 21:18:48 +00:00
|
|
|
if (pid >= 1 && pid <= 4) {
|
|
|
|
proto_item_append_text(ti, " (g%d)", pid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GMHDR_FTYPE_PKTSIZE:
|
2010-07-09 20:27:02 +00:00
|
|
|
if (fl != 2) {
|
2013-05-26 03:29:07 +00:00
|
|
|
expert_add_info_format_text(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
|
2010-07-09 20:27:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-10-06 03:35:44 +00:00
|
|
|
proto_tree_add_item(gmhdr_tree, hf_gmhdr_pktsize, tvb, offset, fl, ENC_BIG_ENDIAN);
|
2010-06-20 21:18:48 +00:00
|
|
|
break;
|
2010-10-08 17:37:19 +00:00
|
|
|
case GMHDR_FTYPE_TIMESTAMP_LOCAL:
|
2010-06-20 21:18:48 +00:00
|
|
|
case GMHDR_FTYPE_TIMESTAMP_NTP:
|
2010-09-14 14:43:56 +00:00
|
|
|
case GMHDR_FTYPE_TIMESTAMP_GPS:
|
|
|
|
case GMHDR_FTYPE_TIMESTAMP_1588:
|
2010-07-09 20:27:02 +00:00
|
|
|
if (fl != 8) {
|
2013-05-26 03:29:07 +00:00
|
|
|
expert_add_info_format_text(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
|
2010-07-09 20:27:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-10-12 14:12:36 +00:00
|
|
|
ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_timestamp, tvb, offset, fl, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN);
|
2012-08-10 22:55:02 +00:00
|
|
|
proto_item_append_text(ti, "; Source: %s", val_to_str_const(tl>>8, gmhdr_ftype_timestamp, "Unknown"));
|
2010-06-20 21:18:48 +00:00
|
|
|
break;
|
2013-01-11 19:20:39 +00:00
|
|
|
case GMHDR_FTYPE_FCS: {
|
|
|
|
if (fl != 4) {
|
2013-05-26 03:29:07 +00:00
|
|
|
expert_add_info_format_text(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
|
2013-01-11 19:20:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_origcrc, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
|
|
proto_item_append_text(ti, ", CRC (Not Verified)");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GMHDR_FTYPE_SRCPORT_H: {
|
|
|
|
if (fl != 4) {
|
2013-05-26 03:29:07 +00:00
|
|
|
expert_add_info_format_text(pinfo, gmhdr_tree, &ei_gmhdr_field_length_invalid, "Field length %u invalid", fl);
|
2013-01-11 19:20:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_srcport_h, tvb, offset, fl, ENC_BIG_ENDIAN);
|
|
|
|
srcport_tree = proto_item_add_subtree(ti, ett_srcport);
|
|
|
|
proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_plfm, tvb, offset, fl, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_gid, tvb, offset, fl, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_bid, tvb, offset, fl, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_sid, tvb, offset, fl, ENC_BIG_ENDIAN);
|
2013-01-14 15:09:12 +00:00
|
|
|
proto_tree_add_item(srcport_tree, hf_gmhdr_srcport_h_pid, tvb, offset, fl, ENC_BIG_ENDIAN);
|
2013-01-11 19:20:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-06-20 21:18:48 +00:00
|
|
|
default:
|
2011-10-04 22:44:31 +00:00
|
|
|
ti = proto_tree_add_item(gmhdr_tree, hf_gmhdr_generic, tvb, offset, fl, ENC_NA);
|
2010-06-20 21:18:48 +00:00
|
|
|
proto_item_append_text(ti, " [Id: %u, Length: %u]", tl >> 8, fl);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Adjust for the field length */
|
|
|
|
offset += fl;
|
|
|
|
length -= fl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-06-19 01:43:11 +00:00
|
|
|
static void
|
|
|
|
dissect_gmhdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
2010-06-23 00:04:37 +00:00
|
|
|
proto_tree *ti;
|
|
|
|
gint16 length;
|
|
|
|
volatile guint16 encap_proto;
|
|
|
|
volatile gboolean is_802_2;
|
2010-06-20 21:18:48 +00:00
|
|
|
proto_tree *volatile gmhdr_tree = NULL;
|
2010-06-23 00:04:37 +00:00
|
|
|
volatile guint offset = 0;
|
2010-06-19 01:43:11 +00:00
|
|
|
|
2010-06-20 21:18:48 +00:00
|
|
|
length = tvb_get_guint8(tvb, offset); /* Length of the Gigamon header */
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
if (tree) {
|
2011-10-21 02:10:19 +00:00
|
|
|
ti = proto_tree_add_item(tree, proto_gmhdr, tvb, offset, length, ENC_NA);
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
if (gmhdr_summary_in_tree) {
|
2010-06-20 21:18:48 +00:00
|
|
|
proto_item_append_text(ti, ", Length: %u", length);
|
2010-06-19 01:43:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gmhdr_tree = proto_item_add_subtree(ti, ett_gmhdr);
|
2010-06-20 21:18:48 +00:00
|
|
|
dissect_gmtlv(tvb, pinfo, gmhdr_tree, offset+1, length-1);
|
2010-06-19 01:43:11 +00:00
|
|
|
|
2010-06-20 21:18:48 +00:00
|
|
|
} /* if (tree) */
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
offset += length;
|
|
|
|
encap_proto = tvb_get_ntohs(tvb, offset);
|
|
|
|
offset += 2;
|
|
|
|
if (encap_proto <= IEEE_802_3_MAX_LEN) {
|
|
|
|
/* Is there an 802.2 layer? I can tell by looking at the first 2
|
|
|
|
bytes after the GMHDR header. If they are 0xffff, then what
|
|
|
|
follows the GMHDR header is an IPX payload, meaning no 802.2.
|
|
|
|
(IPX/SPX is they only thing that can be contained inside a
|
|
|
|
straight 802.3 packet, so presumably the same applies for
|
|
|
|
Ethernet GMHDR packets). A non-0xffff value means that there's an
|
|
|
|
802.2 layer inside the GMHDR layer */
|
|
|
|
is_802_2 = TRUE;
|
2010-10-08 17:37:19 +00:00
|
|
|
|
2010-10-11 20:16:35 +00:00
|
|
|
/* Don't throw an exception for this check (even a BoundsError) */
|
2010-10-08 17:37:19 +00:00
|
|
|
if (tvb_length_remaining(tvb, offset) >= 2) {
|
2010-06-19 01:43:11 +00:00
|
|
|
if (tvb_get_ntohs(tvb, offset) == 0xffff) {
|
|
|
|
is_802_2 = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dissect_802_3(encap_proto, is_802_2, tvb, offset, pinfo, tree, gmhdr_tree,
|
|
|
|
hf_gmhdr_len, hf_gmhdr_trailer, 0);
|
|
|
|
} else {
|
|
|
|
ethertype(encap_proto, tvb, offset, pinfo, tree, gmhdr_tree,
|
|
|
|
hf_gmhdr_etype, hf_gmhdr_trailer, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-19 06:18:30 +00:00
|
|
|
static int
|
2012-09-10 21:40:21 +00:00
|
|
|
dissect_gmtimestamp_trailer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
|
2012-06-19 06:18:30 +00:00
|
|
|
{
|
|
|
|
proto_tree *ti;
|
|
|
|
guint tvblen, trailer_len = 18;
|
|
|
|
proto_tree *gmtrailer_tree = NULL;
|
|
|
|
guint offset = 0;
|
|
|
|
guint32 orig_crc, new_crc, comp_crc;
|
|
|
|
guint16 port_num;
|
2012-12-05 15:56:36 +00:00
|
|
|
nstime_t gmtimev;
|
2012-06-19 06:18:30 +00:00
|
|
|
|
|
|
|
struct tm *tm = NULL;
|
|
|
|
|
|
|
|
if ( ! gmhdr_decode_timestamp_trailer)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* See if this packet has a Gigamon trailer, if yes, then decode it */
|
|
|
|
/* (Don't throw any exceptions while checking for the trailer). */
|
|
|
|
tvblen = tvb_length(tvb); /* end+1 */
|
|
|
|
if (tvblen < trailer_len)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
orig_crc = tvb_get_ntohl(tvb, offset);
|
|
|
|
new_crc = tvb_get_ntohl(tvb, tvblen - 4);
|
|
|
|
|
|
|
|
/* Verify the checksum; if not valid, it means that the trailer is not valid */
|
|
|
|
comp_crc = CRC32C_SWAP(crc32_ccitt_tvb_seed(tvb, 14, CRC32C_SWAP(~orig_crc)));
|
|
|
|
if (comp_crc != new_crc)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* OK: We appear to have a Gigamon trailer */
|
|
|
|
if (tree) {
|
|
|
|
ti = proto_tree_add_item(tree, proto_gmtrailer, tvb, offset, trailer_len - 4, ENC_NA);
|
|
|
|
|
|
|
|
if (gmtrailer_summary_in_tree) {
|
|
|
|
offset += 4;
|
|
|
|
port_num = tvb_get_ntohs(tvb, offset);
|
|
|
|
offset += 2;
|
2012-12-05 15:56:36 +00:00
|
|
|
gmtimev.secs = tvb_get_ntohl(tvb, offset);
|
2012-06-19 06:18:30 +00:00
|
|
|
offset += 4;
|
2012-12-05 15:56:36 +00:00
|
|
|
gmtimev.nsecs = tvb_get_ntohl(tvb, offset);
|
2012-06-19 06:18:30 +00:00
|
|
|
|
2012-12-05 15:56:36 +00:00
|
|
|
tm = localtime(&gmtimev.secs);
|
|
|
|
proto_item_append_text(ti, ", Port: %d, Timestamp: %d:%d:%d.%d", port_num, tm->tm_hour, tm->tm_min, tm->tm_sec, gmtimev.nsecs);
|
2012-06-19 06:18:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
gmtrailer_tree = proto_item_add_subtree(ti, ett_gmtrailer);
|
|
|
|
proto_tree_add_item(gmtrailer_tree, hf_gmtrailer_origcrc, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(gmtrailer_tree, hf_gmtrailer_portid, tvb, offset+4, 2, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(gmtrailer_tree, hf_gmtrailer_timestamp, tvb, offset+6, 8, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 14;
|
|
|
|
}
|
|
|
|
|
2010-06-19 01:43:11 +00:00
|
|
|
static int
|
2012-09-10 21:40:21 +00:00
|
|
|
dissect_gmtrailer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
|
2010-06-19 01:43:11 +00:00
|
|
|
{
|
|
|
|
proto_tree *ti;
|
2010-06-22 15:33:27 +00:00
|
|
|
guint tvblen, length;
|
2010-06-20 21:18:48 +00:00
|
|
|
proto_tree *gmhdr_tree = NULL;
|
|
|
|
guint offset;
|
2013-01-11 19:20:39 +00:00
|
|
|
guint16 cksum, comp_cksum, extra_trailer;
|
2010-10-08 17:37:19 +00:00
|
|
|
|
|
|
|
/* See if this packet has a Gigamon trailer, if yes, then decode it */
|
2010-06-22 15:33:27 +00:00
|
|
|
/* (Don't throw any exceptions while checking for the trailer). */
|
|
|
|
tvblen = tvb_length(tvb); /* end+1 */
|
|
|
|
if (tvblen < 5)
|
2010-06-23 00:04:37 +00:00
|
|
|
return 0;
|
2013-01-11 20:25:05 +00:00
|
|
|
extra_trailer = 0;
|
2013-01-11 19:20:39 +00:00
|
|
|
if (tvb_get_ntohs(tvb, tvblen-4) != ETHERTYPE_GIGAMON) {
|
2013-03-11 19:32:33 +00:00
|
|
|
if (tvblen < 10){
|
|
|
|
return 0;
|
|
|
|
}
|
2013-01-11 19:20:39 +00:00
|
|
|
if (tvb_get_ntohs(tvb, tvblen-8) == ETHERTYPE_GIGAMON) {
|
|
|
|
extra_trailer = 4;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
length = tvb_get_guint8(tvb, tvblen-extra_trailer-5); /* length of Gigamon header */
|
|
|
|
if ((tvblen-extra_trailer-5) != length)
|
2010-06-23 00:04:37 +00:00
|
|
|
return 0;
|
2010-06-22 15:33:27 +00:00
|
|
|
|
2013-01-11 19:20:39 +00:00
|
|
|
offset = tvblen - extra_trailer - 5 - length;
|
2010-06-22 15:33:27 +00:00
|
|
|
|
2013-01-11 19:20:39 +00:00
|
|
|
cksum = tvb_get_ntohs(tvb, tvblen-extra_trailer-2);
|
2010-06-19 01:43:11 +00:00
|
|
|
|
2010-06-20 21:18:48 +00:00
|
|
|
/* Verify the checksum; if not valid, it means that the trailer is not valid */
|
2010-06-19 01:43:11 +00:00
|
|
|
{
|
|
|
|
vec_t vec;
|
|
|
|
vec.len = length + 3;
|
2010-06-20 21:18:48 +00:00
|
|
|
vec.ptr = tvb_get_ptr(tvb, offset, vec.len);
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
comp_cksum = in_cksum(&vec, 1);
|
|
|
|
if (pntohs(&comp_cksum) != cksum) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-22 15:33:27 +00:00
|
|
|
/* OK: We appear to have a Gigamon trailer */
|
2010-06-19 01:43:11 +00:00
|
|
|
if (tree) {
|
2011-10-21 02:10:19 +00:00
|
|
|
ti = proto_tree_add_item(tree, proto_gmhdr, tvb, offset, length + 5, ENC_NA);
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
if (gmhdr_summary_in_tree) {
|
|
|
|
proto_item_append_text(ti, ", Length: %u, Checksum: 0x%x", length, cksum);
|
|
|
|
}
|
|
|
|
|
|
|
|
gmhdr_tree = proto_item_add_subtree(ti, ett_gmhdr);
|
|
|
|
|
2010-06-20 21:18:48 +00:00
|
|
|
dissect_gmtlv(tvb, pinfo, gmhdr_tree, offset, length);
|
2013-01-11 19:20:39 +00:00
|
|
|
if (extra_trailer) {
|
|
|
|
proto_tree_add_item(tree, hf_gmhdr_trailer, tvb, length + 5, extra_trailer, ENC_BIG_ENDIAN);
|
|
|
|
}
|
2010-06-19 01:43:11 +00:00
|
|
|
}
|
2010-06-22 15:33:27 +00:00
|
|
|
return tvblen;
|
2010-06-19 01:43:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_gmhdr(void)
|
|
|
|
{
|
|
|
|
static hf_register_info hf[] = {
|
2013-01-11 19:20:39 +00:00
|
|
|
{ &hf_gmhdr_srcport_g, {
|
|
|
|
"Src Port", "gmhdr.srcport_g", FT_UINT24, BASE_HEX,
|
2010-06-23 00:04:37 +00:00
|
|
|
NULL, 0, "Original Source Port", HFILL }},
|
2013-01-11 19:20:39 +00:00
|
|
|
{ &hf_gmhdr_srcport_g_plfm, {
|
|
|
|
"Platform Id", "gmhdr.srcport_g_plfm", FT_UINT24, BASE_DEC,
|
|
|
|
VALS(gmhdr_plfm_str), GMHDR_SRCPORT_G_PLFM_MASK, "Original Platform Id", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_g_gid, {
|
|
|
|
"Group Id", "gmhdr.srcport_g_gid", FT_UINT24, BASE_DEC,
|
|
|
|
NULL, GMHDR_SRCPORT_G_GID_MASK, "Original Source Group Id", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_g_bid, {
|
|
|
|
"Box Id", "gmhdr.srcport_g_bid", FT_UINT24, BASE_DEC,
|
|
|
|
NULL, GMHDR_SRCPORT_G_BID_MASK, "Original Source Box Id", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_g_pid, {
|
|
|
|
"Port Id", "gmhdr.srcport_g_pid", FT_UINT24, BASE_DEC,
|
|
|
|
NULL, GMHDR_SRCPORT_G_PID_MASK, "Original Source Port Id", HFILL }},
|
2010-06-23 00:04:37 +00:00
|
|
|
{ &hf_gmhdr_pktsize, {
|
|
|
|
"Original Packet Size", "gmhdr.pktsize", FT_UINT16, BASE_DEC,
|
|
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_gmhdr_timestamp, {
|
|
|
|
"Time Stamp", "gmhdr.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
|
|
|
|
NULL, 0x0, NULL, HFILL }},
|
|
|
|
{ &hf_gmhdr_generic, {
|
|
|
|
"Generic Field", "gmhdr.generic", FT_BYTES, BASE_NONE,
|
|
|
|
NULL, 0x0, NULL, HFILL }},
|
|
|
|
{ &hf_gmhdr_etype, {
|
|
|
|
"Type", "gmhdr.etype", FT_UINT16, BASE_HEX,
|
|
|
|
VALS(etype_vals), 0x0, "Ethertype", HFILL }},
|
|
|
|
{ &hf_gmhdr_len, {
|
|
|
|
"Length", "gmhdr.len", FT_UINT16, BASE_DEC,
|
|
|
|
NULL, 0x0, NULL, HFILL }},
|
2013-01-11 19:20:39 +00:00
|
|
|
{ &hf_gmhdr_origcrc, {
|
|
|
|
"Original CRC", "gmhdr.crc", FT_UINT32, BASE_HEX,
|
|
|
|
NULL, 0x0, "Original Packet CRC", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_h, {
|
|
|
|
"Src Port", "gmhdr.srcport", FT_UINT32, BASE_HEX,
|
|
|
|
NULL, 0, "Original Source Port", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_h_plfm, {
|
|
|
|
"Platform Id", "gmhdr.srcport_plfm", FT_UINT32, BASE_DEC,
|
|
|
|
VALS(gmhdr_plfm_str), GMHDR_SRCPORT_H_PLFM_MASK, "Original Platform Id", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_h_gid, {
|
|
|
|
"Group Id", "gmhdr.srcport_gid", FT_UINT32, BASE_DEC,
|
|
|
|
NULL, GMHDR_SRCPORT_H_GID_MASK, "Original Source Group Id", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_h_bid, {
|
|
|
|
"Box Id", "gmhdr.srcport_bid", FT_UINT32, BASE_DEC,
|
|
|
|
NULL, GMHDR_SRCPORT_H_BID_MASK, "Original Source Box Id", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_h_sid, {
|
|
|
|
"Slot Id", "gmhdr.srcport_sid", FT_UINT32, BASE_DEC,
|
|
|
|
NULL, GMHDR_SRCPORT_H_SID_MASK, "Original Source Slot Id", HFILL }},
|
|
|
|
{ &hf_gmhdr_srcport_h_pid, {
|
|
|
|
"Port Id", "gmhdr.srcport_pid", FT_UINT32, BASE_DEC,
|
|
|
|
NULL, GMHDR_SRCPORT_H_PID_MASK, "Original Source Port Id", HFILL }},
|
2010-06-23 00:04:37 +00:00
|
|
|
{ &hf_gmhdr_trailer, {
|
|
|
|
"Trailer", "gmhdr.trailer", FT_BYTES, BASE_NONE,
|
2012-06-19 06:18:30 +00:00
|
|
|
NULL, 0x0, "GMHDR Trailer", HFILL }},
|
|
|
|
};
|
|
|
|
static hf_register_info gmtrailer_hf[] = {
|
|
|
|
{ &hf_gmtrailer_origcrc, {
|
|
|
|
"Original CRC", "gmtrailer.crc", FT_UINT32, BASE_HEX,
|
|
|
|
NULL, 0x0, "Original Packet CRC", HFILL }},
|
|
|
|
{ &hf_gmtrailer_portid, {
|
|
|
|
"Src Port", "gmtrailer.portid", FT_UINT16, BASE_HEX,
|
|
|
|
NULL, 0x0, "Origin Source Port", HFILL }},
|
|
|
|
{ &hf_gmtrailer_timestamp, {
|
|
|
|
"Time Stamp", "gmtrailer.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
|
|
|
|
NULL, 0x0, NULL, HFILL }},
|
2010-06-19 01:43:11 +00:00
|
|
|
};
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_gmhdr,
|
|
|
|
&ett_srcport
|
|
|
|
};
|
2012-06-19 06:18:30 +00:00
|
|
|
static gint *gmtrailer_ett[] = {
|
|
|
|
&ett_gmtrailer,
|
|
|
|
};
|
2013-05-26 03:29:07 +00:00
|
|
|
static ei_register_info ei[] = {
|
|
|
|
{ &ei_gmhdr_field_length_invalid, { "gmhdr.field_length_invalid", PI_MALFORMED, PI_ERROR, "Field length invalid", EXPFILL }},
|
|
|
|
};
|
|
|
|
|
2010-06-19 01:43:11 +00:00
|
|
|
module_t *gmhdr_module;
|
2012-06-19 06:18:30 +00:00
|
|
|
module_t *gmtrailer_module;
|
2013-05-26 03:29:07 +00:00
|
|
|
expert_module_t* expert_gmhdr;
|
2010-06-19 01:43:11 +00:00
|
|
|
|
|
|
|
proto_gmhdr = proto_register_protocol("Gigamon Header", "GMHDR", "gmhdr");
|
|
|
|
proto_register_field_array(proto_gmhdr, hf, array_length(hf));
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2013-05-26 03:29:07 +00:00
|
|
|
expert_gmhdr = expert_register_protocol(proto_gmhdr);
|
|
|
|
expert_register_field_array(expert_gmhdr, ei, array_length(ei));
|
2010-06-19 01:43:11 +00:00
|
|
|
|
2012-06-19 06:18:30 +00:00
|
|
|
proto_gmtrailer = proto_register_protocol("Gigamon Trailer", "GMTRAILER", "gmtrailer");
|
|
|
|
proto_register_field_array(proto_gmtrailer, gmtrailer_hf, array_length(gmtrailer_hf));
|
|
|
|
proto_register_subtree_array(gmtrailer_ett, array_length(gmtrailer_ett));
|
|
|
|
|
2010-06-20 21:18:48 +00:00
|
|
|
gmhdr_module = prefs_register_protocol(proto_gmhdr, NULL);
|
2010-06-19 01:43:11 +00:00
|
|
|
prefs_register_bool_preference(gmhdr_module, "summary_in_tree",
|
|
|
|
"Show Gigamon header summary in protocol tree",
|
|
|
|
"Whether the Gigamon header summary line should be shown in the protocol tree",
|
|
|
|
&gmhdr_summary_in_tree);
|
2012-06-19 06:18:30 +00:00
|
|
|
|
|
|
|
gmtrailer_module = prefs_register_protocol(proto_gmtrailer, NULL);
|
|
|
|
prefs_register_bool_preference(gmtrailer_module, "summary_in_tree",
|
|
|
|
"Show Gigamon Trailer summary in protocol tree",
|
|
|
|
"Whether the Gigamon Trailer summary line should be shown in the protocol tree",
|
|
|
|
&gmtrailer_summary_in_tree);
|
|
|
|
prefs_register_bool_preference(gmtrailer_module, "decode_trailer_timestamp",
|
|
|
|
"Decode Gigamon HW timestamp and source id in trailer",
|
|
|
|
"Whether the Gigamon trailer containing HW timestamp, source id and original CRC should be decoded",
|
|
|
|
&gmhdr_decode_timestamp_trailer);
|
2010-06-19 01:43:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_gmhdr(void)
|
|
|
|
{
|
2010-06-20 21:18:48 +00:00
|
|
|
dissector_handle_t gmhdr_handle;
|
|
|
|
|
|
|
|
gmhdr_handle = create_dissector_handle(dissect_gmhdr, proto_gmhdr);
|
2010-12-20 05:35:29 +00:00
|
|
|
dissector_add_uint("ethertype", ETHERTYPE_GIGAMON, gmhdr_handle);
|
2010-06-20 21:18:48 +00:00
|
|
|
heur_dissector_add("eth.trailer", dissect_gmtrailer, proto_gmhdr);
|
2012-06-19 06:18:30 +00:00
|
|
|
|
|
|
|
heur_dissector_add("eth.trailer", dissect_gmtimestamp_trailer, proto_gmtrailer);
|
2010-06-19 01:43:11 +00:00
|
|
|
}
|
|
|
|
|