* of the GNU General Public License.
*/
-/*
- * FIXME: TCP stats
- */
-
#include "lib/lib.h"
#include "netgrind/pkt.h"
#include "netgrind/netgrind.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
+#include <getopt.h>
#include <pcap.h>
link_handler(p);
}
+static void usage(void)
+{
+ fprintf(stderr, "Usage: netgrind [<switches>] <capture-file>\n\
+\n\
+-a TCP: Record arrival times instead of processing times\n\
+-c <count> Stop after processing <count> packets\n\
+-d <dir> Dump connections to a given directory\n\
+-D <dir> Dump connections with more details\n\
+-f <filter> Apply filter expression\n\
+-w TCP: Wait for ACK before processing packets\n\
+");
+ exit(1);
+}
+
int main(int argc, char **argv)
{
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *pcap;
- int dlt;
+ int c, dlt;
+ int max_packets = -1;
+ byte *filter = NULL;
+ struct bpf_program filter_prog;
- if (argc != 2)
- die("Usage: netgrind <capture-file>");
+ tcp_default_appl = &appl_sink;
+ while ((c = getopt(argc, argv, "ac:d:D:f:w")) >= 0)
+ switch (c)
+ {
+ case 'a':
+ tcp_arrival_times = 1;
+ break;
+ case 'c':
+ max_packets = atol(optarg);
+ break;
+ case 'd':
+ tcp_default_appl = &appl_save;
+ save_dir = optarg;
+ break;
+ case 'D':
+ tcp_default_appl = &appl_asave;
+ save_dir = optarg;
+ break;
+ case 'f':
+ filter = optarg;
+ break;
+ case 'w':
+ tcp_wait_for_ack = 1;
+ break;
+ default:
+ usage();
+ }
+ if (optind != argc - 1)
+ usage();
tcp_init();
- if (!(pcap = pcap_open_offline(argv[1], errbuf)))
- die("Unable to open %s: %s", argv[1], errbuf);
+ if (!(pcap = pcap_open_offline(argv[optind], errbuf)))
+ die("Unable to open %s", errbuf);
dlt = pcap_datalink(pcap);
if (!link_setup_handler(dlt))
die("Don't know how to handle data link type %d", dlt);
- if (pcap_loop(pcap, -1, got_pcap_packet, NULL) < 0)
+ if (filter)
+ {
+ if (pcap_compile(pcap, &filter_prog, filter, 1, 0) < 0)
+ die("Error compiling filter: %s", pcap_geterr(pcap));
+ pcap_setfilter(pcap, &filter_prog);
+ }
+ if (pcap_loop(pcap, max_packets, got_pcap_packet, NULL) < 0)
die("Capture failed: %s", pcap_geterr(pcap));
tcp_cleanup();
-#if 0
- struct pcap_stat stats;
- if (pcap_stats(pcap, &stats))
- die("pcap_stats: %s", pcap_geterr(pcap));
- printf("libpcap stats: %d packets received, %d dropped\n", stats.ps_recv, stats.ps_drop);
-#endif
printf("Pcap: %Ld(%Ld) incomplete\n",
stat_pcap_incomplete.packets, stat_pcap_incomplete.bytes);
printf("Link: %Ld(%Ld) in, %Ld(%Ld) dwarves, %Ld(%Ld) strangers, %Ld(%Ld) ARPs\n",
stat_link_dwarf.packets, stat_link_dwarf.bytes,
stat_link_unknown.packets, stat_link_unknown.bytes,
stat_link_arp.packets, stat_link_arp.bytes);
- printf("IP: %Ld(%Ld) in, %Ld(%Ld) invalid, %Ld(%Ld) boring, %Ld(%Ld) fragmented, %Ld(%Ld) bad checksum\n",
+ printf("IP: %Ld(%Ld) in, %Ld(%Ld) invalid, %Ld(%Ld) boring, %Ld(%Ld) fragmented, %Ld(%Ld) bad checksum; %d flows\n",
stat_ip_in.packets, stat_ip_in.bytes,
stat_ip_invalid.packets, stat_ip_invalid.bytes,
stat_ip_uninteresting.packets, stat_ip_uninteresting.bytes,
stat_ip_fragmented.packets, stat_ip_fragmented.bytes,
- stat_ip_badsum.packets, stat_ip_badsum.bytes);
- printf("TCP: %Ld(%Ld) in, %Ld(%Ld) invalid, %Ld(%Ld) bad checksum\n",
+ stat_ip_badsum.packets, stat_ip_badsum.bytes,
+ tcp_total_flows);
+ printf("TCP: %Ld(%Ld) in, %Ld(%Ld) invalid, %Ld(%Ld) bad checksum, %Ld(%Ld) unmatched, %Ld(%Ld) on closed connections, %Ld(%Ld) in unexpected state\n",
stat_tcp_in.packets, stat_tcp_in.bytes,
stat_tcp_invalid.packets, stat_tcp_invalid.bytes,
- stat_tcp_badsum.packets, stat_tcp_badsum.bytes);
+ stat_tcp_badsum.packets, stat_tcp_badsum.bytes,
+ stat_tcp_unmatched.packets, stat_tcp_unmatched.bytes,
+ stat_tcp_on_closed.packets, stat_tcp_on_closed.bytes,
+ stat_tcp_bad_state.packets, stat_tcp_bad_state.bytes);
pcap_close(pcap);
return 0;
}