nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | */ |