#include #include #include "cap_utils.h" #include "packet.h" #define MAX_PKTS_TO_CHECK_FOR_DROP 10 uint8_t are_packets_equal(struct buffer_packet bpread[]) { size_t s1 = bpread[0].ip.ap.fmt.headers.size, s2 = bpread[1].ip.ap.fmt.headers.size; if (s1 != s2) return 0; for (size_t idx = sizeof(bpread[0].ip.ap.fmt.headers) + sizeof(bpread[0].ip.ap.fmt.content.clear) - sizeof(char); idx < s1; idx++) { char e1 = (&bpread[0].ip.ap.raw)[idx], e2 = (&bpread[1].ip.ap.raw)[idx]; if (e1 != e2) return 0; } return 1; } enum pkt_reconstruct_res { PREC_SAME, PREC_DROP, PREC_FAIL }; struct pkt_reconstruct { enum pkt_reconstruct_res r; int diff_0; int diff_1; }; void reconstruct_action(struct cap_file cf[], struct pkt_reconstruct* pr) { struct buffer_packet bpread[2]; pr->r = PREC_FAIL; for (int m1 = 0; m1 < MAX_PKTS_TO_CHECK_FOR_DROP; m1++) { for (int m2 = 0; m2 <= m1; m2++) { cap_npeek_bp(&cf[0], m1, &bpread[0]); cap_npeek_bp(&cf[1], m2, &bpread[1]); if(are_packets_equal(bpread)) { pr->r = m1 == 0 && m2 == 0 ? PREC_SAME : PREC_DROP; pr->diff_0 = m1; pr->diff_1 = m2; while (m1-- >= 0) cap_next_bp (&cf[0], &bpread[0]); while (m2-- >= 0) cap_next_bp (&cf[1], &bpread[1]); return; } cap_npeek_bp(&cf[0], m2, &bpread[0]); cap_npeek_bp(&cf[1], m1, &bpread[1]); if(are_packets_equal(bpread)) { pr->r = PREC_DROP; pr->diff_0 = m2; pr->diff_1 = m1; while (m2-- >= 0) cap_next_bp (&cf[0], &bpread[0]); while (m1-- >= 0) cap_next_bp (&cf[1], &bpread[1]); return; } } } }; int main(int argc, char** argv) { setvbuf(stdout, NULL, _IONBF, 0); printf("~ capdiff ~\n"); if (argc != 3) { fprintf(stderr, "Usage %s FILE.IN FILE.OUT\n", argv[0]); exit(EXIT_FAILURE); } uint8_t verbose = 0; struct cap_file cf[2]; for (int i = 0; i < 2; i++) cap_load(&cf[i], argv[i+1]); if (cf[0].sz != cf[1].sz) { printf("[!!] %s has %ld entries, %s has %ld entries\n", argv[1], cf[0].sz/sizeof(struct buffer_packet), argv[2], cf[1].sz/sizeof(struct buffer_packet)); } else if (verbose) { printf("[OK] %s and %s have %ld entries\n", argv[1], argv[2], cf[0].sz/sizeof(struct buffer_packet)); } struct pkt_reconstruct pr; struct buffer_packet bpread[2]; int c0 = 0, c1 = 0, stop = 0; while (c0 < cf[0].sz_obj && c1 < cf[1].sz_obj && !stop) { reconstruct_action(cf, &pr); c0 += pr.diff_0 + 1; c1 += pr.diff_1 + 1; switch (pr.r) { case PREC_SAME: // Nothing break; case PREC_DROP: fprintf(stderr, "[!!] packets (%d,%d) ", c0, c1); if (c0 > 0) fprintf(stderr, "%s dropped %d pkts ", cf[0].filename, pr.diff_0); if (c1 > 0) fprintf(stderr, "%s has dropped %d pkts ", cf[1].filename, pr.diff_1); fprintf(stderr, "\n"); break; case PREC_FAIL: fprintf(stderr, "[!!] Unable to remap packets (%d, %d). We should stop\n", c0, c1); stop = 1; break; } } printf("parsed (%d,%d) packets\n", c0, c1); for (int i = 0; i < 2; i++) cap_unload (&cf[i]); return 0; }