2 * Routines for PRP (Parallel Redundancy Protocol; IEC62439 Part 3) dissection
3 * Copyright 2007, Sven Meier <msv[AT]zhwin.ch>
4 * Copyright 2011, Martin Renold <reld[AT]zhaw.ch>
5 * Copyright 2011, Florian Reichert <refl [AT] zhaw.ch>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald[AT]wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/etypes.h>
33 #include <epan/prefs.h>
38 static const value_string prp_lan_vals
[] = {
44 /**********************************************************/
45 /* Initialize the protocol and registered fields */
46 /**********************************************************/
48 void proto_reg_handoff_prp(void);
49 static int proto_prp
= -1;
52 /* Initialize trailer fields */
53 static int hf_prp_redundancy_control_trailer_sequence_nr
= -1;
54 static int hf_prp_redundancy_control_trailer_lan
= -1;
55 static int hf_prp_redundancy_control_trailer_size
= -1;
56 static int hf_prp_redundancy_control_trailer_suffix
= -1;
57 static int hf_prp_redundancy_control_trailer_version
= -1;
60 /* Initialize the subtree pointers */
61 static gint ett_prp_redundancy_control_trailer
= -1;
64 /* Post dissectors (such as the trailer dissector for this protocol)
65 * get called for every single frame anyone loads into Wireshark.
66 * Since this protocol is not of general interest we disable this
67 * protocol by default.
69 * This is done separately from the disabled protocols list mainly so
70 * we can disable it by default. XXX Maybe there's a better way.
72 static gboolean prp_enable_dissector
= FALSE
;
75 /* Code to actually dissect the packets */
77 dissect_prp_redundancy_control_trailer(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
95 length
= tvb_reported_length(tvb
);
102 if(ETHERTYPE_VLAN
== tvb_get_ntohs(tvb
, 12)) /* tagged frame */
111 /* search for PRP-0 trailer */
112 /* If the frame is > 64 bytes, the PRP-0 trailer is always at the end. */
113 /* If the frame is <= 64 bytes, the PRP-0 trailer may be anywhere (before the padding) */
114 for(i
=length
-4; i
>=offset
; i
--)
116 lan_id
= tvb_get_ntohs(tvb
, (i
+2)) >> 12;
117 lsdu_size
= tvb_get_ntohs(tvb
, (i
+2)) & 0x0fff;
118 if(lsdu_size
== i
+4-offset
&& (lan_id
== 0xa || lan_id
== 0xb))
126 break; /* don't search, just check the last position */
130 /* check for PRP-1 trailer */
131 /* PRP-1 trailer is always at the end of the frame, after any padding. */
133 lan_id
= tvb_get_ntohs(tvb
, length
-4) >> 12;
134 lsdu_size
= tvb_get_ntohs(tvb
, length
-4) & 0x0fff;
135 prp1_suffix
= tvb_get_ntohs(tvb
, length
-2);
137 if(prp1_suffix
== ETHERTYPE_PRP
&& (lan_id
== 0xa || lan_id
== 0xb))
139 /* We don't check the lsdu_size, we just display whether
140 it's correct. Helpful for testing, because different
141 definitions of the lsdu_size did exist. */
142 trailer_start
= length
-6;
147 if(trailer_length
!= 0)
149 /* create display subtree for the protocol */
150 ti
= proto_tree_add_item(tree
, proto_prp
, tvb
, trailer_start
,
151 trailer_length
, ENC_NA
);
153 prp_tree
= proto_item_add_subtree(ti
, ett_prp_redundancy_control_trailer
);
155 if (trailer_length
== 4) {
156 ti
= proto_tree_add_string(prp_tree
, hf_prp_redundancy_control_trailer_version
,
157 tvb
, trailer_start
, trailer_length
, "PRP-0");
159 ti
= proto_tree_add_string(prp_tree
, hf_prp_redundancy_control_trailer_version
,
160 tvb
, trailer_start
, trailer_length
, "PRP-1");
162 PROTO_ITEM_SET_GENERATED(ti
);
164 proto_tree_add_item(prp_tree
, hf_prp_redundancy_control_trailer_sequence_nr
,
165 tvb
, trailer_start
, 2, ENC_BIG_ENDIAN
);
167 proto_tree_add_item(prp_tree
, hf_prp_redundancy_control_trailer_lan
,
168 tvb
, trailer_start
+2, 2, ENC_BIG_ENDIAN
);
170 if (trailer_length
== 4) {
172 proto_tree_add_item(prp_tree
, hf_prp_redundancy_control_trailer_size
,
173 tvb
, trailer_start
+2, 2, ENC_BIG_ENDIAN
);
176 int lsdu_size_correct
= length
-offset
;
177 if (lsdu_size
== lsdu_size_correct
) {
178 proto_tree_add_uint_format(prp_tree
, hf_prp_redundancy_control_trailer_size
,
179 tvb
, trailer_start
+2, 2, lsdu_size
,
180 "LSDU size: %d [correct]", lsdu_size
);
182 proto_tree_add_uint_format(prp_tree
, hf_prp_redundancy_control_trailer_size
,
183 tvb
, trailer_start
+2, 2, lsdu_size
,
184 "LSDU size: %d [WRONG, should be %d]", lsdu_size
, lsdu_size_correct
);
187 proto_tree_add_item(prp_tree
, hf_prp_redundancy_control_trailer_suffix
,
188 tvb
, trailer_start
+4, 2, ENC_BIG_ENDIAN
);
193 /* Register the protocol with Wireshark */
194 void proto_register_prp(void)
196 static hf_register_info hf
[] = {
198 { &hf_prp_redundancy_control_trailer_sequence_nr
,
199 { "Sequence number", "prp.trailer.prp_sequence_nr",
200 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
204 { &hf_prp_redundancy_control_trailer_lan
,
205 { "LAN", "prp.trailer.prp_lan",
206 FT_UINT16
, BASE_DEC
, VALS(prp_lan_vals
), 0xf000,
210 { &hf_prp_redundancy_control_trailer_size
,
211 { "Size", "prp.trailer.prp_size",
212 FT_UINT16
, BASE_DEC
, NULL
, 0x0fff,
216 { &hf_prp_redundancy_control_trailer_suffix
,
217 { "Suffix", "prp.trailer.prp1_suffix",
218 FT_UINT16
, BASE_HEX
, NULL
, 0x00,
222 { &hf_prp_redundancy_control_trailer_version
,
223 { "PRP Version", "prp.trailer.version",
224 FT_STRING
, BASE_NONE
, NULL
, 0x00,
229 static gint
*ett
[] = {
230 &ett_prp_redundancy_control_trailer
,
233 module_t
*prp_module
;
235 /* Register the protocol name and description */
236 proto_prp
= proto_register_protocol("Parallel Redundancy Protocol (IEC62439 Part 3)",
238 prp_module
= prefs_register_protocol(proto_prp
, proto_reg_handoff_prp
);
240 prefs_register_bool_preference(prp_module
, "enable", "Enable dissector",
241 "Enable this dissector (default is false)",
242 &prp_enable_dissector
);
244 /* Required function calls to register the header fields and subtree used */
245 proto_register_field_array(proto_prp
, hf
, array_length(hf
));
246 proto_register_subtree_array(ett
, array_length(ett
));
250 void proto_reg_handoff_prp(void)
252 static gboolean prefs_initialized
= FALSE
;
254 if (!prefs_initialized
) {
255 dissector_handle_t prp_redundancy_control_trailer_handle
;
257 prp_redundancy_control_trailer_handle
= create_dissector_handle(dissect_prp_redundancy_control_trailer
, proto_prp
);
258 register_postdissector(prp_redundancy_control_trailer_handle
);
260 prefs_initialized
= TRUE
;
263 proto_set_decoding(proto_prp
, prp_enable_dissector
);