Add support for cloning TVBs, move tvb_new() prototype to wtap-int.h

svn path=/trunk/; revision=50558
This commit is contained in:
Jakub Zawadzki 2013-07-13 17:53:33 +00:00
parent 9bdc911c29
commit ef93945811
4 changed files with 218 additions and 13 deletions

View File

@ -37,6 +37,8 @@ struct tvb_ops {
gint (*tvb_find_guint8)(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle);
gint (*tvb_pbrk_guint8)(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle);
tvbuff_t *(*tvb_clone)(tvbuff_t *tvb, guint abs_offset, guint abs_length);
};
typedef struct {
@ -114,5 +116,6 @@ struct tvb_composite {
tvb_comp_t composite;
};
WS_DLL_PUBLIC tvbuff_t *tvb_new(const struct tvb_ops *ops);
#endif

View File

@ -629,7 +629,40 @@ tvb_composite_finalize(tvbuff_t *tvb)
tvb->initialized = TRUE;
}
static tvbuff_t *
tvb_generic_clone_offset_len(tvbuff_t *tvb, guint offset, guint len)
{
tvbuff_t *cloned_tvb;
guint8 *data = (guint8 *) g_malloc(len);
tvb_memcpy(tvb, data, offset, len);
cloned_tvb = tvb_new_real_data(data, len, len);
tvb_set_free_cb(cloned_tvb, g_free);
return cloned_tvb;
}
tvbuff_t *
tvb_clone_offset_len(tvbuff_t *tvb, guint offset, guint len)
{
if (tvb->ops->tvb_clone) {
tvbuff_t *cloned_tvb;
cloned_tvb = tvb->ops->tvb_clone(tvb, offset, len);
if (cloned_tvb)
return cloned_tvb;
}
return tvb_generic_clone_offset_len(tvb, offset, len);
}
tvbuff_t *
tvb_clone(tvbuff_t *tvb)
{
return tvb_clone_offset_len(tvb, 0, tvb->length);
}
guint
tvb_length(const tvbuff_t *tvb)
@ -2000,6 +2033,12 @@ subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *n
return tvb_pbrk_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needles, found_needle);
}
static tvbuff_t *
subset_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
{
return tvb_clone_offset_len(tvb, abs_offset, abs_length);
}
/* Find size of stringz (NUL-terminated string) by looking for terminating
* NUL. The size of the string includes the terminating NUL.
*
@ -3645,6 +3684,7 @@ static const struct tvb_ops tvb_real_ops = {
NULL, /* memcpy */
NULL, /* find_guint8 */
NULL, /* pbrk_guint8 */
NULL, /* clone */
};
static inline const struct tvb_ops *get_tvb_real_ops(void) { return &tvb_real_ops; }
@ -3657,6 +3697,7 @@ static const struct tvb_ops tvb_subset_ops = {
subset_memcpy, /* memcpy */
subset_find_guint8, /* find_guint8 */
subset_pbrk_guint8, /* pbrk_guint8 */
subset_clone, /* clone */
};
static inline const struct tvb_ops *get_tvb_subset_ops(void) { return &tvb_subset_ops; }
@ -3669,6 +3710,7 @@ static const struct tvb_ops tvb_composite_ops = {
NULL, /* composite_memcpy */ /* memcpy */
NULL, /* find_guint8 XXX */
NULL, /* pbrk_guint8 XXX */
NULL, /* clone */
};
static inline const struct tvb_ops *get_tvb_composite_ops(void) { return &tvb_composite_ops; }

View File

@ -57,8 +57,6 @@ extern "C" {
struct tvbuff;
typedef struct tvbuff tvbuff_t;
struct tvb_ops;
/** @defgroup tvbuff Testy, Virtual(-izable) Buffers
*
* Dissector use and management
@ -115,14 +113,16 @@ struct tvb_ops;
typedef void (*tvbuff_free_cb_t)(void*);
WS_DLL_PUBLIC tvbuff_t *tvb_new(const struct tvb_ops *ops);
/** Extracts 'number of bits' starting at 'bit offset'.
* Returns a pointer to a newly initialized ep_alloc'd REAL_DATA
* tvbuff with the bits octet aligned.
*/
WS_DLL_PUBLIC tvbuff_t* tvb_new_octet_aligned(tvbuff_t *tvb, guint32 bit_offset, gint32 no_of_bits);
WS_DLL_PUBLIC tvbuff_t *tvb_clone(tvbuff_t *tvb);
WS_DLL_PUBLIC tvbuff_t *tvb_clone_offset_len(tvbuff_t *tvb, guint offset, guint len);
/** Free a tvbuff_t and all tvbuffs chained from it
* The tvbuff must be 'the 'head' (initial) tvb of a chain or
* must not be in a chain.

View File

@ -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;
}