syslogd: optional support for dropping dups. closes bug 436.

This commit is contained in:
Denis Vlasenko 2008-02-26 20:13:52 +00:00
parent 06aed4316e
commit be048f21e6
3 changed files with 54 additions and 21 deletions

View File

@ -3686,8 +3686,8 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when
"[OPTION]..." "[OPTION]..."
#define syslogd_full_usage \ #define syslogd_full_usage \
"System logging utility.\n" \ "System logging utility.\n" \
"Note that this version of syslogd ignores /etc/syslog.conf." \ "Note that this version of syslogd ignores /etc/syslog.conf.\n" \
"\n\nOptions:" \ "\nOptions:" \
"\n -n Run in foreground" \ "\n -n Run in foreground" \
"\n -O FILE Log to given file (default=/var/log/messages)" \ "\n -O FILE Log to given file (default=/var/log/messages)" \
"\n -l n Set local log level" \ "\n -l n Set local log level" \
@ -3698,6 +3698,8 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when
USE_FEATURE_REMOTE_LOG( \ USE_FEATURE_REMOTE_LOG( \
"\n -R HOST[:PORT] Log to IP or hostname on PORT (default PORT=514/UDP)" \ "\n -R HOST[:PORT] Log to IP or hostname on PORT (default PORT=514/UDP)" \
"\n -L Log locally and via network (default is network only if -R)") \ "\n -L Log locally and via network (default is network only if -R)") \
USE_FEATURE_SYSLOGD_DUP( \
"\n -D Drop duplicates") \
USE_FEATURE_IPC_SYSLOG( \ USE_FEATURE_IPC_SYSLOG( \
"\n -C[size(KiB)] Log to shared mem buffer (read it using logread)") "\n -C[size(KiB)] Log to shared mem buffer (read it using logread)")
/* NB: -Csize shouldn't have space (because size is optional) */ /* NB: -Csize shouldn't have space (because size is optional) */

View File

@ -42,6 +42,14 @@ config FEATURE_REMOTE_LOG
measure to prevent system logs from being tampered with measure to prevent system logs from being tampered with
by an intruder. by an intruder.
config FEATURE_SYSLOGD_DUP
bool "Support -D (drop dups) option"
default n
depends on SYSLOGD
help
Option -D instructs syslogd to drop consecutive messages
which are totally the same.
config FEATURE_IPC_SYSLOG config FEATURE_IPC_SYSLOG
bool "Circular Buffer support" bool "Circular Buffer support"
default n default n

View File

