3 * Testy, Virtual(-izable) Buffer of guint8*'s
5 * "Testy" -- the buffer gets mad when an attempt to access data
6 * beyond the bounds of the buffer. An exception is thrown.
8 * "Virtual" -- the buffer can have its own data, can use a subset of
9 * the data of a backing tvbuff, or can be a composite of
14 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
16 * Code to convert IEEE floating point formats to native floating point
17 * derived from code Copyright (c) Ashok Narayanan, 2000
19 * Wireshark - Network traffic analyzer
20 * By Gerald Combs <gerald@wireshark.org>
21 * Copyright 1998 Gerald Combs
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
52 #include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
55 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
59 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length);
61 #if GLIB_CHECK_VERSION(2,10,0)
63 /* We dole out tvbuff's from this memchunk. */
64 static GMemChunk *tvbuff_mem_chunk = NULL;
70 #if GLIB_CHECK_VERSION(2,10,0)
72 if (!tvbuff_mem_chunk)
73 tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
80 #if GLIB_CHECK_VERSION(2,10,0)
83 g_mem_chunk_destroy(tvbuff_mem_chunk);
85 tvbuff_mem_chunk = NULL;
90 tvb_init(tvbuff_t *tvb, tvbuff_type type)
92 tvb_backing_t *backing;
93 tvb_comp_t *composite;
96 tvb->initialized = FALSE;
99 tvb->reported_length = 0;
101 tvb->real_data = NULL;
102 tvb->raw_offset = -1;
107 case TVBUFF_REAL_DATA:
112 backing = &tvb->tvbuffs.subset;
118 case TVBUFF_COMPOSITE:
119 composite = &tvb->tvbuffs.composite;
120 composite->tvbs = NULL;
121 composite->start_offsets = NULL;
122 composite->end_offsets = NULL;
126 DISSECTOR_ASSERT_NOT_REACHED();
133 tvb_new(tvbuff_type type)
137 #if GLIB_CHECK_VERSION(2,10,0)
138 tvb = g_slice_new(tvbuff_t);
140 tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
149 tvb_free(tvbuff_t* tvb)
151 tvbuff_t *member_tvb;
152 tvb_comp_t *composite;
157 if (tvb->usage_count == 0) {
159 case TVBUFF_REAL_DATA:
162 * XXX - do this with a union?
164 tvb->free_cb((gpointer)tvb->real_data);
169 /* This will be NULL if tvb_new_subset() fails because
170 * reported_length < -1 */
171 if (tvb->tvbuffs.subset.tvb) {
172 tvb_decrement_usage_count(tvb->tvbuffs.subset.tvb, 1);
176 case TVBUFF_COMPOSITE:
177 composite = &tvb->tvbuffs.composite;
178 for (slist = composite->tvbs; slist != NULL ; slist = slist->next) {
179 member_tvb = slist->data;
180 tvb_decrement_usage_count(member_tvb, 1);
183 g_slist_free(composite->tvbs);
185 g_free(composite->start_offsets);
186 g_free(composite->end_offsets);
187 if (tvb->real_data) {
189 * XXX - do this with a union?
191 g_free((gpointer)tvb->real_data);
198 g_slist_free(tvb->used_in);
201 #if GLIB_CHECK_VERSION(2,10,0)
202 g_slice_free(tvbuff_t, tvb);
204 g_chunk_free(tvb, tvbuff_mem_chunk);
210 tvb_increment_usage_count(tvbuff_t* tvb, guint count)
212 tvb->usage_count += count;
214 return tvb->usage_count;
218 tvb_decrement_usage_count(tvbuff_t* tvb, guint count)
220 if (tvb->usage_count <= count) {
221 tvb->usage_count = 1;
226 tvb->usage_count -= count;
227 return tvb->usage_count;
233 tvb_free_chain(tvbuff_t* tvb)
237 /* Recursively call tvb_free_chain() */
238 for (slist = tvb->used_in; slist != NULL ; slist = slist->next) {
239 tvb_free_chain( (tvbuff_t*)slist->data );
242 /* Stop the recursion */
249 tvb_set_free_cb(tvbuff_t* tvb, tvbuff_free_cb_t func)
251 DISSECTOR_ASSERT(tvb);
252 DISSECTOR_ASSERT(tvb->type == TVBUFF_REAL_DATA);
257 add_to_used_in_list(tvbuff_t *tvb, tvbuff_t *used_in)
259 tvb->used_in = g_slist_prepend(tvb->used_in, used_in);
260 tvb_increment_usage_count(tvb, 1);
264 tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child)
266 DISSECTOR_ASSERT(parent && child);
267 DISSECTOR_ASSERT(parent->initialized);
268 DISSECTOR_ASSERT(child->initialized);
269 DISSECTOR_ASSERT(child->type == TVBUFF_REAL_DATA);
270 add_to_used_in_list(parent, child);
274 tvb_set_real_data_no_exceptions(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
276 tvb->real_data = data;
277 tvb->length = length;
278 tvb->reported_length = reported_length;
279 tvb->initialized = TRUE;
283 tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
285 DISSECTOR_ASSERT(tvb);
286 DISSECTOR_ASSERT(tvb->type == TVBUFF_REAL_DATA);
287 DISSECTOR_ASSERT(!tvb->initialized);
289 THROW_ON(reported_length < -1, ReportedBoundsError);
291 tvb_set_real_data_no_exceptions(tvb, data, length, reported_length);
295 tvb_new_real_data(const guint8* data, guint length, gint reported_length)
299 THROW_ON(reported_length < -1, ReportedBoundsError);
301 tvb = tvb_new(TVBUFF_REAL_DATA);
303 tvb_set_real_data_no_exceptions(tvb, data, length, reported_length);
306 * This is the top-level real tvbuff for this data source,
307 * so its data source tvbuff is itself.
315 tvb_new_child_real_data(tvbuff_t *parent, const guint8* data, guint length, gint reported_length)
317 tvbuff_t *tvb = tvb_new_real_data(data, length, reported_length);
319 tvb_set_child_real_data_tvbuff (parent, tvb);
325 /* Computes the absolute offset and length based on a possibly-negative offset
326 * and a length that is possible -1 (which means "to the end of the data").
327 * Returns TRUE/FALSE indicating whether the offset is in bounds or
328 * not. The integer ptrs are modified with the new offset and length.
329 * No exception is thrown.
331 * XXX - we return TRUE, not FALSE, if the offset is positive and right
332 * after the end of the tvbuff (i.e., equal to the length). We do this
333 * so that a dissector constructing a subset tvbuff for the next protocol
334 * will get a zero-length tvbuff, not an exception, if there's no data
335 * left for the next protocol - we want the next protocol to be the one
336 * that gets an exception, so the error is reported as an error in that
337 * protocol rather than the containing protocol. */
339 compute_offset_length(guint tvb_length, guint tvb_reported_length, gint offset, gint length,
340 guint *offset_ptr, guint *length_ptr, int *exception)
342 DISSECTOR_ASSERT(offset_ptr);
343 DISSECTOR_ASSERT(length_ptr);
345 /* Compute the offset */
347 /* Positive offset - relative to the beginning of the packet. */
348 if ((guint) offset > tvb_reported_length) {
350 *exception = ReportedBoundsError;
354 else if ((guint) offset > tvb_length) {
356 *exception = BoundsError;
361 *offset_ptr = offset;
365 /* Negative offset - relative to the end of the packet. */
366 if ((guint) -offset > tvb_reported_length) {
368 *exception = ReportedBoundsError;
372 else if ((guint) -offset > tvb_length) {
374 *exception = BoundsError;
379 *offset_ptr = tvb_length + offset;
383 /* Compute the length */
386 /* XXX - ReportedBoundsError? */
387 *exception = BoundsError;
391 else if (length == -1) {
392 *length_ptr = tvb_length - *offset_ptr;
395 *length_ptr = length;
403 check_offset_length_no_exception(guint tvb_length, guint tvb_reported_length, gint offset, gint length,
404 guint *offset_ptr, guint *length_ptr, int *exception)
408 if (!compute_offset_length(tvb_length, tvb_reported_length, offset, length, offset_ptr, length_ptr, exception)) {
413 * Compute the offset of the first byte past the length.
415 end_offset = *offset_ptr + *length_ptr;
418 * Check for an overflow, and clamp "end_offset" at the maximum
419 * if we got an overflow - that should force us to indicate that
420 * we're past the end of the tvbuff.
422 if (end_offset < *offset_ptr)
423 end_offset = UINT_MAX;
426 * Check whether that offset goes more than one byte past the
429 * If not, return TRUE; otherwise, return FALSE and, if "exception"
430 * is non-null, return the appropriate exception through it.
432 if (end_offset <= tvb_length) {
435 else if (end_offset <= tvb_reported_length) {
437 *exception = BoundsError;
442 *exception = ReportedBoundsError;
449 /* Checks (+/-) offset and length and throws an exception if
450 * either is out of bounds. Sets integer ptrs to the new offset
453 check_offset_length(guint tvb_length, guint tvb_reported_length, gint offset, gint length,
454 guint *offset_ptr, guint *length_ptr)
458 if (!check_offset_length_no_exception(tvb_length, tvb_reported_length, offset, length, offset_ptr, length_ptr, &exception)) {
459 DISSECTOR_ASSERT(exception > 0);
465 tvb_set_subset_no_exceptions(tvbuff_t *tvb, tvbuff_t *backing,
466 gint backing_offset, gint backing_length, gint reported_length)
468 tvb->tvbuffs.subset.tvb = backing;
469 tvb->length = tvb->tvbuffs.subset.length;
471 if (reported_length == -1) {
472 tvb->reported_length = backing->reported_length - tvb->tvbuffs.subset.offset;
475 tvb->reported_length = reported_length;
477 tvb->initialized = TRUE;
478 add_to_used_in_list(backing, tvb);
480 /* Optimization. If the backing buffer has a pointer to contiguous, real data,
481 * then we can point directly to our starting offset in that buffer */
482 if (backing->real_data != NULL) {
483 tvb->real_data = backing->real_data + tvb->tvbuffs.subset.offset;
488 tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
489 gint backing_offset, gint backing_length, gint reported_length)
491 DISSECTOR_ASSERT(tvb);
492 DISSECTOR_ASSERT(tvb->type == TVBUFF_SUBSET);
493 DISSECTOR_ASSERT(!tvb->initialized);
495 THROW_ON(reported_length < -1, ReportedBoundsError);
497 check_offset_length(backing->length, backing->reported_length, backing_offset, backing_length,
498 &tvb->tvbuffs.subset.offset,
499 &tvb->tvbuffs.subset.length);
501 tvb_set_subset_no_exceptions(tvb, backing, backing_offset, backing_length, reported_length);
505 tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint reported_length)
508 guint subset_tvb_offset;
509 guint subset_tvb_length;
511 THROW_ON(reported_length < -1, ReportedBoundsError);
513 check_offset_length(backing->length, backing->reported_length, backing_offset, backing_length,
517 tvb = tvb_new(TVBUFF_SUBSET);
518 tvb->tvbuffs.subset.offset = subset_tvb_offset;
519 tvb->tvbuffs.subset.length = subset_tvb_length;
521 tvb_set_subset_no_exceptions(tvb, backing, backing_offset, backing_length, reported_length);
524 * The top-level data source of this tvbuff is the top-level
525 * data source of its parent.
527 tvb->ds_tvb = backing->ds_tvb;
533 tvb_composite_append(tvbuff_t* tvb, tvbuff_t* member)
535 tvb_comp_t *composite;
537 DISSECTOR_ASSERT(tvb && !tvb->initialized);
538 DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
539 composite = &tvb->tvbuffs.composite;
540 composite->tvbs = g_slist_append( composite->tvbs, member );
541 add_to_used_in_list(tvb, member);
545 tvb_composite_prepend(tvbuff_t* tvb, tvbuff_t* member)
547 tvb_comp_t *composite;
549 DISSECTOR_ASSERT(tvb && !tvb->initialized);
550 DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
551 composite = &tvb->tvbuffs.composite;
552 composite->tvbs = g_slist_prepend( composite->tvbs, member );
553 add_to_used_in_list(tvb, member);
557 tvb_new_composite(void)
559 return tvb_new(TVBUFF_COMPOSITE);
563 tvb_composite_finalize(tvbuff_t* tvb)
567 tvbuff_t *member_tvb;
568 tvb_comp_t *composite;
571 DISSECTOR_ASSERT(tvb && !tvb->initialized);
572 DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
573 DISSECTOR_ASSERT(tvb->length == 0);
575 composite = &tvb->tvbuffs.composite;
576 num_members = g_slist_length(composite->tvbs);
578 composite->start_offsets = g_new(guint, num_members);
579 composite->end_offsets = g_new(guint, num_members);
581 for (slist = composite->tvbs; slist != NULL; slist = slist->next) {
582 DISSECTOR_ASSERT((guint) i < num_members);
583 member_tvb = slist->data;
584 composite->start_offsets[i] = tvb->length;
585 tvb->length += member_tvb->length;
586 composite->end_offsets[i] = tvb->length - 1;
590 tvb->initialized = TRUE;
596 tvb_length(tvbuff_t* tvb)
598 DISSECTOR_ASSERT(tvb && tvb->initialized);
604 tvb_length_remaining(tvbuff_t *tvb, gint offset)
606 guint abs_offset, abs_length;
608 DISSECTOR_ASSERT(tvb && tvb->initialized);
610 if (compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL)) {
619 tvb_ensure_length_remaining(tvbuff_t *tvb, gint offset)
621 guint abs_offset, abs_length;
624 DISSECTOR_ASSERT(tvb && tvb->initialized);
626 if (!compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, &exception)) {
629 if (abs_length == 0) {
631 * This routine ensures there's at least one byte available.
632 * There aren't any bytes available, so throw the appropriate
635 if (abs_offset >= tvb->reported_length)
636 THROW(ReportedBoundsError);
646 /* Validates that 'length' bytes are available starting from
647 * offset (pos/neg). Does not throw an exception. */
649 tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
651 guint abs_offset, abs_length;
653 DISSECTOR_ASSERT(tvb && tvb->initialized);
655 if (!compute_offset_length(tvb->length, tvb->reported_length, offset, length, &abs_offset, &abs_length, NULL))
658 if (abs_offset + abs_length <= tvb->length) {
666 /* Validates that 'length' bytes are available starting from
667 * offset (pos/neg). Throws an exception if they aren't. */
669 tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
671 guint abs_offset, abs_length;
673 DISSECTOR_ASSERT(tvb && tvb->initialized);
676 * -1 doesn't mean "until end of buffer", as that's pointless
677 * for this routine. We must treat it as a Really Large Positive
678 * Number, so that we throw an exception; we throw
679 * ReportedBoundsError, as if it were past even the end of a
680 * reassembled packet, and past the end of even the data we
683 * We do the same with other negative lengths.
686 THROW(ReportedBoundsError);
688 check_offset_length(tvb->length, tvb->reported_length, offset, length, &abs_offset, &abs_length);
692 tvb_offset_exists(tvbuff_t *tvb, gint offset)
694 guint abs_offset, abs_length;
696 DISSECTOR_ASSERT(tvb && tvb->initialized);
697 if (!compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL))
700 if (abs_offset < tvb->length) {
709 tvb_reported_length(tvbuff_t* tvb)
711 DISSECTOR_ASSERT(tvb && tvb->initialized);
713 return tvb->reported_length;
717 tvb_reported_length_remaining(tvbuff_t *tvb, gint offset)
719 guint abs_offset, abs_length;
721 DISSECTOR_ASSERT(tvb && tvb->initialized);
723 if (compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL)) {
724 if (tvb->reported_length >= abs_offset)
725 return tvb->reported_length - abs_offset;
734 /* Set the reported length of a tvbuff to a given value; used for protocols
735 whose headers contain an explicit length and where the calling
736 dissector's payload may include padding as well as the packet for
739 Also adjusts the data length. */
741 tvb_set_reported_length(tvbuff_t* tvb, guint reported_length)
743 DISSECTOR_ASSERT(tvb && tvb->initialized);
745 if (reported_length > tvb->reported_length)
746 THROW(ReportedBoundsError);
748 tvb->reported_length = reported_length;
749 if (reported_length < tvb->length)
750 tvb->length = reported_length;
756 first_real_data_ptr(tvbuff_t *tvb)
761 case TVBUFF_REAL_DATA:
762 return tvb->real_data;
764 member = tvb->tvbuffs.subset.tvb;
765 return first_real_data_ptr(member);
766 case TVBUFF_COMPOSITE:
767 member = tvb->tvbuffs.composite.tvbs->data;
768 return first_real_data_ptr(member);
771 DISSECTOR_ASSERT_NOT_REACHED();
777 offset_from_real_beginning(tvbuff_t *tvb, int counter)
782 case TVBUFF_REAL_DATA:
785 member = tvb->tvbuffs.subset.tvb;
786 return offset_from_real_beginning(member, counter + tvb->tvbuffs.subset.offset);
787 case TVBUFF_COMPOSITE:
788 member = tvb->tvbuffs.composite.tvbs->data;
789 return offset_from_real_beginning(member, counter);
792 DISSECTOR_ASSERT_NOT_REACHED();
797 composite_ensure_contiguous_no_exception(tvbuff_t *tvb, guint abs_offset,
800 guint i, num_members;
801 tvb_comp_t *composite;
802 tvbuff_t *member_tvb = NULL;
803 guint member_offset, member_length;
806 DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
808 /* Maybe the range specified by offset/length
809 * is contiguous inside one of the member tvbuffs */
810 composite = &tvb->tvbuffs.composite;
811 num_members = g_slist_length(composite->tvbs);
813 for (i = 0; i < num_members; i++) {
814 if (abs_offset <= composite->end_offsets[i]) {
815 slist = g_slist_nth(composite->tvbs, i);
816 member_tvb = slist->data;
820 DISSECTOR_ASSERT(member_tvb);
822 if (check_offset_length_no_exception(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i],
823 abs_length, &member_offset, &member_length, NULL)) {
826 * The range is, in fact, contiguous within member_tvb.
828 DISSECTOR_ASSERT(!tvb->real_data);
829 return ensure_contiguous_no_exception(member_tvb, member_offset, member_length, NULL);
832 tvb->real_data = tvb_memdup(tvb, 0, -1);
833 return tvb->real_data + abs_offset;
836 DISSECTOR_ASSERT_NOT_REACHED();
841 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
844 guint abs_offset, abs_length;
846 if (!check_offset_length_no_exception(tvb->length, tvb->reported_length, offset, length,
847 &abs_offset, &abs_length, exception)) {
852 * We know that all the data is present in the tvbuff, so
853 * no exceptions should be thrown.
855 if (tvb->real_data) {
856 return tvb->real_data + abs_offset;
860 case TVBUFF_REAL_DATA:
861 DISSECTOR_ASSERT_NOT_REACHED();
863 return ensure_contiguous_no_exception(tvb->tvbuffs.subset.tvb,
864 abs_offset - tvb->tvbuffs.subset.offset,
866 case TVBUFF_COMPOSITE:
867 return composite_ensure_contiguous_no_exception(tvb, abs_offset, abs_length);
871 DISSECTOR_ASSERT_NOT_REACHED();
876 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length)
881 p = ensure_contiguous_no_exception(tvb, offset, length, &exception);
883 DISSECTOR_ASSERT(exception > 0);
890 fast_ensure_contiguous(tvbuff_t *tvb, gint offset, guint length)
895 DISSECTOR_ASSERT(tvb && tvb->initialized);
896 /* We don't check for overflow in this fast path so we only handle simple types */
897 DISSECTOR_ASSERT(length <= 8);
899 if (offset < 0 || !tvb->real_data) {
900 return ensure_contiguous(tvb, offset, length);
904 end_offset = u_offset + length;
906 if (end_offset <= tvb->length) {
907 return tvb->real_data + u_offset;
910 if (end_offset > tvb->reported_length) {
911 THROW(ReportedBoundsError);
919 guint8_find(const guint8* haystack, size_t haystacklen, guint8 needle)
924 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
934 guint8_pbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles)
939 const guint8 *needlep;
941 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
944 while ((needle = *needlep) != '\0') {
956 /************** ACCESSORS **************/
959 composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, size_t abs_length)
961 guint i, num_members;
962 tvb_comp_t *composite;
963 tvbuff_t *member_tvb = NULL;
964 guint member_offset, member_length;
968 DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
970 /* Maybe the range specified by offset/length
971 * is contiguous inside one of the member tvbuffs */
972 composite = &tvb->tvbuffs.composite;
973 num_members = g_slist_length(composite->tvbs);
975 for (i = 0; i < num_members; i++) {
976 if (abs_offset <= composite->end_offsets[i]) {
977 slist = g_slist_nth(composite->tvbs, i);
978 member_tvb = slist->data;
982 DISSECTOR_ASSERT(member_tvb);
984 if (check_offset_length_no_exception(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i],
985 (gint) abs_length, &member_offset, &member_length, NULL)) {
987 DISSECTOR_ASSERT(!tvb->real_data);
988 return tvb_memcpy(member_tvb, target, member_offset, member_length);
991 /* The requested data is non-contiguous inside
992 * the member tvb. We have to memcpy() the part that's in the member tvb,
993 * then iterate across the other member tvb's, copying their portions
994 * until we have copied all data.
996 retval = compute_offset_length(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i], -1,
997 &member_offset, &member_length, NULL);
998 DISSECTOR_ASSERT(retval);
1000 tvb_memcpy(member_tvb, target, member_offset, member_length);
1001 abs_offset += member_length;
1002 abs_length -= member_length;
1005 if (abs_length > 0) {
1006 composite_memcpy(tvb, target + member_length, abs_offset, abs_length);
1012 DISSECTOR_ASSERT_NOT_REACHED();
1017 tvb_memcpy(tvbuff_t *tvb, void* target, gint offset, size_t length)
1019 guint abs_offset, abs_length;
1021 DISSECTOR_ASSERT(tvb && tvb->initialized);
1024 * XXX - we should eliminate the "length = -1 means 'to the end
1025 * of the tvbuff'" convention, and use other means to achieve
1026 * that; this would let us eliminate a bunch of checks for
1027 * negative lengths in cases where the protocol has a 32-bit
1030 * Allowing -1 but throwing an assertion on other negative
1031 * lengths is a bit more work with the length being a size_t;
1032 * instead, we check for a length <= 2^31-1.
1034 DISSECTOR_ASSERT(length <= 0x7FFFFFFF);
1035 check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
1037 if (tvb->real_data) {
1038 return memcpy(target, tvb->real_data + abs_offset, abs_length);
1042 case TVBUFF_REAL_DATA:
1043 DISSECTOR_ASSERT_NOT_REACHED();
1046 return tvb_memcpy(tvb->tvbuffs.subset.tvb, target,
1047 abs_offset - tvb->tvbuffs.subset.offset,
1050 case TVBUFF_COMPOSITE:
1051 return composite_memcpy(tvb, target, offset, length);
1054 DISSECTOR_ASSERT_NOT_REACHED();
1060 * XXX - this doesn't treat a length of -1 as an error.
1061 * If it did, this could replace some code that calls
1062 * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
1065 * "composite_ensure_contiguous_no_exception()" depends on -1 not being
1066 * an error; does anything else depend on this routine treating -1 as
1067 * meaning "to the end of the buffer"?
1070 tvb_memdup(tvbuff_t *tvb, gint offset, size_t length)
1072 guint abs_offset, abs_length;
1075 DISSECTOR_ASSERT(tvb && tvb->initialized);
1077 check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
1079 duped = g_malloc(abs_length);
1080 return tvb_memcpy(tvb, duped, abs_offset, abs_length);
1084 * XXX - this doesn't treat a length of -1 as an error.
1085 * If it did, this could replace some code that calls
1086 * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
1089 * "composite_ensure_contiguous_no_exception()" depends on -1 not being
1090 * an error; does anything else depend on this routine treating -1 as
1091 * meaning "to the end of the buffer"?
1093 * This function allocates memory from a buffer with packet lifetime.
1094 * You do not have to free this buffer, it will be automatically freed
1095 * when wireshark starts decoding the next packet.
1096 * Do not use this function if you want the allocated memory to be persistent
1097 * after the current packet has been dissected.
1100 ep_tvb_memdup(tvbuff_t *tvb, gint offset, size_t length)
1102 guint abs_offset, abs_length;
1105 DISSECTOR_ASSERT(tvb && tvb->initialized);
1107 check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
1109 duped = ep_alloc(abs_length);
1110 return tvb_memcpy(tvb, duped, abs_offset, abs_length);
1116 tvb_get_ptr(tvbuff_t *tvb, gint offset, gint length)
1118 return ensure_contiguous(tvb, offset, length);
1121 /* ---------------- */
1123 tvb_get_guint8(tvbuff_t *tvb, gint offset)
1127 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint8));
1132 tvb_get_ntohs(tvbuff_t *tvb, gint offset)
1136 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint16));
1141 tvb_get_ntoh24(tvbuff_t *tvb, gint offset)
1145 ptr = fast_ensure_contiguous(tvb, offset, 3);
1146 return pntoh24(ptr);
1150 tvb_get_ntohl(tvbuff_t *tvb, gint offset)
1154 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
1159 tvb_get_ntoh64(tvbuff_t *tvb, gint offset)
1163 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint64));
1164 return pntoh64(ptr);
1168 * Stuff for IEEE float handling on platforms that don't have IEEE
1169 * format as the native floating-point format.
1171 * For now, we treat only the VAX as such a platform.
1173 * XXX - other non-IEEE boxes that can run UNIX include some Crays,
1174 * and possibly other machines.
1176 * It appears that the official Linux port to System/390 and
1177 * zArchitecture uses IEEE format floating point (not a
1180 * I don't know whether there are any other machines that
1181 * could run Wireshark and that don't use IEEE format.
1182 * As far as I know, all of the main commercial microprocessor
1183 * families on which OSes that support Wireshark can run
1184 * use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
1185 * IA-64, and so on).
1195 #define IEEE_SP_NUMBER_WIDTH 32 /* bits in number */
1196 #define IEEE_SP_EXP_WIDTH 8 /* bits in exponent */
1197 #define IEEE_SP_MANTISSA_WIDTH 23 /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
1199 #define IEEE_SP_SIGN_MASK 0x80000000
1200 #define IEEE_SP_EXPONENT_MASK 0x7F800000
1201 #define IEEE_SP_MANTISSA_MASK 0x007FFFFF
1202 #define IEEE_SP_INFINITY IEEE_SP_EXPONENT_MASK
1204 #define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
1205 #define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
1206 #define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
1209 ieee_float_is_zero(guint32 w)
1211 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1215 get_ieee_float(guint32 w)
1221 sign = w & IEEE_SP_SIGN_MASK;
1222 exponent = w & IEEE_SP_EXPONENT_MASK;
1223 mantissa = w & IEEE_SP_MANTISSA_MASK;
1225 if (ieee_float_is_zero(w)) {
1226 /* number is zero, unnormalized, or not-a-number */
1231 * XXX - how to handle this?
1233 if (IEEE_SP_INFINITY == exponent) {
1235 * number is positive or negative infinity, or a special value
1237 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1241 exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1242 IEEE_SP_MANTISSA_WIDTH;
1243 mantissa |= IEEE_SP_IMPLIED_BIT;
1246 return -mantissa * pow(2, exponent);
1248 return mantissa * pow(2, exponent);
1253 * We assume that if you don't have IEEE floating-point, you have a
1254 * compiler that understands 64-bit integral quantities.
1256 #define IEEE_DP_NUMBER_WIDTH 64 /* bits in number */
1257 #define IEEE_DP_EXP_WIDTH 11 /* bits in exponent */
1258 #define IEEE_DP_MANTISSA_WIDTH 52 /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1260 #define IEEE_DP_SIGN_MASK 0x8000000000000000LL
1261 #define IEEE_DP_EXPONENT_MASK 0x7FF0000000000000LL
1262 #define IEEE_DP_MANTISSA_MASK 0x000FFFFFFFFFFFFFLL
1263 #define IEEE_DP_INFINITY IEEE_DP_EXPONENT_MASK
1265 #define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
1266 #define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1267 #define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1270 ieee_double_is_zero(guint64 w)
1272 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1276 get_ieee_double(guint64 w)
1282 sign = w & IEEE_DP_SIGN_MASK;
1283 exponent = w & IEEE_DP_EXPONENT_MASK;
1284 mantissa = w & IEEE_DP_MANTISSA_MASK;
1286 if (ieee_double_is_zero(w)) {
1287 /* number is zero, unnormalized, or not-a-number */
1292 * XXX - how to handle this?
1294 if (IEEE_DP_INFINITY == exponent) {
1296 * number is positive or negative infinity, or a special value
1298 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1302 exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1303 IEEE_DP_MANTISSA_WIDTH;
1304 mantissa |= IEEE_DP_IMPLIED_BIT;
1307 return -mantissa * pow(2, exponent);
1309 return mantissa * pow(2, exponent);
1314 * Fetches an IEEE single-precision floating-point number, in
1315 * big-endian form, and returns a "float".
1317 * XXX - should this be "double", in case there are IEEE single-
1318 * precision numbers that won't fit in some platform's native
1322 tvb_get_ntohieee_float(tvbuff_t *tvb, int offset)
1325 return get_ieee_float(tvb_get_ntohl(tvb, offset));
1332 ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1333 return ieee_fp_union.f;
1338 * Fetches an IEEE double-precision floating-point number, in
1339 * big-endian form, and returns a "double".
1342 tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
1356 #ifdef WORDS_BIGENDIAN
1357 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1358 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1360 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1361 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1364 return get_ieee_double(ieee_fp_union.dw);
1366 return ieee_fp_union.d;
1371 tvb_get_letohs(tvbuff_t *tvb, gint offset)
1375 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint16));
1376 return pletohs(ptr);
1380 tvb_get_letoh24(tvbuff_t *tvb, gint offset)
1384 ptr = fast_ensure_contiguous(tvb, offset, 3);
1385 return pletoh24(ptr);
1389 tvb_get_letohl(tvbuff_t *tvb, gint offset)
1393 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
1394 return pletohl(ptr);
1398 tvb_get_letoh64(tvbuff_t *tvb, gint offset)
1402 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint64));
1403 return pletoh64(ptr);
1407 * Fetches an IEEE single-precision floating-point number, in
1408 * little-endian form, and returns a "float".
1410 * XXX - should this be "double", in case there are IEEE single-
1411 * precision numbers that won't fit in some platform's native
1415 tvb_get_letohieee_float(tvbuff_t *tvb, int offset)
1418 return get_ieee_float(tvb_get_letohl(tvb, offset));
1425 ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1426 return ieee_fp_union.f;
1431 * Fetches an IEEE double-precision floating-point number, in
1432 * little-endian form, and returns a "double".
1435 tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
1449 #ifdef WORDS_BIGENDIAN
1450 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1451 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1453 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1454 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1457 return get_ieee_double(ieee_fp_union.dw);
1459 return ieee_fp_union.d;
1463 /* Fetch an IPv4 address, in network byte order.
1464 * We do *not* convert them to host byte order; we leave them in
1465 * network byte order. */
1467 tvb_get_ipv4(tvbuff_t *tvb, gint offset)
1472 ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
1473 memcpy(&addr, ptr, sizeof addr);
1477 /* Fetch an IPv6 address. */
1479 tvb_get_ipv6(tvbuff_t *tvb, gint offset, struct e_in6_addr *addr)
1483 ptr = ensure_contiguous(tvb, offset, sizeof(*addr));
1484 memcpy(addr, ptr, sizeof *addr);
1489 tvb_get_ntohguid(tvbuff_t *tvb, gint offset, e_guid_t *guid)
1491 ensure_contiguous(tvb, offset, sizeof(*guid));
1492 guid->data1 = tvb_get_ntohl(tvb, offset);
1493 guid->data2 = tvb_get_ntohs(tvb, offset + 4);
1494 guid->data3 = tvb_get_ntohs(tvb, offset + 6);
1495 tvb_memcpy(tvb, guid->data4, offset + 8, sizeof guid->data4);
1499 tvb_get_letohguid(tvbuff_t *tvb, gint offset, e_guid_t *guid)
1501 ensure_contiguous(tvb, offset, sizeof(*guid));
1502 guid->data1 = tvb_get_letohl(tvb, offset);
1503 guid->data2 = tvb_get_letohs(tvb, offset + 4);
1504 guid->data3 = tvb_get_letohs(tvb, offset + 6);
1505 tvb_memcpy(tvb, guid->data4, offset + 8, sizeof guid->data4);
1509 tvb_get_guid(tvbuff_t *tvb, gint offset, e_guid_t *guid, gboolean little_endian)
1511 if (little_endian) {
1512 tvb_get_letohguid(tvb, offset, guid);
1514 tvb_get_ntohguid(tvb, offset, guid);
1518 static const guint8 bit_mask8[] = {
1529 /* Bit offset mask for number of bits = 8 - 16 */
1530 static const guint16 bit_mask16[] = {
1541 /* Get 1 - 8 bits */
1543 tvb_get_bits8(tvbuff_t *tvb, gint bit_offset, gint no_of_bits)
1550 DISSECTOR_ASSERT_NOT_REACHED();
1552 /* Byte align offset */
1553 offset = bit_offset>>3;
1555 /* Find out which mask to use for the most significant octet
1556 * by convering bit_offset into the offset into the first
1559 bit_offset = bit_offset & 0x7;
1560 tot_no_bits = bit_offset+no_of_bits;
1562 /* Read one octet, mask off bit_offset bits and left shift out the unused bits */
1563 value = tvb_get_guint8(tvb,offset) & bit_mask8[bit_offset];
1564 value = value >> (8-tot_no_bits);
1566 /* Read two octets, mask off bit_offset bits and left shift out the unused bits */
1567 value = tvb_get_ntohs(tvb,offset) & bit_mask16[bit_offset];
1568 value = value >> (16 - tot_no_bits);
1571 return (guint8)value;
1574 /* Get 9 - 16 bits */
1575 /* Bit offset mask for number of bits = 16 - 32 */
1576 static const guint32 bit_mask32[] = {
1588 tvb_get_bits16(tvbuff_t *tvb, gint bit_offset, gint no_of_bits,gboolean little_endian)
1592 guint16 tempval = 0;
1595 if ((no_of_bits<=8)||(no_of_bits>16)) {
1596 /* If bits <= 8 use tvb_get_bits8 */
1597 DISSECTOR_ASSERT_NOT_REACHED();
1600 DISSECTOR_ASSERT_NOT_REACHED();
1601 /* This part is not implemented yet */
1604 /* Byte align offset */
1605 offset = bit_offset>>3;
1607 /* Find out which mask to use for the most significant octet
1608 * by convering bit_offset into the offset into the first
1611 bit_offset = bit_offset & 0x7;
1612 tot_no_bits = bit_offset+no_of_bits;
1613 /* Read two octets and mask off bit_offset bits */
1614 value = tvb_get_ntohs(tvb,offset) & bit_mask16[bit_offset];
1615 if(tot_no_bits < 16){
1616 /* Left shift out the unused bits */
1617 value = value >> (16 - tot_no_bits);
1618 }else if(tot_no_bits > 16){
1619 /* Spans three octets, read next octet and shift as needed */
1620 value = value << (tot_no_bits - 16);
1621 tempval = tvb_get_guint8(tvb,offset+2);
1622 tempval = tempval >> (24-tot_no_bits);
1623 value = value | tempval;
1629 /* Bit offset mask for number of bits = 32 - 64 */
1630 static const guint64 bit_mask64[] = {
1631 G_GINT64_CONSTANT(0xffffffffffffffffU),
1632 G_GINT64_CONSTANT(0x7fffffffffffffffU),
1633 G_GINT64_CONSTANT(0x3fffffffffffffffU),
1634 G_GINT64_CONSTANT(0x1fffffffffffffffU),
1635 G_GINT64_CONSTANT(0x0fffffffffffffffU),
1636 G_GINT64_CONSTANT(0x07ffffffffffffffU),
1637 G_GINT64_CONSTANT(0x03ffffffffffffffU),
1638 G_GINT64_CONSTANT(0x01ffffffffffffffU)
1642 tvb_get_bits32(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
1646 guint32 tempval = 0;
1649 if ((no_of_bits<=16)||(no_of_bits>32)) {
1650 /* If bits <= 16 use tvb_get_bits8 or tvb_get_bits16 */
1651 DISSECTOR_ASSERT_NOT_REACHED();
1654 DISSECTOR_ASSERT_NOT_REACHED();
1655 /* This part is not implemented yet */
1658 /* Byte align offset */
1659 offset = bit_offset>>3;
1661 /* Find out which mask to use for the most significant octet
1662 * by convering bit_offset into the offset into the first
1665 bit_offset = bit_offset & 0x7;
1666 tot_no_bits = bit_offset+no_of_bits;
1667 /* Read four octets and mask off bit_offset bits */
1668 value = tvb_get_ntohl(tvb,offset) & bit_mask32[bit_offset];
1669 if(tot_no_bits < 32){
1670 /* Left shift out the unused bits */
1671 value = value >> (32 - tot_no_bits);
1672 }else if(tot_no_bits > 32){
1673 /* Spans five octets, read next octet and shift as needed */
1674 value = value << (tot_no_bits - 32);
1675 tempval = tvb_get_guint8(tvb,offset+4);
1676 tempval = tempval >> (40-tot_no_bits);
1677 value = value | tempval;
1684 tvb_get_bits64(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
1688 guint64 tempval = 0;
1691 if ((no_of_bits<=32)||(no_of_bits>64)) {
1692 /* If bits <= 32 use tvb_get_bits8, tvb_get_bits16 or tvb_get_bits32 */
1693 DISSECTOR_ASSERT_NOT_REACHED();
1696 DISSECTOR_ASSERT_NOT_REACHED();
1697 /* This part is not implemented yet */
1700 /* Byte align offset */
1701 offset = bit_offset>>3;
1703 /* Find out which mask to use for the most significant octet
1704 * by convering bit_offset into the offset into the first
1707 bit_offset = bit_offset & 0x7;
1708 tot_no_bits = bit_offset+no_of_bits;
1709 /* Read eight octets and mask off bit_offset bits */
1710 value = tvb_get_ntoh64(tvb,offset) & bit_mask64[bit_offset];
1711 if (tot_no_bits < 64){
1712 /* Left shift out the unused bits */
1713 value = value >> (64 - tot_no_bits);
1714 }else if (tot_no_bits > 64){
1715 /* Spans nine octets, read next octet and shift as needed */
1716 value = value << (tot_no_bits - 64);
1717 tempval = tvb_get_guint8(tvb,offset+8);
1718 tempval = tempval >> (72-tot_no_bits);
1719 value = value | tempval;
1725 /* Find first occurence of needle in tvbuff, starting at offset. Searches
1726 * at most maxlength number of bytes; if maxlength is -1, searches to
1728 * Returns the offset of the found needle, or -1 if not found.
1729 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1730 * in that case, -1 will be returned if the boundary is reached before
1731 * finding needle. */
1733 tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
1735 const guint8 *result;
1736 guint abs_offset, junk_length;
1740 DISSECTOR_ASSERT(tvb && tvb->initialized);
1742 check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
1744 /* Only search to end of tvbuff, w/o throwing exception. */
1745 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1746 if (maxlength == -1) {
1747 /* No maximum length specified; search to end of tvbuff. */
1750 else if (tvbufflen < (guint) maxlength) {
1751 /* Maximum length goes past end of tvbuff; search to end
1756 /* Maximum length doesn't go past end of tvbuff; search
1761 /* If we have real data, perform our search now. */
1762 if (tvb->real_data) {
1763 result = guint8_find(tvb->real_data + abs_offset, limit, needle);
1764 if (result == NULL) {
1768 return (gint) (result - tvb->real_data);
1773 case TVBUFF_REAL_DATA:
1774 DISSECTOR_ASSERT_NOT_REACHED();
1777 return tvb_find_guint8(tvb->tvbuffs.subset.tvb,
1778 abs_offset - tvb->tvbuffs.subset.offset,
1781 case TVBUFF_COMPOSITE:
1782 DISSECTOR_ASSERT_NOT_REACHED();
1783 /* XXX - return composite_find_guint8(tvb, offset, limit, needle); */
1786 DISSECTOR_ASSERT_NOT_REACHED();
1790 /* Find first occurence of any of the needles in tvbuff, starting at offset.
1791 * Searches at most maxlength number of bytes; if maxlength is -1, searches
1793 * Returns the offset of the found needle, or -1 if not found.
1794 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1795 * in that case, -1 will be returned if the boundary is reached before
1796 * finding needle. */
1798 tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, const guint8 *needles)
1800 const guint8 *result;
1801 guint abs_offset, junk_length;
1805 DISSECTOR_ASSERT(tvb && tvb->initialized);
1807 check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
1809 /* Only search to end of tvbuff, w/o throwing exception. */
1810 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1811 if (maxlength == -1) {
1812 /* No maximum length specified; search to end of tvbuff. */
1815 else if (tvbufflen < (guint) maxlength) {
1816 /* Maximum length goes past end of tvbuff; search to end
1821 /* Maximum length doesn't go past end of tvbuff; search
1826 /* If we have real data, perform our search now. */
1827 if (tvb->real_data) {
1828 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles);
1829 if (result == NULL) {
1833 return (gint) (result - tvb->real_data);
1838 case TVBUFF_REAL_DATA:
1839 DISSECTOR_ASSERT_NOT_REACHED();
1842 return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
1843 abs_offset - tvb->tvbuffs.subset.offset,
1846 case TVBUFF_COMPOSITE:
1847 DISSECTOR_ASSERT_NOT_REACHED();
1848 /* XXX - return composite_pbrk_guint8(tvb, offset, limit, needle); */
1851 DISSECTOR_ASSERT_NOT_REACHED();
1855 /* Find size of stringz (NUL-terminated string) by looking for terminating
1856 * NUL. The size of the string includes the terminating NUL.
1858 * If the NUL isn't found, it throws the appropriate exception.
1861 tvb_strsize(tvbuff_t *tvb, gint offset)
1863 guint abs_offset, junk_length;
1866 DISSECTOR_ASSERT(tvb && tvb->initialized);
1868 check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
1869 nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
1870 if (nul_offset == -1) {
1872 * OK, we hit the end of the tvbuff, so we should throw
1875 * Did we hit the end of the captured data, or the end
1876 * of the actual data? If there's less captured data
1877 * than actual data, we presumably hit the end of the
1878 * captured data, otherwise we hit the end of the actual
1881 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
1884 THROW(ReportedBoundsError);
1887 return (nul_offset - abs_offset) + 1;
1890 /* Find length of string by looking for end of string ('\0'), up to
1891 * 'maxlength' characters'; if 'maxlength' is -1, searches to end
1893 * Returns -1 if 'maxlength' reached before finding EOS. */
1895 tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
1898 guint abs_offset, junk_length;
1900 DISSECTOR_ASSERT(tvb && tvb->initialized);
1902 check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
1904 result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
1906 if (result_offset == -1) {
1910 return result_offset - abs_offset;
1915 * Implement strneql etc
1919 * Call strncmp after checking if enough chars left, returning 0 if
1920 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1923 tvb_strneql(tvbuff_t *tvb, gint offset, const gchar *str, gint size)
1927 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1930 int cmp = strncmp((const char *)ptr, str, size);
1933 * Return 0 if equal, -1 otherwise.
1935 return (cmp == 0 ? 0 : -1);
1938 * Not enough characters in the tvbuff to match the
1946 * Call g_ascii_strncasecmp after checking if enough chars left, returning
1947 * 0 if it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1950 tvb_strncaseeql(tvbuff_t *tvb, gint offset, const gchar *str, gint size)
1954 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1957 int cmp = g_ascii_strncasecmp((const char *)ptr, str, size);
1960 * Return 0 if equal, -1 otherwise.
1962 return (cmp == 0 ? 0 : -1);
1965 * Not enough characters in the tvbuff to match the
1973 * Call memcmp after checking if enough chars left, returning 0 if
1974 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1977 tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, size_t size)
1981 ptr = ensure_contiguous_no_exception(tvb, offset, (gint) size, NULL);
1984 int cmp = memcmp(ptr, str, size);
1987 * Return 0 if equal, -1 otherwise.
1989 return (cmp == 0 ? 0 : -1);
1992 * Not enough characters in the tvbuff to match the
1999 /* Convert a string from Unicode to ASCII. At the moment we fake it by
2000 * replacing all non-ASCII characters with a '.' )-: The caller must
2001 * free the result returned. The len parameter is the number of guint16's
2002 * to convert from Unicode. */
2004 tvb_fake_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
2010 /* Make sure we have enough data before allocating the buffer,
2011 so we don't blow up if the length is huge. */
2012 tvb_ensure_bytes_exist(tvb, offset, 2*len);
2014 /* We know we won't throw an exception, so we don't have to worry
2015 about leaking this buffer. */
2016 buffer = g_malloc(len + 1);
2018 for (i = 0; i < len; i++) {
2019 character = little_endian ? tvb_get_letohs(tvb, offset)
2020 : tvb_get_ntohs(tvb, offset);
2021 buffer[i] = character < 256 ? character : '.';
2030 /* Convert a string from Unicode to ASCII. At the moment we fake it by
2031 * replacing all non-ASCII characters with a '.' )-: The len parameter is
2032 * the number of guint16's to convert from Unicode.
2034 * This function allocates memory from a buffer with packet lifetime.
2035 * You do not have to free this buffer, it will be automatically freed
2036 * when wireshark starts decoding the next packet.
2039 tvb_get_ephemeral_faked_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
2045 /* Make sure we have enough data before allocating the buffer,
2046 so we don't blow up if the length is huge. */
2047 tvb_ensure_bytes_exist(tvb, offset, 2*len);
2049 /* We know we won't throw an exception, so we don't have to worry
2050 about leaking this buffer. */
2051 buffer = ep_alloc(len + 1);
2053 for (i = 0; i < len; i++) {
2054 character = little_endian ? tvb_get_letohs(tvb, offset)
2055 : tvb_get_ntohs(tvb, offset);
2056 buffer[i] = character < 256 ? character : '.';
2066 * Format the data in the tvb from offset for length ...
2070 tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
2075 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
2077 len = tvb_length_remaining(tvb, offset);
2078 ptr = ensure_contiguous(tvb, offset, len);
2082 return format_text(ptr, len);
2087 * Format the data in the tvb from offset for length ...
2091 tvb_format_text_wsp(tvbuff_t *tvb, gint offset, gint size)
2096 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
2098 len = tvb_length_remaining(tvb, offset);
2099 ptr = ensure_contiguous(tvb, offset, len);
2103 return format_text_wsp(ptr, len);
2108 * Like "tvb_format_text()", but for null-padded strings; don't show
2109 * the null padding characters as "\000".
2112 tvb_format_stringzpad(tvbuff_t *tvb, gint offset, gint size)
2114 const guint8 *ptr, *p;
2118 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
2120 len = tvb_length_remaining(tvb, offset);
2121 ptr = ensure_contiguous(tvb, offset, len);
2125 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2127 return format_text(ptr, stringlen);
2132 * Like "tvb_format_text_wsp()", but for null-padded strings; don't show
2133 * the null padding characters as "\000".
2136 tvb_format_stringzpad_wsp(tvbuff_t *tvb, gint offset, gint size)
2138 const guint8 *ptr, *p;
2142 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
2144 len = tvb_length_remaining(tvb, offset);
2145 ptr = ensure_contiguous(tvb, offset, len);
2149 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2151 return format_text_wsp(ptr, stringlen);
2156 * Given a tvbuff, an offset, and a length, allocate a buffer big enough
2157 * to hold a non-null-terminated string of that length at that offset,
2158 * plus a trailing '\0', copy the string into it, and return a pointer
2161 * Throws an exception if the tvbuff ends before the string does.
2164 tvb_get_string(tvbuff_t *tvb, gint offset, gint length)
2167 guint8 *strbuf = NULL;
2169 tvb_ensure_bytes_exist(tvb, offset, length);
2171 ptr = ensure_contiguous(tvb, offset, length);
2172 strbuf = g_malloc(length + 1);
2174 memcpy(strbuf, ptr, length);
2176 strbuf[length] = '\0';
2180 * Given a tvbuff, an offset, and a length, allocate a buffer big enough
2181 * to hold a non-null-terminated string of that length at that offset,
2182 * plus a trailing '\0', copy the string into it, and return a pointer
2185 * Throws an exception if the tvbuff ends before the string does.
2187 * This function allocates memory from a buffer with packet lifetime.
2188 * You do not have to free this buffer, it will be automatically freed
2189 * when wireshark starts decoding the next packet.
2190 * Do not use this function if you want the allocated memory to be persistent
2191 * after the current packet has been dissected.
2194 tvb_get_ephemeral_string(tvbuff_t *tvb, gint offset, gint length)
2197 guint8 *strbuf = NULL;
2199 tvb_ensure_bytes_exist(tvb, offset, length);
2201 ptr = ensure_contiguous(tvb, offset, length);
2202 strbuf = ep_alloc(length + 1);
2204 memcpy(strbuf, ptr, length);
2206 strbuf[length] = '\0';
2211 * Given a tvbuff, an offset, and a length, allocate a buffer big enough
2212 * to hold a non-null-terminated string of that length at that offset,
2213 * plus a trailing '\0', copy the string into it, and return a pointer
2216 * Throws an exception if the tvbuff ends before the string does.
2218 * This function allocates memory from a buffer with capture session lifetime.
2219 * You do not have to free this buffer, it will be automatically freed
2220 * when wireshark starts or opens a new capture.
2223 tvb_get_seasonal_string(tvbuff_t *tvb, gint offset, gint length)
2226 guint8 *strbuf = NULL;
2228 tvb_ensure_bytes_exist(tvb, offset, length);
2230 ptr = ensure_contiguous(tvb, offset, length);
2231 strbuf = se_alloc(length + 1);
2233 memcpy(strbuf, ptr, length);
2235 strbuf[length] = '\0';
2240 * Given a tvbuff and an offset, with the offset assumed to refer to
2241 * a null-terminated string, find the length of that string (and throw
2242 * an exception if the tvbuff ends before we find the null), allocate
2243 * a buffer big enough to hold the string, copy the string into it,
2244 * and return a pointer to the string. Also return the length of the
2245 * string (including the terminating null) through a pointer.
2248 tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
2253 size = tvb_strsize(tvb, offset);
2254 strptr = g_malloc(size);
2255 tvb_memcpy(tvb, strptr, offset, size);
2260 * Given a tvbuff and an offset, with the offset assumed to refer to
2261 * a null-terminated string, find the length of that string (and throw
2262 * an exception if the tvbuff ends before we find the null), allocate
2263 * a buffer big enough to hold the string, copy the string into it,
2264 * and return a pointer to the string. Also return the length of the
2265 * string (including the terminating null) through a pointer.
2267 * This function allocates memory from a buffer with packet lifetime.
2268 * You do not have to free this buffer, it will be automatically freed
2269 * when wireshark starts decoding the next packet.
2270 * Do not use this function if you want the allocated memory to be persistent
2271 * after the current packet has been dissected.
2274 tvb_get_ephemeral_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
2279 size = tvb_strsize(tvb, offset);
2280 strptr = ep_alloc(size);
2281 tvb_memcpy(tvb, strptr, offset, size);
2287 * Given a tvbuff and an offset, with the offset assumed to refer to
2288 * a null-terminated string, find the length of that string (and throw
2289 * an exception if the tvbuff ends before we find the null), allocate
2290 * a buffer big enough to hold the string, copy the string into it,
2291 * and return a pointer to the string. Also return the length of the
2292 * string (including the terminating null) through a pointer.
2294 * This function allocates memory from a buffer with capture session lifetime.
2295 * You do not have to free this buffer, it will be automatically freed
2296 * when wireshark starts or opens a new capture.
2299 tvb_get_seasonal_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
2304 size = tvb_strsize(tvb, offset);
2305 strptr = se_alloc(size);
2306 tvb_memcpy(tvb, strptr, offset, size);
2311 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
2312 * no more than bufsize number of bytes, including terminating NUL, to buffer.
2313 * Returns length of string (not including terminating NUL), or -1 if the string was
2314 * truncated in the buffer due to not having reached the terminating NUL.
2315 * In this way, it acts like g_snprintf().
2317 * bufsize MUST be greater than 0.
2319 * When processing a packet where the remaining number of bytes is less
2320 * than bufsize, an exception is not thrown if the end of the packet
2321 * is reached before the NUL is found. If no NUL is found before reaching
2322 * the end of the short packet, -1 is still returned, and the string
2323 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
2324 * at the correct spot, terminating the string.
2326 * *bytes_copied will contain the number of bytes actually copied,
2327 * including the terminating-NUL.
2330 _tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer,
2334 guint abs_offset, junk_length;
2336 gboolean decreased_max = FALSE;
2338 check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
2340 /* There must at least be room for the terminating NUL. */
2341 DISSECTOR_ASSERT(bufsize != 0);
2343 /* If there's no room for anything else, just return the NUL. */
2350 /* Only read to end of tvbuff, w/o throwing exception. */
2351 len = tvb_length_remaining(tvb, abs_offset);
2353 /* check_offset_length() won't throw an exception if we're
2354 * looking at the byte immediately after the end of the tvbuff. */
2356 THROW(ReportedBoundsError);
2359 /* This should not happen because check_offset_length() would
2360 * have already thrown an exception if 'offset' were out-of-bounds.
2362 DISSECTOR_ASSERT(len != -1);
2365 * If we've been passed a negative number, bufsize will
2368 DISSECTOR_ASSERT(bufsize <= G_MAXINT);
2370 if ((guint)len < bufsize) {
2372 decreased_max = TRUE;
2378 stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
2379 /* If NUL wasn't found, copy the data and return -1 */
2380 if (stringlen == -1) {
2381 tvb_memcpy(tvb, buffer, abs_offset, limit);
2382 if (decreased_max) {
2384 /* Add 1 for the extra NUL that we set at buffer[limit],
2385 * pretending that it was copied as part of the string. */
2386 *bytes_copied = limit + 1;
2389 *bytes_copied = limit;
2394 /* Copy the string to buffer */
2395 tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
2396 *bytes_copied = stringlen + 1;
2400 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
2401 * no more than bufsize number of bytes, including terminating NUL, to buffer.
2402 * Returns length of string (not including terminating NUL), or -1 if the string was
2403 * truncated in the buffer due to not having reached the terminating NUL.
2404 * In this way, it acts like g_snprintf().
2406 * When processing a packet where the remaining number of bytes is less
2407 * than bufsize, an exception is not thrown if the end of the packet
2408 * is reached before the NUL is found. If no NUL is found before reaching
2409 * the end of the short packet, -1 is still returned, and the string
2410 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
2411 * at the correct spot, terminating the string.
2414 tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
2418 DISSECTOR_ASSERT(tvb && tvb->initialized);
2420 return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
2423 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
2424 * have a terminating NUL. If the string was truncated when copied into buffer,
2425 * a NUL is placed at the end of buffer to terminate it.
2428 tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
2430 gint len, bytes_copied;
2432 DISSECTOR_ASSERT(tvb && tvb->initialized);
2434 len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
2437 buffer[bufsize - 1] = 0;
2438 return bytes_copied - 1;
2446 * Given a tvbuff, an offset into the tvbuff, and a length that starts
2447 * at that offset (which may be -1 for "all the way to the end of the
2448 * tvbuff"), find the end of the (putative) line that starts at the
2449 * specified offset in the tvbuff, going no further than the specified
2452 * Return the length of the line (not counting the line terminator at
2453 * the end), or, if we don't find a line terminator:
2455 * if "deseg" is true, return -1;
2457 * if "deseg" is false, return the amount of data remaining in
2460 * Set "*next_offset" to the offset of the character past the line
2461 * terminator, or past the end of the buffer if we don't find a line
2462 * terminator. (It's not set if we return -1.)
2465 tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
2473 len = tvb_length_remaining(tvb, offset);
2475 * XXX - what if "len" is still -1, meaning "offset is past the
2476 * end of the tvbuff"?
2478 eob_offset = offset + len;
2481 * Look either for a CR or an LF.
2483 eol_offset = tvb_pbrk_guint8(tvb, offset, len, (const guint8 *)"\r\n");
2484 if (eol_offset == -1) {
2486 * No CR or LF - line is presumably continued in next packet.
2490 * Tell our caller we saw no EOL, so they can
2491 * try to desegment and get the entire line
2497 * Pretend the line runs to the end of the tvbuff.
2499 linelen = eob_offset - offset;
2500 *next_offset = eob_offset;
2504 * Find the number of bytes between the starting offset
2507 linelen = eol_offset - offset;
2512 if (tvb_get_guint8(tvb, eol_offset) == '\r') {
2514 * Yes - is it followed by an LF?
2516 if (eol_offset + 1 >= eob_offset) {
2518 * Dunno - the next byte isn't in this
2523 * We'll return -1, although that
2524 * runs the risk that if the line
2525 * really *is* terminated with a CR,
2526 * we won't properly dissect this
2529 * It's probably more likely that
2530 * the line ends with CR-LF than
2531 * that it ends with CR by itself.
2537 * Well, we can at least look at the next
2540 if (tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
2542 * It's an LF; skip over the CR.
2550 * Return the offset of the character after the last
2551 * character in the line, skipping over the last character
2552 * in the line terminator.
2554 *next_offset = eol_offset + 1;
2560 * Given a tvbuff, an offset into the tvbuff, and a length that starts
2561 * at that offset (which may be -1 for "all the way to the end of the
2562 * tvbuff"), find the end of the (putative) line that starts at the
2563 * specified offset in the tvbuff, going no further than the specified
2566 * However, treat quoted strings inside the buffer specially - don't
2567 * treat newlines in quoted strings as line terminators.
2569 * Return the length of the line (not counting the line terminator at
2570 * the end), or the amount of data remaining in the buffer if we don't
2571 * find a line terminator.
2573 * Set "*next_offset" to the offset of the character past the line
2574 * terminator, or past the end of the buffer if we don't find a line
2578 tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
2581 gint cur_offset, char_offset;
2588 len = tvb_length_remaining(tvb, offset);
2590 * XXX - what if "len" is still -1, meaning "offset is past the
2591 * end of the tvbuff"?
2593 eob_offset = offset + len;
2595 cur_offset = offset;
2599 * Is this part of the string quoted?
2603 * Yes - look only for the terminating quote.
2605 char_offset = tvb_find_guint8(tvb, cur_offset, len,
2609 * Look either for a CR, an LF, or a '"'.
2611 char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
2612 (const guint8 *)"\r\n\"");
2614 if (char_offset == -1) {
2616 * Not found - line is presumably continued in
2618 * We pretend the line runs to the end of the tvbuff.
2620 linelen = eob_offset - offset;
2621 *next_offset = eob_offset;
2627 * We're processing a quoted string.
2628 * We only looked for ", so we know it's a ";
2629 * as we're processing a quoted string, it's a
2637 c = tvb_get_guint8(tvb, char_offset);
2640 * Un-quoted "; it begins a quoted
2646 * It's a CR or LF; we've found a line
2649 * Find the number of bytes between the
2650 * starting offset and the CR or LF.
2652 linelen = char_offset - offset;
2659 * Yes; is it followed by an LF?
2661 if (char_offset + 1 < eob_offset &&
2662 tvb_get_guint8(tvb, char_offset + 1)
2665 * Yes; skip over the CR.
2672 * Return the offset of the character after
2673 * the last character in the line, skipping
2674 * over the last character in the line
2675 * terminator, and quit.
2677 *next_offset = char_offset + 1;
2683 * Step past the character we found.
2685 cur_offset = char_offset + 1;
2686 if (cur_offset >= eob_offset) {
2688 * The character we found was the last character
2689 * in the tvbuff - line is presumably continued in
2691 * We pretend the line runs to the end of the tvbuff.
2693 linelen = eob_offset - offset;
2694 *next_offset = eob_offset;
2702 * Copied from the mgcp dissector. (This function should be moved to /epan )
2703 * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
2704 * character following offset or offset + maxlength -1 whichever
2708 * tvb - The tvbuff in which we are skipping whitespace.
2709 * offset - The offset in tvb from which we begin trying to skip whitespace.
2710 * maxlength - The maximum distance from offset that we may try to skip
2713 * Returns: The position in tvb of the first non-whitespace
2714 * character following offset or offset + maxlength -1 whichever
2717 gint tvb_skip_wsp(tvbuff_t* tvb, gint offset, gint maxlength)
2719 gint counter = offset;
2720 gint end = offset + maxlength,tvb_len;
2723 /* Get the length remaining */
2724 tvb_len = tvb_length(tvb);
2725 end = offset + maxlength;
2731 /* Skip past spaces, tabs, CRs and LFs until run out or meet something else */
2732 for (counter = offset;
2734 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
2735 tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
2741 gint tvb_skip_wsp_return(tvbuff_t* tvb, gint offset){
2742 gint counter = offset;
2747 for(counter = offset; counter > end &&
2748 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
2749 tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter--);
2756 * Format a bunch of data from a tvbuff as bytes, returning a pointer
2757 * to the string with the formatted data, with "punct" as a byte
2761 tvb_bytes_to_str_punct(tvbuff_t *tvb, gint offset, gint len, gchar punct)
2763 return bytes_to_str_punct(tvb_get_ptr(tvb, offset, len), len, punct);
2767 * Format a bunch of data from a tvbuff as bytes, returning a pointer
2768 * to the string with the formatted data.
2771 tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len)
2773 return bytes_to_str(tvb_get_ptr(tvb, offset, len), len);
2776 /* Find a needle tvbuff within a haystack tvbuff. */
2778 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
2780 guint haystack_abs_offset, haystack_abs_length;
2781 const guint8 *haystack_data;
2782 const guint8 *needle_data;
2783 const guint needle_len = needle_tvb->length;
2784 const guint8 *location;
2786 DISSECTOR_ASSERT(haystack_tvb && haystack_tvb->initialized);
2788 if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
2792 /* Get pointers to the tvbuffs' data. */
2793 haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
2794 needle_data = tvb_get_ptr(needle_tvb, 0, -1);
2796 check_offset_length(haystack_tvb->length, haystack_tvb->reported_length, haystack_offset, -1,
2797 &haystack_abs_offset, &haystack_abs_length);
2799 location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
2800 needle_data, needle_len);
2803 return (gint) (location - haystack_data);
2811 * Uncompresses a zlib compressed packet inside a message of tvb at offset with
2812 * length comprlen. Returns an uncompressed tvbuffer if uncompression
2813 * succeeded or NULL if uncompression failed.
2815 #define TVB_Z_MIN_BUFSIZ 32768
2816 #define TVB_Z_MAX_BUFSIZ 1048576 * 10
2817 /* #define TVB_Z_DEBUG 1 */
2821 tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
2826 guint bytes_out = 0;
2827 guint8 *compr = NULL;
2828 guint8 *uncompr = NULL;
2829 tvbuff_t *uncompr_tvb = NULL;
2830 z_streamp strm = NULL;
2831 Bytef *strmbuf = NULL;
2832 guint inits_done = 0;
2833 gint wbits = MAX_WBITS;
2834 guint8 *next = NULL;
2835 guint bufsiz = TVB_Z_MIN_BUFSIZ;
2837 guint inflate_passes = 0;
2838 guint bytes_in = tvb_length_remaining(tvb, offset);
2845 strm = g_malloc0(sizeof(z_stream));
2851 compr = tvb_memdup(tvb, offset, comprlen);
2859 * Assume that the uncompressed data is at least twice as big as
2860 * the compressed size.
2862 bufsiz = tvb_length_remaining(tvb, offset) * 2;
2864 if (bufsiz < TVB_Z_MIN_BUFSIZ) {
2865 bufsiz = TVB_Z_MIN_BUFSIZ;
2866 } else if (bufsiz > TVB_Z_MAX_BUFSIZ) {
2867 bufsiz = TVB_Z_MIN_BUFSIZ;
2871 printf("bufsiz: %u bytes\n", bufsiz);
2876 strm->next_in = next;
2877 strm->avail_in = comprlen;
2880 strmbuf = g_malloc0(bufsiz);
2882 if(strmbuf == NULL) {
2888 strm->next_out = strmbuf;
2889 strm->avail_out = bufsiz;
2891 err = inflateInit2(strm, wbits);
2902 memset(strmbuf, '\0', bufsiz);
2903 strm->next_out = strmbuf;
2904 strm->avail_out = bufsiz;
2906 err = inflate(strm, Z_SYNC_FLUSH);
2908 if (err == Z_OK || err == Z_STREAM_END) {
2909 guint bytes_pass = bufsiz - strm->avail_out;
2915 if (uncompr == NULL) {
2916 uncompr = g_memdup(strmbuf, bytes_pass);
2918 guint8 *new_data = g_malloc0(bytes_out +
2921 if (new_data == NULL) {
2927 if (uncompr != NULL) {
2934 g_memmove(new_data, uncompr, bytes_out);
2935 g_memmove((new_data + bytes_out), strmbuf,
2942 bytes_out += bytes_pass;
2944 if ( err == Z_STREAM_END) {
2950 } else if (err == Z_BUF_ERROR) {
2952 * It's possible that not enough frames were captured
2953 * to decompress this fully, so return what we've done
2960 if (uncompr != NULL) {
2967 } else if (err == Z_DATA_ERROR && inits_done == 1
2968 && uncompr == NULL && (*compr == 0x1f) &&
2969 (*(compr + 1) == 0x8b)) {
2971 * inflate() is supposed to handle both gzip and deflate
2972 * streams automatically, but in reality it doesn't
2973 * seem to handle either (at least not within the
2974 * context of an HTTP response.) We have to try
2975 * several tweaks, depending on the type of data and
2976 * version of the library installed.
2980 * Gzip file format. Skip past the header, since the
2981 * fix to make it work (setting windowBits to 31)
2982 * doesn't work with all versions of the library.
2984 Bytef *c = compr + 2;
2987 if (*c == Z_DEFLATED) {
2999 /* Skip past the MTIME, XFL, and OS fields. */
3002 if (flags & (1 << 2)) {
3003 /* An Extra field is present. */
3004 gint xsize = (gint)(*c |
3010 if (flags & (1 << 3)) {
3011 /* A null terminated filename */
3013 while ((c - compr) < comprlen && *c != '\0') {
3020 if (flags & (1 << 4)) {
3021 /* A null terminated comment */
3023 while ((c - compr) < comprlen && *c != '\0') {
3033 strm->next_in = next;
3034 if (c - compr > comprlen) {
3041 comprlen -= (int) (c - compr);
3044 err = inflateInit2(strm, wbits);
3046 } else if (err == Z_DATA_ERROR && uncompr == NULL &&
3050 * Re-init the stream with a negative
3051 * MAX_WBITS. This is necessary due to
3052 * some servers (Apache) not sending
3053 * the deflate header with the
3054 * content-encoded response.
3060 strm->next_in = next;
3061 strm->avail_in = comprlen;
3064 memset(strmbuf, '\0', bufsiz);
3065 strm->next_out = strmbuf;
3066 strm->avail_out = bufsiz;
3068 err = inflateInit2(strm, wbits);
3086 if (uncompr == NULL) {
3095 printf("inflate() total passes: %u\n", inflate_passes);
3096 printf("bytes in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
3099 if (uncompr != NULL) {
3100 uncompr_tvb = tvb_new_real_data((guint8*) uncompr, bytes_out,
3102 tvb_set_free_cb(uncompr_tvb, g_free);
3109 tvb_uncompress(tvbuff_t *tvb _U_, int offset _U_, int comprlen _U_)
3115 tvbuff_t* tvb_child_uncompress(tvbuff_t *parent _U_, tvbuff_t *tvb, int offset, int comprlen)
3117 tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
3119 tvb_set_child_real_data_tvbuff (parent, new_tvb);