/* darkstat 3
- * copyright (c) 2001-2010 Emil Mikulic.
+ * copyright (c) 2001-2011 Emil Mikulic.
*
* darkstat.c: signals, cmdline parsing, program body.
*
* GNU General Public License version 2. (see COPYING.GPL)
*/
-#include "darkstat.h"
#include "acct.h"
#include "cap.h"
+#include "cdefs.h"
#include "config.h"
#include "conv.h"
#include "daylog.h"
#include "db.h"
#include "dns.h"
+#include "err.h"
#include "http.h"
#include "hosts_db.h"
#include "localip.h"
#include "ncache.h"
#include "pidfile.h"
-#include "err.h"
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <netdb.h>
#include <assert.h>
#include <errno.h>
+#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static void cb_port(const char *arg)
{ opt_bindport = (unsigned short)parsenum(arg, 65536); }
-const char *opt_bindaddr = NULL;
-static void cb_bindaddr(const char *arg)
-{
- 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);
- opt_bindaddr = arg;
-}
+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; }
-const char *opt_base = NULL;
-static void cb_base(const char *arg) { opt_base = arg; }
-
const char *opt_privdrop_user = NULL;
static void cb_user(const char *arg) { opt_privdrop_user = arg; }
{ opt_wait_secs = (int)parsenum(arg, 0); }
int opt_want_hexdump = 0;
-static void cb_hexdump(const char *arg _unused_) { opt_want_hexdump = 1; }
+static void cb_hexdump(const char *arg _unused_)
+{ opt_want_hexdump = 1; }
+
+int opt_want_help = 0;
+static void cb_help(const char *arg _unused_)
+{ opt_want_help = 1; }
+static void cb_version(const char *arg _unused_)
+{ opt_want_help = -1; }
/* --- */
static struct cmdline_arg cmdline_args[] = {
{"-i", "interface", cb_interface, 0},
{"-r", "file", cb_capfile, 0},
+ {"-p", "port", cb_port, 0},
+ {"-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},
{"--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},
- {"--base", "path", cb_base, 0},
- {"-f", "filter", cb_filter, 0},
- {"-l", "network/netmask", cb_local, 0},
{"--chroot", "dir", cb_chroot, 0},
{"--user", "username", cb_user, 0},
{"--daylog", "filename", cb_daylog, 0},
{"--highest-port", "port", cb_highest_port, 0},
{"--wait", "secs", cb_wait_secs, 0},
{"--hexdump", NULL, cb_hexdump, 0},
+ {"--version", NULL, cb_version, 0},
+ {"--help", NULL, cb_help, 0},
{NULL, NULL, NULL, 0}
};
-static void
-pad(const int width)
-{
- int i;
- for (i=0; i<width; i++) printf(" ");
-}
-
/*
* We autogenerate the usage statement from the cmdline_args data structure.
*/
static void
usage(void)
{
- int width, first;
+ static char intro[] = "usage: darkstat ";
+ char indent[sizeof(intro)];
struct cmdline_arg *arg;
- printf(PACKAGE_STRING " (built with libpcap %d.%d)\n\n",
- PCAP_VERSION_MAJOR, PCAP_VERSION_MINOR);
+ printf(PACKAGE_STRING " (using %s)\n", pcap_lib_version());
+ if (opt_want_help == -1) return;
- width = printf("usage: darkstat ");
- first = 1;
+ memset(indent, ' ', sizeof(indent));
+ indent[0] = indent[sizeof(indent) - 1] = 0;
+ printf("\n%s", intro);
for (arg = cmdline_args; arg->name != NULL; arg++) {
- if (first) first = 0; else pad(width);
- printf("[ %s", arg->name);
- if (arg->arg_name != NULL) printf(" %s", arg->arg_name);
- printf(" ]\n");
+ printf("%s[ %s%s%s ]\n",
+ indent,
+ arg->name,
+ arg->arg_name != NULL ? " " : "",
+ arg->arg_name != NULL ? arg->arg_name : "");
+ indent[0] = ' ';
}
printf("\n"
"Please refer to the darkstat(8) manual page for further\n"
exit(EXIT_FAILURE);
}
- arg->num_seen++;
+ if (arg->num_seen != -1) /* accept more than one */
+ arg->num_seen++;
+
if (arg->arg_name == NULL) {
arg->callback(NULL);
parse_sub_cmdline(argc-1, argv+1);
parse_sub_cmdline(argc, argv);
+ if (opt_want_help) {
+ usage();
+ exit(EXIT_SUCCESS);
+ }
+
/* start syslogging as early as possible */
if (opt_want_syslog) openlog("darkstat", LOG_NDELAY | LOG_PID, LOG_DAEMON);
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
if (export_fn != NULL) db_export(export_fn);
hosts_db_free();
graph_free();
- verbosef("Total packets: %qu, bytes: %qu",
+#ifndef PRIu64
+#warning "PRIu64 is not defined, using qu instead"
+#define PRIu64 "qu"
+#endif
+ verbosef("Total packets: %"PRIu64", bytes: %"PRIu64,
acct_total_packets, acct_total_bytes);
}
/* do this first as it forks - minimize memory use */
if (opt_want_dns) dns_init(opt_privdrop_user);
cap_init(opt_interface, opt_filter, opt_want_promisc); /* needs root */
- http_init(opt_base, opt_bindaddr, opt_bindport, /*maxconn=*/-1);
+ http_listen(opt_bindport);
ncache_init(); /* must do before chroot() */
privdrop(opt_chroot_dir, opt_privdrop_user);
}
if (reset_pending) {
+ if (export_pending)
+ continue; /* export before reset */
hosts_db_reset();
graph_reset();
reset_pending = 0;