summaryrefslogtreecommitdiff
path: root/frame_tvbuff.c
diff options
context:
space:
mode:
authorJakub Zawadzki <darkjames-ws@darkjames.pl>2013-07-13 17:53:33 +0000
committerJakub Zawadzki <darkjames-ws@darkjames.pl>2013-07-13 17:53:33 +0000
commitef9394581140d5525b6c0983e72938464b91822f (patch)
treef15ca5015eb1ba04b0bfe54b7d133564a44e4ad6 /frame_tvbuff.c
parent9bdc911c29796729dbd27d9fc5f614fa830f94ce (diff)
downloadwireshark-ef9394581140d5525b6c0983e72938464b91822f.tar.gz
Add support for cloning TVBs, move tvb_new() prototype to wtap-int.h
svn path=/trunk/; revision=50558
Diffstat (limited to 'frame_tvbuff.c')
-rw-r--r--frame_tvbuff.c178
1 files changed, 169 insertions, 9 deletions
diff --git a/frame_tvbuff.c b/frame_tvbuff.c
index 5af5b3bc23..20635fd958 100644
--- a/frame_tvbuff.c
+++ b/frame_tvbuff.c
@@ -31,16 +31,119 @@
#include <epan/tvbuff.h>
#include "frame_tvbuff.h"
+#include "globals.h"
-/* XXX, to read data with wtap_seek_read() we need:
- * cf->wth, fdata->file_off, fdata->cap_len
- * add when ready to structure below
- */
+#include "wtap-int.h" /* for ->random_fh */
struct tvb_frame {
struct tvbuff tvb;
+
+ Buffer *buf; /* Packet data */
+
+ wtap *wth; /**< Wiretap session */
+ gint64 file_off; /**< File offset */
+
+ guint offset;
};
+static gboolean
+frame_read(struct tvb_frame *frame_tvb, struct wtap_pkthdr *phdr, Buffer *buf)
+{
+ int err;
+ gchar *err_info;
+
+ /* sanity check, capture file was closed? */
+ if (cfile.wth != frame_tvb->wth)
+ return FALSE;
+
+ if (!wtap_seek_read(frame_tvb->wth, frame_tvb->file_off, phdr, buf, frame_tvb->tvb.length, &err, &err_info)) {
+ switch (err) {
+ case WTAP_ERR_UNSUPPORTED_ENCAP:
+ case WTAP_ERR_BAD_FILE:
+ g_free(err_info);
+ break;
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+static void
+frame_invalidate(struct tvb_frame *frame_tvb)
+{
+ struct wtap_pkthdr phdr; /* Packet header */
+
+ if (frame_tvb->buf == NULL) {
+ frame_tvb->buf = (struct Buffer *) g_malloc(sizeof(struct Buffer));
+
+ /* XXX, register frame_tvb to some list which frees from time to time not used buffers :] */
+ buffer_init(frame_tvb->buf, frame_tvb->tvb.length);
+
+ if (!frame_read(frame_tvb, &phdr, frame_tvb->buf))
+ { /* TODO: THROW(???); */ }
+ }
+
+ frame_tvb->tvb.real_data = buffer_start_ptr(frame_tvb->buf);
+}
+
+static void
+frame_free(tvbuff_t *tvb)
+{
+ struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
+
+ if (frame_tvb->buf) {
+ buffer_free(frame_tvb->buf);
+
+ g_free(frame_tvb->buf);
+ }
+}
+
+static const guint8 *
+frame_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length _U_)
+{
+ struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
+
+ frame_invalidate(frame_tvb);
+
+ return tvb->real_data + abs_offset;
+}
+
+static void *
+frame_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
+{
+ struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
+
+ frame_invalidate(frame_tvb);
+
+ return memcpy(target, tvb->real_data + abs_offset, abs_length);
+}
+
+static gint
+frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
+{
+ struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
+ const guint8 *result;
+
+ frame_invalidate(frame_tvb);
+
+ result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit);
+ if (result)
+ return (gint) (result - tvb->real_data);
+ else
+ return -1;
+}
+
+static gint
+frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle)
+{
+ struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
+
+ frame_invalidate(frame_tvb);
+
+ return tvb_pbrk_guint8(tvb, abs_offset, limit, needles, found_needle);
+}
+
static gsize
frame_sizeof(void)
{
@@ -50,23 +153,28 @@ frame_sizeof(void)
static guint
frame_offset(const tvbuff_t *tvb _U_, const guint counter)
{
+ /* XXX: frame_tvb->offset */
return counter;
}
+static tvbuff_t *frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length);
+
static const struct tvb_ops tvb_frame_ops = {
frame_sizeof, /* size */
- NULL, /* free */
+ frame_free, /* free */
frame_offset, /* offset */
- NULL, /* get_ptr */
- NULL, /* memcpy */
- NULL, /* find_guint8 */
- NULL, /* pbrk_guint8 */
+ frame_get_ptr, /* get_ptr */
+ frame_memcpy, /* memcpy */
+ frame_find_guint8, /* find_guint8 */
+ frame_pbrk_guint8, /* pbrk_guint8 */
+ frame_clone, /* clone */
};
/* based on tvb_new_real_data() */
tvbuff_t *
frame_tvbuff_new(const frame_data *fd, const guint8 *buf)
{
+ struct tvb_frame *frame_tvb;
tvbuff_t *tvb;
tvb = tvb_new(&tvb_frame_ops);
@@ -104,6 +212,21 @@ frame_tvbuff_new(const frame_data *fd, const guint8 *buf)
*/
tvb->ds_tvb = tvb;
+ frame_tvb = (struct tvb_frame *) tvb;
+
+ /* XXX, how to handle fd->file_off == -1 (edited packet) ?? */
+ /* don't care, reassemble code was doing whole copy of data, so it'll work the same */
+
+ /* XXX, wtap_can_seek() */
+ if (fd && cfile.wth && cfile.wth->random_fh) {
+ frame_tvb->wth = cfile.wth;
+ frame_tvb->file_off = fd->file_off;
+ frame_tvb->offset = 0;
+ } else
+ frame_tvb->wth = NULL;
+
+ frame_tvb->buf = NULL;
+
return tvb;
}
@@ -112,3 +235,40 @@ frame_tvbuff_new_buffer(const frame_data *fd, Buffer *buf)
{
return frame_tvbuff_new(fd, buffer_start_ptr(buf));
}
+
+static tvbuff_t *
+frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
+{
+ struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
+
+ tvbuff_t *cloned_tvb;
+ struct tvb_frame *cloned_frame_tvb;
+
+ /* file not seekable */
+ if (!frame_tvb->wth)
+ return NULL;
+
+ abs_offset += frame_tvb->offset;
+
+ cloned_tvb = tvb_new(&tvb_frame_ops);
+
+ /* data will be read when needed */
+ cloned_tvb->real_data = NULL;
+ cloned_tvb->length = abs_length;
+ cloned_tvb->reported_length = abs_length; /* XXX? */
+ cloned_tvb->initialized = TRUE;
+
+ /*
+ * This is the top-level real tvbuff for this data source,
+ * so its data source tvbuff is itself.
+ */
+ cloned_tvb->ds_tvb = cloned_tvb;
+
+ cloned_frame_tvb = (struct tvb_frame *) cloned_tvb;
+ cloned_frame_tvb->wth = frame_tvb->wth;
+ cloned_frame_tvb->file_off = frame_tvb->file_off;
+ cloned_frame_tvb->offset = abs_offset;
+ cloned_frame_tvb->buf = NULL;
+
+ return cloned_tvb;
+}