@ -101,7 +101,7 @@ struct globals {
char *hostname; char *hostname;
/* We recv into recvbuf... */ /* We recv into recvbuf... */
char recvbuf[MAX_READ]; char recvbuf[MAX_READ * (1 + ENABLE_FEATURE_SYSLOGD_DUP)];
/* ...then copy to parsebuf, escaping control chars */ /* ...then copy to parsebuf, escaping control chars */
/* (can grow x2 max) */ /* (can grow x2 max) */
char parsebuf[MAX_READ*2]; char parsebuf[MAX_READ*2];
@ -152,6 +152,7 @@ enum {
USE_FEATURE_REMOTE_LOG( OPTBIT_remote ,) // -R USE_FEATURE_REMOTE_LOG( OPTBIT_remote ,) // -R
USE_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L USE_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L
USE_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C USE_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C
USE_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D
OPT_mark = 1 << OPTBIT_mark , OPT_mark = 1 << OPTBIT_mark ,
OPT_nofork = 1 << OPTBIT_nofork , OPT_nofork = 1 << OPTBIT_nofork ,
@ -163,13 +164,15 @@ enum {
OPT_remotelog = USE_FEATURE_REMOTE_LOG( (1 << OPTBIT_remote )) + 0, OPT_remotelog = USE_FEATURE_REMOTE_LOG( (1 << OPTBIT_remote )) + 0,
OPT_locallog = USE_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0, OPT_locallog = USE_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0,
OPT_circularlog = USE_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, OPT_circularlog = USE_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0,
OPT_dup = USE_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0,
}; };
#define OPTION_STR "m:nO:l:S" \ #define OPTION_STR "m:nO:l:S" \
USE_FEATURE_ROTATE_LOGFILE("s:" ) \ USE_FEATURE_ROTATE_LOGFILE("s:" ) \
USE_FEATURE_ROTATE_LOGFILE("b:" ) \ USE_FEATURE_ROTATE_LOGFILE("b:" ) \
USE_FEATURE_REMOTE_LOG( "R:" ) \ USE_FEATURE_REMOTE_LOG( "R:" ) \
USE_FEATURE_REMOTE_LOG( "L" ) \ USE_FEATURE_REMOTE_LOG( "L" ) \
USE_FEATURE_IPC_SYSLOG( "C::") USE_FEATURE_IPC_SYSLOG( "C::") \
USE_FEATURE_SYSLOGD_DUP( "D" )
#define OPTION_DECL *opt_m, *opt_l \ #define OPTION_DECL *opt_m, *opt_l \
USE_FEATURE_ROTATE_LOGFILE(,*opt_s) \ USE_FEATURE_ROTATE_LOGFILE(,*opt_s) \
USE_FEATURE_ROTATE_LOGFILE(,*opt_b) \ USE_FEATURE_ROTATE_LOGFILE(,*opt_b) \
@ -538,6 +541,13 @@ static void do_syslogd(void) ATTRIBUTE_NORETURN;
static void do_syslogd(void) static void do_syslogd(void)
{ {
int sock_fd; int sock_fd;
#if ENABLE_FEATURE_SYSLOGD_DUP
int last_sz = -1;
char *last_buf;
char *recvbuf = G.recvbuf;
#else
#define recvbuf (G.recvbuf)
#endif
/* Set up signal handlers */ /* Set up signal handlers */
bb_signals(0 bb_signals(0
@ -561,8 +571,16 @@ static void do_syslogd(void)
for (;;) { for (;;) {
size_t sz; size_t sz;
#if ENABLE_FEATURE_SYSLOGD_DUP
last_buf = recvbuf;
if (recvbuf == G.recvbuf)
recvbuf = G.recvbuf + MAX_READ;
else
recvbuf = G.recvbuf;
#endif
read_again: read_again:
sz = safe_read(sock_fd, G.recvbuf, MAX_READ - 1); sz = safe_read(sock_fd, recvbuf, MAX_READ - 1);
if (sz < 0) if (sz < 0)
bb_perror_msg_and_die("read from /dev/log"); bb_perror_msg_and_die("read from /dev/log");
@ -577,11 +595,16 @@ static void do_syslogd(void)
* IOW: newline is passed verbatim! * IOW: newline is passed verbatim!
* I take it to mean that it's syslogd's job * I take it to mean that it's syslogd's job
* to make those look identical in the log files. */ * to make those look identical in the log files. */
if (G.recvbuf[sz-1] != '\0' && G.recvbuf[sz-1] != '\n') if (recvbuf[sz-1] != '\0' && recvbuf[sz-1] != '\n')
break; break;
sz--; sz--;
} }
/* TODO: maybe suppress duplicates? */ #if ENABLE_FEATURE_SYSLOGD_DUP
if ((option_mask32 & OPT_dup) && (sz == last_sz))
if (memcmp(last_buf, recvbuf, sz) == 0)
continue;
last_sz = sz;
#endif
#if ENABLE_FEATURE_REMOTE_LOG #if ENABLE_FEATURE_REMOTE_LOG
/* We are not modifying log messages in any way before send */ /* We are not modifying log messages in any way before send */
/* Remote site cannot trust _us_ anyway and need to do validation again */ /* Remote site cannot trust _us_ anyway and need to do validation again */
@ -593,18 +616,18 @@ static void do_syslogd(void)
} }
/* Stock syslogd sends it '\n'-terminated /* Stock syslogd sends it '\n'-terminated
* over network, mimic that */ * over network, mimic that */
G.recvbuf[sz] = '\n'; recvbuf[sz] = '\n';
/* send message to remote logger, ignore possible error */ /* send message to remote logger, ignore possible error */
/* TODO: on some errors, close and set G.remoteFD to -1 /* TODO: on some errors, close and set G.remoteFD to -1
* so that DNS resolution and connect is retried? */ * so that DNS resolution and connect is retried? */
sendto(G.remoteFD, G.recvbuf, sz+1, MSG_DONTWAIT, sendto(G.remoteFD, recvbuf, sz+1, MSG_DONTWAIT,
&G.remoteAddr->u.sa, G.remoteAddr->len); &G.remoteAddr->u.sa, G.remoteAddr->len);
no_luck: ; no_luck: ;
} }
#endif #endif
if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) { if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) {
G.recvbuf[sz] = '\0'; /* ensure it *is* NUL terminated */ recvbuf[sz] = '\0'; /* ensure it *is* NUL terminated */
split_escape_and_log(G.recvbuf, sz); split_escape_and_log(recvbuf, sz);
} }
} /* for (;;) */ } /* for (;;) */
} }