Revert r50668, remove fd check to fix CID 1050093
[metze/wireshark/wip.git] / frame_tvbuff.c
1 /* frame_tvbuff.c
2  * Implements a tvbuff for frame
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <glib.h>
28
29 #include <epan/packet.h>
30 #include <epan/tvbuff-int.h>
31 #include <epan/tvbuff.h>
32
33 #include "frame_tvbuff.h"
34 #include "globals.h"
35
36 #include "wtap-int.h" /* for ->random_fh */
37
38 struct tvb_frame {
39         struct tvbuff tvb;
40
41         Buffer *buf;         /* Packet data */
42
43         wtap *wth;           /**< Wiretap session */
44         gint64 file_off;     /**< File offset */
45
46         guint offset;
47 };
48
49 static gboolean
50 frame_read(struct tvb_frame *frame_tvb, struct wtap_pkthdr *phdr, Buffer *buf)
51 {
52         int    err;
53         gchar *err_info;
54
55         /* sanity check, capture file was closed? */
56         if (cfile.wth != frame_tvb->wth)
57                 return FALSE;
58
59         if (!wtap_seek_read(frame_tvb->wth, frame_tvb->file_off, phdr, buf, frame_tvb->tvb.length + frame_tvb->offset, &err, &err_info)) {
60                 switch (err) {
61                         case WTAP_ERR_UNSUPPORTED_ENCAP:
62                         case WTAP_ERR_BAD_FILE:
63                                 g_free(err_info);
64                                 break;
65                 }
66                 return FALSE;
67         }
68         return TRUE;
69 }
70
71 static void
72 frame_cache(struct tvb_frame *frame_tvb)
73 {
74         struct wtap_pkthdr phdr; /* Packet header */
75
76         if (frame_tvb->buf == NULL) {
77                 frame_tvb->buf = (struct Buffer *) g_malloc(sizeof(struct Buffer));
78
79                 /* XXX, register frame_tvb to some list which frees from time to time not used buffers :] */
80                 buffer_init(frame_tvb->buf, frame_tvb->tvb.length + frame_tvb->offset);
81
82                 if (!frame_read(frame_tvb, &phdr, frame_tvb->buf))
83                         { /* TODO: THROW(???); */ }
84         }
85
86         frame_tvb->tvb.real_data = buffer_start_ptr(frame_tvb->buf) + frame_tvb->offset;
87 }
88
89 static void
90 frame_free(tvbuff_t *tvb)
91 {
92         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
93
94         if (frame_tvb->buf) {
95                 buffer_free(frame_tvb->buf);
96
97                 g_free(frame_tvb->buf);
98         }
99 }
100
101 static const guint8 *
102 frame_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length _U_)
103 {
104         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
105
106         frame_cache(frame_tvb);
107
108         return tvb->real_data + abs_offset;
109 }
110
111 static void *
112 frame_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
113 {
114         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
115
116         frame_cache(frame_tvb);
117
118         return memcpy(target, tvb->real_data + abs_offset, abs_length);
119 }
120
121 static gint
122 frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
123 {
124         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
125         const guint8 *result;
126
127         frame_cache(frame_tvb);
128
129         result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit);
130         if (result)
131                 return (gint) (result - tvb->real_data);
132         else
133                 return -1;
134 }
135
136 static gint
137 frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle)
138 {
139         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
140
141         frame_cache(frame_tvb);
142
143         return tvb_pbrk_guint8(tvb, abs_offset, limit, needles, found_needle);
144 }
145
146 static gsize
147 frame_sizeof(void)
148 {
149         return sizeof(struct tvb_frame);
150 }
151
152 static guint
153 frame_offset(const tvbuff_t *tvb _U_, const guint counter)
154 {
155         /* XXX: frame_tvb->offset */
156         return counter;
157 }
158
159 static tvbuff_t *frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length);
160
161 static const struct tvb_ops tvb_frame_ops = {
162         frame_sizeof,         /* size */
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, how to handle fd->file_off == -1 (edited packet) ?? */
217         /* don't care, reassemble code was doing whole copy of data, so it'll work the same */
218
219         /* XXX, wtap_can_seek() */
220         if (cfile.wth && cfile.wth->random_fh) {
221                 frame_tvb->wth = cfile.wth;
222                 frame_tvb->file_off = fd->file_off;
223                 frame_tvb->offset = 0;
224         } else
225                 frame_tvb->wth = NULL;
226
227         frame_tvb->buf = NULL;
228
229         return tvb;
230 }
231
232 tvbuff_t *
233 frame_tvbuff_new_buffer(const frame_data *fd, Buffer *buf)
234 {
235         return frame_tvbuff_new(fd, buffer_start_ptr(buf));
236 }
237
238 static tvbuff_t *
239 frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
240 {
241         struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
242
243         tvbuff_t *cloned_tvb;
244         struct tvb_frame *cloned_frame_tvb;
245
246         /* file not seekable */
247         if (!frame_tvb->wth)
248                 return NULL;
249
250         abs_offset += frame_tvb->offset;
251
252         cloned_tvb = tvb_new(&tvb_frame_ops);
253
254         /* data will be read when needed */
255         cloned_tvb->real_data       = NULL;
256         cloned_tvb->length          = abs_length;
257         cloned_tvb->reported_length = abs_length; /* XXX? */
258         cloned_tvb->initialized     = TRUE;
259
260         /*
261          * This is the top-level real tvbuff for this data source,
262          * so its data source tvbuff is itself.
263          */
264         cloned_tvb->ds_tvb = cloned_tvb;
265
266         cloned_frame_tvb = (struct tvb_frame *) cloned_tvb;
267         cloned_frame_tvb->wth = frame_tvb->wth;
268         cloned_frame_tvb->file_off = frame_tvb->file_off;
269         cloned_frame_tvb->offset = abs_offset;
270         cloned_frame_tvb->buf = NULL;
271
272         return cloned_tvb;
273 }