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-socketcan.c
Line
Count
Source
1
/* packet-socketcan.c
2
 * Routines for disassembly of packets from SocketCAN
3
 * Felix Obenhuber <felix@obenhuber.de>
4
 *
5
 * Added support for the DeviceNet Dissector
6
 * Hans-Joergen Gunnarsson <hag@hms.se>
7
 * Copyright 2013
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
16
#include "config.h"
17
18
#include <epan/packet.h>
19
#include <epan/prefs.h>
20
#include <epan/expert.h>
21
#include <epan/decode_as.h>
22
#include <epan/uat.h>
23
#include <wiretap/wtap.h>
24
25
#include "packet-sll.h"
26
#include "packet-socketcan.h"
27
28
void proto_register_socketcan(void);
29
void proto_reg_handoff_socketcan(void);
30
31
static int hf_can_len;
32
static int hf_can_bus_id;
33
static int hf_can_infoent_ext;
34
static int hf_can_infoent_std;
35
static int hf_can_extflag;
36
static int hf_can_rtrflag;
37
static int hf_can_errflag;
38
static int hf_can_reserved;
39
static int hf_can_len8dlc;
40
static int hf_can_padding;
41
42
static int hf_can_err_tx_timeout;
43
static int hf_can_err_lostarb;
44
static int hf_can_err_ctrl;
45
static int hf_can_err_prot;
46
static int hf_can_err_trx;
47
static int hf_can_err_ack;
48
static int hf_can_err_busoff;
49
static int hf_can_err_buserror;
50
static int hf_can_err_restarted;
51
static int hf_can_err_reserved;
52
53
static int hf_can_err_lostarb_bit_number;
54
55
static int hf_can_err_ctrl_rx_overflow;
56
static int hf_can_err_ctrl_tx_overflow;
57
static int hf_can_err_ctrl_rx_warning;
58
static int hf_can_err_ctrl_tx_warning;
59
static int hf_can_err_ctrl_rx_passive;
60
static int hf_can_err_ctrl_tx_passive;
61
static int hf_can_err_ctrl_active;
62
63
static int hf_can_err_prot_error_type_bit;
64
static int hf_can_err_prot_error_type_form;
65
static int hf_can_err_prot_error_type_stuff;
66
static int hf_can_err_prot_error_type_bit0;
67
static int hf_can_err_prot_error_type_bit1;
68
static int hf_can_err_prot_error_type_overload;
69
static int hf_can_err_prot_error_type_active;
70
static int hf_can_err_prot_error_type_tx;
71
72
static int hf_can_err_prot_error_location;
73
74
static int hf_can_err_trx_canh;
75
static int hf_can_err_trx_canl;
76
77
static int hf_can_err_ctrl_specific;
78
79
static int hf_canxl_priority;
80
static int hf_canxl_vcid;
81
static int hf_canxl_secflag;
82
static int hf_canxl_rrsflag;
83
static int hf_canxl_xlflag;
84
static int hf_canxl_sdu_type;
85
static int hf_canxl_len;
86
static int hf_canxl_acceptance_field;
87
88
static expert_field ei_can_err_dlc_mismatch;
89
90
static int hf_canfd_brsflag;
91
static int hf_canfd_esiflag;
92
static int hf_canfd_fdflag;
93
94
static int ett_can;
95
static int ett_can_fd;
96
static int ett_can_xl;
97
98
static int proto_can;
99
static int proto_canfd;
100
static int proto_canxl;
101
102
static bool byte_swap;
103
static bool heuristic_first;
104
105
static heur_dissector_list_t heur_subdissector_list;
106
static heur_dtbl_entry_t *heur_dtbl_entry;
107
108
1
#define LINUX_CAN_STD   0
109
0
#define LINUX_CAN_EXT   1
110
11
#define LINUX_CAN_ERR   2
111
112
11
#define CAN_LEN_OFFSET     4
113
14
#define CAN_DATA_OFFSET    8
114
115
12
#define CANFD_FLAG_OFFSET  5
116
117
6
#define CANXL_FLAGS_OFFSET CAN_LEN_OFFSET
118
2
#define CANXL_LEN_OFFSET   6
119
2
#define CANXL_DATA_OFFSET  12
120
121
static dissector_table_t can_id_dissector_table;
122
static dissector_table_t can_extended_id_dissector_table;
123
static dissector_table_t subdissector_table;
124
static dissector_table_t canxl_sdu_type_dissector_table;
125
static dissector_handle_t socketcan_classic_handle;
126
static dissector_handle_t socketcan_fd_handle;
127
static dissector_handle_t socketcan_xl_handle;
128
static dissector_handle_t socketcan_bigendian_handle;
129
130
131
static const value_string can_err_prot_error_location_vals[] = {
132
    { 0x00, "unspecified" },
133
    { 0x02, "ID bits 28 - 21 (SFF: 10 - 3)" },
134
    { 0x03, "start of frame" },
135
    { 0x04, "substitute RTR (SFF: RTR)" },
136
    { 0x05, "identifier extension" },
137
    { 0x06, "ID bits 20 - 18 (SFF: 2 - 0)" },
138
    { 0x07, "ID bits 17-13" },
139
    { 0x08, "CRC sequence" },
140
    { 0x09, "reserved bit 0" },
141
    { 0x0A, "data section" },
142
    { 0x0B, "data length code" },
143
    { 0x0C, "RTR" },
144
    { 0x0D, "reserved bit 1" },
145
    { 0x0E, "ID bits 4-0" },
146
    { 0x0F, "ID bits 12-5" },
147
    { 0x12, "intermission" },
148
    { 0x18, "CRC delimiter" },
149
    { 0x19, "ACK slot" },
150
    { 0x1A, "end of frame" },
151
    { 0x1B, "ACK delimiter" },
152
    { 0, NULL }
153
};
154
155
static const value_string can_err_trx_canh_vals[] = {
156
    { 0x00, "unspecified" },
157
    { 0x04, "no wire" },
158
    { 0x05, "short to BAT" },
159
    { 0x06, "short to VCC" },
160
    { 0x07, "short to GND" },
161
    { 0, NULL }
162
};
163
164
static const value_string can_err_trx_canl_vals[] = {
165
    { 0x00, "unspecified" },
166
    { 0x04, "no wire" },
167
    { 0x05, "short to BAT" },
168
    { 0x06, "short to VCC" },
169
    { 0x07, "short to GND" },
170
    { 0x08, "short to CANH" },
171
    { 0, NULL }
172
};
173
174
/********* UATs *********/
175
176
/* Interface Config UAT */
177
typedef struct _interface_config {
178
    unsigned   interface_id;
179
    char   *interface_name;
180
    unsigned   bus_id;
181
} interface_config_t;
182
183
16
#define DATAFILE_CAN_INTERFACE_MAPPING "CAN_interface_mapping"
184
185
static GHashTable *data_can_interfaces_by_id;
186
static GHashTable *data_can_interfaces_by_name;
187
static interface_config_t *interface_configs;
188
static unsigned interface_config_num;
189
190
0
UAT_HEX_CB_DEF(interface_configs, interface_id, interface_config_t)
Unexecuted instantiation: packet-socketcan.c:interface_configs_interface_id_set_cb
Unexecuted instantiation: packet-socketcan.c:interface_configs_interface_id_tostr_cb
191
0
UAT_CSTRING_CB_DEF(interface_configs, interface_name, interface_config_t)
192
0
UAT_HEX_CB_DEF(interface_configs, bus_id, interface_config_t)
Unexecuted instantiation: packet-socketcan.c:interface_configs_bus_id_set_cb
Unexecuted instantiation: packet-socketcan.c:interface_configs_bus_id_tostr_cb
193
194
static void *
195
0
copy_interface_config_cb(void *n, const void *o, size_t size _U_) {
196
0
    interface_config_t *new_rec = (interface_config_t *)n;
197
0
    const interface_config_t *old_rec = (const interface_config_t *)o;
198
199
0
    new_rec->interface_id = old_rec->interface_id;
200
0
    new_rec->interface_name = g_strdup(old_rec->interface_name);
201
0
    new_rec->bus_id = old_rec->bus_id;
202
0
    return new_rec;
203
0
}
204
205
static bool
206
0
update_interface_config(void *r, char **err) {
207
0
    interface_config_t *rec = (interface_config_t *)r;
208
209
0
    if (rec->interface_id > 0xffffffff) {
210
0
        *err = ws_strdup_printf("We currently only support 32 bit identifiers (ID: %i  Name: %s)",
211
0
                                rec->interface_id, rec->interface_name);
212
0
        return false;
213
0
    }
214
215
0
    if (rec->bus_id > 0xffff) {
216
0
        *err = ws_strdup_printf("We currently only support 16 bit bus identifiers (ID: %i  Name: %s  Bus-ID: %i)",
217
0
                                rec->interface_id, rec->interface_name, rec->bus_id);
218
0
        return false;
219
0
    }
220
221
0
    return true;
222
0
}
223
224
static void
225
0
free_interface_config_cb(void *r) {
226
0
    interface_config_t *rec = (interface_config_t *)r;
227
228
    /* freeing result of g_strdup */
229
0
    g_free(rec->interface_name);
230
0
    rec->interface_name = NULL;
231
0
}
232
233
static void
234
16
post_update_can_interfaces_cb(void) {
235
16
    unsigned  i;
236
237
    /* destroy old hash tables, if they exist */
238
16
    if (data_can_interfaces_by_id) {
239
0
        g_hash_table_destroy(data_can_interfaces_by_id);
240
0
    }
241
16
    if (data_can_interfaces_by_name) {
242
0
        g_hash_table_destroy(data_can_interfaces_by_name);
243
0
    }
244
245
    /* create new hash table */
246
16
    data_can_interfaces_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
247
16
    data_can_interfaces_by_name = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
248
249
16
    for (i = 0; i < interface_config_num; i++) {
250
0
        if (interface_configs[i].interface_id != 0xfffffff) {
251
0
            g_hash_table_insert(data_can_interfaces_by_id, GUINT_TO_POINTER(interface_configs[i].interface_id), &interface_configs[i]);
252
0
        }
253
254
0
        if (interface_configs[i].interface_name != NULL && interface_configs[i].interface_name[0] != 0) {
255
0
            g_hash_table_insert(data_can_interfaces_by_name, interface_configs[i].interface_name, &interface_configs[i]);
256
0
        }
257
0
    }
258
16
}
259
260
static void
261
0
reset_can_interfaces_cb(void) {
262
0
    if (data_can_interfaces_by_id) {
263
0
        g_hash_table_destroy(data_can_interfaces_by_id);
264
0
        data_can_interfaces_by_id = NULL;
265
0
    }
266
267
0
    if (data_can_interfaces_by_name) {
268
0
        g_hash_table_destroy(data_can_interfaces_by_name);
269
0
        data_can_interfaces_by_name = NULL;
270
0
    }
271
0
}
272
273
/* We match based on the config in the following order:
274
 * - interface_name matches and interface_id matches
275
 * - interface_name matches and interface_id = 0xffffffff
276
 * - interface_name = ""    and interface_id matches
277
 */
