diff options
author | Michael Brown | 2013-01-30 17:58:17 +0100 |
---|---|---|
committer | Michael Brown | 2013-01-31 10:59:36 +0100 |
commit | 0acc52519de732f4f010e1029e1308cee825eaed (patch) | |
tree | fec736bad239f85a595b08e7251a4808eae35cbb /src/core/iobuf.c | |
parent | [src] Fix spelling in comments, debug messages and local variable names (diff) | |
download | ipxe-0acc52519de732f4f010e1029e1308cee825eaed.tar.gz ipxe-0acc52519de732f4f010e1029e1308cee825eaed.tar.xz ipxe-0acc52519de732f4f010e1029e1308cee825eaed.zip |
[tls] Concatenate received non-data records before processing
Allow non-data records to be split across multiple received I/O
buffers, to accommodate large certificate chains.
Reported-by: Nicola Volpini <Nicola.Volpini@kambi.com>
Tested-by: Nicola Volpini <Nicola.Volpini@kambi.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core/iobuf.c')
-rw-r--r-- | src/core/iobuf.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/core/iobuf.c b/src/core/iobuf.c index 3f67d2f5..afc91d15 100644 --- a/src/core/iobuf.c +++ b/src/core/iobuf.c @@ -158,3 +158,45 @@ int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) { return -ENOBUFS; } +/** + * Concatenate I/O buffers into a single buffer + * + * @v list List of I/O buffers + * @ret iobuf Concatenated I/O buffer, or NULL on allocation failure + * + * After a successful concatenation, the list will be empty. + */ +struct io_buffer * iob_concatenate ( struct list_head *list ) { + struct io_buffer *iobuf; + struct io_buffer *tmp; + struct io_buffer *concatenated; + size_t len = 0; + + /* If the list contains only a single entry, avoid an + * unnecessary additional allocation. + */ + if ( list_is_singular ( list ) ) { + iobuf = list_first_entry ( list, struct io_buffer, list ); + INIT_LIST_HEAD ( list ); + return iobuf; + } + + /* Calculate total length */ + list_for_each_entry ( iobuf, list, list ) + len += iob_len ( iobuf ); + + /* Allocate new I/O buffer */ + concatenated = alloc_iob_raw ( len, __alignof__ ( *iobuf ), 0 ); + if ( ! concatenated ) + return NULL; + + /* Move data to new I/O buffer */ + list_for_each_entry_safe ( iobuf, tmp, list, list ) { + list_del ( &iobuf->list ); + memcpy ( iob_put ( concatenated, iob_len ( iobuf ) ), + iobuf->data, iob_len ( iobuf ) ); + free_iob ( iobuf ); + } + + return concatenated; +} |