Implement --wait
authorEmil Mikulic <emikulic@gmail.com>
Sun, 17 Jan 2010 14:17:11 +0000 (01:17 +1100)
committerEmil Mikulic <emikulic@gmail.com>
Wed, 17 Mar 2010 10:18:17 +0000 (21:18 +1100)
cap.c
darkstat.8
darkstat.c

diff --git a/cap.c b/cap.c
index a49e1e2..043f2f3 100644 (file)
--- a/cap.c
+++ b/cap.c
@@ -1,5 +1,5 @@
 /* darkstat 3
- * copyright (c) 2001-2009 Emil Mikulic.
+ * copyright (c) 2001-2010 Emil Mikulic.
  *
  * cap.c: interface to libpcap.
  *
@@ -28,7 +28,7 @@
 #include <string.h>
 #include <unistd.h>
 
-extern int want_pppoe, want_macs, want_hexdump, want_snaplen;
+extern int want_pppoe, want_macs, want_hexdump, want_snaplen, wait_secs;
 
 /* The cap process life-cycle:
  *
@@ -52,22 +52,34 @@ void
 cap_init(const char *device, const char *filter, int promisc)
 {
    char errbuf[PCAP_ERRBUF_SIZE], *tmp_device;
-   int linktype, snaplen;
+   int linktype, snaplen, waited;
 
    /* pcap doesn't like device being const */
    tmp_device = xstrdup(device);
 
    /* Open packet capture descriptor. */
-   errbuf[0] = '\0'; /* zero length string */
-   pcap = pcap_open_live(
-      tmp_device,
-      1,          /* snaplen, irrelevant at this point */
-      0,          /* promisc, also irrelevant */
-      CAP_TIMEOUT,
-      errbuf);
-
-   if (pcap == NULL)
-      errx(1, "pcap_open_live(): %s", errbuf);
+   waited = 0;
+   for (;;) {
+      errbuf[0] = '\0'; /* zero length string */
+      pcap = pcap_open_live(
+         tmp_device,
+         1,          /* snaplen, irrelevant at this point */
+         0,          /* promisc, also irrelevant */
+         CAP_TIMEOUT,
+         errbuf);
+      if (pcap != NULL) break; /* success! */
+
+      if ((wait_secs != -1) && strstr(errbuf, "device is not up")) {
+         if ((wait_secs > 0) && (waited >= wait_secs))
+            errx(1, "waited %d secs, giving up: pcap_open_live(): %s",
+               waited, errbuf);
+
+         verbosef("waited %d secs, interface is not up", waited);
+         sleep(1);
+         waited++;
+      }
+      else errx(1, "pcap_open_live(): %s", errbuf);
+   }
 
    /* Work out the linktype and what snaplen we need. */
    linktype = pcap_datalink(pcap);
index 69da188..d059c17 100644 (file)
@@ -64,6 +64,8 @@ darkstat \- network statistics gatherer
 ] [
 .BI \-\-highest\-port " port"
 ] [
+.BI \-\-wait " secs"
+] [
 .BI \-\-hexdump
 ]
 .\"
@@ -316,6 +318,18 @@ This can be used to hide ephemeral ports.
 By default, all ports are tracked.
 .\"
 .TP
+.BI \-\-wait " secs"
+Don't use this.
+It's a hack to help victims of \fINetworkManager\fR and similar systems.
+.RS
+
+You should start \fIdarkstat\fR after the capture interface has come up.
+If you can't, specifying the \fB\-\-wait\fR option will make \fIdarkstat\fR
+sleep up to the specified number of seconds for the interface to become ready.
+Zero means wait indefinitely.
+.RE
+.\"
+.TP
 .BI \-\-hexdump
 Show hex dumps of received traffic.
 This is only for debugging, and implies \fB\-\-verbose\fR and
index f079203..6b393c7 100644 (file)
@@ -1,5 +1,5 @@
 /* darkstat 3
- * copyright (c) 2001-2009 Emil Mikulic.
+ * copyright (c) 2001-2010 Emil Mikulic.
  *
  * darkstat.c: signals, cmdline parsing, program body.
  *
@@ -177,6 +177,10 @@ unsigned int highest_port = 65535;
 static void cb_highest_port(const char *arg)
 { highest_port = parsenum(arg, 65535); }
 
+int wait_secs = -1;
+static void cb_wait_secs(const char *arg)
+{ wait_secs = parsenum(arg, 0); }
+
 int want_hexdump = 0;
 static void cb_hexdump(const char *arg _unused_) { want_hexdump = 1; }
 
@@ -215,6 +219,7 @@ static struct cmdline_arg cmdline_args[] = {
    {"--ports-max",    "count",           cb_ports_max,    0},
    {"--ports-keep",   "count",           cb_ports_keep,   0},
    {"--highest-port", "port",            cb_highest_port, 0},
+   {"--wait",         "secs",            cb_wait_secs,    0},
    {"--hexdump",      NULL,              cb_hexdump,      0},
    {NULL,             NULL,              NULL,            0}
 };