Implement --local-only
authorEmil Mikulic <emikulic@gmail.com>
Sun, 17 Jul 2011 04:51:37 +0000 (14:51 +1000)
committerEmil Mikulic <emikulic@gmail.com>
Sun, 11 Sep 2011 10:50:09 +0000 (20:50 +1000)
I've had a couple of requests for restricting accounting to the local net.

acct.c
darkstat.8.in
darkstat.c
opt.h

diff --git a/acct.c b/acct.c
index 27f48ac..b3c28c3 100644 (file)
--- a/acct.c
+++ b/acct.c
@@ -210,30 +210,37 @@ acct_for(const struct pktsummary * const sm)
 
    /* Hosts. */
    hosts_db_reduce();
-   hs = host_get(&(sm->src));
-   hs->out   += sm->len;
-   hs->total += sm->len;
-   memcpy(hs->u.host.mac_addr, sm->src_mac, sizeof(sm->src_mac));
-   hs->u.host.lastseen = now;
-
-   hd = host_get(&(sm->dst));
-   hd->in    += sm->len;
-   hd->total += sm->len;
-   memcpy(hd->u.host.mac_addr, sm->dst_mac, sizeof(sm->dst_mac));
-   /*
-    * Don't update recipient's last seen time, we don't know that
-    * they received successfully.
-    */
+   if (!opt_want_local_only || addr_is_local(&sm->src)) {
+      hs = host_get(&(sm->src));
+      hs->out   += sm->len;
+      hs->total += sm->len;
+      memcpy(hs->u.host.mac_addr, sm->src_mac, sizeof(sm->src_mac));
+      hs->u.host.lastseen = now;
+   }
+
+   if (!opt_want_local_only || addr_is_local(&sm->dst)) {
+      hd = host_get(&(sm->dst));
+      hd->in    += sm->len;
+      hd->total += sm->len;
+      memcpy(hd->u.host.mac_addr, sm->dst_mac, sizeof(sm->dst_mac));
+      /*
+       * Don't update recipient's last seen time, we don't know that
+       * they received successfully.
+       */
+   }
 
    /* Protocols. */
    if (sm->proto != IPPROTO_INVALID) {
-      ps = host_get_ip_proto(hs, sm->proto);
-      ps->out   += sm->len;
-      ps->total += sm->len;
-
-      pd = host_get_ip_proto(hd, sm->proto);
-      pd->in    += sm->len;
-      pd->total += sm->len;
+      if (hs) {
+         ps = host_get_ip_proto(hs, sm->proto);
+         ps->out   += sm->len;
+         ps->total += sm->len;
+      }
+      if (hd) {
+         pd = host_get_ip_proto(hd, sm->proto);
+         pd->in    += sm->len;
+         pd->total += sm->len;
+      }
    }
 
    if (opt_ports_max == 0) return; /* skip ports accounting */
@@ -241,13 +248,12 @@ acct_for(const struct pktsummary * const sm)
    /* Ports. */
    switch (sm->proto) {
    case IPPROTO_TCP:
-      if (sm->src_port <= opt_highest_port) {
+      if ((sm->src_port <= opt_highest_port) && hs) {
          ps = host_get_port_tcp(hs, sm->src_port);
          ps->out   += sm->len;
          ps->total += sm->len;
       }
-
-      if (sm->dst_port <= opt_highest_port) {
+      if ((sm->dst_port <= opt_highest_port) && hd) {
          pd = host_get_port_tcp(hd, sm->dst_port);
          pd->in    += sm->len;
          pd->total += sm->len;
@@ -257,13 +263,12 @@ acct_for(const struct pktsummary * const sm)
       break;
 
    case IPPROTO_UDP:
-      if (sm->src_port <= opt_highest_port) {
+      if ((sm->src_port <= opt_highest_port) && hs) {
          ps = host_get_port_udp(hs, sm->src_port);
          ps->out   += sm->len;
          ps->total += sm->len;
       }
-
-      if (sm->dst_port <= opt_highest_port) {
+      if ((sm->dst_port <= opt_highest_port) && hd) {
          pd = host_get_port_udp(hd, sm->dst_port);
          pd->in    += sm->len;
          pd->total += sm->len;
index d4a5cc2..e786af3 100644 (file)
@@ -42,6 +42,8 @@ darkstat \- network statistics gatherer
 ] [
 .BI \-l " network/netmask"
 ] [
+.BI \-\-local\-only
+] [
 .BI \-\-chroot " dir"
 ] [
 .BI \-\-user " username"
@@ -188,6 +190,11 @@ See the usage example below.
 .RE
 .\"
 .TP
+.BI \-\-local\-only
+Make the web interface only display hosts on the "local network."
+This is intended to be used together with the \fB\-l\fR argument.
+.\"
+.TP
 .BI \-\-chroot " dir"
 Force \fIdarkstat\fR to \fBchroot()\fR into the specified directory.
 Without this argument, a default directory will be used, which is
index 6bdae18..75f5c2c 100644 (file)
@@ -114,7 +114,16 @@ static void cb_bindaddr(const char *arg) { http_add_bindaddr(arg); }
 const char *opt_filter = NULL;
 static void cb_filter(const char *arg) { opt_filter = arg; }
 
-static void cb_local(const char *arg) { acct_init_localnet(arg); }
+static int is_localnet_specified = 0;
+static void cb_local(const char *arg)
+{
+   acct_init_localnet(arg);
+   is_localnet_specified = 1;
+}
+
+int opt_want_local_only = 0;
+static void cb_local_only(const char *arg _unused_)
+{ opt_want_local_only = 1; }
 
 const char *opt_chroot_dir = NULL;
 static void cb_chroot(const char *arg) { opt_chroot_dir = arg; }
@@ -211,6 +220,7 @@ static struct cmdline_arg cmdline_args[] = {
    {"-b",             "bindaddr",        cb_bindaddr,    -1},
    {"-f",             "filter",          cb_filter,       0},
    {"-l",             "network/netmask", cb_local,        0},
+   {"--local-only",   NULL,              cb_local_only,   0},
    {"--snaplen",      "bytes",           cb_snaplen,      0},
    {"--pppoe",        NULL,              cb_pppoe,        0},
    {"--syslog",       NULL,              cb_syslog,       0},
@@ -364,6 +374,9 @@ parse_cmdline(const int argc, char * const *argv)
       opt_want_daemonize = 0;
       verbosef("--hexdump implies --no-daemon");
    }
+
+   if (opt_want_local_only && !is_localnet_specified)
+      verbosef("WARNING: --local-only without -l only matches the local host");
 }
 
 static void
diff --git a/opt.h b/opt.h
index d7cbd10..5d75cf3 100644 (file)
--- a/opt.h
+++ b/opt.h
@@ -23,6 +23,7 @@ extern int opt_want_syslog;
  * Accounting options.
  */
 extern unsigned int opt_highest_port;
+extern int opt_want_local_only;
 
 /*
  * Hosts table reduction - when the number of entries is about to exceed
@@ -39,4 +40,4 @@ extern unsigned int opt_ports_keep;
 extern int opt_want_lastseen;
 extern const char *opt_interface;
 
-
+/* vim:set ts=3 sw=3 tw=78 expandtab: */