forked from osmocom/wireshark
Add support for cloning TVBs, move tvb_new() prototype to wtap-int.h
svn path=/trunk/; revision=50558
This commit is contained in:
parent
9bdc911c29
commit
ef93945811
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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.
|
||||
|
|
178
frame_tvbuff.c
178
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue