2 * Implements a tvbuff for frame
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/tvbuff-int.h>
17 #include <epan/tvbuff.h>
19 #include "frame_tvbuff.h"
21 #include "wiretap/wtap-int.h" /* for ->random_fh */
26 Buffer *buf; /* Packet data */
28 const struct packet_provider_data *prov; /* provider of packet information */
29 gint64 file_off; /**< File offset */
35 frame_read(struct tvb_frame *frame_tvb, wtap_rec *rec, Buffer *buf)
40 /* XXX, what if phdr->caplen isn't equal to
41 * frame_tvb->tvb.length + frame_tvb->offset?
43 if (!wtap_seek_read(frame_tvb->prov->wth, frame_tvb->file_off, rec, buf, &err, &err_info)) {
44 /* XXX - report error! */
46 case WTAP_ERR_BAD_FILE:
55 static GPtrArray *buffer_cache = NULL;
58 frame_cache(struct tvb_frame *frame_tvb)
60 wtap_rec rec; /* Record metadata */
64 if (frame_tvb->buf == NULL) {
65 if (G_UNLIKELY(!buffer_cache)) buffer_cache = g_ptr_array_sized_new(1024);
67 if (buffer_cache->len > 0) {
68 frame_tvb->buf = (struct Buffer *) g_ptr_array_remove_index(buffer_cache, buffer_cache->len - 1);
70 frame_tvb->buf = (struct Buffer *) g_malloc(sizeof(struct Buffer));
73 ws_buffer_init(frame_tvb->buf, frame_tvb->tvb.length + frame_tvb->offset);
75 if (!frame_read(frame_tvb, &rec, frame_tvb->buf))
76 { /* TODO: THROW(???); */ }
79 frame_tvb->tvb.real_data = ws_buffer_start_ptr(frame_tvb->buf) + frame_tvb->offset;
81 wtap_rec_cleanup(&rec);
85 frame_free(tvbuff_t *tvb)
87 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
90 ws_buffer_free(frame_tvb->buf);
91 g_ptr_array_add(buffer_cache, frame_tvb->buf);
96 frame_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length _U_)
98 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
100 frame_cache(frame_tvb);
102 return tvb->real_data + abs_offset;
106 frame_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
108 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
110 frame_cache(frame_tvb);
112 return memcpy(target, tvb->real_data + abs_offset, abs_length);
116 frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
118 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
119 const guint8 *result;
121 frame_cache(frame_tvb);
123 result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit);
125 return (gint) (result - tvb->real_data);
131 frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
133 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
135 frame_cache(frame_tvb);
137 return tvb_ws_mempbrk_pattern_guint8(tvb, abs_offset, limit, pattern, found_needle);
141 frame_offset(const tvbuff_t *tvb _U_, const guint counter)
143 /* XXX: frame_tvb->offset */
147 static tvbuff_t *frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length);
149 static const struct tvb_ops tvb_frame_ops = {
150 sizeof(struct tvb_frame), /* size */
152 frame_free, /* free */
153 frame_offset, /* offset */
154 frame_get_ptr, /* get_ptr */
155 frame_memcpy, /* memcpy */
156 frame_find_guint8, /* find_guint8 */
157 frame_pbrk_guint8, /* pbrk_guint8 */
158 frame_clone, /* clone */
161 /* based on tvb_new_real_data() */
163 frame_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd,
166 struct tvb_frame *frame_tvb;
169 tvb = tvb_new(&tvb_frame_ops);
172 * XXX - currently, the length arguments in
173 * tvbuff structure are signed, but the captured
174 * and reported length values are unsigned; this means
175 * that length values > 2^31 - 1 will appear as
178 * Captured length values that large will already
179 * have been filtered out by the Wiretap modules
180 * (the file will be reported as corrupted), to
181 * avoid trying to allocate large chunks of data.
183 * Reported length values will not have been
184 * filtered out, and should not be filtered out,
185 * as those lengths are not necessarily invalid.
187 * For now, we clip the reported length at G_MAXINT
189 * (XXX, is this still a problem?) There was an exception when we call
190 * tvb_new_real_data() now there's no one
193 tvb->real_data = buf;
194 tvb->length = fd->cap_len;
195 tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
196 tvb->contained_length = tvb->reported_length;
197 tvb->initialized = TRUE;
200 * This is the top-level real tvbuff for this data source,
201 * so its data source tvbuff is itself.
205 frame_tvb = (struct tvb_frame *) tvb;
207 /* XXX, wtap_can_seek() */
208 if (prov->wth && prov->wth->random_fh) {
209 frame_tvb->prov = prov;
210 frame_tvb->file_off = fd->file_off;
211 frame_tvb->offset = 0;
213 frame_tvb->prov = NULL;
215 frame_tvb->buf = NULL;
221 frame_tvbuff_new_buffer(const struct packet_provider_data *prov,
222 const frame_data *fd, Buffer *buf)
224 return frame_tvbuff_new(prov, fd, ws_buffer_start_ptr(buf));
228 frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
230 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
232 tvbuff_t *cloned_tvb;
233 struct tvb_frame *cloned_frame_tvb;
235 /* file not seekable */
236 if (!frame_tvb->prov)
239 abs_offset += frame_tvb->offset;
241 cloned_tvb = tvb_new(&tvb_frame_ops);
243 /* data will be read when needed */
244 cloned_tvb->real_data = NULL;
245 cloned_tvb->length = abs_length;
246 cloned_tvb->reported_length = abs_length; /* XXX? */
247 cloned_tvb->contained_length = cloned_tvb->reported_length;
248 cloned_tvb->initialized = TRUE;
251 * This is the top-level real tvbuff for this data source,
252 * so its data source tvbuff is itself.
254 cloned_tvb->ds_tvb = cloned_tvb;
256 cloned_frame_tvb = (struct tvb_frame *) cloned_tvb;
257 cloned_frame_tvb->prov = frame_tvb->prov;
258 cloned_frame_tvb->file_off = frame_tvb->file_off;
259 cloned_frame_tvb->offset = abs_offset;
260 cloned_frame_tvb->buf = NULL;
266 /* based on tvb_new_real_data() */
268 file_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd,
271 struct tvb_frame *frame_tvb;
274 tvb = tvb_new(&tvb_frame_ops);
277 * XXX - currently, the length arguments in
278 * tvbuff structure are signed, but the captured
279 * and reported length values are unsigned; this means
280 * that length values > 2^31 - 1 will appear as
283 * Captured length values that large will already
284 * have been filtered out by the Wiretap modules
285 * (the file will be reported as corrupted), to
286 * avoid trying to allocate large chunks of data.
288 * Reported length values will not have been
289 * filtered out, and should not be filtered out,
290 * as those lengths are not necessarily invalid.
292 * For now, we clip the reported length at G_MAXINT
294 * (XXX, is this still a problem?) There was an exception when we call
295 * tvb_new_real_data() now there's no one
298 tvb->real_data = buf;
299 tvb->length = fd->cap_len;
300 tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
301 tvb->contained_length = tvb->reported_length;
302 tvb->initialized = TRUE;
305 * This is the top-level real tvbuff for this data source,
306 * so its data source tvbuff is itself.
310 frame_tvb = (struct tvb_frame *) tvb;
312 /* XXX, wtap_can_seek() */
313 if (prov->wth && prov->wth->random_fh) {
314 frame_tvb->prov = prov;
315 frame_tvb->file_off = fd->file_off;
316 frame_tvb->offset = 0;
318 frame_tvb->prov = NULL;
320 frame_tvb->buf = NULL;
326 file_tvbuff_new_buffer(const struct packet_provider_data *prov,
327 const frame_data *fd, Buffer *buf)
329 return frame_tvbuff_new(prov, fd, ws_buffer_start_ptr(buf));
333 * Editor modelines - http://www.wireshark.org/tools/modelines.html
338 * indent-tabs-mode: t
341 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
342 * :indentSize=8:tabSize=8:noTabs=false: