For SHBs, always use the byte order from the byte-order magic.
[metze/wireshark/wip.git] / frame_tvbuff.c
1 /* frame_tvbuff.c
2  * Implements a tvbuff for frame
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
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.
12  *
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.
17  *
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.
21  */
22
23 #include <config.h>
24
25 #include <glib.h>
26
27 #include <epan/packet.h>
28 #include <epan/tvbuff-int.h>
29 #include <epan/tvbuff.h>
30
31 #include "frame_tvbuff.h"
32 #include "globals.h"
33
34 #include "wiretap/wtap-int.h" /* for ->random_fh */
35
36 struct tvb_frame {
37         struct tvbuff tvb;
38
39         Buffer *buf;         /* Packet data */
40
41         wtap *wth;           /**< Wiretap session */
42         gint64 file_off;     /**< File offset */
43
44         guint offset;
45 };
46
47 static gboolean
48 frame_read(struct tvb_frame *frame_tvb, struct wtap_pkthdr *phdr, Buffer *buf)
49 {
50         int    err;
51         gchar *err_info;
52
53         /* sanity check, capture file was closed? */
54         if (cfile.wth != frame_tvb->wth)
55                 return FALSE;
56
57         /* XXX, what if phdr->caplen isn't equal to
58          * frame_tvb->tvb.length + frame_tvb->offset?
59          */
60         if (!wtap_seek_read(frame_tvb->wth, frame_tvb->file_off, phdr, buf, &err, &err_info)) {
61                 /* XXX - report error! */
62                 switch (err) {
63                         case WTAP_ERR_BAD_FILE:
64                                 g_free(err_info);
65                                 break;
66                 }
67                 return FALSE;
68         }
69         return TRUE;
70 }
71
72 static void
73 frame_cache(struct tvb_frame *frame_tvb)
74 {
75         struct wtap_pkthdr phdr; /* Packet header */
76
77         wtap_phdr_init(&phdr);
78
79         if (frame_tvb->buf == NULL) {
80                 frame_tvb->buf = (struct Buffer *) g_malloc(sizeof(struct Buffer));
81
82                 /* XXX, register frame_tvb to some list which frees from time to time not used buffers :] */
83                 ws_buffer_init(frame_tvb->buf, frame_tvb->tvb.length + frame_tvb->offset);
84
85                 if (!frame_read(frame_tvb, &phdr, frame_tvb->buf))
86                         { /* TODO: THROW(???); */ }
87         }
88
89         frame_tvb->tvb.real_data = ws_buffer_start_ptr(frame_tvb->buf) + frame_tvb->offset;
90
91         wtap_phdr_cleanup(&phdr);
92 }
93
94 static void
95 frame_free(tvbuff_t *tvb)
96 {
97         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
98
99         if (frame_tvb->buf) {
100                 ws_buffer_free(frame_tvb->buf);
101
102                 g_free(frame_tvb->buf);
103         }
104 }
105
106 static const guint8 *
107 frame_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length _U_)
108 {
109         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
110
111         frame_cache(frame_tvb);
112
113         return tvb->real_data + abs_offset;
114 }
115
116 static void *
117 frame_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
118 {
119         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
120
121         frame_cache(frame_tvb);
122
123         return memcpy(target, tvb->real_data + abs_offset, abs_length);
124 }
125
126 static gint
127 frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
128 {
129         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
130         const guint8 *result;
131
132         frame_cache(frame_tvb);
133
134         result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit);
135         if (result)
136                 return (gint) (result - tvb->real_data);
137         else
138                 return -1;
139 }
140
141 static gint
142 frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
143 {
144         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
145
146         frame_cache(frame_tvb);
147
148         return tvb_ws_mempbrk_pattern_guint8(tvb, abs_offset, limit, pattern, found_needle);
149 }
150
151 static guint
152 frame_offset(const tvbuff_t *tvb _U_, const guint counter)
153 {
154         /* XXX: frame_tvb->offset */
155         return counter;
156 }
157
158 static tvbuff_t *frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length);
159
160 static const struct tvb_ops tvb_frame_ops = {
161         sizeof(struct tvb_frame), /* size */
162
163         frame_free,           /* free */
164         frame_offset,         /* offset */
165         frame_get_ptr,        /* get_ptr */
166         frame_memcpy,         /* memcpy */
167         frame_find_guint8,    /* find_guint8 */
168         frame_pbrk_guint8,    /* pbrk_guint8 */
169         frame_clone,          /* clone */
170 };
171
172 /* based on tvb_new_real_data() */
173 tvbuff_t *
174 frame_tvbuff_new(const frame_data *fd, const guint8 *buf)
175 {
176         struct tvb_frame *frame_tvb;
177         tvbuff_t *tvb;
178
179         tvb = tvb_new(&tvb_frame_ops);
180
181         /*
182          * XXX - currently, the length arguments in
183          * tvbuff structure are signed, but the captured
184          * and reported length values are unsigned; this means
185          * that length values > 2^31 - 1 will appear as
186          * negative lengths
187          *
188          * Captured length values that large will already
189          * have been filtered out by the Wiretap modules
190          * (the file will be reported as corrupted), to
191          * avoid trying to allocate large chunks of data.
192          *
193          * Reported length values will not have been
194          * filtered out, and should not be filtered out,
195          * as those lengths are not necessarily invalid.
196          *
197          * For now, we clip the reported length at G_MAXINT
198          *
199          * (XXX, is this still a problem?) There was an exception when we call
200          * tvb_new_real_data() now there's no one
201          */
202
203         tvb->real_data       = buf;
204         tvb->length          = fd->cap_len;
205         tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
206         tvb->initialized     = TRUE;
207
208         /*
209          * This is the top-level real tvbuff for this data source,
210          * so its data source tvbuff is itself.
211          */
212         tvb->ds_tvb = tvb;
213
214         frame_tvb = (struct tvb_frame *) tvb;
215
216         /* XXX, wtap_can_seek() */
217         if (cfile.wth && cfile.wth->random_fh
218 #ifdef WANT_PACKET_EDITOR
219                 && fd->file_off != -1 /* generic clone for modified packets */
220 #endif
221         ) {
222                 frame_tvb->wth = cfile.wth;
223                 frame_tvb->file_off = fd->file_off;
224                 frame_tvb->offset = 0;
225         } else
226                 frame_tvb->wth = NULL;
227
228         frame_tvb->buf = NULL;
229
230         return tvb;
231 }
232
233 tvbuff_t *
234 frame_tvbuff_new_buffer(const frame_data *fd, Buffer *buf)
235 {
236         return frame_tvbuff_new(fd, ws_buffer_start_ptr(buf));
237 }
238
239 static tvbuff_t *
240 frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
241 {
242         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
243
244         tvbuff_t *cloned_tvb;
245         struct tvb_frame *cloned_frame_tvb;
246
247         /* file not seekable */
248         if (!frame_tvb->wth)
249                 return NULL;
250
251         abs_offset += frame_tvb->offset;
252
253         cloned_tvb = tvb_new(&tvb_frame_ops);
254
255         /* data will be read when needed */
256         cloned_tvb->real_data       = NULL;
257         cloned_tvb->length          = abs_length;
258         cloned_tvb->reported_length = abs_length; /* XXX? */
259         cloned_tvb->initialized     = TRUE;
260
261         /*
262          * This is the top-level real tvbuff for this data source,
263          * so its data source tvbuff is itself.
264          */
265         cloned_tvb->ds_tvb = cloned_tvb;
266
267         cloned_frame_tvb = (struct tvb_frame *) cloned_tvb;
268         cloned_frame_tvb->wth = frame_tvb->wth;
269         cloned_frame_tvb->file_off = frame_tvb->file_off;
270         cloned_frame_tvb->offset = abs_offset;
271         cloned_frame_tvb->buf = NULL;
272
273         return cloned_tvb;
274 }
275
276
277 /* based on tvb_new_real_data() */
278 tvbuff_t *
279 file_tvbuff_new(const frame_data *fd, const guint8 *buf)
280 {
281         struct tvb_frame *frame_tvb;
282         tvbuff_t *tvb;
283
284         tvb = tvb_new(&tvb_frame_ops);
285
286         /*
287          * XXX - currently, the length arguments in
288          * tvbuff structure are signed, but the captured
289          * and reported length values are unsigned; this means
290          * that length values > 2^31 - 1 will appear as
291          * negative lengths
292          *
293          * Captured length values that large will already
294          * have been filtered out by the Wiretap modules
295          * (the file will be reported as corrupted), to
296          * avoid trying to allocate large chunks of data.
297          *
298          * Reported length values will not have been
299          * filtered out, and should not be filtered out,
300          * as those lengths are not necessarily invalid.
301          *
302          * For now, we clip the reported length at G_MAXINT
303          *
304          * (XXX, is this still a problem?) There was an exception when we call
305          * tvb_new_real_data() now there's no one
306          */
307
308         tvb->real_data       = buf;
309         tvb->length          = fd->cap_len;
310         tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
311         tvb->initialized     = TRUE;
312
313         /*
314          * This is the top-level real tvbuff for this data source,
315          * so its data source tvbuff is itself.
316          */
317         tvb->ds_tvb = tvb;
318
319         frame_tvb = (struct tvb_frame *) tvb;
320
321         /* XXX, wtap_can_seek() */
322         if (cfile.wth && cfile.wth->random_fh
323 #ifdef WANT_PACKET_EDITOR
324                 && fd->file_off != -1 /* generic clone for modified packets */
325 #endif
326         ) {
327                 frame_tvb->wth = cfile.wth;
328                 frame_tvb->file_off = fd->file_off;
329                 frame_tvb->offset = 0;
330         } else
331                 frame_tvb->wth = NULL;
332
333         frame_tvb->buf = NULL;
334
335         return tvb;
336 }
337
338 tvbuff_t *
339 file_tvbuff_new_buffer(const frame_data *fd, Buffer *buf)
340 {
341         return frame_tvbuff_new(fd, ws_buffer_start_ptr(buf));
342 }
343
344 /*
345  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
346  *
347  * Local variables:
348  * c-basic-offset: 8
349  * tab-width: 8
350  * indent-tabs-mode: t
351  * End:
352  *
353  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
354  * :indentSize=8:tabSize=8:noTabs=false:
355  */