diff options
author | alagoutte <alagoutte@f5534014-38df-0310-8fa8-9805f1628bb7> | 2011-10-31 18:37:58 +0000 |
---|---|---|
committer | alagoutte <alagoutte@f5534014-38df-0310-8fa8-9805f1628bb7> | 2011-10-31 18:37:58 +0000 |
commit | 28ba4c567f286dad4e931a6657f2a5cbdd73ddd3 (patch) | |
tree | ae2898f1650672fdb4948b708b83a3b5dfd3c166 /epan/dissectors/packet-prp.c | |
parent | 5c63d35bfc996854d4a64ee2ed7b7577f6931627 (diff) |
From Martin Renold via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5730
Dissector for HSR and PRP-1
Here is a patch that adds a dissector for HSR and for PRP-1. Both protocols are defined in IEC62439 Part 3. (High-availability Seamless Redundancy / Parallel Redundancy Protocol)
The existing PRP dissector has been refactored to support both the old PRP (now called PRP-0) and the new PRP-1.
There are three distinct dissectors:
- HSR (ethertype 892F)
- HSR/PRP supervision (ethertype 88FB)
- PRP-0 and PRP-1 (trailer dissector; disabled by default)
From me :
* Fix Clang Warning
* Add modification for CMakeLists.txt
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@39692 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors/packet-prp.c')
-rw-r--r-- | epan/dissectors/packet-prp.c | 294 |
1 files changed, 93 insertions, 201 deletions
diff --git a/epan/dissectors/packet-prp.c b/epan/dissectors/packet-prp.c index bf24f5a125..7f5a65ff68 100644 --- a/epan/dissectors/packet-prp.c +++ b/epan/dissectors/packet-prp.c @@ -1,14 +1,11 @@ /* packet-prp.c * Routines for PRP (Parallel Redundancy Protocol; IEC62439 Part 3) dissection * Copyright 2007, Sven Meier <msv[AT]zhwin.ch> + * Copyright 2011, Martin Renold <reld[AT]zhaw.ch> + * Copyright 2011, Florian Reichert <refl [AT] zhaw.ch> * * $Id$ * - * Revisions: - * - - * - * A plugin for: - * * Wireshark - Network traffic analyzer * By Gerald Combs <gerald[AT]wireshark.org> * Copyright 1998 Gerald Combs @@ -32,56 +29,19 @@ # include "config.h" #endif -#include <stdlib.h> #include <glib.h> #include <epan/packet.h> #include <epan/etypes.h> #include <epan/prefs.h> -/**********************************************************/ -/* Offsets of fields within a PRP packet. */ -/**********************************************************/ -#define PRP_VERSION_OFFSET 0 -#define PRP_TYPE_OFFSET 2 -#define PRP_LENGTH_OFFSET 3 -#define PRP_SOURCEMACADDRESSA_OFFSET 4 -#define PRP_SOURCEMACADDRESSB_OFFSET 10 -#define PRP_TYPE2_OFFSET 16 -#define PRP_LENGTH2_OFFSET 17 -#define PRP_REDBOXVDANMACADDRESS_OFFSET 18 - -/**********************************************************/ -/* Lengths of fields within a PRP packet. */ -/**********************************************************/ -#define PRP_VERSION_LENGTH 2 -#define PRP_TYPE_LENGTH 1 -#define PRP_LENGTH_LENGTH 1 -#define PRP_SOURCE_LENGTH 6 -#define PRP_TOTAL_LENGTH 24 - -/**********************************************************/ -/* Channel values for the PRP_TYPE field */ -/**********************************************************/ -#define PRP_TYPE_DUPLICATE_ACCEPT 21 -#define PRP_TYPE_DUPLICATE_DISCARD 20 -#define PRP_TYPE_REDBOX 30 -#define PRP_TYPE_VDAN 31 - -static const value_string prp_type_vals[] = { - {PRP_TYPE_DUPLICATE_ACCEPT, "Duplicate Accept"}, - {PRP_TYPE_DUPLICATE_DISCARD, "Duplicate Discard"}, - {PRP_TYPE_REDBOX, "Redundancy Box"}, - {PRP_TYPE_VDAN, "Virtual Dual Attached Node"}, - {0, NULL } }; - - #define PRP_LAN_A 10 #define PRP_LAN_B 11 static const value_string prp_lan_vals[] = { - {PRP_LAN_A, "LAN A"}, - {PRP_LAN_B, "LAN B"}, - {0, NULL } }; + {PRP_LAN_A, "LAN A"}, + {PRP_LAN_B, "LAN B"}, + {0, NULL} +}; /**********************************************************/ /* Initialize the protocol and registered fields */ @@ -91,25 +51,16 @@ void proto_reg_handoff_prp(void); static int proto_prp = -1; static module_t *prp_module; -/* Initialize supervision frame fields */ -static int hf_prp_supervision_frame_version = -1; -static int hf_prp_supervision_frame_type = -1; -static int hf_prp_supervision_frame_length = -1; -static int hf_prp_supervision_frame_source_mac_address_A = -1; -static int hf_prp_supervision_frame_source_mac_address_B = -1; -static int hf_prp_supervision_frame_type2 = -1; -static int hf_prp_supervision_frame_length2 = -1; -static int hf_prp_supervision_frame_red_box_mac_address = -1; -static int hf_prp_supervision_frame_vdan_mac_address = -1; /* Initialize trailer fields */ static int hf_prp_redundancy_control_trailer_sequence_nr = -1; static int hf_prp_redundancy_control_trailer_lan = -1; static int hf_prp_redundancy_control_trailer_size = -1; +static int hf_prp_redundancy_control_trailer_suffix = -1; +static int hf_prp_redundancy_control_trailer_version = -1; /* Initialize the subtree pointers */ -static gint ett_prp_supervision_frame = -1; static gint ett_prp_redundancy_control_trailer = -1; @@ -126,70 +77,6 @@ static gboolean prp_enable_dissector = FALSE; /* Code to actually dissect the packets */ static void -dissect_prp_supervision_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) -{ - proto_item *ti; - proto_tree *prp_tree; - guint16 tlv2; - - col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRP"); - - col_set_str(pinfo->cinfo, COL_INFO, "Supervision Frame"); - - if (!tree) - return; - - /* create display subtree for the protocol */ - ti = proto_tree_add_item(tree, proto_prp, tvb, 0, PRP_TOTAL_LENGTH, - ENC_NA); - - prp_tree = proto_item_add_subtree(ti, ett_prp_supervision_frame); - - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_version, - tvb, PRP_VERSION_OFFSET, PRP_VERSION_LENGTH, ENC_BIG_ENDIAN); - - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_type, - tvb, PRP_TYPE_OFFSET, PRP_TYPE_LENGTH, ENC_BIG_ENDIAN); - - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_length, - tvb, PRP_LENGTH_OFFSET, PRP_LENGTH_LENGTH, ENC_BIG_ENDIAN); - - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_source_mac_address_A, - tvb, PRP_SOURCEMACADDRESSA_OFFSET, PRP_SOURCE_LENGTH, - ENC_NA); - - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_source_mac_address_B, - tvb, PRP_SOURCEMACADDRESSB_OFFSET, PRP_SOURCE_LENGTH, - ENC_NA); - - - tlv2 = tvb_get_ntohs(tvb, PRP_TYPE2_OFFSET); - - if((tlv2 == 0x1e06) || (tlv2 == 0x1f06)) - { - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_type2, - tvb, PRP_TYPE2_OFFSET, PRP_TYPE_LENGTH, ENC_BIG_ENDIAN); - - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_length2, - tvb, PRP_LENGTH2_OFFSET, PRP_LENGTH_LENGTH, ENC_BIG_ENDIAN); - - if(tlv2 == 0x1e06) - { - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_red_box_mac_address, - tvb, PRP_REDBOXVDANMACADDRESS_OFFSET, PRP_SOURCE_LENGTH, - ENC_NA); - } - else - { - proto_tree_add_item(prp_tree, hf_prp_supervision_frame_vdan_mac_address, - tvb, PRP_REDBOXVDANMACADDRESS_OFFSET, PRP_SOURCE_LENGTH, - ENC_NA); - } - - } -} - -static void dissect_prp_redundancy_control_trailer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree) { proto_item *ti; @@ -197,13 +84,17 @@ dissect_prp_redundancy_control_trailer(tvbuff_t *tvb, packet_info *pinfo _U_, pr guint i; guint length; guint offset; - guint16 lan_size; - guint trailer_offset; + guint16 lan_id; + guint16 lsdu_size; + guint16 prp1_suffix; + guint trailer_start; + guint trailer_length; if (!tree) return; - trailer_offset = 0; + trailer_start = 0; + trailer_length = 0; length = tvb_reported_length(tvb); if(length < 14) @@ -220,121 +111,126 @@ dissect_prp_redundancy_control_trailer(tvbuff_t *tvb, packet_info *pinfo _U_, pr offset = 14; } - if(length <= 64) + /* search for PRP-0 trailer */ + /* If the frame is > 64 bytes, the PRP-0 trailer is always at the end. */ + /* If the frame is <= 64 bytes, the PRP-0 trailer may be anywhere (before the padding) */ + for(i=length-4; i>=offset; i--) { - for(i=length; i>=(offset+4); i--) /* search trailer */ + lan_id = tvb_get_ntohs(tvb, (i+2)) >> 12; + lsdu_size = tvb_get_ntohs(tvb, (i+2)) & 0x0fff; + if(lsdu_size == i+4-offset && (lan_id == 0xa || lan_id == 0xb)) { - lan_size = tvb_get_ntohs(tvb, (i-2)); - if((lan_size == (0xa000 | ((i-offset) & 0x0fff))) - || (lan_size == (0xb000 | ((i-offset) & 0x0fff)))) - { - trailer_offset = i; - } + trailer_start = i; + trailer_length = 4; + break; + } + + if (length > 64) { + break; /* don't search, just check the last position */ } } - else if(length > 64) + + /* check for PRP-1 trailer */ + /* PRP-1 trailer is always at the end of the frame, after any padding. */ { - lan_size = tvb_get_ntohs(tvb, (length-2)); - if((lan_size == (0xa000 | ((length-offset) & 0x0fff))) - || (lan_size == (0xb000 | ((length-offset) & 0x0fff)))) + lan_id = tvb_get_ntohs(tvb, length-4) >> 12; + lsdu_size = tvb_get_ntohs(tvb, length-4) & 0x0fff; + prp1_suffix = tvb_get_ntohs(tvb, length-2); + + if(prp1_suffix == ETHERTYPE_PRP && (lan_id == 0xa || lan_id == 0xb)) { - trailer_offset = length; + /* We don't check the lsdu_size, we just display whether + it's correct. Helpful for testing, because different + definitions of the lsdu_size did exist. */ + trailer_start = length-6; + trailer_length = 6; } } - if(trailer_offset != 0) + if(trailer_length != 0) { /* create display subtree for the protocol */ - ti = proto_tree_add_item(tree, proto_prp, tvb, trailer_offset - 4, - trailer_offset, ENC_NA); + ti = proto_tree_add_item(tree, proto_prp, tvb, trailer_start, + trailer_length, ENC_NA); prp_tree = proto_item_add_subtree(ti, ett_prp_redundancy_control_trailer); + if (trailer_length == 4) { + ti = proto_tree_add_string(prp_tree, hf_prp_redundancy_control_trailer_version, + tvb, trailer_start, trailer_length, "PRP-0"); + } else { + ti = proto_tree_add_string(prp_tree, hf_prp_redundancy_control_trailer_version, + tvb, trailer_start, trailer_length, "PRP-1"); + } + PROTO_ITEM_SET_GENERATED(ti); + proto_tree_add_item(prp_tree, hf_prp_redundancy_control_trailer_sequence_nr, - tvb, (trailer_offset-4), 2, ENC_BIG_ENDIAN); + tvb, trailer_start, 2, ENC_BIG_ENDIAN); proto_tree_add_item(prp_tree, hf_prp_redundancy_control_trailer_lan, - tvb, (trailer_offset-2), 2, ENC_BIG_ENDIAN); - - proto_tree_add_item(prp_tree, hf_prp_redundancy_control_trailer_size, - tvb, (trailer_offset-2), 2, ENC_BIG_ENDIAN); + tvb, trailer_start+2, 2, ENC_BIG_ENDIAN); + + if (trailer_length == 4) { + /* PRP-0 */ + proto_tree_add_item(prp_tree, hf_prp_redundancy_control_trailer_size, + tvb, trailer_start+2, 2, ENC_BIG_ENDIAN); + } else { + /* PRP-1 */ + int lsdu_size_correct = length-offset; + if (lsdu_size == lsdu_size_correct) { + proto_tree_add_uint_format(prp_tree, hf_prp_redundancy_control_trailer_size, + tvb, trailer_start+2, 2, lsdu_size, + "LSDU size: %d [correct]", lsdu_size); + } else { + proto_tree_add_uint_format(prp_tree, hf_prp_redundancy_control_trailer_size, + tvb, trailer_start+2, 2, lsdu_size, + "LSDU size: %d [WRONG, should be %d]", lsdu_size, lsdu_size_correct); + } + /* suffix */ + proto_tree_add_item(prp_tree, hf_prp_redundancy_control_trailer_suffix, + tvb, trailer_start+4, 2, ENC_BIG_ENDIAN); + } } } /* Register the protocol with Wireshark */ void proto_register_prp(void) { - static hf_register_info hf[] = { - - /*supervision frame*/ - { &hf_prp_supervision_frame_version, - { "version", "prp.supervision_frame.version", - FT_UINT16, BASE_DEC, NULL, 0x00, - NULL, HFILL } - }, - { &hf_prp_supervision_frame_type, - { "type", "prp.supervision_frame.type", - FT_UINT8, BASE_DEC, VALS(prp_type_vals), 0x00, - NULL, HFILL } - }, - { &hf_prp_supervision_frame_length, - { "length", "prp.supervision_frame.length", - FT_UINT8, BASE_DEC, NULL, 0x00, - NULL, HFILL } - }, - { &hf_prp_supervision_frame_source_mac_address_A, - { "sourceMacAddressA", "prp.supervision_frame.prp_source_mac_address_A", - FT_ETHER, BASE_NONE, NULL, 0x00, - NULL, HFILL } - }, - { &hf_prp_supervision_frame_source_mac_address_B, - { "sourceMacAddressB", "prp.supervision_frame.prp_source_mac_address_B", - FT_ETHER, BASE_NONE, NULL, 0x00, - NULL, HFILL } - }, - { &hf_prp_supervision_frame_type2, - { "type2", "prp.supervision_frame.type2", - FT_UINT8, BASE_DEC, VALS(prp_type_vals), 0x00, - NULL, HFILL } - }, - { &hf_prp_supervision_frame_length2, - { "length2", "prp.supervision_frame.length2", - FT_UINT8, BASE_DEC, NULL, 0x00, - NULL, HFILL } - }, - { &hf_prp_supervision_frame_red_box_mac_address, - { "redBoxMacAddress", "prp.supervision_frame.prp_red_box_mac_address", - FT_ETHER, BASE_NONE, NULL, 0x00, - NULL, HFILL } - }, - { &hf_prp_supervision_frame_vdan_mac_address, - { "vdanMacAddress", "prp.supervision_frame.prp_vdan_mac_address", - FT_ETHER, BASE_NONE, NULL, 0x00, - NULL, HFILL } - }, + static hf_register_info hf[] = { /*trailer*/ { &hf_prp_redundancy_control_trailer_sequence_nr, - { "sequenceNr", "prp.trailer.prp_sequence_nr", + { "Sequence number", "prp.trailer.prp_sequence_nr", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL } }, { &hf_prp_redundancy_control_trailer_lan, - { "lan", "prp.trailer.prp_lan", + { "LAN", "prp.trailer.prp_lan", FT_UINT16, BASE_DEC, VALS(prp_lan_vals), 0xf000, NULL, HFILL } }, { &hf_prp_redundancy_control_trailer_size, - { "size", "prp.trailer.prp_size", + { "Size", "prp.trailer.prp_size", FT_UINT16, BASE_DEC, NULL, 0x0fff, NULL, HFILL } + }, + + { &hf_prp_redundancy_control_trailer_suffix, + { "Suffix", "prp.trailer.prp1_suffix", + FT_UINT16, BASE_HEX, NULL, 0x00, + NULL, HFILL } + }, + + { &hf_prp_redundancy_control_trailer_version, + { "PRP Version", "prp.trailer.version", + FT_STRING, BASE_NONE, NULL, 0x00, + NULL, HFILL } } }; static gint *ett[] = { - &ett_prp_supervision_frame, &ett_prp_redundancy_control_trailer, }; @@ -359,12 +255,8 @@ void proto_reg_handoff_prp(void) static gboolean prefs_initialized = FALSE; if (!prefs_initialized) { - dissector_handle_t prp_supervision_frame_handle; dissector_handle_t prp_redundancy_control_trailer_handle; - prp_supervision_frame_handle = create_dissector_handle(dissect_prp_supervision_frame, proto_prp); - dissector_add_uint("ethertype", ETHERTYPE_PRP, prp_supervision_frame_handle); - prp_redundancy_control_trailer_handle = create_dissector_handle(dissect_prp_redundancy_control_trailer, proto_prp); register_postdissector(prp_redundancy_control_trailer_handle); |