#include #include #include #include #include #include #include #include #include #include #include #include static ssize_t handle_option(hexagram_pcapng_stream *stream, uint32_t type, uint16_t code, uint16_t len, void *data) { if (lseek(stream->fd, (size_t)len, SEEK_CUR) < 0) { goto error_io; } stream->error = HEXAGRAM_PCAPNG_ERROR_OK; return (size_t)len; error_io: stream->error = HEXAGRAM_PCAPNG_ERROR_IO; return -1; } static ssize_t handle_block_if(hexagram_pcapng_stream *stream, uint32_t type, size_t len, void *data) { hexagram_pcapng_if iface; ssize_t readlen, total = 0; size_t remaining = len; /* * Read the interface block header. */ if ((readlen = read(stream->fd, &iface, sizeof(iface))) < 0) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; goto error_io; } else { remaining -= readlen; total += readlen; } if ((readlen = hexagram_pcapng_read_options(stream, handle_option, type, remaining, data)) < 0) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; goto error_io; } else { total += readlen; } return total; error_io: return -1; } static ssize_t handle_block_packet(hexagram_pcapng_stream *stream, uint32_t type, size_t len, hexagram_capture *capture) { hexagram_pcapng_packet header; uint8_t body[65535]; ssize_t readlen, total = 0; size_t remaining = len; struct timeval timestamp; uint64_t usec; /* * Read the packet block header so that we may determine the size of the * payload to continue to read. */ if ((readlen = read(stream->fd, &header, sizeof(header))) < 0) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; goto error_io; } else { remaining -= readlen; total += readlen; } /* * Read the packet body into our scratchpad. */ if ((readlen = read(stream->fd, &body, header.caplen)) < 0) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; goto error_io; } else { remaining -= readlen; total += readlen; } usec = (uint64_t)header.timestamp[0] << 32 | (uint64_t)header.timestamp[1]; timestamp.tv_sec = usec / 1000000; timestamp.tv_usec = usec % 1000000; ((struct can_frame *)body)->can_id = be32toh(((struct can_frame *)body)->can_id); if (hexagram_capture_write(capture, (struct can_frame *)body, ×tamp) < 0) { goto error_io; } 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) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; 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) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; goto error_io; } else { total += remaining; } stream->error = HEXAGRAM_PCAPNG_ERROR_OK; return total; 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, void *data) { switch (type) { case HEXAGRAM_PCAPNG_BLOCK_IF: return handle_block_if(stream, type, len, data); case HEXAGRAM_PCAPNG_BLOCK_PACKET: return handle_block_packet(stream, type, len, (hexagram_capture *)data); default: break; } fprintf(stderr, "Read block type %08"PRIx32" len %zu\n", type, len); if (lseek(stream->fd, len, SEEK_CUR) < 0) { stream->error = HEXAGRAM_PCAPNG_ERROR_IO; goto error_io; } return len; error_io: return -1; } int main(int argc, char **argv) { int fd; hexagram_pcapng_stream *stream; hexagram_capture *capture; fd = (argc < 2)? fileno(stdin): open(argv[1], O_RDONLY); if (fd < 0) { perror("open()"); goto error_open_pcapng; } if (argc > 2) { if ((capture = hexagram_capture_open_file(argv[2], O_CREAT | O_WRONLY)) == NULL) { perror("hexagram_capture_open_file()"); goto error_capture_open; } } else { if ((capture = hexagram_capture_open_fd(fileno(stdout), O_WRONLY)) == NULL) { perror("hexagram_capture_open_fd()"); goto error_capture_open; } } if ((stream = hexagram_pcapng_stream_open_fd(fd)) < 0) { perror("hexagram_pcapng_stream_open_fd()"); goto error_pcapng_stream_open_fd; } if (hexagram_pcapng_stream_read(stream, handle_block, capture) < 0) { perror("hexagram_pcapng_stream_read()"); goto error_pcapng_stream_read; } hexagram_pcapng_stream_destroy(stream); hexagram_capture_destroy(capture); if (argc == 2) { close(fd); } return 0; error_pcapng_stream_read: error_pcapng_stream_open_fd: hexagram_pcapng_stream_destroy(stream); error_capture_open: if (argc == 3 || argc == 2) { close(fd); } error_open_pcapng: return 1; }