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