summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/file-dlt.c
blob: 3b03e3520fe95caebe2244ef25755d24c72f62bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* 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/standards/classic/21-11/AUTOSAR_SWS_DiagnosticLogAndTrace.pdf
  * https://www.autosar.org/fileadmin/standards/foundation/1-3/AUTOSAR_PRS_LogAndTraceProtocol.pdf
  * https://github.com/COVESA/dlt-viewer
  */

#include "config.h"

#include <epan/packet.h>
#include <epan/prefs.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:
 */