MSWSP: fix scope of VT_TYPE
[wireshark-wip.git] / trigcap.c
blob554418b9ef3009a86c9d5a5769e0bfe783b13301
1 /*
2 * trigcap
3 * a simple triggered libpcap-based capture agent
5 * $Id$
7 * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <signal.h>
30 #include <errno.h>
31 #include <getopt.h>
32 #include <pcap.h>
34 static int dumping;
35 static volatile int keep_going;
36 static pcap_t* listener;
37 static struct bpf_program stop_filter;
38 static int captured = 0;
39 static int debug_level = 0;
41 static void panic(int err, const char* fmt, ...) {
42 va_list ap;
43 va_start(ap,fmt);
44 vfprintf(stderr,fmt,ap);
45 va_end(ap);
46 exit(err);
49 static void dprintf(int lev, const char* fmt, ...) {
50 va_list ap;
52 if (lev <= debug_level) {
53 va_start(ap,fmt);
54 vfprintf(stderr,fmt,ap);
55 va_end(ap);
56 fflush(stderr);
61 static void usage(int err) {
62 const char* usage_str = "usage:\n"
63 "trigcap -w outfile -b begin -e end [-f capture] [-i iface] [-s snaplen] [-p] [-q] [-d [-d [-d [-d]]]]\n"
64 " -w output file\n"
65 " -b filter to start capturing\n"
66 " -e filter to stop capturing\n"
67 " -f capture filter\n"
68 " -p promiscuous mode\n"
69 " -s snapshot length\n"
70 " -q quiet\n"
71 " -d increase debug level\n"
72 " -h prints this message\n"
75 panic(err,usage_str);
78 static void listener_handler(u_char* u, const struct pcap_pkthdr * ph, const u_char* buf) {
79 char errbuf[PCAP_ERRBUF_SIZE];
81 dprintf(2,"listener handler invoked dumping=%d\n",dumping);
83 if (dumping) {
84 dprintf(2,"last round\n");
85 keep_going = 0;
86 } else {
87 if (pcap_setfilter(listener, &stop_filter) < 0) {
88 panic(23,"could not apply stop filter to listener: %s\n",pcap_geterr(listener));
91 dprintf(2,"apply stop filter to listener\n");
93 if (pcap_setnonblock(listener, 1, errbuf) < 0) {
94 panic(24,"could not set listener in non blocking mode: %s\n",errbuf);
97 dprintf(2,"listener -> non_blocking\n");
98 dumping = 1;
102 static void capture_handler(u_char* dumper, const struct pcap_pkthdr * ph, const u_char* buf) {
103 dprintf(4,"capture handler invoked dumping=%d\n",dumping);
104 if (dumping) {
105 captured++;
106 pcap_dump(dumper, ph, buf);
110 static void sig_int(int sig) {
111 keep_going = 0;
114 int main(int argc, char** argv) {
115 char errbuf[PCAP_ERRBUF_SIZE];
116 char* interface = NULL;
117 char* outfile = NULL;
118 guint snaplen = 65536;
119 char* start_filter_str = NULL;
120 char* stop_filter_str = NULL;
121 char* capture_filter_str = NULL;
122 int promisc = 0;
123 int quiet = 0;
124 struct bpf_program start_filter;
125 struct bpf_program capture_filter;
126 pcap_t* capturer = NULL;
127 pcap_dumper_t* dumper = NULL;
128 int opt;
130 while ((opt = getopt(argc, argv, "i:w:s:b:e:f:phdq")) != -1) {
131 switch (opt) {
132 case 'i':
133 if (interface) panic(1,"interface already given");
134 interface = g_strdup(optarg);
135 break;
136 case 'w':
137 if (outfile) panic(3,"output file already given");
138 outfile = g_strdup(optarg);
139 break;
140 case 's':
141 snaplen = strtoul(optarg,NULL,10);
142 if ( snaplen == 0 )
143 panic(4,"invalid snaplen");
144 break;
145 case 'b':
146 if (start_filter_str) panic(5,"start filter already given");
147 start_filter_str = g_strdup(optarg);
148 break;
149 case 'e':
150 if (stop_filter_str) panic(6,"stop filter already given");
151 stop_filter_str = g_strdup(optarg);
152 break;
153 case 'f':
154 if (capture_filter_str) panic(7,"capture filter already given");
155 capture_filter_str = g_strdup(optarg);
156 break;
157 case 'p':
158 promisc = 1;
159 break;
160 case 'q':
161 quiet = 1;
162 break;
163 case 'd':
164 debug_level++;
165 break;
166 case 'h':
167 default:
168 usage(0);
169 break;
173 dprintf(1,"starting with:\n interface: %s\n snaplen: %d\n promisc: %d"
174 "\n outfile: %s\n capture filter: %s\n start: %s\n stop: %s\n debug level: %d\n",
175 interface ? interface : "to be chosen",
176 snaplen,
177 promisc,
178 outfile ? outfile : "** missing **",
179 capture_filter_str ? capture_filter_str : "** none given **",
180 start_filter_str ? start_filter_str : "** missing **",
181 stop_filter_str ? stop_filter_str : "** missing **",
182 debug_level);
184 if (! ( start_filter_str && stop_filter_str && outfile ) ) {
185 usage(10);
188 if (! interface) {
189 interface = pcap_lookupdev(errbuf);
190 if (!interface) {
191 panic(11, "could not obtain an interface: %s\n",errbuf);
195 #ifdef HAVE_PCAP_OPEN
196 if ( ! ( capturer = pcap_open(interface, snaplen, promisc, 1, NULL, errbuf) )) {
197 #else
198 if ( ! ( capturer = pcap_open_live(interface, snaplen, promisc, 1, errbuf) )) {
199 #endif
200 panic(12,"could not open interface '%s' for listener: %s\n",interface,errbuf);
203 dprintf(1,"opened listener (%s,%d,%d)\n",interface,snaplen, promisc);
205 if (pcap_compile(listener, &start_filter, start_filter_str, 1, 0) < 0) {
206 panic(13,"could not compile start filter: %s\n",pcap_geterr(listener));
209 dprintf(2,"compiled start filter %s\n",start_filter_str);
211 if (pcap_compile(listener, &stop_filter, stop_filter_str, 1, 0) < 0) {
212 panic(14,"could not compile stop filter: %s\n",pcap_geterr(listener));
215 dprintf(2,"compiled stop filter %s\n",stop_filter_str);
217 #ifdef HAVE_PCAP_OPEN
218 if ( ! ( capturer = pcap_open(interface, snaplen, promisc, 1, NULL, errbuf) )) {
219 #else
220 if ( ! ( capturer = pcap_open_live(interface, snaplen, promisc, 1, errbuf) )) {
221 #endif
222 panic(15,"could not open interface '%s' for capturer: %s\n",interface, errbuf);
225 dprintf(1,"opened capturer (%s,%d,%d)\n",interface,snaplen, promisc);
227 if (capture_filter_str) {
228 if (pcap_compile(capturer, &capture_filter, capture_filter_str, 1, 0) < 0) {
229 panic(16,"could not compile capture filter: %s\n",pcap_geterr(capturer));
231 if (pcap_setfilter(capturer, &capture_filter) < 0) {
232 panic(17,"could not apply start filter to capturer: %s\n",pcap_geterr(capturer));
235 dprintf(2,"compiled and set capture filter (%s)\n",capture_filter_str);
238 if (pcap_setfilter(listener, &start_filter) < 0) {
239 panic(18,"could not apply start filter to listener: %s\n",pcap_geterr(listener));
241 dprintf(2,"set start filter on listener\n");
244 if (pcap_setnonblock(listener, 0, errbuf) < 0) {
245 panic(19,"could not set listener in blocking mode: %s\n",errbuf);
247 dprintf(2,"listener -> blocking\n");
249 if (pcap_setnonblock(capturer, 1, errbuf) < 0) {
250 panic(20,"could not set capturer in non blocking mode: %s\n",errbuf);
252 dprintf(2,"capturer -> non_blocking\n");
254 if (! (dumper = pcap_dump_open(listener,outfile)) ) {
255 panic(21,"open dumper file '%s': %s\n",outfile,pcap_geterr(listener));
257 dprintf(2,"opened dumper file '%s'\n",outfile);
259 signal(SIGINT, sig_int);
260 #ifdef SIGQUIT
261 signal(SIGQUIT, sig_int);
262 #endif
263 #ifdef SIGTERM
264 signal(SIGTERM, sig_int);
265 #endif
266 #ifdef SIGSTOP
267 signal(SIGSTOP, sig_int);
268 #endif
270 keep_going = 1;
271 dumping = 0;
273 do {
274 if (pcap_dispatch(listener, -1, listener_handler, NULL) < 0 ) {
275 panic(22,"pcap_dispatch(listener) failed: %s\n",pcap_geterr(listener));
278 if (pcap_dispatch(capturer, -1, capture_handler, (void*)dumper) < 0 ) {
279 panic(23,"pcap_dispatch(capturer) failed: %s\n",pcap_geterr(capturer));
281 } while(keep_going);
283 if (!quiet) {
284 printf("%d packets captured\n",captured);
287 dprintf(1,"done!\n");
289 pcap_dump_close(dumper);
290 pcap_close(listener);
291 pcap_close(capturer);
293 return 0;