doc/Makefile | 4 +- doc/ulogd.sgml | 6 +- output/pcap/ulogd_output_PCAP.c | 2 +- output/ulogd_output_GPRINT.c | 2 +- output/ulogd_output_LOGEMU.c | 2 +- output/ulogd_output_NACCT.c | 2 +- output/ulogd_output_OPRINT.c | 2 +- output/ulogd_output_XML.c | 2 +- src/Makefile.am | 2 +- src/ulogd.c | 132 +++++++++++++++++++++++++++++++++++++--- ulogd.8 | 2 +- ulogd.conf.in | 22 +++---- 12 files changed, 149 insertions(+), 31 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 8ccb9ad..88f5823 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,7 +1,7 @@ all: sgml2txt ulogd.sgml - sgml2latex --papersize=a4 --output=dvi ulogd.sgml - dvips -t a4 -o ulogd.ps ulogd.dvi +# sgml2latex --papersize=a4 --output=dvi ulogd.sgml +# dvips -t a4 -o ulogd.ps ulogd.dvi sgml2html -s 0 ulogd.sgml clean: rm -f ulogd.dvi ulogd.txt ulogd.html ulogd.ps diff --git a/doc/ulogd.sgml b/doc/ulogd.sgml index 30bfecb..23b1f16 100644 --- a/doc/ulogd.sgml +++ b/doc/ulogd.sgml @@ -422,7 +422,7 @@ to a file. The only useful application is debugging. dumpfile The filename where it should log to. The default is -/var/log/ulogd.pktlog +/var/log/ulogd/ulogd.pktlog ulogd_output_LOGEMU.so @@ -433,7 +433,7 @@ as possible. Logging is done to a seperate textfile instead of syslog, though. The module defines the following configuration directives: fileThe filename where it should log to. The default is -/var/log/ulogd.syslogemu +/var/log/ulogd/ulogd.syslogemu syncSet this to 1 if you want to have your logfile written synchronously. This may reduce performance, but makes your log-lines appear immediately. The default is 0 @@ -557,7 +557,7 @@ The module defines the following configuration directives: file The filename where it should log to. The default is: -/var/log/ulogd.pcap +/var/log/ulogd/ulogd.pcap sync Set this to 1 if you want to have your pcap logfile written synchronously. This may reduce performance, but makes your packets appear diff --git a/output/pcap/ulogd_output_PCAP.c b/output/pcap/ulogd_output_PCAP.c index e7798f2..35e39f2 100644 --- a/output/pcap/ulogd_output_PCAP.c +++ b/output/pcap/ulogd_output_PCAP.c @@ -75,7 +75,7 @@ struct pcap_sf_pkthdr { }; #ifndef ULOGD_PCAP_DEFAULT -#define ULOGD_PCAP_DEFAULT "/var/log/ulogd.pcap" +#define ULOGD_PCAP_DEFAULT "/var/log/ulogd/ulogd.pcap" #endif #ifndef ULOGD_PCAP_SYNC_DEFAULT diff --git a/output/ulogd_output_GPRINT.c b/output/ulogd_output_GPRINT.c index 4f49c34..3a45a2d 100644 --- a/output/ulogd_output_GPRINT.c +++ b/output/ulogd_output_GPRINT.c @@ -31,7 +31,7 @@ #include #ifndef ULOGD_GPRINT_DEFAULT -#define ULOGD_GPRINT_DEFAULT "/var/log/ulogd.gprint" +#define ULOGD_GPRINT_DEFAULT "/var/log/ulogd/ulogd.gprint" #endif struct gprint_priv { diff --git a/output/ulogd_output_LOGEMU.c b/output/ulogd_output_LOGEMU.c index bb27209..4f5856e 100644 --- a/output/ulogd_output_LOGEMU.c +++ b/output/ulogd_output_LOGEMU.c @@ -37,7 +37,7 @@ #endif #ifndef ULOGD_LOGEMU_DEFAULT -#define ULOGD_LOGEMU_DEFAULT "/var/log/ulogd.syslogemu" +#define ULOGD_LOGEMU_DEFAULT "/var/log/ulogd/ulogd.syslogemu" #endif #ifndef ULOGD_LOGEMU_SYNC_DEFAULT diff --git a/output/ulogd_output_NACCT.c b/output/ulogd_output_NACCT.c index 9de8a73..5544788 100644 --- a/output/ulogd_output_NACCT.c +++ b/output/ulogd_output_NACCT.c @@ -29,7 +29,7 @@ #include #include -#define NACCT_FILE_DEFAULT "/var/log/nacctdata.log" +#define NACCT_FILE_DEFAULT "/var/log/ulogd/nacctdata.log" /* config accessors (lazy me...) */ #define NACCT_CFG_FILE(pi) ((pi)->config_kset->ces[0].u.string) diff --git a/output/ulogd_output_OPRINT.c b/output/ulogd_output_OPRINT.c index e390c84..bfe5b7a 100644 --- a/output/ulogd_output_OPRINT.c +++ b/output/ulogd_output_OPRINT.c @@ -28,7 +28,7 @@ #include #ifndef ULOGD_OPRINT_DEFAULT -#define ULOGD_OPRINT_DEFAULT "/var/log/ulogd.pktlog" +#define ULOGD_OPRINT_DEFAULT "/var/log/ulogd/ulogd.pktlog" #endif #define NIPQUAD(addr) \ diff --git a/output/ulogd_output_XML.c b/output/ulogd_output_XML.c index ba33739..e2dc5f2 100644 --- a/output/ulogd_output_XML.c +++ b/output/ulogd_output_XML.c @@ -36,7 +36,7 @@ #include #ifndef ULOGD_XML_DEFAULT_DIR -#define ULOGD_XML_DEFAULT_DIR "/var/log/" +#define ULOGD_XML_DEFAULT_DIR "/var/log/ulogd/" #endif enum { diff --git a/src/Makefile.am b/src/Makefile.am index 998e776..b38a42c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include \ -DULOGD_CONFIGFILE="\"$(sysconfdir)/ulogd.conf\"" \ - -DULOGD_LOGFILE_DEFAULT="\"$(localstatedir)/log/ulogd.log\"" + -DULOGD_LOGFILE_DEFAULT="\"/var/log/ulogd/ulogd.log\"" AM_CFLAGS = ${regular_CFLAGS} sbin_PROGRAMS = ulogd diff --git a/src/ulogd.c b/src/ulogd.c index e7cde39..681437a 100644 --- a/src/ulogd.c +++ b/src/ulogd.c @@ -90,6 +90,29 @@ static int info_mode = 0; static int verbose = 0; static int created_pidfile = 0; +/* + * Using self-pipe trick to handle signals safely. + * (To avoid calling Async-Signal-Unsafe functions in signal handler.) + * + * cf. https://lwn.net/Articles/177897/ + * + * Capacity of pipe(2) buffer is >= 4096. + */ +static int signal_channel[2] = { -1, -1 }; /* initialize with invalid fd */ +#define SIGNAL_RX_FD (signal_channel[0]) /* main thread select() this fd */ +#define SIGNAL_TX_FD (signal_channel[1]) /* signal handler writes to this fd */ + +static void signal_handler(int signal); +static void sigterm_handler_task(int signal); +static void signal_handler_task(int signal); + +static int signal_channel_callback(int fd, unsigned int what, void *data); +static struct ulogd_fd signal_channel_ulogfd = { + .when = ULOGD_FD_READ, + .cb = &signal_channel_callback, + .data = &signal_channel_ulogfd, +}; + /* linked list for all registered plugins */ static LLIST_HEAD(ulogd_plugins); /* linked list for all plugins handle */ @@ -387,6 +410,80 @@ void ulogd_register_plugin(struct ulogd_plugin *me) } /*********************************************************************** + * UTILITY FUNCTIONS FOR SIGNAL HANDLING + ***********************************************************************/ +static void call_signal_handler_tasks(int sig) +{ + /* Deliver signals */ + switch (sig) { + case SIGTERM: + case SIGINT: + sigterm_handler_task(sig); + break; + case SIGHUP: + case SIGALRM: + case SIGUSR1: + case SIGUSR2: + signal_handler_task(sig); + break; + default: + break; + } +} + +static int signal_channel_callback(int fd, unsigned int what, void *data) +{ + int ret; + unsigned char c; + + while ((ret = read(fd, &c, 1)) > 0) { + call_signal_handler_tasks((int)c); + } + return 0; +} + +static int create_signal_channel(void) +{ + int ret; + long flags; + + if ((ret = pipe(signal_channel)) < 0) + return ret; + + /* SIGNAL_RX_FD, channel[0] */ + if ((flags = fcntl(SIGNAL_RX_FD, F_GETFL)) < 0) + goto err_exit; + flags |= O_NONBLOCK; + if ( fcntl(SIGNAL_RX_FD, F_SETFL, flags) < 0 ) + goto err_exit; + + /* SIGNAL_TX_FD, channel[1] */ + if ((flags = fcntl(SIGNAL_TX_FD, F_GETFL)) < 0) + goto err_exit; + flags |= O_NONBLOCK; + if ( fcntl(SIGNAL_TX_FD, F_SETFL, flags) < 0 ) + goto err_exit; + + /* register SIGNAL_RX_FD to ulogd */ + signal_channel_ulogfd.fd = SIGNAL_RX_FD; + ulogd_register_fd(&signal_channel_ulogfd); + + return 0; + +err_exit: + if (SIGNAL_RX_FD >= 0) { + (void)close(SIGNAL_RX_FD); + SIGNAL_RX_FD = -1; + } + if (SIGNAL_TX_FD >= 0) { + (void)close(SIGNAL_TX_FD); + SIGNAL_TX_FD = -1; + } + return -1; +} + + +/*********************************************************************** * MAIN PROGRAM ***********************************************************************/ @@ -925,7 +1022,6 @@ static void ulogd_main_loop(void) struct timeval *next = NULL; while (1) { - /* XXX: signal blocking? */ if (next != NULL && !timerisset(next)) next = ulogd_do_timer_run(&next_alarm); else @@ -1225,7 +1321,19 @@ static void stop_stack() } -static void sigterm_handler(int signal) +/* This is a real SIGTERM, SIGINT, SIGHUP, SIGALRM, SIGUSR1, SIGUSR2 handler */ +static void signal_handler(int signal) +{ + unsigned char c = (unsigned char)signal; + + (void)write(SIGNAL_TX_FD, &c, 1); +} + +/* This is NOT a real signal handler. + * It is called in ulogd_main_loop() to avoid + * calling Async-Signal-UnSafe functions in signal handler. + */ +static void sigterm_handler_task(int signal) { ulogd_log(ULOGD_NOTICE, "Terminal signal received, exiting\n"); @@ -1255,7 +1363,12 @@ static void sigterm_handler(int signal) exit(0); } -static void signal_handler(int signal) + +/* This is NOT a real signal handler. + * It is called in ulogd_main_loop() to avoid + * calling Async-Signal-UnSafe functions in signal handler. + */ +static void signal_handler_task(int signal) { ulogd_log(ULOGD_NOTICE, "signal received, calling pluginstances\n"); @@ -1269,7 +1382,7 @@ static void signal_handler(int signal) fprintf(stderr, "ERROR: can't open logfile %s: %s\n", ulogd_logfile, strerror(errno)); - sigterm_handler(signal); + sigterm_handler_task(signal); } } @@ -1464,8 +1577,13 @@ int main(int argc, char* argv[]) } } - signal(SIGTERM, &sigterm_handler); - signal(SIGINT, &sigterm_handler); + if (create_signal_channel() < 0) { + ulogd_log(ULOGD_FATAL, "can't create signal channel\n"); + warn_and_exit(daemonize); + } + + signal(SIGTERM, &signal_handler); + signal(SIGINT, &signal_handler); signal(SIGHUP, &signal_handler); signal(SIGALRM, &signal_handler); signal(SIGUSR1, &signal_handler); @@ -1477,6 +1595,6 @@ int main(int argc, char* argv[]) ulogd_main_loop(); /* hackish, but result is the same */ - sigterm_handler(SIGTERM); + sigterm_handler_task(SIGTERM); return(0); } diff --git a/ulogd.8 b/ulogd.8 index 9d16aeb..c20d0a9 100644 --- a/ulogd.8 +++ b/ulogd.8 @@ -63,7 +63,7 @@ record the ulogd process ID to the given file name .SH FILES .I /etc/ulogd.conf .br -.I /var/log/ulogd.log +.I /var/log/ulogd/ulogd.log .SH SEE ALSO There is more documentation about the daemon and the database plugins (including examples) in the directories diff --git a/ulogd.conf.in b/ulogd.conf.in index 8893175..f0a26b8 100644 --- a/ulogd.conf.in +++ b/ulogd.conf.in @@ -8,7 +8,7 @@ # logfile for status messages -logfile="/var/log/ulogd.log" +logfile="/var/log/ulogd/ulogd.log" # loglevel: debug(1), info(3), notice(5), error(7) or fatal(8) (default 5) # loglevel=1 @@ -52,7 +52,7 @@ plugin="@pkglibdir@/ulogd_output_GRAPHITE.so" #plugin="@pkglibdir@/ulogd_output_JSON.so" # this is a stack for logging packet send by system via LOGEMU -#stack=log1:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,emu1:LOGEMU +stack=log1:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,emu1:LOGEMU # this is a stack for packet-based logging via LOGEMU #stack=log2:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,emu1:LOGEMU @@ -183,20 +183,20 @@ nlgroup=1 socket_path="/tmp/nuauth_ulogd2.sock" [emu1] -file="/var/log/ulogd_syslogemu.log" +file="/var/log/ulogd/ulogd_syslogemu.log" sync=1 [op1] -file="/var/log/ulogd_oprint.log" +file="/var/log/ulogd/ulogd_oprint.log" sync=1 [gp1] -file="/var/log/ulogd_gprint.log" +file="/var/log/ulogd/ulogd_gprint.log" sync=1 timestamp=1 [xml1] -directory="/var/log/" +directory="/var/log/ulogd/" sync=1 [json1] @@ -211,8 +211,8 @@ sync=1 #boolean_label=1 [pcap1] -#default file is /var/log/ulogd.pcap -#file="/var/log/ulogd.pcap" +#default file is /var/log/ulogd/ulogd.pcap +#file="/var/log/ulogd/ulogd.pcap" sync=1 [mysql1] @@ -297,12 +297,12 @@ procedure="INSERT_PACKET_FULL" [sqlite3_ct] table="ulog_ct" -db="/var/log/ulogd.sqlite3db" +db="/var/lib/ulogd/ulogd.sqlite3db" buffer=200 [sqlite3_pkt] table="ulog_pkt" -db="/var/log/ulogd.sqlite3db" +db="/var/lib/ulogd/ulogd.sqlite3db" buffer=200 [sys2] @@ -310,7 +310,7 @@ facility=LOG_LOCAL2 [nacct1] sync = 1 -#file = /var/log/ulogd_nacct.log +#file = /var/log/ulogd/ulogd_nacct.log [mark1] mark = 1