278
static unsigned
279
0
get_bus_id_common(const char* interface_name, uint32_t interface_id) {
280
0
    if (interface_name != NULL && interface_name[0] != 0) {
281
0
        interface_config_t* tmp = NULL;
282
283
0
        if (data_can_interfaces_by_name != NULL) {
284
0
            tmp = g_hash_table_lookup(data_can_interfaces_by_name, interface_name);
285
286
0
            if (tmp != NULL && (tmp->interface_id == 0xffffffff || tmp->interface_id == interface_id)) {
287
                /* name + id match or name match and id = any */
288
0
                return tmp->bus_id;
289
0
            }
290
0
        }
291
292
0
        if (data_can_interfaces_by_id != NULL) {
293
0
            tmp = g_hash_table_lookup(data_can_interfaces_by_id, GUINT_TO_POINTER(interface_id));
294
295
0
            if (tmp != NULL && (tmp->interface_name == NULL || tmp->interface_name[0] == 0)) {
296
                /* id matches and name is any */
297
0
                return tmp->bus_id;
298
0
            }
299
0
        }
300
0
    }
301
302
    /* we found nothing */
303
0
    return 0;
304
0
}
305
306
static unsigned
307
4
get_bus_id(packet_info *pinfo) {
308
4
    if (!(pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)) {
309
4
        return 0;
310
4
    }
311
312
0
    uint32_t    interface_id = pinfo->rec->rec_header.packet_header.interface_id;
313
0
    unsigned    section_number = pinfo->rec->presence_flags & WTAP_HAS_SECTION_NUMBER ? pinfo->rec->section_number : 0;
314
0
    const char* interface_name = epan_get_interface_name(pinfo->epan, interface_id, section_number);
315
316
0
    return get_bus_id_common(interface_name, interface_id);
317
4
}
318
319
unsigned
320
0
can_get_bus_id_from_interface_name(const char* interface_name) {
321
0
    return get_bus_id_common(interface_name, 0xffffffff);
322
0
}
323
324
/* Senders and Receivers UAT */
325
typedef struct _sender_receiver_config {
326
    unsigned   bus_id;
327
    unsigned   can_id;
328
    char   *sender_name;
329
    char   *receiver_name;
330
} sender_receiver_config_t;
331
332
16
#define DATAFILE_CAN_SENDER_RECEIVER "CAN_senders_receivers"
333
334
static GHashTable *data_sender_receiver;
335
static sender_receiver_config_t *sender_receiver_configs;
336
static unsigned sender_receiver_config_num;
337
338
0
UAT_HEX_CB_DEF(sender_receiver_configs, bus_id, sender_receiver_config_t)
Unexecuted instantiation: packet-socketcan.c:sender_receiver_configs_bus_id_set_cb
Unexecuted instantiation: packet-socketcan.c:sender_receiver_configs_bus_id_tostr_cb
339
0
UAT_HEX_CB_DEF(sender_receiver_configs, can_id, sender_receiver_config_t)
Unexecuted instantiation: packet-socketcan.c:sender_receiver_configs_can_id_set_cb
Unexecuted instantiation: packet-socketcan.c:sender_receiver_configs_can_id_tostr_cb
340
0
UAT_CSTRING_CB_DEF(sender_receiver_configs, sender_name, sender_receiver_config_t)
341
0
UAT_CSTRING_CB_DEF(sender_receiver_configs, receiver_name, sender_receiver_config_t)
342
343
static void *
344
0
copy_sender_receiver_config_cb(void *n, const void *o, size_t size _U_) {
345
0
    sender_receiver_config_t *new_rec = (sender_receiver_config_t *)n;
346
0
    const sender_receiver_config_t *old_rec = (const sender_receiver_config_t *)o;
347
348
0
    new_rec->bus_id = old_rec->bus_id;
349
0
    new_rec->can_id = old_rec->can_id;
350
0
    new_rec->sender_name = g_strdup(old_rec->sender_name);
351
0
    new_rec->receiver_name = g_strdup(old_rec->receiver_name);
352
0
    return new_rec;
353
0
}
354
355
static bool
356
0
update_sender_receiver_config(void *r, char **err) {
357
0
    sender_receiver_config_t *rec = (sender_receiver_config_t *)r;
358
359
0
    if (rec->bus_id > 0xffff) {
360
0
        *err = ws_strdup_printf("We currently only support 16 bit bus identifiers (Bus ID: %i  CAN ID: %i)", rec->bus_id, rec->can_id);
361
0
        return false;
362
0
    }
363
364
0
    return true;
365
0
}
366
367
static void
368
0
free_sender_receiver_config_cb(void *r) {
369
0
    sender_receiver_config_t *rec = (sender_receiver_config_t *)r;
370
371
    /* freeing result of g_strdup */
372
0
    g_free(rec->sender_name);
373
0
    rec->sender_name = NULL;
374
0
    g_free(rec->receiver_name);
375
0
    rec->receiver_name = NULL;
376
0
}
377
378
static uint64_t
379
56
sender_receiver_key(uint16_t bus_id, uint32_t can_id) {
380
56
    return ((uint64_t)bus_id << 32) | can_id;
381
56
}
382
383
static sender_receiver_config_t *
384
28
ht_lookup_sender_receiver_config(uint16_t bus_id, uint32_t can_id) {
385
28
    uint64_t key;
386
28
    sender_receiver_config_t* tmp;
387
388
28
    if (data_sender_receiver == NULL) {
389
0
        return NULL;
390
0
    }
391
392
28
    key = sender_receiver_key(bus_id, can_id);
393
28
    tmp = g_hash_table_lookup(data_sender_receiver, &key);
394
395
28
    if (tmp == NULL) {
396
28
        key = sender_receiver_key(0, can_id);
397
28
        tmp = g_hash_table_lookup(data_sender_receiver, &key);
398
28
    }
399
400
28
    return tmp;
401
28
}
402
403
static void
404
16
post_update_sender_receiver_cb(void) {
405
16
    unsigned i;
406
16
    uint64_t *key;
407
408
    /* destroy old hash table, if it exist */
409
16
    if (data_sender_receiver) {
410
0
        g_hash_table_destroy(data_sender_receiver);
411
0
    }
412
413
    /* create new hash table */
414
16
    data_sender_receiver = g_hash_table_new_full(g_int64_hash, g_int64_equal, g_free, NULL);
415
416
16
    for (i = 0; i < sender_receiver_config_num; i++) {
417
0
        key = g_new(uint64_t, 1);
418
0
        *key = sender_receiver_key(sender_receiver_configs[i].bus_id, sender_receiver_configs[i].can_id);
419
0
        g_hash_table_insert(data_sender_receiver, key, &sender_receiver_configs[i]);
420
0
    }
421
16
}
422
423
static void
424
0
reset_sender_receiver_cb(void) {
425
    /* destroy hash table, if it exists */
426
0
    if (data_sender_receiver) {
427
0
        g_hash_table_destroy(data_sender_receiver);
428
0
        data_sender_receiver = NULL;
429
0
    }
430
0
}
431
432
bool
433
28
socketcan_set_source_and_destination_columns(packet_info *pinfo, can_info_t *caninfo) {
434
28
    sender_receiver_config_t *tmp = ht_lookup_sender_receiver_config(caninfo->bus_id, caninfo->id);
435
436
28
    if (tmp != NULL) {
437
        /* remove all addresses to support CAN as payload (e.g., TECMP) */
438
0
        clear_address(&pinfo->net_src);
439
0
        clear_address(&pinfo->dl_src);
440
0
        clear_address(&pinfo->src);
441
0
        clear_address(&pinfo->net_dst);
442
0
        clear_address(&pinfo->dl_dst);
443
0
        clear_address(&pinfo->dst);
444
445
0
        col_add_str(pinfo->cinfo, COL_DEF_SRC, tmp->sender_name);
446
0
        col_add_str(pinfo->cinfo, COL_DEF_DST, tmp->receiver_name);
447
0
        return true;
448
0
    }
449
28
    return false;
450
28
}
451
452
bool
453
56
socketcan_call_subdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, struct can_info *can_info, const bool use_heuristics_first) {
454
56
    dissector_table_t effective_can_id_dissector_table = (can_info->id & CAN_EFF_FLAG) ? can_extended_id_dissector_table : can_id_dissector_table;
455
56
    uint32_t effective_can_id = (can_info->id & CAN_EFF_FLAG) ? can_info->id & CAN_EFF_MASK : can_info->id & CAN_SFF_MASK;
456
457
56
    if (!dissector_try_uint_with_data(effective_can_id_dissector_table, effective_can_id, tvb, pinfo, tree, true, can_info)) {
458
56
        if (!use_heuristics_first) {
459
56
            if (!dissector_try_payload_with_data(subdissector_table, tvb, pinfo, tree, true, can_info)) {
460
56
                if (!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &heur_dtbl_entry, can_info)) {
461
52
                    return false;
462
52
                }
463
56
            }
464
56
        } else {
465
0
            if (!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &heur_dtbl_entry, can_info)) {
466
0
                if (!dissector_try_payload_with_data(subdissector_table, tvb, pinfo, tree, false, can_info)) {
467
0
                    return false;
468
0
                }
469
0
            }
470
0
        }
471
56
    }
472
473
4
    return true;
474
56
}
475
476
/*
477
 * Either:
478
 *
479
 *    1) a given SocketCAN frame is known to contain a classic CAN
480
 *       packet based on information outside the SocketCAN header;
481
 *
482
 *    2) a given SocketCAN frame is known to contain a CAN FD
483
 *       packet based on information outside the SocketCAN header;
484
 *
485
 *    3) a given SocketCAN frame is known to contain a CAN XL
486
 *       packet based on information outside the SocketCAN header;
487
 *
488
 *    4) we don't know whether the given SocketCAN frame is a
489
 *       classic CAN packet, a CAN FD packet, or a CAN XL packet,
490
 *       and will have to check the CANXL_XLF bit in the "Frame Length"
491
 *       field and the CANFD_FDF bit in the "FD flags" field of the
492
 *       SocketCAN header to determine that.
493
 */
494
typedef enum {
495
    PACKET_TYPE_CAN,
496
    PACKET_TYPE_CAN_FD,
497
    PACKET_TYPE_CAN_XL,
498
    PACKET_TYPE_UNKNOWN
499
} can_packet_type_t;
500
501
static int
502
6
dissect_socketcan_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned encoding, unsigned xl_encoding, can_packet_type_t can_packet_type) {
503
6
    proto_tree     *can_tree;
504
6
    proto_item     *ti;
505
6
    uint8_t         frame_type;
506
6
    can_info_t      can_info;
507
6
    int * const    *can_flags_id;
508
509
6
    static int * const can_std_flags_id[] = {
510
6
        &hf_can_infoent_std,
511
6
        &hf_can_extflag,
512
6
        &hf_can_rtrflag,
513
6
        &hf_can_errflag,
514
6
        NULL,
515
6
    };
516
6
    static int * const can_ext_flags_id[] = {
517
6
        &hf_can_infoent_ext,
518
6
        &hf_can_extflag,
519
6
        &hf_can_rtrflag,
520
6
        &hf_can_errflag,
521
6
        NULL,
522
6
    };
523
6
    static int * const canfd_std_flags_id[] = {
524
6
        &hf_can_infoent_std,
525
6
        &hf_can_extflag,
526
6
        NULL,
527
6
    };
528
6
    static int * const canfd_ext_flags_id[] = {
529
6
        &hf_can_infoent_ext,
530
6
        &hf_can_extflag,
531
6
        NULL,
532
6
    };
533
6
    static int * const canfd_flag_fields[] = {
534
6
        &hf_canfd_brsflag,
535
6
        &hf_canfd_esiflag,
536
6
        &hf_canfd_fdflag,
537
6
        NULL,
538
6
    };
539
6
    static int * const can_err_flags[] = {
540
6
        &hf_can_errflag,
541
6
        &hf_can_err_tx_timeout,
542
6
        &hf_can_err_lostarb,
543
6
        &hf_can_err_ctrl,
544
6
        &hf_can_err_prot,
545
6
        &hf_can_err_trx,
546
6
        &hf_can_err_ack,
547
6
        &hf_can_err_busoff,
548
6
        &hf_can_err_buserror,
549
6
        &hf_can_err_restarted,
550
6
        &hf_can_err_reserved,
551
6
        NULL,
552
6
    };
553
6
    static int * const canxl_prio_vcid_fields[] = {
554
6
        &hf_canxl_priority,
555
6
        &hf_canxl_vcid,
556
6
        NULL,
557
6
    };
558
6
    static int * const canxl_flag_fields[] = {
559
6
        &hf_canxl_secflag,
560
6
        &hf_canxl_rrsflag,
561
6
        &hf_canxl_xlflag,
562
6
        NULL,
563
6
    };
564
565
    /* determine CAN packet type */
566
6
    if (can_packet_type == PACKET_TYPE_UNKNOWN) {
567
6
        uint8_t canfd_flags;
568
6
        uint8_t canxl_flags;
569
570
        /*
571
         * Check whether the frame has the CANXL_XLF flag set in what
572
         * is in the location of the frame length field of a CAN classic
573
         * or CAN FD frame; if so, then it's a CAN XL frame (and that
574
         * field is the flags field of that frame).
575
         */
576
6
        canfd_flags = tvb_get_uint8(tvb, CANFD_FLAG_OFFSET);
577
6
        canxl_flags = tvb_get_uint8(tvb, CANXL_FLAGS_OFFSET);
578
579
6
        if (canxl_flags & CANXL_XLF) {
580
            /* CAN XL: check for min/max data length */
581
2
            if (tvb_reported_length(tvb) >= 13 && tvb_reported_length(tvb) <= 2060) {
582
1
                can_packet_type = PACKET_TYPE_CAN_XL;
583
1
            } else {
584
                /* invalid CAN XL frame (expert info) */
585
1
                return tvb_captured_length(tvb);
586
1
            }
587
4
        } else {
588
            /* CAN CC/FD */
589
4
            if (tvb_reported_length(tvb) == 72 || (canfd_flags & CANFD_FDF)) {
590
                /* CAN FD: check for min/max data length */
591
0
                if (tvb_reported_length(tvb) >= 8 && tvb_reported_length(tvb) <= 72) {
592
0
                    can_packet_type = PACKET_TYPE_CAN_FD;
593
0
                } else {
594
                    /* invalid CAN FD frame (expert info) */
595
0
                    return tvb_captured_length(tvb);
596
0
                }
597
4
            } else if (tvb_reported_length(tvb) >= 8 && tvb_reported_length(tvb) <= 16) {
598
3
                can_packet_type = PACKET_TYPE_CAN;
599
3
            } else {
600
                /* invalid CAN CC frame (expert info) */
601
1
                return tvb_captured_length(tvb);
602
1
            }
603
4
        }
604
6
    }
605
606
4
    can_info.bus_id = get_bus_id(pinfo);
607
608
4
    if (can_packet_type == PACKET_TYPE_CAN_XL) {
609
1
        can_info.fd = CAN_TYPE_CAN_XL;
610
1
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "CANXL");
611
1
        col_clear(pinfo->cinfo, COL_INFO);
612
613
1
        can_info.id = 0; /* XXX - is there an "ID" for XL frames? */
614
615
1
        ti = proto_tree_add_item(tree, proto_can, tvb, 0, -1, ENC_NA);
616
1
        proto_item_set_hidden(ti);
617
1
        ti = proto_tree_add_item(tree, proto_canxl, tvb, 0, -1, ENC_NA);
618
1
        can_tree = proto_item_add_subtree(ti, ett_can_xl);
619
620
1
        if (can_info.bus_id != 0) {
621
0
            ti = proto_tree_add_uint(can_tree, hf_can_bus_id, tvb, 0, 0, can_info.bus_id);
622
0
            proto_item_set_hidden(ti);
623
0
        }
624
625
1
        uint32_t proto_vcid;
626
627
  /*
628
   * The priority/VCID field is big-endian in LINKTYPE_CAN_SOCKETCAN
629
   * captures, for historical reasons.  It's host-endian in
630
   * Linux cooked captures.  This means we use the non-XL encoding.
631
   */
632
1
        proto_tree_add_bitmask_list(can_tree, tvb, 0, 4, canxl_prio_vcid_fields, encoding);
633
1
        proto_vcid = tvb_get_uint32(tvb, 0, encoding);
634
1
        col_add_fstr(pinfo->cinfo, COL_INFO, "Priority: %u (0x%03x), VCID: %u (0x%02X)", proto_vcid & 0x7FF, proto_vcid & 0x7FF, (proto_vcid >> 16) & 0xFF, (proto_vcid >> 16) & 0xFF);
635
1
        proto_item_append_text(can_tree, ", Priority: %u (0x%03x), VCID: %u (0x%02X)", proto_vcid & 0x7FF, proto_vcid & 0x7FF, (proto_vcid >> 16) & 0xFF, (proto_vcid >> 16) & 0xFF);
636
1
        proto_tree_add_bitmask_list(can_tree, tvb, 4, 1, canxl_flag_fields, xl_encoding);
637
638
1
        socketcan_set_source_and_destination_columns(pinfo, &can_info);
639
640
1
        uint32_t sdu_type;
641
642
  /*
643
   * These fields are, if multi-byte, little-endian in
644
   * LINKTYPE_CAN_SOCKETCAN captures, so use xl_encoding.
645
   */
646
1
        proto_tree_add_item_ret_uint(can_tree, hf_canxl_sdu_type, tvb, 5, 1, ENC_NA, &sdu_type);
647
1
        proto_tree_add_item_ret_uint(can_tree, hf_canxl_len, tvb, CANXL_LEN_OFFSET, 2, xl_encoding, &can_info.len);
648
1
        col_append_fstr(pinfo->cinfo, COL_INFO, ", Length: %u", can_info.len);
649
1
        proto_item_append_text(can_tree, ", Length: %u", can_info.len);
650
1
        proto_tree_add_item(can_tree, hf_canxl_acceptance_field, tvb, CANXL_LEN_OFFSET+2, 4, xl_encoding);
651
652
1
        tvbuff_t   *next_tvb;
653
654
1
        next_tvb = tvb_new_subset_length(tvb, CANXL_DATA_OFFSET, can_info.len);
655
656
1
        if (!dissector_try_uint_with_data(canxl_sdu_type_dissector_table, sdu_type, next_tvb, pinfo, tree, true, &can_info)) {
657
1
            call_data_dissector(next_tvb, pinfo, tree);
658
1
        }
659
660
1
        if (tvb_captured_length_remaining(tvb, CANXL_DATA_OFFSET+can_info.len) > 0) {
661
0
            proto_tree_add_item(can_tree, hf_can_padding, tvb, CANXL_DATA_OFFSET+can_info.len, -1, ENC_NA);
662
0
        }
663
3
    } else {
664
3
        if (can_packet_type == PACKET_TYPE_CAN_FD) {
665
0
            can_info.fd = CAN_TYPE_CAN_FD;
666
0
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "CANFD");
667
3
        } else {
668
3
            can_info.fd = CAN_TYPE_CAN_CLASSIC;
669
3
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "CAN");
670
3
        }
