aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2012-10-31 20:09:05 +0000
committerMichael Mann <mmann78@netscape.net>2012-10-31 20:09:05 +0000
commit4b0a6ca955e0807354af2a0a67f5ef3ae4f91ebe (patch)
tree9ff8367b5fcb4878c9b33f0e641de56c71243c6d /epan
parent0c24f376ca2eaa6e8d609b25b3846855ba10c111 (diff)
Add CRC verification to Modbus RTU dissector. CRC algorithm is the same as the "crc16-plain" with a different initial CRC (0xFFFF instead of 0). Created crc16_plain_tvb_offset_seed to "replace" crc16_plain_tvb_offset, but didn't remove crc16_plain_tvb_offset for backwards compatibility worries. Updated only dissector that used crc16_plain_tvb_offset (profinet/packet-pn-rt.c) to use crc16_plain_tvb_offset_seed(..., 0)
svn path=/trunk/; revision=45854
Diffstat (limited to 'epan')
-rw-r--r--epan/crc16-tvb.c11
-rw-r--r--epan/crc16-tvb.h16
-rw-r--r--epan/dissectors/packet-mbtcp.c22
-rw-r--r--epan/libwireshark.def1
4 files changed, 46 insertions, 4 deletions
diff --git a/epan/crc16-tvb.c b/epan/crc16-tvb.c
index ea86e4b12a..ee77803a31 100644
--- a/epan/crc16-tvb.c
+++ b/epan/crc16-tvb.c
@@ -102,3 +102,14 @@ guint16 crc16_plain_tvb_offset(tvbuff_t *tvb, guint offset, guint len)
return crc16_plain_finalize(crc);
}
+guint16 crc16_plain_tvb_offset_seed(tvbuff_t *tvb, guint offset, guint len, guint16 crc)
+{
+ const guint8 *buf;
+
+ tvb_ensure_bytes_exist(tvb, offset, len); /* len == -1 not allowed */
+ buf = tvb_get_ptr(tvb, offset, len);
+
+ crc = crc16_plain_update(crc, buf, len);
+
+ return crc16_plain_finalize(crc);
+}
diff --git a/epan/crc16-tvb.h b/epan/crc16-tvb.h
index 0a49bda326..bad28217e3 100644
--- a/epan/crc16-tvb.h
+++ b/epan/crc16-tvb.h
@@ -86,6 +86,22 @@ extern guint16 crc16_ccitt_tvb_offset_seed(tvbuff_t *tvb, guint offset,
@return The CRC16 checksum. */
extern guint16 crc16_plain_tvb_offset(tvbuff_t *tvb, guint offset, guint len);
+/** Compute the "plain" CRC16 checksum of a tv buffer using the following
+ * parameters:
+ * Width = 16
+ * Poly = 0x8005
+ * XorIn = 0x0000
+ * ReflectIn = True
+ * XorOut = 0x0000
+ * ReflectOut = True
+ * Algorithm = table-driven
+ * Direct = True
+ @param tvb The tv buffer containing the data.
+ @param offset The offset into the tv buffer.
+ @param len The number of bytes to include in the computation.
+ @param crc Starting CRC value
+ @return The CRC16 checksum. */
+extern guint16 crc16_plain_tvb_offset_seed(tvbuff_t *tvb, guint offset, guint len, guint16 crc);
#ifdef __cplusplus
}
diff --git a/epan/dissectors/packet-mbtcp.c b/epan/dissectors/packet-mbtcp.c
index d0c13224d0..4605f58196 100644
--- a/epan/dissectors/packet-mbtcp.c
+++ b/epan/dissectors/packet-mbtcp.c
@@ -77,6 +77,7 @@
#include "packet-mbtcp.h"
#include <epan/prefs.h>
#include <epan/expert.h>
+#include <epan/crc16-tvb.h> /* For CRC verification */\
/* Initialize the protocol and registered fields */
static int proto_mbtcp = -1;
@@ -172,6 +173,7 @@ static gboolean mbrtu_desegment = TRUE;
static guint global_mbus_rtu_port = PORT_MBRTU; /* 0, by default */
static gint global_mbus_rtu_register_format = MBTCP_PREF_REGISTER_FORMAT_UINT16;
static gint global_mbus_rtu_register_addr_type = MBTCP_PREF_REGISTER_ADDR_RAW;
+static gboolean mbrtu_crc = FALSE;
static int
classify_mbtcp_packet(packet_info *pinfo)
@@ -474,14 +476,14 @@ static void
dissect_mbrtu_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
- proto_item *mi;
+ proto_item *mi, *crc_item;
proto_tree *mbrtu_tree;
gint offset, packet_type;
tvbuff_t *next_tvb;
const char *func_string = "";
const char *pkt_type_str = "";
const char *err_str = "";
- guint16 len, crc16;
+ guint16 len, crc16, calc_crc16;
guint8 unit_id, function_code, exception_code, subfunction_code;
void *p_save_proto_data;
modbus_request_info_t *request_info;
@@ -578,9 +580,15 @@ dissect_mbrtu_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* Add items to protocol tree specific to Modbus RTU */
proto_tree_add_uint(mbrtu_tree, hf_mbrtu_unitid, tvb, offset, 1, unit_id);
- proto_tree_add_uint(mbrtu_tree, hf_mbrtu_crc16, tvb, len-2, 2, crc16);
+ crc_item = proto_tree_add_uint(mbrtu_tree, hf_mbrtu_crc16, tvb, len-2, 2, crc16);
- /* XXX - TODO CRC validation */
+ /* CRC validation */
+ if (mbrtu_crc)
+ {
+ calc_crc16 = crc16_plain_tvb_offset_seed(tvb, offset, len-2, 0xFFFF);
+ if (g_htons(calc_crc16) != crc16)
+ expert_add_info_format(pinfo, crc_item, PI_PROTOCOL, PI_WARN, "Incorrect CRC - should be 0x%04x", g_htons(calc_crc16));
+ }
/* make sure to ignore the CRC-16 footer bytes */
len = len - 2;
@@ -1736,6 +1744,12 @@ proto_register_modbus(void)
"Whether the Modbus RTU dissector should desegment all messages spanning multiple TCP segments",
&mbrtu_desegment);
+ /* Modbus RTU Preference - CRC verification, defaults to FALSE (not do verification)*/
+ prefs_register_bool_preference(mbrtu_module, "crc_verification",
+ "Validate CRC",
+ "Whether to validate the CRC",
+ &mbrtu_crc);
+
/* Modbus RTU Preference - Default TCP Port, defaults to zero, allows custom user port. */
prefs_register_uint_preference(mbrtu_module, "tcp.port", "Modbus RTU Port",
"Set the TCP port for encapsulated Modbus RTU packets",
diff --git a/epan/libwireshark.def b/epan/libwireshark.def
index 28eaadad69..ffffe1b042 100644
--- a/epan/libwireshark.def
+++ b/epan/libwireshark.def
@@ -116,6 +116,7 @@ copy_file_binary_mode
copy_persconffile_profile
crc16_ccitt_tvb
crc16_plain_tvb_offset
+crc16_plain_tvb_offset_seed
crc16_ccitt_tvb_offset
crc16_ccitt_tvb_offset_seed
crc16_ccitt_tvb_seed