summaryrefslogtreecommitdiff
path: root/src/libstrongswan/bio
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/bio')
-rw-r--r--src/libstrongswan/bio/bio_reader.c174
-rw-r--r--src/libstrongswan/bio/bio_reader.h54
-rw-r--r--src/libstrongswan/bio/bio_writer.c28
-rw-r--r--src/libstrongswan/bio/bio_writer.h25
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);