dcerpc-netlogon: all netr_LogonControl[2[Ex]] calls have the same reply values
[wireshark-sm.git] / plugins / wiretap / usbdump / usbdump.c
blobc5c7ffa6c72caf9bfd93420558357280bdd44015
1 /* usbdump.c
3 * Wiretap Library
4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * File format support for usbdump file format
7 * Copyright (c) 2017 by Jaap Keuter <jaap.keuter@xs4all.nl>
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * This wiretap is for an usbdump file format reader. The format is
14 * reverse engineered from FreeBSD source code.
16 * File format is little endian!
18 * Header
19 * ---------------------------------
20 * 0E 00 90 9A header magic
21 * 00 version major
22 * 03 version minor
23 * 00 00 00 00 00 00 00 00 reserved
24 * 00 00 00 00 00 00 00 00
25 * 00 00 00 00 00 00 00 00
26 * 00 00
28 * Frames
29 * ---------------------------------
30 * F0 26 00 00 length of multiframe read from bpf (9968 octets)
32 * Frame, bpf header (little endian)
33 * ---------------------------------
34 * DE 3F 0E 59 ts sec
35 * 6A 77 01 00 ts usec
36 * 98 00 00 00 capture length (152)
37 * 98 00 00 00 data length (152)
38 * 1C header length (28)
39 * 04 bpf word alignment size
40 * 00 00 00 00 00 00 00 00 padding
41 * 00 00
43 * Frame, captured data
44 * ---------------------------------
45 * 98 00 00 00 00 00 00 00 length, ....
49 #include "config.h"
50 #include "wtap-int.h"
51 #include "file_wrappers.h"
52 #include "string.h"
54 void wtap_register_usbdump(void);
56 #define USBDUMP_MAGIC 0x9a90000e
58 /* Private data needed to read the file initially. */
59 typedef struct {
60 uint16_t version;
61 uint32_t multiframe_size;
62 bool multiframe_overrun;
63 } usbdump_info_t;
66 static bool usbdump_read(wtap *wth, wtap_rec *rec, Buffer *buf,
67 int *err, char **err_info,
68 int64_t *data_offset);
69 static bool usbdump_seek_read(wtap *wth, int64_t seek_off,
70 wtap_rec *rec, Buffer *buf,
71 int *err, char **err_info);
72 static bool usbdump_read_packet(wtap *wth, FILE_T fh,
73 wtap_rec *rec, Buffer *buf,
74 int *err, char **err_info);
76 static int usbdump_file_type_subtype;
79 * Try to interpret a file as a usbdump formatted file.
80 * Read relevant parts of the given file and collect information needed to
81 * read the individual frames. Return value indicates whether or not this is
82 * recognized as an usbdump file.
84 static wtap_open_return_val
85 usbdump_open(wtap *wth, int *err, char **err_info)
87 uint32_t magic;
88 uint16_t version;
89 uint32_t multiframe_size;
90 usbdump_info_t *usbdump_info;
92 /* Read in the number that should be at the start of a "usbdump" file */
93 if (!wtap_read_bytes(wth->fh, &magic, sizeof magic, err, err_info)) {
94 if (*err != WTAP_ERR_SHORT_READ)
95 return WTAP_OPEN_ERROR;
96 return WTAP_OPEN_NOT_MINE;
99 /* Check the file magic */
100 if (GUINT32_FROM_LE(magic) != USBDUMP_MAGIC)
102 return WTAP_OPEN_NOT_MINE;
105 /* Read the version of the header */
106 if (!wtap_read_bytes(wth->fh, &version, sizeof version, err, err_info)) {
107 if (*err != WTAP_ERR_SHORT_READ)
108 return WTAP_OPEN_ERROR;
109 return WTAP_OPEN_NOT_MINE;
112 /* Check for the supported version number */
113 if (GUINT16_FROM_BE(version) != 3) {
114 /* We only support version 0.3 */
115 *err = WTAP_ERR_UNSUPPORTED;
116 *err_info = ws_strdup_printf("usbdump: version %u.%u unsupported",
117 version >> 8, version & 0xff);
118 return WTAP_OPEN_NOT_MINE;
121 /* Read the reserved field of the header */
122 if (!wtap_read_bytes(wth->fh, NULL, 26, err, err_info)) {
123 if (*err != WTAP_ERR_SHORT_READ)
124 return WTAP_OPEN_ERROR;
125 return WTAP_OPEN_NOT_MINE;
128 /* Read the initial multiframe size field */
129 if (!wtap_read_bytes(wth->fh, &multiframe_size, sizeof multiframe_size,
130 err, err_info)) {
131 if (*err != WTAP_ERR_SHORT_READ)
132 return WTAP_OPEN_ERROR;
133 return WTAP_OPEN_NOT_MINE;
136 /* Create a private structure to track the multiframe */
137 usbdump_info = g_new(usbdump_info_t, 1);
138 usbdump_info->version = GUINT16_FROM_BE(version);
139 usbdump_info->multiframe_size = GUINT32_FROM_LE(multiframe_size);
140 usbdump_info->multiframe_overrun = false;
143 * We are convinced this is a usbdump format file.
144 * Setup the wiretap structure and fill it with info of this format.
146 wth->priv = (void *)usbdump_info;
147 wth->subtype_read = usbdump_read;
148 wth->subtype_seek_read = usbdump_seek_read;
149 wth->file_type_subtype = usbdump_file_type_subtype;
150 wth->file_encap = WTAP_ENCAP_USB_FREEBSD;
151 wth->file_tsprec = WTAP_TSPREC_USEC;
153 return WTAP_OPEN_MINE;
157 * Sequential read with offset reporting.
158 * Read the next frame in the file and adjust for the multiframe size
159 * indication. Report back where reading of this frame started to
160 * support subsequent random access read.
162 static bool
163 usbdump_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, char **err_info,
164 int64_t *data_offset)
166 usbdump_info_t *usbdump_info = (usbdump_info_t *)wth->priv;
168 /* Report the current file location */
169 *data_offset = file_tell(wth->fh);
171 /* Try to read a packet worth of data */
172 if (!usbdump_read_packet(wth, wth->fh, rec, buf, err, err_info))
173 return false;
175 /* Check if we overrun the multiframe during the last read */
176 if (usbdump_info->multiframe_overrun)
178 *err = WTAP_ERR_BAD_FILE;
179 *err_info = ws_strdup_printf("Multiframe overrun");
180 return false;
183 /* See if we reached the end of the multiframe */
184 if (usbdump_info->multiframe_size == 0)
187 * Try to read the subsequent multiframe size field.
188 * This will fail at end of file, but that is accepted.
190 wtap_read_bytes_or_eof(wth->fh, &usbdump_info->multiframe_size,
191 sizeof usbdump_info->multiframe_size,
192 err, err_info);
195 return true;
199 * Random access read.
200 * Read the frame at the given offset in the file. Store the frame data
201 * in a buffer and fill in the packet header info.
203 static bool
204 usbdump_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec,
205 Buffer *buf, int *err, char **err_info)
207 /* Seek to the desired file position at the start of the frame */
208 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
209 return false;
211 /* Try to read a packet worth of data */
212 if (!usbdump_read_packet(wth, wth->random_fh, rec, buf, err, err_info)) {
213 if (*err == 0)
214 *err = WTAP_ERR_SHORT_READ;
215 return false;
218 return true;
222 * Read the actual frame data from the file.
223 * This requires reading the header, determine the size, read frame size worth
224 * of data into the buffer and setting the packet header fields to the values
225 * of the frame header.
227 * Also, for the sequential read, keep track of the position in the multiframe
228 * so that we can find the next multiframe size field.
230 static bool
231 usbdump_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf,
232 int *err, char **err_info)
234 usbdump_info_t *usbdump_info = (usbdump_info_t *)wth->priv;
236 uint8_t bpf_hdr[18];
237 uint8_t bpf_hdr_len, alignment;
239 /* Read the packet header */
240 if (!wtap_read_bytes_or_eof(fh, bpf_hdr, 18, err, err_info))
241 return false;
243 /* Get sizes */
244 bpf_hdr_len = bpf_hdr[16];
245 alignment = bpf_hdr[17];
247 /* Check header length */
248 if (bpf_hdr_len > 18)
250 /* Read packet header padding */
251 if (!wtap_read_bytes_or_eof(fh, NULL, bpf_hdr_len - 18, err, err_info))
252 return false;
255 /* Keep track of multiframe_size and detect overrun */
256 if (usbdump_info->multiframe_size < bpf_hdr_len) {
257 usbdump_info->multiframe_overrun = true;
258 } else {
259 usbdump_info->multiframe_size -= bpf_hdr_len;
262 /* Setup the per packet structure and fill it with info from this frame */
263 rec->rec_type = REC_TYPE_PACKET;
264 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
265 rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_CAP_LEN;
266 rec->ts.secs = (uint32_t)bpf_hdr[3] << 24 | (uint32_t)bpf_hdr[2] << 16 |
267 (uint32_t)bpf_hdr[1] << 8 | (uint32_t)bpf_hdr[0];
268 rec->ts.nsecs = ((uint32_t)bpf_hdr[7] << 24 | (uint32_t)bpf_hdr[6] << 16 |
269 (uint32_t)bpf_hdr[5] << 8 | (uint32_t)bpf_hdr[4]) * 1000;
270 rec->rec_header.packet_header.caplen = (uint32_t)bpf_hdr[11] << 24 | (uint32_t)bpf_hdr[10] << 16 |
271 (uint32_t)bpf_hdr[9] << 8 | (uint32_t)bpf_hdr[8];
272 rec->rec_header.packet_header.len = (uint32_t)bpf_hdr[15] << 24 | (uint32_t)bpf_hdr[14] << 16 |
273 (uint32_t)bpf_hdr[13] << 8 | (uint32_t)bpf_hdr[12];
275 /* Read the packet data */
276 if (!wtap_read_packet_bytes(fh, buf, rec->rec_header.packet_header.caplen, err, err_info))
277 return false;
279 /* Keep track of multiframe_size and detect overrun */
280 if (usbdump_info->multiframe_size < rec->rec_header.packet_header.caplen) {
281 usbdump_info->multiframe_overrun = true;
282 } else {
283 usbdump_info->multiframe_size -= rec->rec_header.packet_header.caplen;
286 /* Check for and apply alignment as defined in the frame header */
287 uint8_t pad_len = (uint32_t)alignment -
288 (((uint32_t)bpf_hdr_len + rec->rec_header.packet_header.caplen) &
289 ((uint32_t)alignment - 1));
290 if (pad_len < alignment) {
291 /* Read alignment from the file */
292 if (!wtap_read_bytes(fh, NULL, pad_len, err, err_info))
293 return false;
295 /* Keep track of multiframe_size and detect overrun */
296 if (usbdump_info->multiframe_size < pad_len) {
297 usbdump_info->multiframe_overrun = true;
298 } else {
299 usbdump_info->multiframe_size -= pad_len;
303 return true;
307 * Register with wiretap.
308 * Register how we can handle an unknown file to see if this is a valid
309 * usbdump file and register information about this file format.
311 static const struct supported_block_type usbdump_blocks_supported[] = {
312 /* We support packet blocks, with no comments or other options. */
313 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
315 static const struct file_type_subtype_info fi = {
316 "FreeBSD USBDUMP",
317 "usbdump",
318 NULL,
319 NULL,
320 false,
321 BLOCKS_SUPPORTED(usbdump_blocks_supported),
322 NULL,
323 NULL,
324 NULL
327 void
328 wtap_register_usbdump(void)
330 struct open_info oi = {
331 "FreeBSD usbdump",
332 OPEN_INFO_MAGIC,
333 usbdump_open,
334 NULL,
335 NULL,
336 NULL
339 wtap_register_open_info(&oi, false);
341 usbdump_file_type_subtype = wtap_register_file_type_subtype(&fi);
345 * Editor modelines - https://www.wireshark.org/tools/modelines.html
347 * Local variables:
348 * c-basic-offset: 4
349 * tab-width: 8
350 * indent-tabs-mode: nil
351 * End:
353 * vi: set shiftwidth=4 tabstop=8 expandtab:
354 * :indentSize=4:tabSize=8:noTabs=true: