diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index 4720fc8eba..0c1c6d369e 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -1498,6 +1498,8 @@ set(LIBWIRESHARK_FILES to_str.c tvbparse.c tvbuff.c + tvbuff_real.c + tvbuff_subset.c uat.c value_string.c xdlc.c diff --git a/epan/Makefile.common b/epan/Makefile.common index 441bc8174b..df016301f5 100644 --- a/epan/Makefile.common +++ b/epan/Makefile.common @@ -98,6 +98,8 @@ LIBWIRESHARK_SRC = \ tfs.c \ to_str.c \ tvbparse.c \ + tvbuff_real.c \ + tvbuff_subset.c \ tvbuff.c \ uat.c \ value_string.c \ diff --git a/epan/tvbuff-int.h b/epan/tvbuff-int.h index d8d4cba314..3609a39606 100644 --- a/epan/tvbuff-int.h +++ b/epan/tvbuff-int.h @@ -97,13 +97,6 @@ struct tvbuff { gint raw_offset; }; -struct tvb_real { - struct tvbuff tvb; - - /** Func to call when actually freed */ - tvbuff_free_cb_t free_cb; -}; - struct tvb_subset { struct tvbuff tvb; @@ -118,4 +111,9 @@ struct tvb_composite { WS_DLL_PUBLIC tvbuff_t *tvb_new(const struct tvb_ops *ops); +void tvb_add_to_chain(tvbuff_t *parent, tvbuff_t *child); + +guint tvb_offset_from_real_beginning_counter(const tvbuff_t *tvb, const guint counter); + +void tvb_check_offset_length(const tvbuff_t *tvb, const gint offset, gint const length_val, guint *offset_ptr, guint *length_ptr); #endif diff --git a/epan/tvbuff.c b/epan/tvbuff.c index 6de6b7df35..b99e467891 100644 --- a/epan/tvbuff.c +++ b/epan/tvbuff.c @@ -51,8 +51,6 @@ #include "charsets.h" #include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */ -static inline const struct tvb_ops *get_tvb_real_ops(void); -static inline const struct tvb_ops *get_tvb_subset_ops(void); static inline const struct tvb_ops *get_tvb_composite_ops(void); static const guint8* @@ -86,19 +84,6 @@ tvb_new(const struct tvb_ops *ops) return tvb; } -static void -real_free(tvbuff_t *tvb) -{ - struct tvb_real *real_tvb = (struct tvb_real *) tvb; - - if (real_tvb->free_cb) { - /* - * XXX - do this with a union? - */ - real_tvb->free_cb((gpointer)tvb->real_data); - } -} - static void composite_free(tvbuff_t *tvb) { @@ -158,17 +143,7 @@ tvb_free_chain(tvbuff_t *tvb) } void -tvb_set_free_cb(tvbuff_t *tvb, const tvbuff_free_cb_t func) -{ - struct tvb_real *real_tvb = (struct tvb_real *) tvb; - - DISSECTOR_ASSERT(tvb); - DISSECTOR_ASSERT(tvb->ops == get_tvb_real_ops()); - real_tvb->free_cb = func; -} - -static void -add_to_chain(tvbuff_t *parent, tvbuff_t *child) +tvb_add_to_chain(tvbuff_t *parent, tvbuff_t *child) { DISSECTOR_ASSERT(parent && child); DISSECTOR_ASSERT(!child->next && !child->previous); @@ -179,43 +154,6 @@ add_to_chain(tvbuff_t *parent, tvbuff_t *child) parent->next = child; } -void -tvb_set_child_real_data_tvbuff(tvbuff_t *parent, tvbuff_t *child) -{ - DISSECTOR_ASSERT(parent && child); - DISSECTOR_ASSERT(parent->initialized); - DISSECTOR_ASSERT(child->initialized); - DISSECTOR_ASSERT(child->ops == get_tvb_real_ops()); - add_to_chain(parent, child); -} - -tvbuff_t * -tvb_new_real_data(const guint8* data, const guint length, const gint reported_length) -{ - tvbuff_t *tvb; - struct tvb_real *real_tvb; - - THROW_ON(reported_length < -1, ReportedBoundsError); - - tvb = tvb_new(get_tvb_real_ops()); - - tvb->real_data = data; - tvb->length = length; - tvb->reported_length = reported_length; - tvb->initialized = TRUE; - - /* - * This is the top-level real tvbuff for this data source, - * so its data source tvbuff is itself. - */ - tvb->ds_tvb = tvb; - - real_tvb = (struct tvb_real *) tvb; - real_tvb->free_cb = NULL; - - return tvb; -} - tvbuff_t * tvb_new_child_real_data(tvbuff_t *parent, const guint8* data, const guint length, const gint reported_length) { @@ -349,110 +287,12 @@ check_offset_length(const tvbuff_t *tvb, THROW(exception); } -static tvbuff_t * -tvb_new_with_subset(tvbuff_t *backing, const gint reported_length, - const guint subset_tvb_offset, const guint subset_tvb_length) +void +tvb_check_offset_length(const tvbuff_t *tvb, + const gint offset, gint const length_val, + guint *offset_ptr, guint *length_ptr) { - tvbuff_t *tvb = tvb_new(get_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; - add_to_chain(backing, tvb); - - /* 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(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); - - 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); - - 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_length_remaining(backing, backing_offset); - THROW_ON(captured_length < 0, BoundsError); - if (captured_length > backing_length) - captured_length = backing_length; - - 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); - - 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; - - 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); - - return tvb; + check_offset_length(tvb, offset, length_val, offset_ptr, length_ptr); } static const unsigned char left_aligned_bitmask[] = { @@ -625,7 +465,7 @@ tvb_composite_finalize(tvbuff_t *tvb) composite->end_offsets[i] = tvb->length - 1; i++; } - add_to_chain((tvbuff_t *)composite->tvbs->data, tvb); /* chain composite tvb to first member */ + tvb_add_to_chain((tvbuff_t *)composite->tvbs->data, tvb); /* chain composite tvb to first member */ tvb->initialized = TRUE; } @@ -849,8 +689,8 @@ first_real_data_ptr(tvbuff_t *tvb) } #endif -static guint -offset_from_real_beginning(const tvbuff_t *tvb, const guint counter) +guint +tvb_offset_from_real_beginning_counter(const tvbuff_t *tvb, const guint counter) { if (tvb->ops->tvb_offset) return tvb->ops->tvb_offset(tvb, counter); @@ -859,34 +699,19 @@ offset_from_real_beginning(const tvbuff_t *tvb, const guint counter) return 0; } -static guint -real_offset(const tvbuff_t *tvb _U_, const guint counter) -{ - return counter; -} - -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 offset_from_real_beginning(member, counter + subset_tvb->subset.offset); -} - static guint composite_offset(const tvbuff_t *tvb, const guint counter) { const struct tvb_composite *composite_tvb = (const struct tvb_composite *) tvb; const tvbuff_t *member = (const tvbuff_t *)composite_tvb->composite.tvbs->data; - return offset_from_real_beginning(member, counter); + return tvb_offset_from_real_beginning_counter(member, counter); } guint tvb_offset_from_real_beginning(const tvbuff_t *tvb) { - return offset_from_real_beginning(tvb, 0); + return tvb_offset_from_real_beginning_counter(tvb, 0); } static const guint8* @@ -963,14 +788,6 @@ ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint leng return NULL; } -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 ensure_contiguous_no_exception(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length, NULL); -} - static const guint8* ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length) { @@ -1109,14 +926,6 @@ composite_memcpy(tvbuff_t *tvb, void* _target, guint abs_offset, size_t abs_leng DISSECTOR_ASSERT_NOT_REACHED(); } -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); -} - void * tvb_memcpy(tvbuff_t *tvb, void *target, const gint offset, size_t length) { @@ -1962,14 +1771,6 @@ tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu return -1; } -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); -} - /* Find first occurrence of any of the needles in tvbuff, starting at offset. * Searches at most maxlength number of bytes; if maxlength is -1, searches * to end of tvbuff. @@ -2025,20 +1826,6 @@ tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu return -1; } -static gint -subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle) -{ - struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb; - - 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. * @@ -3672,36 +3459,8 @@ tvb_get_ds_tvb(tvbuff_t *tvb) return(tvb->ds_tvb); } -static gsize real_sizeof(void) { return sizeof(struct tvb_real); } -static gsize subset_sizeof(void) { return sizeof(struct tvb_subset); } static gsize composite_sizeof(void) { return sizeof(struct tvb_composite); } -static const struct tvb_ops tvb_real_ops = { - real_sizeof, /* size */ - real_free, /* free */ - real_offset, /* offset */ - NULL, /* get_ptr */ - 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; } - -static const struct tvb_ops tvb_subset_ops = { - subset_sizeof, /* 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 inline const struct tvb_ops *get_tvb_subset_ops(void) { return &tvb_subset_ops; } - static const struct tvb_ops tvb_composite_ops = { composite_sizeof, /* size */ composite_free, /* free */ diff --git a/epan/tvbuff_real.c b/epan/tvbuff_real.c new file mode 100644 index 0000000000..c1014eddbf --- /dev/null +++ b/epan/tvbuff_real.c @@ -0,0 +1,120 @@ +/* tvbuff_real.c + * + * $Id$ + * + * Copyright (c) 2000 by Gilbert Ramirez + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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? */ + +struct tvb_real { + struct tvbuff tvb; + + /** Func to call when actually freed */ + tvbuff_free_cb_t free_cb; +}; + +static gsize +real_sizeof(void) +{ + return sizeof(struct tvb_real); +} + +static void +real_free(tvbuff_t *tvb) +{ + struct tvb_real *real_tvb = (struct tvb_real *) tvb; + + if (real_tvb->free_cb) { + /* + * XXX - do this with a union? + */ + real_tvb->free_cb((gpointer)tvb->real_data); + } +} + +static guint +real_offset(const tvbuff_t *tvb _U_, const guint counter) +{ + return counter; +} + +static const struct tvb_ops tvb_real_ops = { + real_sizeof, /* size */ + real_free, /* free */ + real_offset, /* offset */ + NULL, /* get_ptr */ + NULL, /* memcpy */ + NULL, /* find_guint8 */ + NULL, /* pbrk_guint8 */ + NULL, /* clone */ +}; + +tvbuff_t * +tvb_new_real_data(const guint8* data, const guint length, const gint reported_length) +{ + tvbuff_t *tvb; + struct tvb_real *real_tvb; + + THROW_ON(reported_length < -1, ReportedBoundsError); + + tvb = tvb_new(&tvb_real_ops); + + tvb->real_data = data; + tvb->length = length; + tvb->reported_length = reported_length; + tvb->initialized = TRUE; + + /* + * This is the top-level real tvbuff for this data source, + * so its data source tvbuff is itself. + */ + tvb->ds_tvb = tvb; + + real_tvb = (struct tvb_real *) tvb; + real_tvb->free_cb = NULL; + + return tvb; +} + +void +tvb_set_free_cb(tvbuff_t *tvb, const tvbuff_free_cb_t func) +{ + struct tvb_real *real_tvb = (struct tvb_real *) tvb; + + DISSECTOR_ASSERT(tvb); + DISSECTOR_ASSERT(tvb->ops == &tvb_real_ops); + real_tvb->free_cb = func; +} + +void +tvb_set_child_real_data_tvbuff(tvbuff_t *parent, tvbuff_t *child) +{ + DISSECTOR_ASSERT(parent && child); + DISSECTOR_ASSERT(parent->initialized); + DISSECTOR_ASSERT(child->initialized); + DISSECTOR_ASSERT(child->ops == &tvb_real_ops); + tvb_add_to_chain(parent, child); +} diff --git a/epan/tvbuff_subset.c b/epan/tvbuff_subset.c new file mode 100644 index 0000000000..1dcdecdd6a --- /dev/null +++ b/epan/tvbuff_subset.c @@ -0,0 +1,200 @@ +/* tvbuff_real.c + * + * $Id$ + * + * Copyright (c) 2000 by Gilbert Ramirez + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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? */ + +static gsize +subset_sizeof(void) +{ + return sizeof(struct tvb_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 guint8 *needles, guchar *found_needle) +{ + struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb; + + 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); +} + +static const struct tvb_ops tvb_subset_ops = { + subset_sizeof, /* 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; + tvb_add_to_chain(backing, tvb); + + /* 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(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); + + 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_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); + + 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); + + return tvb; +}