dcerpc-netlogon: improve NetrLogonGetCapabilities dissection
[wireshark-sm.git] / frame_tvbuff.c
blobb572dddade54574eb24c38435ea57c517120d67e
1 /* frame_tvbuff.c
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
9 */
11 #include <config.h>
13 #include <glib.h>
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 */
23 struct tvb_frame {
24 struct tvbuff tvb;
26 Buffer *buf; /* Packet data */
28 const struct packet_provider_data *prov; /* provider of packet information */
29 int64_t file_off; /**< File offset */
31 unsigned offset;
34 static bool
35 frame_read(struct tvb_frame *frame_tvb, wtap_rec *rec, Buffer *buf)
37 int err;
38 char *err_info;
39 bool ok = true;
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! */
46 switch (err) {
47 case WTAP_ERR_BAD_FILE:
48 g_free(err_info);
49 ok = false;
50 break;
53 return ok;
56 static GPtrArray *buffer_cache;
58 static void
59 frame_cache(struct tvb_frame *frame_tvb)
61 wtap_rec rec; /* Record metadata */
63 wtap_rec_init(&rec);
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);
70 } else {
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);
85 static void
86 frame_free(tvbuff_t *tvb)
88 struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
90 if (frame_tvb->buf) {
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;
106 static void *
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);
116 static int
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);
125 if (result)
126 return (int) (result - tvb->real_data);
127 else
128 return -1;
131 static int
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);
141 static unsigned
142 frame_offset(const tvbuff_t *tvb _U_, const unsigned counter)
144 /* XXX: frame_tvb->offset */
145 return counter;
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() */
163 tvbuff_t *
164 frame_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd,
165 const uint8_t *buf)
167 struct tvb_frame *frame_tvb;
168 tvbuff_t *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
177 * negative lengths
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.
204 tvb->ds_tvb = tvb;
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;
213 } else
214 frame_tvb->prov = NULL;
216 frame_tvb->buf = NULL;
218 return tvb;
221 tvbuff_t *
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));
228 static tvbuff_t *
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)
238 return NULL;
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;
263 return cloned_tvb;
267 /* based on tvb_new_real_data() */
268 tvbuff_t *
269 file_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd,
270 const uint8_t *buf)
272 struct tvb_frame *frame_tvb;
273 tvbuff_t *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
282 * negative lengths
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.
309 tvb->ds_tvb = tvb;
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;
318 } else
319 frame_tvb->prov = NULL;
321 frame_tvb->buf = NULL;
323 return tvb;
326 tvbuff_t *
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));