3 * a simple triggered libpcap-based capture agent
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.
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
, ...) {
44 vfprintf(stderr
,fmt
,ap
);
49 static void dprintf(int lev
, const char* fmt
, ...) {
52 if (lev
<= debug_level
) {
54 vfprintf(stderr
,fmt
,ap
);
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"
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"
71 " -d increase debug level\n"
72 " -h prints this message\n"
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
);
84 dprintf(2,"last round\n");
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");
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
);
106 pcap_dump(dumper
, ph
, buf
);
110 static void sig_int(int sig
) {
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
;
124 struct bpf_program start_filter
;
125 struct bpf_program capture_filter
;
126 pcap_t
* capturer
= NULL
;
127 pcap_dumper_t
* dumper
= NULL
;
130 while ((opt
= getopt(argc
, argv
, "i:w:s:b:e:f:phdq")) != -1) {
133 if (interface
) panic(1,"interface already given");
134 interface
= g_strdup(optarg
);
137 if (outfile
) panic(3,"output file already given");
138 outfile
= g_strdup(optarg
);
141 snaplen
= strtoul(optarg
,NULL
,10);
143 panic(4,"invalid snaplen");
146 if (start_filter_str
) panic(5,"start filter already given");
147 start_filter_str
= g_strdup(optarg
);
150 if (stop_filter_str
) panic(6,"stop filter already given");
151 stop_filter_str
= g_strdup(optarg
);
154 if (capture_filter_str
) panic(7,"capture filter already given");
155 capture_filter_str
= g_strdup(optarg
);
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",
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 **",
184 if (! ( start_filter_str
&& stop_filter_str
&& outfile
) ) {
189 interface
= pcap_lookupdev(errbuf
);
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
) )) {
198 if ( ! ( capturer
= pcap_open_live(interface
, snaplen
, promisc
, 1, errbuf
) )) {
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
) )) {
220 if ( ! ( capturer
= pcap_open_live(interface
, snaplen
, promisc
, 1, errbuf
) )) {
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
);
261 signal(SIGQUIT
, sig_int
);
264 signal(SIGTERM
, sig_int
);
267 signal(SIGSTOP
, sig_int
);
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
));
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
);