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
12 * $Id: tvbuff.c,v 1.49 2003/08/27 15:23:02 gram Exp $
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.
49 /* The backing tvbuff_t */
52 /* The offset/length of 'tvb' to which I'm privy */
61 /* Used for quick testing to see if this
62 * is the tvbuff that a COMPOSITE is
74 tvbuff_t* ds_tvb; /* data source top-level tvbuff */
76 /* The tvbuffs in which this tvbuff is a member
77 * (that is, a backing tvbuff for a TVBUFF_SUBSET
78 * or a member for a TVB_COMPOSITE) */
81 /* TVBUFF_SUBSET and TVBUFF_COMPOSITE keep track
82 * of the other tvbuff's they use */
88 /* We're either a TVBUFF_REAL_DATA or a
89 * TVBUFF_SUBSET that has a backing buffer that
90 * has real_data != NULL, or a TVBUFF_COMPOSITE
91 * which has flattened its data due to a call
96 /* Length of virtual buffer (and/or real_data). */
99 /* Reported length. */
100 guint reported_length;
102 /* Offset from beginning of first TVBUFF_REAL. */
105 /* Func to call when actually freed */
106 tvbuff_free_cb_t free_cb;
110 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
114 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length);
116 /* We dole out tvbuff's from this memchunk. */
117 GMemChunk *tvbuff_mem_chunk = NULL;
122 if (!tvbuff_mem_chunk)
123 tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
129 if (tvbuff_mem_chunk)
130 g_mem_chunk_destroy(tvbuff_mem_chunk);
132 tvbuff_mem_chunk = NULL;
139 tvb_init(tvbuff_t *tvb, tvbuff_type type)
141 tvb_backing_t *backing;
142 tvb_comp_t *composite;
145 tvb->initialized = FALSE;
146 tvb->usage_count = 1;
148 tvb->reported_length = 0;
150 tvb->real_data = NULL;
151 tvb->raw_offset = -1;
156 case TVBUFF_REAL_DATA:
161 backing = &tvb->tvbuffs.subset;
167 case TVBUFF_COMPOSITE:
168 composite = &tvb->tvbuffs.composite;
169 composite->tvbs = NULL;
170 composite->start_offsets = NULL;
171 composite->end_offsets = NULL;
178 tvb_new(tvbuff_type type)
182 tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
190 /* We accept a void* instead of a field_info* to satisfy CLEANUP_POP */
192 tvb_free_void(void *tvb)
194 tvb_free((tvbuff_t*)tvb);
200 tvb_free(tvbuff_t* tvb)
202 tvbuff_t *member_tvb;
203 tvb_comp_t *composite;
208 if (tvb->usage_count == 0) {
210 case TVBUFF_REAL_DATA:
212 tvb->free_cb(tvb->real_data);
217 /* This will be NULL if tvb_new_subset() fails because
218 * reported_length < -1 */
219 if (tvb->tvbuffs.subset.tvb) {
220 tvb_decrement_usage_count(tvb->tvbuffs.subset.tvb, 1);
224 case TVBUFF_COMPOSITE:
225 composite = &tvb->tvbuffs.composite;
226 for (slist = composite->tvbs; slist != NULL ; slist = slist->next) {
227 member_tvb = slist->data;
228 tvb_decrement_usage_count(member_tvb, 1);
231 g_slist_free(composite->tvbs);
233 if (composite->start_offsets)
234 g_free(composite->start_offsets);
235 if (composite->end_offsets)
236 g_free(composite->end_offsets);
238 g_free(tvb->real_data);
244 g_slist_free(tvb->used_in);
247 g_chunk_free(tvb, tvbuff_mem_chunk);
252 tvb_increment_usage_count(tvbuff_t* tvb, guint count)
254 tvb->usage_count += count;
256 return tvb->usage_count;
260 tvb_decrement_usage_count(tvbuff_t* tvb, guint count)
262 if (tvb->usage_count <= count) {
263 tvb->usage_count = 1;
268 tvb->usage_count -= count;
269 return tvb->usage_count;
275 tvb_free_chain(tvbuff_t* tvb)
279 /* Recursively call tvb_free_chain() */
280 for (slist = tvb->used_in; slist != NULL ; slist = slist->next) {
281 tvb_free_chain( (tvbuff_t*)slist->data );
284 /* Stop the recursion */
291 tvb_set_free_cb(tvbuff_t* tvb, tvbuff_free_cb_t func)
293 g_assert(tvb->type == TVBUFF_REAL_DATA);
298 add_to_used_in_list(tvbuff_t *tvb, tvbuff_t *used_in)
300 tvb->used_in = g_slist_prepend(tvb->used_in, used_in);
301 tvb_increment_usage_count(tvb, 1);
305 tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child)
307 g_assert(parent->initialized);
308 g_assert(child->initialized);
309 g_assert(child->type == TVBUFF_REAL_DATA);
310 add_to_used_in_list(parent, child);
314 tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
316 g_assert(tvb->type == TVBUFF_REAL_DATA);
317 g_assert(!tvb->initialized);
319 if (reported_length < -1) {
320 THROW(ReportedBoundsError);
323 tvb->real_data = (gpointer) data;
324 tvb->length = length;
325 tvb->reported_length = reported_length;
326 tvb->initialized = TRUE;
330 tvb_new_real_data(const guint8* data, guint length, gint reported_length)
334 tvb = tvb_new(TVBUFF_REAL_DATA);
336 CLEANUP_PUSH(tvb_free_void, tvb);
338 tvb_set_real_data(tvb, data, length, reported_length);
341 * This is the top-level real tvbuff for this data source,
342 * so its data source tvbuff is itself.
351 /* Computes the absolute offset and length based on a possibly-negative offset
352 * and a length that is possible -1 (which means "to the end of the data").
353 * Returns TRUE/FALSE indicating whether the offset is in bounds or
354 * not. The integer ptrs are modified with the new offset and length.
355 * No exception is thrown.
357 * XXX - we return TRUE, not FALSE, if the offset is positive and right
358 * after the end of the tvbuff (i.e., equal to the length). We do this
359 * so that a dissector constructing a subset tvbuff for the next protocol
360 * will get a zero-length tvbuff, not an exception, if there's no data
361 * left for the next protocol - we want the next protocol to be the one
362 * that gets an exception, so the error is reported as an error in that
363 * protocol rather than the containing protocol. */
365 compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
366 guint *offset_ptr, guint *length_ptr, int *exception)
368 g_assert(offset_ptr);
369 g_assert(length_ptr);
371 /* Compute the offset */
373 /* Positive offset - relative to the beginning of the packet. */
374 if ((guint) offset > tvb->reported_length) {
376 *exception = ReportedBoundsError;
380 else if ((guint) offset > tvb->length) {
382 *exception = BoundsError;
387 *offset_ptr = offset;
391 /* Negative offset - relative to the end of the packet. */
392 if ((guint) -offset > tvb->reported_length) {
394 *exception = ReportedBoundsError;
398 else if ((guint) -offset > tvb->length) {
400 *exception = BoundsError;
405 *offset_ptr = tvb->length + offset;
409 /* Compute the length */
413 else if (length == -1) {
414 *length_ptr = tvb->length - *offset_ptr;
417 *length_ptr = length;
425 check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
426 guint *offset_ptr, guint *length_ptr, int *exception)
430 g_assert(tvb->initialized);
432 if (!compute_offset_length(tvb, offset, length, offset_ptr, length_ptr, exception)) {
437 * Compute the offset of the first byte past the length.
439 end_offset = *offset_ptr + *length_ptr;
442 * Check for an overflow, and clamp "end_offset" at the maximum
443 * if we got an overflow - that should force us to indicate that
444 * we're past the end of the tvbuff.
446 if (end_offset < *offset_ptr)
447 end_offset = UINT_MAX;
450 * Check whether that offset goes more than one byte past the
453 * If not, return TRUE; otherwise, return FALSE and, if "exception"
454 * is non-null, return the appropriate exception through it.
456 if (end_offset <= tvb->length) {
459 else if (end_offset <= tvb->reported_length) {
461 *exception = BoundsError;
467 *exception = ReportedBoundsError;
472 g_assert_not_reached();
475 /* Checks (+/-) offset and length and throws an exception if
476 * either is out of bounds. Sets integer ptrs to the new offset
479 check_offset_length(tvbuff_t *tvb, gint offset, gint length,
480 guint *offset_ptr, guint *length_ptr)
488 if (!check_offset_length_no_exception(tvb, offset, length, offset_ptr, length_ptr, &exception)) {
489 g_assert(exception > 0);
497 tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
498 gint backing_offset, gint backing_length, gint reported_length)
500 g_assert(tvb->type == TVBUFF_SUBSET);
501 g_assert(!tvb->initialized);
503 if (reported_length < -1) {
504 THROW(ReportedBoundsError);
507 check_offset_length(backing, backing_offset, backing_length,
508 &tvb->tvbuffs.subset.offset,
509 &tvb->tvbuffs.subset.length);
511 tvb->tvbuffs.subset.tvb = backing;
512 tvb->length = tvb->tvbuffs.subset.length;
514 if (reported_length == -1) {
515 tvb->reported_length = backing->reported_length - tvb->tvbuffs.subset.offset;
518 tvb->reported_length = reported_length;
520 tvb->initialized = TRUE;
521 add_to_used_in_list(backing, tvb);
523 /* Optimization. If the backing buffer has a pointer to contiguous, real data,
524 * then we can point directly to our starting offset in that buffer */
525 if (backing->real_data != NULL) {
526 tvb->real_data = backing->real_data + tvb->tvbuffs.subset.offset;
532 tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint reported_length)
536 tvb = tvb_new(TVBUFF_SUBSET);
538 CLEANUP_PUSH(tvb_free_void, tvb);
540 tvb_set_subset(tvb, backing, backing_offset, backing_length, reported_length);
543 * The top-level data source of this tvbuff is the top-level
544 * data source of its parent.
546 tvb->ds_tvb = backing->ds_tvb;
554 tvb_composite_append(tvbuff_t* tvb, tvbuff_t* member)
556 tvb_comp_t *composite;
558 g_assert(!tvb->initialized);
559 composite = &tvb->tvbuffs.composite;
560 composite->tvbs = g_slist_append( composite->tvbs, member );
561 add_to_used_in_list(member, tvb);
565 tvb_composite_prepend(tvbuff_t* tvb, tvbuff_t* member)
567 tvb_comp_t *composite;
569 g_assert(!tvb->initialized);
570 composite = &tvb->tvbuffs.composite;
571 composite->tvbs = g_slist_prepend( composite->tvbs, member );
572 add_to_used_in_list(member, tvb);
576 tvb_new_composite(void)
578 return tvb_new(TVBUFF_COMPOSITE);
582 tvb_composite_finalize(tvbuff_t* tvb)
586 tvbuff_t *member_tvb;
587 tvb_comp_t *composite;
590 g_assert(!tvb->initialized);
591 g_assert(tvb->length == 0);
593 composite = &tvb->tvbuffs.composite;
594 num_members = g_slist_length(composite->tvbs);
596 composite->start_offsets = g_new(guint, num_members);
597 composite->end_offsets = g_new(guint, num_members);
599 for (slist = composite->tvbs; slist != NULL; slist = slist->next) {
600 g_assert((guint) i < num_members);
601 member_tvb = slist->data;
602 composite->start_offsets[i] = tvb->length;
603 tvb->length += member_tvb->length;
604 composite->end_offsets[i] = tvb->length - 1;
608 tvb->initialized = TRUE;
614 tvb_length(tvbuff_t* tvb)
616 g_assert(tvb->initialized);
622 tvb_length_remaining(tvbuff_t *tvb, gint offset)
624 guint abs_offset, abs_length;
626 g_assert(tvb->initialized);
628 if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
637 tvb_ensure_length_remaining(tvbuff_t *tvb, gint offset)
639 guint abs_offset, abs_length;
642 g_assert(tvb->initialized);
644 if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, &exception)) {
653 /* Validates that 'length' bytes are available starting from
654 * offset (pos/neg). Does not throw an exception. */
656 tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
658 guint abs_offset, abs_length;
660 g_assert(tvb->initialized);
662 if (!compute_offset_length(tvb, offset, length, &abs_offset, &abs_length, NULL))
665 if (abs_offset + abs_length <= tvb->length) {
673 /* Validates that 'length' bytes are available starting from
674 * offset (pos/neg). Throws an exception if they aren't. */
676 tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
678 guint abs_offset, abs_length;
680 g_assert(tvb->initialized);
683 * -1 doesn't mean "until end of buffer", as that's pointless
684 * for this routine. We must treat it as a Really Large Positive
685 * Number, so that we throw an exception; we throw
686 * ReportedBoundsError, as if it were past even the end of a
687 * reassembled packet, and past the end of even the data we
690 * We do the same with other negative lengths.
693 THROW(ReportedBoundsError);
695 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
699 tvb_offset_exists(tvbuff_t *tvb, gint offset)
701 guint abs_offset, abs_length;
703 g_assert(tvb->initialized);
704 if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL))
707 if (abs_offset < tvb->length) {
716 tvb_reported_length(tvbuff_t* tvb)
718 g_assert(tvb->initialized);
720 return tvb->reported_length;
724 tvb_reported_length_remaining(tvbuff_t *tvb, gint offset)
726 guint abs_offset, abs_length;
728 g_assert(tvb->initialized);
730 if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
731 if (tvb->reported_length >= abs_offset)
732 return tvb->reported_length - abs_offset;
741 /* Set the reported length of a tvbuff to a given value; used for protocols
742 whose headers contain an explicit length and where the calling
743 dissector's payload may include padding as well as the packet for
746 Also adjusts the data length. */
748 tvb_set_reported_length(tvbuff_t* tvb, guint reported_length)
750 g_assert(tvb->initialized);
752 if (reported_length > tvb->reported_length)
753 THROW(ReportedBoundsError);
755 tvb->reported_length = reported_length;
756 if (reported_length < tvb->length)
757 tvb->length = reported_length;
762 first_real_data_ptr(tvbuff_t *tvb)
767 case TVBUFF_REAL_DATA:
768 return tvb->real_data;
770 member = tvb->tvbuffs.subset.tvb;
771 return first_real_data_ptr(member);
772 case TVBUFF_COMPOSITE:
773 member = tvb->tvbuffs.composite.tvbs->data;
774 return first_real_data_ptr(member);
777 g_assert_not_reached();
782 offset_from_real_beginning(tvbuff_t *tvb, int counter)
787 case TVBUFF_REAL_DATA:
790 member = tvb->tvbuffs.subset.tvb;
791 return offset_from_real_beginning(member, counter + tvb->tvbuffs.subset.offset);
792 case TVBUFF_COMPOSITE:
793 member = tvb->tvbuffs.composite.tvbs->data;
794 return offset_from_real_beginning(member, counter);
797 g_assert_not_reached();
802 tvb_raw_offset(tvbuff_t *tvb)
804 if (tvb->raw_offset == -1) {
805 tvb->raw_offset = offset_from_real_beginning(tvb, 0);
807 return tvb->raw_offset;
811 composite_ensure_contiguous_no_exception(tvbuff_t *tvb, guint abs_offset,
814 guint i, num_members;
815 tvb_comp_t *composite;
816 tvbuff_t *member_tvb = NULL;
817 guint member_offset, member_length;
820 g_assert(tvb->type == TVBUFF_COMPOSITE);
822 /* Maybe the range specified by offset/length
823 * is contiguous inside one of the member tvbuffs */
824 composite = &tvb->tvbuffs.composite;
825 num_members = g_slist_length(composite->tvbs);
827 for (i = 0; i < num_members; i++) {
828 if (abs_offset <= composite->end_offsets[i]) {
829 slist = g_slist_nth(composite->tvbs, i);
830 member_tvb = slist->data;
834 g_assert(member_tvb);
836 if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
837 abs_length, &member_offset, &member_length, NULL)) {
840 * The range is, in fact, contiguous within member_tvb.
842 g_assert(!tvb->real_data);
843 return ensure_contiguous_no_exception(member_tvb, member_offset, member_length, NULL);
846 tvb->real_data = tvb_memdup(tvb, 0, -1);
847 return tvb->real_data + abs_offset;
850 g_assert_not_reached();
855 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
858 guint abs_offset, abs_length;
860 if (!check_offset_length_no_exception(tvb, offset, length,
861 &abs_offset, &abs_length, exception)) {
866 * We know that all the data is present in the tvbuff, so
867 * no exceptions should be thrown.
869 if (tvb->real_data) {
870 return tvb->real_data + abs_offset;
874 case TVBUFF_REAL_DATA:
875 g_assert_not_reached();
877 return ensure_contiguous_no_exception(tvb->tvbuffs.subset.tvb,
878 abs_offset - tvb->tvbuffs.subset.offset,
880 case TVBUFF_COMPOSITE:
881 return composite_ensure_contiguous_no_exception(tvb, abs_offset, abs_length);
885 g_assert_not_reached();
890 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length)
895 p = ensure_contiguous_no_exception(tvb, offset, length, &exception);
897 g_assert(exception > 0);
904 guint8_find(const guint8* haystack, size_t haystacklen, guint8 needle)
909 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
919 guint8_pbrk(const guint8* haystack, size_t haystacklen, guint8 *needles)
923 guint8 item, *needlep, needle;
925 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
928 while ((needle = *needlep) != '\0') {
940 /************** ACCESSORS **************/
943 composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, guint abs_length)
945 guint i, num_members;
946 tvb_comp_t *composite;
947 tvbuff_t *member_tvb = NULL;
948 guint member_offset, member_length;
952 g_assert(tvb->type == TVBUFF_COMPOSITE);
954 /* Maybe the range specified by offset/length
955 * is contiguous inside one of the member tvbuffs */
956 composite = &tvb->tvbuffs.composite;
957 num_members = g_slist_length(composite->tvbs);
959 for (i = 0; i < num_members; i++) {
960 if (abs_offset <= composite->end_offsets[i]) {
961 slist = g_slist_nth(composite->tvbs, i);
962 member_tvb = slist->data;
966 g_assert(member_tvb);
968 if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
969 abs_length, &member_offset, &member_length, NULL)) {
971 g_assert(!tvb->real_data);
972 return tvb_memcpy(member_tvb, target, member_offset, member_length);
975 /* The requested data is non-contiguous inside
976 * the member tvb. We have to memcpy() the part that's in the member tvb,
977 * then iterate across the other member tvb's, copying their portions
978 * until we have copied all data.
980 retval = compute_offset_length(member_tvb, abs_offset - composite->start_offsets[i], -1,
981 &member_offset, &member_length, NULL);
984 tvb_memcpy(member_tvb, target, member_offset, member_length);
985 abs_offset += member_length;
986 abs_length -= member_length;
989 if (abs_length > 0) {
990 composite_memcpy(tvb, target + member_length, abs_offset, abs_length);
996 g_assert_not_reached();
1001 tvb_memcpy(tvbuff_t *tvb, guint8* target, gint offset, gint length)
1003 guint abs_offset, abs_length;
1005 g_assert(length >= -1);
1006 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
1008 if (tvb->real_data) {
1009 return (guint8*) memcpy(target, tvb->real_data + abs_offset, abs_length);
1013 case TVBUFF_REAL_DATA:
1014 g_assert_not_reached();
1017 return tvb_memcpy(tvb->tvbuffs.subset.tvb, target,
1018 abs_offset - tvb->tvbuffs.subset.offset,
1021 case TVBUFF_COMPOSITE:
1022 return composite_memcpy(tvb, target, offset, length);
1025 g_assert_not_reached();
1031 * XXX - this doesn't treat a length of -1 as an error.
1032 * If it did, this could replace some code that calls
1033 * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
1036 * "composite_ensure_contiguous_no_exception()" depends on -1 not being
1037 * an error; does anything else depend on this routine treating -1 as
1038 * meaning "to the end of the buffer"?
1041 tvb_memdup(tvbuff_t *tvb, gint offset, gint length)
1043 guint abs_offset, abs_length;
1046 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
1048 duped = g_malloc(abs_length);
1049 return tvb_memcpy(tvb, duped, abs_offset, abs_length);
1055 tvb_get_ptr(tvbuff_t *tvb, gint offset, gint length)
1057 return ensure_contiguous(tvb, offset, length);
1061 tvb_get_guint8(tvbuff_t *tvb, gint offset)
1065 ptr = ensure_contiguous(tvb, offset, sizeof(guint8));
1070 tvb_get_ntohs(tvbuff_t *tvb, gint offset)
1074 ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1079 tvb_get_ntoh24(tvbuff_t *tvb, gint offset)
1083 ptr = ensure_contiguous(tvb, offset, 3);
1084 return pntoh24(ptr);
1088 tvb_get_ntohl(tvbuff_t *tvb, gint offset)
1092 ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1097 * Stuff for IEEE float handling on platforms that don't have IEEE
1098 * format as the native floating-point format.
1100 * For now, we treat only the VAX as such a platform.
1102 * XXX - other non-IEEE boxes that can run UNIX include some Crays,
1103 * and possibly other machines.
1105 * It appears that the official Linux port to System/390 and
1106 * zArchitecture uses IEEE format floating point (not a
1109 * I don't know whether there are any other machines that
1110 * could run Ethereal and that don't use IEEE format.
1111 * As far as I know, all of the main commercial microprocessor
1112 * families on which OSes that support Ethereal can run
1113 * use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
1114 * IA-64, and so on).
1124 #define IEEE_SP_NUMBER_WIDTH 32 /* bits in number */
1125 #define IEEE_SP_EXP_WIDTH 8 /* bits in exponent */
1126 #define IEEE_SP_MANTISSA_WIDTH 23 /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
1128 #define IEEE_SP_SIGN_MASK 0x80000000
1129 #define IEEE_SP_EXPONENT_MASK 0x7F800000
1130 #define IEEE_SP_MANTISSA_MASK 0x007FFFFF
1131 #define IEEE_SP_INFINITY IEEE_SP_EXPONENT_MASK
1133 #define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
1134 #define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
1135 #define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
1138 ieee_float_is_zero(guint32 w)
1140 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1144 get_ieee_float(guint32 w)
1150 sign = w & IEEE_SP_SIGN_MASK;
1151 exponent = w & IEEE_SP_EXPONENT_MASK;
1152 mantissa = w & IEEE_SP_MANTISSA_MASK;
1154 if (ieee_float_is_zero(w)) {
1155 /* number is zero, unnormalized, or not-a-number */
1160 * XXX - how to handle this?
1162 if (IEEE_SP_INFINITY == exponent) {
1164 * number is positive or negative infinity, or a special value
1166 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1170 exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1171 IEEE_SP_MANTISSA_WIDTH;
1172 mantissa |= IEEE_SP_IMPLIED_BIT;
1175 return -mantissa * pow(2, exponent);
1177 return mantissa * pow(2, exponent);
1182 * We assume that if you don't have IEEE floating-point, you have a
1183 * compiler that understands 64-bit integral quantities.
1185 #define IEEE_DP_NUMBER_WIDTH 64 /* bits in number */
1186 #define IEEE_DP_EXP_WIDTH 11 /* bits in exponent */
1187 #define IEEE_DP_MANTISSA_WIDTH 52 /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1189 #define IEEE_DP_SIGN_MASK 0x8000000000000000LL
1190 #define IEEE_DP_EXPONENT_MASK 0x7FF0000000000000LL
1191 #define IEEE_DP_MANTISSA_MASK 0x000FFFFFFFFFFFFFLL
1192 #define IEEE_DP_INFINITY IEEE_DP_EXPONENT_MASK
1194 #define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
1195 #define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1196 #define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1199 ieee_double_is_zero(guint64 w)
1201 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1205 get_ieee_double(guint64 w)
1211 sign = w & IEEE_DP_SIGN_MASK;
1212 exponent = w & IEEE_DP_EXPONENT_MASK;
1213 mantissa = w & IEEE_DP_MANTISSA_MASK;
1215 if (ieee_double_is_zero(w)) {
1216 /* number is zero, unnormalized, or not-a-number */
1221 * XXX - how to handle this?
1223 if (IEEE_DP_INFINITY == exponent) {
1225 * number is positive or negative infinity, or a special value
1227 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1231 exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1232 IEEE_DP_MANTISSA_WIDTH;
1233 mantissa |= IEEE_DP_IMPLIED_BIT;
1236 return -mantissa * pow(2, exponent);
1238 return mantissa * pow(2, exponent);
1243 * Fetches an IEEE single-precision floating-point number, in
1244 * big-endian form, and returns a "float".
1246 * XXX - should this be "double", in case there are IEEE single-
1247 * precision numbers that won't fit in some platform's native
1251 tvb_get_ntohieee_float(tvbuff_t *tvb, int offset)
1254 return get_ieee_float(tvb_get_ntohl(tvb, offset));
1261 ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1262 return ieee_fp_union.f;
1267 * Fetches an IEEE double-precision floating-point number, in
1268 * big-endian form, and returns a "double".
1271 tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
1285 #ifdef WORDS_BIGENDIAN
1286 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1287 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1289 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1290 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1293 return get_ieee_double(ieee_fp_union.dw);
1295 return ieee_fp_union.d;
1300 tvb_get_letohs(tvbuff_t *tvb, gint offset)
1304 ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1305 return pletohs(ptr);
1309 tvb_get_letoh24(tvbuff_t *tvb, gint offset)
1313 ptr = ensure_contiguous(tvb, offset, 3);
1314 return pletoh24(ptr);
1318 tvb_get_letohl(tvbuff_t *tvb, gint offset)
1322 ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1323 return pletohl(ptr);
1327 * Fetches an IEEE single-precision floating-point number, in
1328 * little-endian form, and returns a "float".
1330 * XXX - should this be "double", in case there are IEEE single-
1331 * precision numbers that won't fit in some platform's native
1335 tvb_get_letohieee_float(tvbuff_t *tvb, int offset)
1338 return get_ieee_float(tvb_get_letohl(tvb, offset));
1345 ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1346 return ieee_fp_union.f;
1351 * Fetches an IEEE double-precision floating-point number, in
1352 * little-endian form, and returns a "double".
1355 tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
1369 #ifdef WORDS_BIGENDIAN
1370 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1371 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1373 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1374 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1377 return get_ieee_double(ieee_fp_union.dw);
1379 return ieee_fp_union.d;
1383 /* Find first occurence of needle in tvbuff, starting at offset. Searches
1384 * at most maxlength number of bytes; if maxlength is -1, searches to
1386 * Returns the offset of the found needle, or -1 if not found.
1387 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1388 * in that case, -1 will be returned if the boundary is reached before
1389 * finding needle. */
1391 tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
1393 const guint8 *result;
1394 guint abs_offset, junk_length;
1398 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1400 /* Only search to end of tvbuff, w/o throwing exception. */
1401 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1402 if (maxlength == -1) {
1403 /* No maximum length specified; search to end of tvbuff. */
1406 else if (tvbufflen < (guint) maxlength) {
1407 /* Maximum length goes past end of tvbuff; search to end
1412 /* Maximum length doesn't go past end of tvbuff; search
1417 /* If we have real data, perform our search now. */
1418 if (tvb->real_data) {
1419 result = guint8_find(tvb->real_data + abs_offset, limit, needle);
1420 if (result == NULL) {
1424 return result - tvb->real_data;
1429 case TVBUFF_REAL_DATA:
1430 g_assert_not_reached();
1433 return tvb_find_guint8(tvb->tvbuffs.subset.tvb,
1434 abs_offset - tvb->tvbuffs.subset.offset,
1437 case TVBUFF_COMPOSITE:
1438 g_assert_not_reached();
1439 /* XXX - return composite_find_guint8(tvb, offset, limit, needle); */
1442 g_assert_not_reached();
1446 /* Find first occurence of any of the needles in tvbuff, starting at offset.
1447 * Searches at most maxlength number of bytes; if maxlength is -1, searches
1449 * Returns the offset of the found needle, or -1 if not found.
1450 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1451 * in that case, -1 will be returned if the boundary is reached before
1452 * finding needle. */
1454 tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 *needles)
1456 const guint8 *result;
1457 guint abs_offset, junk_length;
1461 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1463 /* Only search to end of tvbuff, w/o throwing exception. */
1464 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1465 if (maxlength == -1) {
1466 /* No maximum length specified; search to end of tvbuff. */
1469 else if (tvbufflen < (guint) maxlength) {
1470 /* Maximum length goes past end of tvbuff; search to end
1475 /* Maximum length doesn't go past end of tvbuff; search
1480 /* If we have real data, perform our search now. */
1481 if (tvb->real_data) {
1482 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles);
1483 if (result == NULL) {
1487 return result - tvb->real_data;
1492 case TVBUFF_REAL_DATA:
1493 g_assert_not_reached();
1496 return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
1497 abs_offset - tvb->tvbuffs.subset.offset,
1500 case TVBUFF_COMPOSITE:
1501 g_assert_not_reached();
1502 /* XXX - return composite_pbrk_guint8(tvb, offset, limit, needle); */
1505 g_assert_not_reached();
1509 /* Find size of stringz (NUL-terminated string) by looking for terminating
1510 * NUL. The size of the string includes the terminating NUL.
1512 * If the NUL isn't found, it throws the appropriate exception.
1515 tvb_strsize(tvbuff_t *tvb, gint offset)
1517 guint abs_offset, junk_length;
1520 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1521 nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
1522 if (nul_offset == -1) {
1524 * OK, we hit the end of the tvbuff, so we should throw
1527 * Did we hit the end of the captured data, or the end
1528 * of the actual data? If there's less captured data
1529 * than actual data, we presumably hit the end of the
1530 * captured data, otherwise we hit the end of the actual
1533 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
1536 THROW(ReportedBoundsError);
1539 return (nul_offset - abs_offset) + 1;
1542 /* Find length of string by looking for end of string ('\0'), up to
1543 * 'maxlength' characters'; if 'maxlength' is -1, searches to end
1545 * Returns -1 if 'maxlength' reached before finding EOS. */
1547 tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
1550 guint abs_offset, junk_length;
1552 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1554 result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
1556 if (result_offset == -1) {
1560 return result_offset - abs_offset;
1565 * Implement strneql etc
1569 * Call strncmp after checking if enough chars left, returning 0 if
1570 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1573 tvb_strneql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1577 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1580 int cmp = strncmp(ptr, str, size);
1583 * Return 0 if equal, -1 otherwise.
1585 return (cmp == 0 ? 0 : -1);
1588 * Not enough characters in the tvbuff to match the
1596 * Call strncasecmp after checking if enough chars left, returning 0 if
1597 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1600 tvb_strncaseeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1604 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1607 int cmp = strncasecmp(ptr, str, size);
1610 * Return 0 if equal, -1 otherwise.
1612 return (cmp == 0 ? 0 : -1);
1615 * Not enough characters in the tvbuff to match the
1623 * Call memcmp after checking if enough chars left, returning 0 if
1624 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1627 tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1631 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1634 int cmp = memcmp(ptr, str, size);
1637 * Return 0 if equal, -1 otherwise.
1639 return (cmp == 0 ? 0 : -1);
1642 * Not enough characters in the tvbuff to match the
1649 /* Convert a string from Unicode to ASCII. At the moment we fake it by
1650 * assuming all characters are ASCII )-: The caller must free the
1651 * result returned. The len parameter is the number of guint16's to
1652 * convert from Unicode. */
1654 tvb_fake_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
1660 /* Make sure we have enough data before allocating the buffer,
1661 so we don't blow up if the length is huge. */
1662 tvb_ensure_bytes_exist(tvb, offset, 2*len);
1664 /* We know we won't throw an exception, so we don't have to worry
1665 about leaking this buffer. */
1666 buffer = g_malloc(len + 1);
1668 for (i = 0; i < len; i++) {
1669 character = little_endian ? tvb_get_letohs(tvb, offset)
1670 : tvb_get_ntohs(tvb, offset);
1671 buffer[i] = character & 0xff;
1681 * Format the data in the tvb from offset for length ...
1685 tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
1690 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
1692 len = tvb_length_remaining(tvb, offset);
1693 ptr = ensure_contiguous(tvb, offset, len);
1697 return format_text(ptr, len);
1702 * Given a tvbuff, an offset, and a length, allocate a buffer big enough
1703 * to hold a non-null-terminated string of that length at that offset,
1704 * plus a trailing '\0', copy the string into it, and return a pointer
1707 * Throws an exception if the tvbuff ends before the string does.
1710 tvb_get_string(tvbuff_t *tvb, gint offset, gint length)
1712 guint8 *ptr, *strbuf;
1714 ptr = ensure_contiguous(tvb, offset, length);
1715 strbuf = g_malloc(length + 1);
1717 memcpy(strbuf, ptr, length);
1718 strbuf[length] = '\0';
1723 * Given a tvbuff and an offset, with the offset assumed to refer to
1724 * a null-terminated string, find the length of that string (and throw
1725 * an exception if the tvbuff ends before we find the null), allocate
1726 * a buffer big enough to hold the string, copy the string into it,
1727 * and return a pointer to the string. Also return the length of the
1728 * string (including the terminating null) through a pointer.
1731 tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
1736 size = tvb_strsize(tvb, offset);
1737 strptr = g_malloc(size);
1738 tvb_memcpy(tvb, strptr, offset, size);
1743 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1744 * no more than bufsize number of bytes, including terminating NUL, to buffer.
1745 * Returns length of string (not including terminating NUL), or -1 if the string was
1746 * truncated in the buffer due to not having reached the terminating NUL.
1747 * In this way, it acts like snprintf().
1749 * bufsize MUST be greater than 0.
1751 * When processing a packet where the remaining number of bytes is less
1752 * than bufsize, an exception is not thrown if the end of the packet
1753 * is reached before the NUL is found. If no NUL is found before reaching
1754 * the end of the short packet, -1 is still returned, and the string
1755 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1756 * at the correct spot, terminating the string.
1758 * *bytes_copied will contain the number of bytes actually copied,
1759 * including the terminating-NUL.
1762 _tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer,
1766 guint abs_offset, junk_length;
1768 gboolean decreased_max = FALSE;
1770 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1772 /* There must at least be room for the terminating NUL. */
1773 g_assert(bufsize != 0);
1775 /* If there's no room for anything else, just return the NUL. */
1782 /* Only read to end of tvbuff, w/o throwing exception. */
1783 len = tvb_length_remaining(tvb, abs_offset);
1785 /* check_offset_length() won't throw an exception if we're
1786 * looking at the byte immediately after the end of the tvbuff. */
1788 THROW(ReportedBoundsError);
1791 /* This should not happen because check_offset_length() would
1792 * have already thrown an exception if 'offset' were out-of-bounds.
1794 g_assert(len != -1);
1797 * If we've been passed a negative number, bufsize will
1800 g_assert(bufsize <= G_MAXINT);
1802 if ((guint)len < bufsize) {
1804 decreased_max = TRUE;
1810 stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
1811 /* If NUL wasn't found, copy the data and return -1 */
1812 if (stringlen == -1) {
1813 tvb_memcpy(tvb, buffer, abs_offset, limit);
1814 if (decreased_max) {
1816 /* Add 1 for the extra NUL that we set at buffer[limit],
1817 * pretending that it was copied as part of the string. */
1818 *bytes_copied = limit + 1;
1821 *bytes_copied = limit;
1826 /* Copy the string to buffer */
1827 tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
1828 *bytes_copied = stringlen + 1;
1832 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1833 * no more than bufsize number of bytes, including terminating NUL, to buffer.
1834 * Returns length of string (not including terminating NUL), or -1 if the string was
1835 * truncated in the buffer due to not having reached the terminating NUL.
1836 * In this way, it acts like snprintf().
1838 * When processing a packet where the remaining number of bytes is less
1839 * than bufsize, an exception is not thrown if the end of the packet
1840 * is reached before the NUL is found. If no NUL is found before reaching
1841 * the end of the short packet, -1 is still returned, and the string
1842 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1843 * at the correct spot, terminating the string.
1846 tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1850 return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1853 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
1854 * have a terminating NUL. If the string was truncated when copied into buffer,
1855 * a NUL is placed at the end of buffer to terminate it.
1858 tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1860 gint len, bytes_copied;
1862 len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1865 buffer[bufsize - 1] = 0;
1866 return bytes_copied - 1;
1874 * Given a tvbuff, an offset into the tvbuff, and a length that starts
1875 * at that offset (which may be -1 for "all the way to the end of the
1876 * tvbuff"), find the end of the (putative) line that starts at the
1877 * specified offset in the tvbuff, going no further than the specified
1880 * Return the length of the line (not counting the line terminator at
1881 * the end), or, if we don't find a line terminator:
1883 * if "deseg" is true, return -1;
1885 * if "deseg" is false, return the amount of data remaining in
1888 * Set "*next_offset" to the offset of the character past the line
1889 * terminator, or past the end of the buffer if we don't find a line
1890 * terminator. (It's not set if we return -1.)
1893 tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
1901 len = tvb_length_remaining(tvb, offset);
1903 * XXX - what if "len" is still -1, meaning "offset is past the
1904 * end of the tvbuff"?
1906 eob_offset = offset + len;
1909 * Look either for a CR or an LF.
1911 eol_offset = tvb_pbrk_guint8(tvb, offset, len, "\r\n");
1912 if (eol_offset == -1) {
1914 * No CR or LF - line is presumably continued in next packet.
1918 * Tell our caller we saw no EOL, so they can
1919 * try to desegment and get the entire line
1925 * Pretend the line runs to the end of the tvbuff.
1927 linelen = eob_offset - offset;
1928 *next_offset = eob_offset;
1932 * Find the number of bytes between the starting offset
1935 linelen = eol_offset - offset;
1940 if (tvb_get_guint8(tvb, eol_offset) == '\r') {
1942 * Yes - is it followed by an LF?
1944 if (eol_offset + 1 >= eob_offset) {
1946 * Dunno - the next byte isn't in this
1951 * We'll return -1, although that
1952 * runs the risk that if the line
1953 * really *is* terminated with a CR,
1954 * we won't properly dissect this
1957 * It's probably more likely that
1958 * the line ends with CR-LF than
1959 * that it ends with CR by itself.
1965 * Well, we can at least look at the next
1968 if (tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
1970 * It's an LF; skip over the CR.
1978 * Return the offset of the character after the last
1979 * character in the line, skipping over the last character
1980 * in the line terminator.
1982 *next_offset = eol_offset + 1;
1988 * Given a tvbuff, an offset into the tvbuff, and a length that starts
1989 * at that offset (which may be -1 for "all the way to the end of the
1990 * tvbuff"), find the end of the (putative) line that starts at the
1991 * specified offset in the tvbuff, going no further than the specified
1994 * However, treat quoted strings inside the buffer specially - don't
1995 * treat newlines in quoted strings as line terminators.
1997 * Return the length of the line (not counting the line terminator at
1998 * the end), or the amount of data remaining in the buffer if we don't
1999 * find a line terminator.
2001 * Set "*next_offset" to the offset of the character past the line
2002 * terminator, or past the end of the buffer if we don't find a line
2006 tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
2009 gint cur_offset, char_offset;
2016 len = tvb_length_remaining(tvb, offset);
2018 * XXX - what if "len" is still -1, meaning "offset is past the
2019 * end of the tvbuff"?
2021 eob_offset = offset + len;
2023 cur_offset = offset;
2027 * Is this part of the string quoted?
2031 * Yes - look only for the terminating quote.
2033 char_offset = tvb_find_guint8(tvb, cur_offset, len,
2037 * Look either for a CR, an LF, or a '"'.
2039 char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
2042 if (char_offset == -1) {
2044 * Not found - line is presumably continued in
2046 * We pretend the line runs to the end of the tvbuff.
2048 linelen = eob_offset - offset;
2049 *next_offset = eob_offset;
2055 * We're processing a quoted string.
2056 * We only looked for ", so we know it's a ";
2057 * as we're processing a quoted string, it's a
2065 c = tvb_get_guint8(tvb, char_offset);
2068 * Un-quoted "; it begins a quoted
2074 * It's a CR or LF; we've found a line
2077 * Find the number of bytes between the
2078 * starting offset and the CR or LF.
2080 linelen = char_offset - offset;
2087 * Yes; is it followed by an LF?
2089 if (char_offset + 1 < eob_offset &&
2090 tvb_get_guint8(tvb, char_offset + 1)
2093 * Yes; skip over the CR.
2100 * Return the offset of the character after
2101 * the last character in the line, skipping
2102 * over the last character in the line
2103 * terminator, and quit.
2105 *next_offset = char_offset + 1;
2111 * Step past the character we found.
2113 cur_offset = char_offset + 1;
2114 if (cur_offset >= eob_offset) {
2116 * The character we found was the last character
2117 * in the tvbuff - line is presumably continued in
2119 * We pretend the line runs to the end of the tvbuff.
2121 linelen = eob_offset - offset;
2122 *next_offset = eob_offset;
2130 * Format a bunch of data from a tvbuff as bytes, returning a pointer
2131 * to the string with the formatted data.
2134 tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len)
2136 return bytes_to_str(tvb_get_ptr(tvb, offset, len), len);
2140 tvb_get_ds_tvb(tvbuff_t *tvb)
2145 /* Find a needle tvbuff within a haystack tvbuff. */
2147 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
2149 guint haystack_abs_offset, haystack_abs_length;
2150 const guint8 *haystack_data;
2151 const guint8 *needle_data;
2152 const guint needle_len = needle_tvb->length;
2153 const guint8 *location;
2155 /* Get pointers to the tvbuffs' data. */
2156 haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
2157 needle_data = tvb_get_ptr(needle_tvb, 0, -1);
2159 check_offset_length(haystack_tvb, haystack_offset, -1,
2160 &haystack_abs_offset, &haystack_abs_length);
2162 location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
2163 needle_data, needle_len);
2166 return location - haystack_data;