diff options
Diffstat (limited to 'src/libstrongswan/bio')
-rw-r--r-- | src/libstrongswan/bio/bio_reader.c | 174 | ||||
-rw-r--r-- | src/libstrongswan/bio/bio_reader.h | 54 | ||||
-rw-r--r-- | src/libstrongswan/bio/bio_writer.c | 28 | ||||
-rw-r--r-- | src/libstrongswan/bio/bio_writer.h | 25 |
4 files changed, 257 insertions, 24 deletions
diff --git a/src/libstrongswan/bio/bio_reader.c b/src/libstrongswan/bio/bio_reader.c index fce0d1aef..3a62bb541 100644 --- a/src/libstrongswan/bio/bio_reader.c +++ b/src/libstrongswan/bio/bio_reader.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -47,8 +50,38 @@ METHOD(bio_reader_t, peek, chunk_t, return this->buf; } -METHOD(bio_reader_t, read_uint8, bool, - private_bio_reader_t *this, u_int8_t *res) +/** + * A version of chunk_skip() that supports skipping from the end (i.e. simply + * reducing the size) + */ +static inline chunk_t chunk_skip_end(chunk_t chunk, size_t bytes, bool from_end) +{ + if (chunk.len > bytes) + { + if (!from_end) + { + chunk.ptr += bytes; + } + chunk.len -= bytes; + return chunk; + } + return chunk_empty; +} + +/** + * Returns a pointer to the data to read, optionally from the end + */ +static inline u_char *get_ptr_end(private_bio_reader_t *this, u_int32_t len, + bool from_end) +{ + return from_end ? this->buf.ptr + (this->buf.len - len) : this->buf.ptr; +} + +/** + * Read an u_int8_t from the buffer, optionally from the end of the buffer + */ +static bool read_uint8_internal(private_bio_reader_t *this, u_int8_t *res, + bool from_end) { if (this->buf.len < 1) { @@ -56,13 +89,16 @@ METHOD(bio_reader_t, read_uint8, bool, this->buf.len); return FALSE; } - *res = this->buf.ptr[0]; - this->buf = chunk_skip(this->buf, 1); + *res = *get_ptr_end(this, 1, from_end); + this->buf = chunk_skip_end(this->buf, 1, from_end); return TRUE; } -METHOD(bio_reader_t, read_uint16, bool, - private_bio_reader_t *this, u_int16_t *res) +/** + * Read an u_int16_t from the buffer, optionally from the end + */ +static bool read_uint16_internal(private_bio_reader_t *this, u_int16_t *res, + bool from_end) { if (this->buf.len < 2) { @@ -70,13 +106,16 @@ METHOD(bio_reader_t, read_uint16, bool, this->buf.len); return FALSE; } - *res = untoh16(this->buf.ptr); - this->buf = chunk_skip(this->buf, 2); + *res = untoh16(get_ptr_end(this, 2, from_end)); + this->buf = chunk_skip_end(this->buf, 2, from_end); return TRUE; } -METHOD(bio_reader_t, read_uint24, bool, - private_bio_reader_t *this, u_int32_t *res) +/** + * Read an u_int32_t (only 24-bit) from the buffer, optionally from the end + */ +static bool read_uint24_internal(private_bio_reader_t *this, u_int32_t *res, + bool from_end) { if (this->buf.len < 3) { @@ -84,13 +123,16 @@ METHOD(bio_reader_t, read_uint24, bool, this->buf.len); return FALSE; } - *res = untoh32(this->buf.ptr) >> 8; - this->buf = chunk_skip(this->buf, 3); + *res = untoh32(get_ptr_end(this, 3, from_end)) >> 8; + this->buf = chunk_skip_end(this->buf, 3, from_end); return TRUE; } -METHOD(bio_reader_t, read_uint32, bool, - private_bio_reader_t *this, u_int32_t *res) +/** + * Read an u_int32_t from the buffer, optionally from the end + */ +static bool read_uint32_internal(private_bio_reader_t *this, u_int32_t *res, + bool from_end) { if (this->buf.len < 4) { @@ -98,13 +140,16 @@ METHOD(bio_reader_t, read_uint32, bool, this->buf.len); return FALSE; } - *res = untoh32(this->buf.ptr); - this->buf = chunk_skip(this->buf, 4); + *res = untoh32(get_ptr_end(this, 4, from_end)); + this->buf = chunk_skip_end(this->buf, 4, from_end); return TRUE; } -METHOD(bio_reader_t, read_uint64, bool, - private_bio_reader_t *this, u_int64_t *res) +/** + * Read an u_int64_t from the buffer, optionally from the end + */ +static bool read_uint64_internal(private_bio_reader_t *this, u_int64_t *res, + bool from_end) { if (this->buf.len < 8) { @@ -112,13 +157,16 @@ METHOD(bio_reader_t, read_uint64, bool, this->buf.len); return FALSE; } - *res = untoh64(this->buf.ptr); - this->buf = chunk_skip(this->buf, 8); + *res = untoh64(get_ptr_end(this, 8, from_end)); + this->buf = chunk_skip_end(this->buf, 8, from_end); return TRUE; } -METHOD(bio_reader_t, read_data, bool, - private_bio_reader_t *this, u_int32_t len, chunk_t *res) +/** + * Read a chunk of data from the buffer, optionally from the end + */ +static bool read_data_internal(private_bio_reader_t *this, u_int32_t len, + chunk_t *res, bool from_end) { if (this->buf.len < len) { @@ -126,11 +174,83 @@ METHOD(bio_reader_t, read_data, bool, this->buf.len, len); return FALSE; } - *res = chunk_create(this->buf.ptr, len); - this->buf = chunk_skip(this->buf, len); + *res = chunk_create(get_ptr_end(this, len, from_end), len); + this->buf = chunk_skip_end(this->buf, len, from_end); return TRUE; } +METHOD(bio_reader_t, read_uint8, bool, + private_bio_reader_t *this, u_int8_t *res) +{ + return read_uint8_internal(this, res, FALSE); +} + +METHOD(bio_reader_t, read_uint16, bool, + private_bio_reader_t *this, u_int16_t *res) +{ + return read_uint16_internal(this, res, FALSE); +} + +METHOD(bio_reader_t, read_uint24, bool, + private_bio_reader_t *this, u_int32_t *res) +{ + return read_uint24_internal(this, res, FALSE); +} + +METHOD(bio_reader_t, read_uint32, bool, + private_bio_reader_t *this, u_int32_t *res) +{ + return read_uint32_internal(this, res, FALSE); +} + +METHOD(bio_reader_t, read_uint64, bool, + private_bio_reader_t *this, u_int64_t *res) +{ + return read_uint64_internal(this, res, FALSE); +} + +METHOD(bio_reader_t, read_data, bool, + private_bio_reader_t *this, u_int32_t len, chunk_t *res) +{ + return read_data_internal(this, len, res, FALSE); +} + +METHOD(bio_reader_t, read_uint8_end, bool, + private_bio_reader_t *this, u_int8_t *res) +{ + return read_uint8_internal(this, res, TRUE); +} + +METHOD(bio_reader_t, read_uint16_end, bool, + private_bio_reader_t *this, u_int16_t *res) +{ + return read_uint16_internal(this, res, TRUE); +} + +METHOD(bio_reader_t, read_uint24_end, bool, + private_bio_reader_t *this, u_int32_t *res) +{ + return read_uint24_internal(this, res, TRUE); +} + +METHOD(bio_reader_t, read_uint32_end, bool, + private_bio_reader_t *this, u_int32_t *res) +{ + return read_uint32_internal(this, res, TRUE); +} + +METHOD(bio_reader_t, read_uint64_end, bool, + private_bio_reader_t *this, u_int64_t *res) +{ + return read_uint64_internal(this, res, TRUE); +} + +METHOD(bio_reader_t, read_data_end, bool, + private_bio_reader_t *this, u_int32_t len, chunk_t *res) +{ + return read_data_internal(this, len, res, TRUE); +} + METHOD(bio_reader_t, read_data8, bool, private_bio_reader_t *this, chunk_t *res) { @@ -202,6 +322,12 @@ bio_reader_t *bio_reader_create(chunk_t data) .read_uint32 = _read_uint32, .read_uint64 = _read_uint64, .read_data = _read_data, + .read_uint8_end = _read_uint8_end, + .read_uint16_end = _read_uint16_end, + .read_uint24_end = _read_uint24_end, + .read_uint32_end = _read_uint32_end, + .read_uint64_end = _read_uint64_end, + .read_data_end = _read_data_end, .read_data8 = _read_data8, .read_data16 = _read_data16, .read_data24 = _read_data24, diff --git a/src/libstrongswan/bio/bio_reader.h b/src/libstrongswan/bio/bio_reader.h index 85434a784..3162f3eda 100644 --- a/src/libstrongswan/bio/bio_reader.h +++ b/src/libstrongswan/bio/bio_reader.h @@ -1,4 +1,7 @@ /* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -27,6 +30,8 @@ typedef struct bio_reader_t bio_reader_t; /** * Buffered input parser. + * + * @note Integers are returned in host byte order. */ struct bio_reader_t { @@ -94,6 +99,55 @@ struct bio_reader_t { bool (*read_data)(bio_reader_t *this, u_int32_t len, chunk_t *res); /** + * Read a 8-bit integer from the end of the buffer, reduce remaining. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint8_end)(bio_reader_t *this, u_int8_t *res); + + /** + * Read a 16-bit integer from the end of the buffer, reduce remaining. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint16_end)(bio_reader_t *this, u_int16_t *res); + + /** + * Read a 24-bit integer from the end of the buffer, reduce remaining. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint24_end)(bio_reader_t *this, u_int32_t *res); + + /** + * Read a 32-bit integer from the end of the buffer, reduce remaining. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint32_end)(bio_reader_t *this, u_int32_t *res); + + /** + * Read a 64-bit integer from the end of the buffer, reduce remaining. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint64_end)(bio_reader_t *this, u_int64_t *res); + + /** + * Read a chunk of len bytes from the end of the buffer, reduce remaining. + * + * @param len number of bytes to read + * @param res ponter to result, not cloned + * @return TRUE if data read successfully + */ + bool (*read_data_end)(bio_reader_t *this, u_int32_t len, chunk_t *res); + + /** * Read a chunk of bytes with a 8-bit length header, advance. * * @param res pointer to result, not cloned diff --git a/src/libstrongswan/bio/bio_writer.c b/src/libstrongswan/bio/bio_writer.c index bf373d6ac..8576843ee 100644 --- a/src/libstrongswan/bio/bio_writer.c +++ b/src/libstrongswan/bio/bio_writer.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -199,12 +202,35 @@ METHOD(bio_writer_t, wrap32, void, this->used += 4; } +METHOD(bio_writer_t, skip, chunk_t, + private_bio_writer_t *this, size_t len) +{ + chunk_t skipped; + + while (this->used + len > this->buf.len) + { + increase(this); + } + skipped = chunk_create(this->buf.ptr + this->used, len); + this->used += len; + return skipped; +} + METHOD(bio_writer_t, get_buf, chunk_t, private_bio_writer_t *this) { return chunk_create(this->buf.ptr, this->used); } +METHOD(bio_writer_t, extract_buf, chunk_t, + private_bio_writer_t *this) +{ + chunk_t buf = get_buf(this); + this->buf = chunk_empty; + this->used = 0; + return buf; +} + METHOD(bio_writer_t, destroy, void, private_bio_writer_t *this) { @@ -235,7 +261,9 @@ bio_writer_t *bio_writer_create(u_int32_t bufsize) .wrap16 = _wrap16, .wrap24 = _wrap24, .wrap32 = _wrap32, + .skip = _skip, .get_buf = _get_buf, + .extract_buf = _extract_buf, .destroy = _destroy, }, .increase = bufsize ? max(bufsize, 4) : 32, diff --git a/src/libstrongswan/bio/bio_writer.h b/src/libstrongswan/bio/bio_writer.h index 0b50f7882..57a5c3d38 100644 --- a/src/libstrongswan/bio/bio_writer.h +++ b/src/libstrongswan/bio/bio_writer.h @@ -1,4 +1,7 @@ /* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -27,6 +30,8 @@ typedef struct bio_writer_t bio_writer_t; /** * Buffered output generator. + * + * @note Integers are converted to network byte order before writing. */ struct bio_writer_t { @@ -121,6 +126,15 @@ struct bio_writer_t { void (*wrap32)(bio_writer_t *this); /** + * Skips len bytes in the buffer before the next data is written, returns + * a chunk covering the skipped bytes. + * + * @param len number of bytes to skip + * @return chunk pointing to skipped bytes in the internal buffer + */ + chunk_t (*skip)(bio_writer_t *this, size_t len); + + /** * Get the encoded data buffer. * * @return chunk to internal buffer @@ -128,6 +142,14 @@ struct bio_writer_t { chunk_t (*get_buf)(bio_writer_t *this); /** + * Return the encoded data buffer and detach it from the writer (resets + * the internal buffer). + * + * @return chunk to internal buffer (has to be freed) + */ + chunk_t (*extract_buf)(bio_writer_t *this); + + /** * Destroy a bio_writer_t. */ void (*destroy)(bio_writer_t *this); @@ -136,6 +158,9 @@ struct bio_writer_t { /** * Create a bio_writer instance. * + * The size of the internal buffer is increased automatically by bufsize (or a + * default if not given) if the initial size does not suffice. + * * @param bufsize initially allocated buffer size */ bio_writer_t *bio_writer_create(u_int32_t bufsize); |