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 int64_t file_off
; /**< File offset */
35 frame_read(struct tvb_frame
*frame_tvb
, wtap_rec
*rec
, Buffer
*buf
)
41 /* XXX, what if phdr->caplen isn't equal to
42 * frame_tvb->tvb.length + frame_tvb->offset?
44 if (!wtap_seek_read(frame_tvb
->prov
->wth
, frame_tvb
->file_off
, rec
, buf
, &err
, &err_info
)) {
45 /* XXX - report error! */
47 case WTAP_ERR_BAD_FILE
:
56 static GPtrArray
*buffer_cache
;
59 frame_cache(struct tvb_frame
*frame_tvb
)
61 wtap_rec rec
; /* Record metadata */
65 if (frame_tvb
->buf
== NULL
) {
66 if (G_UNLIKELY(!buffer_cache
)) buffer_cache
= g_ptr_array_sized_new(1024);
68 if (buffer_cache
->len
> 0) {
69 frame_tvb
->buf
= (struct Buffer
*) g_ptr_array_remove_index(buffer_cache
, buffer_cache
->len
- 1);
71 frame_tvb
->buf
= g_new(struct Buffer
, 1);
74 ws_buffer_init(frame_tvb
->buf
, frame_tvb
->tvb
.length
+ frame_tvb
->offset
);
76 if (!frame_read(frame_tvb
, &rec
, frame_tvb
->buf
))
77 { /* TODO: THROW(???); */ }
80 frame_tvb
->tvb
.real_data
= ws_buffer_start_ptr(frame_tvb
->buf
) + frame_tvb
->offset
;
82 wtap_rec_cleanup(&rec
);
86 frame_free(tvbuff_t
*tvb
)
88 struct tvb_frame
*frame_tvb
= (struct tvb_frame
*) tvb
;
91 ws_buffer_free(frame_tvb
->buf
);
92 g_ptr_array_add(buffer_cache
, frame_tvb
->buf
);
96 static const uint8_t *
97 frame_get_ptr(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned abs_length _U_
)
99 struct tvb_frame
*frame_tvb
= (struct tvb_frame
*) tvb
;
101 frame_cache(frame_tvb
);
103 return tvb
->real_data
+ abs_offset
;
107 frame_memcpy(tvbuff_t
*tvb
, void *target
, unsigned abs_offset
, unsigned abs_length
)
109 struct tvb_frame
*frame_tvb
= (struct tvb_frame
*) tvb
;
111 frame_cache(frame_tvb
);
113 return memcpy(target
, tvb
->real_data
+ abs_offset
, abs_length
);
117 frame_find_uint8(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned limit
, uint8_t needle
)
119 struct tvb_frame
*frame_tvb
= (struct tvb_frame
*) tvb
;
120 const uint8_t *result
;
122 frame_cache(frame_tvb
);
124 result
= (const uint8_t *)memchr(tvb
->real_data
+ abs_offset
, needle
, limit
);
126 return (int) (result
- tvb
->real_data
);
132 frame_pbrk_uint8(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned limit
, const ws_mempbrk_pattern
* pattern
, unsigned char *found_needle
)
134 struct tvb_frame
*frame_tvb
= (struct tvb_frame
*) tvb
;
136 frame_cache(frame_tvb
);
138 return tvb_ws_mempbrk_pattern_uint8(tvb
, abs_offset
, limit
, pattern
, found_needle
);
142 frame_offset(const tvbuff_t
*tvb _U_
, const unsigned counter
)
144 /* XXX: frame_tvb->offset */
148 static tvbuff_t
*frame_clone(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned abs_length
);
150 static const struct tvb_ops tvb_frame_ops
= {
151 sizeof(struct tvb_frame
), /* size */
153 frame_free
, /* free */
154 frame_offset
, /* offset */
155 frame_get_ptr
, /* get_ptr */
156 frame_memcpy
, /* memcpy */
157 frame_find_uint8
, /* find_uint8 */
158 frame_pbrk_uint8
, /* pbrk_uint8 */
159 frame_clone
, /* clone */
162 /* based on tvb_new_real_data() */
164 frame_tvbuff_new(const struct packet_provider_data
*prov
, const frame_data
*fd
,
167 struct tvb_frame
*frame_tvb
;
170 tvb
= tvb_new(&tvb_frame_ops
);
173 * XXX - currently, the length arguments in
174 * tvbuff structure are signed, but the captured
175 * and reported length values are unsigned; this means
176 * that length values > 2^31 - 1 will appear as
179 * Captured length values that large will already
180 * have been filtered out by the Wiretap modules
181 * (the file will be reported as corrupted), to
182 * avoid trying to allocate large chunks of data.
184 * Reported length values will not have been
185 * filtered out, and should not be filtered out,
186 * as those lengths are not necessarily invalid.
188 * For now, we clip the reported length at INT_MAX
190 * (XXX, is this still a problem?) There was an exception when we call
191 * tvb_new_real_data() now there's no one
194 tvb
->real_data
= buf
;
195 tvb
->length
= fd
->cap_len
;
196 tvb
->reported_length
= fd
->pkt_len
> INT_MAX
? INT_MAX
: fd
->pkt_len
;
197 tvb
->contained_length
= tvb
->reported_length
;
198 tvb
->initialized
= true;
201 * This is the top-level real tvbuff for this data source,
202 * so its data source tvbuff is itself.
206 frame_tvb
= (struct tvb_frame
*) tvb
;
208 /* XXX, wtap_can_seek() */
209 if (prov
->wth
&& prov
->wth
->random_fh
) {
210 frame_tvb
->prov
= prov
;
211 frame_tvb
->file_off
= fd
->file_off
;
212 frame_tvb
->offset
= 0;
214 frame_tvb
->prov
= NULL
;
216 frame_tvb
->buf
= NULL
;
222 frame_tvbuff_new_buffer(const struct packet_provider_data
*prov
,
223 const frame_data
*fd
, Buffer
*buf
)
225 return frame_tvbuff_new(prov
, fd
, ws_buffer_start_ptr(buf
));
229 frame_clone(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned abs_length
)
231 struct tvb_frame
*frame_tvb
= (struct tvb_frame
*) tvb
;
233 tvbuff_t
*cloned_tvb
;
234 struct tvb_frame
*cloned_frame_tvb
;
236 /* file not seekable */
237 if (!frame_tvb
->prov
)
240 abs_offset
+= frame_tvb
->offset
;
242 cloned_tvb
= tvb_new(&tvb_frame_ops
);
244 /* data will be read when needed */
245 cloned_tvb
->real_data
= NULL
;
246 cloned_tvb
->length
= abs_length
;
247 cloned_tvb
->reported_length
= abs_length
; /* XXX? */
248 cloned_tvb
->contained_length
= cloned_tvb
->reported_length
;
249 cloned_tvb
->initialized
= true;
252 * This is the top-level real tvbuff for this data source,
253 * so its data source tvbuff is itself.
255 cloned_tvb
->ds_tvb
= cloned_tvb
;
257 cloned_frame_tvb
= (struct tvb_frame
*) cloned_tvb
;
258 cloned_frame_tvb
->prov
= frame_tvb
->prov
;
259 cloned_frame_tvb
->file_off
= frame_tvb
->file_off
;
260 cloned_frame_tvb
->offset
= abs_offset
;
261 cloned_frame_tvb
->buf
= NULL
;
267 /* based on tvb_new_real_data() */
269 file_tvbuff_new(const struct packet_provider_data
*prov
, const frame_data
*fd
,
272 struct tvb_frame
*frame_tvb
;
275 tvb
= tvb_new(&tvb_frame_ops
);
278 * XXX - currently, the length arguments in
279 * tvbuff structure are signed, but the captured
280 * and reported length values are unsigned; this means
281 * that length values > 2^31 - 1 will appear as
284 * Captured length values that large will already
285 * have been filtered out by the Wiretap modules
286 * (the file will be reported as corrupted), to
287 * avoid trying to allocate large chunks of data.
289 * Reported length values will not have been
290 * filtered out, and should not be filtered out,
291 * as those lengths are not necessarily invalid.
293 * For now, we clip the reported length at INT_MAX
295 * (XXX, is this still a problem?) There was an exception when we call
296 * tvb_new_real_data() now there's no one
299 tvb
->real_data
= buf
;
300 tvb
->length
= fd
->cap_len
;
301 tvb
->reported_length
= fd
->pkt_len
> INT_MAX
? INT_MAX
: fd
->pkt_len
;
302 tvb
->contained_length
= tvb
->reported_length
;
303 tvb
->initialized
= true;
306 * This is the top-level real tvbuff for this data source,
307 * so its data source tvbuff is itself.
311 frame_tvb
= (struct tvb_frame
*) tvb
;
313 /* XXX, wtap_can_seek() */
314 if (prov
->wth
&& prov
->wth
->random_fh
) {
315 frame_tvb
->prov
= prov
;
316 frame_tvb
->file_off
= fd
->file_off
;
317 frame_tvb
->offset
= 0;
319 frame_tvb
->prov
= NULL
;
321 frame_tvb
->buf
= NULL
;
327 file_tvbuff_new_buffer(const struct packet_provider_data
*prov
,
328 const frame_data
*fd
, Buffer
*buf
)
330 return frame_tvbuff_new(prov
, fd
, ws_buffer_start_ptr(buf
));