671
3
        col_clear(pinfo->cinfo, COL_INFO);
672
673
3
        ti = proto_tree_add_item(tree, proto_can, tvb, 0, -1, ENC_NA);
674
3
        if (can_packet_type == PACKET_TYPE_CAN_FD) {
675
0
            proto_item_set_hidden(ti);
676
0
            ti = proto_tree_add_item(tree, proto_canfd, tvb, 0, -1, ENC_NA);
677
0
        }
678
3
        can_tree = proto_item_add_subtree(ti, (can_packet_type == PACKET_TYPE_CAN_FD) ? ett_can_fd : ett_can);
679
680
3
        if (can_info.bus_id != 0) {
681
0
            ti = proto_tree_add_uint(can_tree, hf_can_bus_id, tvb, 0, 0, can_info.bus_id);
682
0
            proto_item_set_hidden(ti);
683
0
        }
684
685
        /* Get the ID and flags field */
686
3
        can_info.id = tvb_get_uint32(tvb, 0, encoding);
687
688
        /* Error Message Frames are only encapsulated in Classic CAN frames */
689
3
        if (can_packet_type == PACKET_TYPE_CAN && (can_info.id & CAN_ERR_FLAG)) {
690
2
            frame_type = LINUX_CAN_ERR;
691
2
            can_flags_id  = can_err_flags;
692
2
        } else if (can_info.id & CAN_EFF_FLAG) {
693
0
            frame_type = LINUX_CAN_EXT;
694
0
            can_info.id &= (CAN_EFF_MASK | CAN_FLAG_MASK);
695
0
            can_flags_id  = (can_packet_type == PACKET_TYPE_CAN_FD) ? canfd_ext_flags_id : can_ext_flags_id;
696
1
        } else {
697
1
            frame_type = LINUX_CAN_STD;
698
1
            can_info.id &= (CAN_SFF_MASK | CAN_FLAG_MASK);
699
1
            can_flags_id  = (can_packet_type == PACKET_TYPE_CAN_FD) ? canfd_std_flags_id : can_std_flags_id;
700
1
        }
