diff --git a/examples/pcapread.c b/examples/pcapread.c index 09ecf95..468695f 100644 --- a/examples/pcapread.c +++ b/examples/pcapread.c @@ -23,14 +23,43 @@ static void usage(int argc, char **argv, const char *message, ...) { exit(1); } +static ssize_t handle_options(hexagram_pcapng_stream *stream, + uint32_t type, + uint16_t code, + uint16_t len) { + ssize_t readlen; + uint8_t data[65535]; + + if ((readlen = read(stream->fd, data, (size_t)len)) < 0) { + goto error_io; + } + + if (type == HEXAGRAM_PCAPNG_BLOCK_IF) { + if (code == HEXAGRAM_PCAPNG_OPTION_IF_TSRESOL) { + stream->if_tsresol = data[0]; + } + } + + stream->error = HEXAGRAM_PCAPNG_ERROR_OK; + + return readlen; + +error_io: + stream->error = HEXAGRAM_PCAPNG_ERROR_IO; + + return -1; +} + static ssize_t handle_block(hexagram_pcapng_stream *stream, uint32_t type, size_t len) { hexagram_pcapng_packet header; uint8_t body[65535]; - ssize_t readlen, - remaining = len; + size_t remaining = len; + + ssize_t total = 0, + readlen; /* * If we've received anything other than a packet block, then seek past @@ -40,13 +69,13 @@ static ssize_t handle_block(hexagram_pcapng_stream *stream, printf("Read block type %08"PRIx32" len %zu\n", type, len); - if (lseek(stream->fd, len, SEEK_CUR) < 0) { + if ((readlen = lseek(stream->fd, len, SEEK_CUR)) < 0) { perror("lseek()"); goto error_io; } - return 0; + return readlen; } /* @@ -59,6 +88,7 @@ static ssize_t handle_block(hexagram_pcapng_stream *stream, goto error_io; } else { remaining -= readlen; + total += readlen; } /* @@ -70,24 +100,38 @@ static ssize_t handle_block(hexagram_pcapng_stream *stream, goto error_io; } else { remaining -= readlen; + total += readlen; } printf("Read packet %"PRIu32" bytes time hi %"PRIu32" lo %"PRIu32"\n", header.caplen, header.timestamp[0], header.timestamp[1]); + if (header.caplen % sizeof(uint32_t)) { + size_t padding = sizeof(uint32_t) - (header.caplen % sizeof(uint32_t)); + + if (lseek(stream->fd, padding, SEEK_CUR) < 0) { + perror("lseek()"); + + goto error_io; + } else { + remaining -= padding; + total += padding; + } + } + /* * The remaining data here should be pcapng option values, and since we do * not presently require them, we can safely seek past them. */ - if (lseek(stream->fd, remaining, SEEK_CUR) < 0) { - perror("lseek()"); - + if ((readlen = hexagram_pcapng_read_options(stream, handle_options, type, remaining)) < 0) { goto error_io; + } else { + total += readlen; } stream->error = HEXAGRAM_PCAPNG_ERROR_OK; - return 0; + return total; error_io: stream->error = HEXAGRAM_PCAPNG_ERROR_IO; diff --git a/include/hexagram/pcapng.h b/include/hexagram/pcapng.h index ff319b4..39e52ad 100644 --- a/include/hexagram/pcapng.h +++ b/include/hexagram/pcapng.h @@ -24,7 +24,7 @@ typedef ssize_t (hexagram_pcapng_block_handler)(hexagram_pcapng_stream *, size_t length); typedef ssize_t (hexagram_pcapng_option_handler)(hexagram_pcapng_stream *, - hexagram_pcapng_block_header *, + uint32_t type, uint16_t code, uint16_t length); @@ -35,4 +35,9 @@ void hexagram_pcapng_stream_destroy(hexagram_pcapng_stream *stream); ssize_t hexagram_pcapng_stream_read(hexagram_pcapng_stream *stream, hexagram_pcapng_block_handler *handler); +ssize_t hexagram_pcapng_read_options(hexagram_pcapng_stream *stream, + hexagram_pcapng_option_handler *handler, + uint32_t type, + size_t len); + #endif /* _HEXAGRAM_PCAPNG_H */ diff --git a/src/pcapng.c b/src/pcapng.c index 1c0222d..c71140e 100644 --- a/src/pcapng.c +++ b/src/pcapng.c @@ -8,37 +8,10 @@ #include -static ssize_t handle_option(hexagram_pcapng_stream *stream, - hexagram_pcapng_block_header *header, - uint16_t code, - uint16_t len) { - ssize_t readlen; - uint8_t data[65535]; - - if ((readlen = read(stream->fd, data, (size_t)len)) < 0) { - goto error_io; - } - - if (header->type == HEXAGRAM_PCAPNG_BLOCK_IF) { - if (code == HEXAGRAM_PCAPNG_OPTION_IF_TSRESOL) { - stream->if_tsresol = data[0]; - } - } - - stream->error = HEXAGRAM_PCAPNG_ERROR_OK; - - return readlen; - -error_io: - stream->error = HEXAGRAM_PCAPNG_ERROR_IO; - - return -1; -} - -static ssize_t read_options(hexagram_pcapng_stream *stream, - hexagram_pcapng_block_header *header, - hexagram_pcapng_option_handler *handler, - size_t len) { +ssize_t hexagram_pcapng_read_options(hexagram_pcapng_stream *stream, + hexagram_pcapng_option_handler *handler, + uint32_t type, + size_t len) { hexagram_pcapng_option option; ssize_t total = 0; @@ -53,7 +26,7 @@ static ssize_t read_options(hexagram_pcapng_stream *stream, total += readlen; } - if ((readlen = handler(stream, header, option.code, option.length)) < 0) { + if ((readlen = handler(stream, type, option.code, option.length)) < 0) { goto error_io; } else if (readlen < option.length) { stream->error = HEXAGRAM_PCAPNG_ERROR_TRUNCATED; @@ -63,10 +36,14 @@ static ssize_t read_options(hexagram_pcapng_stream *stream, total += readlen; } - if ((readlen = lseek(stream->fd, option.length % sizeof(uint32_t), SEEK_CUR)) < 0) { - goto error_io; - } else { - total += readlen; + if (option.length % sizeof(uint32_t)) { + size_t padding = sizeof(uint32_t) - (option.length % sizeof(uint32_t)); + + if ((readlen = lseek(stream->fd, padding, SEEK_CUR)) < 0) { + goto error_io; + } else { + total += padding; + } } }