2 * copyright (c) 2001-2008 Emil Mikulic.
4 * cap.c: interface to libpcap.
6 * You may use, modify and redistribute this file under the terms of the
7 * GNU General Public License version 2. (see COPYING.GPL)
17 #include <sys/ioctl.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
21 #ifdef HAVE_SYS_FILIO_H
22 # include <sys/filio.h> /* Solaris' FIONBIO hides here */
31 extern int want_pppoe
, want_macs
;
33 /* The cap process life-cycle:
36 * Fill fd_set - cap_fd_set()
41 /* Globals - only useful within this module. */
42 static pcap_t
*pcap
= NULL
;
43 static int pcap_fd
= -1;
44 static const linkhdr_t
*linkhdr
= NULL
;
46 #define CAP_TIMEOUT 500 /* granularity of capture buffer, in milliseconds */
48 /* ---------------------------------------------------------------------------
49 * Init pcap. Exits on failure.
52 cap_init(const char *device
, const char *filter
, int promisc
)
54 char errbuf
[PCAP_ERRBUF_SIZE
], *tmp_device
;
57 /* pcap doesn't like device being const */
58 tmp_device
= xstrdup(device
);
60 /* Open packet capture descriptor. */
61 errbuf
[0] = '\0'; /* zero length string */
62 pcap
= pcap_open_live(
64 1, /* snaplen, irrelevant at this point */
65 0, /* promisc, also irrelevant */
70 errx(1, "pcap_open_live(): %s", errbuf
);
72 /* Work out the linktype and what caplen it needs. */
73 linktype
= pcap_datalink(pcap
);
74 verbosef("linktype is %d", linktype
);
75 if ((linktype
== DLT_EN10MB
) && want_macs
)
77 linkhdr
= getlinkhdr(linktype
);
79 errx(1, "unknown linktype %d", linktype
);
80 if (linkhdr
->handler
== NULL
)
81 errx(1, "no handler for linktype %d", linktype
);
82 caplen
= getcaplen(linkhdr
);
84 caplen
+= PPPOE_HDR_LEN
;
85 if (linktype
!= DLT_EN10MB
)
86 errx(1, "can't do PPPoE decoding on a non-Ethernet linktype");
88 verbosef("caplen is %d", caplen
);
90 /* Close and re-open pcap to use the new caplen. */
92 errbuf
[0] = '\0'; /* zero length string */
93 pcap
= pcap_open_live(
101 errx(1, "pcap_open_live(): %s", errbuf
);
103 if (errbuf
[0] != '\0') /* not zero length anymore -> warning */
104 warnx("pcap_open_live() warning: %s", errbuf
);
109 verbosef("capturing in promiscuous mode");
111 verbosef("capturing in non-promiscuous mode");
113 /* Set filter expression, if any. */
116 struct bpf_program prog
;
117 char *tmp_filter
= xstrdup(filter
);
125 errx(1, "pcap_compile(): %s", pcap_geterr(pcap
));
127 if (pcap_setfilter(pcap
, &prog
) == -1)
128 errx(1, "pcap_setfilter(): %s", pcap_geterr(pcap
));
130 pcap_freecode(&prog
);
134 pcap_fd
= pcap_fileno(pcap
);
136 /* set non-blocking */
138 if (ioctl(pcap_fd
, FIONBIO
, &one
) == -1)
139 err(1, "ioctl(pcap_fd, FIONBIO)"); }
143 /* Deny all writes to the socket */
144 struct bpf_insn bpf_wfilter
[] = { BPF_STMT(BPF_RET
+BPF_K
, 0) };
145 int wf_len
= sizeof(bpf_wfilter
) / sizeof(struct bpf_insn
);
146 struct bpf_program pr
;
149 pr
.bf_insns
= bpf_wfilter
;
151 if (ioctl(pcap_fd
, BIOCSETWF
, &pr
) == -1)
152 err(1, "ioctl(pcap_fd, BIOCSETFW)");
153 verbosef("filtered out BPF writes");
158 /* set "locked" flag (no reset) */
159 if (ioctl(pcap_fd
, BIOCLOCK
) == -1)
160 err(1, "ioctl(pcap_fd, BIOCLOCK)");
161 verbosef("locked down BPF for security");
166 * Set pcap_fd in the given fd_set.
171 fd_set
*read_set _unused_
,
172 int *max_fd _unused_
,
173 struct timeval
*timeout
,
177 struct timeval
*timeout _unused_
,
181 assert(*need_timeout
== 0); /* we're first to get a shot at this */
184 * Linux's BPF is immediate, so don't select() as it will lead to horrible
185 * performance. Instead, use a timeout for buffering.
189 timeout
->tv_usec
= CAP_TIMEOUT
* 1000; /* msec->usec */
191 /* We have a BSD-like BPF, we can select() on it. */
192 FD_SET(pcap_fd
, read_set
);
193 *max_fd
= max(*max_fd
, pcap_fd
);
197 unsigned int pkts_recv
= 0, pkts_drop
= 0;
200 cap_stats_update(void)
204 if (pcap_stats(pcap
, &ps
) != 0) {
205 warnx("pcap_stats(): %s", pcap_geterr(pcap
));
209 pkts_recv
= ps
.ps_recv
;
210 pkts_drop
= ps
.ps_drop
;
215 * Process any packets currently in the capture buffer.
218 cap_poll(fd_set
*read_set
226 #ifndef linux /* We don't use select() on Linux. */
227 if (!FD_ISSET(pcap_fd
, read_set
)) {
228 verbosef("cap_poll premature");
234 * Once per capture poll, check our IP address. It's used in accounting
235 * for traffic graphs.
237 localip_update(); /* FIXME: this might even be too often */
243 -1, /* count, -1 = entire buffer */
244 linkhdr
->handler
, /* callback func from decode.c */
248 errx(1, "pcap_dispatch(): %s", pcap_geterr(pcap
));
250 /* Despite count = -1, Linux will only dispatch one packet at a time. */
254 /* keep looping until we've dispatched all the outstanding packets */
257 /* we get them all on the first shot */
261 /*FIXME*/if (want_verbose
) fprintf(stderr
, "%-20d\r", total
);
271 /* Run through entire capfile. */
273 cap_from_file(const char *capfile
, const char *filter
)
275 char errbuf
[PCAP_ERRBUF_SIZE
];
278 /* Open packet capture descriptor. */
279 errbuf
[0] = '\0'; /* zero length string */
280 pcap
= pcap_open_offline(capfile
, errbuf
);
283 errx(1, "pcap_open_offline(): %s", errbuf
);
285 if (errbuf
[0] != '\0') /* not zero length anymore -> warning */
286 warnx("pcap_open_offline() warning: %s", errbuf
);
288 /* Work out the linktype. */
289 linktype
= pcap_datalink(pcap
);
290 linkhdr
= getlinkhdr(linktype
);
292 errx(1, "unknown linktype %d", linktype
);
293 if (linkhdr
->handler
== NULL
)
294 errx(1, "no handler for linktype %d", linktype
);
295 if (linktype
== DLT_EN10MB
) /* FIXME: impossible with capfile? */
298 /* Set filter expression, if any. */ /* FIXME: factor! */
301 struct bpf_program prog
;
302 char *tmp_filter
= xstrdup(filter
);
310 errx(1, "pcap_compile(): %s", pcap_geterr(pcap
));
312 if (pcap_setfilter(pcap
, &prog
) == -1)
313 errx(1, "pcap_setfilter(): %s", pcap_geterr(pcap
));
315 pcap_freecode(&prog
);
322 -1, /* count, -1 = entire buffer */
323 linkhdr
->handler
, /* callback func from decode.c */
327 errx(1, "pcap_dispatch(): %s", pcap_geterr(pcap
));
330 /* vim:set ts=3 sw=3 tw=78 expandtab: */