701
702
3
        socketcan_set_source_and_destination_columns(pinfo, &can_info);
703
704
3
        proto_tree_add_bitmask_list(can_tree, tvb, 0, 4, can_flags_id, encoding);
705
3
        if (can_info.id & CAN_EFF_FLAG) {
706
0
            col_add_fstr(pinfo->cinfo, COL_INFO, "Ext. ID: %u (0x%08x)", can_info.id & CAN_EFF_MASK, can_info.id & CAN_EFF_MASK);
707
0
            proto_item_append_text(can_tree, ", Ext. ID: %u (0x%08x)", can_info.id & CAN_EFF_MASK, can_info.id & CAN_EFF_MASK);
708
3
        } else {
709
3
            col_add_fstr(pinfo->cinfo, COL_INFO, "ID: %u (0x%03x)", can_info.id & CAN_SFF_MASK, can_info.id & CAN_SFF_MASK);
710
3
            proto_item_append_text(can_tree, ", ID: %u (0x%03x)", can_info.id & CAN_SFF_MASK, can_info.id & CAN_SFF_MASK);
711
3
        }
712
3
        proto_tree_add_item_ret_uint(can_tree, hf_can_len, tvb, CAN_LEN_OFFSET, 1, ENC_NA, &can_info.len);
713
3
        col_append_fstr(pinfo->cinfo, COL_INFO, ", Length: %u", can_info.len);
714
3
        proto_item_append_text(can_tree, ", Length: %u", can_info.len);
715
716
3
        if (frame_type == LINUX_CAN_ERR && can_info.len != CAN_ERR_DLC) {
717
2
            proto_tree_add_expert(tree, pinfo, &ei_can_err_dlc_mismatch, tvb, CAN_LEN_OFFSET, 1);
718
2
        }
719
720
3
        if (can_packet_type == PACKET_TYPE_CAN_FD) {
721
0
            proto_tree_add_bitmask_list(can_tree, tvb, CANFD_FLAG_OFFSET, 1, canfd_flag_fields, ENC_NA);
722
0
            proto_tree_add_item(can_tree, hf_can_reserved, tvb, CANFD_FLAG_OFFSET+1, 2, ENC_NA);
723
3
        } else {
724
3
            proto_tree_add_item(can_tree, hf_can_reserved, tvb, CANFD_FLAG_OFFSET, 2, ENC_NA);
725
3
            proto_tree_add_item(can_tree, hf_can_len8dlc, tvb, CANFD_FLAG_OFFSET+2, 1, ENC_NA);
726
3
        }
727
728
3
        if (frame_type == LINUX_CAN_ERR) {
729
2
            int * const *flag;
730
2
            const char *sepa = ": ";
731
732
2
            col_set_str(pinfo->cinfo, COL_INFO, "ERR");
733
734
24
            for (flag = can_err_flags; *flag; flag++) {
735
22
                header_field_info *hfi;
736
737
22
                hfi = proto_registrar_get_nth(**flag);
738
22
                if (!hfi)
739
0
                    continue;
740
741
22
                if ((can_info.id & hfi->bitmask & ~CAN_FLAG_MASK) == 0)
742
12
                    continue;
743
744
10
                col_append_sep_str(pinfo->cinfo, COL_INFO, sepa, hfi->name);
745
10
                sepa = ", ";
746
10
            }
747
748
2
            if (can_info.id & CAN_ERR_LOSTARB) {
749
0
                proto_tree_add_item(can_tree, hf_can_err_lostarb_bit_number, tvb, CAN_DATA_OFFSET + 0, 1, ENC_NA);
750
0
            }
751
752
2
            if (can_info.id & CAN_ERR_CTRL) {
753
1
                static int * const can_err_ctrl_flags[] = {
754
1
                    &hf_can_err_ctrl_rx_overflow,
755
1
                    &hf_can_err_ctrl_tx_overflow,
756
1
                    &hf_can_err_ctrl_rx_warning,
757
1
                    &hf_can_err_ctrl_tx_warning,
758
1
                    &hf_can_err_ctrl_rx_passive,
759
1
                    &hf_can_err_ctrl_tx_passive,
760
1
                    &hf_can_err_ctrl_active,
761
1
                    NULL,
762
1
                };
763
764
1
                proto_tree_add_bitmask_list(can_tree, tvb, CAN_DATA_OFFSET+1, 1, can_err_ctrl_flags, ENC_NA);
765
1
           }
766
767
2
           if (can_info.id & CAN_ERR_PROT) {
768
1
                static int * const can_err_prot_error_type_flags[] = {
769
1
                    &hf_can_err_prot_error_type_bit,
770
1
                    &hf_can_err_prot_error_type_form,
771
1
                    &hf_can_err_prot_error_type_stuff,
772
1
                    &hf_can_err_prot_error_type_bit0,
773
1
                    &hf_can_err_prot_error_type_bit1,
774
1
                    &hf_can_err_prot_error_type_overload,
775
1
                    &hf_can_err_prot_error_type_active,
776
1
                    &hf_can_err_prot_error_type_tx,
777
1
                    NULL
778
1
                };
779
1
                proto_tree_add_bitmask_list(can_tree, tvb, CAN_DATA_OFFSET+2, 1, can_err_prot_error_type_flags, ENC_NA);
780
1
                proto_tree_add_item(can_tree, hf_can_err_prot_error_location, tvb, CAN_DATA_OFFSET+3, 1, ENC_NA);
781
1
            }
782
783
2
            if (can_info.id & CAN_ERR_TRX) {
784
2
                proto_tree_add_item(can_tree, hf_can_err_trx_canh, tvb, CAN_DATA_OFFSET+4, 1, ENC_NA);
785
2
                proto_tree_add_item(can_tree, hf_can_err_trx_canl, tvb, CAN_DATA_OFFSET+4, 1, ENC_NA);
786
2
            }
787
788
2
            proto_tree_add_item(can_tree, hf_can_err_ctrl_specific, tvb, CAN_DATA_OFFSET+5, 3, ENC_NA);
789
2
        } else {
790
1
            tvbuff_t   *next_tvb;
791
792
1
            if (can_info.id & CAN_RTR_FLAG) {
793
0
                col_append_str(pinfo->cinfo, COL_INFO, " (Remote Transmission Request)");
794
0
            }
795
796
1
            next_tvb = tvb_new_subset_length(tvb, CAN_DATA_OFFSET, can_info.len);
797
798
1
            if (!socketcan_call_subdissectors(next_tvb, pinfo, tree, &can_info, heuristic_first)) {
799
1
                call_data_dissector(next_tvb, pinfo, tree);
800
1
           }
801
1
        }
