Annotation of embedaddon/strongswan/src/libstrongswan/bio/bio_reader.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012 Tobias Brunner
3: * HSR 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: * Optional data to free during destruction
42: */
43: chunk_t cleanup;
44: };
45:
46: METHOD(bio_reader_t, remaining, uint32_t,
47: private_bio_reader_t *this)
48: {
49: return this->buf.len;
50: }
51:
52: METHOD(bio_reader_t, peek, chunk_t,
53: private_bio_reader_t *this)
54: {
55: return this->buf;
56: }
57:
58: /**
59: * A version of chunk_skip() that supports skipping from the end (i.e. simply
60: * reducing the size)
61: */
62: static inline chunk_t chunk_skip_end(chunk_t chunk, size_t bytes, bool from_end)
63: {
64: if (chunk.len > bytes)
65: {
66: if (!from_end)
67: {
68: chunk.ptr += bytes;
69: }
70: chunk.len -= bytes;
71: return chunk;
72: }
73: return chunk_empty;
74: }
75:
76: /**
77: * Returns a pointer to the data to read, optionally from the end
78: */
79: static inline u_char *get_ptr_end(private_bio_reader_t *this, uint32_t len,
80: bool from_end)
81: {
82: return from_end ? this->buf.ptr + (this->buf.len - len) : this->buf.ptr;
83: }
84:
85: /**
86: * Read an uint8_t from the buffer, optionally from the end of the buffer
87: */
88: static bool read_uint8_internal(private_bio_reader_t *this, uint8_t *res,
89: bool from_end)
90: {
91: if (this->buf.len < 1)
92: {
93: DBG1(DBG_LIB, "%d bytes insufficient to parse u_int8 data",
94: this->buf.len);
95: return FALSE;
96: }
97: *res = *get_ptr_end(this, 1, from_end);
98: this->buf = chunk_skip_end(this->buf, 1, from_end);
99: return TRUE;
100: }
101:
102: /**
103: * Read an uint16_t from the buffer, optionally from the end
104: */
105: static bool read_uint16_internal(private_bio_reader_t *this, uint16_t *res,
106: bool from_end)
107: {
108: if (this->buf.len < 2)
109: {
110: DBG1(DBG_LIB, "%d bytes insufficient to parse u_int16 data",
111: this->buf.len);
112: return FALSE;
113: }
114: *res = untoh16(get_ptr_end(this, 2, from_end));
115: this->buf = chunk_skip_end(this->buf, 2, from_end);
116: return TRUE;
117: }
118:
119: /**
120: * Read an uint32_t (only 24-bit) from the buffer, optionally from the end
121: */
122: static bool read_uint24_internal(private_bio_reader_t *this, uint32_t *res,
123: bool from_end)
124: {
125: uint32_t tmp;
126:
127: if (this->buf.len < 3)
128: {
129: DBG1(DBG_LIB, "%d bytes insufficient to parse u_int24 data",
130: this->buf.len);
131: return FALSE;
132: }
133: memcpy(&tmp, get_ptr_end(this, 3, from_end), 3);
134: *res = ntohl(tmp) >> 8;
135: this->buf = chunk_skip_end(this->buf, 3, from_end);
136: return TRUE;
137: }
138:
139: /**
140: * Read an uint32_t from the buffer, optionally from the end
141: */
142: static bool read_uint32_internal(private_bio_reader_t *this, uint32_t *res,
143: bool from_end)
144: {
145: if (this->buf.len < 4)
146: {
147: DBG1(DBG_LIB, "%d bytes insufficient to parse u_int32 data",
148: this->buf.len);
149: return FALSE;
150: }
151: *res = untoh32(get_ptr_end(this, 4, from_end));
152: this->buf = chunk_skip_end(this->buf, 4, from_end);
153: return TRUE;
154: }
155:
156: /**
157: * Read an uint64_t from the buffer, optionally from the end
158: */
159: static bool read_uint64_internal(private_bio_reader_t *this, uint64_t *res,
160: bool from_end)
161: {
162: if (this->buf.len < 8)
163: {
164: DBG1(DBG_LIB, "%d bytes insufficient to parse u_int64 data",
165: this->buf.len);
166: return FALSE;
167: }
168: *res = untoh64(get_ptr_end(this, 8, from_end));
169: this->buf = chunk_skip_end(this->buf, 8, from_end);
170: return TRUE;
171: }
172:
173: /**
174: * Read a chunk of data from the buffer, optionally from the end
175: */
176: static bool read_data_internal(private_bio_reader_t *this, uint32_t len,
177: chunk_t *res, bool from_end)
178: {
179: if (this->buf.len < len)
180: {
181: DBG1(DBG_LIB, "%d bytes insufficient to parse %d bytes of data",
182: this->buf.len, len);
183: return FALSE;
184: }
185: *res = chunk_create(get_ptr_end(this, len, from_end), len);
186: this->buf = chunk_skip_end(this->buf, len, from_end);
187: return TRUE;
188: }
189:
190: METHOD(bio_reader_t, read_uint8, bool,
191: private_bio_reader_t *this, uint8_t *res)
192: {
193: return read_uint8_internal(this, res, FALSE);
194: }
195:
196: METHOD(bio_reader_t, read_uint16, bool,
197: private_bio_reader_t *this, uint16_t *res)
198: {
199: return read_uint16_internal(this, res, FALSE);
200: }
201:
202: METHOD(bio_reader_t, read_uint24, bool,
203: private_bio_reader_t *this, uint32_t *res)
204: {
205: return read_uint24_internal(this, res, FALSE);
206: }
207:
208: METHOD(bio_reader_t, read_uint32, bool,
209: private_bio_reader_t *this, uint32_t *res)
210: {
211: return read_uint32_internal(this, res, FALSE);
212: }
213:
214: METHOD(bio_reader_t, read_uint64, bool,
215: private_bio_reader_t *this, uint64_t *res)
216: {
217: return read_uint64_internal(this, res, FALSE);
218: }
219:
220: METHOD(bio_reader_t, read_data, bool,
221: private_bio_reader_t *this, uint32_t len, chunk_t *res)
222: {
223: return read_data_internal(this, len, res, FALSE);
224: }
225:
226: METHOD(bio_reader_t, read_uint8_end, bool,
227: private_bio_reader_t *this, uint8_t *res)
228: {
229: return read_uint8_internal(this, res, TRUE);
230: }
231:
232: METHOD(bio_reader_t, read_uint16_end, bool,
233: private_bio_reader_t *this, uint16_t *res)
234: {
235: return read_uint16_internal(this, res, TRUE);
236: }
237:
238: METHOD(bio_reader_t, read_uint24_end, bool,
239: private_bio_reader_t *this, uint32_t *res)
240: {
241: return read_uint24_internal(this, res, TRUE);
242: }
243:
244: METHOD(bio_reader_t, read_uint32_end, bool,
245: private_bio_reader_t *this, uint32_t *res)
246: {
247: return read_uint32_internal(this, res, TRUE);
248: }
249:
250: METHOD(bio_reader_t, read_uint64_end, bool,
251: private_bio_reader_t *this, uint64_t *res)
252: {
253: return read_uint64_internal(this, res, TRUE);
254: }
255:
256: METHOD(bio_reader_t, read_data_end, bool,
257: private_bio_reader_t *this, uint32_t len, chunk_t *res)
258: {
259: return read_data_internal(this, len, res, TRUE);
260: }
261:
262: METHOD(bio_reader_t, read_data8, bool,
263: private_bio_reader_t *this, chunk_t *res)
264: {
265: uint8_t len;
266:
267: if (!read_uint8(this, &len))
268: {
269: return FALSE;
270: }
271: return read_data(this, len, res);
272: }
273:
274: METHOD(bio_reader_t, read_data16, bool,
275: private_bio_reader_t *this, chunk_t *res)
276: {
277: uint16_t len;
278:
279: if (!read_uint16(this, &len))
280: {
281: return FALSE;
282: }
283: return read_data(this, len, res);
284: }
285:
286: METHOD(bio_reader_t, read_data24, bool,
287: private_bio_reader_t *this, chunk_t *res)
288: {
289: uint32_t len;
290:
291: if (!read_uint24(this, &len))
292: {
293: return FALSE;
294: }
295: return read_data(this, len, res);
296: }
297:
298: METHOD(bio_reader_t, read_data32, bool,
299: private_bio_reader_t *this, chunk_t *res)
300: {
301: uint32_t len;
302:
303: if (!read_uint32(this, &len))
304: {
305: return FALSE;
306: }
307: return read_data(this, len, res);
308: }
309:
310: METHOD(bio_reader_t, destroy, void,
311: private_bio_reader_t *this)
312: {
313: free(this->cleanup.ptr);
314: free(this);
315: }
316:
317: /**
318: * See header
319: */
320: bio_reader_t *bio_reader_create(chunk_t data)
321: {
322: private_bio_reader_t *this;
323:
324: INIT(this,
325: .public = {
326: .remaining = _remaining,
327: .peek = _peek,
328: .read_uint8 = _read_uint8,
329: .read_uint16 = _read_uint16,
330: .read_uint24 = _read_uint24,
331: .read_uint32 = _read_uint32,
332: .read_uint64 = _read_uint64,
333: .read_data = _read_data,
334: .read_uint8_end = _read_uint8_end,
335: .read_uint16_end = _read_uint16_end,
336: .read_uint24_end = _read_uint24_end,
337: .read_uint32_end = _read_uint32_end,
338: .read_uint64_end = _read_uint64_end,
339: .read_data_end = _read_data_end,
340: .read_data8 = _read_data8,
341: .read_data16 = _read_data16,
342: .read_data24 = _read_data24,
343: .read_data32 = _read_data32,
344: .destroy = _destroy,
345: },
346: .buf = data,
347: );
348:
349: return &this->public;
350: }
351:
352: /**
353: * See header
354: */
355: bio_reader_t *bio_reader_create_own(chunk_t data)
356: {
357: private_bio_reader_t *this;
358:
359: this = (private_bio_reader_t*)bio_reader_create(data);
360:
361: this->cleanup = data;
362:
363: return &this->public;
364: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>