/src/wireshark/epan/dissectors/packet-isobus.c
Line | Count | Source |
1 | | /* packet-isobus.c |
2 | | * Routines for ISObus dissection (Based on CANOpen Dissector) |
3 | | * Copyright 2016, Jeroen Sack <jeroen@jeroensack.nl> |
4 | | * ISO 11783 |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@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/reassemble.h> |
17 | | #include "packet-socketcan.h" |
18 | | #include <epan/wmem_scopes.h> |
19 | | #include <epan/expert.h> |
20 | | #include "packet-isobus.h" |
21 | | #include "data-isobus.h" |
22 | | |
23 | | void proto_register_isobus(void); |
24 | | void proto_reg_handoff_isobus(void); |
25 | | |
26 | | static dissector_handle_t isobus_handle; |
27 | | static dissector_table_t subdissector_table_pdu_format; |
28 | | static dissector_table_t subdissector_table_pgn; |
29 | | |
30 | | /* Initialize the protocol and registered fields */ |
31 | | static int proto_isobus; |
32 | | static int hf_isobus_can_id; |
33 | | static int hf_isobus_priority; |
34 | | static int hf_isobus_ext_data_page; |
35 | | static int hf_isobus_data_page; |
36 | | static int hf_isobus_pdu_format_dp0; |
37 | | static int hf_isobus_pdu_format_dp1; |
38 | | static int hf_isobus_group_extension; |
39 | | static int hf_isobus_src_addr; |
40 | | static int hf_isobus_dst_addr; |
41 | | static int hf_isobus_pgn; |
42 | | static int hf_isobus_payload; |
43 | | |
44 | | static int hf_isobus_datetime_response; |
45 | | static int hf_isobus_datetime_seconds; |
46 | | static int hf_isobus_datetime_minute; |
47 | | static int hf_isobus_datetime_hour; |
48 | | static int hf_isobus_datetime_day; |
49 | | static int hf_isobus_datetime_month; |
50 | | static int hf_isobus_datetime_year; |
51 | | static int hf_isobus_datetime_utc_offset; |
52 | | |
53 | | static int hf_isobus_ack_response; |
54 | | static int hf_isobus_ack_control_byte; |
55 | | static int hf_isobus_ack_reserved; |
56 | | static int hf_isobus_ack_address; |
57 | | static int hf_isobus_ack_group_function_value; |
58 | | static int hf_isobus_ack_exended_identifier; |
59 | | static int hf_isobus_ack_pgn; |
60 | | |
61 | | static int hf_isobus_req_requested_pgn; |
62 | | static int hf_isobus_ac_name; |
63 | | static int hf_isobus_ac_name_id_number; |
64 | | static int hf_isobus_ac_name_manufacturer; |
65 | | static int hf_isobus_ac_name_ecu_instance; |
66 | | static int hf_isobus_ac_name_function_instance; |
67 | | static int hf_isobus_ac_name_function; |
68 | | static int hf_isobus_ac_name_reserved; |
69 | | static int hf_isobus_ac_name_vehicle_system; |
70 | | static int hf_isobus_ac_name_vehicle_system_instance; |
71 | | static int hf_isobus_ac_name_industry_group; |
72 | | static int hf_isobus_ac_name_arbitrary_address_capable; |
73 | | |
74 | | static int hf_isobus_transportprotocol_controlbyte; |
75 | | static int hf_isobus_transportprotocol_requesttosend_totalsize; |
76 | | static int hf_isobus_transportprotocol_requesttosend_numberofpackets; |
77 | | static int hf_isobus_transportprotocol_requesttosend_maximumpackets; |
78 | | static int hf_isobus_transportprotocol_requesttosend_pgn; |
79 | | static int hf_isobus_transportprotocol_cleartosend_numberofpacketscanbesent; |
80 | | static int hf_isobus_transportprotocol_cleartosend_nextpacketnumber; |
81 | | static int hf_isobus_transportprotocol_cleartosend_pgn; |
82 | | static int hf_isobus_transportprotocol_endofmsgack_totalsize; |
83 | | static int hf_isobus_transportprotocol_endofmsgack_numberofpackets; |
84 | | static int hf_isobus_transportprotocol_endofmsgack_pgn; |
85 | | static int hf_isobus_transportprotocol_connabort_abortreason; |
86 | | static int hf_isobus_transportprotocol_connabort_pgn; |
87 | | static int hf_isobus_transportprotocol_broadcastannouncemessage_totalsize; |
88 | | static int hf_isobus_transportprotocol_broadcastannouncemessage_numberofpackets; |
89 | | static int hf_isobus_transportprotocol_broadcastannouncemessage_pgn; |
90 | | static int hf_isobus_transportprotocol_reserved; |
91 | | static int hf_isobus_transportprotocol_sequence_number; |
92 | | static int hf_isobus_transportprotocol_data; |
93 | | |
94 | | static int hf_isobus_extendedtransportprotocol_controlbyte; |
95 | | static int hf_isobus_extendedtransportprotocol_requesttosend_totalsize; |
96 | | static int hf_isobus_extendedtransportprotocol_requesttosend_pgn; |
97 | | static int hf_isobus_extendedtransportprotocol_cleartosend_numberofpackets; |
98 | | static int hf_isobus_extendedtransportprotocol_cleartosend_nextpacketnumber; |
99 | | static int hf_isobus_extendedtransportprotocol_cleartosend_pgn; |
100 | | static int hf_isobus_extendedtransportprotocol_datapacketoffset_numberofpackets; |
101 | | static int hf_isobus_extendedtransportprotocol_datapacketoffset_packetoffset; |
102 | | static int hf_isobus_extendedtransportprotocol_datapacketoffset_pgn; |
103 | | static int hf_isobus_extendedtransportprotocol_endofmsgack_totalsize; |
104 | | static int hf_isobus_extendedtransportprotocol_endofmsgack_pgn; |
105 | | static int hf_isobus_extendedtransportprotocol_connabort_abortreason; |
106 | | static int hf_isobus_extendedtransportprotocol_connabort_pgn; |
107 | | static int hf_isobus_extendedtransportprotocol_reserved; |
108 | | static int hf_isobus_extendedtransportprotocol_sequence_number; |
109 | | static int hf_isobus_extendedtransportprotocol_data; |
110 | | |
111 | | static int hf_msg_fragments; |
112 | | static int hf_msg_fragment; |
113 | | static int hf_msg_fragment_overlap; |
114 | | static int hf_msg_fragment_overlap_conflicts; |
115 | | static int hf_msg_fragment_multiple_tails; |
116 | | static int hf_msg_fragment_too_long_fragment; |
117 | | static int hf_msg_fragment_error; |
118 | | static int hf_msg_fragment_count; |
119 | | static int hf_msg_reassembled_in; |
120 | | static int hf_msg_reassembled_length; |
121 | | static int hf_msg_reassembled_data; |
122 | | |
123 | | static expert_field ei_isobus_ack_msg_reserved; |
124 | | |
125 | | /* Desegmentation of isobus transport protocol streams */ |
126 | | static reassembly_table isobus_reassembly_table; |
127 | | static unsigned int reassembly_total_size; |
128 | | static unsigned int reassembly_current_size; |
129 | | |
130 | | #define VT_TO_ECU 230 |
131 | | #define ECU_TO_VT 231 |
132 | 0 | #define REQUEST 234 |
133 | 0 | #define ADDRESS_CLAIM 238 |
134 | 0 | #define ETP_DATA_TRANSFER 199 |
135 | 0 | #define ETP_DATA_MANAGEMENT 200 |
136 | 0 | #define TP_DATA_TRANSFER 235 |
137 | 0 | #define TP_DATA_MANAGEMENT 236 |
138 | | |
139 | | |
140 | | static const value_string pdu_format_dp0[] = { |
141 | | { 7 , "General-purpose valve load sense pressure" }, |
142 | | { 147, "NAME management" }, |
143 | | { 170, "Client to File Server" }, |
144 | | { 171, "File Server to Client" }, |
145 | | { 172, "Guidance machine status" }, |
146 | | { 173, "Guidance system command" }, |
147 | | { 196, "General-purpose valve command" }, |
148 | | { 197, "General-purpose valve measured flow" }, |
149 | | { 198, "General-purpose valve estimated flow" }, |
150 | | { ETP_DATA_TRANSFER, "EXTENDED TRANSPORT PROTOCOL - DATA TRANSFER" }, |
151 | | { ETP_DATA_MANAGEMENT, "EXTENDED TRANSPORT PROTOCOL - CONNECTION MANAGEMENT" }, |
152 | | { 201, "REQUEST2" }, |
153 | | { 202, "TRANSFER" }, |
154 | | { VT_TO_ECU, "VT to ECU" }, |
155 | | { ECU_TO_VT, "ECU to VT" }, |
156 | | { 232, "ACKNOWLEDGEMENT" }, |
157 | | { REQUEST, "REQUEST" }, |
158 | | { TP_DATA_TRANSFER, "TRANSPORT PROTOCOL - DATA TRANSFER" }, |
159 | | { TP_DATA_MANAGEMENT, "TRANSPORT PROTOCOL - CONNECTION MANAGEMENT" }, |
160 | | { ADDRESS_CLAIM, "ADDRESS CLAIM" }, |
161 | | { 239, "PROPRIETARY A" }, |
162 | | { 253, "Certification / Operating state" }, |
163 | | { 254, "Parameter groups" }, |
164 | | { 255, "PROPRIETARY B" }, |
165 | | { 0, NULL } |
166 | | }; |
167 | | |
168 | | static const value_string pdu_format_dp0_short[] = { |
169 | | { 7 , "GPV.LSP" }, |
170 | | { 147, "NM" }, |
171 | | { 170, "C2FS" }, |
172 | | { 171, "FS2C" }, |
173 | | { 172, "G.MS" }, |
174 | | { 173, "G.SC" }, |
175 | | { 196, "GPV.C" }, |
176 | | { 197, "GPV.MF" }, |
177 | | { 198, "GPV.EF" }, |
178 | | { ETP_DATA_TRANSFER, "ETP.DT" }, |
179 | | { ETP_DATA_MANAGEMENT, "ETP.CM" }, |
180 | | { 201, "REQ2" }, |
181 | | { 202, "TRANS" }, |
182 | | { VT_TO_ECU, "VT2ECU" }, |
183 | | { ECU_TO_VT, "ECU2VT" }, |
184 | | { 232, "ACK" }, |
185 | | { REQUEST, "REQ" }, |
186 | | { TP_DATA_TRANSFER, "TP.DT" }, |
187 | | { TP_DATA_MANAGEMENT, "TP.CM" }, |
188 | | { ADDRESS_CLAIM, "AC" }, |
189 | | { 239, "PR.A" }, |
190 | | { 253, "Cert/OS" }, |
191 | | { 254, "PAR.G" }, |
192 | | { 255, "PR.B" }, |
193 | | { 0, NULL } |
194 | | }; |
195 | | |
196 | | static const value_string pdu_format_dp1[] = { |
197 | | { 239, "PROPRIETARY A2" }, |
198 | | { 0, NULL } |
199 | | }; |
200 | | |
201 | | static const value_string pdu_format_dp1_short[] = { |
202 | | { 239, "PR.A2" }, |
203 | | { 0, NULL } |
204 | | }; |
205 | | |
206 | | static const range_string address_range[] = { |
207 | | { 0 , 127, "Preferred Address" }, |
208 | | { 128, 247, "Self-configurable Address" }, |
209 | | { 248, 253, "Preferred Address" }, |
210 | | { 254, 254, "NULL Address" }, |
211 | | { 255, 255, "Global Address" }, |
212 | | { 0, 0, NULL } |
213 | | }; |
214 | | |
215 | | static const range_string connection_abort_reasons[] = { |
216 | | { 1, 1, "Already in one or more connection-managed sessions and cannot support another" }, |
217 | | { 2, 2, "System resources were needed for another task so this connection managed session was terminated" }, |
218 | | { 3, 3, "A timeout occurred and this is the connection abort to close the session" }, |
219 | | { 4, 4, "CTS messages received when data transfer is in progress" }, |
220 | | { 5, 5, "Maximum retransmit request limit reached" }, |
221 | | { 6, 6, "Unexpected data transfer packet" }, |
222 | | { 7, 7, "Bad sequence number (and software is not able to recover)" }, |
223 | | { 8, 8, "Duplicate sequence number (and software is not able to recover)" }, |
224 | | { 9, 250, "Reserved for assignment in a future International Standard" }, |
225 | | { 251, 255, "According to ISO 11783-7 definitions" }, |
226 | | { 0, 0, NULL } |
227 | | }; |
228 | | |
229 | | static const value_string transport_protocol_control_byte[] = { |
230 | | { 16, "Request To Send" }, |
231 | | { 17, "Clear To Send" }, |
232 | | { 19, "End of Message Acknowledgment" }, |
233 | | { 255, "Connection Abort" }, |
234 | | { 32, "Broadcast Announce Message" }, |
235 | | { 0, NULL } |
236 | | }; |
237 | | |
238 | | static const value_string extended_transport_protocol_control_byte[] = { |
239 | | { 20, "Request To Send" }, |
240 | | { 21, "Clear To Send" }, |
241 | | { 22, "Data Packet Offset" }, |
242 | | { 23, "End of Message Acknowledgment" }, |
243 | | { 255, "Connection Abort" }, |
244 | | { 0, NULL } |
245 | | }; |
246 | | |
247 | | static const range_string extended_connection_abort_reasons[] = { |
248 | | { 0, 0, "Reserved" }, |
249 | | { 1, 1, "Already in one or more connection-managed sessions and cannot support another" }, |
250 | | { 2, 2, "System resources were needed for another task so this connection managed session was terminated" }, |
251 | | { 3, 3, "A timeout occurred and this is the connection abort to close the session" }, |
252 | | { 4, 4, "CTS messages received when data transfer is in progress" }, |
253 | | { 5, 5, "Maximum retransmit request limit reached" }, |
254 | | { 6, 6, "Unexpected data transfer packet" }, |
255 | | { 7, 7, "Bad sequence number" }, |
256 | | { 8, 8, "Duplicate sequence number" }, |
257 | | { 9, 9, "Unexpected EDP0 packet" }, |
258 | | { 10, 10, "Unexpected EDP0 PGN" }, |
259 | | { 11, 11, "EDP0 number of packets is greater than CTS" }, |
260 | | { 12, 12, "Bad EDP0 offset" }, |
261 | | { 13, 13, "Reserved" }, |
262 | | { 14, 14, "Unexpected clear to send PGN" }, |
263 | | { 15, 15, "Number of clear to send packets exceeds message size" }, |
264 | | { 16, 249, "Reserved" }, |
265 | | { 250, 250, "Any other error" }, |
266 | | { 251, 255, "According to ISO 11783-7 definitions" }, |
267 | | { 0, 0, NULL } |
268 | | }; |
269 | | |
270 | | typedef enum { |
271 | | ACK = 0, |
272 | | NACK = 1, |
273 | | AccessDenied = 2, |
274 | | CannotRespond = 3, |
275 | | |
276 | | ACK_OneByte = 128, |
277 | | NACK_OneByte = 129, |
278 | | AccessDenied_OneByte = 130, |
279 | | CannotRespond_OneByte = 131, |
280 | | |
281 | | ACK_TwoByte = 144, |
282 | | NACK_TwoByte = 145, |
283 | | AccessDenied_TwoByte = 146, |
284 | | CannotRespond_TwoByte = 147, |
285 | | |
286 | | ACK_ThreeByte = 160, |
287 | | NACK_ThreeByte = 161, |
288 | | AccessDenied_ThreeByte = 162, |
289 | | CannotRespond_ThreeByte = 163, |
290 | | |
291 | | } AckMessageControlByte_t; |
292 | | |
293 | | static const value_string acknowledgement_control_byte[] = { |
294 | | { ACK, "ACK" }, |
295 | | { NACK, "NACK" }, |
296 | | { AccessDenied, "Access denied" }, |
297 | | { CannotRespond, "Cannot respond" }, |
298 | | |
299 | | // One Byte extended identifier |
300 | | { ACK_OneByte, "ACK" }, |
301 | | { NACK_OneByte, "NACK" }, |
302 | | { AccessDenied_OneByte, "Access denied" }, |
303 | | { CannotRespond_OneByte, "Cannot respond" }, |
304 | | |
305 | | // Two Byte extended identifier |
306 | | { ACK_TwoByte, "ACK" }, |
307 | | { NACK_TwoByte, "NACK" }, |
308 | | { AccessDenied_TwoByte, "Access denied" }, |
309 | | { CannotRespond_TwoByte, "Cannot respond" }, |
310 | | |
311 | | // Three Byte extended identifier |
312 | | { ACK_ThreeByte, "ACK" }, |
313 | | { NACK_ThreeByte, "NACK" }, |
314 | | { AccessDenied_ThreeByte, "Access denied" }, |
315 | | { CannotRespond_ThreeByte, "Cannot respond" }, |
316 | | |
317 | | { 0, NULL } |
318 | | }; |
319 | | |
320 | | static int ett_isobus; |
321 | | static int ett_isobus_can_id; |
322 | | static int ett_isobus_name; |
323 | | static int ett_isobus_fragment; |
324 | | static int ett_isobus_fragments; |
325 | | static int ett_isobus_datetime_response; |
326 | | static int ett_isobus_ack_response; |
327 | | |
328 | | static const fragment_items isobus_frag_items = { |
329 | | &ett_isobus_fragment, |
330 | | &ett_isobus_fragments, |
331 | | /* Fragment fields */ |
332 | | &hf_msg_fragments, |
333 | | &hf_msg_fragment, |
334 | | &hf_msg_fragment_overlap, |
335 | | &hf_msg_fragment_overlap_conflicts, |
336 | | &hf_msg_fragment_multiple_tails, |
337 | | &hf_msg_fragment_too_long_fragment, |
338 | | &hf_msg_fragment_error, |
339 | | &hf_msg_fragment_count, |
340 | | /* Reassembled in field */ |
341 | | &hf_msg_reassembled_in, |
342 | | /* Reassembled length field */ |
343 | | &hf_msg_reassembled_length, |
344 | | &hf_msg_reassembled_data, |
345 | | /* Tag */ |
346 | | "Message fragments" |
347 | | }; |
348 | | |
349 | | struct address_combination { |
350 | | uint8_t src_address; |
351 | | uint8_t dst_address; |
352 | | }; |
353 | | |
354 | | struct reassemble_identifier { |
355 | | uint32_t startFrameId; |
356 | | uint32_t endFrameId; |
357 | | uint32_t identifier; |
358 | | }; |
359 | | |
360 | | struct address_reassemble_table { |
361 | | wmem_list_t *reassembleIdentifierTable; |
362 | | uint32_t identifierCounter; |
363 | | }; |
364 | | |
365 | | static wmem_map_t *addressIdentifierTable; |
366 | | |
367 | 0 | static struct reassemble_identifier * findIdentifierFor(wmem_list_t *reassembleIdentifierTable, uint32_t frameIndex) { |
368 | 0 | wmem_list_frame_t *currentItem = wmem_list_head(reassembleIdentifierTable); |
369 | |
|
370 | 0 | while (currentItem != NULL) { |
371 | 0 | struct reassemble_identifier *currentData = (struct reassemble_identifier *)wmem_list_frame_data(currentItem); |
372 | 0 | if (frameIndex <= currentData->endFrameId && frameIndex >= currentData->startFrameId) |
373 | 0 | { |
374 | 0 | return currentData; |
375 | 0 | } else { |
376 | 0 | currentItem = wmem_list_frame_next(currentItem); |
377 | 0 | } |
378 | 0 | } |
379 | 0 | return NULL; |
380 | 0 | } |
381 | | |
382 | | static gboolean |
383 | 0 | address_combination_equal(const void *p1, const void *p2) { |
384 | 0 | const struct address_combination *addr_combi1 = (const struct address_combination *)p1; |
385 | 0 | const struct address_combination *addr_combi2 = (const struct address_combination *)p2; |
386 | |
|
387 | 0 | if (addr_combi1->src_address == addr_combi2->src_address && addr_combi1->dst_address == addr_combi2->dst_address) { |
388 | 0 | return TRUE; |
389 | 0 | } else { |
390 | 0 | return FALSE; |
391 | 0 | } |
392 | 0 | } |
393 | | |
394 | | static unsigned |
395 | 0 | address_combination_hash(const void *p) { |
396 | 0 | const struct address_combination *addr_combi = (const struct address_combination *)p; |
397 | 0 | return (addr_combi->src_address * 256) + (addr_combi->dst_address); |
398 | 0 | } |
399 | | |
400 | 0 | static struct address_reassemble_table * findAddressIdentifierFor(uint8_t src_address, uint8_t dst_address) { |
401 | 0 | struct address_combination *addrCombi = wmem_new(wmem_file_scope(), struct address_combination); |
402 | 0 | struct address_reassemble_table *foundItem; |
403 | |
|
404 | 0 | addrCombi->src_address = src_address; |
405 | 0 | addrCombi->dst_address = dst_address; |
406 | |
|
407 | 0 | foundItem = (struct address_reassemble_table *)wmem_map_lookup(addressIdentifierTable, addrCombi); |
408 | |
|
409 | 0 | if (foundItem != NULL) { |
410 | 0 | return foundItem; |
411 | 0 | } else { |
412 | | /* nothing found so create a new one */ |
413 | 0 | struct address_reassemble_table *newItem; |
414 | 0 | newItem = wmem_new(wmem_file_scope(), struct address_reassemble_table); |
415 | 0 | newItem->identifierCounter = 0; |
416 | 0 | newItem->reassembleIdentifierTable = wmem_list_new(wmem_file_scope()); |
417 | 0 | wmem_map_insert(addressIdentifierTable, addrCombi, newItem); |
418 | 0 | return newItem; |
419 | 0 | } |
420 | 0 | } |
421 | | |
422 | | static const char * |
423 | 0 | isobus_lookup_function(uint32_t industry_group, uint32_t vehicle_system, uint32_t function) { |
424 | 0 | if (function < 128) { |
425 | 0 | return try_val_to_str_ext((uint32_t)function, &isobus_global_name_functions_ext); |
426 | 0 | } |
427 | | |
428 | 0 | uint32_t new_id = industry_group << 16 | vehicle_system << 8 | function; |
429 | 0 | return try_val_to_str_ext((uint32_t)new_id, &isobus_ig_specific_name_functions_ext); |
430 | 0 | } |
431 | | |
432 | | static const char * |
433 | 0 | isobus_lookup_pgn(uint32_t pgn) { |
434 | | /* TODO: add configuration option via UAT? */ |
435 | |
|
436 | 0 | return try_val_to_str_ext(pgn, &isobus_pgn_names_ext); |
437 | 0 | } |
438 | | |
439 | | static void |
440 | 0 | proto_item_append_conditional(proto_item *ti, const char *str) { |
441 | 0 | if (str != NULL && ti != NULL) { |
442 | 0 | proto_item_append_text(ti, " (%s)", str); |
443 | 0 | } |
444 | 0 | } |
445 | | |
446 | | static int |
447 | | call_isobus_subdissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const bool add_proto_name, |
448 | 0 | uint8_t priority, uint8_t pdu_format, unsigned pgn, uint8_t source_addr, void *data) { |
449 | 0 | can_info_t *can_info = (can_info_t *)data; |
450 | |
|
451 | 0 | isobus_info_t isobus_info; |
452 | 0 | isobus_info.can_id = can_info->id; |
453 | 0 | isobus_info.bus_id = can_info->bus_id; |
454 | 0 | isobus_info.pdu_format = pdu_format; |
455 | 0 | isobus_info.pgn = pgn; |
456 | 0 | isobus_info.priority = priority; |
457 | 0 | isobus_info.source_addr = source_addr; |
458 | | |
459 | | /* try PGN */ |
460 | 0 | int ret = dissector_try_uint_with_data(subdissector_table_pgn, pgn, tvb, pinfo, tree, add_proto_name, &isobus_info); |
461 | 0 | if (ret > 0) { |
462 | 0 | return ret; |
463 | 0 | } |
464 | | |
465 | | /* try PDU Format */ |
466 | 0 | return dissector_try_uint_with_data(subdissector_table_pdu_format, pdu_format, tvb, pinfo, tree, add_proto_name, &isobus_info); |
467 | 0 | } |
468 | | |
469 | | static void |
470 | | dissect_etp_connection_management(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
471 | 0 | { |
472 | 0 | uint32_t control_byte; |
473 | |
|
474 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_extendedtransportprotocol_controlbyte, tvb, 0, 1, ENC_LITTLE_ENDIAN, &control_byte); |
475 | |
|
476 | 0 | switch (control_byte) { |
477 | 0 | case 20: { /* ETP.CM_RTS */ |
478 | 0 | uint32_t total_size; |
479 | |
|
480 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_extendedtransportprotocol_requesttosend_totalsize, tvb, 1, 4, ENC_LITTLE_ENDIAN, &total_size); |
481 | 0 | proto_tree_add_item(tree, hf_isobus_extendedtransportprotocol_requesttosend_pgn, tvb, 5, 3, ENC_LITTLE_ENDIAN); |
482 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Request to send message of %u bytes", total_size); |
483 | 0 | break; |
484 | 0 | } |
485 | 0 | case 21: { /* ETP.CM_CTS */ |
486 | 0 | uint32_t number_of_packets; |
487 | 0 | uint32_t next_packet_number; |
488 | |
|
489 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_extendedtransportprotocol_cleartosend_numberofpackets, tvb, 1, 1, ENC_LITTLE_ENDIAN, &number_of_packets); |
490 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_extendedtransportprotocol_cleartosend_nextpacketnumber, tvb, 2, 3, ENC_LITTLE_ENDIAN, &next_packet_number); |
491 | 0 | proto_tree_add_item(tree, hf_isobus_extendedtransportprotocol_cleartosend_pgn, tvb, 5, 3, ENC_LITTLE_ENDIAN); |
492 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Clear to send, can receive %u packets, next packet is %u", number_of_packets, next_packet_number); |
493 | 0 | break; |
494 | 0 | } |
495 | 0 | case 22: { /* ETP.CM_DPO */ |
496 | 0 | uint32_t number_of_packets; |
497 | 0 | uint32_t packet_offset; |
498 | |
|
499 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_extendedtransportprotocol_datapacketoffset_numberofpackets, tvb, 1, 1, ENC_LITTLE_ENDIAN, &number_of_packets); |
500 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_extendedtransportprotocol_datapacketoffset_packetoffset, tvb, 2, 3, ENC_LITTLE_ENDIAN, &packet_offset); |
501 | 0 | proto_tree_add_item(tree, hf_isobus_extendedtransportprotocol_datapacketoffset_pgn, tvb, 5, 3, ENC_LITTLE_ENDIAN); |
502 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Data packet offset, %u packets at offset %u", number_of_packets, packet_offset); |
503 | 0 | break; |
504 | 0 | } |
505 | 0 | case 23: { /* ETP.CM_EOMA */ |
506 | 0 | uint32_t total_size; |
507 | |
|
508 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_extendedtransportprotocol_endofmsgack_totalsize, tvb, 1, 4, ENC_LITTLE_ENDIAN, &total_size); |
509 | 0 | proto_tree_add_item(tree, hf_isobus_extendedtransportprotocol_endofmsgack_pgn, tvb, 5, 3, ENC_LITTLE_ENDIAN); |
510 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "End of Message Acknowledgment, %u bytes sent", total_size); |
511 | 0 | break; |
512 | 0 | } |
513 | 0 | case 255: { /* ETP.CM_Abort */ |
514 | 0 | uint32_t abort_reason; |
515 | |
|
516 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_extendedtransportprotocol_connabort_abortreason, tvb, 1, 1, ENC_LITTLE_ENDIAN, &abort_reason); |
517 | 0 | proto_tree_add_item(tree, hf_isobus_extendedtransportprotocol_reserved, tvb, 2, 3, ENC_NA); |
518 | 0 | proto_tree_add_item(tree, hf_isobus_extendedtransportprotocol_connabort_pgn, tvb, 5, 3, ENC_LITTLE_ENDIAN); |
519 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Abort, %s", rval_to_str_const(abort_reason, extended_connection_abort_reasons, "unknown reason")); |
520 | 0 | break; |
521 | 0 | } |
522 | 0 | default: |
523 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown control byte 0x%02x", control_byte); |
524 | 0 | proto_tree_add_item(tree, hf_isobus_extendedtransportprotocol_data, tvb, 1, -1, ENC_NA); |
525 | 0 | break; |
526 | 0 | } |
527 | 0 | } |
528 | | |
529 | | /* Code to actually dissect the packets */ |
530 | | static int |
531 | 0 | dissect_isobus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
532 | 0 | uint8_t priority; |
533 | | /* unsigned ext_data_page; */ |
534 | 0 | unsigned src_addr; |
535 | 0 | unsigned data_page; |
536 | 0 | uint8_t pdu_format; |
537 | 0 | uint8_t pdu_specific; |
538 | 0 | unsigned pgn; |
539 | 0 | struct can_info can_info; |
540 | 0 | char str_dst[10]; |
541 | 0 | char str_src[4]; |
542 | |
|
543 | 0 | static unsigned seqnr = 0; |
544 | |
|
545 | 0 | int data_offset = 0; |
546 | |
|
547 | 0 | proto_item *ti, *can_id_ti; |
548 | 0 | proto_tree *isobus_tree; |
549 | 0 | proto_tree *isobus_can_id_tree; |
550 | |
|
551 | 0 | struct reassemble_identifier *identifier = NULL; |
552 | 0 | struct address_reassemble_table *address_reassemble_table_item = NULL; |
553 | |
|
554 | 0 | DISSECTOR_ASSERT(data); |
555 | 0 | can_info = *((struct can_info*)data); |
556 | |
|
557 | 0 | if ((can_info.id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) || !(can_info.id & CAN_EFF_FLAG)) { |
558 | | /* Error, RTR and frames with standard ids are not for us. */ |
559 | 0 | return 0; |
560 | 0 | } |
561 | | |
562 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISObus"); |
563 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
564 | |
|
565 | 0 | priority = (can_info.id >> 26) & 0x07; |
566 | | /*ext_data_page = (can_info.id >> 25) & 0x01;*/ |
567 | 0 | data_page = (can_info.id >> 24) & 0x01; |
568 | 0 | pdu_format = (can_info.id >> 16) & 0xff; |
569 | 0 | pdu_specific = (can_info.id >> 8) & 0xff; |
570 | 0 | src_addr = (can_info.id >> 0 ) & 0xff; |
571 | |
|
572 | 0 | if (pdu_format < 240) { |
573 | 0 | pgn = (can_info.id >> 8) & 0x03ff00; |
574 | 0 | } else { |
575 | 0 | pgn = (can_info.id >> 8) & 0x03ffff; |
576 | 0 | } |
577 | |
|
578 | 0 | ti = proto_tree_add_item(tree, proto_isobus, tvb, 0, tvb_reported_length(tvb), ENC_NA); |
579 | 0 | isobus_tree = proto_item_add_subtree(ti, ett_isobus); |
580 | | |
581 | | /* add COB-ID with function code and node id */ |
582 | 0 | can_id_ti = proto_tree_add_uint(isobus_tree, hf_isobus_can_id, tvb, 0, 0, can_info.id); |
583 | 0 | isobus_can_id_tree = proto_item_add_subtree(can_id_ti, ett_isobus_can_id); |
584 | | |
585 | | /* add priority */ |
586 | 0 | ti = proto_tree_add_uint(isobus_can_id_tree, hf_isobus_priority, tvb, 0, 0, can_info.id); |
587 | 0 | proto_item_set_generated(ti); |
588 | | |
589 | | /* add extended data page */ |
590 | 0 | ti = proto_tree_add_uint(isobus_can_id_tree, hf_isobus_ext_data_page, tvb, 0, 0, can_info.id); |
591 | 0 | proto_item_set_generated(ti); |
592 | | |
593 | | /* add data page */ |
594 | 0 | ti = proto_tree_add_uint(isobus_can_id_tree, hf_isobus_data_page, tvb, 0, 0, can_info.id); |
595 | 0 | proto_item_set_generated(ti); |
596 | | |
597 | | /* add pdu format */ |
598 | 0 | switch(data_page) { |
599 | 0 | case 0: |
600 | 0 | ti = proto_tree_add_uint(isobus_can_id_tree, hf_isobus_pdu_format_dp0, tvb, 0, 0, can_info.id); |
601 | 0 | proto_item_set_generated(ti); |
602 | 0 | break; |
603 | 0 | case 1: |
604 | 0 | ti = proto_tree_add_uint(isobus_can_id_tree, hf_isobus_pdu_format_dp1, tvb, 0, 0, can_info.id); |
605 | 0 | proto_item_set_generated(ti); |
606 | 0 | break; |
607 | 0 | } |
608 | | |
609 | | /* add pdu specific */ |
610 | 0 | if (pdu_format <= 239) { |
611 | 0 | ti = proto_tree_add_uint(isobus_can_id_tree, hf_isobus_dst_addr, tvb, 0, 0, can_info.id); |
612 | 0 | proto_item_set_generated(ti); |
613 | 0 | } else { |
614 | 0 | ti = proto_tree_add_uint(isobus_can_id_tree, hf_isobus_group_extension, tvb, 0, 0, can_info.id); |
615 | 0 | proto_item_set_generated(ti); |
616 | 0 | } |
617 | | |
618 | | /* add source address */ |
619 | 0 | ti = proto_tree_add_uint(isobus_can_id_tree, hf_isobus_src_addr, tvb, 0, 0, can_info.id); |
620 | 0 | proto_item_set_generated(ti); |
621 | | |
622 | | /* put source address in source field */ |
623 | 0 | snprintf(str_src, 4, "%d", src_addr); |
624 | 0 | alloc_address_wmem(pinfo->pool, &pinfo->src, AT_STRINGZ, (int)strlen(str_src) + 1, str_src); |
625 | |
|
626 | 0 | if (pdu_format <= 239) { |
627 | | /* put destination address in address field */ |
628 | 0 | snprintf(str_dst, 4, "%d", pdu_specific); |
629 | 0 | alloc_address_wmem(pinfo->pool, &pinfo->dst, AT_STRINGZ, (int)strlen(str_dst) + 1, str_dst); |
630 | 0 | } else { |
631 | | /* put group destination address in address field and add (grp) to it */ |
632 | 0 | snprintf(str_dst, 10, "%d (grp)", pdu_specific); |
633 | 0 | alloc_address_wmem(pinfo->pool, &pinfo->dst, AT_STRINGZ, (int)strlen(str_dst) + 1, str_dst); |
634 | 0 | } |
635 | |
|
636 | 0 | proto_tree_add_uint(isobus_tree, hf_isobus_pgn, tvb, 0, 0, pgn); |
637 | |
|
638 | 0 | switch(data_page) { |
639 | 0 | case 0: |
640 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "[%s] ", val_to_str_const(pdu_format, pdu_format_dp0_short, "Unknown")); |
641 | 0 | break; |
642 | 0 | case 1: |
643 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "[%s] ", val_to_str_const(pdu_format, pdu_format_dp1_short, "Unknown")); |
644 | 0 | break; |
645 | 0 | } |
646 | | |
647 | 0 | if (pdu_format == TP_DATA_MANAGEMENT || pdu_format == TP_DATA_TRANSFER || pdu_format == ETP_DATA_MANAGEMENT || pdu_format == ETP_DATA_TRANSFER) { |
648 | 0 | bool isReply = false; |
649 | |
|
650 | 0 | if (pdu_format == TP_DATA_MANAGEMENT) { |
651 | 0 | uint8_t control_byte = tvb_get_uint8(tvb, data_offset); |
652 | 0 | switch(control_byte) { |
653 | 0 | case 17: |
654 | 0 | case 19: |
655 | 0 | isReply = true; |
656 | 0 | break; |
657 | 0 | case 16: |
658 | 0 | default: |
659 | 0 | isReply = false; |
660 | 0 | break; |
661 | 0 | } |
662 | 0 | } |
663 | | |
664 | 0 | if (isReply) { |
665 | 0 | address_reassemble_table_item = findAddressIdentifierFor(pdu_specific, src_addr); |
666 | 0 | } else { |
667 | 0 | address_reassemble_table_item = findAddressIdentifierFor(src_addr, pdu_specific); |
668 | 0 | } |
669 | |
|
670 | 0 | identifier = findIdentifierFor(address_reassemble_table_item->reassembleIdentifierTable, pinfo->num); |
671 | 0 | } |
672 | | |
673 | 0 | if (pdu_format == TP_DATA_MANAGEMENT) { |
674 | 0 | uint32_t control_byte; |
675 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_controlbyte, tvb, data_offset, 1, ENC_LITTLE_ENDIAN, &control_byte); |
676 | 0 | data_offset += 1; |
677 | |
|
678 | 0 | if (control_byte == 16) { |
679 | 0 | uint32_t total_size, number_of_packets; |
680 | |
|
681 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_requesttosend_totalsize, tvb, data_offset, 2, ENC_LITTLE_ENDIAN, &total_size); |
682 | 0 | data_offset += 2; |
683 | |
|
684 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_requesttosend_numberofpackets, tvb, data_offset, 1, ENC_LITTLE_ENDIAN, &number_of_packets); |
685 | 0 | data_offset += 1; |
686 | |
|
687 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_requesttosend_maximumpackets, tvb, data_offset, 1, ENC_LITTLE_ENDIAN); |
688 | 0 | data_offset += 1; |
689 | |
|
690 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_requesttosend_pgn, tvb, data_offset, 3, ENC_LITTLE_ENDIAN); |
691 | |
|
692 | 0 | if (identifier) { |
693 | 0 | seqnr = identifier->identifier; |
694 | 0 | } else { |
695 | 0 | struct reassemble_identifier *reassembleIdentifierTableEntry = wmem_new(wmem_file_scope(), struct reassemble_identifier); |
696 | 0 | seqnr = ++address_reassemble_table_item->identifierCounter; |
697 | 0 | reassembleIdentifierTableEntry->identifier = seqnr; |
698 | 0 | reassembleIdentifierTableEntry->startFrameId = pinfo->num; |
699 | 0 | reassembleIdentifierTableEntry->endFrameId = pinfo->num; |
700 | |
|
701 | 0 | wmem_list_append(address_reassemble_table_item->reassembleIdentifierTable, reassembleIdentifierTableEntry); |
702 | 0 | } |
703 | |
|
704 | 0 | fragment_add_seq(&isobus_reassembly_table, tvb, 5, pinfo, seqnr, NULL, 0, 3, true, 0); |
705 | 0 | fragment_set_tot_len(&isobus_reassembly_table, pinfo, seqnr, NULL, number_of_packets); |
706 | 0 | reassembly_current_size = 3; |
707 | 0 | reassembly_total_size = total_size + 3; |
708 | |
|
709 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Request to send message of %u bytes in %u fragments", total_size, number_of_packets); |
710 | 0 | } else if (control_byte == 17) { |
711 | 0 | uint32_t number_of_packets_can_be_sent, next_packet_number; |
712 | |
|
713 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_cleartosend_numberofpacketscanbesent, tvb, data_offset, 1, ENC_LITTLE_ENDIAN, &number_of_packets_can_be_sent); |
714 | 0 | data_offset += 1; |
715 | |
|
716 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_cleartosend_nextpacketnumber, tvb, data_offset, 1, ENC_LITTLE_ENDIAN, &next_packet_number); |
717 | 0 | data_offset += 1; |
718 | |
|
719 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_reserved, tvb, data_offset, 2, ENC_NA); |
720 | 0 | data_offset += 2; |
721 | |
|
722 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_cleartosend_pgn, tvb, data_offset, 3, ENC_LITTLE_ENDIAN); |
723 | |
|
724 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Clear to send, can receive %u packets, next packet is %u", number_of_packets_can_be_sent, next_packet_number); |
725 | 0 | } else if (control_byte == 19) { |
726 | 0 | uint32_t total_size, number_of_packets; |
727 | |
|
728 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_endofmsgack_totalsize, tvb, data_offset, 2, ENC_LITTLE_ENDIAN, &total_size); |
729 | 0 | data_offset += 2; |
730 | |
|
731 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_endofmsgack_numberofpackets, tvb, data_offset, 1, ENC_LITTLE_ENDIAN, &number_of_packets); |
732 | 0 | data_offset += 1; |
733 | |
|
734 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_reserved, tvb, data_offset, 1, ENC_NA); |
735 | 0 | data_offset += 1; |
736 | |
|
737 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_endofmsgack_pgn, tvb, data_offset, 3, ENC_LITTLE_ENDIAN); |
738 | |
|
739 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "End of Message Acknowledgment, %u bytes sent in %u packets", total_size, number_of_packets); |
740 | 0 | } else if (control_byte == 255) { |
741 | 0 | uint32_t connection_abort_reason; |
742 | |
|
743 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_connabort_abortreason, tvb, data_offset, 1, ENC_LITTLE_ENDIAN, &connection_abort_reason); |
744 | 0 | data_offset += 1; |
745 | |
|
746 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_reserved, tvb, data_offset, 3, ENC_NA); |
747 | 0 | data_offset += 3; |
748 | |
|
749 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_connabort_pgn, tvb, data_offset, 3, ENC_LITTLE_ENDIAN); |
750 | |
|
751 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Abort, %s", rval_to_str_const(connection_abort_reason, connection_abort_reasons, "unknown reason")); |
752 | 0 | } else if (control_byte == 32) { |
753 | 0 | uint32_t total_size, number_of_packets; |
754 | |
|
755 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_broadcastannouncemessage_totalsize, tvb, data_offset, 2, ENC_LITTLE_ENDIAN, &total_size); |
756 | 0 | data_offset += 2; |
757 | |
|
758 | 0 | proto_tree_add_item_ret_uint(tree, hf_isobus_transportprotocol_broadcastannouncemessage_numberofpackets, tvb, data_offset, 1, ENC_LITTLE_ENDIAN, &number_of_packets); |
759 | 0 | data_offset += 1; |
760 | |
|
761 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_reserved, tvb, data_offset, 1, ENC_NA); |
762 | 0 | data_offset += 1; |
763 | |
|
764 | 0 | proto_tree_add_item(tree, hf_isobus_transportprotocol_broadcastannouncemessage_pgn, tvb, data_offset, 3, ENC_LITTLE_ENDIAN); |
765 | |
|
766 | 0 | if (identifier) { |
767 | 0 | seqnr = identifier->identifier; |
768 | 0 | } else { |
769 | 0 | struct reassemble_identifier *reassembleIdentifierTableEntry = wmem_new(wmem_file_scope(), struct reassemble_identifier); |
770 | 0 | seqnr = ++address_reassemble_table_item->identifierCounter; |
771 | 0 | reassembleIdentifierTableEntry->identifier = seqnr; |
772 | 0 | reassembleIdentifierTableEntry->startFrameId = pinfo->num; |
773 | 0 | reassembleIdentifierTableEntry->endFrameId = pinfo->num; |
774 | |
|
775 | 0 | wmem_list_append(address_reassemble_table_item->reassembleIdentifierTable, reassembleIdentifierTableEntry); |
776 | 0 | } |
777 | |
|
778 | 0 | fragment_add_seq(&isobus_reassembly_table, tvb, 5, pinfo, seqnr, NULL, 0, 3, true, 0); |
779 | 0 | fragment_set_tot_len(&isobus_reassembly_table, pinfo, seqnr, NULL, number_of_packets); |
780 | 0 | reassembly_current_size = 3; |
781 | 0 | reassembly_total_size = total_size + 3; |
782 | |
|
783 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Broadcast Announcement Message, %u bytes sent in %u packets", total_size, number_of_packets); |
784 | 0 | } else { |
785 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown control byte 0x%02x", control_byte); |
786 | 0 | proto_tree_add_item(isobus_tree, hf_isobus_payload, tvb, 1, -1, ENC_NA); |
787 | 0 | } |
788 | 0 | } else if (pdu_format == ETP_DATA_MANAGEMENT) { |
789 | 0 | dissect_etp_connection_management(tvb, pinfo, isobus_tree); |
790 | 0 | } |
791 | | |
792 | | /* Decode every TP.DT packet even when no matching CM packet was captured. */ |
793 | 0 | else if (pdu_format == TP_DATA_TRANSFER && address_reassemble_table_item->reassembleIdentifierTable != NULL) |
794 | 0 | { |
795 | 0 | tvbuff_t *reassembled_data; |
796 | 0 | uint16_t fragment_size = 0; |
797 | 0 | bool lastPacket; |
798 | 0 | uint8_t sequenceId = tvb_get_uint8(tvb, 0); |
799 | 0 | fragment_head *fg_head; |
800 | |
|
801 | 0 | proto_tree_add_item(isobus_tree, hf_isobus_transportprotocol_sequence_number, tvb, 0, 1, ENC_LITTLE_ENDIAN); |
802 | 0 | proto_tree_add_item(isobus_tree, hf_isobus_transportprotocol_data, tvb, 1, -1, ENC_NA); |
803 | |
|
804 | 0 | if (identifier == NULL) { |
805 | 0 | wmem_list_frame_t *lastItem = wmem_list_tail(address_reassemble_table_item->reassembleIdentifierTable); |
806 | |
|
807 | 0 | if (lastItem != NULL) { |
808 | 0 | struct reassemble_identifier *lastIdentifier = (struct reassemble_identifier *)wmem_list_frame_data(lastItem); |
809 | 0 | lastIdentifier->endFrameId = pinfo->num; |
810 | 0 | identifier = lastIdentifier; |
811 | 0 | } |
812 | 0 | } |
813 | |
|
814 | 0 | if (identifier != NULL) { |
815 | 0 | if (reassembly_total_size > reassembly_current_size + 7) { |
816 | 0 | fragment_size = 7; |
817 | 0 | lastPacket = false; |
818 | 0 | } else { |
819 | 0 | fragment_size = reassembly_total_size - reassembly_current_size; |
820 | 0 | lastPacket = true; |
821 | 0 | } |
822 | |
|
823 | 0 | fg_head = fragment_add_seq(&isobus_reassembly_table, tvb, 1, pinfo, identifier->identifier, NULL, sequenceId, fragment_size, !lastPacket, 0); |
824 | 0 | reassembly_current_size += fragment_size; |
825 | |
|
826 | 0 | reassembled_data = process_reassembled_data(tvb, 0, pinfo, "Reassembled data", fg_head, &isobus_frag_items, NULL, isobus_tree); |
827 | |
|
828 | 0 | if (reassembled_data) { |
829 | 0 | uint32_t id_reassembled = tvb_get_uint24(reassembled_data, 0, ENC_BIG_ENDIAN); |
830 | 0 | uint8_t pdu_format_reassembled = (uint8_t)((id_reassembled >> 8) & 0xff); |
831 | |
|
832 | 0 | uint32_t pgn_reassembled; |
833 | 0 | if (pdu_format < 240) { |
834 | 0 | pgn_reassembled = id_reassembled & 0x03ff00; |
835 | 0 | } else { |
836 | 0 | pgn_reassembled = id_reassembled & 0x03ffff; |
837 | 0 | } |
838 | |
|
839 | 0 | proto_tree_add_uint(isobus_tree, hf_isobus_pgn, reassembled_data, 0, 3, pgn_reassembled); |
840 | |
|
841 | 0 | if (call_isobus_subdissector(tvb_new_subset_remaining(reassembled_data, 3), pinfo, isobus_tree, false, 0, pdu_format_reassembled, |
842 | 0 | pgn_reassembled, src_addr, data) == 0) { |
843 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Protocol not yet supported"); |
844 | 0 | } |
845 | 0 | } else { |
846 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Fragment number %u", sequenceId); |
847 | 0 | } |
848 | 0 | } else { |
849 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "ERROR: Transport protocol was not initialized"); |
850 | 0 | } |
851 | 0 | } else if (pdu_format == ETP_DATA_TRANSFER) { |
852 | 0 | uint8_t sequence_number = tvb_get_uint8(tvb, 0); |
853 | |
|
854 | 0 | proto_tree_add_item(isobus_tree, hf_isobus_extendedtransportprotocol_sequence_number, tvb, 0, 1, ENC_LITTLE_ENDIAN); |
855 | 0 | proto_tree_add_item(isobus_tree, hf_isobus_extendedtransportprotocol_data, tvb, 1, -1, ENC_NA); |
856 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Data transfer packet, sequence number %u", sequence_number); |
857 | 0 | } else if (pdu_format == REQUEST) { |
858 | 0 | uint32_t req_pgn; |
859 | 0 | proto_tree_add_item_ret_uint(isobus_tree, hf_isobus_req_requested_pgn, tvb, 0, 3, ENC_LITTLE_ENDIAN, &req_pgn); |
860 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Requesting PGN: %u", req_pgn); |
861 | 0 | const char *tmp = isobus_lookup_pgn(req_pgn); |
862 | |
|
863 | 0 | if (tmp != NULL) { |
864 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", tmp); |
865 | 0 | } |
866 | 0 | } else if (pdu_format == ADDRESS_CLAIM) { |
867 | 0 | proto_tree *name_tree; |
868 | 0 | ti = proto_tree_add_item(isobus_tree, hf_isobus_ac_name, tvb, 0, 8, ENC_NA); |
869 | 0 | name_tree = proto_item_add_subtree(ti, ett_isobus_name); |
870 | | |
871 | | /* we cannot directly use the value strings as they depend on other parameters */ |
872 | 0 | uint64_t industry_group, vehicle_system, function, manufacturer; |
873 | 0 | proto_tree_add_item(name_tree, hf_isobus_ac_name_arbitrary_address_capable, tvb, 0, 8, ENC_LITTLE_ENDIAN); |
874 | 0 | ti = proto_tree_add_item_ret_uint64(name_tree, hf_isobus_ac_name_industry_group, tvb, 0, 8, ENC_LITTLE_ENDIAN, &industry_group); |
875 | 0 | proto_item_append_conditional(ti, try_val_to_str_ext((uint32_t)industry_group, &isobus_industry_groups_ext)); |
876 | |
|
877 | 0 | proto_tree_add_item(name_tree, hf_isobus_ac_name_vehicle_system_instance, tvb, 0, 8, ENC_LITTLE_ENDIAN); |
878 | 0 | ti = proto_tree_add_item_ret_uint64(name_tree, hf_isobus_ac_name_vehicle_system, tvb, 0, 8, ENC_LITTLE_ENDIAN, &vehicle_system); |
879 | 0 | proto_item_append_conditional(ti, try_val_to_str_ext((uint16_t)industry_group * 256 + (uint8_t)vehicle_system, &isobus_vehicle_systems_ext)); |
880 | |
|
881 | 0 | proto_tree_add_item(name_tree, hf_isobus_ac_name_reserved, tvb, 0, 8, ENC_LITTLE_ENDIAN); |
882 | 0 | ti = proto_tree_add_item_ret_uint64(name_tree, hf_isobus_ac_name_function, tvb, 0, 8, ENC_LITTLE_ENDIAN, &function); |
883 | 0 | proto_item_append_conditional(ti, isobus_lookup_function((uint32_t)industry_group, (uint32_t)vehicle_system, (uint32_t)function)); |
884 | |
|
885 | 0 | proto_tree_add_item(name_tree, hf_isobus_ac_name_function_instance, tvb, 0, 8, ENC_LITTLE_ENDIAN); |
886 | |
|
887 | 0 | proto_tree_add_item(name_tree, hf_isobus_ac_name_ecu_instance, tvb, 0, 8, ENC_LITTLE_ENDIAN); |
888 | 0 | ti = proto_tree_add_item_ret_uint64(name_tree, hf_isobus_ac_name_manufacturer, tvb, 0, 8, ENC_LITTLE_ENDIAN, &manufacturer); |
889 | 0 | proto_item_append_conditional(ti, try_val_to_str_ext((uint32_t)manufacturer, &isobus_manufacturers_ext)); |
890 | |
|
891 | 0 | proto_tree_add_item(name_tree, hf_isobus_ac_name_id_number, tvb, 0, 8, ENC_LITTLE_ENDIAN); |
892 | |
|
893 | 0 | unsigned address_claimed = can_info.id & 0xff; |
894 | 0 | switch (address_claimed) { |
895 | 0 | case 255: |
896 | | /* This seems to be not allowed. Create ticket, if this is not correct. */ |
897 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Trying to claim global destination address!? This seems wrong!"); |
898 | 0 | break; |
899 | 0 | case 254: |
900 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Cannot claim address"); |
901 | 0 | break; |
902 | 0 | default: |
903 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Address claimed %u", address_claimed); |
904 | 0 | } |
905 | 0 | } else if (call_isobus_subdissector(tvb, pinfo, isobus_tree, false, priority, pdu_format, pgn, src_addr, data) == 0) { |
906 | 0 | if (pgn == 65254) { |
907 | | // Time/Date response |
908 | 0 | uint16_t year = tvb_get_uint8(tvb, 5) + 1985; |
909 | 0 | uint8_t day = (uint8_t)(tvb_get_uint8(tvb, 4) * 0.25f); |
910 | 0 | uint8_t sec = (uint8_t)(tvb_get_uint8(tvb, 0) * 0.25f); |
911 | 0 | int8_t utc_hour_offset = tvb_get_int8(tvb, 7) - 125; |
912 | 0 | int8_t utc_min_offset = tvb_get_int8(tvb, 6) - 125; |
913 | |
|
914 | 0 | wmem_strbuf_t *utc_min_offset_strbuf = wmem_strbuf_create(pinfo->pool); |
915 | 0 | if (utc_min_offset) |
916 | 0 | { |
917 | 0 | wmem_strbuf_append_printf(utc_min_offset_strbuf, " %d min", utc_min_offset); |
918 | 0 | } |
919 | |
|
920 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Date/time: %u.%u.%u %u:%u:%u (UTC+%d hour%s)", |
921 | 0 | year, |
922 | 0 | tvb_get_uint8(tvb, 3), |
923 | 0 | day, |
924 | 0 | tvb_get_uint8(tvb, 2), |
925 | 0 | tvb_get_uint8(tvb, 1), |
926 | 0 | sec, |
927 | 0 | utc_hour_offset, |
928 | 0 | wmem_strbuf_finalize(utc_min_offset_strbuf) |
929 | 0 | ); |
930 | 0 | proto_tree *datetime_tree; |
931 | 0 | ti = proto_tree_add_item(isobus_tree, hf_isobus_datetime_response, tvb, 0, 8, ENC_NA); |
932 | 0 | datetime_tree = proto_item_add_subtree(ti, ett_isobus_datetime_response); |
933 | |
|
934 | 0 | proto_tree_add_item(datetime_tree, hf_isobus_datetime_year, tvb, 5, 1, ENC_NA); |
935 | 0 | proto_tree_add_item(datetime_tree, hf_isobus_datetime_month, tvb, 3, 1, ENC_NA); |
936 | 0 | proto_tree_add_item(datetime_tree, hf_isobus_datetime_day, tvb, 4, 1, ENC_NA); |
937 | |
|
938 | 0 | proto_tree_add_item(datetime_tree, hf_isobus_datetime_hour, tvb, 2, 1, ENC_NA); |
939 | 0 | proto_tree_add_item(datetime_tree, hf_isobus_datetime_minute, tvb, 1, 1, ENC_NA); |
940 | 0 | proto_tree_add_item(datetime_tree, hf_isobus_datetime_seconds, tvb, 0, 1, ENC_NA); |
941 | |
|
942 | 0 | proto_tree_add_item(datetime_tree, hf_isobus_datetime_utc_offset, tvb, 6, 2, ENC_LITTLE_ENDIAN); |
943 | 0 | } else if (pgn == 59392) { |
944 | | // Acknowledgement message |
945 | 0 | uint32_t reserved = 0xFFFFFF; |
946 | 0 | col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(tvb_get_uint8(tvb, 0), acknowledgement_control_byte, "Unknown")); |
947 | |
|
948 | 0 | proto_tree *ack_tree; |
949 | 0 | ti = proto_tree_add_item(isobus_tree, hf_isobus_ack_response, tvb, 0, 8, ENC_NA); |
950 | 0 | ack_tree = proto_item_add_subtree(ti, ett_isobus_ack_response); |
951 | |
|
952 | 0 | proto_tree_add_item(ack_tree, hf_isobus_ack_control_byte, tvb, 0, 1, ENC_NA); |
953 | 0 | uint8_t controlByte = tvb_get_uint8(tvb, 0); |
954 | |
|
955 | 0 | if ((controlByte <= CannotRespond) || (ACK_OneByte <= controlByte && controlByte <= CannotRespond_OneByte)) { |
956 | 0 | if (controlByte <= CannotRespond) |
957 | 0 | proto_tree_add_item(ack_tree, hf_isobus_ack_group_function_value, tvb, 1, 1, ENC_NA); |
958 | 0 | else |
959 | 0 | proto_tree_add_item(ack_tree, hf_isobus_ack_exended_identifier, tvb, 1, 1, ENC_NA); |
960 | 0 | proto_tree_add_item_ret_uint(ack_tree, hf_isobus_ack_reserved, tvb, 2, 2, ENC_LITTLE_ENDIAN, &reserved); |
961 | 0 | if (reserved != 0xFFFF) { |
962 | 0 | expert_add_info(pinfo, ti, &ei_isobus_ack_msg_reserved); |
963 | 0 | } |
964 | 0 | } else if (ACK_TwoByte <= controlByte && controlByte <= CannotRespond_TwoByte) { |
965 | 0 | proto_tree_add_item(ack_tree, hf_isobus_ack_exended_identifier, tvb, 1, 2, ENC_LITTLE_ENDIAN); |
966 | 0 | proto_tree_add_item_ret_uint(ack_tree, hf_isobus_ack_reserved, tvb, 2, 1, ENC_LITTLE_ENDIAN, &reserved); |
967 | 0 | if (reserved != 0xFF) { |
968 | 0 | expert_add_info(pinfo, ti, &ei_isobus_ack_msg_reserved); |
969 | 0 | } |
970 | 0 | } else if (ACK_ThreeByte <= controlByte && controlByte <= CannotRespond_ThreeByte) { |
971 | 0 | proto_tree_add_item(ack_tree, hf_isobus_ack_exended_identifier, tvb, 1, 3, ENC_LITTLE_ENDIAN); |
972 | 0 | } |
973 | 0 | proto_tree_add_item_ret_uint(ack_tree, hf_isobus_ack_address, tvb, 4, 1, ENC_LITTLE_ENDIAN, &reserved); |
974 | 0 | proto_tree_add_item(ack_tree, hf_isobus_ack_pgn, tvb, 5, 3, ENC_LITTLE_ENDIAN); |
975 | 0 | } else { |
976 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Protocol not yet supported"); |
977 | 0 | proto_tree_add_item(isobus_tree, hf_isobus_payload, tvb, 0, tvb_captured_length(tvb), ENC_NA); |
978 | 0 | } |
979 | 0 | } |
980 | | |
981 | 0 | return tvb_reported_length(tvb); |
982 | 0 | } |
983 | | |
984 | | static void isobus_print_datetime_year(char* s, uint32_t v) |
985 | 0 | { |
986 | 0 | snprintf(s, ITEM_LABEL_LENGTH, "%u", v + 1985); |
987 | 0 | } |
988 | | |
989 | | static void isobus_print_datetime_day_or_sec(char* s, uint32_t v) |
990 | 0 | { |
991 | 0 | snprintf(s, ITEM_LABEL_LENGTH, "%u", (uint8_t)(v * 0.25f)); |
992 | 0 | } |
993 | | |
994 | | static void isobus_print_datetime_utc_offset(char* s, uint32_t v) |
995 | 0 | { |
996 | 0 | snprintf(s, ITEM_LABEL_LENGTH, "%d hour", (int8_t)(((v >> 8) & 0xFF) - 125)); |
997 | 0 | int8_t minutes = ((v & 0xFF) - 125); |
998 | 0 | if (minutes != 0) |
999 | 0 | { |
1000 | 0 | size_t current_len = strlen(s); |
1001 | 0 | snprintf(&s[current_len], ITEM_LABEL_LENGTH - current_len, " %d minute(s)", minutes); |
1002 | 0 | } |
1003 | 0 | } |
1004 | | |
1005 | | static void |
1006 | 16 | isobus_init(void) { |
1007 | 16 | reassembly_table_init(&isobus_reassembly_table, &addresses_reassembly_table_functions); |
1008 | 16 | } |
1009 | | |
1010 | | static void |
1011 | 0 | isobus_cleanup(void) { |
1012 | 0 | reassembly_table_destroy(&isobus_reassembly_table); |
1013 | 0 | } |
1014 | | |
1015 | | /* Register the protocol with Wireshark */ |
1016 | | void |
1017 | 16 | proto_register_isobus(void) { |
1018 | 16 | static hf_register_info hf[] = { |
1019 | 16 | { &hf_isobus_can_id, { |
1020 | 16 | "CAN-ID", "isobus.can_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
1021 | 16 | { &hf_isobus_priority, { |
1022 | 16 | "Priority", "isobus.priority", FT_UINT32, BASE_HEX, NULL, 0x1C000000, NULL, HFILL } }, |
1023 | 16 | { &hf_isobus_ext_data_page, { |
1024 | 16 | "Ext data page", "isobus.edp", FT_UINT32, BASE_HEX, NULL, 0x02000000, NULL, HFILL } }, |
1025 | 16 | { &hf_isobus_data_page, { |
1026 | 16 | "Data page", "isobus.datapage", FT_UINT32, BASE_HEX, NULL, 0x01000000, NULL, HFILL } }, |
1027 | 16 | { &hf_isobus_pdu_format_dp0, { |
1028 | 16 | "PDU Format", "isobus.pdu_format", FT_UINT32, BASE_DEC, VALS(pdu_format_dp0), 0xff0000, NULL, HFILL } }, |
1029 | 16 | { &hf_isobus_pdu_format_dp1, { |
1030 | 16 | "PDU Format", "isobus.pdu_format", FT_UINT32, BASE_DEC, VALS(pdu_format_dp1), 0xff0000, NULL, HFILL } }, |
1031 | 16 | { &hf_isobus_group_extension, { |
1032 | 16 | "Group Extension", "isobus.grp_ext", FT_UINT32, BASE_DEC, NULL, 0xff00, NULL, HFILL } }, |
1033 | 16 | { &hf_isobus_dst_addr, { |
1034 | 16 | "Destination Address", "isobus.dst_addr", FT_UINT32, BASE_DEC | BASE_RANGE_STRING, RVALS(address_range), 0xff00, NULL, HFILL } }, |
1035 | 16 | { &hf_isobus_src_addr, { |
1036 | 16 | "Source Address", "isobus.src_addr", FT_UINT32, BASE_DEC | BASE_RANGE_STRING, RVALS(address_range), 0xff, NULL, HFILL } }, |
1037 | 16 | { &hf_isobus_pgn, { |
1038 | 16 | "PGN", "isobus.pgn", FT_UINT24, BASE_DEC_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1039 | 16 | { &hf_isobus_payload, { |
1040 | 16 | "Payload", "isobus.payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1041 | | |
1042 | 16 | { &hf_isobus_datetime_response, { |
1043 | 16 | "Date/Time", "isobus.datetime_response", FT_PROTOCOL, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1044 | 16 | { &hf_isobus_datetime_year, { |
1045 | 16 | "Year", "isobus.datetime.year", FT_UINT8, BASE_CUSTOM, CF_FUNC(isobus_print_datetime_year), 0x0, NULL, HFILL } }, |
1046 | 16 | { &hf_isobus_datetime_month, { |
1047 | 16 | "Month", "isobus.datetime.month", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1048 | 16 | { &hf_isobus_datetime_day, { |
1049 | 16 | "Day", "isobus.datetime.day", FT_UINT8, BASE_CUSTOM, CF_FUNC(isobus_print_datetime_day_or_sec), 0x0, NULL, HFILL } }, |
1050 | 16 | { &hf_isobus_datetime_hour, { |
1051 | 16 | "Hour", "isobus.datetime.hour", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1052 | 16 | { &hf_isobus_datetime_minute, { |
1053 | 16 | "Minute", "isobus.datetime.minute", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1054 | 16 | { &hf_isobus_datetime_seconds, { |
1055 | 16 | "Second", "isobus.datetime.second", FT_UINT8, BASE_CUSTOM, CF_FUNC(isobus_print_datetime_day_or_sec), 0x0, NULL, HFILL } }, |
1056 | 16 | { &hf_isobus_datetime_utc_offset, { |
1057 | 16 | "Local time - UTC offset", "isobus.datetime.utc_offset", FT_UINT16, BASE_CUSTOM, CF_FUNC(isobus_print_datetime_utc_offset), 0x0, NULL, HFILL } }, |
1058 | | |
1059 | 16 | { &hf_isobus_ack_response, {"ACK", "isobus.ack_response", FT_PROTOCOL, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1060 | 16 | { &hf_isobus_ack_control_byte, {"Control byte", "isobus.ack_response.control_byte", FT_UINT8, BASE_DEC, VALS(acknowledgement_control_byte), 0x0, NULL, HFILL } }, |
1061 | 16 | { &hf_isobus_ack_reserved, {"Reserved", "isobus.ack_response.reserved", FT_UINT24, BASE_DEC, VALS(acknowledgement_control_byte), 0x0, NULL, HFILL } }, |
1062 | 16 | { &hf_isobus_ack_address, {"Address", "isobus.ack_response.address", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1063 | 16 | { &hf_isobus_ack_group_function_value, { |
1064 | 16 | "Group function value", "isobus.ack_response.group_function_value", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1065 | 16 | { &hf_isobus_ack_exended_identifier, { |
1066 | 16 | "Extended identifier", "isobus.ack_response.extended_identifier", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1067 | 16 | { &hf_isobus_ack_pgn, { |
1068 | 16 | "PGN", "isobus.pgn", FT_UINT24, BASE_DEC_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1069 | | |
1070 | 16 | { &hf_isobus_req_requested_pgn, { |
1071 | 16 | "Requested PGN", "isobus.req.requested_pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1072 | | |
1073 | 16 | { &hf_isobus_ac_name, { |
1074 | 16 | "Name", "isobus.ac.name", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1075 | 16 | { &hf_isobus_ac_name_id_number, { |
1076 | 16 | "Identity Number", "isobus.ac.name.identity_number", FT_UINT64, BASE_DEC, NULL, 0x00000000001fffff, NULL, HFILL } }, |
1077 | 16 | { &hf_isobus_ac_name_manufacturer, { |
1078 | 16 | "Manufacturer", "isobus.ac.name.manufacturer", FT_UINT64, BASE_DEC, NULL, 0x00000000ffe00000, NULL, HFILL } }, |
1079 | 16 | { &hf_isobus_ac_name_function_instance, { |
1080 | 16 | "Function Instance", "isobus.ac.name.function_instance", FT_UINT64, BASE_DEC, NULL, 0x000000f800000000, NULL, HFILL } }, |
1081 | 16 | { &hf_isobus_ac_name_ecu_instance, { |
1082 | 16 | "ECU Instance", "isobus.ac.name.ecu_instance", FT_UINT64, BASE_DEC, NULL, 0x0000000700000000, NULL, HFILL } }, |
1083 | 16 | { &hf_isobus_ac_name_function, { |
1084 | 16 | "Function", "isobus.ac.name.function", FT_UINT64, BASE_DEC, NULL, 0x0000ff0000000000, NULL, HFILL } }, |
1085 | 16 | { &hf_isobus_ac_name_reserved, { |
1086 | 16 | "Reserved", "isobus.ac.name.reserved", FT_UINT64, BASE_HEX, NULL, 0x0001000000000000, NULL, HFILL } }, |
1087 | 16 | { &hf_isobus_ac_name_vehicle_system, |
1088 | 16 | { "Vehicle System", "isobus.ac.name.vehicle_system", FT_UINT64, BASE_DEC, NULL, 0x00fe000000000000, NULL, HFILL } }, |
1089 | 16 | { &hf_isobus_ac_name_vehicle_system_instance, { |
1090 | 16 | "System Instance", "isobus.ac.name.system_instance", FT_UINT64, BASE_DEC, NULL, 0x0f00000000000000, NULL, HFILL } }, |
1091 | 16 | { &hf_isobus_ac_name_industry_group, { |
1092 | 16 | "Industry Group", "isobus.ac.name.industry_group", FT_UINT64, BASE_DEC, NULL, 0x7000000000000000, NULL, HFILL } }, |
1093 | 16 | { &hf_isobus_ac_name_arbitrary_address_capable, { |
1094 | 16 | "Arbitrary Address Capable", "isobus.ac.name.arbitrary_address_capable", FT_UINT64, BASE_DEC, NULL, 0x8000000000000000, NULL, HFILL } }, |
1095 | | |
1096 | 16 | { &hf_isobus_transportprotocol_controlbyte, { |
1097 | 16 | "Control Byte", "isobus.transport_protocol.control_byte", FT_UINT8, BASE_DEC, VALS(transport_protocol_control_byte), 0x0, NULL, HFILL } }, |
1098 | 16 | { &hf_isobus_transportprotocol_requesttosend_totalsize, { |
1099 | 16 | "Total message size", "isobus.transport_protocol.request_to_send.total_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1100 | 16 | { &hf_isobus_transportprotocol_requesttosend_numberofpackets, { |
1101 | 16 | "Number of Packets", "isobus.transport_protocol.request_to_send.number_of_packets", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1102 | 16 | { &hf_isobus_transportprotocol_requesttosend_maximumpackets, { |
1103 | 16 | "Maximum Packets", "isobus.transport_protocol.request_to_send.maximum_packets", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1104 | 16 | { &hf_isobus_transportprotocol_requesttosend_pgn, { |
1105 | 16 | "PGN", "isobus.transport_protocol.request_to_send.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1106 | 16 | { &hf_isobus_transportprotocol_cleartosend_numberofpacketscanbesent, { |
1107 | 16 | "Number of packets that can be sent", "isobus.transport_protocol.request_to_send.number_of_packets_that_can_be_sent", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1108 | 16 | { &hf_isobus_transportprotocol_cleartosend_nextpacketnumber, { |
1109 | 16 | "Next packet number", "isobus.transport_protocol.request_to_send.next_packet_number", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1110 | 16 | { &hf_isobus_transportprotocol_cleartosend_pgn, { |
1111 | 16 | "PGN", "isobus.transport_protocol.clear_to_send.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1112 | 16 | { &hf_isobus_transportprotocol_endofmsgack_totalsize, { |
1113 | 16 | "Total Size", "isobus.transport_protocol.end_of_message_acknowledgement.total_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1114 | 16 | { &hf_isobus_transportprotocol_endofmsgack_numberofpackets, { |
1115 | 16 | "Number of Packets", "isobus.transport_protocol.end_of_message_acknowledgement.number_of_packets", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1116 | 16 | { &hf_isobus_transportprotocol_endofmsgack_pgn, { |
1117 | 16 | "PGN", "isobus.transport_protocol.end_of_message_acknowledgement.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1118 | 16 | { &hf_isobus_transportprotocol_connabort_abortreason, { |
1119 | 16 | "Connection Abort reason", "isobus.transport_protocol.connection_abort.abort_reason", FT_UINT8, BASE_DEC | BASE_RANGE_STRING, RVALS(connection_abort_reasons), 0x0, NULL, HFILL } }, |
1120 | 16 | { &hf_isobus_transportprotocol_connabort_pgn, { |
1121 | 16 | "PGN", "isobus.transport_protocol.connection_abort.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1122 | 16 | { &hf_isobus_transportprotocol_broadcastannouncemessage_totalsize, { |
1123 | 16 | "Total Message Size", "isobus.transport_protocol.broadcast_announce_message.total_message_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1124 | 16 | { &hf_isobus_transportprotocol_broadcastannouncemessage_numberofpackets, { |
1125 | 16 | "Total Number of Packets", "isobus.transport_protocol.broadcast_announce_message.total_number_of_packets", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1126 | 16 | { &hf_isobus_transportprotocol_broadcastannouncemessage_pgn, { |
1127 | 16 | "PGN", "isobus.transport_protocol.broadcast_announce_message.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1128 | 16 | { &hf_isobus_transportprotocol_reserved, { |
1129 | 16 | "Reserved", "isobus.transport_protocol.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1130 | 16 | { &hf_isobus_transportprotocol_sequence_number, { |
1131 | 16 | "Sequence Number", "isobus.transport_protocol.data_transfer.sequence_number", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1132 | 16 | { &hf_isobus_transportprotocol_data, { |
1133 | 16 | "Data", "isobus.transport_protocol.data_transfer.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1134 | | |
1135 | 16 | { &hf_isobus_extendedtransportprotocol_controlbyte, { |
1136 | 16 | "Control Byte", "isobus.extended_transport_protocol.control_byte", FT_UINT8, BASE_DEC, VALS(extended_transport_protocol_control_byte), 0x0, NULL, HFILL } }, |
1137 | 16 | { &hf_isobus_extendedtransportprotocol_requesttosend_totalsize, { |
1138 | 16 | "Total Message Size", "isobus.extended_transport_protocol.request_to_send.total_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1139 | 16 | { &hf_isobus_extendedtransportprotocol_requesttosend_pgn, { |
1140 | 16 | "PGN", "isobus.extended_transport_protocol.request_to_send.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1141 | 16 | { &hf_isobus_extendedtransportprotocol_cleartosend_numberofpackets, { |
1142 | 16 | "Number of packets that can be sent", "isobus.extended_transport_protocol.clear_to_send.number_of_packets_that_can_be_sent", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1143 | 16 | { &hf_isobus_extendedtransportprotocol_cleartosend_nextpacketnumber, { |
1144 | 16 | "Next Packet Number", "isobus.extended_transport_protocol.clear_to_send.next_packet_number", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1145 | 16 | { &hf_isobus_extendedtransportprotocol_cleartosend_pgn, { |
1146 | 16 | "PGN", "isobus.extended_transport_protocol.clear_to_send.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1147 | 16 | { &hf_isobus_extendedtransportprotocol_datapacketoffset_numberofpackets, { |
1148 | 16 | "Number of Packets", "isobus.extended_transport_protocol.data_packet_offset.number_of_packets", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1149 | 16 | { &hf_isobus_extendedtransportprotocol_datapacketoffset_packetoffset, { |
1150 | 16 | "Packet Offset", "isobus.extended_transport_protocol.data_packet_offset.packet_offset", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1151 | 16 | { &hf_isobus_extendedtransportprotocol_datapacketoffset_pgn, { |
1152 | 16 | "PGN", "isobus.extended_transport_protocol.data_packet_offset.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1153 | 16 | { &hf_isobus_extendedtransportprotocol_endofmsgack_totalsize, { |
1154 | 16 | "Total Message Size", "isobus.extended_transport_protocol.end_of_message_acknowledgement.total_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1155 | 16 | { &hf_isobus_extendedtransportprotocol_endofmsgack_pgn, { |
1156 | 16 | "PGN", "isobus.extended_transport_protocol.end_of_message_acknowledgement.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1157 | 16 | { &hf_isobus_extendedtransportprotocol_connabort_abortreason, { |
1158 | 16 | "Connection Abort Reason", "isobus.extended_transport_protocol.connection_abort.abort_reason", FT_UINT8, BASE_DEC | BASE_RANGE_STRING, RVALS(extended_connection_abort_reasons), 0x0, NULL, HFILL } }, |
1159 | 16 | { &hf_isobus_extendedtransportprotocol_connabort_pgn, { |
1160 | 16 | "PGN", "isobus.extended_transport_protocol.connection_abort.pgn", FT_UINT24, BASE_HEX | BASE_EXT_STRING, &isobus_pgn_names_ext, 0x0, NULL, HFILL } }, |
1161 | 16 | { &hf_isobus_extendedtransportprotocol_reserved, { |
1162 | 16 | "Reserved", "isobus.extended_transport_protocol.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1163 | 16 | { &hf_isobus_extendedtransportprotocol_sequence_number, { |
1164 | 16 | "Sequence Number", "isobus.extended_transport_protocol.data_transfer.sequence_number", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, |
1165 | 16 | { &hf_isobus_extendedtransportprotocol_data, { |
1166 | 16 | "Data", "isobus.extended_transport_protocol.data_transfer.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, |
1167 | | |
1168 | 16 | { &hf_msg_fragments, { |
1169 | 16 | "Message fragments", "isobus.fragments", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1170 | 16 | { &hf_msg_fragment, { |
1171 | 16 | "Message fragment", "isobus.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1172 | 16 | { &hf_msg_fragment_overlap, { |
1173 | 16 | "Message fragment overlap", "isobus.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1174 | 16 | { &hf_msg_fragment_overlap_conflicts, { |
1175 | 16 | "Message fragment overlapping with conflicting data", "isobus.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1176 | 16 | { &hf_msg_fragment_multiple_tails, { |
1177 | 16 | "Message has multiple tail fragments", "isobus.fragment.multiple_tails", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1178 | 16 | { &hf_msg_fragment_too_long_fragment, { |
1179 | 16 | "Message fragment too long", "isobus.fragment.too_long_fragment", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1180 | 16 | { &hf_msg_fragment_error, { |
1181 | 16 | "Message defragmentation error", "isobus.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1182 | 16 | { &hf_msg_fragment_count, { |
1183 | 16 | "Message fragment count", "isobus.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }, |
1184 | 16 | { &hf_msg_reassembled_in, { |
1185 | 16 | "Reassembled in", "isobus.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1186 | 16 | { &hf_msg_reassembled_length, { |
1187 | 16 | "Reassembled length", "isobus.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }, |
1188 | 16 | { &hf_msg_reassembled_data, { |
1189 | 16 | "Reassembled data", "isobus.reassembled.data", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL } } |
1190 | 16 | }; |
1191 | | |
1192 | 16 | static int *ett[] = { |
1193 | 16 | &ett_isobus, |
1194 | 16 | &ett_isobus_can_id, |
1195 | 16 | &ett_isobus_name, |
1196 | 16 | &ett_isobus_fragment, |
1197 | 16 | &ett_isobus_fragments, |
1198 | 16 | &ett_isobus_datetime_response, |
1199 | 16 | &ett_isobus_ack_response |
1200 | 16 | }; |
1201 | | |
1202 | | /* Register protocol init routine */ |
1203 | 16 | register_init_routine(&isobus_init); |
1204 | 16 | register_cleanup_routine(&isobus_cleanup); |
1205 | | |
1206 | 16 | proto_isobus = proto_register_protocol("ISObus", "ISOBUS", "isobus"); |
1207 | | |
1208 | 16 | proto_register_field_array(proto_isobus, hf, array_length(hf)); |
1209 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
1210 | | |
1211 | | /* Register expert info fields */ |
1212 | 16 | expert_module_t *expert_isobus = expert_register_protocol(proto_isobus); |
1213 | 16 | static ei_register_info ei[] = { |
1214 | 16 | { &ei_isobus_ack_msg_reserved, { "isobus.ack_msg_reserved", PI_UNDECODED, PI_WARN, "Reserved field not zero", EXPFILL }} |
1215 | 16 | }; |
1216 | 16 | expert_register_field_array(expert_isobus, ei, array_length(ei)); |
1217 | | |
1218 | | |
1219 | 16 | addressIdentifierTable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), address_combination_hash, address_combination_equal); |
1220 | | |
1221 | 16 | subdissector_table_pdu_format = register_dissector_table("isobus.pdu_format", "PDU format", proto_isobus, FT_UINT8, BASE_DEC); |
1222 | 16 | subdissector_table_pgn = register_dissector_table("isobus.pgn", "PGN", proto_isobus, FT_UINT32, BASE_DEC); |
1223 | | |
1224 | 16 | isobus_handle = register_dissector("isobus", dissect_isobus, proto_isobus ); |
1225 | 16 | } |
1226 | | |
1227 | | void |
1228 | 16 | proto_reg_handoff_isobus(void) { |
1229 | 16 | dissector_add_for_decode_as("can.subdissector", isobus_handle ); |
1230 | 16 | } |
1231 | | |
1232 | | /* |
1233 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1234 | | * |
1235 | | * Local variables: |
1236 | | * c-basic-offset: 4 |
1237 | | * tab-width: 8 |
1238 | | * indent-tabs-mode: nil |
1239 | | * End: |
1240 | | * |
1241 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
1242 | | * :indentSize=4:tabSize=8:noTabs=true: |
1243 | | */ |