Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
 */