#include #include #include #include #include #include #include #include ssize_t hexagram_pcapng_read_options(hexagram_pcapng_stream *stream, hexagram_pcapng_option_handler *handler, uint32_t type, size_t len, void *data) { hexagram_pcapng_option option; ssize_t total = 0; if (handler == NULL) { goto error_no_handler; } while (total < len) { ssize_t readlen; size_t remaining; 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, type, option.code, option.length, data)) < 0) { goto error_io; } else if (readlen < option.length) { stream->error = HEXAGRAM_PCAPNG_ERROR_TRUNCATED; goto error_io; } else { total += readlen; } if ((remaining = option.length % sizeof(uint32_t)) > 0) { size_t padding = sizeof(uint32_t) - remaining; if ((readlen = lseek(stream->fd, padding, SEEK_CUR)) < 0) { goto error_io; } else { total += padding; } } } stream->error = HEXAGRAM_PCAPNG_ERROR_OK; return total; error_io: error_no_handler: 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, void *data) { hexagram_pcapng_block_header header; hexagram_pcapng_block_footer footer; ssize_t total = 0; if (handler == NULL) { goto error_no_handler; } while (1) { size_t expected; ssize_t readlen; if ((readlen = read(stream->fd, &header, sizeof(header))) < 0) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; goto error_io; } else if (readlen == 0) { goto done; } else if (readlen < sizeof(header)) { stream->error = HEXAGRAM_PCAPNG_ERROR_TRUNCATED; goto error_io; } else { total += readlen; } expected = header.length - sizeof(header) - sizeof(footer); if ((readlen = handler(stream, header.type, expected, data)) < 0) { goto error_io; } else { total += readlen; } if ((readlen = read(stream->fd, &footer, sizeof(footer))) < 0) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; goto error_io; } else if (readlen == 0) { goto done; } else if (readlen < sizeof(footer)) { stream->error = HEXAGRAM_PCAPNG_ERROR_TRUNCATED; goto error_io; } else if (footer.length != header.length) { stream->error = HEXAGRAM_PCAPNG_ERROR_FORMAT; goto error_io; } else { total += readlen; } } done: stream->error = HEXAGRAM_PCAPNG_ERROR_OK; return total; error_io: error_no_handler: return -1; }