802
803
3
        if (tvb_captured_length_remaining(tvb, CAN_DATA_OFFSET+can_info.len) > 0) {
804
1
            proto_tree_add_item(can_tree, hf_can_padding, tvb, CAN_DATA_OFFSET+can_info.len, -1, ENC_NA);
805
1
        }
806
3
    }
807
808
4
    return tvb_captured_length(tvb);
809
6
}
810
811
static int
812
6
dissect_socketcan_bigendian(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
813
6
    return dissect_socketcan_common(tvb, pinfo, tree,
814
6
                                    byte_swap ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN,
815
6
                                    ENC_LITTLE_ENDIAN,
816
6
                                    PACKET_TYPE_UNKNOWN);
817
6
}
818
819
static int
820
0
dissect_socketcan_classic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
821
0
    return dissect_socketcan_common(tvb, pinfo, tree,
822
0
                                    byte_swap ? ENC_ANTI_HOST_ENDIAN : ENC_HOST_ENDIAN,
823
0
                                    ENC_HOST_ENDIAN, /* Not used, as this is CAN classic, not CAN XL */
824
0
                                    PACKET_TYPE_CAN);
825
0
}
826
827
static int
828
0
dissect_socketcan_fd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
829
0
    return dissect_socketcan_common(tvb, pinfo, tree,
830
0
                                    byte_swap ? ENC_ANTI_HOST_ENDIAN : ENC_HOST_ENDIAN,
831
0
                                    ENC_HOST_ENDIAN, /* Not used, as this is CAN FD, not CAN XL */
832
0
                                    PACKET_TYPE_CAN_FD);
833
0
}
834
835
static int
836
0
dissect_socketcan_xl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
837
0
    return dissect_socketcan_common(tvb, pinfo, tree,
838
0
                                    byte_swap ? ENC_ANTI_HOST_ENDIAN : ENC_HOST_ENDIAN,
839
0
                                    ENC_HOST_ENDIAN,
840
0
                                    PACKET_TYPE_CAN_XL);
