From 2408f6ba75c12c88454f52a3239a61645499bae6 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 3 Jun 2019 17:09:40 +0200 Subject: [PATCH] Working capdiff --- src/cap_utils.c | 17 +++++-- src/cap_utils.h | 3 ++ src/capdiff.c | 117 ++++++++++++++++++++++++++++++------------------ 3 files changed, 91 insertions(+), 46 deletions(-) diff --git a/src/cap_utils.c b/src/cap_utils.c index 765808a..4a21f4a 100644 --- a/src/cap_utils.c +++ b/src/cap_utils.c @@ -5,19 +5,30 @@ void cap_load(struct cap_file *cf, char* filename) { perror("Unable to open file"); exit(EXIT_FAILURE); } - + cf->filename = filename; fseek(cf->fd, 0, SEEK_END); cf->sz = ftell(cf->fd); fseek(cf->fd, 0, SEEK_SET); + + cf->sz_obj = cf->sz / sizeof(struct buffer_packet); } void cap_next_bp(struct cap_file *cf, struct buffer_packet* bp) { fread(bp, sizeof(struct buffer_packet), 1, cf->fd); } -void cap_peek_bp(struct cap_file *cf, struct buffer_packet* bp) { +void cap_npeek_bp(struct cap_file *cf, int c, struct buffer_packet* bp) { + //fprintf(stdout, "c: %d, current pos: %ld, ", c, ftell(cf->fd)); + + ssize_t cbytes = c*sizeof(struct buffer_packet); + fseek(cf->fd, cbytes, SEEK_CUR); size_t n = fread(bp, sizeof(struct buffer_packet), 1, cf->fd); - fseek(cf->fd, -n, SEEK_CUR); + fseek(cf->fd, -(n*sizeof(struct buffer_packet) + cbytes), SEEK_CUR); + //fprintf(stdout, "cbytes: %ld, n: %ld, final pos: %ld\n", cbytes, n, ftell(cf->fd)); +} + +void cap_peek_bp(struct cap_file *cf, struct buffer_packet* bp) { + cap_npeek_bp(cf, 0, bp); } size_t cap_count_bp(struct cap_file *cf) { diff --git a/src/cap_utils.h b/src/cap_utils.h index 5f0f4ba..e4ea634 100644 --- a/src/cap_utils.h +++ b/src/cap_utils.h @@ -6,11 +6,14 @@ struct cap_file { FILE *fd; + char* filename; size_t sz; + size_t sz_obj; }; void cap_load(struct cap_file *cf, char* filename); void cap_next_bp(struct cap_file *cf, struct buffer_packet* bp); void cap_peek_bp(struct cap_file *cf, struct buffer_packet* bp); +void cap_npeek_bp(struct cap_file *cf, int c, struct buffer_packet* bp); size_t cap_count_bp(struct cap_file *cf); void cap_unload(struct cap_file *cf); diff --git a/src/capdiff.c b/src/capdiff.c index 0cb3e49..684841d 100644 --- a/src/capdiff.c +++ b/src/capdiff.c @@ -3,12 +3,63 @@ #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 FILE1 FILE2\n", argv[0]); + fprintf(stderr, "Usage %s FILE.IN FILE.OUT\n", argv[0]); exit(EXIT_FAILURE); } uint8_t verbose = 0; @@ -29,52 +80,32 @@ int main(int argc, char** argv) { cf[0].sz/sizeof(struct buffer_packet)); } - size_t to_read = cf[0].sz < cf[1].sz ? cf[0].sz : cf[1].sz; - size_t to_read_obj = to_read / sizeof(struct buffer_packet); - uint16_t expected_id = 0; + struct pkt_reconstruct pr; struct buffer_packet bpread[2]; - for (size_t c = 0; c < to_read_obj; c++) { - for (int i = 0; i < 2; i++) cap_next_bp(&cf[i], &bpread[i]); - /*if (expected_id != bpread[0].ip.ap.fmt.content.clear.id || expected_id != bpread[1].ip.ap.fmt.content.clear.id) { - printf("[!!] expected id is %d, %s has id %d, %s has id %d\n", - expected_id, - argv[1], - bpread[0].ip.ap.fmt.content.clear.id, - argv[2], - bpread[1].ip.ap.fmt.content.clear.id); - }*/ - - size_t s1 = bpread[0].ip.ap.fmt.headers.size, s2 = bpread[1].ip.ap.fmt.headers.size; - uint8_t is_same_size = s1 == s2; - if (!is_same_size) { - printf("[!!] %s packet has size %d, %s packet has size %d for expected id %d\n", - argv[1], - bpread[0].ip.ap.fmt.headers.size, - argv[2], - bpread[1].ip.ap.fmt.headers.size, - expected_id); - } else if (verbose) { - printf("[OK] %s and %s packets for expected id %d have size %d\n", - argv[1], - argv[2], - expected_id, - bpread[0].ip.ap.fmt.headers.size); + 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; } - - - size_t max_size = s1 > s2 ? s1 : s2; - for (size_t idx = sizeof(bpread[0].ip.ap.fmt.headers) + sizeof(bpread[0].ip.ap.fmt.content.clear) - sizeof(char); idx < max_size; idx++) { - char e1 = (&bpread[0].ip.ap.raw)[idx], e2 = (&bpread[1].ip.ap.raw)[idx]; - if (e1 != e2) { - printf("[!!] for expected id %d, byte 0x%04x is different: 0x%02x vs 0x%02x\n", expected_id, (uint16_t)idx, (uint8_t)e1, (uint8_t)e2); - } - } - - expected_id++; } - for (int i = 0; i < 2; i++) cap_unload (&cf[i]); + printf("parsed (%d,%d) packets\n", c0, c1); - printf("parsed %d packets\n", expected_id); + for (int i = 0; i < 2; i++) cap_unload (&cf[i]); return 0; }