From: Emil Mikulic
Date: Sat, 10 Oct 2015 10:20:24 +0000 (+1100)
Subject: Pull in darkstat-3.0.718
X-Git-Url: https://unix4lyfe.org/gitweb/darkstat-debian/commitdiff_plain/3c6b3682c70be84db86e70c191016913a9836c31?ds=sidebyside
Pull in darkstat-3.0.718
$ apt-get source darkstat
---
diff --git a/ChangeLog b/ChangeLog
index 561c567..1a6e982 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+v3.0.718 (25 January 2014)
+ - (SECURITY!) Don't chroot() by default. The user must specify
+ a --chroot dir for this to happen now.
+ - Bring back the "--base /path" functionality.
+ - Add explicit warning about graphs being blank if we can't get
+ local IPs on an interface.
+ - Don't crash in timer_stop() if monotonic time stops or goes
+ backwards.
+ - Lots of internal cleanups.
+ - Use time_t instead of "long" for time. This is more correct
+ and should fix darkstat on OpenBSD 5.5 on 32-bit systems.
+
v3.0.717 (14 August 2013)
- (OS X only) Work around lack of clock_gettime().
- Fix crash due to str_appendf() not understanding %ld.
@@ -29,15 +41,17 @@ v3.0.714 (June 2011)
- Allow sort on last-seen, thanks to Dirk Koopman.
- Support multiple bind addresses.
- Add --disable-debug configure flag, thanks to Malte S. Stretz.
- - Make it possible to save the DB without resetting it (SIGUSR2).
- - Web: Use relative URLs, so darkstat works properly behind mod_proxy,
- thanks to Malte S. Stretz.
+ - Make it possible to export the database without resetting it:
+ by sending SIGUSR2.
+ - Web: Use relative URLs, so darkstat works properly
+ behind mod_proxy, thanks to Malte S. Stretz.
v3.0.713 (March 2010)
- Don't require --verbose for pcap_stats.
- Survive interface going down on Linux.
- Support DLT_RAW, implemented by Anton S. Ustyuzhanin.
- - Skip accounting for hosts or ports if their max is set to zero.
+ - Skip accounting for hosts or ports if their max
+ is set to zero.
- Implement --hexdump for troubleshooting.
- Web: Implement --no-lastseen
- Implement --snaplen manual override.
@@ -177,6 +191,6 @@ v3.0.471 (Jun 2006)
v2.6 (Nov 2003)
- End of the line for darkstat 2
+ End of the line for darkstat 2.
vim:set noet ts=8 sw=8 tw=72:
diff --git a/Makefile.in b/Makefile.in
index b0dbf2e..6aa57d1 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,5 +1,5 @@
# darkstat 3
-# copyright (c) 2001-2011 Emil Mikulic.
+# copyright (c) 2001-2014 Emil Mikulic.
#
# You may use, modify and redistribute this file under the terms of the
# GNU General Public License version 2. (see COPYING.GPL)
@@ -129,9 +129,9 @@ cap.o: cap.c acct.h cdefs.h cap.h config.h conv.h decode.h addr.h err.h \
hosts_db.h localip.h now.h opt.h queue.h str.h
conv.o: conv.c conv.h err.h cdefs.h
darkstat.o: darkstat.c acct.h cap.h cdefs.h config.h conv.h daylog.h \
- graph_db.h db.h dns.h err.h http.h hosts_db.h addr.h localip.h ncache.h \
- now.h pidfile.h
-daylog.o: daylog.c err.h cdefs.h daylog.h graph_db.h str.h now.h
+ graph_db.h db.h dns.h err.h hosts_db.h addr.h http.h localip.h ncache.h \
+ now.h pidfile.h str.h
+daylog.o: daylog.c cdefs.h err.h daylog.h graph_db.h str.h now.h
db.o: db.c cdefs.h err.h hosts_db.h addr.h graph_db.h db.h
decode.o: decode.c cdefs.h decode.h addr.h err.h opt.h
dns.o: dns.c cdefs.h conv.h decode.h addr.h dns.h err.h hosts_db.h \
@@ -142,12 +142,12 @@ graph_db.o: graph_db.c cap.h conv.h db.h acct.h err.h cdefs.h str.h \
hosts_db.o: hosts_db.c cdefs.h conv.h decode.h addr.h dns.h err.h \
hosts_db.h db.h html.h ncache.h now.h opt.h str.h
hosts_sort.o: hosts_sort.c cdefs.h err.h hosts_db.h addr.h
-html.o: html.c config.h str.h html.h opt.h
+html.o: html.c config.h str.h cdefs.h html.h opt.h
http.o: http.c cdefs.h config.h conv.h err.h graph_db.h hosts_db.h addr.h \
http.h now.h queue.h str.h stylecss.h graphjs.h
localip.o: localip.c addr.h bsd.h config.h conv.h err.h cdefs.h localip.h \
now.h
ncache.o: ncache.c conv.h err.h cdefs.h ncache.h tree.h bsd.h config.h
-now.o: now.c err.h cdefs.h now.h
+now.o: now.c err.h cdefs.h now.h str.h
pidfile.o: pidfile.c err.h cdefs.h str.h pidfile.h
str.o: str.c conv.h err.h cdefs.h str.h
diff --git a/NEWS b/NEWS
index c40c9de..5c4af07 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
Changes to defaults, most recent first:
+- After v3.0.717, the user must specify a --chroot dir for chroot() to happen.
+ We don't set a default in the configure script anymore.
+
- After v3.0.708, --debug was split into --verbose and --no-daemon.
- Since v3.0.694, darkstat is able to save its internal database into a file and
@@ -17,3 +20,5 @@ Changes to defaults, most recent first:
terminal, and run in the background.
After 540, the default has been inverted. darkstat will daemonize by default.
+
+vim:set noet ts=8 sw=8 tw=80:
diff --git a/acct.c b/acct.c
index 17aa4f0..3605674 100644
--- a/acct.c
+++ b/acct.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* acct.c: traffic accounting
*
diff --git a/acct.h b/acct.h
index b4edb7f..0a4b261 100644
--- a/acct.h
+++ b/acct.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* acct.h: traffic accounting
*/
diff --git a/bsd.c b/bsd.c
index 9a9f156..0b9c316 100644
--- a/bsd.c
+++ b/bsd.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2011 Emil Mikulic.
*
* bsd.c: *BSD compatibility.
*
diff --git a/bsd.h b/bsd.h
index 3426add..6939f59 100644
--- a/bsd.h
+++ b/bsd.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2011-2014 Emil Mikulic.
*
* bsd.h: *BSD compatibility.
*/
@@ -22,7 +22,7 @@ size_t strlcat(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_SETPROCTITLE
-#define setproctitle(fmt, ...) /* no-op */
+#define setproctitle(fmt) /* no-op */
#endif
/* vim:set ts=3 sw=3 tw=78 expandtab: */
diff --git a/cap.c b/cap.c
index 7e1c41b..62da77d 100644
--- a/cap.c
+++ b/cap.c
@@ -1,5 +1,5 @@
/* 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.
*
@@ -398,12 +398,21 @@ static void callback(u_char *user,
/* Process any packets currently in the capture buffer. */
void 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;
@@ -415,18 +424,19 @@ void cap_poll(fd_set *read_set _unused_on_linux_) {
-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;
}
- 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 */
diff --git a/cap.h b/cap.h
index e1a77cf..f9f455a 100644
--- a/cap.h
+++ b/cap.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* cap.h: interface to libpcap.
*/
diff --git a/cdefs.h b/cdefs.h
index a0405eb..2bcdf31 100644
--- a/cdefs.h
+++ b/cdefs.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* cdefs.h: compiler-specific defines
*
@@ -26,7 +26,7 @@
#endif
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901
-#define restrict __restrict
+# define restrict __restrict
#endif
#ifndef MAX
@@ -37,4 +37,14 @@
# define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
+# ifdef __COUNTER__
+# define _Static_assert(x, y) __Static_assert(x, __COUNTER__)
+# else
+# define _Static_assert(x, y) __Static_assert(x, __LINE__)
+# endif
+# define __Static_assert(x, y) ___Static_assert(x, y)
+# define ___Static_assert(x, y) typedef char __assert_ ## y[(x) ? 1 : -1]
+#endif
+
/* vim:set ts=3 sw=3 tw=78 expandtab: */
diff --git a/config.h.in b/config.h.in
index 6a34856..f0e3e7f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,8 +1,5 @@
/* config.h.in. Generated from configure.ac by autoheader. */
-/* Default chroot directory. */
-#undef CHROOT_DIR
-
/* Define to 1 if you have the header file. */
#undef HAVE_BSD_STRING_H
diff --git a/configure b/configure
index 520dc65..dd5e415 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for darkstat 3.0.717.
+# Generated by GNU Autoconf 2.69 for darkstat 3.0.718.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='darkstat'
PACKAGE_TARNAME='darkstat'
-PACKAGE_VERSION='3.0.717'
-PACKAGE_STRING='darkstat 3.0.717'
+PACKAGE_VERSION='3.0.718'
+PACKAGE_STRING='darkstat 3.0.718'
PACKAGE_BUGREPORT=''
PACKAGE_URL='http://unix4lyfe.org/darkstat/'
@@ -676,7 +676,6 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
-with_chroot_dir
with_privdrop_user
enable_silent_rules
enable_debug
@@ -1232,7 +1231,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures darkstat 3.0.717 to adapt to many kinds of systems.
+\`configure' configures darkstat 3.0.718 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1293,7 +1292,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of darkstat 3.0.717:";;
+ short | recursive ) echo "Configuration of darkstat 3.0.718:";;
esac
cat <<\_ACEOF
@@ -1310,7 +1309,6 @@ Optional Features:
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --with-chroot-dir specify the chroot directory (default: /var/empty)
--with-privdrop-user specify which user to drop privileges to (default:
nobody)
--with-pcap=DIR prefix to libpcap installation
@@ -1392,7 +1390,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-darkstat configure 3.0.717
+darkstat configure 3.0.718
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1690,7 +1688,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by darkstat $as_me 3.0.717, which was
+It was created by darkstat $as_me 3.0.718, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2044,45 +2042,6 @@ ac_config_headers="$ac_config_headers config.h"
RULE="------------------------------------------------------------"
-# Let user specify CHROOT_DIR, or else autodetect it, or else die.
-
-# Check whether --with-chroot-dir was given.
-if test "${with_chroot_dir+set}" = set; then :
- withval=$with_chroot_dir; if test "x$withval" = "xyes"; then
- as_fn_error $? "please specify --with-chroot-dir=/path/to/darkstat/chroot" "$LINENO" 5
- fi
- _chd="$withval"
-else
- # Find an "empty" directory to serve as the chroot.
- _chd="/var/empty"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $_chd" >&5
-$as_echo_n "checking for $_chd... " >&6; }
- if test -d $_chd ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: found it" >&5
-$as_echo "found it" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not there" >&5
-$as_echo "not there" >&6; }
- _chd="/var/lib/empty"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $_chd" >&5
-$as_echo_n "checking for $_chd... " >&6; }
- if test -d $_chd ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: found it" >&5
-$as_echo "found it" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not there either" >&5
-$as_echo "not there either" >&6; }
- as_fn_error $? "please specify --with-chroot-dir=/path/to/darkstat/chroot" "$LINENO" 5
- fi
- fi
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define CHROOT_DIR "$_chd"
-_ACEOF
-
-
# Allow configure-time override of PRIVDROP_USER.
# Check whether --with-privdrop-user was given.
@@ -4746,7 +4705,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by darkstat $as_me 3.0.717, which was
+This file was extended by darkstat $as_me 3.0.718, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -4809,7 +4768,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-darkstat config.status 3.0.717
+darkstat config.status 3.0.718
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 7af8316..2c22002 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,36 +1,11 @@
# Need at least 2.64 for PACKAGE_URL
AC_PREREQ([2.64])
-AC_INIT(darkstat, 3.0.717, , , http://unix4lyfe.org/darkstat/)
+AC_INIT(darkstat, 3.0.718, , , http://unix4lyfe.org/darkstat/)
AC_CONFIG_SRCDIR([darkstat.c])
AC_CONFIG_HEADER([config.h])
RULE="------------------------------------------------------------"
-# Let user specify CHROOT_DIR, or else autodetect it, or else die.
-AC_ARG_WITH(chroot-dir, AS_HELP_STRING([--with-chroot-dir],
- [specify the chroot directory (default: /var/empty)]),
- [if test "x$withval" = "xyes"; then
- AC_MSG_ERROR([please specify --with-chroot-dir=/path/to/darkstat/chroot])
- fi
- _chd="$withval"],
- [# Find an "empty" directory to serve as the chroot.
- _chd="/var/empty"
- AC_MSG_CHECKING([for $_chd])
- if test -d $_chd ; then
- AC_MSG_RESULT(found it)
- else
- AC_MSG_RESULT(not there)
- _chd="/var/lib/empty"
- AC_MSG_CHECKING([for $_chd])
- if test -d $_chd ; then
- AC_MSG_RESULT(found it)
- else
- AC_MSG_RESULT(not there either)
- AC_MSG_ERROR([please specify --with-chroot-dir=/path/to/darkstat/chroot])
- fi
- fi])
-AC_DEFINE_UNQUOTED(CHROOT_DIR, "$_chd", [Default chroot directory.])
-
# Allow configure-time override of PRIVDROP_USER.
AC_ARG_WITH(privdrop-user, AS_HELP_STRING([--with-privdrop-user],
[specify which user to drop privileges to (default: nobody)]),
diff --git a/contrib/darkstat_export b/contrib/darkstat_export
new file mode 100644
index 0000000..f0dacec
--- /dev/null
+++ b/contrib/darkstat_export
@@ -0,0 +1,257 @@
+#!/bin/sh
+
+# Copyright 2013 MediaMobil Communication GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# This script converts a binary .db file into a .csv file.
+# The .db file was generated by darkstat with the --export option.
+# The .csv file shall be read by any spreadsheet application.
+SCRIPTNAME=$( basename $0)
+if test -z "$( type -P awk )" ; then
+ echo "${SCRIPTNAME}: missing AWK interpreter, at least not found in PATH"
+ echo "${SCRIPTNAME}: every POSIX compliant OS has one; add the location to PATH"
+ exit 1
+fi
+if test -z "$( type -P od )" ; then
+ echo "${SCRIPTNAME}: missing od file dump tool, at least not found in PATH"
+ echo "${SCRIPTNAME}: every POSIX compliant OS has one; add the location to PATH"
+ exit 1
+fi
+if test $# -ne 1; then
+ echo "${SCRIPTNAME}: missing parameter; need file name of .db file"
+ exit 1
+fi
+DBFILENAME=$1
+if test -r ${DBFILENAME}; then
+ echo ${SCRIPTNAME}: Found file ${DBFILENAME}
+else
+ echo ${SCRIPTNAME}: file ${DBFILENAME} does not exist
+ exit 1
+fi
+CSVFILENAME=${DBFILENAME%%.*}.csv
+echo ${SCRIPTNAME}: Writing output into ${CSVFILENAME}
+
+# The spec of the .db export format exists for different versions:
+# http://unix4lyfe.org/gitweb/darkstat/blob/0a152e51f5d9c1771308caa7135d363a722aee18:/export-format.txt
+# http://git.msquadrat.de/darkstat.git/blob_plain/master:/export-format.txt
+# http://phil.lavin.me.uk/downloads/parse.phps
+# Only file format version 1 is supported by us.
+# Obviously, darkstat itself distinguishes 3 different host format versions.
+# Only host format version 2 is supported by us.
+# The darkstat database file is converted from binary format
+# to ASCII by the standard Unix command od.
+
+# Some things don't work correctly yet.
+# Probably because there is no DNS server configured in our embedded device
+# that produces .db files within OpenWRT.
+# - host name contains nonsense at constant length 5
+# - "last seen" timing information contains always 0
+# - we read the graphics section of the file but ignore it
+
+# Let the od tool convert each binary byte into several textual formats.
+# The AWK script reads all variants and later picks the format it needs.
+od -Ad -v -tx1 -tu1 -ta -w1 < ${DBFILENAME} |
+awk '
+ NF==2 { addr = 0 + $1; hex[addr] = $2; next }
+ NF==1 && addr in dec { ascii[addr]=$1; next }
+ NF==1 && ! (addr in dec) { dec[addr]=$1; next }
+ # Now all variants of the bytes are available in certain arrays.
+ # The array indices cover the range 0 .. addr.
+
+ function read_bytes(array, address, count, retval, c) {
+ retval=""
+ for (c=0; c 0)
+ print reason
+ if (terminate != 0) {
+ # Any remaining bytes in the file shall be dumped.
+ for (i=ai; i<=addr; i++)
+ print i, hex[i], ascii[i]
+ exit(retval)
+ }
+ }
+ function readIPsection() {
+ ip_protos_data=read_bytes(ascii, ai, 1)
+ if (ip_protos_data != "P")
+ quit("expected ip_protos_data P, found " ip_protos_data, 1, 1)
+ ai += 1
+ ip_proto_count=read_number(ai, 1)
+ ai += 1
+ for (pi=0; pi 1) {
+ last_seen=read_number(ai, 4)
+ # This value is always 0 in our files.
+ ai += 4
+ }
+ mac_address=hex[ai+0] ":" hex[ai+1] ":" hex[ai+2] ":" hex[ai+3] ":" hex[ai+4] ":" hex[ai+5]
+ ai += 6
+ # Weird stuff: the host name should be read.
+ # But there are only 5 bytes of nonsense.
+ # The first byte should be the length counter, but it isnt.
+ # The last byte is in fact a 0 byte.
+ # Probably caused by the missing DNS server.
+ # ignore 5 bytes with nonsense
+ nonsense=read_text(ai, 5)
+ ai += 5
+ host_bytes_in=read_number(ai, 8)
+ ai += 8
+ host_bytes_out=read_number(ai, 8)
+ ai += 8
+ readIPsection()
+ readTCPsection()
+ readUDPsection()
+ } else {
+ quit("host format supported only in version 02: " host_version, 1, 1)
+ #address_familiy=read_bytes(hex, ai, 1)
+ #print "address familiy = " address_familiy
+ }
+ printf("\"%s\";\"%s\";%d;%d;%s;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%s;%s\n",
+ ip_address, mac_address, host_bytes_in, host_bytes_out,
+ IPprotos, ip_proto_in, ip_proto_out,
+ tcp_proto_count, tcp_proto_in, tcp_proto_out,
+ udp_proto_count, udp_proto_in, udp_proto_out,
+ ssh_in, ssh_out, rdp_in, rdp_out,
+ TCPports, UDPports)
+ }
+ section_header=read_bytes(hex, ai, 3)
+ if (section_header != "da4752")
+ quit("section header da4752 expected: " section_header, 1, 1)
+ ai += 3
+ db_version=read_bytes(hex, ai, 1)
+ if (db_version != "01")
+ quit("file format supported only in version 01", 1, 1)
+ ai += 1
+ last_time=read_number(ai, 8)
+ ai += 8
+ readGraphsection("60 seconds")
+ readGraphsection("60 minutes")
+ readGraphsection("24 hours")
+ readGraphsection("31 days")
+ # The complete file has been parsed, no bytes should be left over.
+ # Terminate with return value 0 if the byte numbers match.
+ quit("", (addr != ai+1) ?0:1, addr != ai+1)
+ }
+ ' > ${CSVFILENAME}
diff --git a/conv.c b/conv.c
index 4ff95ae..265f864 100644
--- a/conv.c
+++ b/conv.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* conv.c: convenience functions.
*
@@ -288,9 +288,7 @@ daemonize_finish(void)
* For security, chroot (optionally) and drop privileges.
* Pass a NULL chroot_dir to disable chroot() behaviour.
*/
-void
-privdrop(const char *chroot_dir, const char *privdrop_user)
-{
+void privdrop(const char *chroot_dir, const char *privdrop_user) {
struct passwd *pw;
errno = 0;
@@ -302,7 +300,9 @@ privdrop(const char *chroot_dir, const char *privdrop_user)
else
err(1, "getpwnam(\"%s\") failed", privdrop_user);
}
- if (chroot_dir != NULL) {
+ if (chroot_dir == NULL) {
+ verbosef("no --chroot dir specified, darkstat will not chroot()");
+ } else {
tzset(); /* read /etc/localtime before we chroot */
if (chdir(chroot_dir) == -1)
err(1, "chdir(\"%s\") failed", chroot_dir);
@@ -344,3 +344,5 @@ fd_set_block(const int fd)
err(1, "fcntl(fd %d) to unset O_NONBLOCK", fd);
assert( (fcntl(fd, F_GETFL, 0) & O_NONBLOCK ) == 0 );
}
+
+/* vim:set ts=3 sw=3 tw=78 expandtab: */
diff --git a/darkstat.8.in b/darkstat.8.in
index e786af3..9b5a0b4 100644
--- a/darkstat.8.in
+++ b/darkstat.8.in
@@ -1,6 +1,6 @@
.\"
.\" darkstat 3
-.\" Copyright 2001-2011, Emil Mikulic.
+.\" Copyright 2001-2014, Emil Mikulic.
.\"
.\" You may use, modify and redistribute this file under the terms of the
.\" GNU General Public License version 2. (see COPYING.GPL)
@@ -38,6 +38,8 @@ darkstat \- network statistics gatherer
] [
.BI \-b " bindaddr"
] [
+.BI \-\-base " path"
+] [
.BI \-f " filter"
] [
.BI \-l " network/netmask"
@@ -169,11 +171,30 @@ Bind the web interface to the specified address.
The default is to listen on all interfaces.
.\"
.TP
+.BI \-\-base " path"
+.RS
+Specify the path of the base URL.
+This can be useful if \fIdarkstat\fR is accessed via a reverse proxy.
+
+For example, if you use Apache's \fImod_proxy\fR and want to avoid a
+complicated setup with \fImod_proxy_html\fR (and \fImod_header\fR to unset
+the \fIAccept-Encoding\fR header), just set the base path to something like
+\fIstats\fR and use a config similar to the following snippet:
+
+.IP
+ ProxyPass /stats/ http://localhost:667/stats/
+ ProxyPassReverse /stats/ http://localhost:667/stats/
+.PP
+
+The default is \fI/\fR (i.e. the root).
+.RE
+.\"
+.TP
.BI \-f " filter"
Use the specified filter expression when capturing traffic.
The filter syntax is beyond the scope of this manual page;
please refer to the
-.BR tcpdump (1)
+.BR tcpdump (8)
documentation.
.\"
.TP
@@ -381,7 +402,7 @@ darkstat \-i fxp0 \-f "not (src net 192.168.0 and dst net 192.168.0)"
.PP
.\"
(For a full reference on filter syntax, refer to the
-.BR tcpdump (1)
+.BR tcpdump (8)
manpage)
.PP
.\"
@@ -439,7 +460,7 @@ You can also use it to do accounting for a whole subnet by specifying
an appropriate netmask.
.\"
.SH SEE ALSO
-.BR tcpdump (1)
+.BR tcpdump (8)
.\"
.SH HISTORY
.I darkstat
diff --git a/darkstat.c b/darkstat.c
index 2213986..c65631e 100644
--- a/darkstat.c
+++ b/darkstat.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* darkstat.c: signals, cmdline parsing, program body.
*
@@ -16,12 +16,13 @@
#include "db.h"
#include "dns.h"
#include "err.h"
-#include "http.h"
#include "hosts_db.h"
+#include "http.h"
#include "localip.h"
#include "ncache.h"
#include "now.h"
#include "pidfile.h"
+#include "str.h"
#include
#include
@@ -126,48 +127,23 @@ static void cb_local_only(const char *arg _unused_)
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; }
-const char *daylog_fn = NULL;
-static void cb_daylog(const char *arg)
-{
- if (opt_chroot_dir == NULL)
- errx(1, "the daylog file is relative to the chroot.\n"
- "You must specify a --chroot dir before you can use --daylog.");
- else
- daylog_fn = arg;
-}
+const char *opt_daylog_fn = NULL;
+static void cb_daylog(const char *arg) { opt_daylog_fn = arg; }
const char *import_fn = NULL;
-static void cb_import(const char *arg)
-{
- if (opt_chroot_dir == NULL)
- errx(1, "the import file is relative to the chroot.\n"
- "You must specify a --chroot dir before you can use --import.");
- else
- import_fn = arg;
-}
+static void cb_import(const char *arg) { import_fn = arg; }
const char *export_fn = NULL;
-static void cb_export(const char *arg)
-{
- if ((opt_chroot_dir == NULL) && (opt_capfile == NULL))
- errx(1, "the export file is relative to the chroot.\n"
- "You must specify a --chroot dir before you can use --export.");
- else
- export_fn = arg;
-}
+static void cb_export(const char *arg) { export_fn = arg; }
static const char *pid_fn = NULL;
-static void cb_pidfile(const char *arg)
-{
- if (opt_chroot_dir == NULL)
- errx(1, "the pidfile is relative to the chroot.\n"
- "You must specify a --chroot dir before you can use --pidfile.");
- else
- pid_fn = arg;
-}
+static void cb_pidfile(const char *arg) { pid_fn = arg; }
unsigned int opt_hosts_max = 1000;
static void cb_hosts_max(const char *arg)
@@ -218,6 +194,7 @@ static struct cmdline_arg cmdline_args[] = {
{"-p", "port", cb_port, 0},
{"-b", "bindaddr", cb_bindaddr, -1},
{"-l", "network/netmask", cb_local, 0},
+ {"--base", "path", cb_base, 0},
{"--local-only", NULL, cb_local_only, 0},
{"--snaplen", "bytes", cb_snaplen, 0},
{"--pppoe", NULL, cb_pppoe, 0},
@@ -329,9 +306,7 @@ static void parse_cmdline(const int argc, char * const *argv) {
if (opt_want_syslog)
openlog("darkstat", LOG_NDELAY | LOG_PID, LOG_DAEMON);
- /* some default values */
- if (opt_chroot_dir == NULL)
- opt_chroot_dir = CHROOT_DIR;
+ /* default value */
if (opt_privdrop_user == NULL)
opt_privdrop_user = PRIVDROP_USER;
@@ -381,8 +356,8 @@ static void run_from_capfile(void) {
hosts_db_free();
graph_free();
verbosef("Total packets: %llu, bytes: %llu",
- (unsigned long long)acct_total_packets,
- (unsigned long long)acct_total_bytes);
+ (llu)acct_total_packets,
+ (llu)acct_total_bytes);
}
/* --- Program body --- */
@@ -411,6 +386,7 @@ main(int argc, char **argv)
/* do this first as it forks - minimize memory use */
if (opt_want_dns) dns_init(opt_privdrop_user);
cap_start(opt_want_promisc); /* needs root */
+ http_init_base(opt_base);
http_listen(opt_bindport);
ncache_init(); /* must do before chroot() */
@@ -418,7 +394,7 @@ main(int argc, char **argv)
/* Don't need root privs for these: */
now_init();
- if (daylog_fn != NULL) daylog_init(daylog_fn);
+ if (opt_daylog_fn != NULL) daylog_init(opt_daylog_fn);
graph_init();
hosts_db_init();
if (import_fn != NULL) db_import(import_fn);
@@ -490,7 +466,7 @@ main(int argc, char **argv)
if (export_fn != NULL) db_export(export_fn);
hosts_db_free();
graph_free();
- if (daylog_fn != NULL) daylog_free();
+ if (opt_daylog_fn != NULL) daylog_free();
ncache_free();
if (pid_fn) pidfile_unlink();
verbosef("shut down");
diff --git a/daylog.c b/daylog.c
index fe1928f..080f11f 100644
--- a/daylog.c
+++ b/daylog.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2007-2011 Emil Mikulic.
+ * copyright (c) 2007-2014 Emil Mikulic.
*
* daylog.c: daily usage log
*
@@ -9,6 +9,7 @@
#define _GNU_SOURCE 1 /* for O_NOFOLLOW on Linux */
+#include "cdefs.h"
#include "err.h"
#include "daylog.h"
#include "str.h"
@@ -23,7 +24,7 @@
#include
static const char *daylog_fn = NULL;
-static long today_real, tomorrow_real;
+static time_t today_real, tomorrow_real;
static uint64_t bytes_in, bytes_out, pkts_in, pkts_out;
#define DAYLOG_DATE_LEN 26 /* strlen("1900-01-01 00:00:00 +1234") + 1 */
@@ -55,6 +56,7 @@ static time_t tomorrow(time_t t_before) {
}
/* Warns on error. */
+static void daylog_write(const char *format, ...) _printflike_(1, 2);
static void daylog_write(const char *format, ...) {
int fd;
ssize_t wr;
@@ -87,27 +89,32 @@ static void daylog_write(const char *format, ...) {
static void daylog_emit(void) {
daylog_write("%s|%qu|%qu|%qu|%qu|%qu\n",
- fmt_date(today_real), (uint64_t)today_real,
- bytes_in, bytes_out, pkts_in, pkts_out);
+ fmt_date(today_real),
+ (qu)today_real,
+ (qu)bytes_in,
+ (qu)bytes_out,
+ (qu)pkts_in,
+ (qu)pkts_out);
}
void daylog_init(const char *filename) {
daylog_fn = filename;
today_real = now_real();
tomorrow_real = tomorrow(today_real);
- verbosef("today is %ld, tomorrow is %ld",
- (long)today_real, (long)tomorrow_real);
+ verbosef("today is %llu, tomorrow is %llu",
+ (llu)today_real,
+ (llu)tomorrow_real);
bytes_in = bytes_out = pkts_in = pkts_out = 0;
daylog_write("# logging started at %s (%qu)\n",
- fmt_date(today_real), (uint64_t)today_real);
+ fmt_date(today_real), (qu)today_real);
}
void daylog_free(void) {
today_real = now_real();
daylog_emit(); /* Emit what's currently accumulated before we exit. */
daylog_write("# logging stopped at %s (%qu)\n",
- fmt_date(today_real), (uint64_t)today_real);
+ fmt_date(today_real), (qu)today_real);
}
void daylog_acct(uint64_t amount, enum graph_dir dir) {
@@ -121,7 +128,7 @@ void daylog_acct(uint64_t amount, enum graph_dir dir) {
today_real = now_real();
tomorrow_real = tomorrow(today_real);
bytes_in = bytes_out = pkts_in = pkts_out = 0;
- verbosef("updated daylog, tomorrow = %ld", (long)tomorrow_real);
+ verbosef("updated daylog, tomorrow = %llu", (llu)tomorrow_real);
}
/* Accounting. */
diff --git a/db.c b/db.c
index cf50da9..cadd26e 100644
--- a/db.c
+++ b/db.c
@@ -1,7 +1,7 @@
/* darkstat 3
*
* db.c: load and save in-memory database from/to file
- * copyright (c) 2007-2011 Ben Stewart, Emil Mikulic.
+ * copyright (c) 2007-2012 Ben Stewart, Emil Mikulic.
*
* You may use, modify and redistribute this file under the terms of the
* GNU General Public License version 2. (see COPYING.GPL)
diff --git a/db.h b/db.h
index 6f9d28a..8fde50d 100644
--- a/db.h
+++ b/db.h
@@ -1,7 +1,7 @@
/* darkstat 3
*
* db.h: load and save in-memory database from/to file
- * copyright (c) 2007-2011 Ben Stewart, Emil Mikulic.
+ * copyright (c) 2007-2012 Ben Stewart, Emil Mikulic.
*/
#include /* for size_t */
diff --git a/debian/README.Source b/debian/README.Source
deleted file mode 100644
index 10a1ce4..0000000
--- a/debian/README.Source
+++ /dev/null
@@ -1,10 +0,0 @@
-Repackaged upstream source:
-===========================
-
-The original darkstat tarball includes contrib/darkproxy.php, this file
-does not have any valid license that allow us o modify and redistribute it
-so the file is being removed from the original tarball to fulfill the DFSG.
-
-If you need to recreate the tarball you can execute
-uuscan --verbose --no-symlink this will download the current version and
-it will create the +dfsg.orig.tar.gz file.
diff --git a/debian/changelog b/debian/changelog
index dfd5e0e..ca4bc75 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,28 @@
-darkstat (3.0.717-1) UNRELEASED; urgency=low
+darkstat (3.0.718-2) unstable; urgency=low
- * Imported Upstream version 3.0.717
+ * Fix FTBFS on Hurd
- -- Emil Mikulic Sun, 18 Aug 2013 16:37:10 +1000
+ -- Rene Mayorga Sun, 13 Apr 2014 18:41:00 +0000
+
+darkstat (3.0.718-1) unstable; urgency=low
+
+ * New upstream release (Closes: #737857)
+ + Fix IPv6 error on start (Closes: 687967)
+ + Fix exits when monitoring ppp0 (Closes: #663515)
+ * debian/watch - remove dversionmangle and repack script
+ * debian/rpack.sh deleted.
+ * README.Source deleted
+ * Add Emil as a co-maint
+ * debian/rules
+ + remove not needed options on configure-stamp
+ + use dpkg-buildflags
+ * use dh compat 9, debhelper B-D updated
+ * Update debian policy to 3.9.5
+ + use mandatory build-arch and build-indep targets
+ * Convert to dpkg-source 3.0 quilt format
+ * Correct tcpdump's section number on the manpage (Closes: #671442)
+
+ -- Rene Mayorga Sun, 23 Mar 2014 12:36:51 +0000
darkstat (3.0.715-1) unstable; urgency=low
diff --git a/debian/compat b/debian/compat
index 7f8f011..ec63514 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-7
+9
diff --git a/debian/control b/debian/control
index 17cc6ad..ff0da4c 100644
--- a/debian/control
+++ b/debian/control
@@ -3,9 +3,9 @@ Section: net
Priority: optional
Maintainer: Rene Mayorga
Uploaders: Emil Mikulic
-Build-Depends: debhelper (>= 7), libpcap-dev, autotools-dev, po-debconf,
+Build-Depends: debhelper (>= 9), libpcap-dev, autotools-dev, po-debconf,
zlib1g-dev
-Standards-Version: 3.9.2
+Standards-Version: 3.9.5
Homepage: http://unix4lyfe.org/darkstat/
Package: darkstat
diff --git a/debian/patches/CorrectTcmpdump-section b/debian/patches/CorrectTcmpdump-section
new file mode 100644
index 0000000..68ab15b
--- /dev/null
+++ b/debian/patches/CorrectTcmpdump-section
@@ -0,0 +1,36 @@
+Description: Correct tcpdump section number
+ Use tcpdump section number 8 for debian systems.
+Author: Rene Mayorga
+Forwarded: not-needed
+Last-Update: 2014-03-23
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/darkstat.8.in
++++ b/darkstat.8.in
+@@ -194,7 +194,7 @@
+ Use the specified filter expression when capturing traffic.
+ The filter syntax is beyond the scope of this manual page;
+ please refer to the
+-.BR tcpdump (1)
++.BR tcpdump (8)
+ documentation.
+ .\"
+ .TP
+@@ -402,7 +402,7 @@
+ .PP
+ .\"
+ (For a full reference on filter syntax, refer to the
+-.BR tcpdump (1)
++.BR tcpdump (8)
+ manpage)
+ .PP
+ .\"
+@@ -460,7 +460,7 @@
+ an appropriate netmask.
+ .\"
+ .SH SEE ALSO
+-.BR tcpdump (1)
++.BR tcpdump (8)
+ .\"
+ .SH HISTORY
+ .I darkstat
diff --git a/debian/patches/FixHURDsFTBS.patch b/debian/patches/FixHURDsFTBS.patch
new file mode 100644
index 0000000..1a05c77
--- /dev/null
+++ b/debian/patches/FixHURDsFTBS.patch
@@ -0,0 +1,17 @@
+Description: Use the correct macro for OS X
+ The OS X fix use the macro __MACH__, this catch up on Hurd, so
+ better use __APPLE__
+Author: René Mayorga
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/now.c
++++ b/now.c
+@@ -23,7 +23,7 @@
+ #include
+ #include
+
+-#ifdef __MACH__
++#ifdef __APPLE__
+ /* Fake up clock_gettime() on OS X. */
+ # include
+ # include
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..c58bf3c
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,2 @@
+CorrectTcmpdump-section
+FixHURDsFTBS.patch
diff --git a/debian/rpack.sh b/debian/rpack.sh
deleted file mode 100755
index 3f2a823..0000000
--- a/debian/rpack.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-set -e
-set -u
-
-VER="3.0.714"
-FILE="../darkstat-3.0.714.tar.bz2"
-PKG="darkstat"
-
-SUFFIX="+dfsg"
-
-echo
-echo "Repackaging $FILE"
-echo
-
-DIR=`mktemp -d ./tmpRepackXXXXXX`
-DIR=$(readlink -f "$DIR")
-trap "/bin/rm -rf \"$DIR\"" QUIT INT EXIT
-
-
-UP_BASE="$DIR/unpack"
-mkdir "$UP_BASE"
-tar -xvjf "$FILE" -C /"$UP_BASE"
-
-set -f
-MYORIGPWD=$(pwd)
-cd "$UP_BASE"
-rm "$PKG-$VER/contrib/darkproxy.php"
-tar -cvzf "$PKG-$VER$SUFFIX.orig.tar.gz" "$PKG-$VER/"
-mv "$PKG-$VER$SUFFIX.orig.tar.gz" "$MYORIGPWD/../"
-cd "$MYORIGPWD"
-
-echo
-echo "done"
-echo
-
-rm "$FILE"
-rm -rf "$DIR"
diff --git a/debian/rules b/debian/rules
index f01ccfd..514a26e 100755
--- a/debian/rules
+++ b/debian/rules
@@ -3,16 +3,22 @@
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-CFLAGS += -Wall -g
+# CFLAGS += -Wall -g
+#
+
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/buildflags.mk
configure: configure-stamp
configure-stamp:
dh_testdir
cp /usr/share/misc/config.sub /usr/share/misc/config.guess .
- CFLAGS="$(CFLAGS)" LDFLAGS="$(INSTALL_PROGRAM)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --with-chroot-dir=/var/lib/darkstat
+ CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man
touch $@
build: configure-stamp build-stamp
+build-arch: build
+build-indep: build
build-stamp: configure-stamp
dh_testdir
diff --git a/debian/watch b/debian/watch
index d99b761..a7c078b 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,4 +1,2 @@
version=3
-options=dversionmangle=s/\+dfsg// \
- http://unix4lyfe.org/darkstat/darkstat-(.*)\.tar\.bz2 \
- debian debian/rpack.sh
+http://unix4lyfe.org/darkstat/darkstat-(.*)\.tar\.bz2
diff --git a/decode.c b/decode.c
index e8e5f35..efa6b00 100644
--- a/decode.c
+++ b/decode.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* decode.c: packet decoding.
*
diff --git a/decode.h b/decode.h
index cc4bd55..827c0ad 100644
--- a/decode.h
+++ b/decode.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* decode.h: packet decoding.
*
diff --git a/dns.c b/dns.c
index c89dc1b..5b6d95b 100644
--- a/dns.c
+++ b/dns.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* dns.c: synchronous DNS in a child process.
*
@@ -38,7 +38,7 @@ static void dns_main(void) _noreturn_; /* the child process runs this */
#define CHILD 0 /* child process uses this socket */
#define PARENT 1
-static int sock[2];
+static int dns_sock[2];
static pid_t pid = -1;
struct dns_reply {
@@ -50,7 +50,7 @@ struct dns_reply {
void
dns_init(const char *privdrop_user)
{
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) == -1)
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, dns_sock) == -1)
err(1, "socketpair");
pid = fork();
@@ -60,19 +60,18 @@ dns_init(const char *privdrop_user)
if (pid == 0) {
/* We are the child. */
privdrop(NULL /* don't chroot */, privdrop_user);
- close(sock[PARENT]);
- sock[PARENT] = -1;
+ close(dns_sock[PARENT]);
+ dns_sock[PARENT] = -1;
daemonize_finish(); /* drop our copy of the lifeline! */
if (signal(SIGUSR1, SIG_IGN) == SIG_ERR)
errx(1, "signal(SIGUSR1, ignore) failed");
dns_main();
- verbosef("fell out of dns_main()");
exit(0);
} else {
/* We are the parent. */
- close(sock[CHILD]);
- sock[CHILD] = -1;
- fd_set_nonblock(sock[PARENT]);
+ close(dns_sock[CHILD]);
+ dns_sock[CHILD] = -1;
+ fd_set_nonblock(dns_sock[PARENT]);
verbosef("DNS child has PID %d", pid);
}
}
@@ -82,7 +81,7 @@ dns_stop(void)
{
if (pid == -1)
return; /* no child was started */
- close(sock[PARENT]);
+ close(dns_sock[PARENT]);
if (kill(pid, SIGINT) == -1)
err(1, "kill");
verbosef("dns_stop() waiting for child");
@@ -112,12 +111,7 @@ tree_cmp(struct tree_rec *a, struct tree_rec *b)
}
static RB_HEAD(tree_t, tree_rec) ip_tree = RB_INITIALIZER(&tree_rec);
-/* Quiet warnings. */
-static struct tree_rec * tree_t_RB_NEXT(struct tree_rec *elm)
- _unused_;
-static struct tree_rec * tree_t_RB_MINMAX(struct tree_t *head, int val)
- _unused_;
-RB_GENERATE(tree_t, tree_rec, ptree, tree_cmp)
+RB_GENERATE_STATIC(tree_t, tree_rec, ptree, tree_cmp)
void
dns_queue(const struct addr *const ipaddr)
@@ -144,7 +138,7 @@ dns_queue(const struct addr *const ipaddr)
return;
}
- num_w = write(sock[PARENT], ipaddr, sizeof(*ipaddr)); /* won't block */
+ num_w = write(dns_sock[PARENT], ipaddr, sizeof(*ipaddr)); /* won't block */
if (num_w == 0)
warnx("dns_queue: write: ignoring end of file");
else if (num_w == -1)
@@ -177,7 +171,7 @@ dns_get_result(struct addr *ipaddr, char **name)
struct dns_reply reply;
ssize_t numread;
- numread = read(sock[PARENT], &reply, sizeof(reply));
+ numread = read(dns_sock[PARENT], &reply, sizeof(reply));
if (numread == -1) {
if (errno == EAGAIN)
return (0); /* no input waiting */
@@ -256,7 +250,7 @@ struct qitem {
struct addr ip;
};
-STAILQ_HEAD(qhead, qitem) queue = STAILQ_HEAD_INITIALIZER(queue);
+static STAILQ_HEAD(qhead, qitem) queue = STAILQ_HEAD_INITIALIZER(queue);
static void
enqueue(const struct addr *const ip)
@@ -302,23 +296,23 @@ dns_main(void)
struct addr ip;
setproctitle("DNS child");
- fd_set_nonblock(sock[CHILD]);
+ fd_set_nonblock(dns_sock[CHILD]);
verbosef("DNS child entering main DNS loop");
for (;;) {
int blocking;
if (STAILQ_EMPTY(&queue)) {
blocking = 1;
- fd_set_block(sock[CHILD]);
+ fd_set_block(dns_sock[CHILD]);
verbosef("entering blocking read loop");
} else {
blocking = 0;
- fd_set_nonblock(sock[CHILD]);
+ fd_set_nonblock(dns_sock[CHILD]);
verbosef("non-blocking poll");
}
for (;;) {
/* While we have input to process... */
- ssize_t numread = read(sock[CHILD], &ip, sizeof(ip));
+ ssize_t numread = read(dns_sock[CHILD], &ip, sizeof(ip));
if (numread == 0)
exit(0); /* end of file, nothing more to do here. */
if (numread == -1) {
@@ -336,7 +330,7 @@ dns_main(void)
* run out of input we fall through to queue processing.
*/
blocking = 0;
- fd_set_nonblock(sock[CHILD]);
+ fd_set_nonblock(dns_sock[CHILD]);
}
}
@@ -392,8 +386,8 @@ dns_main(void)
strlcpy(reply.name, host, sizeof(reply.name));
reply.error = 0;
}
- fd_set_block(sock[CHILD]);
- xwrite(sock[CHILD], &reply, sizeof(reply));
+ fd_set_block(dns_sock[CHILD]);
+ xwrite(dns_sock[CHILD], &reply, sizeof(reply));
verbosef("DNS: %s is \"%s\".", addr_to_str(&reply.addr),
(ret == 0) ? reply.name : gai_strerror(ret));
}
diff --git a/err.c b/err.c
index 3b42d18..bee8234 100644
--- a/err.c
+++ b/err.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* err.c: BSD-like err() and warn() functions
*
diff --git a/err.h b/err.h
index 842595a..b93f2ec 100644
--- a/err.h
+++ b/err.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* err.h: BSD-like err() and warn() functions
*
@@ -27,6 +27,6 @@ void warn(const char *format, ...) _printflike_(1, 2);
void warnx(const char *format, ...) _printflike_(1, 2);
void verbosef(const char *format, ...) _printflike_(1, 2);
-void dverbosef(const char *format _unused_, ...);
+void dverbosef(const char *format _unused_, ...) _printflike_(1, 2);
/* vim:set ts=3 sw=3 tw=78 expandtab: */
diff --git a/graph_db.c b/graph_db.c
index c0875d4..4485d45 100644
--- a/graph_db.c
+++ b/graph_db.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2006-2011 Emil Mikulic.
+ * copyright (c) 2006-2014 Emil Mikulic.
*
* graph_db.c: round robin database for graph data
*
@@ -47,7 +47,7 @@ static struct graph *graph_db[] = {
};
static unsigned int graph_db_size = sizeof(graph_db)/sizeof(*graph_db);
-static long start_mono, start_real, last_real;
+static time_t start_mono, start_real, last_real;
void graph_init(void) {
unsigned int i;
@@ -57,6 +57,7 @@ void graph_init(void) {
}
start_mono = now_mono();
start_real = now_real();
+ last_real = 0;
graph_reset();
}
@@ -127,6 +128,7 @@ static void rotate(struct graph *g, const unsigned int pos) {
memcpy(g->out, tmp, size);
free(tmp);
+ assert(g->num_bars > 0);
assert(pos == ( (g->pos + ofs) % g->num_bars ));
g->pos = pos;
}
@@ -169,7 +171,7 @@ static void graph_resync(const time_t new_real) {
}
void graph_rotate(void) {
- long t, td;
+ time_t t, td;
struct tm *tm;
unsigned int i;
@@ -287,7 +289,7 @@ struct str *html_front_page(void) {
struct str *buf, *rf;
unsigned int i;
char start_when[100];
- long d_real, d_mono;
+ time_t d_real, d_mono;
buf = str_make();
html_open(buf, "Graphs", /*path_depth=*/0, /*want_graph_js=*/1);
@@ -302,7 +304,7 @@ struct str *html_front_page(void) {
str_append(buf, "");
if (abs(d_real - d_mono) > 1)
str_appendf(buf, " (real time is off by %qd sec)",
- (int64_t)d_real - (int64_t)d_mono);
+ (qd)d_real - (qd)d_mono);
if (strftime(start_when, sizeof(start_when),
"%Y-%m-%d %H:%M:%S %Z%z", localtime(&start_real)) != 0)
@@ -314,9 +316,10 @@ struct str *html_front_page(void) {
"(%'u captured, "
"%'u dropped)
\n"
"
\n",
- acct_total_bytes,
- acct_total_packets,
- cap_pkts_recv, cap_pkts_drop);
+ (qu)acct_total_bytes,
+ (qu)acct_total_packets,
+ cap_pkts_recv,
+ cap_pkts_drop);
str_append(buf,
"\n"
@@ -361,7 +364,10 @@ struct str *xml_graphs(void) {
struct str *buf = str_make(), *rf;
str_appendf(buf, "
num_bars;
/* */
str_appendf(buf, "\n",
- g->offset + j, g->in[j], g->out[j]);
+ g->offset + j,
+ (qu)g->in[j],
+ (qu)g->out[j]);
} while (j != g->pos);
str_appendf(buf, "%s>\n", g->unit);
}
diff --git a/hosts_db.c b/hosts_db.c
index c2d7ae4..3058d65 100644
--- a/hosts_db.c
+++ b/hosts_db.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* hosts_db.c: database of hosts, ports, protocols.
*
@@ -20,7 +20,7 @@
#include "opt.h"
#include "str.h"
-#include /* struct addrinfo */
+#include /* struct addrinfo */
#include
#include
#include
@@ -342,10 +342,12 @@ format_row_host(struct str *buf, const struct bucket *b,
" %'qu | \n"
" %'qu | \n"
" %'qu | \n",
- b->in, b->out, b->total);
+ (qu)b->in,
+ (qu)b->out,
+ (qu)b->total);
if (opt_want_lastseen) {
- long last = b->u.host.last_seen_mono;
+ time_t last = b->u.host.last_seen_mono;
struct str *last_str = NULL;
if ((now_mono() >= last) && (last > 0))
@@ -356,7 +358,9 @@ format_row_host(struct str *buf, const struct bucket *b,
if (last == 0)
str_append(buf, "(never)");
else
- str_append(buf, "(clock error)");
+ str_appendf(buf, "(clock error: now = %qu, last = %qu)",
+ (qu)now_mono(),
+ (qu)last);
} else {
str_appendstr(buf, last_str);
str_free(last_str);
@@ -403,7 +407,12 @@ format_row_port_tcp(struct str *buf, const struct bucket *b,
" %'qu | \n"
"\n",
css_class,
- p->port, getservtcp(p->port), b->in, b->out, b->total, p->syn
+ p->port,
+ getservtcp(p->port),
+ (qu)b->in,
+ (qu)b->out,
+ (qu)b->total,
+ (qu)p->syn
);
}
@@ -437,7 +446,11 @@ format_row_port_udp(struct str *buf, const struct bucket *b,
" %'qu | \n"
"\n",
css_class,
- p->port, getservudp(p->port), b->in, b->out, b->total
+ p->port,
+ getservudp(p->port),
+ (qu)b->in,
+ (qu)b->out,
+ (qu)b->total
);
}
@@ -471,8 +484,11 @@ format_row_ip_proto(struct str *buf, const struct bucket *b,
" %'qu | \n"
"\n",
css_class,
- p->proto, getproto(p->proto),
- b->in, b->out, b->total
+ p->proto,
+ getproto(p->proto),
+ (qu)b->in,
+ (qu)b->out,
+ (qu)b->total
);
}
@@ -1027,7 +1043,7 @@ static struct str *html_hosts_detail(const char *ip) {
struct str *buf, *ls_len;
char ls_when[100];
const char *canonical;
- time_t last_real;
+ time_t last_seen_real;
h = host_search(ip);
if (h == NULL)
@@ -1065,9 +1081,9 @@ static struct str *html_hosts_detail(const char *ip) {
"\n"
"Last seen: ");
- last_real = mono_to_real(h->u.host.last_seen_mono);
+ last_seen_real = mono_to_real(h->u.host.last_seen_mono);
if (strftime(ls_when, sizeof(ls_when),
- "%Y-%m-%d %H:%M:%S %Z%z", localtime(&last_real)) != 0)
+ "%Y-%m-%d %H:%M:%S %Z%z", localtime(&last_seen_real)) != 0)
str_append(buf, ls_when);
if (h->u.host.last_seen_mono <= now_mono()) {
@@ -1087,7 +1103,9 @@ static struct str *html_hosts_detail(const char *ip) {
" Out: %'qu
\n"
" Total: %'qu
\n"
"
\n",
- h->in, h->out, h->total);
+ (qu)h->in,
+ (qu)h->out,
+ (qu)h->total);
str_append(buf, "TCP ports
\n");
format_table(buf, h->u.host.ports_tcp, 0,TOTAL,0);
diff --git a/hosts_db.h b/hosts_db.h
index 3f869f1..109f373 100644
--- a/hosts_db.h
+++ b/hosts_db.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* hosts_db.h: database of hosts, ports, protocols.
*
@@ -19,7 +19,7 @@ struct host {
struct addr addr;
char *dns;
uint8_t mac_addr[6];
- long last_seen_mono;
+ time_t last_seen_mono;
struct hashtable *ports_tcp, *ports_udp, *ip_protos;
};
diff --git a/hosts_sort.c b/hosts_sort.c
index b6f32dd..bb88581 100644
--- a/hosts_sort.c
+++ b/hosts_sort.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* hosts_sort.c: quicksort a table of buckets.
*
diff --git a/http.c b/http.c
index e39f16b..0cd6133 100644
--- a/http.c
+++ b/http.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2012 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* http.c: embedded webserver.
* This borrows a lot of code from darkhttpd.
@@ -37,6 +37,9 @@
#include
#include
+static char *http_base_url = NULL;
+static int http_base_len = 0;
+
static const char mime_type_xml[] = "text/xml";
static const char mime_type_html[] = "text/html; charset=us-ascii";
static const char mime_type_css[] = "text/css";
@@ -56,7 +59,7 @@ struct connection {
int socket;
struct sockaddr_storage client;
- long last_active_mono;
+ time_t last_active_mono;
enum {
RECV_REQUEST, /* receiving request */
SEND_HEADER_AND_REPLY, /* try to send header+reply together */
@@ -381,23 +384,28 @@ static void generate_header(struct connection *conn,
if (conn->encoding == NULL)
conn->encoding = encoding_identity;
- verbosef("http: %d %s (%s: %zu bytes)", code, text,
- conn->encoding, conn->reply_length);
+ verbosef("http: %d %s (%s: %zu bytes)",
+ code,
+ text,
+ conn->encoding,
+ conn->reply_length);
conn->header_length = xasprintf(&(conn->header),
"HTTP/1.1 %d %s\r\n"
"Date: %s\r\n"
"Server: %s\r\n"
"Vary: Accept-Encoding\r\n"
"Content-Type: %s\r\n"
- "Content-Length: %d\r\n"
+ "Content-Length: %qu\r\n"
"Content-Encoding: %s\r\n"
"X-Robots-Tag: noindex, noarchive\r\n"
"%s"
- "\r\n"
- ,
+ "\r\n",
code, text,
- rfc1123_date(date, now_real()), server,
- conn->mime_type, conn->reply_length, conn->encoding,
+ rfc1123_date(date, now_real()),
+ server,
+ conn->mime_type,
+ (qu)conn->reply_length,
+ conn->encoding,
conn->header_extra);
conn->http_code = code;
}
@@ -407,6 +415,9 @@ static void generate_header(struct connection *conn,
/* ---------------------------------------------------------------------------
* A default reply for any (erroneous) occasion.
*/
+static void default_reply(struct connection *conn,
+ const int errcode, const char *errname, const char *format, ...)
+ _printflike_(4, 5);
static void default_reply(struct connection *conn,
const int errcode, const char *errname, const char *format, ...)
{
@@ -571,11 +582,16 @@ process_gzip(struct connection *conn)
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
- if (deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED,
- 15+16, /* 15 = biggest window, 16 = add gzip header+trailer */
- 8 /* default */,
- Z_DEFAULT_STRATEGY) != Z_OK)
- return;
+ if (deflateInit2(&zs,
+ Z_BEST_COMPRESSION,
+ Z_DEFLATED,
+ 15+16, /* 15 = biggest window,
+ 16 = add gzip header+trailer */
+ 8 /* default */,
+ Z_DEFAULT_STRATEGY) != Z_OK) {
+ free(buf);
+ return;
+ }
zs.avail_in = conn->reply_length;
zs.next_in = (unsigned char *)conn->reply;
@@ -586,7 +602,7 @@ process_gzip(struct connection *conn)
if (deflate(&zs, Z_FINISH) != Z_STREAM_END) {
deflateEnd(&zs);
free(buf);
- verbosef("failed to compress %u bytes", (unsigned int)len);
+ verbosef("failed to compress %zu bytes", len);
return;
}
@@ -605,22 +621,32 @@ process_gzip(struct connection *conn)
*/
static void process_get(struct connection *conn)
{
- char *decoded_url, *safe_url;
+ char *safe_url;
verbosef("http: %s \"%s\" %s", conn->method, conn->uri,
(conn->query == NULL)?"":conn->query);
- /* work out path of file being requested */
- decoded_url = urldecode(conn->uri);
-
- /* make sure it's safe */
- safe_url = make_safe_uri(decoded_url);
- free(decoded_url);
- if (safe_url == NULL)
{
- default_reply(conn, 400, "Bad Request",
- "You requested an invalid URI: %s", conn->uri);
- return;
+ /* Decode the URL being requested. */
+ char *decoded_url;
+ char *decoded_url_offset;
+
+ decoded_url = urldecode(conn->uri);
+
+ /* Optionally strip the base. */
+ decoded_url_offset = decoded_url;
+ if (str_starts_with(decoded_url, http_base_url)) {
+ decoded_url_offset += http_base_len - 1;
+ }
+
+ /* Make sure it's safe. */
+ safe_url = make_safe_uri(decoded_url_offset);
+ free(decoded_url);
+ if (safe_url == NULL) {
+ default_reply(conn, 400, "Bad Request",
+ "You requested an invalid URI: %s", conn->uri);
+ return;
+ }
}
if (strcmp(safe_url, "/") == 0) {
@@ -873,6 +899,40 @@ static void poll_send_reply(struct connection *conn)
if (conn->reply_sent == conn->reply_length) conn->state = DONE;
}
+
+
+/* --------------------------------------------------------------------------
+ * Initialize the base url.
+ */
+void http_init_base(const char *url) {
+ char *slashed_url, *safe_url;
+ size_t urllen;
+
+ if (url == NULL) {
+ http_base_url = strdup("/");
+ } else {
+ /* Make sure that the url has leading and trailing slashes. */
+ urllen = strlen(url);
+ slashed_url = xmalloc(urllen+3);
+ slashed_url[0] = '/';
+ memcpy(slashed_url+1, url, urllen); /* don't copy NUL */
+ slashed_url[urllen+1] = '/';
+ slashed_url[urllen+2] = '\0';
+
+ /* Clean the url. */
+ safe_url = make_safe_uri(slashed_url);
+ free(slashed_url);
+ if (safe_url == NULL) {
+ verbosef("invalid base \"%s\", ignored", url);
+ http_base_url = strdup("/"); /* set to default */
+ } else {
+ http_base_url = safe_url;
+ }
+ }
+ http_base_len = strlen(http_base_url);
+ verbosef("set base url to \"%s\"", http_base_url);
+}
+
/* Use getaddrinfo to figure out what type of socket to create and
* what to bind it to. "bindaddr" can be NULL. Remember to freeaddrinfo()
* the result.
@@ -962,11 +1022,12 @@ static void http_listen_one(struct addrinfo *ai,
if (listen(sockin, 128) == -1)
err(1, "listen() failed");
- verbosef("listening on http://%s%s%s:%u/",
+ verbosef("listening on http://%s%s%s:%u%s",
(ai->ai_family == AF_INET6) ? "[" : "",
ipaddr,
(ai->ai_family == AF_INET6) ? "]" : "",
- bindport);
+ bindport,
+ http_base_url);
/* add to insocks */
insocks = xrealloc(insocks, sizeof(*insocks) * (insock_num + 1));
@@ -1122,6 +1183,8 @@ void http_stop(void) {
struct connection *conn;
unsigned int i;
+ free(http_base_url);
+
/* Close listening sockets. */
for (i=0; i
#include
+void http_init_base(const char *url);
void http_add_bindaddr(const char *bindaddr);
void http_listen(const unsigned short bindport);
void http_fd_set(fd_set *recv_set, fd_set *send_set, int *max_fd,
diff --git a/localip.c b/localip.c
index f7b7f93..24951c6 100644
--- a/localip.c
+++ b/localip.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* localip.c: determine local IPs of an interface
*
diff --git a/localip.h b/localip.h
index a5b48ea..2625ada 100644
--- a/localip.h
+++ b/localip.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* localip.h: determine the local IPs of an interface
*
@@ -13,7 +13,7 @@
struct local_ips {
int is_valid;
- long last_update_mono;
+ time_t last_update_mono;
int num_addrs;
struct addr *addrs;
};
diff --git a/ncache.c b/ncache.c
index 96e052f..1d23d1c 100644
--- a/ncache.c
+++ b/ncache.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* ncache.c: cache of protocol and service names.
*
@@ -33,7 +33,7 @@ rec_cmp(struct name_rec *a, struct name_rec *b)
}
RB_HEAD(nc_tree, name_rec);
-RB_GENERATE(nc_tree, name_rec, ptree, rec_cmp)
+RB_GENERATE_STATIC(nc_tree, name_rec, ptree, rec_cmp)
static struct nc_tree
t_proto = RB_INITIALIZER(&name_rec),
diff --git a/now.c b/now.c
index f0751a8..95ab2a2 100644
--- a/now.c
+++ b/now.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2012 Emil Mikulic.
+ * copyright (c) 2012-2014 Emil Mikulic.
*
* now.c: a cache of the current time.
*
@@ -17,12 +17,13 @@
*/
#include "err.h"
#include "now.h"
+#include "str.h"
#include
#include
#include
-#ifdef __MACH__
+#ifdef __APPLE__
/* Fake up clock_gettime() on OS X. */
# include
# include
@@ -62,12 +63,12 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp) {
static struct timespec clock_real, clock_mono;
static int now_initialized = 0;
-long now_real(void) {
+time_t now_real(void) {
assert(now_initialized);
return clock_real.tv_sec;
}
-long now_mono(void) {
+time_t now_mono(void) {
assert(now_initialized);
return clock_mono.tv_sec;
}
@@ -80,6 +81,17 @@ static int before(const struct timespec *a, const struct timespec *b) {
return 0;
}
+static void warn_backwards(const char *name,
+ const struct timespec * const t0,
+ const struct timespec * const t1) {
+ verbosef("%s clock went backwards from %lld.%09lld to %lld.%09lld",
+ name,
+ (lld)t0->tv_sec,
+ (lld)t0->tv_nsec,
+ (lld)t1->tv_sec,
+ (lld)t1->tv_nsec);
+}
+
static void clock_update(const clockid_t clk_id,
struct timespec *dest,
const char *name) {
@@ -87,12 +99,7 @@ static void clock_update(const clockid_t clk_id,
clock_gettime(clk_id, &t);
if (now_initialized && before(&t, dest)) {
- verbosef("%s clock went backwards from %ld.%09ld to %ld.%09ld",
- name,
- (long)dest->tv_sec,
- (long)dest->tv_nsec,
- (long)t.tv_sec,
- (long)t.tv_nsec);
+ warn_backwards(name, &t, dest);
}
memcpy(dest, &t, sizeof(t));
}
@@ -113,12 +120,12 @@ void now_update(void) {
all_clocks_update();
}
-long mono_to_real(const long t) {
+time_t mono_to_real(const time_t t) {
assert(now_initialized);
return t - clock_mono.tv_sec + clock_real.tv_sec;
}
-long real_to_mono(const long t) {
+time_t real_to_mono(const time_t t) {
assert(now_initialized);
return t - clock_real.tv_sec + clock_mono.tv_sec;
}
@@ -133,20 +140,24 @@ static int64_t ts_diff(const struct timespec * const a,
a->tv_nsec - b->tv_nsec;
}
-void timer_stop(const struct timespec * const t,
+void timer_stop(const struct timespec * const t0,
const int64_t nsec,
const char *warning) {
- struct timespec t2;
+ struct timespec t1;
int64_t diff;
- clock_gettime(CLOCK_MONOTONIC, &t2);
- diff = ts_diff(&t2, t);
- assert(diff > 0);
- if (diff > nsec)
+ clock_gettime(CLOCK_MONOTONIC, &t1);
+ if (before(&t1, t0)) {
+ warn_backwards("monotonic timer", t0, &t1);
+ return;
+ }
+ diff = ts_diff(&t1, t0);
+ if (diff > nsec) {
warnx("%s (took %lld nsec, over threshold of %lld nsec)",
warning,
- (long long)diff,
- (long long)nsec);
+ (lld)diff,
+ (lld)nsec);
+ }
}
/* vim:set ts=3 sw=3 tw=80 et: */
diff --git a/now.h b/now.h
index 9c61f45..03366e7 100644
--- a/now.h
+++ b/now.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2006 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* now.h: a cache of the current time.
*
@@ -20,11 +20,11 @@
void now_init(void);
void now_update(void); /* once per event loop (in darkstat.c) */
-long now_real(void);
-long now_mono(void);
+time_t now_real(void);
+time_t now_mono(void);
-long mono_to_real(const long t);
-long real_to_mono(const long t);
+time_t mono_to_real(const time_t t);
+time_t real_to_mono(const time_t t);
/* Emits warnings if a call is too slow. */
struct timespec;
diff --git a/opt.h b/opt.h
index 34afc36..dfbd384 100644
--- a/opt.h
+++ b/opt.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* opt.h: global options
*/
diff --git a/pidfile.c b/pidfile.c
index 044c574..92403cd 100644
--- a/pidfile.c
+++ b/pidfile.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2007-2011 Emil Mikulic.
+ * copyright (c) 2007-2014 Emil Mikulic.
*
* pidfile.h: pidfile manglement
*
@@ -29,10 +29,9 @@
static int pidfd = -1;
static const char *pidname = NULL;
-void
-pidfile_create(const char *chroot_dir, const char *filename,
- const char *privdrop_user)
-{
+void pidfile_create(const char *chroot_dir,
+ const char *filename,
+ const char *privdrop_user) {
struct passwd *pw;
if (pidfd != -1)
@@ -48,8 +47,11 @@ pidfile_create(const char *chroot_dir, const char *filename,
err(1, "getpwnam(\"%s\") failed", privdrop_user);
}
- if (chdir(chroot_dir) == -1)
- err(1, "chdir(\"%s\") failed", chroot_dir);
+ if (chroot_dir != NULL) {
+ if (chdir(chroot_dir) == -1) {
+ err(1, "chdir(\"%s\") failed", chroot_dir);
+ }
+ }
pidname = filename;
pidfd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600);
if (pidfd == -1)
diff --git a/str.c b/str.c
index 852a24d..a73f387 100644
--- a/str.c
+++ b/str.c
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* str.c: string buffer with pool-based reallocation
*
diff --git a/str.h b/str.h
index 92cb78f..c6cb197 100644
--- a/str.h
+++ b/str.h
@@ -1,5 +1,5 @@
/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2014 Emil Mikulic.
*
* str.h: string buffer with pool-based reallocation
*
@@ -15,9 +15,24 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifndef __DARKSTAT_STR_H
+#define __DARKSTAT_STR_H
+
+#include "cdefs.h"
#include
#include
+#include /* for uint64_t */
+
+typedef long long signed int qd; /* as in appendf("%qd") */
+typedef long long unsigned int qu; /* as in appendf("%qu") */
+typedef long long unsigned int lld; /* as in printf("%lld") */
+typedef long long unsigned int llu; /* as in printf("%llu") */
+
+_Static_assert(sizeof(qd) == sizeof(int64_t), "qd must be int64_t sized");
+_Static_assert(sizeof(qu) == sizeof(uint64_t), "qu must be uint64_t sized");
+_Static_assert(sizeof(lld) == sizeof(int64_t), "lld must be int64_t sized");
+_Static_assert(sizeof(llu) == sizeof(uint64_t), "llu must be uint64_t sized");
/* Note: the contents are 8-bit clean and not zero terminated! */
@@ -39,13 +54,16 @@ void str_appendstr(struct str *buf, const struct str *s);
void str_append(struct str *buf, const char *s);
#endif
-size_t xvasprintf(char **result, const char *format, va_list va);
-size_t xasprintf(char **result, const char *format, ...);
-void str_appendf(struct str *buf, const char *format, ...);
-void str_vappendf(struct str *s, const char *format, va_list va);
+size_t xvasprintf(char **result, const char *format, va_list va)
+ _printflike_(2, 0);
+size_t xasprintf(char **result, const char *format, ...) _printflike_(2, 3);
+void str_vappendf(struct str *s, const char *format, va_list va)
+ _printflike_(2, 0);
+void str_appendf(struct str *s, const char *format, ...) _printflike_(2, 3);
struct str *length_of_time(const time_t t);
ssize_t str_write(const struct str * const buf, const int fd);
size_t str_len(const struct str * const buf);
+#endif /* __DARKSTAT_STR_H */
/* vim:set ts=3 sw=3 tw=78 expandtab: */
diff --git a/tree.h b/tree.h
index f533547..6ee1af6 100644
--- a/tree.h
+++ b/tree.h
@@ -1,12 +1,8 @@
-/* This is a cut down version of FreeBSD's
- * src/sys/sys/tree.h,v 1.5
- *
- * Also tagged
- * $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $
- * $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $
- *
- * The original file's license:
- *
+/* This is a cut down version of NetBSD's /usr/include/sys/tree.h */
+
+/* $NetBSD: tree.h,v 1.20 2013/09/14 13:20:45 joerg Exp $ */
+/* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */
+/*
* Copyright 2002 Niels Provos
* All rights reserved.
*
@@ -31,12 +27,23 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef _SYS_TREE_H_
+#define _SYS_TREE_H_
+
+#include "cdefs.h"
+
+/* Macros that define a red-black tree */
#define RB_HEAD(name, type) \
struct name { \
struct type *rbh_root; /* root of the tree */ \
}
-#define RB_INITIALIZER(root) { NULL }
+#define RB_INITIALIZER(root) \
+ { NULL }
+
+#define RB_INIT(root) do { \
+ (root)->rbh_root = NULL; \
+} while (/*CONSTCOND*/ 0)
#define RB_BLACK 0
#define RB_RED 1
@@ -53,6 +60,7 @@ struct { \
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
#define RB_COLOR(elm, field) (elm)->field.rbe_color
#define RB_ROOT(head) (head)->rbh_root
+#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
#define RB_SET(elm, parent, field) do { \
RB_PARENT(elm, field) = parent; \
@@ -65,7 +73,9 @@ struct { \
RB_COLOR(red, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
-#define RB_AUGMENT(x) do {} while (0)
+#ifndef RB_AUGMENT
+#define RB_AUGMENT(x) do {} while (/*CONSTCOND*/ 0)
+#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
@@ -107,8 +117,32 @@ struct { \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
+/* Generates prototypes and inline functions */
+#define RB_PROTOTYPE(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
+#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, _unused_ static)
+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
+attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
+attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
+attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
+attr struct type *name##_RB_INSERT(struct name *, struct type *); \
+attr struct type *name##_RB_FIND(struct name *, struct type *); \
+attr struct type *name##_RB_NFIND(struct name *, struct type *); \
+attr struct type *name##_RB_NEXT(struct type *); \
+attr struct type *name##_RB_PREV(struct type *); \
+attr struct type *name##_RB_MINMAX(struct name *, int); \
+ \
+
+#include
+
+/* Main rb operation.
+ * Moves node close to the key of elm to top
+ */
#define RB_GENERATE(name, type, field, cmp) \
- RB_GENERATE_INTERNAL(name, type, field, cmp, static)
+ RB_GENERATE_INTERNAL(name, type, field, cmp,)
+#define RB_GENERATE_STATIC(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, _unused_ static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
@@ -117,6 +151,7 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
while ((parent = RB_PARENT(elm, field)) != NULL && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
+ assert(gparent != NULL); \
if (parent == RB_LEFT(gparent, field)) { \
tmp = RB_RIGHT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
@@ -167,6 +202,7 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = RB_RIGHT(parent, field); \
} \
+ assert(tmp != NULL); \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
@@ -200,6 +236,7 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = RB_LEFT(parent, field); \
} \
+ assert(tmp != NULL); \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
@@ -270,6 +307,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
RB_AUGMENT(RB_PARENT(old, field)); \
} else \
RB_ROOT(head) = elm; \
+ assert(RB_LEFT(old, field) != NULL); \
RB_PARENT(RB_LEFT(old, field), field) = elm; \
if (RB_RIGHT(old, field)) \
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
@@ -348,6 +386,27 @@ name##_RB_FIND(struct name *head, struct type *elm) \
return (NULL); \
} \
\
+/* Finds the first node greater than or equal to the search key */ \
+attr struct type * \
+name##_RB_NFIND(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *res = NULL; \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) { \
+ res = tmp; \
+ tmp = RB_LEFT(tmp, field); \
+ } \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (res); \
+} \
+ \
/* ARGSUSED */ \
attr struct type * \
name##_RB_NEXT(struct type *elm) \
@@ -370,6 +429,28 @@ name##_RB_NEXT(struct type *elm) \
return (elm); \
} \
\
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_PREV(struct type *elm) \
+{ \
+ if (RB_LEFT(elm, field)) { \
+ elm = RB_LEFT(elm, field); \
+ while (RB_RIGHT(elm, field)) \
+ elm = RB_RIGHT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
attr struct type * \
name##_RB_MINMAX(struct name *head, int val) \
{ \
@@ -386,9 +467,45 @@ name##_RB_MINMAX(struct name *head, int val) \
}
#define RB_NEGINF -1
+#define RB_INF 1
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
+#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
+#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
+#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
+
+#define RB_FOREACH(x, name, head) \
+ for ((x) = RB_MIN(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_NEXT(x))
+
+#define RB_FOREACH_FROM(x, name, y) \
+ for ((x) = (y); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_SAFE(x, name, head, y) \
+ for ((x) = RB_MIN(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE(x, name, head) \
+ for ((x) = RB_MAX(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_PREV(x))
+
+#define RB_FOREACH_REVERSE_FROM(x, name, y) \
+ for ((x) = (y); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
+ for ((x) = RB_MAX(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
+ (x) = (y))
+
+#endif /* _SYS_TREE_H_ */