841
0
}
842
843
void
844
16
proto_register_socketcan(void) {
845
16
    static hf_register_info hf[] = {
846
16
        { &hf_can_bus_id, {
847
16
            "Bus ID", "can.bus_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
848
16
        { &hf_can_infoent_ext, {
849
16
            "ID", "can.id", FT_UINT32, BASE_DEC_HEX, NULL, CAN_EFF_MASK, NULL, HFILL } },
850
16
        { &hf_can_infoent_std, {
851
16
            "ID", "can.id", FT_UINT32, BASE_DEC_HEX, NULL, CAN_SFF_MASK, NULL, HFILL } },
852
16
        { &hf_can_extflag, {
853
16
            "Extended Flag", "can.flags.xtd", FT_BOOLEAN, 32, NULL, CAN_EFF_FLAG, NULL, HFILL } },
854
16
        { &hf_can_rtrflag, {
855
16
            "Remote Transmission Request Flag", "can.flags.rtr", FT_BOOLEAN, 32, NULL, CAN_RTR_FLAG, NULL, HFILL } },
856
16
        { &hf_can_errflag, {
857
16
            "Error Message Flag", "can.flags.err", FT_BOOLEAN, 32, NULL, CAN_ERR_FLAG, NULL, HFILL } },
858
16
        { &hf_can_len, {
859
16
            "Frame-Length", "can.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
860
16
        { &hf_can_len8dlc, {
861
16
            "Len 8 DLC", "can.len8dlc", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
862
16
        { &hf_can_reserved, {
863
16
            "Reserved", "can.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
864
16
        { &hf_can_padding, {
865
16
            "Padding", "can.padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
866
867
16
        { &hf_canfd_brsflag, {
868
16
            "Bit Rate Setting", "canfd.flags.brs", FT_BOOLEAN, 8, NULL, CANFD_BRS, NULL, HFILL } },
869
16
        { &hf_canfd_esiflag, {
870
16
            "Error State Indicator", "canfd.flags.esi", FT_BOOLEAN, 8, NULL, CANFD_ESI, NULL, HFILL } },
871
16
        { &hf_canfd_fdflag, {
872
16
            "FD Frame", "canfd.flags.fdf", FT_BOOLEAN, 8, NULL, CANFD_FDF, NULL, HFILL } },
873
874
16
        { &hf_can_err_tx_timeout, {
875
16
            "Transmit timeout", "can.err.tx_timeout", FT_BOOLEAN, 32, NULL, CAN_ERR_TX_TIMEOUT, NULL, HFILL } },
876
16
        { &hf_can_err_lostarb, {
877
16
            "Lost arbitration", "can.err.lostarb", FT_BOOLEAN, 32, NULL, CAN_ERR_LOSTARB, NULL, HFILL } },
878
16
        { &hf_can_err_ctrl, {
879
16
            "Controller problems", "can.err.ctrl", FT_BOOLEAN, 32, NULL, CAN_ERR_CTRL, NULL, HFILL } },
880
16
        { &hf_can_err_prot, {
881
16
            "Protocol violation", "can.err.prot", FT_BOOLEAN, 32, NULL, CAN_ERR_PROT, NULL, HFILL } },
882
16
        { &hf_can_err_trx, {
883
16
            "Transceiver status", "can.err.trx", FT_BOOLEAN, 32, NULL, CAN_ERR_TRX, NULL, HFILL } },
884
16
        { &hf_can_err_ack, {
885
16
            "No acknowledgment", "can.err.ack", FT_BOOLEAN, 32, NULL, CAN_ERR_ACK, NULL, HFILL } },
886
16
        { &hf_can_err_busoff, {
887
16
            "Bus off", "can.err.busoff", FT_BOOLEAN, 32, NULL, CAN_ERR_BUSOFF, NULL, HFILL } },
888
16
        { &hf_can_err_buserror, {
889
16
            "Bus error", "can.err.buserror", FT_BOOLEAN, 32, NULL, CAN_ERR_BUSERROR, NULL, HFILL } },
890
16
        { &hf_can_err_restarted, {
891
16
            "Controller restarted", "can.err.restarted", FT_BOOLEAN, 32, NULL, CAN_ERR_RESTARTED, NULL, HFILL } },
892
16
        { &hf_can_err_reserved, {
893
16
            "Reserved", "can.err.reserved", FT_UINT32, BASE_HEX, NULL, CAN_ERR_RESERVED, NULL, HFILL } },
894
16
        { &hf_can_err_lostarb_bit_number, {
895
16
            "Lost arbitration in bit number", "can.err.lostarb.bitnum", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
896
16
        { &hf_can_err_ctrl_rx_overflow, {
897
16
            "RX buffer overflow", "can.err.ctrl.rx_overflow", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL } },
898
16
        { &hf_can_err_ctrl_tx_overflow, {
899
16
            "TX buffer overflow", "can.err.ctrl.tx_overflow", FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL } },
900
16
        { &hf_can_err_ctrl_rx_warning, {
901
16
            "Reached warning level for RX errors", "can.err.ctrl.rx_warning", FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL } },
902
16
        { &hf_can_err_ctrl_tx_warning, {
903
16
            "Reached warning level for TX errors", "can.err.ctrl.tx_warning", FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL } },
904
16
        { &hf_can_err_ctrl_rx_passive, {
905
16
            "Reached error passive status RX", "can.err.ctrl.rx_passive", FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL } },
906
16
        { &hf_can_err_ctrl_tx_passive, {
907
16
            "Reached error passive status TX", "can.err.ctrl.tx_passive", FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL } },
908
16
        { &hf_can_err_ctrl_active, {
909
16
            "Recovered to error active state", "can.err.ctrl.active", FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL } },
910
16
        { &hf_can_err_prot_error_type_bit, {
911
16
            "Single bit error", "can.err.prot.type.bit", FT_BOOLEAN, 8, NULL, CAN_ERR_PROT_BIT, NULL, HFILL } },
912
16
        { &hf_can_err_prot_error_type_form, {
913
16
            "Frame format error", "can.err.prot.type.form", FT_BOOLEAN, 8, NULL, CAN_ERR_PROT_FORM, NULL, HFILL } },
914
16
        { &hf_can_err_prot_error_type_stuff, {
915
16
            "Bit stuffing error", "can.err.prot.type.stuff", FT_BOOLEAN, 8, NULL, CAN_ERR_PROT_STUFF, NULL, HFILL } },
916
16
        { &hf_can_err_prot_error_type_bit0, {
917
16
            "Unable to send dominant bit", "can.err.prot.type.bit0", FT_BOOLEAN, 8, NULL, CAN_ERR_PROT_BIT0, NULL, HFILL } },
918
16
        { &hf_can_err_prot_error_type_bit1, {
919
16
            "Unable to send recessive bit", "can.err.prot.type.bit1", FT_BOOLEAN, 8, NULL, CAN_ERR_PROT_BIT1, NULL, HFILL } },
920
16
        { &hf_can_err_prot_error_type_overload, {
921
16
            "Bus overload", "can.err.prot.type.overload", FT_BOOLEAN, 8, NULL, CAN_ERR_PROT_OVERLOAD, NULL, HFILL } },
922
16
        { &hf_can_err_prot_error_type_active, {
923
16
            "Active error announcement", "can.err.prot.type.active", FT_BOOLEAN, 8, NULL, CAN_ERR_PROT_ACTIVE, NULL, HFILL } },
924
16
        { &hf_can_err_prot_error_type_tx, {
925
16
            "Error occurred on transmission", "can.err.prot.type.tx", FT_BOOLEAN, 8, NULL, CAN_ERR_PROT_TX, NULL, HFILL } },
926
16
        { &hf_can_err_prot_error_location, {
927
16
            "Protocol error location", "can.err.prot.location", FT_UINT8, BASE_DEC, VALS(can_err_prot_error_location_vals), 0, NULL, HFILL } },
928
16
        { &hf_can_err_trx_canh, {
929
16
            "Transceiver CANH status", "can.err.trx.canh", FT_UINT8, BASE_DEC, VALS(can_err_trx_canh_vals), 0x0F, NULL, HFILL } },
930
16
        { &hf_can_err_trx_canl, {
931
16
            "Transceiver CANL status", "can.err.trx.canl", FT_UINT8, BASE_DEC, VALS(can_err_trx_canl_vals), 0xF0, NULL, HFILL } },
932
16
        { &hf_can_err_ctrl_specific, {
933
16
            "Controller specific data", "can.err.ctrl_specific", FT_BYTES, SEP_SPACE, NULL, 0, NULL, HFILL } },
934
935
16
        { &hf_canxl_priority, {
936
16
            "Priority", "canxl.priority", FT_UINT32, BASE_DEC, NULL, 0x0000FFFF, NULL, HFILL } },
937
16
        { &hf_canxl_vcid, {
938
16
            "VCID", "canxl.vcid", FT_UINT32, BASE_DEC, NULL, 0x00FF0000, NULL, HFILL } },
939
16
        { &hf_canxl_secflag, {
940
16
            "Simple Extended Content", "canxl.flags.sec", FT_BOOLEAN, 8, NULL, CANXL_SEC, NULL, HFILL } },
941
16
        { &hf_canxl_rrsflag, {
942
16
            "Remote Request Substitution", "canxl.flags.rrs", FT_BOOLEAN, 8, NULL, CANXL_RRS, NULL, HFILL } },
943
16
        { &hf_canxl_xlflag, {
944
16
            "XL Frame", "canxl.flags.xl", FT_BOOLEAN, 8, NULL, CANXL_XLF, NULL, HFILL } },
945
16
        { &hf_canxl_sdu_type, {
946
16
            "SDU type", "canxl.sdu_type", FT_UINT8, BASE_HEX, VALS(canxl_sdu_type_vals), 0, NULL, HFILL } },
947
16
        { &hf_canxl_len, {
948
16
            "Frame-Length", "canxl.len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
949
16
        { &hf_canxl_acceptance_field, {
950
16
            "Acceptance field", "canxl.acceptance_field", FT_UINT32, BASE_DEC_HEX, NULL, 0, NULL, HFILL } },
951
16
    };
952
953
16
    uat_t *can_interface_uat = NULL;
954
16
    uat_t *sender_receiver_uat = NULL;
955
956
    /* Setup protocol subtree array */
957
16
    static int *ett[] = {
958
16
        &ett_can,
959
16
        &ett_can_fd,
960
16
        &ett_can_xl
961
16
    };
962
963
16
    static ei_register_info ei[] = {
964
16
        { &ei_can_err_dlc_mismatch, {
965
16
            "can.err.dlc_mismatch", PI_MALFORMED, PI_ERROR, "ERROR: DLC mismatch", EXPFILL } }
966
16
    };
967
968
16
    module_t *can_module;
969
970
16
    proto_can = proto_register_protocol("Controller Area Network", "CAN", "can");
971
972
    /*
973
     * "can-hostendian" is a legacy name (there never was, in any libpcap
974
     * release, a SocketCAN LINKTYPE_ value for a host-endian CAN ID
975
     * and flags field); we need to keep it around in case some candump
976
     * or Busmaster capture that was saved as a pcap or pcapng file,
977
     * as those use a linktype of LINKTYPE_WIRESHARK_UPPER_PDU with
978
     * "can-hostendian" as the dissector name.
979
     *
980
     * "can-bigendian" is also a legacy name (fpr CAN XL frames, the
981
     * fields in the header are in *little-endian* order); we keep it
982
     * around for the same reason.  It's used for the dissector for
983
     * LINKTYPE_CAN_SOCKETCAN.
984
     */
985
16
    socketcan_classic_handle = register_dissector("can-hostendian", dissect_socketcan_classic, proto_can);
986
16
    socketcan_bigendian_handle = register_dissector("can-bigendian", dissect_socketcan_bigendian, proto_can);
987
988
16
    proto_canfd = proto_register_protocol("Controller Area Network FD", "CANFD", "canfd");
989
16
    socketcan_fd_handle = register_dissector("canfd", dissect_socketcan_fd, proto_canfd);
990
991
16
    proto_canxl = proto_register_protocol("Controller Area Network XL", "CANXL", "canxl");
992
16
    socketcan_xl_handle = register_dissector("canxl", dissect_socketcan_xl, proto_canxl);
993
994
16
    proto_register_field_array(proto_can, hf, array_length(hf));
995
16
    proto_register_subtree_array(ett, array_length(ett));
996
997
16
    expert_register_field_array(expert_register_protocol(proto_can), ei, array_length(ei));
998
999
16
    can_module = prefs_register_protocol(proto_can, NULL);
1000
1001
16
    prefs_register_obsolete_preference(can_module, "protocol");
1002
1003
16
    prefs_register_bool_preference(can_module, "byte_swap", "Byte-swap the CAN ID/flags field",
1004
16
        "Whether the CAN ID/flags field should be byte-swapped in CAN classic and CAN FD packets",
1005
16
        &byte_swap);
1006
1007
16
    prefs_register_bool_preference(can_module, "try_heuristic_first", "Try heuristic sub-dissectors first",
1008
16
        "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to \"decode as\"",
1009
16
        &heuristic_first);
1010
1011
16
    can_id_dissector_table = register_dissector_table("can.id", "CAN ID", proto_can, FT_UINT32, BASE_DEC);
1012
1013
16
    can_extended_id_dissector_table = register_dissector_table("can.extended_id", "CAN Extended ID", proto_can, FT_UINT32, BASE_DEC);
1014
1015
16
    subdissector_table = register_decode_as_next_proto(proto_can, "can.subdissector", "CAN next level dissector", NULL);
1016
1017
16
    canxl_sdu_type_dissector_table = register_dissector_table("canxl.sdu_type", "CAN XL SDU type",  proto_canxl, FT_UINT8, BASE_HEX);
1018
1019
16
    heur_subdissector_list = register_heur_dissector_list_with_description("can", "CAN heuristic", proto_can);
1020
1021
16
    static uat_field_t can_interface_mapping_uat_fields[] = {
1022
16
        UAT_FLD_HEX(interface_configs,      interface_id,   "Interface ID",   "ID of the Interface with 0xffffffff = any (hex uint32 without leading 0x)"),
1023
16
        UAT_FLD_CSTRING(interface_configs,  interface_name, "Interface Name", "Name of the Interface, empty = any (string)"),
1024
16
        UAT_FLD_HEX(interface_configs,      bus_id,         "Bus ID",         "Bus ID of the Interface (hex uint16 without leading 0x)"),
1025
16
        UAT_END_FIELDS
1026
16
    };
1027
1028
16
    can_interface_uat = uat_new("CAN Interface Mapping",
1029
16
        sizeof(interface_config_t),         /* record size           */
1030
16
        DATAFILE_CAN_INTERFACE_MAPPING,     /* filename              */
1031
16
        true,                               /* from profile          */
1032
16
        (void**)&interface_configs,         /* data_ptr              */
1033
16
        &interface_config_num,              /* numitems_ptr          */
1034
16
        UAT_AFFECTS_DISSECTION,             /* but not fields        */
1035
16
        NULL,                               /* help                  */
1036
16
        copy_interface_config_cb,           /* copy callback         */
1037
16
        update_interface_config,            /* update callback       */
1038
16
        free_interface_config_cb,           /* free callback         */
1039
16
        post_update_can_interfaces_cb,      /* post update callback  */
1040
16
        reset_can_interfaces_cb,            /* reset callback        */
1041
16
        can_interface_mapping_uat_fields    /* UAT field definitions */
1042
16
    );
1043
1044
16
    prefs_register_uat_preference(can_module, "_can_interface_mapping", "Interface Mapping",
1045
16
        "A table to define the mapping between interface and Bus ID.", can_interface_uat);
1046
1047
16
    static uat_field_t sender_receiver_mapping_uat_fields[] = {
1048
16
        UAT_FLD_HEX(sender_receiver_configs,     bus_id,        "Bus ID",        "Bus ID of the Interface with 0 meaning any (hex uint16 without leading 0x)."),
1049
16
        UAT_FLD_HEX(sender_receiver_configs,     can_id,        "CAN ID",        "ID of the CAN Message (hex uint32 without leading 0x)"),
1050
16
        UAT_FLD_CSTRING(sender_receiver_configs, sender_name,   "Sender Name",   "Name of Sender(s)"),
1051
16
        UAT_FLD_CSTRING(sender_receiver_configs, receiver_name, "Receiver Name", "Name of Receiver(s)"),
1052
16
        UAT_END_FIELDS
1053
16
    };
1054
1055
16
    sender_receiver_uat = uat_new("Sender Receiver Config",
1056
16
        sizeof(sender_receiver_config_t),   /* record size           */
1057
16
        DATAFILE_CAN_SENDER_RECEIVER,       /* filename              */
1058
16
        true,                               /* from profile          */
1059
16
        (void**)&sender_receiver_configs,   /* data_ptr              */
1060
16
        &sender_receiver_config_num,        /* numitems_ptr          */
1061
16
        UAT_AFFECTS_DISSECTION,             /* but not fields        */
1062
16
        NULL,                               /* help                  */
1063
16
        copy_sender_receiver_config_cb,     /* copy callback         */
1064
16
        update_sender_receiver_config,      /* update callback       */
1065
16
        free_sender_receiver_config_cb,     /* free callback         */
1066
16
        post_update_sender_receiver_cb,     /* post update callback  */
1067
16
        reset_sender_receiver_cb,           /* reset callback        */
1068
16
        sender_receiver_mapping_uat_fields  /* UAT field definitions */
1069
16
    );
1070
1071
16
    prefs_register_uat_preference(can_module, "_sender_receiver_config", "Sender Receiver Config",
1072
16
        "A table to define the mapping between Bus ID and CAN ID to Sender and Receiver.", sender_receiver_uat);
1073
16
}
1074
1075
void
1076
16
proto_reg_handoff_socketcan(void) {
1077
16
    dissector_add_uint("wtap_encap", WTAP_ENCAP_SOCKETCAN, socketcan_bigendian_handle);
1078
1079
16
    dissector_add_uint("sll.ltype", LINUX_SLL_P_CAN, socketcan_classic_handle);
1080
16
    dissector_add_uint("sll.ltype", LINUX_SLL_P_CANFD, socketcan_fd_handle);
1081
16
    dissector_add_uint("sll.ltype", LINUX_SLL_P_CANXL, socketcan_xl_handle);
1082
16
}
1083
1084
/*
1085
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1086
 *
1087
 * Local variables:
1088
 * c-basic-offset: 4
1089
 * tab-width: 8
1090
 * indent-tabs-mode: nil
1091
 * End:
1092
 *
1093
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1094
 * :indentSize=4:tabSize=8:noTabs=true:
1095
 */