forked from osmocom/wireshark
7cd6906056
This emphasizes that there is no such thing as *the* routine to construct a subset tvbuff; you need to choose one of tvb_new_subset_remaining() (if you want a new tvbuff that contains everything past a certain point in an existing tvbuff), tvb_new_subset_length() (if you want a subset that contains everything past a certain point, for some number of bytes, in an existing tvbuff), and tvb_new_subset_length_caplen() (for all other cases). Many of the calls to tvb_new_subset_length_caplen() should really be calling one of the other routines; that's the next step. (This also makes it easier to find the calls that need fixing.) Change-Id: Ieb3d676d8cda535451c119487d7cd3b559221f2b Reviewed-on: https://code.wireshark.org/review/19597 Reviewed-by: Guy Harris <guy@alum.mit.edu>
248 lines
6.7 KiB
C
248 lines
6.7 KiB
C
/* tvbuff_real.c
|
|
*
|
|
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "tvbuff.h"
|
|
#include "tvbuff-int.h"
|
|
#include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
|
|
#include "exceptions.h"
|
|
|
|
typedef struct {
|
|
/** The backing tvbuff_t */
|
|
struct tvbuff *tvb;
|
|
|
|
/** The offset of 'tvb' to which I'm privy */
|
|
guint offset;
|
|
/** The length of 'tvb' to which I'm privy */
|
|
guint length;
|
|
|
|
} tvb_backing_t;
|
|
|
|
struct tvb_subset {
|
|
struct tvbuff tvb;
|
|
|
|
tvb_backing_t subset;
|
|
};
|
|
|
|
static guint
|
|
subset_offset(const tvbuff_t *tvb, const guint counter)
|
|
{
|
|
const struct tvb_subset *subset_tvb = (const struct tvb_subset *) tvb;
|
|
const tvbuff_t *member = subset_tvb->subset.tvb;
|
|
|
|
return tvb_offset_from_real_beginning_counter(member, counter + subset_tvb->subset.offset);
|
|
}
|
|
|
|
static void *
|
|
subset_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
|
|
{
|
|
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
|
|
|
return tvb_memcpy(subset_tvb->subset.tvb, target, subset_tvb->subset.offset + abs_offset, abs_length);
|
|
}
|
|
|
|
static const guint8 *
|
|
subset_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length)
|
|
{
|
|
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
|
|
|
return tvb_get_ptr(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
|
|
}
|
|
|
|
static gint
|
|
subset_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
|
|
{
|
|
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
|
|
|
return tvb_find_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needle);
|
|
}
|
|
|
|
static gint
|
|
subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
|
|
{
|
|
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
|
|
|
return tvb_ws_mempbrk_pattern_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, pattern, found_needle);
|
|
}
|
|
|
|
static tvbuff_t *
|
|
subset_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
|
|
{
|
|
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
|
|
|
return tvb_clone_offset_len(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
|
|
}
|
|
|
|
static const struct tvb_ops tvb_subset_ops = {
|
|
sizeof(struct tvb_subset), /* size */
|
|
|
|
NULL, /* free */
|
|
subset_offset, /* offset */
|
|
subset_get_ptr, /* get_ptr */
|
|
subset_memcpy, /* memcpy */
|
|
subset_find_guint8, /* find_guint8 */
|
|
subset_pbrk_guint8, /* pbrk_guint8 */
|
|
subset_clone, /* clone */
|
|
};
|
|
|
|
static tvbuff_t *
|
|
tvb_new_with_subset(tvbuff_t *backing, const gint reported_length,
|
|
const guint subset_tvb_offset, const guint subset_tvb_length)
|
|
{
|
|
tvbuff_t *tvb = tvb_new(&tvb_subset_ops);
|
|
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
|
|
|
subset_tvb->subset.offset = subset_tvb_offset;
|
|
subset_tvb->subset.length = subset_tvb_length;
|
|
|
|
subset_tvb->subset.tvb = backing;
|
|
tvb->length = subset_tvb_length;
|
|
tvb->flags = backing->flags;
|
|
|
|
if (reported_length == -1) {
|
|
tvb->reported_length = backing->reported_length - subset_tvb_offset;
|
|
}
|
|
else {
|
|
tvb->reported_length = reported_length;
|
|
}
|
|
tvb->initialized = TRUE;
|
|
|
|
/* Optimization. If the backing buffer has a pointer to contiguous, real data,
|
|
* then we can point directly to our starting offset in that buffer */
|
|
if (backing->real_data != NULL) {
|
|
tvb->real_data = backing->real_data + subset_tvb_offset;
|
|
}
|
|
|
|
/*
|
|
* The top-level data source of this tvbuff is the top-level
|
|
* data source of its parent.
|
|
*/
|
|
tvb->ds_tvb = backing->ds_tvb;
|
|
|
|
return tvb;
|
|
}
|
|
|
|
tvbuff_t *
|
|
tvb_new_subset_length_caplen(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
|
|
{
|
|
tvbuff_t *tvb;
|
|
guint subset_tvb_offset;
|
|
guint subset_tvb_length;
|
|
|
|
DISSECTOR_ASSERT(backing && backing->initialized);
|
|
|
|
THROW_ON(reported_length < -1, ReportedBoundsError);
|
|
|
|
tvb_check_offset_length(backing, backing_offset, backing_length,
|
|
&subset_tvb_offset,
|
|
&subset_tvb_length);
|
|
|
|
tvb = tvb_new_with_subset(backing, reported_length,
|
|
subset_tvb_offset, subset_tvb_length);
|
|
|
|
tvb_add_to_chain(backing, tvb);
|
|
|
|
return tvb;
|
|
}
|
|
|
|
tvbuff_t *
|
|
tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint backing_length)
|
|
{
|
|
gint captured_length;
|
|
tvbuff_t *tvb;
|
|
guint subset_tvb_offset;
|
|
guint subset_tvb_length;
|
|
|
|
DISSECTOR_ASSERT(backing && backing->initialized);
|
|
|
|
THROW_ON(backing_length < 0, ReportedBoundsError);
|
|
|
|
/*
|
|
* Give the next dissector only captured_length bytes.
|
|
*/
|
|
captured_length = tvb_captured_length_remaining(backing, backing_offset);
|
|
THROW_ON(captured_length < 0, BoundsError);
|
|
if (captured_length > backing_length)
|
|
captured_length = backing_length;
|
|
|
|
tvb_check_offset_length(backing, backing_offset, captured_length,
|
|
&subset_tvb_offset,
|
|
&subset_tvb_length);
|
|
|
|
tvb = tvb_new_with_subset(backing, backing_length,
|
|
subset_tvb_offset, subset_tvb_length);
|
|
|
|
tvb_add_to_chain(backing, tvb);
|
|
|
|
return tvb;
|
|
}
|
|
|
|
tvbuff_t *
|
|
tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
|
|
{
|
|
tvbuff_t *tvb;
|
|
guint subset_tvb_offset;
|
|
guint subset_tvb_length;
|
|
|
|
tvb_check_offset_length(backing, backing_offset, -1 /* backing_length */,
|
|
&subset_tvb_offset,
|
|
&subset_tvb_length);
|
|
|
|
tvb = tvb_new_with_subset(backing, -1 /* reported_length */,
|
|
subset_tvb_offset, subset_tvb_length);
|
|
|
|
tvb_add_to_chain(backing, tvb);
|
|
|
|
return tvb;
|
|
}
|
|
|
|
tvbuff_t *
|
|
tvb_new_proxy(tvbuff_t *backing)
|
|
{
|
|
tvbuff_t *tvb;
|
|
|
|
if (backing)
|
|
tvb = tvb_new_with_subset(backing, backing->reported_length, 0, backing->length);
|
|
else
|
|
tvb = tvb_new_real_data(NULL, 0, 0);
|
|
|
|
tvb->ds_tvb = tvb;
|
|
|
|
return tvb;
|
|
}
|
|
|
|
|
|
/*
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local variables:
|
|
* c-basic-offset: 8
|
|
* tab-width: 8
|
|
* indent-tabs-mode: t
|
|
* End:
|
|
*
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
*/
|