]> mj.ucw.cz Git - netgrind.git/blob - netgrind/netgrind.c
Live counter. Bug fixes to tcp.
[netgrind.git] / netgrind / netgrind.c
1 /*
2  *      Netgrind -- The Network Traffic Analyser
3  *
4  *      (c) 2003 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "netgrind/pkt.h"
12 #include "netgrind/netgrind.h"
13
14 #include <stdio.h>
15 #include <stdarg.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <getopt.h>
19
20 #include <pcap.h>
21
22 void die(byte *msg, ...)
23 {
24   va_list args;
25
26   va_start(args, msg);
27   fputs("netgrind: ", stderr);
28   vfprintf(stderr, msg, args);
29   fputs("\n", stderr);
30   exit(1);
31 }
32
33 /*** PCAP INTERFACE ***/
34
35 static void (*link_handler)(struct pkt *);
36 static struct pkt_stats stat_pcap_incomplete;
37
38 static uns in_count, start_sec;
39
40 static int link_setup_handler(int dlt)
41 {
42   switch (dlt)
43     {
44     case DLT_EN10MB:    link_handler = link_eth_got_packet; return 1;
45     default:            return 0;
46     }
47 }
48
49 static void got_pcap_packet(u_char *userdata UNUSED, const struct pcap_pkthdr *hdr, const u_char *pkt)
50 {
51   if (hdr->caplen != hdr->len)
52     {
53       stat_pcap_incomplete.packets++;
54       stat_pcap_incomplete.bytes += hdr->len - hdr->caplen;
55       return;
56     }
57   if (!(in_count % 1024))
58     {
59       if (!in_count)
60         start_sec = hdr->ts.tv_sec;
61       fprintf(stderr, "%d packets, %d seconds, %d conns (%d still open)\r",
62               in_count, (int)hdr->ts.tv_sec - start_sec,
63               tcp_total_flows, tcp_num_flows);
64       fflush(stderr);
65     }
66   in_count++;
67   struct pkt *p = pkt_new(0, hdr->len);
68   memcpy(pkt_append(p, hdr->len), pkt, hdr->len);
69   p->timestamp = (u64)hdr->ts.tv_sec * 1000000 + hdr->ts.tv_usec;
70   link_handler(p);
71 }
72
73 static void usage(void)
74 {
75   fprintf(stderr, "Usage: netgrind [<switches>] <capture-file>\n\
76 \n\
77 -a              TCP: Record arrival times instead of processing times\n\
78 -c <count>      Stop after processing <count> packets\n\
79 -d <dir>        Dump connections to a given directory\n\
80 -D <dir>        Dump connections with more details\n\
81 -f <filter>     Apply filter expression\n\
82 -w              TCP: Wait for ACK before processing packets\n\
83 ");
84   exit(1);
85 }
86
87 int main(int argc, char **argv)
88 {
89   char errbuf[PCAP_ERRBUF_SIZE];
90   pcap_t *pcap;
91   int c, dlt;
92   int max_packets = -1;
93   byte *filter = NULL;
94   struct bpf_program filter_prog;
95
96   tcp_default_appl = &appl_sink;
97   while ((c = getopt(argc, argv, "ac:d:D:f:w")) >= 0)
98     switch (c)
99       {
100       case 'a':
101         tcp_arrival_times = 1;
102         break;
103       case 'c':
104         max_packets = atol(optarg);
105         break;
106       case 'd':
107         tcp_default_appl = &appl_save;
108         save_dir = optarg;
109         break;
110       case 'D':
111         tcp_default_appl = &appl_asave;
112         save_dir = optarg;
113         break;
114       case 'f':
115         filter = optarg;
116         break;
117       case 'w':
118         tcp_wait_for_ack = 1;
119         break;
120       default:
121         usage();
122       }
123   if (optind != argc - 1)
124     usage();
125
126   tcp_init();
127
128   if (!(pcap = pcap_open_offline(argv[optind], errbuf)))
129     die("Unable to open %s", errbuf);
130   dlt = pcap_datalink(pcap);
131   if (!link_setup_handler(dlt))
132     die("Don't know how to handle data link type %d", dlt);
133   if (filter)
134     {
135       if (pcap_compile(pcap, &filter_prog, filter, 1, 0) < 0)
136         die("Error compiling filter: %s", pcap_geterr(pcap));
137       pcap_setfilter(pcap, &filter_prog);
138     }
139   if (pcap_loop(pcap, max_packets, got_pcap_packet, NULL) < 0)
140     die("Capture failed: %s", pcap_geterr(pcap));
141   tcp_cleanup();
142   printf("Pcap: %Ld(%Ld) incomplete\n",
143          stat_pcap_incomplete.packets, stat_pcap_incomplete.bytes);
144   printf("Link: %Ld(%Ld) in, %Ld(%Ld) dwarves, %Ld(%Ld) strangers, %Ld(%Ld) ARPs\n",
145          stat_link_in.packets, stat_link_in.bytes,
146          stat_link_dwarf.packets, stat_link_dwarf.bytes,
147          stat_link_unknown.packets, stat_link_unknown.bytes,
148          stat_link_arp.packets, stat_link_arp.bytes);
149   printf("IP: %Ld(%Ld) in, %Ld(%Ld) invalid, %Ld(%Ld) boring, %Ld(%Ld) fragmented, %Ld(%Ld) bad checksum; %d flows\n",
150          stat_ip_in.packets, stat_ip_in.bytes,
151          stat_ip_invalid.packets, stat_ip_invalid.bytes,
152          stat_ip_uninteresting.packets, stat_ip_uninteresting.bytes,
153          stat_ip_fragmented.packets, stat_ip_fragmented.bytes,
154          stat_ip_badsum.packets, stat_ip_badsum.bytes,
155          tcp_total_flows);
156   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",
157          stat_tcp_in.packets, stat_tcp_in.bytes,
158          stat_tcp_invalid.packets, stat_tcp_invalid.bytes,
159          stat_tcp_badsum.packets, stat_tcp_badsum.bytes,
160          stat_tcp_unmatched.packets, stat_tcp_unmatched.bytes,
161          stat_tcp_on_closed.packets, stat_tcp_on_closed.bytes,
162          stat_tcp_bad_state.packets, stat_tcp_bad_state.bytes);
163   pcap_close(pcap);
164   return 0;
165 }