Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/file-pcap.c
Line
Count
Source (jump to first uncovered line)
1
/* file-pcap.c
2
 * Routines for PCAP File Format
3
 * http://www.tcpdump.org/manpages/pcap-savefile.5.html
4
 *
5
 * Copyright 2015, Michal Labedzki for Tieto Corporation
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
#include "config.h"
15
16
#include <epan/packet.h>
17
#include <epan/prefs.h>
18
#include <epan/expert.h>
19
#include <epan/exceptions.h>
20
#include <epan/show_exception.h>
21
#include <wsutil/array.h>
22
23
#include "packet-pcap_pktdata.h"
24
25
static int proto_pcap;
26
27
static dissector_handle_t pcap_pktdata_handle;
28
29
static int hf_pcap_header;
30
static int hf_pcap_header_magic_number;
31
static int hf_pcap_header_version_major;
32
static int hf_pcap_header_version_minor;
33
static int hf_pcap_header_this_zone;
34
static int hf_pcap_header_sigfigs;
35
static int hf_pcap_header_snapshot_length;
36
static int hf_pcap_header_link_type;
37
static int hf_pcap_packet;
38
static int hf_pcap_packet_timestamp;
39
static int hf_pcap_packet_timestamp_sec;
40
static int hf_pcap_packet_timestamp_usec;
41
static int hf_pcap_packet_captured_length;
42
static int hf_pcap_packet_original_length;
43
static int hf_pcap_packet_data;
44
45
static expert_field ei_pcap_capt_larger_than_orig;
46
static expert_field ei_pcap_capt_larger_than_snap;
47
48
static int ett_pcap;
49
static int ett_pcap_header;
50
static int ett_pcap_packet;
51
static int ett_pcap_packet_data;
52
static int ett_pcap_timestamp;
53
54
static bool pref_dissect_next_layer;
55
56
void proto_register_file_pcap(void);
57
void proto_reg_handoff_file_pcap(void);
58
59
0
#define MAGIC_NUMBER_SIZE    4
60
61
static int
62
dissect_pcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
63
0
{
64
0
    static const uint8_t pcap_big_endian_magic[MAGIC_NUMBER_SIZE] = {
65
0
        0xa1, 0xb2, 0xc3, 0xd4
66
0
    };
67
0
    static const uint8_t pcap_little_endian_magic[MAGIC_NUMBER_SIZE] = {
68
0
        0xd4, 0xc3, 0xb2, 0xa1
69
0
    };
70
0
    static const uint8_t pcap_nsec_big_endian_magic[MAGIC_NUMBER_SIZE] = {
71
0
        0xa1, 0xb2, 0x3c, 0x4d
72
0
    };
73
0
    static const uint8_t pcap_nsec_little_endian_magic[MAGIC_NUMBER_SIZE] = {
74
0
        0x4d, 0x3c, 0xb2, 0xa1
75
0
    };
76
0
    volatile int     offset = 0;
77
0
    proto_tree      *main_tree;
78
0
    proto_item      *main_item;
79
0
    proto_tree      *header_tree;
80
0
    proto_item      *header_item;
81
0
    proto_item      *magic_number_item;
82
0
    proto_tree      *packet_tree;
83
0
    proto_item      *volatile packet_item;
84
0
    proto_tree      *timestamp_tree;
85
0
    proto_item      *timestamp_item;
86
0
    proto_tree      *packet_data_tree;
87
0
    proto_item      *packet_data_item;
88
0
    proto_item      *capt_len_item;
89
0
    volatile uint32_t encoding;
90
0
    volatile unsigned   timestamp_scale_factor;
91
0
    const char      *magic;
92
0
    uint32_t         snap_length;
93
0
    uint32_t         captured_length;
94
0
    uint32_t         original_length;
95
0
    uint32_t         link_type;
96
0
    volatile uint32_t frame_number = 1;
97
0
    nstime_t         timestamp;
98
99
0
    if (tvb_memeql(tvb, 0, pcap_big_endian_magic, MAGIC_NUMBER_SIZE) == 0) {
100
0
        encoding = ENC_BIG_ENDIAN;
101
0
        timestamp_scale_factor = 1000;
102
0
        magic = "Big-endian";
103
0
    } else if (tvb_memeql(tvb, 0, pcap_little_endian_magic, MAGIC_NUMBER_SIZE) == 0) {
104
0
        encoding = ENC_LITTLE_ENDIAN;
105
0
        timestamp_scale_factor = 1000;
106
0
        magic = "Little-endian";
107
0
    } else if (tvb_memeql(tvb, 0, pcap_nsec_big_endian_magic, MAGIC_NUMBER_SIZE) == 0) {
108
0
        encoding = ENC_BIG_ENDIAN;
109
0
        timestamp_scale_factor = 1;
110
0
        magic = "Big-endian, nanosecond resolution";
111
0
    } else if (tvb_memeql(tvb, 0, pcap_nsec_little_endian_magic, MAGIC_NUMBER_SIZE) == 0) {
112
0
        encoding = ENC_LITTLE_ENDIAN;
113
0
        timestamp_scale_factor = 1;
114
0
        magic = "Little-endian, nanosecond resolution";
115
0
    } else {
116
        /*
117
         * Not one of the magic numbers we recognize.
118
         * XXX - add them?
119
         */
