hexagram/src/pcapng.c

163 lines
4 KiB
C
Raw Normal View History

#include <stdlib.h>
2018-12-16 02:11:53 -06:00
#include <stdint.h>
#include <string.h>
2018-12-16 02:11:53 -06:00
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
2018-12-16 02:15:33 -06:00
#include <hexagram/pcapng.h>
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) {
hexagram_pcapng_option option;
ssize_t total = 0;
while (total < len) {
ssize_t readlen;
if ((readlen = read(stream->fd, &option, sizeof(option))) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
goto error_io;
} else {
total += readlen;
}
if ((readlen = handler(stream, header, option.code, option.length)) < 0) {
goto error_io;
} else if (readlen < option.length) {
stream->error = HEXAGRAM_PCAPNG_ERROR_TRUNCATED;
goto error_io;
} else {
total += readlen;
}
if ((readlen = lseek(stream->fd, option.length % sizeof(uint32_t), SEEK_CUR)) < 0) {
goto error_io;
} else {
total += readlen;
}
}
stream->error = HEXAGRAM_PCAPNG_ERROR_OK;
return total;
error_io:
return -1;
}
hexagram_pcapng_stream *hexagram_pcapng_stream_open_fd(int fd) {
hexagram_pcapng_stream *stream;
if ((stream = malloc(sizeof(*stream))) == NULL) {
goto error_malloc_stream;
}
stream->fd = fd;
stream->error = HEXAGRAM_PCAPNG_ERROR_OK;
stream->if_tsresol = 0;
return stream;
error_malloc_stream:
return NULL;
}
void hexagram_pcapng_stream_destroy(hexagram_pcapng_stream *stream) {
memset(stream, '\0', sizeof(*stream));
free(stream);
}
ssize_t hexagram_pcapng_stream_read(hexagram_pcapng_stream *stream,
hexagram_pcapng_block_handler *handler) {
hexagram_pcapng_block_header header;
hexagram_pcapng_block_footer footer;
2018-12-16 02:11:53 -06:00
ssize_t total = 0;
while (1) {
size_t expected;
2018-12-16 02:11:53 -06:00
ssize_t readlen;
if ((readlen = read(stream->fd, &header, sizeof(header))) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
2018-12-16 02:11:53 -06:00
goto error_io;
} else if (readlen == 0) {
goto done;
} else if (readlen < sizeof(header)) {
stream->error = HEXAGRAM_PCAPNG_ERROR_TRUNCATED;
2018-12-16 02:11:53 -06:00
goto error_io;
} else {
total += readlen;
2018-12-16 02:11:53 -06:00
}
expected = header.length - sizeof(header) - sizeof(footer);
2018-12-16 02:11:53 -06:00
if ((readlen = handler(stream, header.type, expected)) < 0) {
2018-12-16 02:11:53 -06:00
goto error_io;
} else {
total += readlen;
2018-12-16 02:11:53 -06:00
}
if ((readlen = read(stream->fd, &footer, sizeof(footer))) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
2018-12-16 02:11:53 -06:00
goto error_io;
} else if (readlen == 0) {
goto done;
} else if (readlen < sizeof(footer)) {
stream->error = HEXAGRAM_PCAPNG_ERROR_TRUNCATED;
2018-12-16 02:11:53 -06:00
goto error_io;
} else if (footer.length != header.length) {
stream->error = HEXAGRAM_PCAPNG_ERROR_FORMAT;
2018-12-16 03:00:28 -06:00
goto error_io;
} else {
total += readlen;
2018-12-16 03:00:28 -06:00
}
2018-12-16 02:11:53 -06:00
}
done:
stream->error = HEXAGRAM_PCAPNG_ERROR_OK;
2018-12-16 02:11:53 -06:00
return total;
error_io:
return -1;
}