1 /* packet-hsr-prp-supervision.c
2 * Routines for HSR/PRP supervision dissection (IEC62439 Part 3)
3 * Copyright 2009, Florian Reichert <refl[AT]zhaw.ch>
4 * Copyright 2011, Martin Renold <reld[AT]zhaw.ch>
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald[AT]wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13 #include "config.h"
14
15 #include <epan/packet.h>
16 #include <epan/etypes.h>
17
18 void proto_register_hsr_prp_supervision(void);
19 void proto_reg_handoff_hsr_prp_supervision(void);
20
21 /**********************************************************/
22 /* Channel values for the supervision type field */
23 /**********************************************************/
24
25 static const value_string type_vals[] = {
26 {20, "PRP Node (Duplicate Discard)"},
27 {21, "PRP Node (Duplicate Accept)"},
28 {22, "Obsolete TLV value"},
29 {23, "HSR Node"},
30 {30, "Redundancy Box MAC Address"},
31 {31, "Virtual Dual Attached Node"},
32 {0, "End of TLVs"},
33 {0, NULL}
34 };
35
36 /**********************************************************/
37 /* Initialize the protocol and registered fields */
38 /**********************************************************/
39
40 static int proto_hsr_prp_supervision = -1;
41
42 /* Initialize supervision frame fields */
43 static int hf_hsr_prp_supervision_path = -1;
44 static int hf_hsr_prp_supervision_version = -1;
45 static int hf_hsr_prp_supervision_seqno = -1;
46 static int hf_hsr_prp_supervision_tlv_type = -1;
47 static int hf_hsr_prp_supervision_tlv_length = -1;
48 static int hf_hsr_prp_supervision_source_mac_address_A = -1;
49 static int hf_hsr_prp_supervision_source_mac_address_B = -1;
50 static int hf_hsr_prp_supervision_source_mac_address = -1;
51 static int hf_hsr_prp_supervision_red_box_mac_address = -1;
52 static int hf_hsr_prp_supervision_vdan_mac_address = -1;
53
54 /* Initialize the subtree pointers */
55 static gint ett_hsr_prp_supervision = -1;
56
57 /* Code to actually dissect the packets */
58 static int
dissect_hsr_prp_supervision(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)59 dissect_hsr_prp_supervision(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
60 {
61 proto_item *ti;
62 proto_tree *hsr_prp_supervision_tree;
63 guint8 tlv_type;
64 guint8 tlv_length;
65 guint16 sup_version;
66 int offset;
67
68 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSR/PRP");
69
70 /* may get modified later while parsing */
71 col_set_str(pinfo->cinfo, COL_INFO, "HSR or PRP Supervision");
72
73 /* create display subtree for the protocol */
74 ti = proto_tree_add_item(tree, proto_hsr_prp_supervision, tvb, 0, -1, ENC_NA);
75
76 hsr_prp_supervision_tree = proto_item_add_subtree(ti, ett_hsr_prp_supervision);
77
78 offset = 0;
79
80 /* SupVersion */
81 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_path,
82 tvb, offset, 2, ENC_BIG_ENDIAN);
83 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_version,
84 tvb, offset, 2, ENC_BIG_ENDIAN);
85 sup_version = tvb_get_ntohs(tvb, 0) & 0x0fff;
86 offset += 2;
87
88 if (sup_version > 0) {
89 /* SupSequenceNumber */
90 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_seqno,
91 tvb, offset, 2, ENC_BIG_ENDIAN);
92 offset += 2;
93 }
94
95 while (tvb_reported_length_remaining(tvb, offset) > 0) {
96 /* TLV.type */
97 tlv_type = tvb_get_guint8(tvb, offset);
98 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_tlv_type,
99 tvb, offset, 1, ENC_BIG_ENDIAN);
100 offset += 1;
101
102 /* TLV.length */
103 tlv_length = tvb_get_guint8(tvb, offset);
104 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_tlv_length,
105 tvb, offset, 1, ENC_BIG_ENDIAN);
106 offset += 1;
107
108 /* TLV.value */
109 if ((tlv_type == 20 || tlv_type == 21 || tlv_type == 23) && (tlv_length == 6 || tlv_length == 12)) {
110 if (tlv_type == 23) {
111 col_set_str(pinfo->cinfo, COL_INFO, "HSR Supervision");
112 } else {
113 col_set_str(pinfo->cinfo, COL_INFO, "PRP Supervision");
114 }
115 if (tlv_length == 12) {
116 /* MacAddressA, MacAddressB (PRP only) */
117 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_source_mac_address_A,
118 tvb, offset, 6, ENC_NA);
119 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_source_mac_address_B,
120 tvb, offset+6, 6, ENC_NA);
121 /* PRP-0 supervision: if the node is not a RedBox, we have
122 just read the last TLV. The next two octets are
123 required to be zero by PRP-0. We will dissect those as
124 "end of list" and break. */
125 } else {
126 /* MacAddress */
127 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_source_mac_address,
128 tvb, offset, 6, ENC_NA);
129 }
130 } else if (tlv_type == 30 && tlv_length == 6) {
131 /* RedBoxMacAddress */
132 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_red_box_mac_address,
133 tvb, offset, 6, ENC_NA);
134 if (sup_version == 0) {
135 /* PRP-0 supervision: end of TLV data. Stop now, don't
136 interpret the padding. */
137 offset += tlv_length;
138 break;
139 }
140 } else if (tlv_type == 31 && tlv_length == 6) {
141 /* VdanMacAddress */
142 proto_tree_add_item(hsr_prp_supervision_tree, hf_hsr_prp_supervision_vdan_mac_address,
143 tvb, offset, 6, ENC_NA);
144 if (sup_version == 0) {
145 /* PRP-0 supervision: end of TLV data, padding starts */
146 offset += tlv_length;
147 break;
148 }
149 } else if (tlv_type == 0) {
150 /* End of TLV list. */
151 offset += tlv_length;
152 break;
153 } else {
154 /* unknown TLV.type, or unexpected TLV.length */
155 }
156 offset += tlv_length;
157 }
158
159 proto_item_set_len(ti, offset);
160 /* Adjust the length of this tvbuff to include only the supervision data.
161 This allows the rest to be marked as padding. */
162 tvb_set_reported_length(tvb, offset);
163 return tvb_captured_length(tvb);
164 }
165
166
167 /* Register the protocol with Wireshark */
proto_register_hsr_prp_supervision(void)168 void proto_register_hsr_prp_supervision(void)
169 {
170
171 static hf_register_info hf[] = {
172
173 { &hf_hsr_prp_supervision_path,
174 { "Path", "hsr_prp_supervision.path",
175 FT_UINT16, BASE_DEC, NULL, 0xf000,
176 NULL, HFILL }
177 },
178 { &hf_hsr_prp_supervision_version,
179 { "Version", "hsr_prp_supervision.version",
180 FT_UINT16, BASE_DEC, NULL, 0x0fff,
181 NULL, HFILL }
182 },
183 { &hf_hsr_prp_supervision_seqno,
184 { "Sequence number", "hsr_prp_supervision.supervision_seqno",
185 FT_UINT16, BASE_DEC, NULL, 0x00,
186 NULL, HFILL }
187 },
188 { &hf_hsr_prp_supervision_tlv_type,
189 { "TLV type", "hsr_prp_supervision.tlv.type",
190 FT_UINT8, BASE_DEC, VALS(type_vals), 0x00,
191 NULL, HFILL }
192 },
193 { &hf_hsr_prp_supervision_tlv_length,
194 { "TLV length", "hsr_prp_supervision.tlv.length",
195 FT_UINT8, BASE_DEC, NULL, 0x00,
196 NULL, HFILL }
197 },
198 { &hf_hsr_prp_supervision_source_mac_address_A,
199 { "Source MAC Address A", "hsr_prp_supervision.source_mac_address_A",
200 FT_ETHER, BASE_NONE, NULL, 0x00,
201 NULL, HFILL }
202 },
203 { &hf_hsr_prp_supervision_source_mac_address_B,
204 { "Source MAC Address B", "hsr_prp_supervision.source_mac_address_B",
205 FT_ETHER, BASE_NONE, NULL, 0x00,
206 NULL, HFILL }
207 },
208 { &hf_hsr_prp_supervision_source_mac_address,
209 { "Source MAC Address", "hsr_prp_supervision.source_mac_address",
210 FT_ETHER, BASE_NONE, NULL, 0x00,
211 NULL, HFILL }
212 },
213 { &hf_hsr_prp_supervision_red_box_mac_address,
214 { "RedBox MAC Address", "hsr_prp_supervision.red_box_mac_address",
215 FT_ETHER, BASE_NONE, NULL, 0x00,
216 NULL, HFILL }
217 },
218 { &hf_hsr_prp_supervision_vdan_mac_address,
219 { "VDAN MAC Address", "hsr_prp_supervision.vdan_mac_address",
220 FT_ETHER, BASE_NONE, NULL, 0x00,
221 NULL, HFILL }
222 }
223 };
224
225
226 static gint *ett[] = {
227 &ett_hsr_prp_supervision
228 };
229
230 /* Register the protocol name and description */
231 proto_hsr_prp_supervision = proto_register_protocol("HSR/PRP Supervision (IEC62439 Part 3)",
232 "HSR_PRP_SUPERVISION", "hsr_prp_supervision");
233
234
235 /* Required function calls to register the header fields and subtree used */
236 proto_register_field_array(proto_hsr_prp_supervision, hf, array_length(hf));
237 proto_register_subtree_array(ett, array_length(ett));
238 }
239
240
proto_reg_handoff_hsr_prp_supervision(void)241 void proto_reg_handoff_hsr_prp_supervision(void)
242 {
243 dissector_handle_t hsr_prp_supervision_handle;
244 hsr_prp_supervision_handle = create_dissector_handle(dissect_hsr_prp_supervision, proto_hsr_prp_supervision);
245 dissector_add_uint("ethertype", ETHERTYPE_PRP, hsr_prp_supervision_handle);
246 }
247
248 /*
249 * Editor modelines - https://www.wireshark.org/tools/modelines.html
250 *
251 * Local variables:
252 * c-basic-offset: 4
253 * tab-width: 8
254 * indent-tabs-mode: nil
255 * End:
256 *
257 * vi: set shiftwidth=4 tabstop=8 expandtab:
258 * :indentSize=4:tabSize=8:noTabs=true:
259 */
260