120
0
        return 0;
121
0
    }
122
123
0
    main_item = proto_tree_add_item(tree, proto_pcap, tvb, offset, -1, ENC_NA);
124
0
    main_tree = proto_item_add_subtree(main_item, ett_pcap);
125
126
0
    header_item = proto_tree_add_item(main_tree, hf_pcap_header    , tvb, offset, 24, ENC_NA);
127
0
    header_tree = proto_item_add_subtree(header_item, ett_pcap_header);
128
129
0
    magic_number_item = proto_tree_add_item(header_tree, hf_pcap_header_magic_number, tvb, offset, 4, ENC_NA);
130
0
    proto_item_append_text(magic_number_item, " (%s)", magic);
131
0
    offset += 4;
132
133
0
    proto_tree_add_item(header_tree, hf_pcap_header_version_major, tvb, offset, 2, encoding);
134
0
    offset += 2;
135
136
0
    proto_tree_add_item(header_tree, hf_pcap_header_version_minor, tvb, offset, 2, encoding);
137
0
    offset += 2;
138
139
0
    proto_tree_add_item(header_tree, hf_pcap_header_this_zone, tvb, offset, 4, encoding);
140
0
    offset += 4;
141
142
0
    proto_tree_add_item(header_tree, hf_pcap_header_sigfigs, tvb, offset, 4, encoding);
143
0
    offset += 4;
144
145
0
    proto_tree_add_item_ret_uint(header_tree, hf_pcap_header_snapshot_length, tvb, offset, 4, encoding, &snap_length);
146
0
    offset += 4;
147
148
0
    proto_tree_add_item(header_tree, hf_pcap_header_link_type, tvb, offset, 4, encoding);
149
0
    link_type = tvb_get_uint32(tvb, offset, encoding);
150
0
    offset += 4;
