From 2a1ebd1e915278eed7b99ecb678578f683780f23 Mon Sep 17 00:00:00 2001 From: Developer Alexander Date: Wed, 14 Jul 2021 20:35:12 +0200 Subject: [PATCH] can: more specific dissector tables for CAN IDs and extended IDs Introduces two new dissector tables can.id and can.extended_id to enable a more precise control of subdissectors dependent on the can id which is often used to identify the the payload. Since standard CAN IDs and extended IDs can be used in the same network and their ranges overlap it is necessary to have two different dissector tables. Existing Decode as dissector table can.subdissector stays as is to prevent a breaking change. But new dissector tables can.id and can.extended_id get priority over can.subdissector since they are more specific. Id they get a match can.subdissector won't be called. New dissector tables can.id and can.extended_id are accessible in lua scripts via DissectorTable:add() while can.subdissector unfortunately is not. For related Discussion see MR !3405 --- epan/dissectors/packet-socketcan.c | 88 ++++++++++++++++-------------- epan/dissectors/packet-socketcan.h | 8 +++ wiretap/busmaster_parser.lemon | 2 +- wiretap/busmaster_priv.h | 4 +- 4 files changed, 58 insertions(+), 44 deletions(-) diff --git a/epan/dissectors/packet-socketcan.c b/epan/dissectors/packet-socketcan.c index b793cab6ee..b96c68c374 100644 --- a/epan/dissectors/packet-socketcan.c +++ b/epan/dissectors/packet-socketcan.c @@ -102,7 +102,9 @@ static heur_dtbl_entry_t *heur_dtbl_entry; #define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ #define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ -static dissector_table_t subdissector_table; +static dissector_table_t can_id_dissector_table = NULL; +static dissector_table_t can_extended_id_dissector_table = NULL; +static dissector_table_t subdissector_table = NULL; static dissector_handle_t socketcan_bigendian_handle; static dissector_handle_t socketcan_hostendian_handle; static dissector_handle_t socketcan_fd_handle; @@ -161,9 +163,41 @@ static const value_string can_err_trx_canl_vals[] = { 0, NULL } }; +gboolean +socketcan_call_subdissectors(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, struct can_info* can_info, const gboolean use_heuristics_first) +{ + dissector_table_t effective_can_id_dissector_table = (can_info->id & CAN_EFF_FLAG) ? can_extended_id_dissector_table : can_id_dissector_table; + guint32 effective_can_id = (can_info->id & CAN_EFF_FLAG) ? can_info->id & CAN_EFF_MASK : can_info->id & CAN_SFF_MASK; + + if (!dissector_try_uint_new(effective_can_id_dissector_table, effective_can_id, tvb, pinfo, tree, TRUE, can_info)) + { + if (!use_heuristics_first) + { + if (!dissector_try_payload_new(subdissector_table, tvb, pinfo, tree, TRUE, can_info)) + { + if (!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &heur_dtbl_entry, can_info)) + { + return FALSE; + } + } + } + else + { + if (!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &heur_dtbl_entry, can_info)) + { + if (!dissector_try_payload_new(subdissector_table, tvb, pinfo, tree, FALSE, can_info)) + { + return FALSE; + } + } + } + } + + return TRUE; +} + static int -dissect_socketcan_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, - guint encoding) +dissect_socketcan_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint encoding) { proto_tree *can_tree; proto_item *ti; @@ -317,25 +351,9 @@ dissect_socketcan_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, next_tvb = tvb_new_subset_length(tvb, CAN_DATA_OFFSET, can_info.len); - if (!heuristic_first) + if (!socketcan_call_subdissectors(next_tvb, pinfo, tree, &can_info, heuristic_first)) { - if (!dissector_try_payload_new(subdissector_table, next_tvb, pinfo, tree, TRUE, &can_info)) - { - if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &heur_dtbl_entry, &can_info)) - { - call_data_dissector(next_tvb, pinfo, tree); - } - } - } - else - { - if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &heur_dtbl_entry, &can_info)) - { - if (!dissector_try_payload_new(subdissector_table, next_tvb, pinfo, tree, FALSE, &can_info)) - { - call_data_dissector(next_tvb, pinfo, tree); - } - } + call_data_dissector(next_tvb, pinfo, tree); } } @@ -417,25 +435,9 @@ dissect_socketcanfd_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, next_tvb = tvb_new_subset_length(tvb, CAN_DATA_OFFSET, can_info.len); - if(!heuristic_first) + if (!socketcan_call_subdissectors(next_tvb, pinfo, tree, &can_info, heuristic_first)) { - if (!dissector_try_payload_new(subdissector_table, next_tvb, pinfo, tree, TRUE, &can_info)) - { - if(!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &heur_dtbl_entry, &can_info)) - { - call_data_dissector(next_tvb, pinfo, tree); - } - } - } - else - { - if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &heur_dtbl_entry, &can_info)) - { - if(!dissector_try_payload_new(subdissector_table, next_tvb, pinfo, tree, FALSE, &can_info)) - { - call_data_dissector(next_tvb, pinfo, tree); - } - } + call_data_dissector(next_tvb, pinfo, tree); } if (tvb_captured_length_remaining(tvb, CAN_DATA_OFFSET+can_info.len) > 0) @@ -462,7 +464,7 @@ proto_register_socketcan(void) &hf_can_infoent_ext, { "Identifier", "can.id", - FT_UINT32, BASE_HEX, + FT_UINT32, BASE_DEC_HEX, NULL, CAN_EFF_MASK, NULL, HFILL } @@ -471,7 +473,7 @@ proto_register_socketcan(void) &hf_can_infoent_std, { "Identifier", "can.id", - FT_UINT32, BASE_HEX, + FT_UINT32, BASE_DEC_HEX, NULL, CAN_SFF_MASK, NULL, HFILL } @@ -865,6 +867,10 @@ proto_register_socketcan(void) " before using a sub-dissector registered to \"decode as\"", &heuristic_first); + can_id_dissector_table = register_dissector_table("can.id", "CAN ID", proto_can, FT_UINT32, BASE_DEC); + + can_extended_id_dissector_table = register_dissector_table("can.extended_id", "CAN Extended ID", proto_can, FT_UINT32, BASE_DEC); + subdissector_table = register_decode_as_next_proto(proto_can, "can.subdissector", "CAN next level dissector", NULL); heur_subdissector_list = register_heur_dissector_list("can", proto_can); diff --git a/epan/dissectors/packet-socketcan.h b/epan/dissectors/packet-socketcan.h index 1d56cca3c6..8bce54ebcb 100644 --- a/epan/dissectors/packet-socketcan.h +++ b/epan/dissectors/packet-socketcan.h @@ -10,6 +10,11 @@ #ifndef __PACKET_SOCKETCAN_H__ #define __PACKET_SOCKETCAN_H__ +#include +#include +#include + + /* Structure that gets passed between dissectors. */ struct can_info { @@ -49,6 +54,9 @@ typedef struct can_info can_info_t; #define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */ #define CAN_ERR_RESERVED 0x1FFFFE00U /* reserved bits */ + +gboolean socketcan_call_subdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, struct can_info *can_info, const gboolean use_heuristics_first); + #endif /* __PACKET_SOCKETCAN_H__ */ /* diff --git a/wiretap/busmaster_parser.lemon b/wiretap/busmaster_parser.lemon index cabe11286f..436794790a 100644 --- a/wiretap/busmaster_parser.lemon +++ b/wiretap/busmaster_parser.lemon @@ -157,7 +157,7 @@ header ::= version ENDL maybe_lines state->entry_type = LOG_ENTRY_HEADER; state->header.start_date = S.date; state->header.start_time = S.time; - state->header.protocol = (protocol_t)P.v0; + state->header.protocol = (protocol_type_t)P.v0; state->header.data_mode = (data_mode_t)D.v0; state->header.time_mode = (time_mode_t)T.v0; } diff --git a/wiretap/busmaster_priv.h b/wiretap/busmaster_priv.h index 11bf384e10..1e011b3a49 100644 --- a/wiretap/busmaster_priv.h +++ b/wiretap/busmaster_priv.h @@ -35,7 +35,7 @@ typedef enum { PROTOCOL_CAN, PROTOCOL_LIN, PROTOCOL_J1939, -} protocol_t; +} protocol_type_t; typedef enum { DATA_MODE_UNKNOWN = 0, @@ -100,7 +100,7 @@ typedef struct { typedef struct { gint64 file_start_offset; gint64 file_end_offset; - protocol_t protocol; + protocol_type_t protocol; data_mode_t data_mode; time_mode_t time_mode; msg_date_t start_date;