Qt: use data() instead of constData() in pcap_compile().
[metze/wireshark/wip.git] / trigcap.c
1 /*
2  * trigcap
3  * a simple triggered libpcap-based capture agent
4  *
5  * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stdarg.h>
13 #include <string.h>
14 #include <signal.h>
15 #include <errno.h>
16 #include <getopt.h>
17
18 #include <wsutil/wspcap.h>
19
20 static int dumping;
21 static volatile int keep_going;
22 static pcap_t* listener;
23 static struct bpf_program stop_filter;
24 static int captured = 0;
25 static int debug_level = 0;
26
27 static void panic(int err, const char* fmt, ...) {
28         va_list ap;
29         va_start(ap,fmt);
30         vfprintf(stderr,fmt,ap);
31         va_end(ap);
32         exit(err);
33 }
34
35 static void dprintf(int lev, const char* fmt, ...) {
36         va_list ap;
37
38         if (lev <= debug_level) {
39                 va_start(ap,fmt);
40                 vfprintf(stderr,fmt,ap);
41                 va_end(ap);
42                 fflush(stderr);
43         }
44 }
45
46
47 static void usage(int err) {
48         const char* usage_str = "usage:\n"
49         "trigcap -w outfile -b begin -e end [-f capture] [-i iface] [-s snaplen] [-p] [-q] [-d [-d [-d [-d]]]]\n"
50         "   -w output file\n"
51         "   -b filter to start capturing\n"
52         "   -e filter to stop capturing\n"
53         "   -f capture filter\n"
54         "   -p promiscuous mode\n"
55         "   -s snapshot length\n"
56         "   -q quiet\n"
57         "   -d increase debug level\n"
58         "   -h prints this message\n"
59         ;
60
61         panic(err,usage_str);
62 }
63
64 static void listener_handler(u_char* u, const struct pcap_pkthdr * ph, const u_char* buf) {
65         char errbuf[PCAP_ERRBUF_SIZE];
66
67         dprintf(2,"listener handler invoked dumping=%d\n",dumping);
68
69         if (dumping) {
70                 dprintf(2,"last round\n");
71                 keep_going = 0;
72         } else {
73                 if (pcap_setfilter(listener, &stop_filter) < 0) {
74                         panic(23,"could not apply stop filter to listener: %s\n",pcap_geterr(listener));
75                 }
76
77                 dprintf(2,"apply stop filter to listener\n");
78
79                 if (pcap_setnonblock(listener, 1, errbuf) < 0) {
80                         panic(24,"could not set listener in non blocking mode: %s\n",errbuf);
81                 }
82
83                 dprintf(2,"listener -> non_blocking\n");
84                 dumping = 1;
85         }
86 }
87
88 static void capture_handler(u_char* dumper, const struct pcap_pkthdr * ph, const u_char* buf) {
89         dprintf(4,"capture handler invoked dumping=%d\n",dumping);
90         if (dumping) {
91                 captured++;
92                 pcap_dump(dumper, ph, buf);
93         }
94 }
95
96 static void sig_int(int sig) {
97         keep_going = 0;
98 }
99
100 int main(int argc, char** argv) {
101         char errbuf[PCAP_ERRBUF_SIZE];
102         char* interface = NULL;
103         char* outfile = NULL;
104         guint snaplen = 65536;
105         char* start_filter_str = NULL;
106         char* stop_filter_str = NULL;
107         char* capture_filter_str = NULL;
108         int promisc = 0;
109         int quiet = 0;
110         struct bpf_program start_filter;
111         struct bpf_program capture_filter;
112         pcap_t* capturer = NULL;
113         pcap_dumper_t* dumper = NULL;
114         int opt;
115
116         while ((opt = getopt(argc, argv, "i:w:s:b:e:f:phdq")) != -1) {
117                 switch (opt) {
118                         case 'i':
119                                 if (interface) panic(1,"interface already given");
120                                 interface = g_strdup(optarg);
121                                 break;
122                         case 'w':
123                                 if (outfile) panic(3,"output file already given");
124                                 outfile = g_strdup(optarg);
125                                 break;
126                         case 's':
127                                 snaplen = strtoul(optarg,NULL,10);
128                                 if ( snaplen == 0 )
129                                         panic(4,"invalid snaplen");
130                                 break;
131                         case 'b':
132                                 if (start_filter_str) panic(5,"start filter already given");
133                                 start_filter_str = g_strdup(optarg);
134                                 break;
135                         case 'e':
136                                 if (stop_filter_str) panic(6,"stop filter already given");
137                                 stop_filter_str = g_strdup(optarg);
138                                 break;
139                         case 'f':
140                                 if (capture_filter_str) panic(7,"capture filter already given");
141                                 capture_filter_str = g_strdup(optarg);
142                                 break;
143                         case 'p':
144                                 promisc = 1;
145                                 break;
146                         case 'q':
147                                 quiet = 1;
148                                 break;
149                         case 'd':
150                                 debug_level++;
151                                 break;
152                         case 'h':
153                         default:
154                                 usage(0);
155                                 break;
156                         }
157                 }
158
159         dprintf(1,"starting with:\n interface: %s\n snaplen: %d\n promisc: %d"
160                         "\n outfile: %s\n capture filter: %s\n start: %s\n stop: %s\n debug level: %d\n",
161                         interface ? interface : "to be chosen",
162                         snaplen,
163                         promisc,
164                         outfile ? outfile : "** missing **",
165                         capture_filter_str ? capture_filter_str : "** none given **",
166                         start_filter_str ? start_filter_str : "** missing **",
167                         stop_filter_str ? stop_filter_str : "** missing **",
168                         debug_level);
169
170         if (! ( start_filter_str && stop_filter_str && outfile ) ) {
171                 usage(10);
172         }
173
174         if (! interface) {
175                 interface = pcap_lookupdev(errbuf);
176                 if (!interface) {
177                         panic(11, "could not obtain an interface: %s\n",errbuf);
178                 }
179         }
180
181 #ifdef HAVE_PCAP_OPEN
182         if ( ! ( capturer = pcap_open(interface, snaplen, promisc, 1, NULL, errbuf) )) {
183 #else
184         if ( ! ( capturer = pcap_open_live(interface, snaplen, promisc, 1, errbuf) )) {
185 #endif
186                 panic(12,"could not open interface '%s' for listener: %s\n",interface,errbuf);
187         }
188
189         dprintf(1,"opened listener (%s,%d,%d)\n",interface,snaplen, promisc);
190
191         if (pcap_compile(listener, &start_filter, start_filter_str, 1, 0) < 0) {
192                 panic(13,"could not compile start filter: %s\n",pcap_geterr(listener));
193         }
194
195         dprintf(2,"compiled start filter %s\n",start_filter_str);
196
197         if (pcap_compile(listener, &stop_filter, stop_filter_str, 1, 0) < 0) {
198                 panic(14,"could not compile stop filter: %s\n",pcap_geterr(listener));
199         }
200
201         dprintf(2,"compiled stop filter %s\n",stop_filter_str);
202
203 #ifdef HAVE_PCAP_OPEN
204         if ( ! ( capturer = pcap_open(interface, snaplen, promisc, 1, NULL, errbuf) )) {
205 #else
206         if ( ! ( capturer = pcap_open_live(interface, snaplen, promisc, 1, errbuf) )) {
207 #endif
208                 panic(15,"could not open interface '%s' for capturer: %s\n",interface, errbuf);
209         }
210
211         dprintf(1,"opened capturer (%s,%d,%d)\n",interface,snaplen, promisc);
212
213         if (capture_filter_str) {
214                 if (pcap_compile(capturer, &capture_filter, capture_filter_str, 1, 0) < 0) {
215                         panic(16,"could not compile capture filter: %s\n",pcap_geterr(capturer));
216                 }
217                 if (pcap_setfilter(capturer, &capture_filter) < 0) {
218                         panic(17,"could not apply start filter to capturer: %s\n",pcap_geterr(capturer));
219                 }
220
221                 dprintf(2,"compiled and set capture filter (%s)\n",capture_filter_str);
222         }
223
224         if (pcap_setfilter(listener, &start_filter) < 0) {
225                 panic(18,"could not apply start filter to listener: %s\n",pcap_geterr(listener));
226         }
227         dprintf(2,"set start filter on listener\n");
228
229
230         if (pcap_setnonblock(listener, 0, errbuf) < 0) {
231                 panic(19,"could not set listener in blocking mode: %s\n",errbuf);
232         }
233         dprintf(2,"listener -> blocking\n");
234
235         if (pcap_setnonblock(capturer, 1, errbuf) < 0) {
236                 panic(20,"could not set capturer in non blocking mode: %s\n",errbuf);
237         }
238         dprintf(2,"capturer -> non_blocking\n");
239
240         if (! (dumper = pcap_dump_open(listener,outfile)) ) {
241                 panic(21,"open dumper file '%s': %s\n",outfile,pcap_geterr(listener));
242         }
243         dprintf(2,"opened dumper file '%s'\n",outfile);
244
245         signal(SIGINT, sig_int);
246 #ifdef SIGQUIT
247         signal(SIGQUIT, sig_int);
248 #endif
249 #ifdef SIGTERM
250         signal(SIGTERM, sig_int);
251 #endif
252 #ifdef SIGSTOP
253         signal(SIGSTOP, sig_int);
254 #endif
255
256         keep_going = 1;
257         dumping = 0;
258
259         do {
260                 if (pcap_dispatch(listener, -1, listener_handler, NULL) < 0 ) {
261                         panic(22,"pcap_dispatch(listener) failed: %s\n",pcap_geterr(listener));
262                 }
263
264                 if (pcap_dispatch(capturer, -1, capture_handler, (void*)dumper) < 0 ) {
265                         panic(23,"pcap_dispatch(capturer) failed: %s\n",pcap_geterr(capturer));
266                 }
267         } while(keep_going);
268
269         if (!quiet) {
270                 printf("%d packets captured\n",captured);
271         }
272
273         dprintf(1,"done!\n");
274
275         pcap_dump_close(dumper);
276         pcap_close(listener);
277         pcap_close(capturer);
278
279         return 0;
280 }
281
282 /*
283  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
284  *
285  * Local variables:
286  * c-basic-offset: 8
287  * tab-width: 8
288  * indent-tabs-mode: t
289  * End:
290  *
291  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
292  * :indentSize=8:tabSize=8:noTabs=false:
293  */