151
152
0
    while (offset < (int) tvb_reported_length(tvb)) {
153
0
        packet_item = proto_tree_add_item(main_tree, hf_pcap_packet, tvb, offset, 4 * 4, ENC_NA);
154
0
        packet_tree = proto_item_add_subtree(packet_item, ett_pcap_packet);
155
0
        proto_item_append_text(packet_item, " %u", frame_number);
156
157
0
        timestamp.secs = tvb_get_uint32(tvb, offset, encoding);
158
0
        timestamp.nsecs = tvb_get_uint32(tvb, offset + 4, encoding) * timestamp_scale_factor;
159
160
0
        timestamp_item = proto_tree_add_time(packet_tree, hf_pcap_packet_timestamp, tvb, offset, 8, &timestamp);
161
0
        timestamp_tree = proto_item_add_subtree(timestamp_item, ett_pcap_timestamp);
162
163
0
        proto_tree_add_item(timestamp_tree, hf_pcap_packet_timestamp_sec, tvb, offset, 4, encoding);
164
0
        offset += 4;
165
166
0
        proto_tree_add_item(timestamp_tree, hf_pcap_packet_timestamp_usec, tvb, offset, 4, encoding);
167
0
        offset += 4;
168
169
0
        capt_len_item = proto_tree_add_item_ret_uint(packet_tree, hf_pcap_packet_captured_length, tvb, offset, 4, encoding, &captured_length);
170
0
        offset += 4;
171
172
0
        proto_tree_add_item_ret_uint(packet_tree, hf_pcap_packet_original_length, tvb, offset, 4, encoding, &original_length);
173
0
        offset += 4;
174
175
0
        if (captured_length > snap_length)
176
0
        {
177
0
            expert_add_info(pinfo, capt_len_item,
178
0
                    &ei_pcap_capt_larger_than_snap);
179
0
        }
180
181
0
        if (captured_length > original_length) {
182
0
            expert_add_info(pinfo, capt_len_item,
183
0
                    &ei_pcap_capt_larger_than_orig);
184
0
            break;
185
0
        }
186
187
0
        packet_data_item = proto_tree_add_item(packet_tree, hf_pcap_packet_data, tvb, offset, captured_length, ENC_NA);
188
0
        packet_data_tree = proto_item_add_subtree(packet_data_item, ett_pcap_packet_data);
189
190
0
        pinfo->num = frame_number;
191
0
        pinfo->abs_ts = timestamp;
192
193
0
        if (pref_dissect_next_layer) {
194
0
            TRY {
195
0
                call_dissector_with_data(pcap_pktdata_handle, tvb_new_subset_length_caplen(tvb, offset, captured_length, original_length), pinfo, packet_data_tree, &link_type);
196
0
            }
197
0
            CATCH_BOUNDS_ERRORS {
198
0
                show_exception(tvb, pinfo, packet_data_tree, EXCEPT_CODE, GET_MESSAGE);
199
0
            }
200
0
            ENDTRY;
201
0
        }
202
0
        offset += captured_length;
203
204
0
        proto_item_set_len(packet_item, 4 * 4 + captured_length);
205
0
        frame_number += 1;
206
0
    }
207
208
0
    return offset;
209
0
}
210
211
static bool
212
dissect_pcap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
213
0
{
214
0
    return dissect_pcap(tvb, pinfo, tree, data) > 0;
215
0
}
216
217
void
218
proto_register_file_pcap(void)
219
14
{
220
14
    module_t         *module;
221
14
    expert_module_t  *expert_pcap;
222
223
14
    static hf_register_info hf[] = {
224
14
        { &hf_pcap_header,
225
14
            { "Header",                                    "pcap.header",
226
14
            FT_NONE, BASE_NONE, NULL, 0x00,
227
14
            NULL, HFILL }
228
14
        },
229
14
        { &hf_pcap_header_magic_number,
230
14
            { "Magic Number",                              "pcap.header.magic_number",
231
14
            FT_BYTES, BASE_NONE, NULL, 0x00,
232
14
            NULL, HFILL }
233
14
        },
234
14
        { &hf_pcap_header_version_major,
235
14
            { "Version Major",                             "pcap.header.version.major",
236
14
            FT_UINT16, BASE_DEC, NULL, 0x00,
237
14
            NULL, HFILL }
238
14
        },
239
14
        { &hf_pcap_header_version_minor,
240
14
            { "Version Minor",                             "pcap.header.version.minor",
241
14
            FT_UINT16, BASE_DEC, NULL, 0x00,
242
14
            NULL, HFILL }
243
14
        },
244
14
        { &hf_pcap_header_this_zone,
245
14
            { "This Zone",                                 "pcap.header.this_zone",
246
14
            FT_INT32, BASE_DEC, NULL, 0x00,
247
14
            NULL, HFILL }
248
14
        },
249
14
        { &hf_pcap_header_sigfigs,
250
14
            { "Sigfigs",                                   "pcap.header.sigfigs",
251
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
252
14
            NULL, HFILL }
253
14
        },
254
14
        { &hf_pcap_header_snapshot_length,
255
14
            { "Snapshot Length",                           "pcap.header.snapshot_length",
256
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
257
14
            NULL, HFILL }
258
14
        },
259
14
        { &hf_pcap_header_link_type,
260
14
            { "Link Type",                                 "pcap.header.link_type",
261
14
            FT_UINT32, BASE_DEC_HEX, VALS(link_type_vals), 0x00,
262
14
            NULL, HFILL }
263
14
        },
264
14
        { &hf_pcap_packet,
265
14
            { "Packet",                                    "pcap.packet",
266
14
            FT_NONE, BASE_NONE, NULL, 0x00,
267
14
            NULL, HFILL }
268
14
        },
269
14
        { &hf_pcap_packet_timestamp,
270
14
            { "Timestamp",                             "pcap.packet.timestamp",
271
14
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
272
14
            NULL, HFILL }
273
14
        },
274
14
        { &hf_pcap_packet_timestamp_sec,
275
14
            { "Timestamp sec",                             "pcap.packet.timestamp.sec",
276
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
277
14
            NULL, HFILL }
278
14
        },
279
14
        { &hf_pcap_packet_timestamp_usec,
280
14
            { "Timestamp usec",                            "pcap.packet.timestamp.usec",
281
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
282
14
            NULL, HFILL }
283
14
        },
284
14
        { &hf_pcap_packet_captured_length,
285
14
            { "Captured Packet Length",                    "pcap.packet.captured_length",
286
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
287
14
            NULL, HFILL }
288
14
        },
289
14
        { &hf_pcap_packet_original_length,
290
14
            { "Original Packet Length",                    "pcap.packet.original_length",
291
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
292
14
            NULL, HFILL }
293
14
        },
294
14
        { &hf_pcap_packet_data,
295
14
            { "Data",                                      "pcap.packet.data",
296
14
            FT_NONE, BASE_NONE, NULL, 0x00,
297
14
            NULL, HFILL }
298
14
        },
299
14
    };
300
301
14
    static ei_register_info ei[] = {
302
14
        { &ei_pcap_capt_larger_than_orig,
303
14
            { "pcap.capt_len_larger_than_orig_len", PI_MALFORMED, PI_ERROR,
304
14
                "captured length is larger than original length",
305
14
                EXPFILL }},
306
14
        { &ei_pcap_capt_larger_than_snap,
307
14
            { "pcap.capt_len_larger_than_snap_len", PI_PROTOCOL, PI_WARN,
308
14
                "captured length is larger than snapshot length",
309
14
                EXPFILL }}
310
14
    };
311
312
14
    static int *ett[] = {
313
14
        &ett_pcap,
314
14
        &ett_pcap_header,
315
14
        &ett_pcap_packet,
316
14
        &ett_pcap_packet_data,
317
14
        &ett_pcap_timestamp
318
14
    };
319
320
14
    proto_pcap = proto_register_protocol("PCAP File Format", "File-PCAP", "file-pcap");
321
14
    proto_register_field_array(proto_pcap, hf, array_length(hf));
322
14
    proto_register_subtree_array(ett, array_length(ett));
323
14
    expert_pcap = expert_register_protocol(proto_pcap);
324
14
    expert_register_field_array(expert_pcap, ei, array_length(ei));
325
326
14
    register_dissector("file-pcap", dissect_pcap, proto_pcap);
327
328
14
    module = prefs_register_protocol(proto_pcap, NULL);
329
14
    prefs_register_static_text_preference(module, "version",
330
14
            "PCAP version: >=2.4",
331
14
            "Version of file-format supported by this dissector.");
332
333
14
    prefs_register_bool_preference(module, "dissect_next_layer",
334
14
            "Dissect next layer",
335
14
            "Dissect next layer",
336
14
            &pref_dissect_next_layer);
337
14
}
338
339
void
340
proto_reg_handoff_file_pcap(void)
341
14
{
342
14
    heur_dissector_add("wtap_file", dissect_pcap_heur, "PCAP File", "pcap_wtap", proto_pcap, HEURISTIC_ENABLE);
343
14
    pcap_pktdata_handle = find_dissector_add_dependency("pcap_pktdata", proto_pcap);
344
14
}
345
346
/*
347
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
348
 *
349
 * Local variables:
350
 * c-basic-offset: 4
351
 * tab-width: 8
352
 * indent-tabs-mode: nil
353
 * End:
354
 *
355
 * vi: set shiftwidth=4 tabstop=8 expandtab:
356
 * :indentSize=4:tabSize=8:noTabs=true:
357
 */