/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* cap.c: capture packets, and hand them off to decode and acct.
*
free(tmp_filter);
}
+/* Start capturing on just one interface. Called from cap_start(). */
static void cap_start_one(struct cap_iface *iface, const int promisc) {
char errbuf[PCAP_ERRBUF_SIZE], *tmp_device;
int linktype, snaplen, waited;
acct_for(&sm, &iface->local_ips);
}
-/* Process any packets currently in the capture buffer. */
-void cap_poll(fd_set *read_set _unused_on_linux_) {
+/* Process any packets currently in the capture buffer.
+ * Returns 0 on error (usually means the interface went down).
+ */
+int cap_poll(fd_set *read_set _unused_on_linux_) {
struct cap_iface *iface;
+ static int told = 0;
STAILQ_FOREACH(iface, &cap_ifs, entries) {
/* Once per capture poll, check our IP address. It's used in accounting
* for traffic graphs.
*/
localip_update(iface->name, &iface->local_ips);
+ if (!told && iface->local_ips.num_addrs == 0) {
+ verbosef("interface '%s' has no addresses, "
+ "your graphs will be blank",
+ iface->name);
+ verbosef("please read the darkstat manpage, "
+ "and consider using the -l option");
+ told = 1;
+ }
for (;;) {
struct timespec t;
-1, /* count = entire buffer */
callback,
(u_char*)iface); /* user = struct to pass to callback */
+ timer_stop(&t,
+ 2 * CAP_TIMEOUT_MSEC * 1000000,
+ "pcap_dispatch took too long");
if (ret < 0) {
warnx("pcap_dispatch('%s'): %s",
iface->name, pcap_geterr(iface->pcap));
- continue;
+ return 0;
}
- timer_stop(&t,
- 2 * CAP_TIMEOUT_MSEC * 1000000,
- "pcap_dispatch took too long");
- if (0) /* debugging */
- verbosef("iface '%s' got %d pkts", iface->name, ret);
+#if 0 /* debugging */
+ verbosef("iface '%s' got %d pkts", iface->name, ret);
+#endif
#ifdef linux
/* keep looping until we've dispatched all the outstanding packets */
}
}
cap_stats_update();
+ return 1;
}
void cap_stop(void) {
title_interfaces = NULL;
}
+/* This is only needed by the DNS child. In the main process, the deallocation
+ * happens in cap_start().
+ */
+void cap_free_args(void) {
+ while (!STAILQ_EMPTY(&cli_ifnames)) {
+ struct strnode *ifname = STAILQ_FIRST(&cli_ifnames);
+ STAILQ_REMOVE_HEAD(&cli_ifnames, entries);
+ free(ifname);
+ }
+
+ while (!STAILQ_EMPTY(&cli_filters)) {
+ struct strnode *filter = STAILQ_FIRST(&cli_filters);
+ STAILQ_REMOVE_HEAD(&cli_filters, entries);
+ free(filter);
+ }
+}
+
/* Run through entire capfile. */
void cap_from_file(const char *capfile) {
char errbuf[PCAP_ERRBUF_SIZE];