#include #include #include #include #include #include #include #include #include static void usage(int argc, char **argv, const char *message, ...) { if (message) { va_list args; va_start(args, message); vfprintf(stderr, message, args); va_end(args); } fprintf(stderr, "usage: %s [file.pcapng]\n", argv[0]); exit(1); } static int handle_block(int fd, uint32_t type, size_t len) { hexagram_pcapng_packet header; uint8_t packet[65535]; ssize_t readlen, remaining = len; /* * If we've received anything other than a packet block, then seek past * that data and move on. */ if (type != HEXAGRAM_PCAPNG_BLOCK_PACKET) { printf("Read block type %08"PRIx32" len %zu\n", type, len); if (lseek(fd, len, SEEK_CUR) < 0) { perror("lseek()"); goto error_io; } return 0; } /* * Otherwise, read the packet block header so that we may determine the * size of the payload to continue to read. */ if ((readlen = read(fd, &header, sizeof(header))) < 0) { perror("read()"); goto error_io; } else { remaining -= readlen; } /* * Read the packet data into our scratchpad. */ if ((readlen = read(fd, &packet, header.caplen)) < 0) { perror("read()"); goto error_io; } else { remaining -= readlen; } printf("Read packet %"PRIu32" bytes time hi %"PRIu32" lo %"PRIu32"\n", header.caplen, header.timestamp[0], header.timestamp[1]); /* * 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(fd, remaining, SEEK_CUR) < 0) { perror("lseek()"); goto error_io; } return 0; error_io: return -1; } int main(int argc, char **argv) { int fd, error; if (argc == 1) { fd = fileno(stdin); } else if (argc == 2) { if ((fd = open(argv[1], O_RDONLY)) < 0) { perror("open()"); goto error_open; } } else { usage(argc, argv, NULL); } if (hexagram_pcapng_stream_read(fd, handle_block, &error) < 0) { perror("hexagram_pcapng_stream_read()"); goto error_io; } if (argc == 2) { close(fd); } return 0; error_io: if (argc == 2) { close(fd); } error_open: return 1; }