* Testy, Virtual(-izable) Buffer of guint8*'s
*
* "Testy" -- the buffer gets mad when an attempt to access data
- * beyond the bounds of the buffer. An exception is thrown.
+ * beyond the bounds of the buffer. An exception is thrown.
*
* "Virtual" -- the buffer can have its own data, can use a subset of
- * the data of a backing tvbuff, or can be a composite of
- * other tvbuffs.
+ * the data of a backing tvbuff, or can be a composite of
+ * other tvbuffs.
*
* $Id$
*
#include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
static const guint8*
-ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
+ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint length,
int *exception);
static const guint8*
-ensure_contiguous(tvbuff_t *tvb, gint offset, gint length);
+ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length);
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
/* We dole out tvbuff's from this memchunk. */
-GMemChunk *tvbuff_mem_chunk = NULL;
+static GMemChunk *tvbuff_mem_chunk = NULL;
+#endif
void
tvbuff_init(void)
{
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
if (!tvbuff_mem_chunk)
tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
+#endif
}
void
tvbuff_cleanup(void)
{
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
if (tvbuff_mem_chunk)
g_mem_chunk_destroy(tvbuff_mem_chunk);
tvbuff_mem_chunk = NULL;
+#endif
}
-
-
-
static void
-tvb_init(tvbuff_t *tvb, tvbuff_type type)
+tvb_init(tvbuff_t *tvb, const tvbuff_type type)
{
tvb_backing_t *backing;
tvb_comp_t *composite;
composite->start_offsets = NULL;
composite->end_offsets = NULL;
break;
+
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ break;
}
}
tvbuff_t*
-tvb_new(tvbuff_type type)
+tvb_new(const tvbuff_type type)
{
tvbuff_t *tvb;
+#if GLIB_CHECK_VERSION(2,10,0)
+ tvb = g_slice_new(tvbuff_t);
+#else
tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
+#endif
tvb_init(tvb, type);
return tvb;
}
+static tvbuff_t*
+tvb_new_with_subset(const guint subset_tvb_offset, const guint subset_tvb_length)
+{
+ tvbuff_t *tvb = tvb_new(TVBUFF_SUBSET);
+ tvb->tvbuffs.subset.offset = subset_tvb_offset;
+ tvb->tvbuffs.subset.length = subset_tvb_length;
+
+ return tvb;
+}
+
void
tvb_free(tvbuff_t* tvb)
{
g_slist_free(composite->tvbs);
- if (composite->start_offsets)
- g_free(composite->start_offsets);
- if (composite->end_offsets)
- g_free(composite->end_offsets);
+ g_free(composite->start_offsets);
+ g_free(composite->end_offsets);
if (tvb->real_data) {
/*
* XXX - do this with a union?
g_slist_free(tvb->used_in);
}
+#if GLIB_CHECK_VERSION(2,10,0)
+ g_slice_free(tvbuff_t, tvb);
+#else
g_chunk_free(tvb, tvbuff_mem_chunk);
+#endif
}
}
guint
-tvb_increment_usage_count(tvbuff_t* tvb, guint count)
+tvb_increment_usage_count(tvbuff_t* tvb, const guint count)
{
tvb->usage_count += count;
}
guint
-tvb_decrement_usage_count(tvbuff_t* tvb, guint count)
+tvb_decrement_usage_count(tvbuff_t* tvb, const guint count)
{
if (tvb->usage_count <= count) {
tvb->usage_count = 1;
void
-tvb_set_free_cb(tvbuff_t* tvb, tvbuff_free_cb_t func)
+tvb_set_free_cb(tvbuff_t* tvb, const tvbuff_free_cb_t func)
{
DISSECTOR_ASSERT(tvb);
DISSECTOR_ASSERT(tvb->type == TVBUFF_REAL_DATA);
add_to_used_in_list(parent, child);
}
+static void
+tvb_set_real_data_no_exceptions(tvbuff_t* tvb, const guint8* data, const guint length, const gint reported_length)
+{
+ tvb->real_data = data;
+ tvb->length = length;
+ tvb->reported_length = reported_length;
+ tvb->initialized = TRUE;
+}
+
void
-tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
+tvb_set_real_data(tvbuff_t* tvb, const guint8* data, const guint length, const gint reported_length)
{
DISSECTOR_ASSERT(tvb);
DISSECTOR_ASSERT(tvb->type == TVBUFF_REAL_DATA);
DISSECTOR_ASSERT(!tvb->initialized);
- if (reported_length < -1) {
- THROW(ReportedBoundsError);
- }
+ THROW_ON(reported_length < -1, ReportedBoundsError);
- tvb->real_data = data;
- tvb->length = length;
- tvb->reported_length = reported_length;
- tvb->initialized = TRUE;
+ tvb_set_real_data_no_exceptions(tvb, data, length, reported_length);
}
tvbuff_t*
-tvb_new_real_data(const guint8* data, guint length, gint reported_length)
+tvb_new_real_data(const guint8* data, const guint length, const gint reported_length)
{
- static tvbuff_t *last_tvb=NULL;
tvbuff_t *tvb;
- tvb = tvb_new(TVBUFF_REAL_DATA);
+ THROW_ON(reported_length < -1, ReportedBoundsError);
- if(last_tvb){
- tvb_free(last_tvb);
- }
- /* remember this tvb in case we throw an exception and
- * lose the pointer to it.
- */
- last_tvb=tvb;
+ tvb = tvb_new(TVBUFF_REAL_DATA);
- tvb_set_real_data(tvb, data, length, reported_length);
+ tvb_set_real_data_no_exceptions(tvb, data, length, reported_length);
/*
* This is the top-level real tvbuff for this data source,
*/
tvb->ds_tvb = tvb;
- /* ok no exception so we dont need to remember it any longer */
- last_tvb=NULL;
+ return tvb;
+}
+
+tvbuff_t*
+tvb_new_child_real_data(tvbuff_t *parent, const guint8* data, const guint length, const gint reported_length)
+{
+ tvbuff_t *tvb = tvb_new_real_data(data, length, reported_length);
+ if (tvb) {
+ tvb_set_child_real_data_tvbuff (parent, tvb);
+ }
return tvb;
}
* that gets an exception, so the error is reported as an error in that
* protocol rather than the containing protocol. */
static gboolean
-compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
+compute_offset_length(const guint tvb_length_val, const guint tvb_reported_length_val, const gint offset, const gint length_val,
guint *offset_ptr, guint *length_ptr, int *exception)
{
DISSECTOR_ASSERT(offset_ptr);
/* Compute the offset */
if (offset >= 0) {
/* Positive offset - relative to the beginning of the packet. */
- if ((guint) offset > tvb->reported_length) {
+ if ((guint) offset > tvb_reported_length_val) {
if (exception) {
*exception = ReportedBoundsError;
}
return FALSE;
}
- else if ((guint) offset > tvb->length) {
+ else if ((guint) offset > tvb_length_val) {
if (exception) {
*exception = BoundsError;
}
}
else {
/* Negative offset - relative to the end of the packet. */
- if ((guint) -offset > tvb->reported_length) {
+ if ((guint) -offset > tvb_reported_length_val) {
if (exception) {
*exception = ReportedBoundsError;
}
return FALSE;
}
- else if ((guint) -offset > tvb->length) {
+ else if ((guint) -offset > tvb_length_val) {
if (exception) {
*exception = BoundsError;
}
return FALSE;
}
else {
- *offset_ptr = tvb->length + offset;
+ *offset_ptr = tvb_length_val + offset;
}
}
/* Compute the length */
- if (length < -1) {
+ if (length_val < -1) {
if (exception) {
/* XXX - ReportedBoundsError? */
*exception = BoundsError;
}
return FALSE;
}
- else if (length == -1) {
- *length_ptr = tvb->length - *offset_ptr;
+ else if (length_val == -1) {
+ *length_ptr = tvb_length_val - *offset_ptr;
}
else {
- *length_ptr = length;
+ *length_ptr = length_val;
}
return TRUE;
static gboolean
-check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
+check_offset_length_no_exception(const guint tvb_length_val, const guint tvb_reported_length_val, const gint offset, gint const length_val,
guint *offset_ptr, guint *length_ptr, int *exception)
{
guint end_offset;
- DISSECTOR_ASSERT(tvb && tvb->initialized);
-
- if (!compute_offset_length(tvb, offset, length, offset_ptr, length_ptr, exception)) {
+ if (!compute_offset_length(tvb_length_val, tvb_reported_length_val, offset, length_val, offset_ptr, length_ptr, exception)) {
return FALSE;
}
* If not, return TRUE; otherwise, return FALSE and, if "exception"
* is non-null, return the appropriate exception through it.
*/
- if (end_offset <= tvb->length) {
+ if (end_offset <= tvb_length_val) {
return TRUE;
}
- else if (end_offset <= tvb->reported_length) {
+ else if (end_offset <= tvb_reported_length_val) {
if (exception) {
*exception = BoundsError;
}
- return FALSE;
}
else {
if (exception) {
*exception = ReportedBoundsError;
}
- return FALSE;
}
- DISSECTOR_ASSERT_NOT_REACHED();
+ return FALSE;
}
/* Checks (+/-) offset and length and throws an exception if
* either is out of bounds. Sets integer ptrs to the new offset
* and length. */
static void
-check_offset_length(tvbuff_t *tvb, gint offset, gint length,
+check_offset_length(const guint tvb_length_val, const guint tvb_reported_length_val, const gint offset, gint const length_val,
guint *offset_ptr, guint *length_ptr)
{
int exception = 0;
- if (!check_offset_length_no_exception(tvb, offset, length, offset_ptr, length_ptr, &exception)) {
+ if (!check_offset_length_no_exception(tvb_length_val, tvb_reported_length_val, offset, length_val, offset_ptr, length_ptr, &exception)) {
DISSECTOR_ASSERT(exception > 0);
THROW(exception);
}
- return;
}
-
-void
-tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
- gint backing_offset, gint backing_length, gint reported_length)
+static void
+tvb_set_subset_no_exceptions(tvbuff_t *tvb, tvbuff_t *backing, const gint reported_length)
{
- DISSECTOR_ASSERT(tvb);
- DISSECTOR_ASSERT(tvb->type == TVBUFF_SUBSET);
- DISSECTOR_ASSERT(!tvb->initialized);
-
- if (reported_length < -1) {
- THROW(ReportedBoundsError);
- }
-
- check_offset_length(backing, backing_offset, backing_length,
- &tvb->tvbuffs.subset.offset,
- &tvb->tvbuffs.subset.length);
-
tvb->tvbuffs.subset.tvb = backing;
tvb->length = tvb->tvbuffs.subset.length;
}
}
+void
+tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
+ const gint backing_offset, const gint backing_length, const gint reported_length)
+{
+ DISSECTOR_ASSERT(tvb);
+ DISSECTOR_ASSERT(tvb->type == TVBUFF_SUBSET);
+ DISSECTOR_ASSERT(!tvb->initialized);
+
+ THROW_ON(reported_length < -1, ReportedBoundsError);
+
+ check_offset_length(backing->length, backing->reported_length, backing_offset, backing_length,
+ &tvb->tvbuffs.subset.offset,
+ &tvb->tvbuffs.subset.length);
+
+ tvb_set_subset_no_exceptions(tvb, backing, reported_length);
+}
tvbuff_t*
-tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint reported_length)
+tvb_new_subset(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
{
- static tvbuff_t *last_tvb=NULL;
tvbuff_t *tvb;
+ guint subset_tvb_offset;
+ guint subset_tvb_length;
- tvb = tvb_new(TVBUFF_SUBSET);
+ DISSECTOR_ASSERT(backing && backing->initialized);
- if(last_tvb){
- tvb_free(last_tvb);
- }
- /* remember this tvb in case we throw an exception and
- * lose the pointer to it.
- */
- last_tvb=tvb;
+ THROW_ON(reported_length < -1, ReportedBoundsError);
+
+ check_offset_length(backing->length, backing->reported_length, backing_offset, backing_length,
+ &subset_tvb_offset,
+ &subset_tvb_length);
- tvb_set_subset(tvb, backing, backing_offset, backing_length, reported_length);
+ tvb = tvb_new_with_subset(subset_tvb_offset, subset_tvb_length);
+
+ tvb_set_subset_no_exceptions(tvb, backing, reported_length);
/*
* The top-level data source of this tvbuff is the top-level
*/
tvb->ds_tvb = backing->ds_tvb;
- /* ok no exception so we dont need to remember it any longer */
- last_tvb=NULL;
+ 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->length, backing->reported_length, backing_offset, -1 /* backing_length */,
+ &subset_tvb_offset,
+ &subset_tvb_length);
+
+ tvb = tvb_new_with_subset(subset_tvb_offset, subset_tvb_length);
+
+ tvb_set_subset_no_exceptions(tvb, backing, -1 /* reported_length */);
+
+ /*
+ * 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;
}
tvb_comp_t *composite;
DISSECTOR_ASSERT(tvb && !tvb->initialized);
+ DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
composite = &tvb->tvbuffs.composite;
composite->tvbs = g_slist_append( composite->tvbs, member );
- add_to_used_in_list(member, tvb);
+ add_to_used_in_list(tvb, member);
}
void
tvb_comp_t *composite;
DISSECTOR_ASSERT(tvb && !tvb->initialized);
+ DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
composite = &tvb->tvbuffs.composite;
composite->tvbs = g_slist_prepend( composite->tvbs, member );
- add_to_used_in_list(member, tvb);
+ add_to_used_in_list(tvb, member);
}
tvbuff_t*
int i = 0;
DISSECTOR_ASSERT(tvb && !tvb->initialized);
+ DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
DISSECTOR_ASSERT(tvb->length == 0);
composite = &tvb->tvbuffs.composite;
guint
-tvb_length(tvbuff_t* tvb)
+tvb_length(const tvbuff_t* tvb)
{
DISSECTOR_ASSERT(tvb && tvb->initialized);
}
gint
-tvb_length_remaining(tvbuff_t *tvb, gint offset)
+tvb_length_remaining(const tvbuff_t *tvb, const gint offset)
{
guint abs_offset, abs_length;
DISSECTOR_ASSERT(tvb && tvb->initialized);
- if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
+ if (compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL)) {
return abs_length;
}
else {
}
guint
-tvb_ensure_length_remaining(tvbuff_t *tvb, gint offset)
+tvb_ensure_length_remaining(const tvbuff_t *tvb, const gint offset)
{
guint abs_offset, abs_length;
int exception;
DISSECTOR_ASSERT(tvb && tvb->initialized);
- if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, &exception)) {
+ if (!compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, &exception)) {
THROW(exception);
}
if (abs_length == 0) {
/* Validates that 'length' bytes are available starting from
* offset (pos/neg). Does not throw an exception. */
gboolean
-tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
+tvb_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
{
guint abs_offset, abs_length;
DISSECTOR_ASSERT(tvb && tvb->initialized);
- if (!compute_offset_length(tvb, offset, length, &abs_offset, &abs_length, NULL))
+ if (!compute_offset_length(tvb->length, tvb->reported_length, offset, length, &abs_offset, &abs_length, NULL))
return FALSE;
if (abs_offset + abs_length <= tvb->length) {
/* Validates that 'length' bytes are available starting from
* offset (pos/neg). Throws an exception if they aren't. */
void
-tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
+tvb_ensure_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
{
guint abs_offset, abs_length;
if (length < 0) {
THROW(ReportedBoundsError);
}
- check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
+ check_offset_length(tvb->length, tvb->reported_length, offset, length, &abs_offset, &abs_length);
}
gboolean
-tvb_offset_exists(tvbuff_t *tvb, gint offset)
+tvb_offset_exists(const tvbuff_t *tvb, const gint offset)
{
guint abs_offset, abs_length;
DISSECTOR_ASSERT(tvb && tvb->initialized);
- if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL))
+ if (!compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL))
return FALSE;
if (abs_offset < tvb->length) {
}
guint
-tvb_reported_length(tvbuff_t* tvb)
+tvb_reported_length(const tvbuff_t* tvb)
{
DISSECTOR_ASSERT(tvb && tvb->initialized);
}
gint
-tvb_reported_length_remaining(tvbuff_t *tvb, gint offset)
+tvb_reported_length_remaining(const tvbuff_t *tvb, const gint offset)
{
guint abs_offset, abs_length;
DISSECTOR_ASSERT(tvb && tvb->initialized);
- if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
+ if (compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL)) {
if (tvb->reported_length >= abs_offset)
return tvb->reported_length - abs_offset;
else
Also adjusts the data length. */
void
-tvb_set_reported_length(tvbuff_t* tvb, guint reported_length)
+tvb_set_reported_length(tvbuff_t* tvb, const guint reported_length)
{
DISSECTOR_ASSERT(tvb && tvb->initialized);
}
+#if 0
static const guint8*
first_real_data_ptr(tvbuff_t *tvb)
{
DISSECTOR_ASSERT_NOT_REACHED();
return NULL;
}
+#endif
-int
-offset_from_real_beginning(tvbuff_t *tvb, int counter)
+static guint
+offset_from_real_beginning(const tvbuff_t *tvb, const guint counter)
{
tvbuff_t *member;
return 0;
}
+guint
+tvb_offset_from_real_beginning(const tvbuff_t *tvb)
+{
+ return offset_from_real_beginning(tvb, 0);
+}
+
static const guint8*
-composite_ensure_contiguous_no_exception(tvbuff_t *tvb, guint abs_offset,
- guint abs_length)
+composite_ensure_contiguous_no_exception(tvbuff_t *tvb, const guint abs_offset,
+ const guint abs_length)
{
guint i, num_members;
tvb_comp_t *composite;
}
DISSECTOR_ASSERT(member_tvb);
- if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
+ if (check_offset_length_no_exception(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i],
abs_length, &member_offset, &member_length, NULL)) {
/*
}
static const guint8*
-ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
+ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint length,
int *exception)
{
guint abs_offset, abs_length;
- if (!check_offset_length_no_exception(tvb, offset, length,
- &abs_offset, &abs_length, exception)) {
+ if (!check_offset_length_no_exception(tvb->length, tvb->reported_length, offset, length,
+ &abs_offset, &abs_length, exception)) {
return NULL;
}
}
static const guint8*
-ensure_contiguous(tvbuff_t *tvb, gint offset, gint length)
+ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length)
{
int exception;
const guint8 *p;
}
static const guint8*
-guint8_find(const guint8* haystack, size_t haystacklen, guint8 needle)
+fast_ensure_contiguous(tvbuff_t *tvb, const gint offset, const guint length)
{
- const guint8 *b;
- int i;
+ guint end_offset;
+ guint u_offset;
- for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
- if (*b == needle) {
- return b;
- }
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+ /* We don't check for overflow in this fast path so we only handle simple types */
+ DISSECTOR_ASSERT(length <= 8);
+
+ if (offset < 0 || !tvb->real_data) {
+ return ensure_contiguous(tvb, offset, length);
+ }
+
+ u_offset = offset;
+ end_offset = u_offset + length;
+
+ if (end_offset <= tvb->length) {
+ return tvb->real_data + u_offset;
}
+ if (end_offset > tvb->reported_length) {
+ THROW(ReportedBoundsError);
+ }
+ THROW(BoundsError);
+ /* not reached */
return NULL;
}
static const guint8*
-guint8_pbrk(const guint8* haystack, size_t haystacklen, guint8 *needles)
-{
- const guint8 *b;
- int i;
- guint8 item, *needlep, needle;
-
- for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
- item = *b;
- needlep = needles;
- while ((needle = *needlep) != '\0') {
- if (item == needle)
- return b;
- needlep++;
+guint8_pbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles, guchar *found_needle)
+{
+ gchar tmp[256] = { 0 };
+ const guint8 *haystack_end;
+
+ while (*needles)
+ tmp[*needles++] = 1;
+
+ haystack_end = haystack + haystacklen;
+ while (haystack < haystack_end) {
+ if (tmp[*haystack]) {
+ if(found_needle)
+ *found_needle = *haystack;
+ return haystack;
}
+ haystack++;
}
return NULL;
/************** ACCESSORS **************/
-static guint8*
-composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, guint abs_length)
+static void*
+composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, size_t abs_length)
{
guint i, num_members;
tvb_comp_t *composite;
}
DISSECTOR_ASSERT(member_tvb);
- if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
- abs_length, &member_offset, &member_length, NULL)) {
+ if (check_offset_length_no_exception(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i],
+ (gint) abs_length, &member_offset, &member_length, NULL)) {
DISSECTOR_ASSERT(!tvb->real_data);
return tvb_memcpy(member_tvb, target, member_offset, member_length);
* then iterate across the other member tvb's, copying their portions
* until we have copied all data.
*/
- retval = compute_offset_length(member_tvb, abs_offset - composite->start_offsets[i], -1,
+ retval = compute_offset_length(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i], -1,
&member_offset, &member_length, NULL);
DISSECTOR_ASSERT(retval);
return NULL;
}
-guint8*
-tvb_memcpy(tvbuff_t *tvb, guint8* target, gint offset, gint length)
+void*
+tvb_memcpy(tvbuff_t *tvb, void* target, const gint offset, size_t length)
{
guint abs_offset, abs_length;
- DISSECTOR_ASSERT(length >= -1);
- check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ /*
+ * XXX - we should eliminate the "length = -1 means 'to the end
+ * of the tvbuff'" convention, and use other means to achieve
+ * that; this would let us eliminate a bunch of checks for
+ * negative lengths in cases where the protocol has a 32-bit
+ * length field.
+ *
+ * Allowing -1 but throwing an assertion on other negative
+ * lengths is a bit more work with the length being a size_t;
+ * instead, we check for a length <= 2^31-1.
+ */
+ DISSECTOR_ASSERT(length <= 0x7FFFFFFF);
+ check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
if (tvb->real_data) {
- return (guint8*) memcpy(target, tvb->real_data + abs_offset, abs_length);
+ return memcpy(target, tvb->real_data + abs_offset, abs_length);
}
switch(tvb->type) {
* an error; does anything else depend on this routine treating -1 as
* meaning "to the end of the buffer"?
*/
-guint8*
-tvb_memdup(tvbuff_t *tvb, gint offset, gint length)
+void*
+tvb_memdup(tvbuff_t *tvb, const gint offset, size_t length)
{
guint abs_offset, abs_length;
- guint8 *duped;
+ void *duped;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
- check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
+ check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
duped = g_malloc(abs_length);
return tvb_memcpy(tvb, duped, abs_offset, abs_length);
* Do not use this function if you want the allocated memory to be persistent
* after the current packet has been dissected.
*/
-guint8*
-ep_tvb_memdup(tvbuff_t *tvb, gint offset, gint length)
+void*
+ep_tvb_memdup(tvbuff_t *tvb, const gint offset, size_t length)
{
guint abs_offset, abs_length;
- guint8 *duped;
+ void *duped;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
- check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
+ check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
duped = ep_alloc(abs_length);
return tvb_memcpy(tvb, duped, abs_offset, abs_length);
const guint8*
-tvb_get_ptr(tvbuff_t *tvb, gint offset, gint length)
+tvb_get_ptr(tvbuff_t *tvb, const gint offset, const gint length)
{
return ensure_contiguous(tvb, offset, length);
}
+/* ---------------- */
guint8
-tvb_get_guint8(tvbuff_t *tvb, gint offset)
+tvb_get_guint8(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, sizeof(guint8));
+ ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint8));
return *ptr;
}
guint16
-tvb_get_ntohs(tvbuff_t *tvb, gint offset)
+tvb_get_ntohs(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
+ ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint16));
return pntohs(ptr);
}
guint32
-tvb_get_ntoh24(tvbuff_t *tvb, gint offset)
+tvb_get_ntoh24(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, 3);
+ ptr = fast_ensure_contiguous(tvb, offset, 3);
return pntoh24(ptr);
}
guint32
-tvb_get_ntohl(tvbuff_t *tvb, gint offset)
+tvb_get_ntohl(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
+ ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
return pntohl(ptr);
}
guint64
-tvb_get_ntoh64(tvbuff_t *tvb, gint offset)
+tvb_get_ntoh64(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, sizeof(guint64));
+ ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint64));
return pntoh64(ptr);
}
#define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
static int
-ieee_float_is_zero(guint32 w)
+ieee_float_is_zero(const guint32 w)
{
return ((w & ~IEEE_SP_SIGN_MASK) == 0);
}
static gfloat
-get_ieee_float(guint32 w)
+get_ieee_float(const guint32 w)
{
long sign;
long exponent;
#endif
exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
- IEEE_SP_MANTISSA_WIDTH;
+ IEEE_SP_MANTISSA_WIDTH;
mantissa |= IEEE_SP_IMPLIED_BIT;
if (sign)
#define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
static int
-ieee_double_is_zero(guint64 w)
+ieee_double_is_zero(const guint64 w)
{
return ((w & ~IEEE_SP_SIGN_MASK) == 0);
}
static gdouble
-get_ieee_double(guint64 w)
+get_ieee_double(const guint64 w)
{
gint64 sign;
gint64 exponent;
#endif
exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
- IEEE_DP_MANTISSA_WIDTH;
+ IEEE_DP_MANTISSA_WIDTH;
mantissa |= IEEE_DP_IMPLIED_BIT;
if (sign)
* "float" format?
*/
gfloat
-tvb_get_ntohieee_float(tvbuff_t *tvb, int offset)
+tvb_get_ntohieee_float(tvbuff_t *tvb, const int offset)
{
#if defined(vax)
return get_ieee_float(tvb_get_ntohl(tvb, offset));
* big-endian form, and returns a "double".
*/
gdouble
-tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
+tvb_get_ntohieee_double(tvbuff_t *tvb, const int offset)
{
#if defined(vax)
union {
}
guint16
-tvb_get_letohs(tvbuff_t *tvb, gint offset)
+tvb_get_letohs(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
+ ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint16));
return pletohs(ptr);
}
guint32
-tvb_get_letoh24(tvbuff_t *tvb, gint offset)
+tvb_get_letoh24(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, 3);
+ ptr = fast_ensure_contiguous(tvb, offset, 3);
return pletoh24(ptr);
}
guint32
-tvb_get_letohl(tvbuff_t *tvb, gint offset)
+tvb_get_letohl(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
+ ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
return pletohl(ptr);
}
guint64
-tvb_get_letoh64(tvbuff_t *tvb, gint offset)
+tvb_get_letoh64(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
- ptr = ensure_contiguous(tvb, offset, sizeof(guint64));
+ ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint64));
return pletoh64(ptr);
}
* "float" format?
*/
gfloat
-tvb_get_letohieee_float(tvbuff_t *tvb, int offset)
+tvb_get_letohieee_float(tvbuff_t *tvb, const int offset)
{
#if defined(vax)
return get_ieee_float(tvb_get_letohl(tvb, offset));
* little-endian form, and returns a "double".
*/
gdouble
-tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
+tvb_get_letohieee_double(tvbuff_t *tvb, const int offset)
{
#if defined(vax)
union {
* We do *not* convert them to host byte order; we leave them in
* network byte order. */
guint32
-tvb_get_ipv4(tvbuff_t *tvb, gint offset)
+tvb_get_ipv4(tvbuff_t *tvb, const gint offset)
{
const guint8* ptr;
guint32 addr;
- ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
+ ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
memcpy(&addr, ptr, sizeof addr);
return addr;
}
/* Fetch an IPv6 address. */
void
-tvb_get_ipv6(tvbuff_t *tvb, gint offset, struct e_in6_addr *addr)
+tvb_get_ipv6(tvbuff_t *tvb, const gint offset, struct e_in6_addr *addr)
{
const guint8* ptr;
/* Fetch a GUID. */
void
-tvb_get_ntohguid(tvbuff_t *tvb, gint offset, e_guid_t *guid)
+tvb_get_ntohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid)
{
ensure_contiguous(tvb, offset, sizeof(*guid));
guid->data1 = tvb_get_ntohl(tvb, offset);
}
void
-tvb_get_letohguid(tvbuff_t *tvb, gint offset, e_guid_t *guid)
+tvb_get_letohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid)
{
ensure_contiguous(tvb, offset, sizeof(*guid));
guid->data1 = tvb_get_letohl(tvb, offset);
tvb_memcpy(tvb, guid->data4, offset + 8, sizeof guid->data4);
}
+/*
+ * NOTE: to support code written when proto_tree_add_item() took a
+ * gboolean as its last argument, with FALSE meaning "big-endian"
+ * and TRUE meaning "little-endian", we treat any non-zero value of
+ * "representation" as meaning "little-endian".
+ */
void
-tvb_get_guid(tvbuff_t *tvb, gint offset, e_guid_t *guid, gboolean little_endian)
+tvb_get_guid(tvbuff_t *tvb, const gint offset, e_guid_t *guid, const guint representation)
{
- if (little_endian) {
+ if (representation) {
tvb_get_letohguid(tvb, offset, guid);
} else {
tvb_get_ntohguid(tvb, offset, guid);
}
}
+static const guint8 bit_mask8[] = {
+ 0xff,
+ 0x7f,
+ 0x3f,
+ 0x1f,
+ 0x0f,
+ 0x07,
+ 0x03,
+ 0x01
+};
+
+/* Bit offset mask for number of bits = 8 - 16 */
+static const guint16 bit_mask16[] = {
+ 0xffff,
+ 0x7fff,
+ 0x3fff,
+ 0x1fff,
+ 0x0fff,
+ 0x07ff,
+ 0x03ff,
+ 0x01ff
+};
+
+/* Get 1 - 8 bits */
+guint8
+tvb_get_bits8(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits)
+{
+ gint offset;
+ guint16 value = 0;
+ guint8 tot_no_bits;
+
+ if (no_of_bits>8) {
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ /* Byte align offset */
+ offset = bit_offset>>3;
+
+ /* Find out which mask to use for the most significant octet
+ * by convering bit_offset into the offset into the first
+ * fetched octet.
+ */
+ bit_offset = bit_offset & 0x7;
+ tot_no_bits = bit_offset+no_of_bits;
+ if(tot_no_bits<=8){
+ /* Read one octet, mask off bit_offset bits and left shift out the unused bits */
+ value = tvb_get_guint8(tvb,offset) & bit_mask8[bit_offset];
+ value = value >> (8-tot_no_bits);
+ }else{
+ /* Read two octets, mask off bit_offset bits and left shift out the unused bits */
+ value = tvb_get_ntohs(tvb,offset) & bit_mask16[bit_offset];
+ value = value >> (16 - tot_no_bits);
+ }
+
+ return (guint8)value;
+}
+
+/* Get 9 - 16 bits */
+/* Bit offset mask for number of bits = 16 - 32 */
+static const guint32 bit_mask32[] = {
+ 0xffffffff,
+ 0x7fffffff,
+ 0x3fffffff,
+ 0x1fffffff,
+ 0x0fffffff,
+ 0x07ffffff,
+ 0x03ffffff,
+ 0x01ffffff
+};
+
+guint16
+tvb_get_bits16(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits,const gboolean little_endian)
+{
+ gint offset;
+ guint16 value = 0;
+ guint16 tempval = 0;
+ guint8 tot_no_bits;
+
+ if ((no_of_bits<=8)||(no_of_bits>16)) {
+ /* If bits <= 8 use tvb_get_bits8 */
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ if(little_endian){
+ DISSECTOR_ASSERT_NOT_REACHED();
+ /* This part is not implemented yet */
+ }
+
+ /* Byte align offset */
+ offset = bit_offset>>3;
+
+ /* Find out which mask to use for the most significant octet
+ * by convering bit_offset into the offset into the first
+ * fetched octet.
+ */
+ bit_offset = bit_offset & 0x7;
+ tot_no_bits = bit_offset+no_of_bits;
+ /* Read two octets and mask off bit_offset bits */
+ value = tvb_get_ntohs(tvb,offset) & bit_mask16[bit_offset];
+ if(tot_no_bits < 16){
+ /* Left shift out the unused bits */
+ value = value >> (16 - tot_no_bits);
+ }else if(tot_no_bits > 16){
+ /* Spans three octets, read next octet and shift as needed */
+ value = value << (tot_no_bits - 16);
+ tempval = tvb_get_guint8(tvb,offset+2);
+ tempval = tempval >> (24-tot_no_bits);
+ value = value | tempval;
+ }
+
+ return value;
+}
+
+/* Bit offset mask for number of bits = 32 - 64 */
+static const guint64 bit_mask64[] = {
+ G_GINT64_CONSTANT(0xffffffffffffffffU),
+ G_GINT64_CONSTANT(0x7fffffffffffffffU),
+ G_GINT64_CONSTANT(0x3fffffffffffffffU),
+ G_GINT64_CONSTANT(0x1fffffffffffffffU),
+ G_GINT64_CONSTANT(0x0fffffffffffffffU),
+ G_GINT64_CONSTANT(0x07ffffffffffffffU),
+ G_GINT64_CONSTANT(0x03ffffffffffffffU),
+ G_GINT64_CONSTANT(0x01ffffffffffffffU)
+};
+
+guint32
+tvb_get_bits32(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const gboolean little_endian)
+{
+ gint offset;
+ guint32 value = 0;
+ guint32 tempval = 0;
+ guint8 tot_no_bits;
+ guint8 tot_no_octets = 0;
+ guint8 i = 0;
+ gint8 shift = 0;
+
+ if ((no_of_bits<=16)||(no_of_bits>32)) {
+ /* If bits <= 16 use tvb_get_bits8 or tvb_get_bits16 */
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ if(little_endian){
+ DISSECTOR_ASSERT_NOT_REACHED();
+ /* This part is not implemented yet */
+ }
+
+ /* Byte align offset */
+ offset = bit_offset>>3;
+
+ bit_offset = bit_offset & 0x7;
+ tot_no_bits = bit_offset+no_of_bits;
+ tot_no_octets = tot_no_bits / 8;
+ if (tot_no_bits % 8)
+ tot_no_octets++;
+ shift = no_of_bits - (8 - bit_offset);
+
+ value = tvb_get_guint8(tvb, offset) & bit_mask8[bit_offset];
+ value = value << shift;
+
+ for (i = 1; i < tot_no_octets; i++)
+ {
+ shift = shift - 8;
+ tempval = tvb_get_guint8(tvb, offset+i);
+ if (shift >= 0)
+ {
+ tempval = tempval << shift;
+ }
+ else
+ {
+ tempval = tempval >> (8 - shift);
+ }
+ value = value | tempval;
+ }
+
+ return value;
+}
+
+guint64
+tvb_get_bits64(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const gboolean little_endian)
+{
+ gint offset;
+ guint64 value = 0;
+ guint64 tempval = 0;
+ guint8 tot_no_bits;
+
+ if ((no_of_bits<=32)||(no_of_bits>64)) {
+ /* If bits <= 32 use tvb_get_bits8, tvb_get_bits16 or tvb_get_bits32 */
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ if(little_endian){
+ DISSECTOR_ASSERT_NOT_REACHED();
+ /* This part is not implemented yet */
+ }
+
+ /* Byte align offset */
+ offset = bit_offset>>3;
+
+ /* Find out which mask to use for the most significant octet
+ * by convering bit_offset into the offset into the first
+ * fetched octet.
+ */
+ bit_offset = bit_offset & 0x7;
+ tot_no_bits = bit_offset+no_of_bits;
+ /* Read eight octets and mask off bit_offset bits */
+ value = tvb_get_ntoh64(tvb,offset) & bit_mask64[bit_offset];
+ if (tot_no_bits < 64){
+ /* Left shift out the unused bits */
+ value = value >> (64 - tot_no_bits);
+ }else if (tot_no_bits > 64){
+ /* Spans nine octets, read next octet and shift as needed */
+ value = value << (tot_no_bits - 64);
+ tempval = tvb_get_guint8(tvb,offset+8);
+ tempval = tempval >> (72-tot_no_bits);
+ value = value | tempval;
+ }
+
+ return value;
+}
+
+guint32
+tvb_get_bits(tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits, const gboolean little_endian)
+{
+ /* This function can handle only up to 32 requested bits */
+ if (no_of_bits > 32)
+ DISSECTOR_ASSERT_NOT_REACHED();
+
+ if (no_of_bits == 0)
+ return 0;
+
+ /* Number of requested bits is in range [17, 32] */
+ if (no_of_bits > 16)
+ return tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
+
+ /* Number of requested bits is in range [9, 16] */
+ if (no_of_bits > 8)
+ return tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
+
+ /* Number of requested bits is in range [1, 8] */
+ return tvb_get_bits8(tvb, bit_offset, no_of_bits);
+}
+
/* Find first occurence of needle in tvbuff, starting at offset. Searches
* at most maxlength number of bytes; if maxlength is -1, searches to
* end of tvbuff.
* in that case, -1 will be returned if the boundary is reached before
* finding needle. */
gint
-tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
+tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 needle)
{
const guint8 *result;
guint abs_offset, junk_length;
guint tvbufflen;
guint limit;
- check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
/* Only search to end of tvbuff, w/o throwing exception. */
tvbufflen = tvb_length_remaining(tvb, abs_offset);
/* If we have real data, perform our search now. */
if (tvb->real_data) {
- result = guint8_find(tvb->real_data + abs_offset, limit, needle);
+ result = memchr(tvb->real_data + abs_offset, needle, limit);
if (result == NULL) {
return -1;
}
else {
- return result - tvb->real_data;
+ return (gint) (result - tvb->real_data);
}
}
* in that case, -1 will be returned if the boundary is reached before
* finding needle. */
gint
-tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, const guint8 *needles)
+tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 *needles, guchar *found_needle)
{
const guint8 *result;
guint abs_offset, junk_length;
guint tvbufflen;
guint limit;
- check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
/* Only search to end of tvbuff, w/o throwing exception. */
tvbufflen = tvb_length_remaining(tvb, abs_offset);
/* If we have real data, perform our search now. */
if (tvb->real_data) {
- result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles);
+ result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles, found_needle);
if (result == NULL) {
return -1;
}
else {
- return result - tvb->real_data;
+ return (gint) (result - tvb->real_data);
}
}
case TVBUFF_SUBSET:
return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
abs_offset - tvb->tvbuffs.subset.offset,
- limit, needles);
+ limit, needles, found_needle);
case TVBUFF_COMPOSITE:
DISSECTOR_ASSERT_NOT_REACHED();
* If the NUL isn't found, it throws the appropriate exception.
*/
guint
-tvb_strsize(tvbuff_t *tvb, gint offset)
+tvb_strsize(tvbuff_t *tvb, const gint offset)
{
guint abs_offset, junk_length;
gint nul_offset;
- check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
if (nul_offset == -1) {
/*
* an exception.
*
* Did we hit the end of the captured data, or the end
- * of the actual data? If there's less captured data
+ * of the actual data? If there's less captured data
* than actual data, we presumably hit the end of the
* captured data, otherwise we hit the end of the actual
* data.
* of tvbuff.
* Returns -1 if 'maxlength' reached before finding EOS. */
gint
-tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
+tvb_strnlen(tvbuff_t *tvb, const gint offset, const guint maxlength)
{
gint result_offset;
guint abs_offset, junk_length;
- check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
* it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
*/
gint
-tvb_strneql(tvbuff_t *tvb, gint offset, const gchar *str, gint size)
+tvb_strneql(tvbuff_t *tvb, const gint offset, const gchar *str, const gint size)
{
const guint8 *ptr;
}
/*
- * Call strncasecmp after checking if enough chars left, returning 0 if
- * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
+ * Call g_ascii_strncasecmp after checking if enough chars left, returning
+ * 0 if it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
*/
gint
-tvb_strncaseeql(tvbuff_t *tvb, gint offset, const gchar *str, gint size)
+tvb_strncaseeql(tvbuff_t *tvb, const gint offset, const gchar *str, const gint size)
{
const guint8 *ptr;
ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
if (ptr) {
- int cmp = strncasecmp((const char *)ptr, str, size);
+ int cmp = g_ascii_strncasecmp((const char *)ptr, str, size);
/*
* Return 0 if equal, -1 otherwise.
* it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
*/
gint
-tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
+tvb_memeql(tvbuff_t *tvb, const gint offset, const guint8 *str, size_t size)
{
const guint8 *ptr;
- ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
+ ptr = ensure_contiguous_no_exception(tvb, offset, (gint) size, NULL);
if (ptr) {
int cmp = memcmp(ptr, str, size);
}
}
-/* Convert a string from Unicode to ASCII. At the moment we fake it by
+/* Convert a string from Unicode to ASCII. At the moment we fake it by
* replacing all non-ASCII characters with a '.' )-: The caller must
* free the result returned. The len parameter is the number of guint16's
* to convert from Unicode. */
char *
-tvb_fake_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
+tvb_fake_unicode(tvbuff_t *tvb, int offset, const int len, const gboolean little_endian)
{
char *buffer;
int i;
return buffer;
}
-/* Convert a string from Unicode to ASCII. At the moment we fake it by
+/* Convert a string from Unicode to ASCII. At the moment we fake it by
* replacing all non-ASCII characters with a '.' )-: The len parameter is
* the number of guint16's to convert from Unicode.
*
* when wireshark starts decoding the next packet.
*/
char *
-tvb_get_ephemeral_faked_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
+tvb_get_ephemeral_faked_unicode(tvbuff_t *tvb, int offset, const int len, const gboolean little_endian)
{
char *buffer;
int i;
*/
gchar *
-tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
+tvb_format_text(tvbuff_t *tvb, const gint offset, const gint size)
{
const guint8 *ptr;
gint len = size;
if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
-
len = tvb_length_remaining(tvb, offset);
ptr = ensure_contiguous(tvb, offset, len);
-
}
return format_text(ptr, len);
-
}
/*
*/
gchar *
-tvb_format_text_wsp(tvbuff_t *tvb, gint offset, gint size)
+tvb_format_text_wsp(tvbuff_t *tvb, const gint offset, const gint size)
{
const guint8 *ptr;
gint len = size;
if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
- len = tvb_length_remaining(tvb, offset);
- ptr = ensure_contiguous(tvb, offset, len);
+ len = tvb_length_remaining(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, len);
}
* the null padding characters as "\000".
*/
gchar *
-tvb_format_stringzpad(tvbuff_t *tvb, gint offset, gint size)
+tvb_format_stringzpad(tvbuff_t *tvb, const gint offset, const gint size)
{
const guint8 *ptr, *p;
gint len = size;
if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
- len = tvb_length_remaining(tvb, offset);
- ptr = ensure_contiguous(tvb, offset, len);
+ len = tvb_length_remaining(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, len);
}
for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
- ;
+ ;
return format_text(ptr, stringlen);
}
+/*
+ * Like "tvb_format_text_wsp()", but for null-padded strings; don't show
+ * the null padding characters as "\000".
+ */
+gchar *
+tvb_format_stringzpad_wsp(tvbuff_t *tvb, const gint offset, const gint size)
+{
+ const guint8 *ptr, *p;
+ gint len = size;
+ gint stringlen;
+
+ if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
+
+ len = tvb_length_remaining(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, len);
+
+ }
+
+ for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
+ ;
+ return format_text_wsp(ptr, stringlen);
+
+}
+
/*
* Given a tvbuff, an offset, and a length, allocate a buffer big enough
* to hold a non-null-terminated string of that length at that offset,
* Throws an exception if the tvbuff ends before the string does.
*/
guint8 *
-tvb_get_string(tvbuff_t *tvb, gint offset, gint length)
+tvb_get_string(tvbuff_t *tvb, const gint offset, const gint length)
{
const guint8 *ptr;
guint8 *strbuf = NULL;
* after the current packet has been dissected.
*/
guint8 *
-tvb_get_ephemeral_string(tvbuff_t *tvb, gint offset, gint length)
+tvb_get_ephemeral_string(tvbuff_t *tvb, const gint offset, const gint length)
{
const guint8 *ptr;
guint8 *strbuf = NULL;
return strbuf;
}
+/*
+ * Given a tvbuff, an offset, and a length, allocate a buffer big enough
+ * to hold a non-null-terminated string of that length at that offset,
+ * plus a trailing '\0', copy the string into it, and return a pointer
+ * to the string.
+ *
+ * Throws an exception if the tvbuff ends before the string does.
+ *
+ * This function allocates memory from a buffer with capture session lifetime.
+ * You do not have to free this buffer, it will be automatically freed
+ * when wireshark starts or opens a new capture.
+ */
+guint8 *
+tvb_get_seasonal_string(tvbuff_t *tvb, const gint offset, const gint length)
+{
+ const guint8 *ptr;
+ guint8 *strbuf = NULL;
+
+ tvb_ensure_bytes_exist(tvb, offset, length);
+
+ ptr = ensure_contiguous(tvb, offset, length);
+ strbuf = se_alloc(length + 1);
+ if (length != 0) {
+ memcpy(strbuf, ptr, length);
+ }
+ strbuf[length] = '\0';
+ return strbuf;
+}
/*
* Given a tvbuff and an offset, with the offset assumed to refer to
* a null-terminated string, find the length of that string (and throw
* an exception if the tvbuff ends before we find the null), allocate
* a buffer big enough to hold the string, copy the string into it,
- * and return a pointer to the string. Also return the length of the
+ * and return a pointer to the string. Also return the length of the
* string (including the terminating null) through a pointer.
*/
guint8 *
-tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
+tvb_get_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
{
guint size;
guint8 *strptr;
size = tvb_strsize(tvb, offset);
strptr = g_malloc(size);
tvb_memcpy(tvb, strptr, offset, size);
- *lengthp = size;
+ if (lengthp)
+ *lengthp = size;
return strptr;
}
/*
* a null-terminated string, find the length of that string (and throw
* an exception if the tvbuff ends before we find the null), allocate
* a buffer big enough to hold the string, copy the string into it,
- * and return a pointer to the string. Also return the length of the
+ * and return a pointer to the string. Also return the length of the
* string (including the terminating null) through a pointer.
*
* This function allocates memory from a buffer with packet lifetime.
* after the current packet has been dissected.
*/
guint8 *
-tvb_get_ephemeral_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
+tvb_get_ephemeral_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
{
guint size;
guint8 *strptr;
size = tvb_strsize(tvb, offset);
strptr = ep_alloc(size);
tvb_memcpy(tvb, strptr, offset, size);
- *lengthp = size;
+ if (lengthp)
+ *lengthp = size;
+ return strptr;
+}
+
+/*
+ * Given a tvbuff and an offset, with the offset assumed to refer to
+ * a null-terminated string, find the length of that string (and throw
+ * an exception if the tvbuff ends before we find the null), allocate
+ * a buffer big enough to hold the string, copy the string into it,
+ * and return a pointer to the string. Also return the length of the
+ * string (including the terminating null) through a pointer.
+ *
+ * This function allocates memory from a buffer with capture session lifetime.
+ * You do not have to free this buffer, it will be automatically freed
+ * when wireshark starts or opens a new capture.
+ */
+guint8 *
+tvb_get_seasonal_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
+{
+ guint size;
+ guint8 *strptr;
+
+ size = tvb_strsize(tvb, offset);
+ strptr = se_alloc(size);
+ tvb_memcpy(tvb, strptr, offset, size);
+ if (lengthp)
+ *lengthp = size;
return strptr;
}
* including the terminating-NUL.
*/
static gint
-_tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer,
+_tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer,
gint *bytes_copied)
{
gint stringlen;
gint limit, len;
gboolean decreased_max = FALSE;
- check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+ check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
/* There must at least be room for the terminating NUL. */
DISSECTOR_ASSERT(bufsize != 0);
* at the correct spot, terminating the string.
*/
gint
-tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
+tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer)
{
gint bytes_copied;
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
}
* a NUL is placed at the end of buffer to terminate it.
*/
gint
-tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
+tvb_get_nstringz0(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer)
{
gint len, bytes_copied;
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
if (len == -1) {
*
* Set "*next_offset" to the offset of the character past the line
* terminator, or past the end of the buffer if we don't find a line
- * terminator. (It's not set if we return -1.)
+ * terminator. (It's not set if we return -1.)
*/
gint
-tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
- gboolean desegment)
+tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset,
+ const gboolean desegment)
{
gint eob_offset;
gint eol_offset;
int linelen;
+ guchar found_needle = 0;
if (len == -1)
len = tvb_length_remaining(tvb, offset);
/*
* Look either for a CR or an LF.
*/
- eol_offset = tvb_pbrk_guint8(tvb, offset, len, (const guint8 *)"\r\n");
+ eol_offset = tvb_pbrk_guint8(tvb, offset, len, (const guint8 *)"\r\n", &found_needle);
if (eol_offset == -1) {
/*
* No CR or LF - line is presumably continued in next packet.
* Pretend the line runs to the end of the tvbuff.
*/
linelen = eob_offset - offset;
- *next_offset = eob_offset;
+ if (next_offset)
+ *next_offset = eob_offset;
}
} else {
/*
/*
* Is it a CR?
- */
- if (tvb_get_guint8(tvb, eol_offset) == '\r') {
+ */
+ if (found_needle == '\r') {
/*
* Yes - is it followed by an LF?
*/
* character in the line, skipping over the last character
* in the line terminator.
*/
- *next_offset = eol_offset + 1;
+ if (next_offset)
+ *next_offset = eol_offset + 1;
}
return linelen;
}
* terminator.
*/
gint
-tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
- gint *next_offset)
+tvb_find_line_end_unquoted(tvbuff_t *tvb, const gint offset, int len,
+ gint *next_offset)
{
gint cur_offset, char_offset;
gboolean is_quoted;
- guchar c;
+ guchar c = 0;
gint eob_offset;
int linelen;
cur_offset = offset;
is_quoted = FALSE;
for (;;) {
- /*
+ /*
* Is this part of the string quoted?
*/
if (is_quoted) {
* Yes - look only for the terminating quote.
*/
char_offset = tvb_find_guint8(tvb, cur_offset, len,
- '"');
+ '"');
} else {
/*
* Look either for a CR, an LF, or a '"'.
*/
char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
- (const guint8 *)"\r\n\"");
+ (const guint8 *)"\r\n\"", &c);
}
if (char_offset == -1) {
/*
* We pretend the line runs to the end of the tvbuff.
*/
linelen = eob_offset - offset;
- *next_offset = eob_offset;
+ if (next_offset)
+ *next_offset = eob_offset;
break;
}
/*
* OK, what is it?
*/
- c = tvb_get_guint8(tvb, char_offset);
if (c == '"') {
/*
* Un-quoted "; it begins a quoted
* Yes; is it followed by an LF?
*/
if (char_offset + 1 < eob_offset &&
- tvb_get_guint8(tvb, char_offset + 1)
- == '\n') {
+ tvb_get_guint8(tvb, char_offset + 1)
+ == '\n') {
/*
* Yes; skip over the CR.
*/
* over the last character in the line
* terminator, and quit.
*/
- *next_offset = char_offset + 1;
+ if (next_offset)
+ *next_offset = char_offset + 1;
break;
}
}
* We pretend the line runs to the end of the tvbuff.
*/
linelen = eob_offset - offset;
- *next_offset = eob_offset;
+ if (next_offset)
+ *next_offset = eob_offset;
break;
}
}
return linelen;
}
+/*
+ * Copied from the mgcp dissector. (This function should be moved to /epan )
+ * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
+ * character following offset or offset + maxlength -1 whichever
+ * is smaller.
+ *
+ * Parameters:
+ * tvb - The tvbuff in which we are skipping whitespace.
+ * offset - The offset in tvb from which we begin trying to skip whitespace.
+ * maxlength - The maximum distance from offset that we may try to skip
+ * whitespace.
+ *
+ * Returns: The position in tvb of the first non-whitespace
+ * character following offset or offset + maxlength -1 whichever
+ * is smaller.
+ */
+gint tvb_skip_wsp(tvbuff_t* tvb, const gint offset, const gint maxlength)
+{
+ gint counter = offset;
+ gint end = offset + maxlength,tvb_len;
+ guint8 tempchar;
+
+ /* Get the length remaining */
+ tvb_len = tvb_length(tvb);
+ end = offset + maxlength;
+ if (end >= tvb_len)
+ {
+ end = tvb_len;
+ }
+
+ /* Skip past spaces, tabs, CRs and LFs until run out or meet something else */
+ for (counter = offset;
+ counter < end &&
+ ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
+ tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
+ counter++);
+
+ return (counter);
+}
+
+gint tvb_skip_wsp_return(tvbuff_t* tvb, const gint offset){
+ gint counter = offset;
+ gint end;
+ guint8 tempchar;
+ end = 0;
+
+ for(counter = offset; counter > end &&
+ ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
+ tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter--);
+ counter++;
+ return (counter);
+}
+
+
/*
* Format a bunch of data from a tvbuff as bytes, returning a pointer
* to the string with the formatted data, with "punct" as a byte
* separator.
*/
gchar *
-tvb_bytes_to_str_punct(tvbuff_t *tvb, gint offset, gint len, gchar punct)
+tvb_bytes_to_str_punct(tvbuff_t *tvb, const gint offset, const gint len, const gchar punct)
{
return bytes_to_str_punct(tvb_get_ptr(tvb, offset, len), len, punct);
}
* to the string with the formatted data.
*/
gchar *
-tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len)
+tvb_bytes_to_str(tvbuff_t *tvb, const gint offset, const gint len)
{
return bytes_to_str(tvb_get_ptr(tvb, offset, len), len);
}
/* Find a needle tvbuff within a haystack tvbuff. */
gint
-tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
+tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, const gint haystack_offset)
{
guint haystack_abs_offset, haystack_abs_length;
const guint8 *haystack_data;
const guint needle_len = needle_tvb->length;
const guint8 *location;
+ DISSECTOR_ASSERT(haystack_tvb && haystack_tvb->initialized);
+
if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
return -1;
}
haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
needle_data = tvb_get_ptr(needle_tvb, 0, -1);
- check_offset_length(haystack_tvb, haystack_offset, -1,
+ check_offset_length(haystack_tvb->length, haystack_tvb->reported_length, haystack_offset, -1,
&haystack_abs_offset, &haystack_abs_length);
location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
needle_data, needle_len);
if (location) {
- return location - haystack_data;
- }
- else {
- return -1;
+ return (gint) (location - haystack_data);
}
return -1;
#undef TVB_Z_DEBUG
tvbuff_t *
-tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
+tvb_uncompress(tvbuff_t *tvb, const int offset, int comprlen)
{
-
-
gint err = Z_OK;
guint bytes_out = 0;
guint8 *compr = NULL;
return NULL;
}
- strm = g_malloc0(sizeof(z_stream));
-
- if (strm == NULL) {
- return NULL;
- }
-
compr = tvb_memdup(tvb, offset, comprlen);
- if (!compr) {
- g_free(strm);
+ if (!compr)
return NULL;
- }
/*
* Assume that the uncompressed data is at least twice as big as
* the compressed size.
*/
bufsiz = tvb_length_remaining(tvb, offset) * 2;
-
- if (bufsiz < TVB_Z_MIN_BUFSIZ) {
- bufsiz = TVB_Z_MIN_BUFSIZ;
- } else if (bufsiz > TVB_Z_MAX_BUFSIZ) {
- bufsiz = TVB_Z_MIN_BUFSIZ;
- }
+ bufsiz = CLAMP(bufsiz, TVB_Z_MIN_BUFSIZ, TVB_Z_MAX_BUFSIZ);
#ifdef TVB_Z_DEBUG
printf("bufsiz: %u bytes\n", bufsiz);
next = compr;
+ strm = g_new0(z_stream, 1);
strm->next_in = next;
strm->avail_in = comprlen;
-
strmbuf = g_malloc0(bufsiz);
-
- if(strmbuf == NULL) {
- g_free(compr);
- g_free(strm);
- return NULL;
- }
-
strm->next_out = strmbuf;
strm->avail_out = bufsiz;
if (uncompr == NULL) {
uncompr = g_memdup(strmbuf, bytes_pass);
} else {
- guint8 *new_data = g_malloc0(bytes_out +
- bytes_pass);
-
- if (new_data == NULL) {
- inflateEnd(strm);
- g_free(strm);
- g_free(strmbuf);
- g_free(compr);
-
- if (uncompr != NULL) {
- g_free(uncompr);
- }
-
- return NULL;
- }
+ guint8 *new_data = g_malloc0(bytes_out + bytes_pass);
g_memmove(new_data, uncompr, bytes_out);
g_memmove((new_data + bytes_out), strmbuf,
- bytes_pass);
+ bytes_pass);
g_free(uncompr);
uncompr = new_data;
}
} else if (err == Z_DATA_ERROR && inits_done == 1
- && uncompr == NULL && (*compr == 0x1f) &&
- (*(compr + 1) == 0x8b)) {
+ && uncompr == NULL && (*compr == 0x1f) &&
+ (*(compr + 1) == 0x8b)) {
/*
* inflate() is supposed to handle both gzip and deflate
* streams automatically, but in reality it doesn't
if (flags & (1 << 2)) {
/* An Extra field is present. */
gint xsize = (gint)(*c |
- (*(c + 1) << 8));
+ (*(c + 1) << 8));
c += xsize;
}
if (flags & (1 << 3)) {
/* A null terminated filename */
- while (*c != '\0') {
+ while ((c - compr) < comprlen && *c != '\0') {
c++;
}
if (flags & (1 << 4)) {
/* A null terminated comment */
- while (*c != '\0') {
+ while ((c - compr) < comprlen && *c != '\0') {
c++;
}
g_free(strmbuf);
return NULL;
}
- comprlen -= (c - compr);
+ comprlen -= (int) (c - compr);
inflateEnd(strm);
err = inflateInit2(strm, wbits);
inits_done++;
} else if (err == Z_DATA_ERROR && uncompr == NULL &&
- inits_done <= 3) {
+ inits_done <= 3) {
/*
* Re-init the stream with a negative
strm->next_in = next;
strm->avail_in = comprlen;
+ inflateEnd(strm);
memset(strmbuf, '\0', bufsiz);
strm->next_out = strmbuf;
strm->avail_out = bufsiz;
if (uncompr != NULL) {
uncompr_tvb = tvb_new_real_data((guint8*) uncompr, bytes_out,
- bytes_out);
+ bytes_out);
tvb_set_free_cb(uncompr_tvb, g_free);
}
g_free(compr);
}
#else
tvbuff_t *
-tvb_uncompress(tvbuff_t *tvb _U_, int offset _U_, int comprlen _U_)
+tvb_uncompress(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
{
return NULL;
}
#endif
+tvbuff_t* tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
+{
+ tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
+ if (new_tvb)
+ tvb_set_child_real_data_tvbuff (parent, new_tvb);
+ return new_tvb;
+}
+