aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorStig Bjørlykke <stig@bjorlykke.org>2009-07-07 11:13:22 +0000
committerStig Bjørlykke <stig@bjorlykke.org>2009-07-07 11:13:22 +0000
commit09218f73384cc2bf7544476c4c8f70d069619475 (patch)
tree3bfe9c40048cfa003ec352e32c7c038284a94e65 /plugins
parent3f625c283e4ece33e6444f449496ef220f49f0c6 (diff)
From Richard Kummel:
- New dissector for EtherCAT Switch Link Header added to EtherCAT plugin - Changed filtering of EtherCAT commands to the abbreviated form: e.g. ecat.cmd = APWR From me: - Mark unused variables - Fixed a string warning - Do not initialize a static struct - Use tfs_yes_no - Reorder files in Makefile svn path=/trunk/; revision=28976
Diffstat (limited to 'plugins')
-rw-r--r--plugins/ethercat/Makefile.common12
-rw-r--r--plugins/ethercat/packet-esl.c283
-rw-r--r--plugins/ethercat/packet-esl.h67
-rw-r--r--plugins/ethercat/packet-ethercat-datagram.c64
4 files changed, 396 insertions, 30 deletions
diff --git a/plugins/ethercat/Makefile.common b/plugins/ethercat/Makefile.common
index bbcc02ffb7..647465793c 100644
--- a/plugins/ethercat/Makefile.common
+++ b/plugins/ethercat/Makefile.common
@@ -28,18 +28,20 @@ PLUGIN_NAME = ethercat
# the dissector sources (without any helpers)
DISSECTOR_SRC = \
- packet-ethercat-frame.c \
- packet-ioraw.c \
- packet-nv.c \
packet-ams.c \
packet-ecatmb.c \
- packet-ethercat-datagram.c
+ packet-esl.c \
+ packet-ethercat-datagram.c \
+ packet-ethercat-frame.c \
+ packet-ioraw.c \
+ packet-nv.c
# corresponding headers
DISSECTOR_INCLUDES = \
packet-ams.h \
- packet-ethercat-frame.h \
packet-ecatmb.h \
+ packet-esl.h \
packet-ethercat-datagram.h \
+ packet-ethercat-frame.h \
packet-ioraw.h \
packet-nv.h
diff --git a/plugins/ethercat/packet-esl.c b/plugins/ethercat/packet-esl.c
new file mode 100644
index 0000000000..063f9ccae5
--- /dev/null
+++ b/plugins/ethercat/packet-esl.c
@@ -0,0 +1,283 @@
+/* packet-esl.c
+ * Routines for EtherCAT Switch Link disassembly
+ *
+ * $Id$
+ *
+ * Copyright (c) 2007 by Beckhoff Automation GmbH
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1999 Gerald Combs
+ *
+ * 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
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Include files */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/tfs.h>
+
+#include "packet-esl.h"
+
+static dissector_handle_t eth_withoutfcs_handle = NULL;
+static int esl_enable_dissector = FALSE;
+
+void proto_reg_handoff_esl(void);
+
+/* Define the esl proto */
+int proto_esl = -1;
+
+static int ett_esl = -1;
+
+static int hf_esl_timestamp = -1;
+static int hf_esl_port = -1;
+static int hf_esl_crcerror = -1;
+static int hf_esl_alignerror = -1;
+
+static guint16 flags_to_port(guint16 flagsValue) {
+ EslFlagsUnion flagsUnion;
+ flagsUnion.flags = flagsValue;
+ if ( flagsUnion.d.port0 )
+ return 0;
+ else if ( flagsUnion.d.port1 )
+ return 1;
+ else if ( flagsUnion.d.port2 )
+ return 2;
+ else if ( flagsUnion.d.port3 )
+ return 3;
+ else if ( flagsUnion.d.port4 )
+ return 4;
+ else if ( flagsUnion.d.port5 )
+ return 5;
+ else if ( flagsUnion.d.port6 )
+ return 6;
+ else if ( flagsUnion.d.port7 )
+ return 7;
+ else if ( flagsUnion.d.port8 )
+ return 8;
+ else if ( flagsUnion.d.port9 )
+ return 9;
+
+ return -1;
+}
+
+
+/*esl*/
+static void
+dissect_esl_header(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree) {
+
+ proto_item *ti = NULL;
+ proto_tree *esl_header_tree;
+ gint offset = 0;
+
+ guint esl_length = tvb_reported_length(tvb);
+ if ( esl_length >= SIZEOF_ESLHEADER )
+ {
+ if (tree)
+ {
+ guint16 flags;
+
+ ti = proto_tree_add_item(tree, proto_esl, tvb, 0, SIZEOF_ESLHEADER, TRUE);
+ esl_header_tree = proto_item_add_subtree(ti, ett_esl);
+ offset+=6;
+
+ flags = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(esl_header_tree, hf_esl_port, tvb, offset, 2, flags_to_port(flags));
+
+ proto_tree_add_item(esl_header_tree, hf_esl_crcerror, tvb, offset, 2, TRUE);
+ proto_tree_add_item(esl_header_tree, hf_esl_alignerror, tvb, offset, 2, TRUE);
+ offset+=2;
+
+ proto_tree_add_item(esl_header_tree, hf_esl_timestamp, tvb, offset, 8, TRUE);
+ }
+ }
+}
+
+typedef struct _ref_time_frame_info
+{
+ frame_data *fd;
+ guint64 esl_ts;
+ nstime_t abs_ts;
+ guint32 num;
+} ref_time_frame_info;
+
+static ref_time_frame_info ref_time_frame;
+
+gboolean is_esl_header(tvbuff_t *tvb, gint offset)
+{
+ return tvb_get_guint8(tvb, offset) == 0x01 &&
+ tvb_get_guint8(tvb, offset+1) == 0x01 &&
+ tvb_get_guint8(tvb, offset+2) == 0x05 &&
+ tvb_get_guint8(tvb, offset+3) == 0x10 &&
+ tvb_get_guint8(tvb, offset+4) == 0x00 &&
+ tvb_get_guint8(tvb, offset+5) == 0x00;
+}
+
+void modify_times(tvbuff_t *tvb, gint offset, packet_info *pinfo)
+{
+ if ( ref_time_frame.fd == NULL )
+ {
+ ref_time_frame.esl_ts = tvb_get_letoh64(tvb, offset+8);
+ ref_time_frame.fd = pinfo->fd;
+ ref_time_frame.num = pinfo->fd->num;
+ ref_time_frame.abs_ts = pinfo->fd->abs_ts;
+ }
+ else if ( !pinfo->fd->flags.visited )
+ {
+ guint64 nsecs = tvb_get_letoh64(tvb, offset+8) - ref_time_frame.esl_ts;
+ guint64 secs = nsecs/1000000000;
+ nstime_t ts;
+ nstime_t ts_delta;
+
+ ts.nsecs = ref_time_frame.abs_ts.nsecs + (int)(nsecs-(secs*1000000000));
+ if ( ts.nsecs > 1000000000 )
+ {
+ ts.nsecs-=1000000000;
+ secs++;
+ }
+
+ ts.secs = ref_time_frame.abs_ts.secs+(int)secs;
+ nstime_delta(&ts_delta, &ts, &pinfo->fd->abs_ts);
+
+ pinfo->fd->abs_ts = ts;
+ nstime_add(&pinfo->fd->rel_ts, &ts_delta);
+ nstime_add(&pinfo->fd->del_dis_ts, &ts_delta);
+ nstime_add(&pinfo->fd->del_cap_ts, &ts_delta);
+ }
+}
+
+static gboolean
+dissect_esl_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ static gboolean in_heur = FALSE;
+ gboolean result;
+ tvbuff_t *next_tvb;
+ guint esl_length = tvb_length(tvb);
+
+ if ( in_heur )
+ return FALSE;
+
+ in_heur = TRUE;
+ /*TRY */
+ {
+ if ( ref_time_frame.fd != NULL && !pinfo->fd->flags.visited && pinfo->fd->num <= ref_time_frame.num )
+ ref_time_frame.fd = NULL;
+
+ /* Check that there's enough data */
+ if ( tvb_length(tvb) < SIZEOF_ESLHEADER )
+ return FALSE;
+
+ /* check for Esl frame, this has a unique destination MAC from Beckhoff range
+ First 6 bytes must be: 01 01 05 10 00 00 */
+ if ( is_esl_header(tvb, 0) )
+ {
+ dissect_esl_header(tvb, pinfo, tree);
+ if ( eth_withoutfcs_handle != NULL )
+ {
+ next_tvb = tvb_new_subset(tvb, SIZEOF_ESLHEADER, -1, -1);
+ call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
+ }
+ modify_times(tvb, 0, pinfo);
+ result = TRUE;
+ }
+ else if ( is_esl_header(tvb, esl_length-SIZEOF_ESLHEADER) )
+ {
+ if ( eth_withoutfcs_handle != NULL )
+ {
+ next_tvb = tvb_new_subset(tvb, 0, esl_length-SIZEOF_ESLHEADER, esl_length-SIZEOF_ESLHEADER);
+ call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
+ }
+ next_tvb = tvb_new_subset(tvb, esl_length-SIZEOF_ESLHEADER, SIZEOF_ESLHEADER, SIZEOF_ESLHEADER);
+ dissect_esl_header(next_tvb, pinfo, tree);
+ modify_times(tvb, esl_length-SIZEOF_ESLHEADER, pinfo);
+
+ result = TRUE;
+ }
+ else
+ {
+ result = FALSE;
+ }
+ }
+ /*CATCH_ALL{
+ in_heur = FALSE;
+ RETHROW;
+ }ENDTRY;*/
+ in_heur = FALSE;
+ return result;
+}
+
+void
+proto_register_esl(void) {
+ static hf_register_info hf[] = {
+ { &hf_esl_port,
+ { "Port", "esl.port",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ NULL, 0xC0FF, 0, 0, 0, NULL, NULL }
+ },
+ { &hf_esl_crcerror,
+ { "Crc Error", "esl.crcerror",
+ FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x1000,
+ NULL, HFILL }
+ },
+ { &hf_esl_alignerror,
+ { "Alignment Error", "esl.alignerror",
+ FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0800,
+ NULL, HFILL }
+ },
+ { &hf_esl_timestamp,
+ { "timestamp", "esl.timestamp",
+ FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_esl,
+ };
+
+ module_t *esl_module;
+
+ proto_esl = proto_register_protocol("EtherCAT Switch Link",
+ "ESL","esl");
+
+ esl_module = prefs_register_protocol(proto_esl, proto_reg_handoff_esl);
+
+ prefs_register_bool_preference(esl_module, "enable", "Enable dissector",
+ "Enable this dissector (default is false)",
+ &esl_enable_dissector);
+
+
+ proto_register_field_array(proto_esl,hf,array_length(hf));
+ proto_register_subtree_array(ett,array_length(ett));
+
+ register_dissector("esl", dissect_esl_header, proto_esl);
+}
+
+void
+proto_reg_handoff_esl(void) {
+ static dissector_handle_t esl_handle;
+
+ esl_handle = create_dissector_handle(dissect_esl_header, proto_esl);
+ eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
+
+ heur_dissector_add("eth", dissect_esl_heur, proto_esl);
+ proto_set_decoding(proto_esl, esl_enable_dissector);
+}
diff --git a/plugins/ethercat/packet-esl.h b/plugins/ethercat/packet-esl.h
new file mode 100644
index 0000000000..858312debb
--- /dev/null
+++ b/plugins/ethercat/packet-esl.h
@@ -0,0 +1,67 @@
+/* packet-esl.h
+ *
+ * $Id$
+ *
+ * Copyright (c) 2007 by Beckhoff Automation GmbH
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_ESL_H_
+#define _PACKET_ESL_H_
+
+typedef union _EslFlagsUnion
+{
+ struct
+ {
+ guint16 port7 : 1;
+ guint16 port6 : 1;
+ guint16 port5 : 1;
+ guint16 port4 : 1;
+ guint16 port3 : 1;
+ guint16 port2 : 1;
+ guint16 port1 : 1;
+ guint16 port0 : 1;
+ guint16 extended : 1;
+ guint16 reserved : 2;
+ guint16 crcError : 1;
+ guint16 alignError : 1;
+ guint16 timeStampEna: 1;
+ guint16 port9 : 1;
+ guint16 port8 : 1;
+ }d;
+ struct
+ {
+ guint8 loPorts : 1;
+ guint8 flagsHiPorts : 1;
+ }lo_hi_flags;
+ guint flags;
+}EslFlagsUnion;
+
+/*
+typedef struct _EslHeader
+{
+ guint8 eslCookie[6]; // 01 01 05 10 00 00
+ EslFlagsUnion flags;
+ guint64 timeStamp;
+} EslHeader, *PEslHeader;*/
+
+
+#define SIZEOF_ESLHEADER 16
+#endif /* _PACKET_ESL_H_*/
diff --git a/plugins/ethercat/packet-ethercat-datagram.c b/plugins/ethercat/packet-ethercat-datagram.c
index 6daefb77e8..a737e33fec 100644
--- a/plugins/ethercat/packet-ethercat-datagram.c
+++ b/plugins/ethercat/packet-ethercat-datagram.c
@@ -157,20 +157,20 @@ static const value_string EcCmdShort[] =
static const value_string EcCmdLong[] =
{
{ 0, "No operation" },
- { 1, "Auto increment read" },
- { 2, "Auto increment write" },
- { 3, "Auto increment read write" },
- { 4, "Configured address read" },
- { 5, "Configured address write" },
- { 6, "Configured address read write" },
- { 7, "Broadcast read" },
- { 8, "Broadcast write" },
- { 9, "Broadcast read write" },
- { 10, "Logical memory read" },
- { 11, "Logical memory write" },
- { 12, "Logical memory read write" },
- { 13, "Auto increment read multiple write" },
- { 14, "Configured read multiple write" },
+ { 1, "Auto Increment Physical Read" },
+ { 2, "Auto Increment Physical Write" },
+ { 3, "Auto Increment Physical ReadWrite" },
+ { 4, "Configured address Physical Read" },
+ { 5, "Configured address Physical Write" },
+ { 6, "Configured address Physical ReadWrite" },
+ { 7, "Broadcast Read" },
+ { 8, "Broadcast Write" },
+ { 9, "Broadcast ReadWrite" },
+ { 10, "Logical Read" },
+ { 11, "Logical Write" },
+ { 12, "Logical ReadWrite" },
+ { 13, "Auto Increment Physical Read Multiple Write" },
+ { 14, "Configured Address Physical Read Multiple Write" },
{ 255, "EXT" },
{ 0, NULL }
};
@@ -393,6 +393,18 @@ static void EcSummaryFormater(guint32 datalength, tvbuff_t *tvb, gint offset, ch
nSub, nLen, convertEcCmdToText(ecFirst.cmd, EcCmdShort));
}
+static void EcCmdFormatter(guint8 cmd, char *szText, gint nMax)
+{
+ gint idx=0;
+ const gchar *szCmd = match_strval_idx((guint32)cmd, EcCmdLong, &idx);
+
+ if ( idx != -1 )
+ g_snprintf(szText, nMax, "Cmd : %d (%s)", cmd, szCmd);
+ else
+ g_snprintf(szText, nMax, "Cmd : %d (Unknown command)", cmd);
+}
+
+
static void EcSubFormatter(tvbuff_t *tvb, gint offset, char *szText, gint nMax)
{
EcParserHDR ecParser;
@@ -548,7 +560,9 @@ static void dissect_ecat_datagram(tvbuff_t *tvb, packet_info *pinfo, proto_tree
aitem = proto_tree_add_text(ecat_datagram_tree, tvb, offset, EcParserHDR_Len, "Header");
ecat_header_tree = proto_item_add_subtree(aitem, ett_ecat_header);
+ EcCmdFormatter(ecHdr.cmd, szText, nMax);
aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_cmd, tvb, suboffset, sizeof(ecHdr.cmd), TRUE);
+ proto_item_set_text(aitem, "%s", szText);
if( subCount < 10 ){
aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_cmd[subCount], tvb, suboffset, sizeof(ecHdr.cmd), TRUE);
PROTO_ITEM_SET_HIDDEN(aitem);
@@ -969,47 +983,47 @@ void proto_register_ecat(void)
},
{ &hf_ecat_cmd,
{ "Command", "ecat.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[0],
{ "Command", "ecat.sub1.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[1],
{ "Command", "ecat.sub2.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[2],
{ "Command", "ecat.sub3.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[3],
{ "Command", "ecat.sub4.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[4],
{ "Command", "ecat.sub5.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[5],
{ "Command", "ecat.sub6.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[6],
{ "Command", "ecat.sub7.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[7],
{ "Command", "ecat.sub8.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[8],
{ "Command", "ecat.sub9.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_sub_cmd[9],
{ "Command", "ecat.sub10.cmd",
- FT_UINT8, BASE_HEX, VALS(EcCmdLong), 0x0, NULL, HFILL }
+ FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL }
},
{ &hf_ecat_idx,
{ "Index", "ecat.idx",