Fine tuning for OpenBSD and GNU/kfreebsd.
[darkstat] / darkstat.c
index b654da9..da3b92d 100644 (file)
@@ -1,5 +1,5 @@
 /* darkstat 3
- * copyright (c) 2001-2008 Emil Mikulic.
+ * copyright (c) 2001-2010 Emil Mikulic.
  *
  * darkstat.c: signals, cmdline parsing, program body.
  *
 
 #include "err.h"
 #include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
 #include <assert.h>
 #include <errno.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <syslog.h>
 #include <unistd.h>
 #include <pcap.h>
 
@@ -69,9 +72,14 @@ static void cb_interface(const char *arg) { interface = arg; }
 const char *capfile = NULL;
 static void cb_capfile(const char *arg) { capfile = arg; }
 
+int want_snaplen = -1;
+static void cb_snaplen(const char *arg) { want_snaplen = parsenum(arg, 0); }
+
 int want_pppoe = 0;
 static void cb_pppoe(const char *arg _unused_) { want_pppoe = 1; }
 
+static void cb_syslog(const char *arg _unused_) { want_syslog = 1; }
+
 static void cb_verbose(const char *arg _unused_) { want_verbose = 1; }
 
 int want_daemonize = 1;
@@ -86,15 +94,30 @@ static void cb_no_dns(const char *arg _unused_) { want_dns = 0; }
 int want_macs = 1;
 static void cb_no_macs(const char *arg _unused_) { want_macs = 0; }
 
+int want_lastseen = 1;
+static void cb_no_lastseen(const char *arg _unused_) { want_lastseen = 0; }
+
 unsigned short bindport = 667;
 static void cb_port(const char *arg) { bindport = parsenum(arg, 65536); }
 
-in_addr_t bindaddr = INADDR_ANY;
+char * bindaddr = NULL;
 static void cb_bindaddr(const char *arg)
 {
-   bindaddr = inet_addr(arg);
-   if (bindaddr == (in_addr_t)INADDR_NONE)
+   struct addrinfo hints, *ai;
+
+   memset(&hints, '\0', sizeof(hints));
+   hints.ai_flags = AI_PASSIVE;
+#ifdef AI_ADDRCONFIG
+   hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_STREAM;
+
+   if (getaddrinfo(arg, NULL, &hints, &ai))
       errx(1, "malformed address \"%s\"", arg);
+
+   freeaddrinfo(ai);
+   bindaddr = strdup(arg);
 }
 
 const char *filter = NULL;
@@ -168,6 +191,13 @@ 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; }
+
 /* --- */
 
 struct cmdline_arg {
@@ -179,12 +209,15 @@ struct cmdline_arg {
 static struct cmdline_arg cmdline_args[] = {
    {"-i",             "interface",       cb_interface,    0},
    {"-r",             "file",            cb_capfile,      0},
+   {"--snaplen",      "bytes",           cb_snaplen,      0},
    {"--pppoe",        NULL,              cb_pppoe,        0},
+   {"--syslog",       NULL,              cb_syslog,       0},
    {"--verbose",      NULL,              cb_verbose,      0},
    {"--no-daemon",    NULL,              cb_no_daemon,    0},
    {"--no-promisc",   NULL,              cb_no_promisc,   0},
    {"--no-dns",       NULL,              cb_no_dns,       0},
    {"--no-macs",      NULL,              cb_no_macs,      0},
+   {"--no-lastseen",  NULL,              cb_no_lastseen,  0},
    {"-p",             "port",            cb_port,         0},
    {"-b",             "bindaddr",        cb_bindaddr,     0},
    {"-f",             "filter",          cb_filter,       0},
@@ -200,6 +233,8 @@ 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}
 };
 
@@ -232,7 +267,7 @@ usage(void)
       printf(" ]\n");
    }
    printf("\n"
-"Please refer to the darkstat(1) manual page for further\n"
+"Please refer to the darkstat(8) manual page for further\n"
 "documentation and usage examples.\n");
 }
 
@@ -245,13 +280,15 @@ parse_sub_cmdline(const int argc, char * const *argv)
    for (arg = cmdline_args; arg->name != NULL; arg++)
       if (strcmp(argv[0], arg->name) == 0) {
          if ((arg->arg_name != NULL) && (argc == 1)) {
-            printf("\nerror: argument \"%s\" requires parameter \"%s\"\n",
+            fprintf(stderr,
+               "error: argument \"%s\" requires parameter \"%s\"\n",
                arg->name, arg->arg_name);
             usage();
             exit(EXIT_FAILURE);
          }
          if (arg->num_seen > 0) {
-            printf("\nerror: already specified argument \"%s\"\n",
+            fprintf(stderr,
+               "error: already specified argument \"%s\"\n",
                arg->name);
             usage();
             exit(EXIT_FAILURE);
@@ -268,7 +305,7 @@ parse_sub_cmdline(const int argc, char * const *argv)
          return;
       }
 
-   printf("\nerror: illegal argument: \"%s\"\n", argv[0]);
+   fprintf(stderr, "error: illegal argument: \"%s\"\n", argv[0]);
    usage();
    exit(EXIT_FAILURE);
 }
@@ -284,6 +321,9 @@ parse_cmdline(const int argc, char * const *argv)
 
    parse_sub_cmdline(argc, argv);
 
+   /* start syslogging as early as possible */
+   if (want_syslog) openlog("darkstat", LOG_NDELAY | LOG_PID, LOG_DAEMON);
+
    /* some default values */
    if (chroot_dir == NULL) chroot_dir = CHROOT_DIR;
    if (privdrop_user == NULL) privdrop_user = PRIVDROP_USER;
@@ -295,15 +335,31 @@ parse_cmdline(const int argc, char * const *argv)
    if ((interface != NULL) && (capfile != NULL))
       errx(1, "can't specify both interface (-i) and capture file (-r)");
 
-   if ((hosts_max != 0) && (hosts_keep >= hosts_max))
-      errx(1, "must keep fewer hosts than --hosts-max (%u)", hosts_max);
+   if ((hosts_max != 0) && (hosts_keep >= hosts_max)) {
+      hosts_keep = hosts_max / 2;
+      warnx("reducing --hosts-keep to %u, to be under --hosts-max (%u)",
+         hosts_keep, hosts_max);
+   }
    verbosef("max %u hosts, cutting down to %u when exceeded",
       hosts_max, hosts_keep);
 
-   if ((ports_max != 0) && (ports_keep >= ports_max))
-      errx(1, "must keep fewer ports than --ports-max (%u)", ports_max);
+   if ((ports_max != 0) && (ports_keep >= ports_max)) {
+      ports_keep = ports_max / 2;
+      warnx("reducing --ports-keep to %u, to be under --ports-max (%u)",
+         ports_keep, ports_max);
+   }
    verbosef("max %u ports per host, cutting down to %u when exceeded",
       ports_max, ports_keep);
+
+   if (want_hexdump && !want_verbose) {
+      want_verbose = 1;
+      verbosef("--hexdump implies --verbose");
+   }
+
+   if (want_hexdump && want_daemonize) {
+      want_daemonize = 0;
+      verbosef("--hexdump implies --no-daemon");
+   }
 }
 
 static void