]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/bio/bio_reader.c
Moved debug.[ch] to utils folder
[thirdparty/strongswan.git] / src / libstrongswan / bio / bio_reader.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
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
19 #include "bio_reader.h"
20
21 #include <utils/debug.h>
22
23 typedef struct private_bio_reader_t private_bio_reader_t;
24
25 /**
26 * Private data of an bio_reader_t object.
27 */
28 struct private_bio_reader_t {
29
30 /**
31 * Public bio_reader_t interface.
32 */
33 bio_reader_t public;
34
35 /**
36 * Remaining data to process
37 */
38 chunk_t buf;
39 };
40
41 METHOD(bio_reader_t, remaining, u_int32_t,
42 private_bio_reader_t *this)
43 {
44 return this->buf.len;
45 }
46
47 METHOD(bio_reader_t, peek, chunk_t,
48 private_bio_reader_t *this)
49 {
50 return this->buf;
51 }
52
53 /**
54 * A version of chunk_skip() that supports skipping from the end (i.e. simply
55 * reducing the size)
56 */
57 static 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 */
74 static 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 */
83 static bool read_uint8_internal(private_bio_reader_t *this, u_int8_t *res,
84 bool from_end)
85 {
86 if (this->buf.len < 1)
87 {
88 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int8 data",
89 this->buf.len);
90 return FALSE;
91 }
92 *res = *get_ptr_end(this, 1, from_end);
93 this->buf = chunk_skip_end(this->buf, 1, from_end);
94 return TRUE;
95 }
96
97 /**
98 * Read an u_int16_t from the buffer, optionally from the end
99 */
100 static bool read_uint16_internal(private_bio_reader_t *this, u_int16_t *res,
101 bool from_end)
102 {
103 if (this->buf.len < 2)
104 {
105 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int16 data",
106 this->buf.len);
107 return FALSE;
108 }
109 *res = untoh16(get_ptr_end(this, 2, from_end));
110 this->buf = chunk_skip_end(this->buf, 2, from_end);
111 return TRUE;
112 }
113
114 /**
115 * Read an u_int32_t (only 24-bit) from the buffer, optionally from the end
116 */
117 static bool read_uint24_internal(private_bio_reader_t *this, u_int32_t *res,
118 bool from_end)
119 {
120 if (this->buf.len < 3)
121 {
122 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int24 data",
123 this->buf.len);
124 return FALSE;
125 }
126 *res = untoh32(get_ptr_end(this, 3, from_end)) >> 8;
127 this->buf = chunk_skip_end(this->buf, 3, from_end);
128 return TRUE;
129 }
130
131 /**
132 * Read an u_int32_t from the buffer, optionally from the end
133 */
134 static bool read_uint32_internal(private_bio_reader_t *this, u_int32_t *res,
135 bool from_end)
136 {
137 if (this->buf.len < 4)
138 {
139 DBG1(DBG_LIB, "%d bytes insufficient to parse u_int32 data",
140 this->buf.len);
141 return FALSE;
142 }
143 *res = untoh32(get_ptr_end(this, 4, from_end));
144 this->buf = chunk_skip_end(this->buf, 4, from_end);
145 return TRUE;
146 }
147
148 /**
149 * Read an u_int64_t from the buffer, optionally from the end
150 */
151 static bool read_uint64_internal(private_bio_reader_t *this, u_int64_t *res,
152 bool from_end)
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 }
160 *res = untoh64(get_ptr_end(this, 8, from_end));
161 this->buf = chunk_skip_end(this->buf, 8, from_end);
162 return TRUE;
163 }
164
165 /**
166 * Read a chunk of data from the buffer, optionally from the end
167 */
168 static bool read_data_internal(private_bio_reader_t *this, u_int32_t len,
169 chunk_t *res, bool from_end)
170 {
171 if (this->buf.len < len)
172 {
173 DBG1(DBG_LIB, "%d bytes insufficient to parse %d bytes of data",
174 this->buf.len, len);
175 return FALSE;
176 }
177 *res = chunk_create(get_ptr_end(this, len, from_end), len);
178 this->buf = chunk_skip_end(this->buf, len, from_end);
179 return TRUE;
180 }
181
182 METHOD(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
188 METHOD(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
194 METHOD(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
200 METHOD(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
206 METHOD(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
212 METHOD(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
218 METHOD(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
224 METHOD(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
230 METHOD(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
236 METHOD(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
242 METHOD(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
248 METHOD(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
254 METHOD(bio_reader_t, read_data8, bool,
255 private_bio_reader_t *this, chunk_t *res)
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
266 METHOD(bio_reader_t, read_data16, bool,
267 private_bio_reader_t *this, chunk_t *res)
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
278 METHOD(bio_reader_t, read_data24, bool,
279 private_bio_reader_t *this, chunk_t *res)
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
290 METHOD(bio_reader_t, read_data32, bool,
291 private_bio_reader_t *this, chunk_t *res)
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
302 METHOD(bio_reader_t, destroy, void,
303 private_bio_reader_t *this)
304 {
305 free(this);
306 }
307
308 /**
309 * See header
310 */
311 bio_reader_t *bio_reader_create(chunk_t data)
312 {
313 private_bio_reader_t *this;
314
315 INIT(this,
316 .public = {
317 .remaining = _remaining,
318 .peek = _peek,
319 .read_uint8 = _read_uint8,
320 .read_uint16 = _read_uint16,
321 .read_uint24 = _read_uint24,
322 .read_uint32 = _read_uint32,
323 .read_uint64 = _read_uint64,
324 .read_data = _read_data,
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,
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 }