diff options
Diffstat (limited to 'src/libstrongswan/bio')
-rw-r--r-- | src/libstrongswan/bio/bio_reader.c | 215 | ||||
-rw-r--r-- | src/libstrongswan/bio/bio_reader.h | 139 | ||||
-rw-r--r-- | src/libstrongswan/bio/bio_writer.c | 249 | ||||
-rw-r--r-- | src/libstrongswan/bio/bio_writer.h | 143 |
4 files changed, 746 insertions, 0 deletions
diff --git a/src/libstrongswan/bio/bio_reader.c b/src/libstrongswan/bio/bio_reader.c new file mode 100644 index 000000000..fce0d1aef --- /dev/null +++ b/src/libstrongswan/bio/bio_reader.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "bio_reader.h" + +#include <debug.h> + +typedef struct private_bio_reader_t private_bio_reader_t; + +/** + * Private data of an bio_reader_t object. + */ +struct private_bio_reader_t { + + /** + * Public bio_reader_t interface. + */ + bio_reader_t public; + + /** + * Remaining data to process + */ + chunk_t buf; +}; + +METHOD(bio_reader_t, remaining, u_int32_t, + private_bio_reader_t *this) +{ + return this->buf.len; +} + +METHOD(bio_reader_t, peek, chunk_t, + private_bio_reader_t *this) +{ + return this->buf; +} + +METHOD(bio_reader_t, read_uint8, bool, + private_bio_reader_t *this, u_int8_t *res) +{ + if (this->buf.len < 1) + { + DBG1(DBG_LIB, "%d bytes insufficient to parse u_int8 data", + this->buf.len); + return FALSE; + } + *res = this->buf.ptr[0]; + this->buf = chunk_skip(this->buf, 1); + return TRUE; +} + +METHOD(bio_reader_t, read_uint16, bool, + private_bio_reader_t *this, u_int16_t *res) +{ + if (this->buf.len < 2) + { + DBG1(DBG_LIB, "%d bytes insufficient to parse u_int16 data", + this->buf.len); + return FALSE; + } + *res = untoh16(this->buf.ptr); + this->buf = chunk_skip(this->buf, 2); + return TRUE; +} + +METHOD(bio_reader_t, read_uint24, bool, + private_bio_reader_t *this, u_int32_t *res) +{ + if (this->buf.len < 3) + { + DBG1(DBG_LIB, "%d bytes insufficient to parse u_int24 data", + this->buf.len); + return FALSE; + } + *res = untoh32(this->buf.ptr) >> 8; + this->buf = chunk_skip(this->buf, 3); + return TRUE; +} + +METHOD(bio_reader_t, read_uint32, bool, + private_bio_reader_t *this, u_int32_t *res) +{ + if (this->buf.len < 4) + { + DBG1(DBG_LIB, "%d bytes insufficient to parse u_int32 data", + this->buf.len); + return FALSE; + } + *res = untoh32(this->buf.ptr); + this->buf = chunk_skip(this->buf, 4); + return TRUE; +} + +METHOD(bio_reader_t, read_uint64, bool, + private_bio_reader_t *this, u_int64_t *res) +{ + if (this->buf.len < 8) + { + DBG1(DBG_LIB, "%d bytes insufficient to parse u_int64 data", + this->buf.len); + return FALSE; + } + *res = untoh64(this->buf.ptr); + this->buf = chunk_skip(this->buf, 8); + return TRUE; +} + +METHOD(bio_reader_t, read_data, bool, + private_bio_reader_t *this, u_int32_t len, chunk_t *res) +{ + if (this->buf.len < len) + { + DBG1(DBG_LIB, "%d bytes insufficient to parse %d bytes of data", + this->buf.len, len); + return FALSE; + } + *res = chunk_create(this->buf.ptr, len); + this->buf = chunk_skip(this->buf, len); + return TRUE; +} + +METHOD(bio_reader_t, read_data8, bool, + private_bio_reader_t *this, chunk_t *res) +{ + u_int8_t len; + + if (!read_uint8(this, &len)) + { + return FALSE; + } + return read_data(this, len, res); +} + +METHOD(bio_reader_t, read_data16, bool, + private_bio_reader_t *this, chunk_t *res) +{ + u_int16_t len; + + if (!read_uint16(this, &len)) + { + return FALSE; + } + return read_data(this, len, res); +} + +METHOD(bio_reader_t, read_data24, bool, + private_bio_reader_t *this, chunk_t *res) +{ + u_int32_t len; + + if (!read_uint24(this, &len)) + { + return FALSE; + } + return read_data(this, len, res); +} + +METHOD(bio_reader_t, read_data32, bool, + private_bio_reader_t *this, chunk_t *res) +{ + u_int32_t len; + + if (!read_uint32(this, &len)) + { + return FALSE; + } + return read_data(this, len, res); +} + +METHOD(bio_reader_t, destroy, void, + private_bio_reader_t *this) +{ + free(this); +} + +/** + * See header + */ +bio_reader_t *bio_reader_create(chunk_t data) +{ + private_bio_reader_t *this; + + INIT(this, + .public = { + .remaining = _remaining, + .peek = _peek, + .read_uint8 = _read_uint8, + .read_uint16 = _read_uint16, + .read_uint24 = _read_uint24, + .read_uint32 = _read_uint32, + .read_uint64 = _read_uint64, + .read_data = _read_data, + .read_data8 = _read_data8, + .read_data16 = _read_data16, + .read_data24 = _read_data24, + .read_data32 = _read_data32, + .destroy = _destroy, + }, + .buf = data, + ); + + return &this->public; +} diff --git a/src/libstrongswan/bio/bio_reader.h b/src/libstrongswan/bio/bio_reader.h new file mode 100644 index 000000000..85434a784 --- /dev/null +++ b/src/libstrongswan/bio/bio_reader.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup bio_reader bio_reader + * @{ @ingroup bio + */ + +#ifndef BIO_READER_H_ +#define BIO_READER_H_ + +typedef struct bio_reader_t bio_reader_t; + +#include <library.h> + +/** + * Buffered input parser. + */ +struct bio_reader_t { + + /** + * Get the number of remaining bytes. + * + * @return number of remaining bytes in buffer + */ + u_int32_t (*remaining)(bio_reader_t *this); + + /** + * Peek the remaining data, not consuming any bytes. + * + * @return remaining data + */ + chunk_t (*peek)(bio_reader_t *this); + + /** + * Read a 8-bit integer from the buffer, advance. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint8)(bio_reader_t *this, u_int8_t *res); + + /** + * Read a 16-bit integer from the buffer, advance. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint16)(bio_reader_t *this, u_int16_t *res); + + /** + * Read a 24-bit integer from the buffer, advance. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint24)(bio_reader_t *this, u_int32_t *res); + + /** + * Read a 32-bit integer from the buffer, advance. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint32)(bio_reader_t *this, u_int32_t *res); + + /** + * Read a 64-bit integer from the buffer, advance. + * + * @param res pointer to result + * @return TRUE if integer read successfully + */ + bool (*read_uint64)(bio_reader_t *this, u_int64_t *res); + + /** + * Read a chunk of len bytes, advance. + * + * @param len number of bytes to read + * @param res pointer to result, not cloned + * @return TRUE if data read successfully + */ + bool (*read_data)(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 + * @return TRUE if data read successfully + */ + bool (*read_data8)(bio_reader_t *this, chunk_t *res); + + /** + * Read a chunk of bytes with a 16-bit length header, advance. + * + * @param res pointer to result, not cloned + * @return TRUE if data read successfully + */ + bool (*read_data16)(bio_reader_t *this, chunk_t *res); + + /** + * Read a chunk of bytes with a 24-bit length header, advance. + * + * @param res pointer to result, not cloned + * @return TRUE if data read successfully + */ + bool (*read_data24)(bio_reader_t *this, chunk_t *res); + + /** + * Read a chunk of bytes with a 32-bit length header, advance. + * + * @param res pointer to result, not cloned + * @return TRUE if data read successfully + */ + bool (*read_data32)(bio_reader_t *this, chunk_t *res); + + /** + * Destroy a bio_reader_t. + */ + void (*destroy)(bio_reader_t *this); +}; + +/** + * Create a bio_reader instance. + */ +bio_reader_t *bio_reader_create(chunk_t data); + +#endif /** bio_reader_H_ @}*/ diff --git a/src/libstrongswan/bio/bio_writer.c b/src/libstrongswan/bio/bio_writer.c new file mode 100644 index 000000000..bf373d6ac --- /dev/null +++ b/src/libstrongswan/bio/bio_writer.c @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "bio_writer.h" + +typedef struct private_bio_writer_t private_bio_writer_t; + +/** + * Private data of an bio_writer_t object. + */ +struct private_bio_writer_t { + + /** + * Public bio_writer_t interface. + */ + bio_writer_t public; + + /** + * Allocated buffer + */ + chunk_t buf; + + /** + * Used bytes in buffer + */ + size_t used; + + /** + * Number of bytes to increase buffer size + */ + size_t increase; +}; + +/** + * Increase buffer size + */ +static void increase(private_bio_writer_t *this) +{ + this->buf.len += this->increase; + this->buf.ptr = realloc(this->buf.ptr, this->buf.len); +} + +METHOD(bio_writer_t, write_uint8, void, + private_bio_writer_t *this, u_int8_t value) +{ + if (this->used + 1 > this->buf.len) + { + increase(this); + } + this->buf.ptr[this->used] = value; + this->used += 1; +} + +METHOD(bio_writer_t, write_uint16, void, + private_bio_writer_t *this, u_int16_t value) +{ + if (this->used + 2 > this->buf.len) + { + increase(this); + } + htoun16(this->buf.ptr + this->used, value); + this->used += 2; +} + +METHOD(bio_writer_t, write_uint24, void, + private_bio_writer_t *this, u_int32_t value) +{ + if (this->used + 3 > this->buf.len) + { + increase(this); + } + value = htonl(value); + memcpy(this->buf.ptr + this->used, ((char*)&value) + 1, 3); + this->used += 3; +} + +METHOD(bio_writer_t, write_uint32, void, + private_bio_writer_t *this, u_int32_t value) +{ + if (this->used + 4 > this->buf.len) + { + increase(this); + } + htoun32(this->buf.ptr + this->used, value); + this->used += 4; +} + +METHOD(bio_writer_t, write_uint64, void, + private_bio_writer_t *this, u_int64_t value) +{ + if (this->used + 8 > this->buf.len) + { + increase(this); + } + htoun64(this->buf.ptr + this->used, value); + this->used += 8; +} + +METHOD(bio_writer_t, write_data, void, + private_bio_writer_t *this, chunk_t value) +{ + while (this->used + value.len > this->buf.len) + { + increase(this); + } + memcpy(this->buf.ptr + this->used, value.ptr, value.len); + this->used += value.len; +} + +METHOD(bio_writer_t, write_data8, void, + private_bio_writer_t *this, chunk_t value) +{ + write_uint8(this, value.len); + write_data(this, value); +} + +METHOD(bio_writer_t, write_data16, void, + private_bio_writer_t *this, chunk_t value) +{ + write_uint16(this, value.len); + write_data(this, value); +} + +METHOD(bio_writer_t, write_data24, void, + private_bio_writer_t *this, chunk_t value) +{ + write_uint24(this, value.len); + write_data(this, value); +} + +METHOD(bio_writer_t, write_data32, void, + private_bio_writer_t *this, chunk_t value) +{ + write_uint32(this, value.len); + write_data(this, value); +} + +METHOD(bio_writer_t, wrap8, void, + private_bio_writer_t *this) +{ + if (this->used + 1 > this->buf.len) + { + increase(this); + } + memmove(this->buf.ptr + 1, this->buf.ptr, this->used); + this->buf.ptr[0] = this->used; + this->used += 1; +} + +METHOD(bio_writer_t, wrap16, void, + private_bio_writer_t *this) +{ + if (this->used + 2 > this->buf.len) + { + increase(this); + } + memmove(this->buf.ptr + 2, this->buf.ptr, this->used); + htoun16(this->buf.ptr, this->used); + this->used += 2; +} + +METHOD(bio_writer_t, wrap24, void, + private_bio_writer_t *this) +{ + u_int32_t len; + + if (this->used + 3 > this->buf.len) + { + increase(this); + } + memmove(this->buf.ptr + 3, this->buf.ptr, this->used); + + len = htonl(this->used); + memcpy(this->buf.ptr, ((char*)&len) + 1, 3); + this->used += 3; +} + +METHOD(bio_writer_t, wrap32, void, + private_bio_writer_t *this) +{ + if (this->used + 4 > this->buf.len) + { + increase(this); + } + memmove(this->buf.ptr + 4, this->buf.ptr, this->used); + htoun32(this->buf.ptr, this->used); + this->used += 4; +} + +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, destroy, void, + private_bio_writer_t *this) +{ + free(this->buf.ptr); + free(this); +} + +/** + * See header + */ +bio_writer_t *bio_writer_create(u_int32_t bufsize) +{ + private_bio_writer_t *this; + + INIT(this, + .public = { + .write_uint8 = _write_uint8, + .write_uint16 = _write_uint16, + .write_uint24 = _write_uint24, + .write_uint32 = _write_uint32, + .write_uint64 = _write_uint64, + .write_data = _write_data, + .write_data8 = _write_data8, + .write_data16 = _write_data16, + .write_data24 = _write_data24, + .write_data32 = _write_data32, + .wrap8 = _wrap8, + .wrap16 = _wrap16, + .wrap24 = _wrap24, + .wrap32 = _wrap32, + .get_buf = _get_buf, + .destroy = _destroy, + }, + .increase = bufsize ? max(bufsize, 4) : 32, + ); + if (bufsize) + { + this->buf = chunk_alloc(bufsize); + } + + return &this->public; +} diff --git a/src/libstrongswan/bio/bio_writer.h b/src/libstrongswan/bio/bio_writer.h new file mode 100644 index 000000000..0b50f7882 --- /dev/null +++ b/src/libstrongswan/bio/bio_writer.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup bio_writer bio_writer + * @{ @ingroup bio + */ + +#ifndef BIO_WRITER_H_ +#define BIO_WRITER_H_ + +typedef struct bio_writer_t bio_writer_t; + +#include <library.h> + +/** + * Buffered output generator. + */ +struct bio_writer_t { + + /** + * Append a 8-bit integer to the buffer. + * + * @param value value to append + */ + void (*write_uint8)(bio_writer_t *this, u_int8_t value); + + /** + * Append a 16-bit integer to the buffer. + * + * @param value value to append + */ + void (*write_uint16)(bio_writer_t *this, u_int16_t value); + + /** + * Append a 24-bit integer to the buffer. + * + * @param value value to append + */ + void (*write_uint24)(bio_writer_t *this, u_int32_t value); + + /** + * Append a 32-bit integer to the buffer. + * + * @param value value to append + */ + void (*write_uint32)(bio_writer_t *this, u_int32_t value); + + /** + * Append a 64-bit integer to the buffer. + * + * @param value value to append + */ + void (*write_uint64)(bio_writer_t *this, u_int64_t value); + + /** + * Append a chunk of data without a length header. + * + * @param value value to append + */ + void (*write_data)(bio_writer_t *this, chunk_t value); + + /** + * Append a chunk of data with a 8-bit length header. + * + * @param value value to append + */ + void (*write_data8)(bio_writer_t *this, chunk_t value); + + /** + * Append a chunk of data with a 16-bit length header. + * + * @param value value to append + */ + void (*write_data16)(bio_writer_t *this, chunk_t value); + + /** + * Append a chunk of data with a 24-bit length header. + * + * @param value value to append + */ + void (*write_data24)(bio_writer_t *this, chunk_t value); + + /** + * Append a chunk of data with a 32-bit length header. + * + * @param value value to append + */ + void (*write_data32)(bio_writer_t *this, chunk_t value); + + /** + * Prepend a 8-bit length header to existing data. + */ + void (*wrap8)(bio_writer_t *this); + + /** + * Prepend a 16-bit length header to existing data. + */ + void (*wrap16)(bio_writer_t *this); + + /** + * Prepend a 24-bit length header to existing data. + */ + void (*wrap24)(bio_writer_t *this); + + /** + * Prepend a 32-bit length header to existing data. + */ + void (*wrap32)(bio_writer_t *this); + + /** + * Get the encoded data buffer. + * + * @return chunk to internal buffer + */ + chunk_t (*get_buf)(bio_writer_t *this); + + /** + * Destroy a bio_writer_t. + */ + void (*destroy)(bio_writer_t *this); +}; + +/** + * Create a bio_writer instance. + * + * @param bufsize initially allocated buffer size + */ +bio_writer_t *bio_writer_create(u_int32_t bufsize); + +#endif /** BIO_WRITER_H_ @}*/ |