3 * a simple triggered libpcap-based capture agent
5 * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
7 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include <wsutil/wspcap.h>
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;
27 static void panic(int err, const char* fmt, ...) {
30 vfprintf(stderr,fmt,ap);
35 static void dprintf(int lev, const char* fmt, ...) {
38 if (lev <= debug_level) {
40 vfprintf(stderr,fmt,ap);
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"
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"
57 " -d increase debug level\n"
58 " -h prints this message\n"
64 static void listener_handler(u_char* u, const struct pcap_pkthdr * ph, const u_char* buf) {
65 char errbuf[PCAP_ERRBUF_SIZE];
67 dprintf(2,"listener handler invoked dumping=%d\n",dumping);
70 dprintf(2,"last round\n");
73 if (pcap_setfilter(listener, &stop_filter) < 0) {
74 panic(23,"could not apply stop filter to listener: %s\n",pcap_geterr(listener));
77 dprintf(2,"apply stop filter to listener\n");
79 if (pcap_setnonblock(listener, 1, errbuf) < 0) {
80 panic(24,"could not set listener in non blocking mode: %s\n",errbuf);
83 dprintf(2,"listener -> non_blocking\n");
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);
92 pcap_dump(dumper, ph, buf);
96 static void sig_int(int sig) {
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;
110 struct bpf_program start_filter;
111 struct bpf_program capture_filter;
112 pcap_t* capturer = NULL;
113 pcap_dumper_t* dumper = NULL;
116 while ((opt = getopt(argc, argv, "i:w:s:b:e:f:phdq")) != -1) {
119 if (interface) panic(1,"interface already given");
120 interface = g_strdup(optarg);
123 if (outfile) panic(3,"output file already given");
124 outfile = g_strdup(optarg);
127 snaplen = strtoul(optarg,NULL,10);
129 panic(4,"invalid snaplen");
132 if (start_filter_str) panic(5,"start filter already given");
133 start_filter_str = g_strdup(optarg);
136 if (stop_filter_str) panic(6,"stop filter already given");
137 stop_filter_str = g_strdup(optarg);
140 if (capture_filter_str) panic(7,"capture filter already given");
141 capture_filter_str = g_strdup(optarg);
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",
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 **",
170 if (! ( start_filter_str && stop_filter_str && outfile ) ) {
175 interface = pcap_lookupdev(errbuf);
177 panic(11, "could not obtain an interface: %s\n",errbuf);
181 #ifdef HAVE_PCAP_OPEN
182 if ( ! ( capturer = pcap_open(interface, snaplen, promisc, 1, NULL, errbuf) )) {
184 if ( ! ( capturer = pcap_open_live(interface, snaplen, promisc, 1, errbuf) )) {
186 panic(12,"could not open interface '%s' for listener: %s\n",interface,errbuf);
189 dprintf(1,"opened listener (%s,%d,%d)\n",interface,snaplen, promisc);
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));
195 dprintf(2,"compiled start filter %s\n",start_filter_str);
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));
201 dprintf(2,"compiled stop filter %s\n",stop_filter_str);
203 #ifdef HAVE_PCAP_OPEN
204 if ( ! ( capturer = pcap_open(interface, snaplen, promisc, 1, NULL, errbuf) )) {
206 if ( ! ( capturer = pcap_open_live(interface, snaplen, promisc, 1, errbuf) )) {
208 panic(15,"could not open interface '%s' for capturer: %s\n",interface, errbuf);
211 dprintf(1,"opened capturer (%s,%d,%d)\n",interface,snaplen, promisc);
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));
217 if (pcap_setfilter(capturer, &capture_filter) < 0) {
218 panic(17,"could not apply start filter to capturer: %s\n",pcap_geterr(capturer));
221 dprintf(2,"compiled and set capture filter (%s)\n",capture_filter_str);
224 if (pcap_setfilter(listener, &start_filter) < 0) {
225 panic(18,"could not apply start filter to listener: %s\n",pcap_geterr(listener));
227 dprintf(2,"set start filter on listener\n");
230 if (pcap_setnonblock(listener, 0, errbuf) < 0) {
231 panic(19,"could not set listener in blocking mode: %s\n",errbuf);
233 dprintf(2,"listener -> blocking\n");
235 if (pcap_setnonblock(capturer, 1, errbuf) < 0) {
236 panic(20,"could not set capturer in non blocking mode: %s\n",errbuf);
238 dprintf(2,"capturer -> non_blocking\n");
240 if (! (dumper = pcap_dump_open(listener,outfile)) ) {
241 panic(21,"open dumper file '%s': %s\n",outfile,pcap_geterr(listener));
243 dprintf(2,"opened dumper file '%s'\n",outfile);
245 signal(SIGINT, sig_int);
247 signal(SIGQUIT, sig_int);
250 signal(SIGTERM, sig_int);
253 signal(SIGSTOP, sig_int);
260 if (pcap_dispatch(listener, -1, listener_handler, NULL) < 0 ) {
261 panic(22,"pcap_dispatch(listener) failed: %s\n",pcap_geterr(listener));
264 if (pcap_dispatch(capturer, -1, capture_handler, (void*)dumper) < 0 ) {
265 panic(23,"pcap_dispatch(capturer) failed: %s\n",pcap_geterr(capturer));
270 printf("%d packets captured\n",captured);
273 dprintf(1,"done!\n");
275 pcap_dump_close(dumper);
276 pcap_close(listener);
277 pcap_close(capturer);
283 * Editor modelines - http://www.wireshark.org/tools/modelines.html
288 * indent-tabs-mode: t
291 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
292 * :indentSize=8:tabSize=8:noTabs=false: