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 * Ethereal - Network traffic analyzer
20 * By Gerald Combs <gerald@ethereal.com>
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.
53 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
57 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length);
59 /* We dole out tvbuff's from this memchunk. */
60 GMemChunk *tvbuff_mem_chunk = NULL;
65 if (!tvbuff_mem_chunk)
66 tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
73 g_mem_chunk_destroy(tvbuff_mem_chunk);
75 tvbuff_mem_chunk = NULL;
82 tvb_init(tvbuff_t *tvb, tvbuff_type type)
84 tvb_backing_t *backing;
85 tvb_comp_t *composite;
88 tvb->initialized = FALSE;
91 tvb->reported_length = 0;
93 tvb->real_data = NULL;
99 case TVBUFF_REAL_DATA:
104 backing = &tvb->tvbuffs.subset;
110 case TVBUFF_COMPOSITE:
111 composite = &tvb->tvbuffs.composite;
112 composite->tvbs = NULL;
113 composite->start_offsets = NULL;
114 composite->end_offsets = NULL;
121 tvb_new(tvbuff_type type)
125 tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
134 tvb_free(tvbuff_t* tvb)
136 tvbuff_t *member_tvb;
137 tvb_comp_t *composite;
142 if (tvb->usage_count == 0) {
144 case TVBUFF_REAL_DATA:
147 * XXX - do this with a union?
149 tvb->free_cb((gpointer)tvb->real_data);
154 /* This will be NULL if tvb_new_subset() fails because
155 * reported_length < -1 */
156 if (tvb->tvbuffs.subset.tvb) {
157 tvb_decrement_usage_count(tvb->tvbuffs.subset.tvb, 1);
161 case TVBUFF_COMPOSITE:
162 composite = &tvb->tvbuffs.composite;
163 for (slist = composite->tvbs; slist != NULL ; slist = slist->next) {
164 member_tvb = slist->data;
165 tvb_decrement_usage_count(member_tvb, 1);
168 g_slist_free(composite->tvbs);
170 if (composite->start_offsets)
171 g_free(composite->start_offsets);
172 if (composite->end_offsets)
173 g_free(composite->end_offsets);
174 if (tvb->real_data) {
176 * XXX - do this with a union?
178 g_free((gpointer)tvb->real_data);
185 g_slist_free(tvb->used_in);
188 g_chunk_free(tvb, tvbuff_mem_chunk);
193 tvb_increment_usage_count(tvbuff_t* tvb, guint count)
195 tvb->usage_count += count;
197 return tvb->usage_count;
201 tvb_decrement_usage_count(tvbuff_t* tvb, guint count)
203 if (tvb->usage_count <= count) {
204 tvb->usage_count = 1;
209 tvb->usage_count -= count;
210 return tvb->usage_count;
216 tvb_free_chain(tvbuff_t* tvb)
220 /* Recursively call tvb_free_chain() */
221 for (slist = tvb->used_in; slist != NULL ; slist = slist->next) {
222 tvb_free_chain( (tvbuff_t*)slist->data );
225 /* Stop the recursion */
232 tvb_set_free_cb(tvbuff_t* tvb, tvbuff_free_cb_t func)
234 g_assert(tvb->type == TVBUFF_REAL_DATA);
239 add_to_used_in_list(tvbuff_t *tvb, tvbuff_t *used_in)
241 tvb->used_in = g_slist_prepend(tvb->used_in, used_in);
242 tvb_increment_usage_count(tvb, 1);
246 tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child)
248 g_assert(parent->initialized);
249 g_assert(child->initialized);
250 g_assert(child->type == TVBUFF_REAL_DATA);
251 add_to_used_in_list(parent, child);
255 tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
257 g_assert(tvb->type == TVBUFF_REAL_DATA);
258 g_assert(!tvb->initialized);
260 if (reported_length < -1) {
261 THROW(ReportedBoundsError);
264 tvb->real_data = data;
265 tvb->length = length;
266 tvb->reported_length = reported_length;
267 tvb->initialized = TRUE;
271 tvb_new_real_data(const guint8* data, guint length, gint reported_length)
273 static tvbuff_t *last_tvb=NULL;
276 tvb = tvb_new(TVBUFF_REAL_DATA);
281 /* remember this tvb in case we throw an exception and
282 * lose the pointer to it.
286 tvb_set_real_data(tvb, data, length, reported_length);
289 * This is the top-level real tvbuff for this data source,
290 * so its data source tvbuff is itself.
294 /* ok no exception so we dont need to remember it any longer */
300 /* Computes the absolute offset and length based on a possibly-negative offset
301 * and a length that is possible -1 (which means "to the end of the data").
302 * Returns TRUE/FALSE indicating whether the offset is in bounds or
303 * not. The integer ptrs are modified with the new offset and length.
304 * No exception is thrown.
306 * XXX - we return TRUE, not FALSE, if the offset is positive and right
307 * after the end of the tvbuff (i.e., equal to the length). We do this
308 * so that a dissector constructing a subset tvbuff for the next protocol
309 * will get a zero-length tvbuff, not an exception, if there's no data
310 * left for the next protocol - we want the next protocol to be the one
311 * that gets an exception, so the error is reported as an error in that
312 * protocol rather than the containing protocol. */
314 compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
315 guint *offset_ptr, guint *length_ptr, int *exception)
317 g_assert(offset_ptr);
318 g_assert(length_ptr);
320 /* Compute the offset */
322 /* Positive offset - relative to the beginning of the packet. */
323 if ((guint) offset > tvb->reported_length) {
325 *exception = ReportedBoundsError;
329 else if ((guint) offset > tvb->length) {
331 *exception = BoundsError;
336 *offset_ptr = offset;
340 /* Negative offset - relative to the end of the packet. */
341 if ((guint) -offset > tvb->reported_length) {
343 *exception = ReportedBoundsError;
347 else if ((guint) -offset > tvb->length) {
349 *exception = BoundsError;
354 *offset_ptr = tvb->length + offset;
358 /* Compute the length */
361 /* XXX - ReportedBoundsError? */
362 *exception = BoundsError;
366 else if (length == -1) {
367 *length_ptr = tvb->length - *offset_ptr;
370 *length_ptr = length;
378 check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
379 guint *offset_ptr, guint *length_ptr, int *exception)
383 g_assert(tvb->initialized);
385 if (!compute_offset_length(tvb, offset, length, offset_ptr, length_ptr, exception)) {
390 * Compute the offset of the first byte past the length.
392 end_offset = *offset_ptr + *length_ptr;
395 * Check for an overflow, and clamp "end_offset" at the maximum
396 * if we got an overflow - that should force us to indicate that
397 * we're past the end of the tvbuff.
399 if (end_offset < *offset_ptr)
400 end_offset = UINT_MAX;
403 * Check whether that offset goes more than one byte past the
406 * If not, return TRUE; otherwise, return FALSE and, if "exception"
407 * is non-null, return the appropriate exception through it.
409 if (end_offset <= tvb->length) {
412 else if (end_offset <= tvb->reported_length) {
414 *exception = BoundsError;
420 *exception = ReportedBoundsError;
425 g_assert_not_reached();
428 /* Checks (+/-) offset and length and throws an exception if
429 * either is out of bounds. Sets integer ptrs to the new offset
432 check_offset_length(tvbuff_t *tvb, gint offset, gint length,
433 guint *offset_ptr, guint *length_ptr)
437 if (!check_offset_length_no_exception(tvb, offset, length, offset_ptr, length_ptr, &exception)) {
438 g_assert(exception > 0);
446 tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
447 gint backing_offset, gint backing_length, gint reported_length)
449 g_assert(tvb->type == TVBUFF_SUBSET);
450 g_assert(!tvb->initialized);
452 if (reported_length < -1) {
453 THROW(ReportedBoundsError);
456 check_offset_length(backing, backing_offset, backing_length,
457 &tvb->tvbuffs.subset.offset,
458 &tvb->tvbuffs.subset.length);
460 tvb->tvbuffs.subset.tvb = backing;
461 tvb->length = tvb->tvbuffs.subset.length;
463 if (reported_length == -1) {
464 tvb->reported_length = backing->reported_length - tvb->tvbuffs.subset.offset;
467 tvb->reported_length = reported_length;
469 tvb->initialized = TRUE;
470 add_to_used_in_list(backing, tvb);
472 /* Optimization. If the backing buffer has a pointer to contiguous, real data,
473 * then we can point directly to our starting offset in that buffer */
474 if (backing->real_data != NULL) {
475 tvb->real_data = backing->real_data + tvb->tvbuffs.subset.offset;
481 tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint reported_length)
483 static tvbuff_t *last_tvb=NULL;
486 tvb = tvb_new(TVBUFF_SUBSET);
491 /* remember this tvb in case we throw an exception and
492 * lose the pointer to it.
496 tvb_set_subset(tvb, backing, backing_offset, backing_length, reported_length);
499 * The top-level data source of this tvbuff is the top-level
500 * data source of its parent.
502 tvb->ds_tvb = backing->ds_tvb;
504 /* ok no exception so we dont need to remember it any longer */
511 tvb_composite_append(tvbuff_t* tvb, tvbuff_t* member)
513 tvb_comp_t *composite;
515 g_assert(!tvb->initialized);
516 composite = &tvb->tvbuffs.composite;
517 composite->tvbs = g_slist_append( composite->tvbs, member );
518 add_to_used_in_list(member, tvb);
522 tvb_composite_prepend(tvbuff_t* tvb, tvbuff_t* member)
524 tvb_comp_t *composite;
526 g_assert(!tvb->initialized);
527 composite = &tvb->tvbuffs.composite;
528 composite->tvbs = g_slist_prepend( composite->tvbs, member );
529 add_to_used_in_list(member, tvb);
533 tvb_new_composite(void)
535 return tvb_new(TVBUFF_COMPOSITE);
539 tvb_composite_finalize(tvbuff_t* tvb)
543 tvbuff_t *member_tvb;
544 tvb_comp_t *composite;
547 g_assert(!tvb->initialized);
548 g_assert(tvb->length == 0);
550 composite = &tvb->tvbuffs.composite;
551 num_members = g_slist_length(composite->tvbs);
553 composite->start_offsets = g_new(guint, num_members);
554 composite->end_offsets = g_new(guint, num_members);
556 for (slist = composite->tvbs; slist != NULL; slist = slist->next) {
557 g_assert((guint) i < num_members);
558 member_tvb = slist->data;
559 composite->start_offsets[i] = tvb->length;
560 tvb->length += member_tvb->length;
561 composite->end_offsets[i] = tvb->length - 1;
565 tvb->initialized = TRUE;
571 tvb_length(tvbuff_t* tvb)
573 g_assert(tvb->initialized);
579 tvb_length_remaining(tvbuff_t *tvb, gint offset)
581 guint abs_offset, abs_length;
583 g_assert(tvb->initialized);
585 if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
594 tvb_ensure_length_remaining(tvbuff_t *tvb, gint offset)
596 guint abs_offset, abs_length;
599 g_assert(tvb->initialized);
601 if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, &exception)) {
604 if (abs_length == 0) {
606 * This routine ensures there's at least one byte available.
607 * There aren't any bytes available, so throw the appropriate
610 if (abs_offset >= tvb->reported_length)
611 THROW(ReportedBoundsError);
621 /* Validates that 'length' bytes are available starting from
622 * offset (pos/neg). Does not throw an exception. */
624 tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
626 guint abs_offset, abs_length;
628 g_assert(tvb->initialized);
630 if (!compute_offset_length(tvb, offset, length, &abs_offset, &abs_length, NULL))
633 if (abs_offset + abs_length <= tvb->length) {
641 /* Validates that 'length' bytes are available starting from
642 * offset (pos/neg). Throws an exception if they aren't. */
644 tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
646 guint abs_offset, abs_length;
648 g_assert(tvb->initialized);
651 * -1 doesn't mean "until end of buffer", as that's pointless
652 * for this routine. We must treat it as a Really Large Positive
653 * Number, so that we throw an exception; we throw
654 * ReportedBoundsError, as if it were past even the end of a
655 * reassembled packet, and past the end of even the data we
658 * We do the same with other negative lengths.
661 THROW(ReportedBoundsError);
663 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
667 tvb_offset_exists(tvbuff_t *tvb, gint offset)
669 guint abs_offset, abs_length;
671 g_assert(tvb->initialized);
672 if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL))
675 if (abs_offset < tvb->length) {
684 tvb_reported_length(tvbuff_t* tvb)
686 g_assert(tvb->initialized);
688 return tvb->reported_length;
692 tvb_reported_length_remaining(tvbuff_t *tvb, gint offset)
694 guint abs_offset, abs_length;
696 g_assert(tvb->initialized);
698 if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
699 if (tvb->reported_length >= abs_offset)
700 return tvb->reported_length - abs_offset;
709 /* Set the reported length of a tvbuff to a given value; used for protocols
710 whose headers contain an explicit length and where the calling
711 dissector's payload may include padding as well as the packet for
714 Also adjusts the data length. */
716 tvb_set_reported_length(tvbuff_t* tvb, guint reported_length)
718 g_assert(tvb->initialized);
720 if (reported_length > tvb->reported_length)
721 THROW(ReportedBoundsError);
723 tvb->reported_length = reported_length;
724 if (reported_length < tvb->length)
725 tvb->length = reported_length;
730 first_real_data_ptr(tvbuff_t *tvb)
735 case TVBUFF_REAL_DATA:
736 return tvb->real_data;
738 member = tvb->tvbuffs.subset.tvb;
739 return first_real_data_ptr(member);
740 case TVBUFF_COMPOSITE:
741 member = tvb->tvbuffs.composite.tvbs->data;
742 return first_real_data_ptr(member);
745 g_assert_not_reached();
750 offset_from_real_beginning(tvbuff_t *tvb, int counter)
755 case TVBUFF_REAL_DATA:
758 member = tvb->tvbuffs.subset.tvb;
759 return offset_from_real_beginning(member, counter + tvb->tvbuffs.subset.offset);
760 case TVBUFF_COMPOSITE:
761 member = tvb->tvbuffs.composite.tvbs->data;
762 return offset_from_real_beginning(member, counter);
765 g_assert_not_reached();
770 composite_ensure_contiguous_no_exception(tvbuff_t *tvb, guint abs_offset,
773 guint i, num_members;
774 tvb_comp_t *composite;
775 tvbuff_t *member_tvb = NULL;
776 guint member_offset, member_length;
779 g_assert(tvb->type == TVBUFF_COMPOSITE);
781 /* Maybe the range specified by offset/length
782 * is contiguous inside one of the member tvbuffs */
783 composite = &tvb->tvbuffs.composite;
784 num_members = g_slist_length(composite->tvbs);
786 for (i = 0; i < num_members; i++) {
787 if (abs_offset <= composite->end_offsets[i]) {
788 slist = g_slist_nth(composite->tvbs, i);
789 member_tvb = slist->data;
793 g_assert(member_tvb);
795 if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
796 abs_length, &member_offset, &member_length, NULL)) {
799 * The range is, in fact, contiguous within member_tvb.
801 g_assert(!tvb->real_data);
802 return ensure_contiguous_no_exception(member_tvb, member_offset, member_length, NULL);
805 tvb->real_data = tvb_memdup(tvb, 0, -1);
806 return tvb->real_data + abs_offset;
809 g_assert_not_reached();
814 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
817 guint abs_offset, abs_length;
819 if (!check_offset_length_no_exception(tvb, offset, length,
820 &abs_offset, &abs_length, exception)) {
825 * We know that all the data is present in the tvbuff, so
826 * no exceptions should be thrown.
828 if (tvb->real_data) {
829 return tvb->real_data + abs_offset;
833 case TVBUFF_REAL_DATA:
834 g_assert_not_reached();
836 return ensure_contiguous_no_exception(tvb->tvbuffs.subset.tvb,
837 abs_offset - tvb->tvbuffs.subset.offset,
839 case TVBUFF_COMPOSITE:
840 return composite_ensure_contiguous_no_exception(tvb, abs_offset, abs_length);
844 g_assert_not_reached();
849 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length)
854 p = ensure_contiguous_no_exception(tvb, offset, length, &exception);
856 g_assert(exception > 0);
863 guint8_find(const guint8* haystack, size_t haystacklen, guint8 needle)
868 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
878 guint8_pbrk(const guint8* haystack, size_t haystacklen, guint8 *needles)
882 guint8 item, *needlep, needle;
884 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
887 while ((needle = *needlep) != '\0') {
899 /************** ACCESSORS **************/
902 composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, guint abs_length)
904 guint i, num_members;
905 tvb_comp_t *composite;
906 tvbuff_t *member_tvb = NULL;
907 guint member_offset, member_length;
911 g_assert(tvb->type == TVBUFF_COMPOSITE);
913 /* Maybe the range specified by offset/length
914 * is contiguous inside one of the member tvbuffs */
915 composite = &tvb->tvbuffs.composite;
916 num_members = g_slist_length(composite->tvbs);
918 for (i = 0; i < num_members; i++) {
919 if (abs_offset <= composite->end_offsets[i]) {
920 slist = g_slist_nth(composite->tvbs, i);
921 member_tvb = slist->data;
925 g_assert(member_tvb);
927 if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
928 abs_length, &member_offset, &member_length, NULL)) {
930 g_assert(!tvb->real_data);
931 return tvb_memcpy(member_tvb, target, member_offset, member_length);
934 /* The requested data is non-contiguous inside
935 * the member tvb. We have to memcpy() the part that's in the member tvb,
936 * then iterate across the other member tvb's, copying their portions
937 * until we have copied all data.
939 retval = compute_offset_length(member_tvb, abs_offset - composite->start_offsets[i], -1,
940 &member_offset, &member_length, NULL);
943 tvb_memcpy(member_tvb, target, member_offset, member_length);
944 abs_offset += member_length;
945 abs_length -= member_length;
948 if (abs_length > 0) {
949 composite_memcpy(tvb, target + member_length, abs_offset, abs_length);
955 g_assert_not_reached();
960 tvb_memcpy(tvbuff_t *tvb, guint8* target, gint offset, gint length)
962 guint abs_offset, abs_length;
964 g_assert(length >= -1);
965 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
967 if (tvb->real_data) {
968 return (guint8*) memcpy(target, tvb->real_data + abs_offset, abs_length);
972 case TVBUFF_REAL_DATA:
973 g_assert_not_reached();
976 return tvb_memcpy(tvb->tvbuffs.subset.tvb, target,
977 abs_offset - tvb->tvbuffs.subset.offset,
980 case TVBUFF_COMPOSITE:
981 return composite_memcpy(tvb, target, offset, length);
984 g_assert_not_reached();
990 * XXX - this doesn't treat a length of -1 as an error.
991 * If it did, this could replace some code that calls
992 * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
995 * "composite_ensure_contiguous_no_exception()" depends on -1 not being
996 * an error; does anything else depend on this routine treating -1 as
997 * meaning "to the end of the buffer"?
1000 tvb_memdup(tvbuff_t *tvb, gint offset, gint length)
1002 guint abs_offset, abs_length;
1005 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
1007 duped = g_malloc(abs_length);
1008 return tvb_memcpy(tvb, duped, abs_offset, abs_length);
1014 tvb_get_ptr(tvbuff_t *tvb, gint offset, gint length)
1016 return ensure_contiguous(tvb, offset, length);
1020 tvb_get_guint8(tvbuff_t *tvb, gint offset)
1024 ptr = ensure_contiguous(tvb, offset, sizeof(guint8));
1029 tvb_get_ntohs(tvbuff_t *tvb, gint offset)
1033 ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1038 tvb_get_ntoh24(tvbuff_t *tvb, gint offset)
1042 ptr = ensure_contiguous(tvb, offset, 3);
1043 return pntoh24(ptr);
1047 tvb_get_ntohl(tvbuff_t *tvb, gint offset)
1051 ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1056 tvb_get_ntoh64(tvbuff_t *tvb, gint offset)
1060 ptr = ensure_contiguous(tvb, offset, sizeof(guint64));
1061 return pntoh64(ptr);
1065 * Stuff for IEEE float handling on platforms that don't have IEEE
1066 * format as the native floating-point format.
1068 * For now, we treat only the VAX as such a platform.
1070 * XXX - other non-IEEE boxes that can run UNIX include some Crays,
1071 * and possibly other machines.
1073 * It appears that the official Linux port to System/390 and
1074 * zArchitecture uses IEEE format floating point (not a
1077 * I don't know whether there are any other machines that
1078 * could run Ethereal and that don't use IEEE format.
1079 * As far as I know, all of the main commercial microprocessor
1080 * families on which OSes that support Ethereal can run
1081 * use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
1082 * IA-64, and so on).
1092 #define IEEE_SP_NUMBER_WIDTH 32 /* bits in number */
1093 #define IEEE_SP_EXP_WIDTH 8 /* bits in exponent */
1094 #define IEEE_SP_MANTISSA_WIDTH 23 /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
1096 #define IEEE_SP_SIGN_MASK 0x80000000
1097 #define IEEE_SP_EXPONENT_MASK 0x7F800000
1098 #define IEEE_SP_MANTISSA_MASK 0x007FFFFF
1099 #define IEEE_SP_INFINITY IEEE_SP_EXPONENT_MASK
1101 #define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
1102 #define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
1103 #define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
1106 ieee_float_is_zero(guint32 w)
1108 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1112 get_ieee_float(guint32 w)
1118 sign = w & IEEE_SP_SIGN_MASK;
1119 exponent = w & IEEE_SP_EXPONENT_MASK;
1120 mantissa = w & IEEE_SP_MANTISSA_MASK;
1122 if (ieee_float_is_zero(w)) {
1123 /* number is zero, unnormalized, or not-a-number */
1128 * XXX - how to handle this?
1130 if (IEEE_SP_INFINITY == exponent) {
1132 * number is positive or negative infinity, or a special value
1134 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1138 exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1139 IEEE_SP_MANTISSA_WIDTH;
1140 mantissa |= IEEE_SP_IMPLIED_BIT;
1143 return -mantissa * pow(2, exponent);
1145 return mantissa * pow(2, exponent);
1150 * We assume that if you don't have IEEE floating-point, you have a
1151 * compiler that understands 64-bit integral quantities.
1153 #define IEEE_DP_NUMBER_WIDTH 64 /* bits in number */
1154 #define IEEE_DP_EXP_WIDTH 11 /* bits in exponent */
1155 #define IEEE_DP_MANTISSA_WIDTH 52 /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1157 #define IEEE_DP_SIGN_MASK 0x8000000000000000LL
1158 #define IEEE_DP_EXPONENT_MASK 0x7FF0000000000000LL
1159 #define IEEE_DP_MANTISSA_MASK 0x000FFFFFFFFFFFFFLL
1160 #define IEEE_DP_INFINITY IEEE_DP_EXPONENT_MASK
1162 #define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
1163 #define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1164 #define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1167 ieee_double_is_zero(guint64 w)
1169 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1173 get_ieee_double(guint64 w)
1179 sign = w & IEEE_DP_SIGN_MASK;
1180 exponent = w & IEEE_DP_EXPONENT_MASK;
1181 mantissa = w & IEEE_DP_MANTISSA_MASK;
1183 if (ieee_double_is_zero(w)) {
1184 /* number is zero, unnormalized, or not-a-number */
1189 * XXX - how to handle this?
1191 if (IEEE_DP_INFINITY == exponent) {
1193 * number is positive or negative infinity, or a special value
1195 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1199 exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1200 IEEE_DP_MANTISSA_WIDTH;
1201 mantissa |= IEEE_DP_IMPLIED_BIT;
1204 return -mantissa * pow(2, exponent);
1206 return mantissa * pow(2, exponent);
1211 * Fetches an IEEE single-precision floating-point number, in
1212 * big-endian form, and returns a "float".
1214 * XXX - should this be "double", in case there are IEEE single-
1215 * precision numbers that won't fit in some platform's native
1219 tvb_get_ntohieee_float(tvbuff_t *tvb, int offset)
1222 return get_ieee_float(tvb_get_ntohl(tvb, offset));
1229 ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1230 return ieee_fp_union.f;
1235 * Fetches an IEEE double-precision floating-point number, in
1236 * big-endian form, and returns a "double".
1239 tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
1253 #ifdef WORDS_BIGENDIAN
1254 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1255 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1257 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1258 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1261 return get_ieee_double(ieee_fp_union.dw);
1263 return ieee_fp_union.d;
1268 tvb_get_letohs(tvbuff_t *tvb, gint offset)
1272 ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1273 return pletohs(ptr);
1277 tvb_get_letoh24(tvbuff_t *tvb, gint offset)
1281 ptr = ensure_contiguous(tvb, offset, 3);
1282 return pletoh24(ptr);
1286 tvb_get_letohl(tvbuff_t *tvb, gint offset)
1290 ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1291 return pletohl(ptr);
1295 tvb_get_letoh64(tvbuff_t *tvb, gint offset)
1299 ptr = ensure_contiguous(tvb, offset, sizeof(guint64));
1300 return pletoh64(ptr);
1304 * Fetches an IEEE single-precision floating-point number, in
1305 * little-endian form, and returns a "float".
1307 * XXX - should this be "double", in case there are IEEE single-
1308 * precision numbers that won't fit in some platform's native
1312 tvb_get_letohieee_float(tvbuff_t *tvb, int offset)
1315 return get_ieee_float(tvb_get_letohl(tvb, offset));
1322 ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1323 return ieee_fp_union.f;
1328 * Fetches an IEEE double-precision floating-point number, in
1329 * little-endian form, and returns a "double".
1332 tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
1346 #ifdef WORDS_BIGENDIAN
1347 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1348 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1350 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1351 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1354 return get_ieee_double(ieee_fp_union.dw);
1356 return ieee_fp_union.d;
1360 /* Find first occurence of needle in tvbuff, starting at offset. Searches
1361 * at most maxlength number of bytes; if maxlength is -1, searches to
1363 * Returns the offset of the found needle, or -1 if not found.
1364 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1365 * in that case, -1 will be returned if the boundary is reached before
1366 * finding needle. */
1368 tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
1370 const guint8 *result;
1371 guint abs_offset, junk_length;
1375 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1377 /* Only search to end of tvbuff, w/o throwing exception. */
1378 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1379 if (maxlength == -1) {
1380 /* No maximum length specified; search to end of tvbuff. */
1383 else if (tvbufflen < (guint) maxlength) {
1384 /* Maximum length goes past end of tvbuff; search to end
1389 /* Maximum length doesn't go past end of tvbuff; search
1394 /* If we have real data, perform our search now. */
1395 if (tvb->real_data) {
1396 result = guint8_find(tvb->real_data + abs_offset, limit, needle);
1397 if (result == NULL) {
1401 return result - tvb->real_data;
1406 case TVBUFF_REAL_DATA:
1407 g_assert_not_reached();
1410 return tvb_find_guint8(tvb->tvbuffs.subset.tvb,
1411 abs_offset - tvb->tvbuffs.subset.offset,
1414 case TVBUFF_COMPOSITE:
1415 g_assert_not_reached();
1416 /* XXX - return composite_find_guint8(tvb, offset, limit, needle); */
1419 g_assert_not_reached();
1423 /* Find first occurence of any of the needles in tvbuff, starting at offset.
1424 * Searches at most maxlength number of bytes; if maxlength is -1, searches
1426 * Returns the offset of the found needle, or -1 if not found.
1427 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1428 * in that case, -1 will be returned if the boundary is reached before
1429 * finding needle. */
1431 tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 *needles)
1433 const guint8 *result;
1434 guint abs_offset, junk_length;
1438 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1440 /* Only search to end of tvbuff, w/o throwing exception. */
1441 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1442 if (maxlength == -1) {
1443 /* No maximum length specified; search to end of tvbuff. */
1446 else if (tvbufflen < (guint) maxlength) {
1447 /* Maximum length goes past end of tvbuff; search to end
1452 /* Maximum length doesn't go past end of tvbuff; search
1457 /* If we have real data, perform our search now. */
1458 if (tvb->real_data) {
1459 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles);
1460 if (result == NULL) {
1464 return result - tvb->real_data;
1469 case TVBUFF_REAL_DATA:
1470 g_assert_not_reached();
1473 return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
1474 abs_offset - tvb->tvbuffs.subset.offset,
1477 case TVBUFF_COMPOSITE:
1478 g_assert_not_reached();
1479 /* XXX - return composite_pbrk_guint8(tvb, offset, limit, needle); */
1482 g_assert_not_reached();
1486 /* Find size of stringz (NUL-terminated string) by looking for terminating
1487 * NUL. The size of the string includes the terminating NUL.
1489 * If the NUL isn't found, it throws the appropriate exception.
1492 tvb_strsize(tvbuff_t *tvb, gint offset)
1494 guint abs_offset, junk_length;
1497 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1498 nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
1499 if (nul_offset == -1) {
1501 * OK, we hit the end of the tvbuff, so we should throw
1504 * Did we hit the end of the captured data, or the end
1505 * of the actual data? If there's less captured data
1506 * than actual data, we presumably hit the end of the
1507 * captured data, otherwise we hit the end of the actual
1510 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
1513 THROW(ReportedBoundsError);
1516 return (nul_offset - abs_offset) + 1;
1519 /* Find length of string by looking for end of string ('\0'), up to
1520 * 'maxlength' characters'; if 'maxlength' is -1, searches to end
1522 * Returns -1 if 'maxlength' reached before finding EOS. */
1524 tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
1527 guint abs_offset, junk_length;
1529 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1531 result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
1533 if (result_offset == -1) {
1537 return result_offset - abs_offset;
1542 * Implement strneql etc
1546 * Call strncmp after checking if enough chars left, returning 0 if
1547 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1550 tvb_strneql(tvbuff_t *tvb, gint offset, const gchar *str, gint size)
1554 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1557 int cmp = strncmp((const char *)ptr, str, size);
1560 * Return 0 if equal, -1 otherwise.
1562 return (cmp == 0 ? 0 : -1);
1565 * Not enough characters in the tvbuff to match the
1573 * Call strncasecmp after checking if enough chars left, returning 0 if
1574 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1577 tvb_strncaseeql(tvbuff_t *tvb, gint offset, const gchar *str, gint size)
1581 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1584 int cmp = strncasecmp((const char *)ptr, str, size);
1587 * Return 0 if equal, -1 otherwise.
1589 return (cmp == 0 ? 0 : -1);
1592 * Not enough characters in the tvbuff to match the
1600 * Call memcmp after checking if enough chars left, returning 0 if
1601 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1604 tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1608 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1611 int cmp = memcmp(ptr, str, size);
1614 * Return 0 if equal, -1 otherwise.
1616 return (cmp == 0 ? 0 : -1);
1619 * Not enough characters in the tvbuff to match the
1626 /* Convert a string from Unicode to ASCII. At the moment we fake it by
1627 * replacing all non-ASCII characters with a '.' )-: The caller must
1628 * free the result returned. The len parameter is the number of guint16's
1629 * to convert from Unicode. */
1631 tvb_fake_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
1637 /* Make sure we have enough data before allocating the buffer,
1638 so we don't blow up if the length is huge. */
1639 tvb_ensure_bytes_exist(tvb, offset, 2*len);
1641 /* We know we won't throw an exception, so we don't have to worry
1642 about leaking this buffer. */
1643 buffer = g_malloc(len + 1);
1645 for (i = 0; i < len; i++) {
1646 character = little_endian ? tvb_get_letohs(tvb, offset)
1647 : tvb_get_ntohs(tvb, offset);
1648 buffer[i] = character < 256 ? character : '.';
1658 * Format the data in the tvb from offset for length ...
1662 tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
1667 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
1669 len = tvb_length_remaining(tvb, offset);
1670 ptr = ensure_contiguous(tvb, offset, len);
1674 return format_text(ptr, len);
1679 * Like "tvb_format_text()", but for null-padded strings; don't show
1680 * the null padding characters as "\000".
1683 tvb_format_stringzpad(tvbuff_t *tvb, gint offset, gint size)
1685 const guint8 *ptr, *p;
1689 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
1691 len = tvb_length_remaining(tvb, offset);
1692 ptr = ensure_contiguous(tvb, offset, len);
1696 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
1698 return format_text(ptr, stringlen);
1703 * Given a tvbuff, an offset, and a length, allocate a buffer big enough
1704 * to hold a non-null-terminated string of that length at that offset,
1705 * plus a trailing '\0', copy the string into it, and return a pointer
1708 * Throws an exception if the tvbuff ends before the string does.
1711 tvb_get_string(tvbuff_t *tvb, gint offset, gint length)
1714 guint8 *strbuf = NULL;
1717 THROW(DissectorError);
1719 ptr = ensure_contiguous(tvb, offset, length);
1720 strbuf = g_malloc(length + 1);
1722 memcpy(strbuf, ptr, length);
1724 strbuf[length] = '\0';
1729 * Given a tvbuff and an offset, with the offset assumed to refer to
1730 * a null-terminated string, find the length of that string (and throw
1731 * an exception if the tvbuff ends before we find the null), allocate
1732 * a buffer big enough to hold the string, copy the string into it,
1733 * and return a pointer to the string. Also return the length of the
1734 * string (including the terminating null) through a pointer.
1737 tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
1742 size = tvb_strsize(tvb, offset);
1743 strptr = g_malloc(size);
1744 tvb_memcpy(tvb, strptr, offset, size);
1749 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1750 * no more than bufsize number of bytes, including terminating NUL, to buffer.
1751 * Returns length of string (not including terminating NUL), or -1 if the string was
1752 * truncated in the buffer due to not having reached the terminating NUL.
1753 * In this way, it acts like snprintf().
1755 * bufsize MUST be greater than 0.
1757 * When processing a packet where the remaining number of bytes is less
1758 * than bufsize, an exception is not thrown if the end of the packet
1759 * is reached before the NUL is found. If no NUL is found before reaching
1760 * the end of the short packet, -1 is still returned, and the string
1761 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1762 * at the correct spot, terminating the string.
1764 * *bytes_copied will contain the number of bytes actually copied,
1765 * including the terminating-NUL.
1768 _tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer,
1772 guint abs_offset, junk_length;
1774 gboolean decreased_max = FALSE;
1776 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1778 /* There must at least be room for the terminating NUL. */
1779 g_assert(bufsize != 0);
1781 /* If there's no room for anything else, just return the NUL. */
1788 /* Only read to end of tvbuff, w/o throwing exception. */
1789 len = tvb_length_remaining(tvb, abs_offset);
1791 /* check_offset_length() won't throw an exception if we're
1792 * looking at the byte immediately after the end of the tvbuff. */
1794 THROW(ReportedBoundsError);
1797 /* This should not happen because check_offset_length() would
1798 * have already thrown an exception if 'offset' were out-of-bounds.
1800 g_assert(len != -1);
1803 * If we've been passed a negative number, bufsize will
1806 g_assert(bufsize <= G_MAXINT);
1808 if ((guint)len < bufsize) {
1810 decreased_max = TRUE;
1816 stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
1817 /* If NUL wasn't found, copy the data and return -1 */
1818 if (stringlen == -1) {
1819 tvb_memcpy(tvb, buffer, abs_offset, limit);
1820 if (decreased_max) {
1822 /* Add 1 for the extra NUL that we set at buffer[limit],
1823 * pretending that it was copied as part of the string. */
1824 *bytes_copied = limit + 1;
1827 *bytes_copied = limit;
1832 /* Copy the string to buffer */
1833 tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
1834 *bytes_copied = stringlen + 1;
1838 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1839 * no more than bufsize number of bytes, including terminating NUL, to buffer.
1840 * Returns length of string (not including terminating NUL), or -1 if the string was
1841 * truncated in the buffer due to not having reached the terminating NUL.
1842 * In this way, it acts like snprintf().
1844 * When processing a packet where the remaining number of bytes is less
1845 * than bufsize, an exception is not thrown if the end of the packet
1846 * is reached before the NUL is found. If no NUL is found before reaching
1847 * the end of the short packet, -1 is still returned, and the string
1848 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1849 * at the correct spot, terminating the string.
1852 tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1856 return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1859 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
1860 * have a terminating NUL. If the string was truncated when copied into buffer,
1861 * a NUL is placed at the end of buffer to terminate it.
1864 tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1866 gint len, bytes_copied;
1868 len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1871 buffer[bufsize - 1] = 0;
1872 return bytes_copied - 1;
1880 * Given a tvbuff, an offset into the tvbuff, and a length that starts
1881 * at that offset (which may be -1 for "all the way to the end of the
1882 * tvbuff"), find the end of the (putative) line that starts at the
1883 * specified offset in the tvbuff, going no further than the specified
1886 * Return the length of the line (not counting the line terminator at
1887 * the end), or, if we don't find a line terminator:
1889 * if "deseg" is true, return -1;
1891 * if "deseg" is false, return the amount of data remaining in
1894 * Set "*next_offset" to the offset of the character past the line
1895 * terminator, or past the end of the buffer if we don't find a line
1896 * terminator. (It's not set if we return -1.)
1899 tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
1907 len = tvb_length_remaining(tvb, offset);
1909 * XXX - what if "len" is still -1, meaning "offset is past the
1910 * end of the tvbuff"?
1912 eob_offset = offset + len;
1915 * Look either for a CR or an LF.
1917 eol_offset = tvb_pbrk_guint8(tvb, offset, len, (guint8 *)"\r\n");
1918 if (eol_offset == -1) {
1920 * No CR or LF - line is presumably continued in next packet.
1924 * Tell our caller we saw no EOL, so they can
1925 * try to desegment and get the entire line
1931 * Pretend the line runs to the end of the tvbuff.
1933 linelen = eob_offset - offset;
1934 *next_offset = eob_offset;
1938 * Find the number of bytes between the starting offset
1941 linelen = eol_offset - offset;
1946 if (tvb_get_guint8(tvb, eol_offset) == '\r') {
1948 * Yes - is it followed by an LF?
1950 if (eol_offset + 1 >= eob_offset) {
1952 * Dunno - the next byte isn't in this
1957 * We'll return -1, although that
1958 * runs the risk that if the line
1959 * really *is* terminated with a CR,
1960 * we won't properly dissect this
1963 * It's probably more likely that
1964 * the line ends with CR-LF than
1965 * that it ends with CR by itself.
1971 * Well, we can at least look at the next
1974 if (tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
1976 * It's an LF; skip over the CR.
1984 * Return the offset of the character after the last
1985 * character in the line, skipping over the last character
1986 * in the line terminator.
1988 *next_offset = eol_offset + 1;
1994 * Given a tvbuff, an offset into the tvbuff, and a length that starts
1995 * at that offset (which may be -1 for "all the way to the end of the
1996 * tvbuff"), find the end of the (putative) line that starts at the
1997 * specified offset in the tvbuff, going no further than the specified
2000 * However, treat quoted strings inside the buffer specially - don't
2001 * treat newlines in quoted strings as line terminators.
2003 * Return the length of the line (not counting the line terminator at
2004 * the end), or the amount of data remaining in the buffer if we don't
2005 * find a line terminator.
2007 * Set "*next_offset" to the offset of the character past the line
2008 * terminator, or past the end of the buffer if we don't find a line
2012 tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
2015 gint cur_offset, char_offset;
2022 len = tvb_length_remaining(tvb, offset);
2024 * XXX - what if "len" is still -1, meaning "offset is past the
2025 * end of the tvbuff"?
2027 eob_offset = offset + len;
2029 cur_offset = offset;
2033 * Is this part of the string quoted?
2037 * Yes - look only for the terminating quote.
2039 char_offset = tvb_find_guint8(tvb, cur_offset, len,
2043 * Look either for a CR, an LF, or a '"'.
2045 char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
2046 (guint8 *)"\r\n\"");
2048 if (char_offset == -1) {
2050 * Not found - line is presumably continued in
2052 * We pretend the line runs to the end of the tvbuff.
2054 linelen = eob_offset - offset;
2055 *next_offset = eob_offset;
2061 * We're processing a quoted string.
2062 * We only looked for ", so we know it's a ";
2063 * as we're processing a quoted string, it's a
2071 c = tvb_get_guint8(tvb, char_offset);
2074 * Un-quoted "; it begins a quoted
2080 * It's a CR or LF; we've found a line
2083 * Find the number of bytes between the
2084 * starting offset and the CR or LF.
2086 linelen = char_offset - offset;
2093 * Yes; is it followed by an LF?
2095 if (char_offset + 1 < eob_offset &&
2096 tvb_get_guint8(tvb, char_offset + 1)
2099 * Yes; skip over the CR.
2106 * Return the offset of the character after
2107 * the last character in the line, skipping
2108 * over the last character in the line
2109 * terminator, and quit.
2111 *next_offset = char_offset + 1;
2117 * Step past the character we found.
2119 cur_offset = char_offset + 1;
2120 if (cur_offset >= eob_offset) {
2122 * The character we found was the last character
2123 * in the tvbuff - line is presumably continued in
2125 * We pretend the line runs to the end of the tvbuff.
2127 linelen = eob_offset - offset;
2128 *next_offset = eob_offset;
2136 * Format a bunch of data from a tvbuff as bytes, returning a pointer
2137 * to the string with the formatted data, with "punct" as a byte
2141 tvb_bytes_to_str_punct(tvbuff_t *tvb, gint offset, gint len, gchar punct)
2143 return bytes_to_str_punct(tvb_get_ptr(tvb, offset, len), len, punct);
2147 * Format a bunch of data from a tvbuff as bytes, returning a pointer
2148 * to the string with the formatted data.
2151 tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len)
2153 return bytes_to_str(tvb_get_ptr(tvb, offset, len), len);
2156 /* Find a needle tvbuff within a haystack tvbuff. */
2158 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
2160 guint haystack_abs_offset, haystack_abs_length;
2161 const guint8 *haystack_data;
2162 const guint8 *needle_data;
2163 const guint needle_len = needle_tvb->length;
2164 const guint8 *location;
2166 if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
2170 /* Get pointers to the tvbuffs' data. */
2171 haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
2172 needle_data = tvb_get_ptr(needle_tvb, 0, -1);
2174 check_offset_length(haystack_tvb, haystack_offset, -1,
2175 &haystack_abs_offset, &haystack_abs_length);
2177 location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
2178 needle_data, needle_len);
2181 return location - haystack_data;
2192 * Uncompresses a zlib compressed packet inside a message of tvb at offset with
2193 * length comprlen. Returns an uncompressed tvbuffer if uncompression
2194 * succeeded or NULL if uncompression failed.
2196 #define TVB_Z_MIN_BUFSIZ 32768
2197 #define TVB_Z_MAX_BUFSIZ 1048576 * 10
2198 /* #define TVB_Z_DEBUG 1 */
2202 tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
2207 guint bytes_out = 0;
2208 guint8 *compr = NULL;
2209 guint8 *uncompr = NULL;
2210 tvbuff_t *uncompr_tvb = NULL;
2211 z_streamp strm = NULL;
2212 Bytef *strmbuf = NULL;
2213 guint inits_done = 0;
2214 gint wbits = MAX_WBITS;
2215 guint8 *next = NULL;
2216 guint bufsiz = TVB_Z_MIN_BUFSIZ;
2218 guint inflate_passes = 0;
2219 guint bytes_in = tvb_length_remaining(tvb, offset);
2226 strm = g_malloc0(sizeof(z_stream));
2232 compr = tvb_memdup(tvb, offset, comprlen);
2240 * Assume that the uncompressed data is at least twice as big as
2241 * the compressed size.
2243 bufsiz = tvb_length_remaining(tvb, offset) * 2;
2245 if (bufsiz < TVB_Z_MIN_BUFSIZ) {
2246 bufsiz = TVB_Z_MIN_BUFSIZ;
2247 } else if (bufsiz > TVB_Z_MAX_BUFSIZ) {
2248 bufsiz = TVB_Z_MIN_BUFSIZ;
2252 printf("bufsiz: %u bytes\n", bufsiz);
2257 strm->next_in = next;
2258 strm->avail_in = comprlen;
2261 strmbuf = g_malloc0(bufsiz);
2263 if(strmbuf == NULL) {
2269 strm->next_out = strmbuf;
2270 strm->avail_out = bufsiz;
2272 err = inflateInit2(strm, wbits);
2282 memset(strmbuf, '\0', bufsiz);
2283 strm->next_out = strmbuf;
2284 strm->avail_out = bufsiz;
2286 err = inflate(strm, Z_SYNC_FLUSH);
2288 if (err == Z_OK || err == Z_STREAM_END) {
2289 guint bytes_pass = bufsiz - strm->avail_out;
2295 if (uncompr == NULL) {
2296 uncompr = g_memdup(strmbuf, bytes_pass);
2298 guint8 *new_data = g_malloc0(bytes_out +
2301 if (new_data == NULL) {
2306 if (uncompr != NULL) {
2313 g_memmove(new_data, uncompr, bytes_out);
2314 g_memmove((new_data + bytes_out), strmbuf,
2321 bytes_out += bytes_pass;
2323 if ( err == Z_STREAM_END) {
2329 } else if (err == Z_BUF_ERROR) {
2331 * It's possible that not enough frames were captured
2332 * to decompress this fully, so return what we've done
2339 if (uncompr != NULL) {
2346 } else if (err == Z_DATA_ERROR && inits_done == 1
2347 && uncompr == NULL && (*compr == 0x1f) &&
2348 (*(compr + 1) == 0x8b)) {
2350 * inflate() is supposed to handle both gzip and deflate
2351 * streams automatically, but in reality it doesn't
2352 * seem to handle either (at least not within the
2353 * context of an HTTP response.) We have to try
2354 * several tweaks, depending on the type of data and
2355 * version of the library installed.
2359 * Gzip file format. Skip past the header, since the
2360 * fix to make it work (setting windowBits to 31)
2361 * doesn't work with all versions of the library.
2363 Bytef *c = compr + 2;
2366 if (*c == Z_DEFLATED) {
2377 /* Skip past the MTIME, XFL, and OS fields. */
2380 if (flags & (1 << 2)) {
2381 /* An Extra field is present. */
2382 gint xsize = (gint)(*c |
2388 if (flags & (1 << 3)) {
2389 /* A null terminated filename */
2391 while (*c != '\0') {
2398 if (flags & (1 << 4)) {
2399 /* A null terminated comment */
2401 while (*c != '\0') {
2411 strm->next_in = next;
2412 comprlen -= (c - compr);
2414 err = inflateInit2(strm, wbits);
2416 } else if (err == Z_DATA_ERROR && uncompr == NULL &&
2420 * Re-init the stream with a negative
2421 * MAX_WBITS. This is necessary due to
2422 * some servers (Apache) not sending
2423 * the deflate header with the
2424 * content-encoded response.
2430 strm->next_in = next;
2431 strm->avail_in = comprlen;
2433 memset(strmbuf, '\0', bufsiz);
2434 strm->next_out = strmbuf;
2435 strm->avail_out = bufsiz;
2437 err = inflateInit2(strm, wbits);
2454 if (uncompr == NULL) {
2463 printf("inflate() total passes: %u\n", inflate_passes);
2464 printf("bytes in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
2467 if (uncompr != NULL) {
2468 uncompr_tvb = tvb_new_real_data((guint8*) uncompr, bytes_out,
2470 tvb_set_free_cb(uncompr_tvb, g_free);
2477 tvb_uncompress(tvbuff_t *tvb _U_, int offset _U_, int comprlen _U_)