2 * Implements a tvbuff for frame
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <epan/packet.h>
28 #include <epan/tvbuff-int.h>
29 #include <epan/tvbuff.h>
31 #include "frame_tvbuff.h"
34 #include "wiretap/wtap-int.h" /* for ->random_fh */
39 Buffer *buf; /* Packet data */
41 wtap *wth; /**< Wiretap session */
42 gint64 file_off; /**< File offset */
48 frame_read(struct tvb_frame *frame_tvb, struct wtap_pkthdr *phdr, Buffer *buf)
53 /* sanity check, capture file was closed? */
54 if (cfile.wth != frame_tvb->wth)
57 /* XXX, what if phdr->caplen isn't equal to
58 * frame_tvb->tvb.length + frame_tvb->offset?
60 if (!wtap_seek_read(frame_tvb->wth, frame_tvb->file_off, phdr, buf, &err, &err_info)) {
61 /* XXX - report error! */
63 case WTAP_ERR_BAD_FILE:
72 static GPtrArray *buffer_cache = NULL;
75 frame_cache(struct tvb_frame *frame_tvb)
77 struct wtap_pkthdr phdr; /* Packet header */
79 wtap_phdr_init(&phdr);
81 if (frame_tvb->buf == NULL) {
82 if G_UNLIKELY(!buffer_cache) buffer_cache = g_ptr_array_sized_new(1024);
84 if (buffer_cache->len > 0) {
85 frame_tvb->buf = (struct Buffer *) g_ptr_array_remove_index(buffer_cache, buffer_cache->len - 1);
87 frame_tvb->buf = (struct Buffer *) g_malloc(sizeof(struct Buffer));
90 ws_buffer_init(frame_tvb->buf, frame_tvb->tvb.length + frame_tvb->offset);
92 if (!frame_read(frame_tvb, &phdr, frame_tvb->buf))
93 { /* TODO: THROW(???); */ }
96 frame_tvb->tvb.real_data = ws_buffer_start_ptr(frame_tvb->buf) + frame_tvb->offset;
98 wtap_phdr_cleanup(&phdr);
102 frame_free(tvbuff_t *tvb)
104 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
106 if (frame_tvb->buf) {
107 ws_buffer_free(frame_tvb->buf);
108 g_ptr_array_add(buffer_cache, frame_tvb->buf);
112 static const guint8 *
113 frame_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length _U_)
115 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
117 frame_cache(frame_tvb);
119 return tvb->real_data + abs_offset;
123 frame_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
125 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
127 frame_cache(frame_tvb);
129 return memcpy(target, tvb->real_data + abs_offset, abs_length);
133 frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
135 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
136 const guint8 *result;
138 frame_cache(frame_tvb);
140 result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit);
142 return (gint) (result - tvb->real_data);
148 frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
150 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
152 frame_cache(frame_tvb);
154 return tvb_ws_mempbrk_pattern_guint8(tvb, abs_offset, limit, pattern, found_needle);
158 frame_offset(const tvbuff_t *tvb _U_, const guint counter)
160 /* XXX: frame_tvb->offset */
164 static tvbuff_t *frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length);
166 static const struct tvb_ops tvb_frame_ops = {
167 sizeof(struct tvb_frame), /* size */
169 frame_free, /* free */
170 frame_offset, /* offset */
171 frame_get_ptr, /* get_ptr */
172 frame_memcpy, /* memcpy */
173 frame_find_guint8, /* find_guint8 */
174 frame_pbrk_guint8, /* pbrk_guint8 */
175 frame_clone, /* clone */
178 /* based on tvb_new_real_data() */
180 frame_tvbuff_new(const frame_data *fd, const guint8 *buf)
182 struct tvb_frame *frame_tvb;
185 tvb = tvb_new(&tvb_frame_ops);
188 * XXX - currently, the length arguments in
189 * tvbuff structure are signed, but the captured
190 * and reported length values are unsigned; this means
191 * that length values > 2^31 - 1 will appear as
194 * Captured length values that large will already
195 * have been filtered out by the Wiretap modules
196 * (the file will be reported as corrupted), to
197 * avoid trying to allocate large chunks of data.
199 * Reported length values will not have been
200 * filtered out, and should not be filtered out,
201 * as those lengths are not necessarily invalid.
203 * For now, we clip the reported length at G_MAXINT
205 * (XXX, is this still a problem?) There was an exception when we call
206 * tvb_new_real_data() now there's no one
209 tvb->real_data = buf;
210 tvb->length = fd->cap_len;
211 tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
212 tvb->initialized = TRUE;
215 * This is the top-level real tvbuff for this data source,
216 * so its data source tvbuff is itself.
220 frame_tvb = (struct tvb_frame *) tvb;
222 /* XXX, wtap_can_seek() */
223 if (cfile.wth && cfile.wth->random_fh
224 #ifdef WANT_PACKET_EDITOR
225 && fd->file_off != -1 /* generic clone for modified packets */
228 frame_tvb->wth = cfile.wth;
229 frame_tvb->file_off = fd->file_off;
230 frame_tvb->offset = 0;
232 frame_tvb->wth = NULL;
234 frame_tvb->buf = NULL;
240 frame_tvbuff_new_buffer(const frame_data *fd, Buffer *buf)
242 return frame_tvbuff_new(fd, ws_buffer_start_ptr(buf));
246 frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
248 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
250 tvbuff_t *cloned_tvb;
251 struct tvb_frame *cloned_frame_tvb;
253 /* file not seekable */
257 abs_offset += frame_tvb->offset;
259 cloned_tvb = tvb_new(&tvb_frame_ops);
261 /* data will be read when needed */
262 cloned_tvb->real_data = NULL;
263 cloned_tvb->length = abs_length;
264 cloned_tvb->reported_length = abs_length; /* XXX? */
265 cloned_tvb->initialized = TRUE;
268 * This is the top-level real tvbuff for this data source,
269 * so its data source tvbuff is itself.
271 cloned_tvb->ds_tvb = cloned_tvb;
273 cloned_frame_tvb = (struct tvb_frame *) cloned_tvb;
274 cloned_frame_tvb->wth = frame_tvb->wth;
275 cloned_frame_tvb->file_off = frame_tvb->file_off;
276 cloned_frame_tvb->offset = abs_offset;
277 cloned_frame_tvb->buf = NULL;
283 /* based on tvb_new_real_data() */
285 file_tvbuff_new(const frame_data *fd, const guint8 *buf)
287 struct tvb_frame *frame_tvb;
290 tvb = tvb_new(&tvb_frame_ops);
293 * XXX - currently, the length arguments in
294 * tvbuff structure are signed, but the captured
295 * and reported length values are unsigned; this means
296 * that length values > 2^31 - 1 will appear as
299 * Captured length values that large will already
300 * have been filtered out by the Wiretap modules
301 * (the file will be reported as corrupted), to
302 * avoid trying to allocate large chunks of data.
304 * Reported length values will not have been
305 * filtered out, and should not be filtered out,
306 * as those lengths are not necessarily invalid.
308 * For now, we clip the reported length at G_MAXINT
310 * (XXX, is this still a problem?) There was an exception when we call
311 * tvb_new_real_data() now there's no one
314 tvb->real_data = buf;
315 tvb->length = fd->cap_len;
316 tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
317 tvb->initialized = TRUE;
320 * This is the top-level real tvbuff for this data source,
321 * so its data source tvbuff is itself.
325 frame_tvb = (struct tvb_frame *) tvb;
327 /* XXX, wtap_can_seek() */
328 if (cfile.wth && cfile.wth->random_fh
329 #ifdef WANT_PACKET_EDITOR
330 && fd->file_off != -1 /* generic clone for modified packets */
333 frame_tvb->wth = cfile.wth;
334 frame_tvb->file_off = fd->file_off;
335 frame_tvb->offset = 0;
337 frame_tvb->wth = NULL;
339 frame_tvb->buf = NULL;
345 file_tvbuff_new_buffer(const frame_data *fd, Buffer *buf)
347 return frame_tvbuff_new(fd, ws_buffer_start_ptr(buf));
351 * Editor modelines - http://www.wireshark.org/tools/modelines.html
356 * indent-tabs-mode: t
359 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
360 * :indentSize=8:tabSize=8:noTabs=false: