/*
*
* Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
* All rights reserved.
*
* This file is part of libtrace.
*
* This code has been developed by the University of Waikato WAND
* research group. For further information please see http://www.wand.net.nz/
*
* libtrace is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* libtrace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*
*/
/* Tool that compares two traces and outputs any packets that do not match
* between the two
*
* Author: Shane Alcock
*/
#include "libtrace.h"
#include
#include
#include
#include
#include
#include "libpacketdump.h"
uint32_t max_diff = 0;
uint32_t dumped_diff = 0;
/* Compares the two provided packets. If the packets differ in any fashion,
* both will be dumped to standard output using libpacketdump followed by a
* line of asterisks.
*
* Note that only the contents of the packet are compared; the framing provided
* by the trace format, e.g. the ERF or PCAP header, is not examined.
*/
static void per_packet(libtrace_packet_t *a, libtrace_packet_t *b)
{
char *buf_a, *buf_b;
libtrace_linktype_t lt;
uint32_t rem_a, rem_b;
buf_a = trace_get_packet_buffer(a, <, &rem_a);
buf_b = trace_get_packet_buffer(b, <, &rem_b);
if (rem_a > trace_get_wire_length(a))
rem_a = trace_get_wire_length(a);
if (rem_b > trace_get_wire_length(b))
rem_b = trace_get_wire_length(b);
if (!buf_a && !buf_b)
return;
if (!buf_a || !buf_b) {
trace_dump_packet(a);
trace_dump_packet(b);
printf("****************\n");
dumped_diff ++;
return;
}
if (rem_a == 0 || rem_b == 0)
return;
if (rem_a != rem_b) {
trace_dump_packet(a);
trace_dump_packet(b);
printf("****************\n");
dumped_diff ++;
return;
}
/* This is not exactly going to be snappy, but it's the easiest way
* to look for differences */
if (memcmp(buf_a, buf_b, rem_a) != 0) {
trace_dump_packet(a);
trace_dump_packet(b);
printf("****************\n");
dumped_diff ++;
}
}
static void usage(char *prog) {
printf("Usage instructions for %s\n\n", prog);
printf("\t%s [options] traceA traceB\n\n", prog);
printf("Supported options:\n");
printf("\t-m Stop after differences have been reported\n");
return;
}
int main(int argc, char *argv[])
{
libtrace_t *trace[2];
libtrace_packet_t *packet[2];
int opt;
if (argc<2) {
usage(argv[0]);
return -1;
}
while ((opt = getopt(argc, argv, "m:")) != EOF) {
switch (opt) {
case 'm':
if (atoi(optarg) < 0) {
fprintf(stderr, "-m option must not be negative - ignoring\n");
} else {
max_diff = (uint32_t) atoi(optarg);
}
break;
default:
usage(argv[0]);
}
}
if (optind + 2 > argc) {
usage(argv[0]);
return -1;
}
packet[0] = trace_create_packet();
packet[1] = trace_create_packet();
trace[0] = trace_create(argv[optind++]);
if (trace_is_err(trace[0])) {
trace_perror(trace[0],"Opening trace file");
return -1;
}
if (trace_start(trace[0])) {
trace_perror(trace[0],"Starting trace");
trace_destroy(trace[0]);
return -1;
}
trace[1] = trace_create(argv[optind++]);
if (trace_is_err(trace[1])) {
trace_perror(trace[1],"Opening trace file");
return -1;
}
if (trace_start(trace[1])) {
trace_perror(trace[1],"Starting trace");
trace_destroy(trace[1]);
return -1;
}
while (trace_read_packet(trace[0], packet[0]) > 0 &&
trace_read_packet(trace[1], packet[1]) > 0) {
per_packet(packet[0], packet[1]);
if (max_diff > 0 && dumped_diff >= max_diff)
break;
}
if (trace_is_err(trace[0])) {
trace_perror(trace[0],"Reading packets");
trace_destroy(trace[0]);
return -1;
}
if (trace_is_err(trace[1])) {
trace_perror(trace[1],"Reading packets");
trace_destroy(trace[1]);
return -1;
}
trace_destroy(trace[0]);
trace_destroy(trace[1]);
trace_destroy_packet(packet[0]);
trace_destroy_packet(packet[1]);
if (dumped_diff == 0)
return 0;
else
return 1;
}