2 * Routines for Ether-S-I/O dissection (from Saia Burgess Controls AG )
3 * Copyright 2010, Christian Durrer <christian.durrer@sensemail.ch>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/expert.h>
18 #define ESIO_TRANSFER 0x01
19 #define ESIO_STATUS 0x02
21 void proto_register_esio(void);
22 void proto_reg_handoff_esio(void);
24 static dissector_handle_t esio_handle
;
26 #define ESIO_UDP_PORT 6060 /* Not IANA registered */
28 /* Initialize the protocol and registered fields */
29 static int proto_esio
;
30 static int hf_esio_type
;
31 static int hf_esio_version
;
32 static int hf_esio_length
;
33 static int hf_esio_transaction_id
;
34 static int hf_esio_tlg_id
;
35 static int hf_esio_src_stn_id
;
36 static int hf_esio_data_nbr
;
37 static int hf_esio_data_flags
;
38 static int hf_esio_data_transfer_id
;
39 static int hf_esio_data_dest_id
;
40 static int hf_esio_data_length
;
41 static int hf_esio_data
;
42 static int hf_esio_sts_type
;
43 static int hf_esio_sts_size
;
44 static int hf_esio_rio_sts
;
45 static int hf_esio_rio_tlgs_lost
;
46 static int hf_esio_rio_diag
;
47 static int hf_esio_rio_flags
;
49 /* Initialize the subtree pointers */
51 static int ett_esio_header
;
52 static int ett_esio_transfer_header
;
53 static int ett_esio_transfer_data
;
54 static int ett_esio_data
;
56 static expert_field ei_esio_telegram_lost
;
58 /* value to string definitions*/
59 /* Ether-S-I/O telegram types*/
60 static const value_string esio_tlg_types
[] = {
62 {1, "Data transfer telegram"},
63 {2, "Status/Diag telegram"},
67 /* Status telegram types*/
68 static const value_string esio_sts_types
[] = {
74 /* check whether the packet looks like SBUS or not */
76 is_esio_pdu(tvbuff_t
*tvb
)
78 /* we need at least 8 bytes to determine whether this is
80 /* minimal length is 20 bytes*/
81 if (tvb_captured_length(tvb
) < 20) {
84 /* First four bytes must be "ESIO"*/
85 if (tvb_strneql(tvb
, 0, "ESIO", 4) != 0) {
88 /* fifth byte must be 0*/
89 if (tvb_get_uint8(tvb
, 4) > 0x00) {
92 /* sixth byte indicates telegram type and must be 0, 1 or 2*/
93 if (tvb_get_uint8(tvb
, 5) > 0x02) {
96 /* seventh byte must be 0*/
97 if (tvb_get_uint8(tvb
, 6) > 0x00) {
100 /* eight byte indicates telegram version and must be 0 (up to now)*/
101 if (tvb_get_uint8(tvb
, 7) > 0x00) {
104 /*header seems to be Ether-S-I/O*/
108 /*Dissect the telegram*/
110 dissect_esio(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
113 /* Set up structures needed to add the protocol subtree and manage it */
115 proto_tree
*esio_tree
, *esio_header_tree
, *esio_transfer_header_tree
,
116 *esio_data_tansfer_tree
, *esio_data_tree
;
120 uint8_t esio_nbr_data_transfers
;
121 uint16_t esio_telegram_type
;
122 uint16_t esio_tlg_type
;
123 uint16_t esio_transfer_length
;
124 uint32_t esio_transfer_dest_id
;
125 uint32_t esio_src_id
;
126 uint32_t esio_dst_id
;
128 /* does this look like an sbus pdu? */
129 if (!is_esio_pdu(tvb
)) {
133 /* Make entries in Protocol column and Info column on summary display */
134 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ESIO");
135 col_clear(pinfo
->cinfo
, COL_INFO
);
136 esio_telegram_type
= tvb_get_uint8(tvb
,5);
138 switch (esio_telegram_type
) {
140 esio_src_id
= tvb_get_ntohl(tvb
,16);
141 esio_nbr_data_transfers
= tvb_get_uint8(tvb
, 20);
142 esio_dst_id
= tvb_get_ntohl(tvb
,26);
143 col_add_fstr( pinfo
->cinfo
, COL_INFO
,
144 "Data transfer: Src ID: %d, Dst ID(s): %d",
145 esio_src_id
, esio_dst_id
);
146 if (esio_nbr_data_transfers
> 1) {
147 col_append_str( pinfo
->cinfo
, COL_INFO
,
152 esio_src_id
= tvb_get_ntohl(tvb
,16);
153 col_add_fstr( pinfo
->cinfo
, COL_INFO
,
154 "Status/diag telegram: Src ID: %d",
158 /* All other telegrams */
159 col_set_str( pinfo
->cinfo
, COL_INFO
,
164 /* create display subtree for the protocol */
166 ti
= proto_tree_add_item(tree
, proto_esio
, tvb
, offset
, -1, ENC_NA
);
167 esio_tree
= proto_item_add_subtree(ti
, ett_esio
);
168 /*Add subtree for Ether-S-I/O header*/
169 esio_header_tree
= proto_tree_add_subtree(esio_tree
, tvb
, offset
, 12, ett_esio_header
, NULL
, "Ether-S-I/O header");
170 offset
+= 4; /*first four bytes are "ESIO"*/
171 /* add items to the Ether-S-I/O header subtree*/
172 esio_tlg_type
= tvb_get_ntohs(tvb
,offset
);
173 proto_tree_add_item(esio_header_tree
,
174 hf_esio_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
176 proto_tree_add_item(esio_header_tree
,
177 hf_esio_version
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
179 proto_tree_add_item(esio_header_tree
,
180 hf_esio_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
182 proto_tree_add_item(esio_header_tree
,
183 hf_esio_transaction_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
185 switch (esio_tlg_type
) {
188 /*Add subtree for Ether-S-I/O header*/
189 esio_transfer_header_tree
= proto_tree_add_subtree(esio_tree
, tvb
, offset
, 12,
190 ett_esio_transfer_header
, NULL
, "Transfer header");
191 proto_tree_add_item(esio_transfer_header_tree
,
192 hf_esio_tlg_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
194 proto_tree_add_item(esio_transfer_header_tree
,
195 hf_esio_src_stn_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
197 esio_nbr_data_transfers
= tvb_get_uint8(tvb
,offset
);
198 proto_tree_add_item(esio_transfer_header_tree
,
199 hf_esio_data_nbr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
201 proto_tree_add_item(esio_transfer_header_tree
,
202 hf_esio_data_flags
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
204 for (i
=((esio_nbr_data_transfers
)); i
>0; i
--) {
205 /*Add subtree(s) for Ether-S-I/O data transfers*/
206 esio_transfer_dest_id
= tvb_get_ntohl(tvb
,(offset
+4));
207 esio_transfer_length
= tvb_get_ntohs(tvb
,(offset
+8));
208 esio_data_tansfer_tree
= proto_tree_add_subtree_format(esio_tree
, tvb
, offset
,
209 (esio_transfer_length
+ 10), ett_esio_transfer_data
, NULL
,
210 "Data transfer to ID: %d ", esio_transfer_dest_id
);
212 proto_tree_add_item(esio_data_tansfer_tree
,
213 hf_esio_data_transfer_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
215 proto_tree_add_item(esio_data_tansfer_tree
,
216 hf_esio_data_dest_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
218 proto_tree_add_item(esio_data_tansfer_tree
,
219 hf_esio_data_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
221 /*here comes the data*/
222 esio_data_tree
= proto_tree_add_subtree(esio_data_tansfer_tree
, tvb
, offset
,
223 esio_transfer_length
, ett_esio_data
, NULL
, "Data bytes ");
224 for (i
=((esio_transfer_length
)); i
>0; i
--) {
225 proto_tree_add_item(esio_data_tree
,
226 hf_esio_data
, tvb
, offset
,
234 proto_item
*hi
= NULL
;
236 proto_tree_add_item(esio_tree
,
237 hf_esio_sts_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
238 proto_tree_add_item(esio_tree
,
239 hf_esio_sts_size
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
240 proto_tree_add_item(esio_tree
,
241 hf_esio_src_stn_id
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
242 proto_tree_add_item(esio_tree
,
243 hf_esio_rio_sts
, tvb
, offset
+8,
245 hi
= proto_tree_add_item(esio_tree
,
246 hf_esio_rio_tlgs_lost
, tvb
, offset
+9,
248 proto_tree_add_item(esio_tree
,
249 hf_esio_rio_diag
, tvb
, offset
+10,
251 proto_tree_add_item(esio_tree
,
252 hf_esio_rio_flags
, tvb
, offset
+11, 1, ENC_BIG_ENDIAN
);
254 if (tvb_get_uint8(tvb
, offset
+ 9) > 0) {
255 expert_add_info(pinfo
, hi
, &ei_esio_telegram_lost
);
263 return tvb_captured_length(tvb
);
264 /*End of dissect_sbus*/
267 /* Register the protocol with Wireshark */
269 proto_register_esio(void)
271 /* Setup list of header fields See Section 1.6.1 for details*/
272 static hf_register_info hf
[] = {
274 { "Telegram type", "esio.type",
275 FT_UINT16
, BASE_HEX
, VALS(esio_tlg_types
), 0,
280 { "Version", "esio.vers",
281 FT_UINT16
, BASE_DEC
, NULL
, 0,
286 { "Length (bytes)", "esio.len",
287 FT_UINT16
, BASE_DEC
, NULL
, 0,
291 { &hf_esio_transaction_id
,
292 { "Transaction ID", "esio.transaction_id",
293 FT_UINT16
, BASE_DEC
, NULL
, 0,
297 { &hf_esio_src_stn_id
,
298 { "Source station ID", "esio.src_stn_id",
299 FT_UINT32
, BASE_DEC
, NULL
, 0,
304 { "Telegram ID", "esio.transfer.tlg_id",
305 FT_UINT32
, BASE_DEC
, NULL
, 0,
310 { "Nbr. of data transfers", "esio.data.nbr",
311 FT_UINT8
, BASE_DEC
, NULL
, 0,
315 { &hf_esio_data_flags
,
316 { "Transfer header flags", "esio.data.flags",
317 FT_UINT8
, BASE_HEX
, NULL
, 0,
321 { &hf_esio_data_transfer_id
,
322 { "Data transfer ID", "esio.data.transfer_id",
323 FT_UINT32
, BASE_DEC
, NULL
, 0,
327 { &hf_esio_data_dest_id
,
328 { "Data destination ID", "esio.data.destination_id",
329 FT_UINT32
, BASE_DEC
, NULL
, 0,
333 { &hf_esio_data_length
,
334 { "Data transfer length", "esio.data.length",
335 FT_UINT16
, BASE_DEC
, NULL
, 0,
340 { "Data", "esio.data",
341 FT_UINT8
, BASE_DEC
, NULL
, 0,
346 { "Status type", "esio.sts.type",
347 FT_UINT16
, BASE_HEX
, VALS(esio_sts_types
), 0,
352 { "Status length (bytes)", "esio.sts.length",
353 FT_UINT16
, BASE_DEC
, NULL
, 0,
358 { "RIO status", "esio.sts.rio_sts",
359 FT_UINT8
, BASE_DEC
, NULL
, 0,
363 { &hf_esio_rio_tlgs_lost
,
364 { "Lost telegrams to RIO", "esio.sts.rio_lost_tlg",
365 FT_UINT8
, BASE_DEC
, NULL
, 0,
370 { "RIO diagnostics", "esio.sts.rio_diag",
371 FT_UINT8
, BASE_DEC
, NULL
, 0,
375 { &hf_esio_rio_flags
,
376 { "RIO flags", "esio.sts.rio_flags",
377 FT_UINT8
, BASE_HEX
, NULL
, 0,
383 /* Setup protocol subtree array */
384 static int *ett
[] = {
387 &ett_esio_transfer_header
,
388 &ett_esio_transfer_data
,
392 static ei_register_info ei
[] = {
393 { &ei_esio_telegram_lost
, { "esio.telegram_lost", PI_SEQUENCE
, PI_NOTE
, "Telegram(s) lost", EXPFILL
}},
396 expert_module_t
* expert_esio
;
398 /* Register the protocol name and description */
399 proto_esio
= proto_register_protocol("SAIA Ether-S-I/O protocol", "ESIO", "esio");
401 /* Required function calls to register the header fields and subtrees used */
402 proto_register_field_array(proto_esio
, hf
, array_length(hf
));
403 proto_register_subtree_array(ett
, array_length(ett
));
404 expert_esio
= expert_register_protocol(proto_esio
);
405 expert_register_field_array(expert_esio
, ei
, array_length(ei
));
407 /* Register the dissector by name and save its handle */
408 esio_handle
= register_dissector("esio", dissect_esio
, proto_esio
);
412 proto_reg_handoff_esio(void)
414 dissector_add_uint_with_preference("udp.port", ESIO_UDP_PORT
, esio_handle
);
423 * indent-tabs-mode: nil
426 * ex: set shiftwidth=7 tabstop=8 expandtab:
427 * :indentSize=7:tabSize=8:noTabs=true: