]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/bio/bio_reader.c
Moved debug.[ch] to utils folder
[thirdparty/strongswan.git] / src / libstrongswan / bio / bio_reader.c
CommitLineData
4ef946dd 1/*
c1830d26
TB
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
4ef946dd 5 * Copyright (C) 2010 Martin Willi
0f82a470 6 * Copyright (C) 2010 revosec AG
4ef946dd
MW
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
7e432eff 19#include "bio_reader.h"
4ef946dd 20
f05b4272 21#include <utils/debug.h>
4ef946dd 22
7e432eff 23typedef struct private_bio_reader_t private_bio_reader_t;
4ef946dd
MW
24
25/**
7e432eff 26 * Private data of an bio_reader_t object.
4ef946dd 27 */
7e432eff 28struct private_bio_reader_t {
4ef946dd
MW
29
30 /**
7e432eff 31 * Public bio_reader_t interface.
4ef946dd 32 */
7e432eff 33 bio_reader_t public;
4ef946dd
MW
34
35 /**
36 * Remaining data to process
37 */
38 chunk_t buf;
39};
40
7e432eff
AS
41METHOD(bio_reader_t, remaining, u_int32_t,
42 private_bio_reader_t *this)
4ef946dd
MW
43{
44 return this->buf.len;
45}
46
7e432eff
AS
47METHOD(bio_reader_t, peek, chunk_t,
48 private_bio_reader_t *this)
3ddd164e
MW
49{
50 return this->buf;
51}
52
c1830d26
TB
53/**
54 * A version of chunk_skip() that supports skipping from the end (i.e. simply
55 * reducing the size)
56 */
57static inline chunk_t chunk_skip_end(chunk_t chunk, size_t bytes, bool from_end)
58{
59 if (chunk.len > bytes)
60 {
61 if (!from_end)
62 {
63 chunk.ptr += bytes;
64 }
65 chunk.len -= bytes;
66 return chunk;
67 }
68 return chunk_empty;
69}
70
71/**
72 * Returns a pointer to the data to read, optionally from the end
73 */
74static inline u_char *get_ptr_end(private_bio_reader_t *this, u_int32_t len,
75 bool from_end)
76{
77 return from_end ? this->buf.ptr + (this->buf.len - len) : this->buf.ptr;
78}
79
80/**
81 * Read an u_int8_t from the buffer, optionally from the end of the buffer
82 */
83static bool read_uint8_internal(private_bio_reader_t *this, u_int8_t *res,
84 bool from_end)
4ef946dd
MW
85{
86 if (this->buf.len < 1)
87 {
7e432eff 88 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int8 data",
58d73d38 89 this->buf.len);
4ef946dd
MW
90 return FALSE;
91 }
c1830d26
TB
92 *res = *get_ptr_end(this, 1, from_end);
93 this->buf = chunk_skip_end(this->buf, 1, from_end);
4ef946dd
MW
94 return TRUE;
95}
96
c1830d26
TB
97/**
98 * Read an u_int16_t from the buffer, optionally from the end
99 */
100static bool read_uint16_internal(private_bio_reader_t *this, u_int16_t *res,
101 bool from_end)
4ef946dd
MW
102{
103 if (this->buf.len < 2)
104 {
7e432eff 105 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int16 data",
58d73d38 106 this->buf.len);
4ef946dd
MW
107 return FALSE;
108 }
c1830d26
TB
109 *res = untoh16(get_ptr_end(this, 2, from_end));
110 this->buf = chunk_skip_end(this->buf, 2, from_end);
4ef946dd
MW
111 return TRUE;
112}
113
c1830d26
TB
114/**
115 * Read an u_int32_t (only 24-bit) from the buffer, optionally from the end
116 */
117static bool read_uint24_internal(private_bio_reader_t *this, u_int32_t *res,
118 bool from_end)
4ef946dd
MW
119{
120 if (this->buf.len < 3)
121 {
7e432eff 122 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int24 data",
58d73d38 123 this->buf.len);
4ef946dd
MW
124 return FALSE;
125 }
c1830d26
TB
126 *res = untoh32(get_ptr_end(this, 3, from_end)) >> 8;
127 this->buf = chunk_skip_end(this->buf, 3, from_end);
4ef946dd
MW
128 return TRUE;
129}
130
c1830d26
TB
131/**
132 * Read an u_int32_t from the buffer, optionally from the end
133 */
134static bool read_uint32_internal(private_bio_reader_t *this, u_int32_t *res,
135 bool from_end)
4ef946dd
MW
136{
137 if (this->buf.len < 4)
138 {
7e432eff 139 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int32 data",
58d73d38 140 this->buf.len);
4ef946dd
MW
141 return FALSE;
142 }
c1830d26
TB
143 *res = untoh32(get_ptr_end(this, 4, from_end));
144 this->buf = chunk_skip_end(this->buf, 4, from_end);
4ef946dd
MW
145 return TRUE;
146}
147
c1830d26
TB
148/**
149 * Read an u_int64_t from the buffer, optionally from the end
150 */
151static bool read_uint64_internal(private_bio_reader_t *this, u_int64_t *res,
152 bool from_end)
fbeb9454
AS
153{
154 if (this->buf.len < 8)
155 {
156 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int64 data",
157 this->buf.len);
158 return FALSE;
159 }
c1830d26
TB
160 *res = untoh64(get_ptr_end(this, 8, from_end));
161 this->buf = chunk_skip_end(this->buf, 8, from_end);
fbeb9454
AS
162 return TRUE;
163}
164
c1830d26
TB
165/**
166 * Read a chunk of data from the buffer, optionally from the end
167 */
168static bool read_data_internal(private_bio_reader_t *this, u_int32_t len,
169 chunk_t *res, bool from_end)
4ef946dd
MW
170{
171 if (this->buf.len < len)
172 {
7e432eff 173 DBG1(DBG_LIB, "%d bytes insufficient to parse %d bytes of data",
4ef946dd
MW
174 this->buf.len, len);
175 return FALSE;
176 }
c1830d26
TB
177 *res = chunk_create(get_ptr_end(this, len, from_end), len);
178 this->buf = chunk_skip_end(this->buf, len, from_end);
4ef946dd
MW
179 return TRUE;
180}
181
c1830d26
TB
182METHOD(bio_reader_t, read_uint8, bool,
183 private_bio_reader_t *this, u_int8_t *res)
184{
185 return read_uint8_internal(this, res, FALSE);
186}
187
188METHOD(bio_reader_t, read_uint16, bool,
189 private_bio_reader_t *this, u_int16_t *res)
190{
191 return read_uint16_internal(this, res, FALSE);
192}
193
194METHOD(bio_reader_t, read_uint24, bool,
195 private_bio_reader_t *this, u_int32_t *res)
196{
197 return read_uint24_internal(this, res, FALSE);
198}
199
200METHOD(bio_reader_t, read_uint32, bool,
201 private_bio_reader_t *this, u_int32_t *res)
202{
203 return read_uint32_internal(this, res, FALSE);
204}
205
206METHOD(bio_reader_t, read_uint64, bool,
207 private_bio_reader_t *this, u_int64_t *res)
208{
209 return read_uint64_internal(this, res, FALSE);
210}
211
212METHOD(bio_reader_t, read_data, bool,
213 private_bio_reader_t *this, u_int32_t len, chunk_t *res)
214{
215 return read_data_internal(this, len, res, FALSE);
216}
217
218METHOD(bio_reader_t, read_uint8_end, bool,
219 private_bio_reader_t *this, u_int8_t *res)
220{
221 return read_uint8_internal(this, res, TRUE);
222}
223
224METHOD(bio_reader_t, read_uint16_end, bool,
225 private_bio_reader_t *this, u_int16_t *res)
226{
227 return read_uint16_internal(this, res, TRUE);
228}
229
230METHOD(bio_reader_t, read_uint24_end, bool,
231 private_bio_reader_t *this, u_int32_t *res)
232{
233 return read_uint24_internal(this, res, TRUE);
234}
235
236METHOD(bio_reader_t, read_uint32_end, bool,
237 private_bio_reader_t *this, u_int32_t *res)
238{
239 return read_uint32_internal(this, res, TRUE);
240}
241
242METHOD(bio_reader_t, read_uint64_end, bool,
243 private_bio_reader_t *this, u_int64_t *res)
244{
245 return read_uint64_internal(this, res, TRUE);
246}
247
248METHOD(bio_reader_t, read_data_end, bool,
249 private_bio_reader_t *this, u_int32_t len, chunk_t *res)
250{
251 return read_data_internal(this, len, res, TRUE);
252}
253
7e432eff
AS
254METHOD(bio_reader_t, read_data8, bool,
255 private_bio_reader_t *this, chunk_t *res)
4ef946dd
MW
256{
257 u_int8_t len;
258
259 if (!read_uint8(this, &len))
260 {
261 return FALSE;
262 }
263 return read_data(this, len, res);
264}
265
7e432eff
AS
266METHOD(bio_reader_t, read_data16, bool,
267 private_bio_reader_t *this, chunk_t *res)
4ef946dd
MW
268{
269 u_int16_t len;
270
271 if (!read_uint16(this, &len))
272 {
273 return FALSE;
274 }
275 return read_data(this, len, res);
276}
277
7e432eff
AS
278METHOD(bio_reader_t, read_data24, bool,
279 private_bio_reader_t *this, chunk_t *res)
4ef946dd
MW
280{
281 u_int32_t len;
282
283 if (!read_uint24(this, &len))
284 {
285 return FALSE;
286 }
287 return read_data(this, len, res);
288}
289
7e432eff
AS
290METHOD(bio_reader_t, read_data32, bool,
291 private_bio_reader_t *this, chunk_t *res)
4ef946dd
MW
292{
293 u_int32_t len;
294
295 if (!read_uint32(this, &len))
296 {
297 return FALSE;
298 }
299 return read_data(this, len, res);
300}
301
7e432eff
AS
302METHOD(bio_reader_t, destroy, void,
303 private_bio_reader_t *this)
4ef946dd
MW
304{
305 free(this);
306}
307
308/**
309 * See header
310 */
7e432eff 311bio_reader_t *bio_reader_create(chunk_t data)
4ef946dd 312{
7e432eff 313 private_bio_reader_t *this;
4ef946dd
MW
314
315 INIT(this,
316 .public = {
317 .remaining = _remaining,
3ddd164e 318 .peek = _peek,
4ef946dd
MW
319 .read_uint8 = _read_uint8,
320 .read_uint16 = _read_uint16,
321 .read_uint24 = _read_uint24,
322 .read_uint32 = _read_uint32,
fbeb9454 323 .read_uint64 = _read_uint64,
4ef946dd 324 .read_data = _read_data,
c1830d26
TB
325 .read_uint8_end = _read_uint8_end,
326 .read_uint16_end = _read_uint16_end,
327 .read_uint24_end = _read_uint24_end,
328 .read_uint32_end = _read_uint32_end,
329 .read_uint64_end = _read_uint64_end,
330 .read_data_end = _read_data_end,
4ef946dd
MW
331 .read_data8 = _read_data8,
332 .read_data16 = _read_data16,
333 .read_data24 = _read_data24,
334 .read_data32 = _read_data32,
335 .destroy = _destroy,
336 },
337 .buf = data,
338 );
339
340 return &this->public;
341}