Try to improve the "Kerberos requested but not OpenSSL" message.
[jelmer/wireshark.git] / epan / tvbuff_subset.c
1 /* tvbuff_real.c
2  *
3  * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "config.h"
25
26 #include <epan/emem.h>
27
28 #include "tvbuff.h"
29 #include "tvbuff-int.h"
30 #include "proto.h"      /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
31 #include "exceptions.h"
32
33 typedef struct {
34         /** The backing tvbuff_t */
35         struct tvbuff   *tvb;
36
37         /** The offset of 'tvb' to which I'm privy */
38         guint           offset;
39         /** The length of 'tvb' to which I'm privy */
40         guint           length;
41
42 } tvb_backing_t;
43
44 struct tvb_subset {
45         struct tvbuff tvb;
46
47         tvb_backing_t   subset;
48 };
49
50 static guint
51 subset_offset(const tvbuff_t *tvb, const guint counter)
52 {
53         const struct tvb_subset *subset_tvb = (const struct tvb_subset *) tvb;
54         const tvbuff_t *member = subset_tvb->subset.tvb;
55
56         return tvb_offset_from_real_beginning_counter(member, counter + subset_tvb->subset.offset);
57 }
58
59 static void *
60 subset_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
61 {
62         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
63
64         return tvb_memcpy(subset_tvb->subset.tvb, target, subset_tvb->subset.offset + abs_offset, abs_length);
65 }
66
67 static const guint8 *
68 subset_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length)
69 {
70         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
71
72         return tvb_get_ptr(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
73 }
74
75 static gint
76 subset_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
77 {
78         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
79
80         return tvb_find_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needle);
81 }
82
83 static gint
84 subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle)
85 {
86         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
87
88         return tvb_pbrk_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needles, found_needle);
89 }
90
91 static tvbuff_t *
92 subset_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
93 {
94         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
95
96         return tvb_clone_offset_len(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
97 }
98
99 static const struct tvb_ops tvb_subset_ops = {
100         sizeof(struct tvb_subset), /* size */
101
102         NULL,                 /* free */
103         subset_offset,        /* offset */
104         subset_get_ptr,       /* get_ptr */
105         subset_memcpy,        /* memcpy */
106         subset_find_guint8,   /* find_guint8 */
107         subset_pbrk_guint8,   /* pbrk_guint8 */
108         subset_clone,         /* clone */
109 };
110
111 static tvbuff_t *
112 tvb_new_with_subset(tvbuff_t *backing, const gint reported_length,
113     const guint subset_tvb_offset, const guint subset_tvb_length)
114 {
115         tvbuff_t *tvb = tvb_new(&tvb_subset_ops);
116         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
117
118         subset_tvb->subset.offset = subset_tvb_offset;
119         subset_tvb->subset.length = subset_tvb_length;
120
121         subset_tvb->subset.tvb       = backing;
122         tvb->length                  = subset_tvb_length;
123         tvb->flags                   = backing->flags;
124
125         if (reported_length == -1) {
126                 tvb->reported_length = backing->reported_length - subset_tvb_offset;
127         }
128         else {
129                 tvb->reported_length = reported_length;
130         }
131         tvb->initialized             = TRUE;
132
133         /* Optimization. If the backing buffer has a pointer to contiguous, real data,
134          * then we can point directly to our starting offset in that buffer */
135         if (backing->real_data != NULL) {
136                 tvb->real_data = backing->real_data + subset_tvb_offset;
137         }
138
139         /*
140          * The top-level data source of this tvbuff is the top-level
141          * data source of its parent.
142          */
143         tvb->ds_tvb = backing->ds_tvb;
144
145         return tvb;
146 }
147
148 tvbuff_t *
149 tvb_new_subset(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
150 {
151         tvbuff_t *tvb;
152         guint     subset_tvb_offset;
153         guint     subset_tvb_length;
154
155         DISSECTOR_ASSERT(backing && backing->initialized);
156
157         THROW_ON(reported_length < -1, ReportedBoundsError);
158
159         tvb_check_offset_length(backing, backing_offset, backing_length,
160                                 &subset_tvb_offset,
161                                 &subset_tvb_length);
162
163         tvb = tvb_new_with_subset(backing, reported_length,
164             subset_tvb_offset, subset_tvb_length);
165
166         tvb_add_to_chain(backing, tvb);
167
168         return tvb;
169 }
170
171 tvbuff_t *
172 tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint backing_length)
173 {
174         gint      captured_length;
175         tvbuff_t *tvb;
176         guint     subset_tvb_offset;
177         guint     subset_tvb_length;
178
179         DISSECTOR_ASSERT(backing && backing->initialized);
180
181         THROW_ON(backing_length < 0, ReportedBoundsError);
182
183         /*
184          * Give the next dissector only captured_length bytes.
185          */
186         captured_length = tvb_length_remaining(backing, backing_offset);
187         THROW_ON(captured_length < 0, BoundsError);
188         if (captured_length > backing_length)
189                 captured_length = backing_length;
190
191         tvb_check_offset_length(backing, backing_offset, captured_length,
192                                 &subset_tvb_offset,
193                                 &subset_tvb_length);
194
195         tvb = tvb_new_with_subset(backing, backing_length,
196             subset_tvb_offset, subset_tvb_length);
197
198         tvb_add_to_chain(backing, tvb);
199
200         return tvb;
201 }
202
203 tvbuff_t *
204 tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
205 {
206         tvbuff_t *tvb;
207         guint     subset_tvb_offset;
208         guint     subset_tvb_length;
209
210         tvb_check_offset_length(backing, backing_offset, -1 /* backing_length */,
211                                 &subset_tvb_offset,
212                                 &subset_tvb_length);
213
214         tvb = tvb_new_with_subset(backing, -1 /* reported_length */,
215             subset_tvb_offset, subset_tvb_length);
216
217         tvb_add_to_chain(backing, tvb);
218
219         return tvb;
220 }
221
222 tvbuff_t *
223 tvb_new_proxy(tvbuff_t *backing)
224 {
225         tvbuff_t *tvb;
226
227         if (backing)
228                 tvb = tvb_new_with_subset(backing, backing->reported_length, 0, backing->length);
229         else
230                 tvb = tvb_new_real_data(NULL, 0, 0);
231
232         tvb->ds_tvb = tvb;
233
234         return tvb;
235 }
236
237
238 /*
239  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
240  *
241  * Local variables:
242  * c-basic-offset: 8
243  * tab-width: 8
244  * indent-tabs-mode: t
245  * End:
246  *
247  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
248  * :indentSize=8:tabSize=8:noTabs=false:
249  */