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 unsigned 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
, unsigned abs_offset
, unsigned 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
);
53 static const uint8_t *
54 subset_get_ptr(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned 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_uint8(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned limit
, uint8_t needle
)
64 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
67 result
= tvb_find_uint8(subset_tvb
->subset
.tvb
, subset_tvb
->subset
.offset
+ abs_offset
, limit
, needle
);
72 * Make the result relative to the beginning of the tvbuff we
73 * were handed, *not* relative to the beginning of its parent
76 return result
- subset_tvb
->subset
.offset
;
80 subset_pbrk_uint8(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned limit
, const ws_mempbrk_pattern
* pattern
, unsigned char *found_needle
)
82 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
85 result
= tvb_ws_mempbrk_pattern_uint8(subset_tvb
->subset
.tvb
, subset_tvb
->subset
.offset
+ abs_offset
, limit
, pattern
, found_needle
);
90 * Make the result relative to the beginning of the tvbuff we
91 * were handed, *not* relative to the beginning of its parent
94 return result
- subset_tvb
->subset
.offset
;
98 subset_clone(tvbuff_t
*tvb
, unsigned abs_offset
, unsigned abs_length
)
100 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
102 return tvb_clone_offset_len(subset_tvb
->subset
.tvb
, subset_tvb
->subset
.offset
+ abs_offset
, abs_length
);
105 static const struct tvb_ops tvb_subset_ops
= {
106 sizeof(struct tvb_subset
), /* size */
109 subset_offset
, /* offset */
110 subset_get_ptr
, /* get_ptr */
111 subset_memcpy
, /* memcpy */
112 subset_find_uint8
, /* find_uint8 */
113 subset_pbrk_uint8
, /* pbrk_uint8 */
114 subset_clone
, /* clone */
118 tvb_new_with_subset(tvbuff_t
*backing
, const unsigned reported_length
,
119 const unsigned subset_tvb_offset
, const unsigned subset_tvb_length
)
121 tvbuff_t
*tvb
= tvb_new(&tvb_subset_ops
);
122 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
124 subset_tvb
->subset
.offset
= subset_tvb_offset
;
125 subset_tvb
->subset
.length
= subset_tvb_length
;
127 subset_tvb
->subset
.tvb
= backing
;
128 tvb
->length
= subset_tvb_length
;
130 * The contained length must not exceed what remains in the
133 tvb
->contained_length
= MIN(reported_length
, backing
->contained_length
- subset_tvb_offset
);
134 tvb
->flags
= backing
->flags
;
136 tvb
->reported_length
= reported_length
;
137 tvb
->initialized
= true;
139 /* Optimization. If the backing buffer has a pointer to contiguous, real data,
140 * then we can point directly to our starting offset in that buffer */
141 if (backing
->real_data
!= NULL
) {
142 tvb
->real_data
= backing
->real_data
+ subset_tvb_offset
;
146 * The top-level data source of this tvbuff is the top-level
147 * data source of its parent.
149 tvb
->ds_tvb
= backing
->ds_tvb
;
155 tvb_new_subset_length_caplen(tvbuff_t
*backing
, const int backing_offset
, const int backing_length
, const int reported_length
)
158 unsigned subset_tvb_offset
;
159 unsigned subset_tvb_length
;
160 unsigned actual_reported_length
;
162 DISSECTOR_ASSERT(backing
&& backing
->initialized
);
164 THROW_ON(reported_length
< -1, ReportedBoundsError
);
166 tvb_check_offset_length(backing
, backing_offset
, backing_length
,
170 if (reported_length
== -1)
171 actual_reported_length
= backing
->reported_length
- subset_tvb_offset
;
173 actual_reported_length
= (unsigned)reported_length
;
176 * Cut the captured length short, so it doesn't go past the subset's
179 if (subset_tvb_length
> actual_reported_length
)
180 subset_tvb_length
= actual_reported_length
;
182 tvb
= tvb_new_with_subset(backing
, actual_reported_length
,
183 subset_tvb_offset
, subset_tvb_length
);
185 tvb_add_to_chain(backing
, tvb
);
191 tvb_new_subset_length(tvbuff_t
*backing
, const int backing_offset
, const int reported_length
)
194 int actual_reported_length
;
196 unsigned subset_tvb_offset
;
197 unsigned subset_tvb_length
;
199 DISSECTOR_ASSERT(backing
&& backing
->initialized
);
201 THROW_ON(reported_length
< -1, ReportedBoundsError
);
203 if (reported_length
== -1)
204 actual_reported_length
= backing
->reported_length
;
206 actual_reported_length
= reported_length
;
209 * Cut the captured length short, so it doesn't go past the subset's
212 captured_length
= tvb_captured_length_remaining(backing
, backing_offset
);
213 THROW_ON(captured_length
< 0, BoundsError
);
214 if (captured_length
> actual_reported_length
)
215 captured_length
= actual_reported_length
;
217 tvb_check_offset_length(backing
, backing_offset
, captured_length
,
222 * If the requested reported length is "to the end of the buffer",
223 * subtract the offset from the total length. We do this now, because
224 * the user might have passed in a negative offset.
226 if (reported_length
== -1) {
227 THROW_ON(backing
->reported_length
< subset_tvb_offset
, ReportedBoundsError
);
228 actual_reported_length
-= subset_tvb_offset
;
231 tvb
= tvb_new_with_subset(backing
, (unsigned)actual_reported_length
,
232 subset_tvb_offset
, subset_tvb_length
);
234 tvb_add_to_chain(backing
, tvb
);
240 tvb_new_subset_remaining(tvbuff_t
*backing
, const int backing_offset
)
243 unsigned subset_tvb_offset
;
244 unsigned subset_tvb_length
;
245 unsigned reported_length
;
247 tvb_check_offset_length(backing
, backing_offset
, -1 /* backing_length */,
251 THROW_ON(backing
->reported_length
< subset_tvb_offset
, ReportedBoundsError
);
252 reported_length
= backing
->reported_length
- subset_tvb_offset
;
254 tvb
= tvb_new_with_subset(backing
, reported_length
,
255 subset_tvb_offset
, subset_tvb_length
);
257 tvb_add_to_chain(backing
, tvb
);
263 tvb_new_proxy(tvbuff_t
*backing
)
268 tvb
= tvb_new_with_subset(backing
, backing
->reported_length
, 0, backing
->length
);
270 tvb
= tvb_new_real_data(NULL
, 0, 0);
279 * Editor modelines - https://www.wireshark.org/tools/modelines.html
284 * indent-tabs-mode: t
287 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
288 * :indentSize=8:tabSize=8:noTabs=false: