forked from osmocom/wireshark
DLT: Adding support to open DLT files
This patch allows Wireshark to open DLT files directly.
This commit is contained in:
parent
95aff565ab
commit
05916eec1f
|
@ -660,6 +660,7 @@ set(DISSECTOR_SRC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/packet-li5g.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file-blf.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file-btsnoop.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file-dlt.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file-elf.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file-file.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file-gif.c
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
/* file-dlt.c
|
||||
* DLT File Format.
|
||||
* By Dr. Lars Voelker <lars.voelker@technica-engineering.de>
|
||||
* Copyright 2022-2022 Dr. Lars Voelker
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This dissector allows to parse DLT files.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sources for specification:
|
||||
* https://www.autosar.org/fileadmin/user_upload/standards/classic/21-11/AUTOSAR_SWS_DiagnosticLogAndTrace.pdf
|
||||
* https://www.autosar.org/fileadmin/user_upload/standards/foundation/21-11/AUTOSAR_PRS_LogAndTraceProtocol.pdf
|
||||
* https://github.com/COVESA/dlt-viewer
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <epan/packet.h>
|
||||
#include <epan/prefs.h>
|
||||
#include <epan/expert.h>
|
||||
#include <epan/exceptions.h>
|
||||
#include <epan/show_exception.h>
|
||||
#include <epan/wmem_scopes.h>
|
||||
#include <wiretap/autosar_dlt.h>
|
||||
|
||||
static int proto_dlt = -1;
|
||||
|
||||
static int hf_dlt_file_magic = -1;
|
||||
static int hf_dlt_file_tstamp_s = -1;
|
||||
static int hf_dlt_file_tstamp_us = -1;
|
||||
static int hf_dlt_file_ecuid = -1;
|
||||
|
||||
static int hf_dlt_file_header_type = -1;
|
||||
static int hf_dlt_file_message_counter = -1;
|
||||
static int hf_dlt_file_length = -1;
|
||||
static int hf_dlt_file_data = -1;
|
||||
|
||||
static gint ett_dlt = -1;
|
||||
static gint ett_dlt_item = -1;
|
||||
|
||||
void proto_register_file_dlt(void);
|
||||
void proto_reg_handoff_file_dlt(void);
|
||||
|
||||
#define MAGIC_NUMBER_SIZE 4
|
||||
static const guint8 dlt_file_magic[MAGIC_NUMBER_SIZE] = { 'D', 'L', 'T', 0x01 };
|
||||
|
||||
static int
|
||||
dissect_dlt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
|
||||
volatile gint offset = 0;
|
||||
proto_tree *dlt_tree;
|
||||
proto_tree *item_tree;
|
||||
proto_item *ti;
|
||||
proto_item *ti_item;
|
||||
guint32 len = 0;
|
||||
|
||||
if (tvb_captured_length(tvb) < 16 || tvb_memeql(tvb, 0, dlt_file_magic, MAGIC_NUMBER_SIZE) != 0) {
|
||||
/* does not start with DLT\x1, so this is not DLT it seems */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ti = proto_tree_add_item(tree, proto_dlt, tvb, offset, -1, ENC_NA);
|
||||
dlt_tree = proto_item_add_subtree(ti, ett_dlt);
|
||||
|
||||
gint tvb_length = tvb_captured_length(tvb);
|
||||
|
||||
while (offset + 20 <= tvb_length) {
|
||||
item_tree = proto_tree_add_subtree_format(dlt_tree, tvb, offset, -1, ett_dlt_item, &ti_item, "DLT Log Line");
|
||||
proto_tree_add_item(item_tree, hf_dlt_file_magic, tvb, offset, 4, ENC_ASCII | ENC_NA);
|
||||
offset += 4;
|
||||
|
||||
guint32 tstamp_s = 0;
|
||||
proto_tree_add_item_ret_uint(item_tree, hf_dlt_file_tstamp_s, tvb, offset, 4, ENC_LITTLE_ENDIAN, &tstamp_s);
|
||||
offset += 4;
|
||||
|
||||
guint32 tstamp_us = 0;
|
||||
proto_tree_add_item_ret_uint(item_tree, hf_dlt_file_tstamp_us, tvb, offset, 4, ENC_LITTLE_ENDIAN, &tstamp_us);
|
||||
offset += 4;
|
||||
|
||||
const guint8 *ecuid;
|
||||
proto_tree_add_item_ret_string(item_tree, hf_dlt_file_ecuid, tvb, offset, 4, ENC_ASCII | ENC_NA, pinfo->pool, &ecuid);
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(item_tree, hf_dlt_file_header_type, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
|
||||
guint counter = 0;
|
||||
proto_tree_add_item_ret_uint(item_tree, hf_dlt_file_message_counter, tvb, offset, 1, ENC_NA, &counter);
|
||||
offset += 1;
|
||||
|
||||
proto_tree_add_item_ret_uint(item_tree, hf_dlt_file_length, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
|
||||
offset += 2;
|
||||
|
||||
proto_tree_add_item(item_tree, hf_dlt_file_data, tvb, offset, len - 4, ENC_NA);
|
||||
offset += (len - 4);
|
||||
|
||||
proto_item_set_end(ti_item, tvb, offset);
|
||||
proto_item_append_text(ti_item, " %3u %u.%06u ECU:%s Len:%u", counter, tstamp_s, tstamp_us, ecuid, len);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dissect_dlt_heur(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_) {
|
||||
return dissect_dlt(tvb, pinfo, tree, NULL) > 0;
|
||||
}
|
||||
|
||||
void
|
||||
proto_register_file_dlt(void) {
|
||||
static hf_register_info hf[] = {
|
||||
{ &hf_dlt_file_magic,
|
||||
{ "Magic", "file-dlt.magic", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_dlt_file_tstamp_s,
|
||||
{ "Timestamp s", "file-dlt.timestamp_s", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_dlt_file_tstamp_us,
|
||||
{ "Timestamp us", "file-dlt.timestamp_us", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_dlt_file_ecuid,
|
||||
{ "ECU ID", "file-dlt.ecu_id", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{ &hf_dlt_file_header_type,
|
||||
{ "Header Type", "file-dlt.header_type", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_dlt_file_message_counter,
|
||||
{ "Message Counter", "file-dlt.msg_counter", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_dlt_file_length,
|
||||
{ "Length", "file-dlt.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
||||
{ &hf_dlt_file_data,
|
||||
{ "Data", "file-dlt.data", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
};
|
||||
|
||||
static gint *ett[] = {
|
||||
&ett_dlt,
|
||||
&ett_dlt_item,
|
||||
};
|
||||
|
||||
proto_dlt = proto_register_protocol("DLT File Format", "File-DLT", "file-dlt");
|
||||
proto_register_field_array(proto_dlt, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
register_dissector("file-dlt", dissect_dlt, proto_dlt);
|
||||
}
|
||||
|
||||
void
|
||||
proto_reg_handoff_file_dlt(void) {
|
||||
heur_dissector_add("wtap_file", dissect_dlt_heur, "DLT File", "dlt_wtap", proto_dlt, HEURISTIC_ENABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
|
@ -37,10 +37,17 @@
|
|||
void proto_register_dlt(void);
|
||||
void proto_reg_handoff_dlt(void);
|
||||
|
||||
void proto_register_dlt_storage_header(void);
|
||||
void proto_reg_handoff_dlt_storage_header(void);
|
||||
|
||||
#define DLT_NAME "DLT"
|
||||
#define DLT_NAME_LONG "Diagnostic Log and Trace (DLT)"
|
||||
#define DLT_NAME_FILTER "dlt"
|
||||
|
||||
#define DLT_STORAGE_HEADER_NAME "DLT Storage Header (short)"
|
||||
#define DLT_STORAGE_HEADER_NAME_LONG "Shortened Diagnostic Log and Trace (DLT) Storage Header"
|
||||
#define DLT_STORAGE_HEADER_NAME_FILTER "dlt.storage"
|
||||
|
||||
#define DLT_MIN_SIZE_FOR_PARSING 4
|
||||
|
||||
#define DLT_HDR_TYPE_EXT_HEADER 0x01
|
||||
|
@ -153,9 +160,11 @@ void proto_reg_handoff_dlt(void);
|
|||
#define DLT_SERVICE_OPTIONS_WITH_LOG_TRACE_TEXT 7
|
||||
|
||||
static int proto_dlt = -1;
|
||||
static int proto_dlt_storage_header = -1;
|
||||
|
||||
static dissector_handle_t dlt_handle_udp = NULL;
|
||||
static dissector_handle_t dlt_handle_tcp = NULL;
|
||||
static dissector_handle_t dlt_handle_storage = NULL;
|
||||
|
||||
/* Subdissectors */
|
||||
static heur_dissector_list_t heur_subdissector_list;
|
||||
|
@ -222,6 +231,11 @@ static int hf_dlt_service_count = -1;
|
|||
static int hf_dlt_service_app_desc = -1;
|
||||
static int hf_dlt_service_ctx_desc = -1;
|
||||
|
||||
static int hf_dlt_storage_tstamp_s = -1;
|
||||
static int hf_dlt_storage_tstamp_us = -1;
|
||||
static int hf_dlt_storage_ecu_name = -1;
|
||||
static int hf_dlt_storage_reserved = -1;
|
||||
|
||||
/* subtrees */
|
||||
static gint ett_dlt = -1;
|
||||
static gint ett_dlt_hdr_type = -1;
|
||||
|
@ -232,6 +246,8 @@ static gint ett_dlt_service_app_ids = -1;
|
|||
static gint ett_dlt_service_app_id = -1;
|
||||
static gint ett_dlt_service_ctx_id = -1;
|
||||
|
||||
static gint ett_dlt_storage = -1;
|
||||
|
||||
/***************************
|
||||
****** String Tables ******
|
||||
***************************/
|
||||
|
@ -1035,12 +1051,12 @@ dissect_dlt_non_verbose_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *r
|
|||
}
|
||||
|
||||
static int
|
||||
dissect_dlt_msg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
|
||||
dissect_dlt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_, guint32 offset_orig) {
|
||||
proto_item *ti;
|
||||
proto_tree *dlt_tree = NULL;
|
||||
proto_tree *ext_hdr_tree = NULL;
|
||||
proto_tree *subtree = NULL;
|
||||
guint32 offset = 0;
|
||||
guint32 offset = offset_orig;
|
||||
|
||||
guint8 header_type = 0;
|
||||
gboolean ext_header = FALSE;
|
||||
|
@ -1069,11 +1085,11 @@ dissect_dlt_msg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
|
|||
return captured_length;
|
||||
}
|
||||
|
||||
header_type = tvb_get_guint8( tvb, 0 );
|
||||
header_type = tvb_get_guint8(tvb, offset);
|
||||
ext_header = ((header_type & DLT_HDR_TYPE_EXT_HEADER) == DLT_HDR_TYPE_EXT_HEADER);
|
||||
payload_le = ((header_type & DLT_HDR_TYPE_MSB_FIRST) != DLT_HDR_TYPE_MSB_FIRST);
|
||||
|
||||
ti = proto_tree_add_item(tree, proto_dlt, tvb, 0, -1, ENC_NA);
|
||||
ti = proto_tree_add_item(tree, proto_dlt, tvb, offset, -1, ENC_NA);
|
||||
dlt_tree = proto_item_add_subtree(ti, ett_dlt);
|
||||
|
||||
ti = proto_tree_add_item(dlt_tree, hf_dlt_header_type, tvb, offset, 1, ENC_NA);
|
||||
|
@ -1153,25 +1169,55 @@ dissect_dlt_msg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
|
|||
}
|
||||
|
||||
col_set_fence(pinfo->cinfo, COL_INFO);
|
||||
return offset;
|
||||
}
|
||||
|
||||
static guint
|
||||
get_dlt_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_, void* data _U_) {
|
||||
return tvb_get_ntohs(tvb, offset+2);
|
||||
return offset - offset_orig;
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_dlt_tcp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data) {
|
||||
dissect_dlt_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
|
||||
return dissect_dlt(tvb, pinfo, tree, data, 0);
|
||||
}
|
||||
|
||||
static guint
|
||||
get_dlt_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void* data _U_) {
|
||||
return tvb_get_ntohs(tvb, offset + 2);
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_dlt_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
|
||||
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DLT_MIN_SIZE_FOR_PARSING, get_dlt_message_len, dissect_dlt_msg, data);
|
||||
return tvb_reported_length(tvb);
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_dlt_udp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data) {
|
||||
dissect_dlt_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
|
||||
return udp_dissect_pdus(tvb, pinfo, tree, DLT_MIN_SIZE_FOR_PARSING, NULL, get_dlt_message_len, dissect_dlt_msg, data);
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_dlt_storage_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
|
||||
proto_tree *dlt_storage_tree;
|
||||
proto_item *ti;
|
||||
|
||||
guint32 offset = 0;
|
||||
|
||||
ti = proto_tree_add_item(tree, proto_dlt_storage_header, tvb, offset, 16, ENC_NA);
|
||||
dlt_storage_tree = proto_item_add_subtree(ti, ett_dlt_storage);
|
||||
|
||||
proto_tree_add_item(dlt_storage_tree, hf_dlt_storage_tstamp_s, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(dlt_storage_tree, hf_dlt_storage_tstamp_us, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
||||
offset += 4;
|
||||
|
||||
/* setting source to ECU Name of the encapsulation header */
|
||||
set_address_tvb(&(pinfo->src), AT_STRINGZ, 4, tvb, offset);
|
||||
proto_tree_add_item(dlt_storage_tree, hf_dlt_storage_ecu_name, tvb, offset, 5, ENC_ASCII);
|
||||
offset += 5;
|
||||
|
||||
proto_tree_add_item(dlt_storage_tree, hf_dlt_storage_reserved, tvb, offset, 3, ENC_NA);
|
||||
return 16 + dissect_dlt(tvb, pinfo, tree, data, 16);
|
||||
}
|
||||
|
||||
void proto_register_dlt(void) {
|
||||
expert_module_t *expert_module_DLT;
|
||||
|
||||
|
@ -1394,6 +1440,37 @@ void proto_reg_handoff_dlt(void) {
|
|||
dissector_add_uint_with_preference("tcp.port", 0, dlt_handle_tcp);
|
||||
}
|
||||
|
||||
void proto_register_dlt_storage_header(void) {
|
||||
static hf_register_info hfs[] = {
|
||||
{ &hf_dlt_storage_tstamp_s, {
|
||||
"Timestamp s", "dlt.storage.timestamp_s",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_dlt_storage_tstamp_us, {
|
||||
"Timestamp us", "dlt.storage.timestamp_us",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_dlt_storage_ecu_name, {
|
||||
"ECU Name", "dlt.storage.ecu_name",
|
||||
FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_dlt_storage_reserved, {
|
||||
"Reserved", "dlt.storage.reserved",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
};
|
||||
|
||||
static gint *ett[] = {
|
||||
&ett_dlt_storage,
|
||||
};
|
||||
|
||||
/* Register the protocol name and description */
|
||||
proto_dlt_storage_header = proto_register_protocol(DLT_STORAGE_HEADER_NAME_LONG, DLT_STORAGE_HEADER_NAME, DLT_STORAGE_HEADER_NAME_FILTER);
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
proto_register_field_array(proto_dlt, hfs, array_length(hfs));
|
||||
}
|
||||
|
||||
void proto_reg_handoff_dlt_storage_header(void) {
|
||||
dlt_handle_storage = create_dissector_handle(dissect_dlt_storage_header, proto_dlt_storage_header);
|
||||
dissector_add_uint("wtap_encap", WTAP_ENCAP_AUTOSAR_DLT, dlt_handle_storage);
|
||||
}
|
||||
/*
|
||||
* Editor modelines
|
||||
*
|
||||
|
|
|
@ -33,6 +33,7 @@ set(WIRETAP_C_MODULE_FILES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/aethra.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ascendtext.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/atm.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/autosar_dlt.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ber.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/blf.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/btsnoop.c
|
||||
|
|
|
@ -0,0 +1,356 @@
|
|||
/* autosar_dlt.c
|
||||
*
|
||||
* Wiretap Library
|
||||
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
|
||||
*
|
||||
* Support for DLT file format as defined by AUTOSAR et. al.
|
||||
* Copyright (c) 2022-2022 by Dr. Lars Voelker <lars.voelker@technica-engineering.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sources for specification:
|
||||
* https://www.autosar.org/fileadmin/user_upload/standards/classic/21-11/AUTOSAR_SWS_DiagnosticLogAndTrace.pdf
|
||||
* https://www.autosar.org/fileadmin/user_upload/standards/foundation/21-11/AUTOSAR_PRS_LogAndTraceProtocol.pdf
|
||||
* https://github.com/COVESA/dlt-viewer
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include "autosar_dlt.h"
|
||||
|
||||
#include "file_wrappers.h"
|
||||
#include "wtap-int.h"
|
||||
|
||||
static const guint8 dlt_magic[] = { 'D', 'L', 'T', 0x01 };
|
||||
|
||||
static int autosar_dlt_file_type_subtype = -1;
|
||||
|
||||
|
||||
void register_autosar_dlt(void);
|
||||
static gboolean autosar_dlt_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info, gint64 *data_offset);
|
||||
static gboolean autosar_dlt_seek_read(wtap *wth, gint64 seek_off, wtap_rec* rec, Buffer *buf, int *err, gchar **err_info);
|
||||
static void autosar_dlt_close(wtap *wth);
|
||||
|
||||
|
||||
typedef struct autosar_dlt_blockheader {
|
||||
guint8 magic[4];
|
||||
guint32 timestamp_s;
|
||||
guint32 timestamp_us;
|
||||
guint8 ecu_id[4];
|
||||
} autosar_dlt_blockheader_t;
|
||||
|
||||
typedef struct autosar_dlt_itemheader {
|
||||
guint8 header_type;
|
||||
guint8 counter;
|
||||
guint16 length;
|
||||
} autosar_dlt_itemheader_t;
|
||||
|
||||
|
||||
typedef struct autosar_dlt_data {
|
||||
GHashTable *ecu_to_iface_ht;
|
||||
guint32 next_interface_id;
|
||||
} autosar_dlt_t;
|
||||
|
||||
typedef struct autosar_dlt_params {
|
||||
wtap *wth;
|
||||
wtap_rec *rec;
|
||||
Buffer *buf;
|
||||
FILE_T fh;
|
||||
|
||||
autosar_dlt_t *dlt_data;
|
||||
} autosar_dlt_params_t;
|
||||
|
||||
static gint
|
||||
autosar_dlt_calc_key(guint8 ecu[4]) {
|
||||
return (gint)(ecu[0] << 24 | ecu[1] << 16 | ecu[2] << 8 | ecu[3]);
|
||||
}
|
||||
|
||||
static guint32
|
||||
autosar_dlt_add_interface(autosar_dlt_params_t *params, guint8 ecu[4]) {
|
||||
wtap_block_t int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
|
||||
wtapng_if_descr_mandatory_t *if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
|
||||
|
||||
if_descr_mand->wtap_encap = WTAP_ENCAP_AUTOSAR_DLT;
|
||||
wtap_block_add_string_option(int_data, OPT_IDB_NAME, (gchar *)ecu, 4);
|
||||
if_descr_mand->time_units_per_second = 1000 * 1000 * 1000;
|
||||
if_descr_mand->tsprecision = WTAP_TSPREC_NSEC;
|
||||
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 9);
|
||||
if_descr_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;
|
||||
if_descr_mand->num_stat_entries = 0;
|
||||
if_descr_mand->interface_statistics = NULL;
|
||||
wtap_add_idb(params->wth, int_data);
|
||||
|
||||
if (params->wth->file_encap == WTAP_ENCAP_UNKNOWN) {
|
||||
params->wth->file_encap = if_descr_mand->wtap_encap;
|
||||
} else {
|
||||
if (params->wth->file_encap != if_descr_mand->wtap_encap) {
|
||||
params->wth->file_encap = WTAP_ENCAP_PER_PACKET;
|
||||
}
|
||||
}
|
||||
|
||||
gint32 key = autosar_dlt_calc_key(ecu);
|
||||
guint32 iface_id = params->dlt_data->next_interface_id++;
|
||||
g_hash_table_insert(params->dlt_data->ecu_to_iface_ht, GINT_TO_POINTER(key), GUINT_TO_POINTER(iface_id));
|
||||
|
||||
return iface_id;
|
||||
}
|
||||
|
||||
static guint32
|
||||
autosar_dlt_lookup_interface(autosar_dlt_params_t *params, guint8 ecu[4]) {
|
||||
gint32 key = autosar_dlt_calc_key(ecu);
|
||||
|
||||
if (params->dlt_data->ecu_to_iface_ht == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
gpointer iface = NULL;
|
||||
gboolean found = g_hash_table_lookup_extended(params->dlt_data->ecu_to_iface_ht, GINT_TO_POINTER(key), NULL, &iface);
|
||||
|
||||
if (found) {
|
||||
return GPOINTER_TO_UINT(iface);
|
||||
} else {
|
||||
return autosar_dlt_add_interface(params, ecu);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fix_endianness_autosar_dlt_blockheader(autosar_dlt_blockheader_t *header) {
|
||||
header->timestamp_s = GUINT32_FROM_LE(header->timestamp_s);
|
||||
header->timestamp_us = GUINT32_FROM_LE(header->timestamp_us);
|
||||
}
|
||||
|
||||
static void
|
||||
fix_endianness_autosar_dlt_itemheader(autosar_dlt_itemheader_t *header) {
|
||||
header->length = GUINT16_FROM_BE(header->length);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
autosar_dlt_read_block(autosar_dlt_params_t *params, gint64 start_pos, int *err, gchar **err_info) {
|
||||
autosar_dlt_blockheader_t header;
|
||||
autosar_dlt_itemheader_t item_header;
|
||||
|
||||
while (1) {
|
||||
params->buf->first_free = params->buf->start;
|
||||
|
||||
if (!wtap_read_bytes_or_eof(params->fh, &header, sizeof header, err, err_info)) {
|
||||
if (*err == WTAP_ERR_SHORT_READ) {
|
||||
*err = WTAP_ERR_BAD_FILE;
|
||||
g_free(*err_info);
|
||||
*err_info = ws_strdup_printf("AUTOSAR DLT: Capture file cut short! Cannot find storage header at pos 0x%" PRIx64 "!", start_pos);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fix_endianness_autosar_dlt_blockheader(&header);
|
||||
|
||||
if (memcmp(header.magic, dlt_magic, sizeof(dlt_magic))) {
|
||||
*err = WTAP_ERR_BAD_FILE;
|
||||
*err_info = ws_strdup_printf("AUTOSAR DLT: Bad capture file! Object magic is not DLT\\x01 at pos 0x%" PRIx64 "!", start_pos);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Set to the byte after the magic. */
|
||||
guint64 current_start_of_item = file_tell(params->fh) - sizeof header + 4;
|
||||
|
||||
if (!wtap_read_bytes_or_eof(params->fh, &item_header, sizeof item_header, err, err_info)) {
|
||||
*err = WTAP_ERR_BAD_FILE;
|
||||
g_free(*err_info);
|
||||
*err_info = ws_strdup_printf("AUTOSAR DLT: Capture file cut short! Not enough bytes for item header at pos 0x%" PRIx64 "!", start_pos);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fix_endianness_autosar_dlt_itemheader(&item_header);
|
||||
|
||||
if (file_seek(params->fh, current_start_of_item, SEEK_SET, err) < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ws_buffer_assure_space(params->buf, (gsize)(item_header.length + sizeof header));
|
||||
|
||||
/* Creating AUTOSAR DLT Encapsulation Header:
|
||||
* guint32 time_s
|
||||
* guint32 time_us
|
||||
* guint8[4] ecuname
|
||||
* guint8[1] 0x00 (termination)
|
||||
* guint8[3] reserved
|
||||
*/
|
||||
void *tmpbuf = g_malloc0(sizeof header);
|
||||
if (!wtap_read_bytes_or_eof(params->fh, tmpbuf, sizeof header - 4, err, err_info)) {
|
||||
/* this would have been caught before ...*/
|
||||
*err = WTAP_ERR_BAD_FILE;
|
||||
g_free(*err_info);
|
||||
*err_info = ws_strdup_printf("AUTOSAR DLT: Internal Error! Not enough bytes for storage header at pos 0x%" PRIx64 "!", start_pos);
|
||||
return FALSE;
|
||||
}
|
||||
ws_buffer_append(params->buf, tmpbuf, (gsize)(sizeof header));
|
||||
g_free(tmpbuf);
|
||||
|
||||
tmpbuf = g_try_malloc0(item_header.length);
|
||||
if (tmpbuf == NULL) {
|
||||
*err = ENOMEM; /* we assume we're out of memory */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!wtap_read_bytes_or_eof(params->fh, tmpbuf, item_header.length, err, err_info)) {
|
||||
*err = WTAP_ERR_BAD_FILE;
|
||||
g_free(*err_info);
|
||||
*err_info = ws_strdup_printf("AUTOSAR DLT: Capture file cut short! Not enough bytes for item at pos 0x%" PRIx64 "!", start_pos);
|
||||
return FALSE;
|
||||
}
|
||||
ws_buffer_append(params->buf, tmpbuf, (gsize)(item_header.length));
|
||||
g_free(tmpbuf);
|
||||
|
||||
params->rec->rec_type = REC_TYPE_PACKET;
|
||||
params->rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
|
||||
params->rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_CAP_LEN | WTAP_HAS_INTERFACE_ID;
|
||||
params->rec->tsprec = WTAP_TSPREC_USEC;
|
||||
params->rec->ts.secs = header.timestamp_s;
|
||||
params->rec->ts.nsecs = header.timestamp_us * 1000;
|
||||
|
||||
params->rec->rec_header.packet_header.caplen = (guint32)(item_header.length + sizeof header);
|
||||
params->rec->rec_header.packet_header.len = (guint32)(item_header.length + sizeof header);
|
||||
params->rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_AUTOSAR_DLT;
|
||||
params->rec->rec_header.packet_header.interface_id = autosar_dlt_lookup_interface(params, header.ecu_id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean autosar_dlt_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info, gint64 *data_offset) {
|
||||
autosar_dlt_params_t dlt_tmp;
|
||||
|
||||
dlt_tmp.wth = wth;
|
||||
dlt_tmp.fh = wth->fh;
|
||||
dlt_tmp.rec = rec;
|
||||
dlt_tmp.buf = buf;
|
||||
dlt_tmp.dlt_data = (autosar_dlt_t *)wth->priv;
|
||||
|
||||
*data_offset = file_tell(wth->fh);
|
||||
|
||||
if (!autosar_dlt_read_block(&dlt_tmp, *data_offset, err, err_info)) {
|
||||
ws_debug("couldn't read packet block (data_offset is %" PRId64 ")", *data_offset);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean autosar_dlt_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info) {
|
||||
autosar_dlt_params_t dlt_tmp;
|
||||
|
||||
dlt_tmp.wth = wth;
|
||||
dlt_tmp.fh = wth->random_fh;
|
||||
dlt_tmp.rec = rec;
|
||||
dlt_tmp.buf = buf;
|
||||
dlt_tmp.dlt_data = (autosar_dlt_t *)wth->priv;
|
||||
|
||||
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
|
||||
return FALSE;
|
||||
|
||||
if (!autosar_dlt_read_block(&dlt_tmp, seek_off, err, err_info)) {
|
||||
ws_debug("couldn't read packet block (seek_off: %" PRId64 ") (err=%d).", seek_off, *err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void autosar_dlt_close(wtap *wth) {
|
||||
autosar_dlt_t *dlt = (autosar_dlt_t *)wth->priv;
|
||||
|
||||
if (dlt != NULL && dlt->ecu_to_iface_ht != NULL) {
|
||||
g_hash_table_destroy(dlt->ecu_to_iface_ht);
|
||||
dlt->ecu_to_iface_ht = NULL;
|
||||
}
|
||||
|
||||
g_free(dlt);
|
||||
wth->priv = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
wtap_open_return_val
|
||||
autosar_dlt_open(wtap *wth, int *err, gchar **err_info) {
|
||||
guint8 magic[4];
|
||||
autosar_dlt_t *dlt;
|
||||
|
||||
ws_debug("opening file");
|
||||
|
||||
if (!wtap_read_bytes_or_eof(wth->fh, &magic, sizeof magic, err, err_info)) {
|
||||
ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err);
|
||||
if (*err == 0 || *err == WTAP_ERR_SHORT_READ) {
|
||||
*err = 0;
|
||||
g_free(*err_info);
|
||||
*err_info = NULL;
|
||||
return WTAP_OPEN_NOT_MINE;
|
||||
}
|
||||
return WTAP_OPEN_ERROR;
|
||||
}
|
||||
|
||||
if (memcmp(magic, dlt_magic, sizeof(dlt_magic))) {
|
||||
return WTAP_OPEN_NOT_MINE;
|
||||
}
|
||||
|
||||
file_seek(wth->fh, 0, SEEK_SET, err);
|
||||
|
||||
dlt = g_new(autosar_dlt_t, 1);
|
||||
dlt->ecu_to_iface_ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
|
||||
dlt->next_interface_id = 0;
|
||||
|
||||
wth->priv = (void *)dlt;
|
||||
wth->file_encap = WTAP_ENCAP_UNKNOWN;
|
||||
wth->snapshot_length = 0;
|
||||
wth->file_tsprec = WTAP_TSPREC_UNKNOWN;
|
||||
wth->subtype_read = autosar_dlt_read;
|
||||
wth->subtype_seek_read = autosar_dlt_seek_read;
|
||||
wth->subtype_close = autosar_dlt_close;
|
||||
wth->file_type_subtype = autosar_dlt_file_type_subtype;
|
||||
|
||||
return WTAP_OPEN_MINE;
|
||||
}
|
||||
|
||||
/* Options for interface blocks. */
|
||||
static const struct supported_option_type interface_block_options_supported[] = {
|
||||
/* No comments, just an interface name. */
|
||||
{ OPT_IDB_NAME, ONE_OPTION_SUPPORTED }
|
||||
};
|
||||
|
||||
static const struct supported_block_type dlt_blocks_supported[] = {
|
||||
{ WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED },
|
||||
{ WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported) },
|
||||
};
|
||||
|
||||
static const struct file_type_subtype_info dlt_info = {
|
||||
"AUTOSAR DLT Logfile", "dlt", "dlt", NULL,
|
||||
FALSE, BLOCKS_SUPPORTED(dlt_blocks_supported),
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
void register_autosar_dlt(void)
|
||||
{
|
||||
autosar_dlt_file_type_subtype = wtap_register_file_type_subtype(&dlt_info);
|
||||
|
||||
/*
|
||||
* Register name for backwards compatibility with the
|
||||
* wtap_filetypes table in Lua.
|
||||
*/
|
||||
wtap_register_backwards_compatibility_lua_name("DLT", autosar_dlt_file_type_subtype);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
|
@ -0,0 +1,39 @@
|
|||
/* autosar_dlt.h
|
||||
*
|
||||
* Wiretap Library
|
||||
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
|
||||
*
|
||||
* Support for DLT file format as defined by AUTOSAR et. al.
|
||||
* Copyright (c) 2022-2022 by Dr. Lars Voelker <lars.voelker@technica-engineering.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sources for specification:
|
||||
* https://www.autosar.org/fileadmin/user_upload/standards/classic/21-11/AUTOSAR_SWS_DiagnosticLogAndTrace.pdf
|
||||
* https://www.autosar.org/fileadmin/user_upload/standards/foundation/21-11/AUTOSAR_PRS_LogAndTraceProtocol.pdf
|
||||
* https://github.com/COVESA/dlt-viewer
|
||||
*/
|
||||
|
||||
#ifndef __W_AUTOSAR_DLT_H__
|
||||
#define __W_AUTOSAR_DLT_H__
|
||||
|
||||
#include "wtap.h"
|
||||
|
||||
wtap_open_return_val autosar_dlt_open(wtap *wth, int *err, gchar **err_info);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
|
@ -90,6 +90,7 @@
|
|||
#include "busmaster.h"
|
||||
#include "blf.h"
|
||||
#include "eri_enb_log.h"
|
||||
#include "autosar_dlt.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -161,6 +162,7 @@ static const struct file_extension_info file_type_extensions_base[] = {
|
|||
{ "Ixia IxVeriWave .vwr Raw 802.11 Capture", TRUE, "vwr" },
|
||||
{ "CAM Inspector file", TRUE, "camins" },
|
||||
{ "BLF file", TRUE, "blf" },
|
||||
{ "AUTOSAR DLT file", TRUE, "dlt" },
|
||||
{ "MPEG files", FALSE, "mpg;mp3" },
|
||||
{ "Transport-Neutral Encapsulation Format", FALSE, "tnef" },
|
||||
{ "JPEG/JFIF files", FALSE, "jpg;jpeg;jfif" },
|
||||
|
@ -388,6 +390,7 @@ static const struct open_info open_info_base[] = {
|
|||
/* Gammu DCT3 trace must come before MIME files as it's XML based*/
|
||||
{ "Gammu DCT3 trace", OPEN_INFO_MAGIC, dct3trace_open, NULL, NULL, NULL },
|
||||
{ "BLF Logfile", OPEN_INFO_MAGIC, blf_open, "blf", NULL, NULL },
|
||||
{ "AUTOSAR DLT Logfile", OPEN_INFO_MAGIC, autosar_dlt_open, "dlt", NULL, NULL },
|
||||
{ "MIME Files Format", OPEN_INFO_MAGIC, mime_file_open, NULL, NULL, NULL },
|
||||
{ "Micropross mplog", OPEN_INFO_MAGIC, mplog_open, "mplog", NULL, NULL },
|
||||
{ "Unigraf DPA-400 capture", OPEN_INFO_MAGIC, dpa400_open, "bin", NULL, NULL },
|
||||
|
|
|
@ -71,6 +71,7 @@ static const guint8 pcap_nsec_magic[] = { 0xA1, 0xB2, 0x3C, 0x4D };
|
|||
static const guint8 pcap_nsec_swapped_magic[] = { 0x4D, 0x3C, 0xB2, 0xA1 };
|
||||
static const guint8 pcapng_premagic[] = { 0x0A, 0x0D, 0x0D, 0x0A };
|
||||
static const guint8 blf_magic[] = { 'L', 'O', 'G', 'G' };
|
||||
static const guint8 autosar_dlt_magic[] = { 'D', 'L', 'T', 0x01 };
|
||||
|
||||
/* File does not start with it */
|
||||
static const guint8 pcapng_xmagic[] = { 0x1A, 0x2B, 0x3C, 0x4D };
|
||||
|
@ -91,7 +92,8 @@ static const mime_files_t magic_files[] = {
|
|||
{ pcap_nsec_magic, sizeof(pcap_nsec_magic) },
|
||||
{ pcap_nsec_swapped_magic, sizeof(pcap_nsec_swapped_magic) },
|
||||
{ pcapng_premagic, sizeof(pcapng_premagic) },
|
||||
{ blf_magic, sizeof(blf_magic) }
|
||||
{ blf_magic, sizeof(blf_magic) },
|
||||
{ autosar_dlt_magic, sizeof(autosar_dlt_magic) }
|
||||
};
|
||||
|
||||
#define N_MAGIC_TYPES (sizeof(magic_files) / sizeof(magic_files[0]))
|
||||
|
|
|
@ -1188,6 +1188,9 @@ static struct encap_type_info encap_table_base[] = {
|
|||
|
||||
/* WTAP_ENCAP_USB_2_0_HIGH_SPEED */
|
||||
{ "usb-20-high", "High-Speed USB 2.0 packets" },
|
||||
|
||||
/* WTAP_ENCAP_AUTOSAR_DLT */
|
||||
{ "autosardlt", "AUTOSAR DLT" },
|
||||
};
|
||||
|
||||
WS_DLL_LOCAL
|
||||
|
|
|
@ -293,6 +293,7 @@ extern "C" {
|
|||
#define WTAP_ENCAP_USB_2_0_LOW_SPEED 215
|
||||
#define WTAP_ENCAP_USB_2_0_FULL_SPEED 216
|
||||
#define WTAP_ENCAP_USB_2_0_HIGH_SPEED 217
|
||||
#define WTAP_ENCAP_AUTOSAR_DLT 218
|
||||
|
||||
/* After adding new item here, please also add new item to encap_table_base array */
|
||||
|
||||
|
|
Loading…
Reference in New Issue