3 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "tvbuff-int.h"
16 #include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
17 #include "exceptions.h"
20 /** The backing tvbuff_t */
23 /** The offset of 'tvb' to which I'm privy */
25 /** The length of 'tvb' to which I'm privy */
37 subset_offset(const tvbuff_t *tvb, const guint counter)
39 const struct tvb_subset *subset_tvb = (const struct tvb_subset *) tvb;
40 const tvbuff_t *member = subset_tvb->subset.tvb;
42 return tvb_offset_from_real_beginning_counter(member, counter + subset_tvb->subset.offset);
46 subset_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
48 struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
50 return tvb_memcpy(subset_tvb->subset.tvb, target, subset_tvb->subset.offset + abs_offset, abs_length);
54 subset_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length)
56 struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
58 return tvb_get_ptr(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
62 subset_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
64 struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
66 return tvb_find_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needle);
70 subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
72 struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
74 return tvb_ws_mempbrk_pattern_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, pattern, found_needle);
78 subset_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
80 struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
82 return tvb_clone_offset_len(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
85 static const struct tvb_ops tvb_subset_ops = {
86 sizeof(struct tvb_subset), /* size */
89 subset_offset, /* offset */
90 subset_get_ptr, /* get_ptr */
91 subset_memcpy, /* memcpy */
92 subset_find_guint8, /* find_guint8 */
93 subset_pbrk_guint8, /* pbrk_guint8 */
94 subset_clone, /* clone */
98 tvb_new_with_subset(tvbuff_t *backing, const guint reported_length,
99 const guint subset_tvb_offset, const guint subset_tvb_length)
101 tvbuff_t *tvb = tvb_new(&tvb_subset_ops);
102 struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
104 subset_tvb->subset.offset = subset_tvb_offset;
105 subset_tvb->subset.length = subset_tvb_length;
107 subset_tvb->subset.tvb = backing;
108 tvb->length = subset_tvb_length;
110 * The contained length must not exceed what remains in the
113 tvb->contained_length = MIN(reported_length, backing->contained_length - subset_tvb_offset);
114 tvb->flags = backing->flags;
116 tvb->reported_length = reported_length;
117 tvb->initialized = TRUE;
119 /* Optimization. If the backing buffer has a pointer to contiguous, real data,
120 * then we can point directly to our starting offset in that buffer */
121 if (backing->real_data != NULL) {
122 tvb->real_data = backing->real_data + subset_tvb_offset;
126 * The top-level data source of this tvbuff is the top-level
127 * data source of its parent.
129 tvb->ds_tvb = backing->ds_tvb;
135 tvb_new_subset_length_caplen(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
138 guint subset_tvb_offset;
139 guint subset_tvb_length;
140 guint actual_reported_length;
142 DISSECTOR_ASSERT(backing && backing->initialized);
144 THROW_ON(reported_length < -1, ReportedBoundsError);
146 tvb_check_offset_length(backing, backing_offset, backing_length,
150 if (reported_length == -1)
151 actual_reported_length = backing->reported_length - subset_tvb_offset;
153 actual_reported_length = (guint)reported_length;
155 tvb = tvb_new_with_subset(backing, actual_reported_length,
156 subset_tvb_offset, subset_tvb_length);
158 tvb_add_to_chain(backing, tvb);
164 tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint reported_length)
166 gint captured_length;
167 gint actual_reported_length;
169 guint subset_tvb_offset;
170 guint subset_tvb_length;
172 DISSECTOR_ASSERT(backing && backing->initialized);
174 THROW_ON(reported_length < -1, ReportedBoundsError);
176 if (reported_length == -1)
177 actual_reported_length = backing->reported_length;
179 actual_reported_length = reported_length;
182 * Cut the captured length short, so it doesn't go past the subset's
185 captured_length = tvb_captured_length_remaining(backing, backing_offset);
186 THROW_ON(captured_length < 0, BoundsError);
187 if (captured_length > actual_reported_length)
188 captured_length = actual_reported_length;
190 tvb_check_offset_length(backing, backing_offset, captured_length,
194 tvb = tvb_new_with_subset(backing, (guint)actual_reported_length,
195 subset_tvb_offset, subset_tvb_length);
197 tvb_add_to_chain(backing, tvb);
203 tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
206 guint subset_tvb_offset;
207 guint subset_tvb_length;
208 guint reported_length;
210 tvb_check_offset_length(backing, backing_offset, -1 /* backing_length */,
214 THROW_ON(backing->reported_length < subset_tvb_offset, ReportedBoundsError);
215 reported_length = backing->reported_length - subset_tvb_offset;
217 tvb = tvb_new_with_subset(backing, reported_length,
218 subset_tvb_offset, subset_tvb_length);
220 tvb_add_to_chain(backing, tvb);
226 tvb_new_proxy(tvbuff_t *backing)
231 tvb = tvb_new_with_subset(backing, backing->reported_length, 0, backing->length);
233 tvb = tvb_new_real_data(NULL, 0, 0);
242 * Editor modelines - http://www.wireshark.org/tools/modelines.html
247 * indent-tabs-mode: t
250 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
251 * :indentSize=8:tabSize=8:noTabs=false: