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>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald[AT]wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/packet.h>
17 #include <epan/etypes.h>
18 #include <epan/prefs.h>
23 static const value_string prp_lan_vals
[] = {
29 /**********************************************************/
30 /* Initialize the protocol and registered fields */
31 /**********************************************************/
33 void proto_register_prp(void);
38 /* Initialize trailer fields */
39 static int hf_prp_redundancy_control_trailer_sequence_nr
;
40 static int hf_prp_redundancy_control_trailer_lan
;
41 static int hf_prp_redundancy_control_trailer_size
;
42 static int hf_prp_redundancy_control_trailer_suffix
;
43 static int hf_prp_redundancy_control_trailer_version
;
46 /* Initialize the subtree pointers */
47 static int ett_prp_redundancy_control_trailer
;
50 /* Code to actually dissect the packets */
52 dissect_prp_redundancy_control_trailer(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data
)
61 unsigned trailer_start
;
62 unsigned trailer_length
;
66 length
= tvb_reported_length(tvb
);
69 * Is there enough data in the packet to every try to search for a
72 if (!tvb_bytes_exist(tvb
, (length
-4)+2, 2))
79 int lsdu_size_correct
= *(int*)data
;
81 /* search for PRP-0 trailer */
82 /* If the frame is > 64 bytes, the PRP-0 trailer is always at the end. */
83 /* If the frame is <= 64 bytes, the PRP-0 trailer may be anywhere (before the padding) */
84 for(i
= 0; i
<= length
- 4; i
++)
86 lan_id
= tvb_get_ntohs(tvb
, length
- 2 - i
) >> 12;
87 lsdu_size
= tvb_get_ntohs(tvb
, length
- 2 - i
) & 0x0fff;
88 if(lsdu_size
== (lsdu_size_correct
- i
) && (lan_id
== 0xa || lan_id
== 0xb))
90 trailer_start
= length
- 4 - i
;
96 /* check for PRP-1 trailer */
97 /* PRP-1 trailer is always at the end of the frame, after any padding. */
99 lan_id
= tvb_get_ntohs(tvb
, length
-4) >> 12;
100 lsdu_size
= tvb_get_ntohs(tvb
, length
-4) & 0x0fff;
101 prp1_suffix
= tvb_get_ntohs(tvb
, length
-2);
103 if(prp1_suffix
== ETHERTYPE_PRP
&& (lan_id
== 0xa || lan_id
== 0xb))
105 /* We don't check the lsdu_size, we just display whether
106 it's correct. Helpful for testing, because different
107 definitions of the lsdu_size did exist. */
108 trailer_start
= length
-6;
113 if(trailer_length
!= 0)
115 /* create display subtree for the protocol */
116 ti
= proto_tree_add_item(tree
, proto_prp
, tvb
, trailer_start
,
117 trailer_length
, ENC_NA
);
119 prp_tree
= proto_item_add_subtree(ti
, ett_prp_redundancy_control_trailer
);
121 if (trailer_length
== 4) {
122 ti
= proto_tree_add_string(prp_tree
, hf_prp_redundancy_control_trailer_version
,
123 tvb
, trailer_start
, trailer_length
, "PRP-0");
125 ti
= proto_tree_add_string(prp_tree
, hf_prp_redundancy_control_trailer_version
,
126 tvb
, trailer_start
, trailer_length
, "PRP-1");
128 proto_item_set_generated(ti
);
130 proto_tree_add_item(prp_tree
, hf_prp_redundancy_control_trailer_sequence_nr
,
131 tvb
, trailer_start
, 2, ENC_BIG_ENDIAN
);
133 proto_tree_add_item(prp_tree
, hf_prp_redundancy_control_trailer_lan
,
134 tvb
, trailer_start
+2, 2, ENC_BIG_ENDIAN
);
136 if (trailer_length
== 4) {
138 proto_tree_add_item(prp_tree
, hf_prp_redundancy_control_trailer_size
,
139 tvb
, trailer_start
+2, 2, ENC_BIG_ENDIAN
);
142 if (lsdu_size
== lsdu_size_correct
) {
143 proto_tree_add_uint_format(prp_tree
, hf_prp_redundancy_control_trailer_size
,
144 tvb
, trailer_start
+2, 2, lsdu_size
,
145 "LSDU size: %d [correct]", lsdu_size
);
147 proto_tree_add_uint_format(prp_tree
, hf_prp_redundancy_control_trailer_size
,
148 tvb
, trailer_start
+2, 2, lsdu_size
,
149 "LSDU size: %d [WRONG, should be %d]", lsdu_size
, lsdu_size_correct
);
152 proto_tree_add_item(prp_tree
, hf_prp_redundancy_control_trailer_suffix
,
153 tvb
, trailer_start
+4, 2, ENC_BIG_ENDIAN
);
156 return trailer_length
;
159 static bool dissect_prp_redundancy_control_trailer_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, void *data
)
161 return dissect_prp_redundancy_control_trailer(tvb
, pinfo
, parent_tree
, data
) > 0;
164 /* Register the protocol with Wireshark */
165 void proto_register_prp(void)
167 static hf_register_info hf
[] = {
169 { &hf_prp_redundancy_control_trailer_sequence_nr
,
170 { "Sequence number", "prp.trailer.prp_sequence_nr",
171 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
175 { &hf_prp_redundancy_control_trailer_lan
,
176 { "LAN", "prp.trailer.prp_lan",
177 FT_UINT16
, BASE_DEC
, VALS(prp_lan_vals
), 0xf000,
181 { &hf_prp_redundancy_control_trailer_size
,
182 { "Size", "prp.trailer.prp_size",
183 FT_UINT16
, BASE_DEC
, NULL
, 0x0fff,
187 { &hf_prp_redundancy_control_trailer_suffix
,
188 { "Suffix", "prp.trailer.prp1_suffix",
189 FT_UINT16
, BASE_HEX
, NULL
, 0x00,
193 { &hf_prp_redundancy_control_trailer_version
,
194 { "PRP Version", "prp.trailer.version",
195 FT_STRING
, BASE_NONE
, NULL
, 0x00,
200 static int *ett
[] = {
201 &ett_prp_redundancy_control_trailer
,
204 module_t
*prp_module
;
206 /* Register the protocol name and description */
207 proto_prp
= proto_register_protocol("Parallel Redundancy Protocol (IEC62439 Part 3)", "PRP", "prp");
209 prp_module
= prefs_register_protocol_obsolete(proto_prp
);
211 prefs_register_obsolete_preference(prp_module
, "enable");
213 /* Required function calls to register the header fields and subtree used */
214 proto_register_field_array(proto_prp
, hf
, array_length(hf
));
215 proto_register_subtree_array(ett
, array_length(ett
));
217 heur_dissector_add("eth.trailer", dissect_prp_redundancy_control_trailer_heur
,
218 "PRP Trailer", "prp_eth", proto_prp
, HEURISTIC_ENABLE
);
222 * Editor modelines - https://www.wireshark.org/tools/modelines.html
227 * indent-tabs-mode: nil
230 * vi: set shiftwidth=4 tabstop=8 expandtab:
231 * :indentSize=4:tabSize=8:noTabs=true: