/src/wireshark/wiretap/hcidump.c
Line | Count | Source |
1 | | /* hcidump.c |
2 | | * |
3 | | * Copyright (c) 2003 by Marcel Holtmann <marcel@holtmann.org> |
4 | | * |
5 | | * SPDX-License-Identifier: GPL-2.0-or-later |
6 | | */ |
7 | | |
8 | | #include "config.h" |
9 | | #include "hcidump.h" |
10 | | |
11 | | #include "wtap_module.h" |
12 | | #include "file_wrappers.h" |
13 | | |
14 | | static int hcidump_file_type_subtype = -1; |
15 | | |
16 | | void register_hcidump(void); |
17 | | |
18 | | struct dump_hdr { |
19 | | uint16_t len; |
20 | | uint8_t in; |
21 | | uint8_t pad; |
22 | | uint32_t ts_sec; |
23 | | uint32_t ts_usec; |
24 | | }; |
25 | | |
26 | 0 | #define DUMP_HDR_SIZE (sizeof(struct dump_hdr)) |
27 | | |
28 | | static bool hcidump_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec, |
29 | | int *err, char **err_info) |
30 | 0 | { |
31 | 0 | struct dump_hdr dh; |
32 | 0 | unsigned packet_size; |
33 | |
|
34 | 0 | if (!wtap_read_bytes_or_eof(fh, &dh, DUMP_HDR_SIZE, err, err_info)) |
35 | 0 | return false; |
36 | | |
37 | 0 | packet_size = GUINT16_FROM_LE(dh.len); |
38 | 0 | if (packet_size > WTAP_MAX_PACKET_SIZE_STANDARD) { |
39 | | /* |
40 | | * Probably a corrupt capture file; don't blow up trying |
41 | | * to allocate space for an immensely-large packet. |
42 | | */ |
43 | 0 | *err = WTAP_ERR_BAD_FILE; |
44 | 0 | *err_info = ws_strdup_printf("hcidump: File has %u-byte packet, bigger than maximum of %u", |
45 | 0 | packet_size, WTAP_MAX_PACKET_SIZE_STANDARD); |
46 | 0 | return false; |
47 | 0 | } |
48 | | |
49 | 0 | wtap_setup_packet_rec(rec, wth->file_encap); |
50 | 0 | rec->block = wtap_block_create(WTAP_BLOCK_PACKET); |
51 | 0 | rec->presence_flags = WTAP_HAS_TS; |
52 | 0 | rec->ts.secs = GUINT32_FROM_LE(dh.ts_sec); |
53 | 0 | rec->ts.nsecs = GUINT32_FROM_LE(dh.ts_usec) * 1000; |
54 | 0 | rec->rec_header.packet_header.caplen = packet_size; |
55 | 0 | rec->rec_header.packet_header.len = packet_size; |
56 | |
|
57 | 0 | rec->rec_header.packet_header.pseudo_header.p2p.sent = (dh.in ? false : true); |
58 | |
|
59 | 0 | return wtap_read_bytes_buffer(fh, &rec->data, packet_size, err, err_info); |
60 | 0 | } |
61 | | |
62 | | static bool hcidump_read(wtap *wth, wtap_rec *rec, |
63 | | int *err, char **err_info, int64_t *data_offset) |
64 | 0 | { |
65 | 0 | *data_offset = file_tell(wth->fh); |
66 | |
|
67 | 0 | return hcidump_read_packet(wth, wth->fh, rec, err, err_info); |
68 | 0 | } |
69 | | |
70 | | static bool hcidump_seek_read(wtap *wth, int64_t seek_off, |
71 | | wtap_rec *rec, int *err, char **err_info) |
72 | 0 | { |
73 | 0 | if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) |
74 | 0 | return false; |
75 | | |
76 | 0 | return hcidump_read_packet(wth, wth->random_fh, rec, err, err_info); |
77 | 0 | } |
78 | | |
79 | | wtap_open_return_val hcidump_open(wtap *wth, int *err, char **err_info) |
80 | 0 | { |
81 | 0 | struct dump_hdr dh; |
82 | 0 | uint8_t type; |
83 | |
|
84 | 0 | if (!wtap_read_bytes(wth->fh, &dh, DUMP_HDR_SIZE, err, err_info)) { |
85 | 0 | if (*err != WTAP_ERR_SHORT_READ) |
86 | 0 | return WTAP_OPEN_ERROR; |
87 | 0 | return WTAP_OPEN_NOT_MINE; |
88 | 0 | } |
89 | | |
90 | 0 | if ((dh.in != 0 && dh.in != 1) || dh.pad != 0 |
91 | 0 | || GUINT16_FROM_LE(dh.len) < 1) |
92 | 0 | return WTAP_OPEN_NOT_MINE; |
93 | | |
94 | 0 | if (!wtap_read_bytes(wth->fh, &type, 1, err, err_info)) { |
95 | 0 | if (*err != WTAP_ERR_SHORT_READ) |
96 | 0 | return WTAP_OPEN_ERROR; |
97 | 0 | return WTAP_OPEN_NOT_MINE; |
98 | 0 | } |
99 | | |
100 | 0 | if (type < 1 || type > 4) |
101 | 0 | return WTAP_OPEN_NOT_MINE; |
102 | | |
103 | 0 | if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) |
104 | 0 | return WTAP_OPEN_ERROR; |
105 | | |
106 | 0 | wth->file_type_subtype = hcidump_file_type_subtype; |
107 | 0 | wth->file_encap = WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR; |
108 | 0 | wth->snapshot_length = 0; |
109 | |
|
110 | 0 | wth->subtype_read = hcidump_read; |
111 | 0 | wth->subtype_seek_read = hcidump_seek_read; |
112 | 0 | wth->file_tsprec = WTAP_TSPREC_USEC; |
113 | | |
114 | | /* |
115 | | * Add an IDB; we don't know how many interfaces were |
116 | | * involved, so we just say one interface, about which |
117 | | * we only know the link-layer type, snapshot length, |
118 | | * and time stamp resolution. |
119 | | */ |
120 | 0 | wtap_add_generated_idb(wth); |
121 | |
|
122 | 0 | return WTAP_OPEN_MINE; |
123 | 0 | } |
124 | | |
125 | | static const struct supported_block_type hcidummp_blocks_supported[] = { |
126 | | /* |
127 | | * We support packet blocks, with no comments or other options. |
128 | | */ |
129 | | { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED } |
130 | | }; |
131 | | |
132 | | static const struct file_type_subtype_info hcidump_info = { |
133 | | "Bluetooth HCI dump", "hcidump", NULL, NULL, |
134 | | false, BLOCKS_SUPPORTED(hcidummp_blocks_supported), |
135 | | NULL, NULL, NULL |
136 | | }; |
137 | | |
138 | | void register_hcidump(void) |
139 | 16 | { |
140 | 16 | hcidump_file_type_subtype = wtap_register_file_type_subtype(&hcidump_info); |
141 | | |
142 | | /* |
143 | | * Register name for backwards compatibility with the |
144 | | * wtap_filetypes table in Lua. |
145 | | */ |
146 | 16 | wtap_register_backwards_compatibility_lua_name("HCIDUMP", |
147 | 16 | hcidump_file_type_subtype); |
148 | 16 | } |
149 | | |
150 | | /* |
151 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
152 | | * |
153 | | * Local variables: |
154 | | * c-basic-offset: 8 |
155 | | * tab-width: 8 |
156 | | * indent-tabs-mode: t |
157 | | * End: |
158 | | * |
159 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
160 | | * :indentSize=8:tabSize=8:noTabs=false: |
161 | | */ |