Skip to content

Commit

Permalink
Add support for tag/ident based property filtering
Browse files Browse the repository at this point in the history
This patch adds support for tag/identity/program based filtering of
messages, similar to what FreeBSD and NetBSD syslogd have.

Issue #84

Signed-off-by: Joachim Wiberg <[email protected]>
  • Loading branch information
troglobit committed Dec 30, 2024
1 parent b2841e5 commit 42c87d7
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 11 deletions.
64 changes: 60 additions & 4 deletions man/syslog.conf.5
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,13 @@
.Sh DESCRIPTION
The
.Nm
file is the configuration file for the
.Xr syslogd 8
program. It consists of lines of rules for logging, with each line
containing at least two fields: the
file is the configuration file for
.Xr syslogd 8 ,
it consists of rules for logging and controlling daemon behavior.
Logging rules are blocks of lines separated by optional
.Em program-based
filter specifications. Each rule in such a block contains at least two
fields: the
.Em selector
field which specifies the types of messages and priorities to which the
line applies, and an
Expand All @@ -59,6 +62,9 @@ rule may be divided into several lines if the leading line ends with a
single backslash ('\\') character.
.Pp
.Bd -literal -offset indent
PROGRAM := !IDENT[,IDENT]
|= !+IDENT[,IDENT]
|= !-IDENT[,IDENT]
RULE := SELECTOR ACTION [;OPTION]
SELECTOR := [SELECTOR;]facility[,facility].[!=]severity
ACTION := /path/to/file
Expand All @@ -85,6 +91,44 @@ include /etc/syslog.d/*.conf
notify /path/to/script-on-rotate
.Ed
.Pp
Each block of rules is separated from the previous block by a
.Em program filter
specification. A block will only log messages corresponding to the most
recent
.Em program filter
specification given.
.Pp
A
.Em program
specification is a line starting with
.Ql #!prog
or
.Ql !prog
(the former is for compatibility with other syslogd implementations) and
the following rules are then associated with this specification only. The
.Ql #!+prog
or
.Ql !+prog
specification works just like the previous one,
and the
.Ql #!-prog
or
.Ql !-prog
specification will match any message
.Em excluding
prog. Multiple programs may be listed, separated by commas:
.Ql !prog1,prog2
matches messages from either program, while
.Ql !-prog1,prog2
matches all messages except those from
.Ql prog1
or
.Ql prog2 .
You can reset the program specification at any time using the
.Ql !*
syntax. The program specification is also reset for each included .conf
file.
.Pp
The
.Em selector
field specifies a pattern of facilities and priorities belonging to the
Expand Down Expand Up @@ -460,6 +504,18 @@ five files in total are kept, including the non-rotated file.
#
*.* /var/log/critical ;rotate=10M:5,RFC5424
.Ed
.Ss Program Based Filtering
Ensure multicast programs from log only to their own log files.
.Bd -literal -offset indent
# Match all log messages, except from certain programs
#
!-pimd,mrouted
*.* /var/log/syslog
!+pimd
*.* /var/log/pimd
!+mrouted
*.* /var/log/mrouted
.Ed
.Ss Critical
This stores all messages of priority
.Ql crit
Expand Down
4 changes: 2 additions & 2 deletions man/syslogd.8
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ starts up it reads its main configuration file
.Pa /etc/syslog.conf ,
or an alternate file given with the
.Fl f Ar file
option. For details on how to configure syslog priority
(facility.severity) filtering, see
option. For details on how to set up syslog message filtering, using
priority (facility.severity) or other means, see
.Xr syslog.conf 5 .
.Sh OPTIONS
By default,
Expand Down
92 changes: 87 additions & 5 deletions src/syslogd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1695,6 +1695,51 @@ static void check_timestamp(struct buf_msg *buffer)
buffer->timestamp = now;
}

/*
* Match a program or host name against a specification.
* Return a non-0 value if the message must be ignored
* based on the specification.
*/
static int
skip_message(const char *name, const char *spec, int checkcase)
{
const char *s;
char prev, next;
int exclude = 0;
/* Behaviour on explicit match */

if (spec == NULL || *spec == '\0')
return 0;

switch (*spec) {
case '-':
exclude = 1;
/*FALLTHROUGH*/
case '+':
spec++;
break;
default:
break;
}

if (checkcase)
s = strstr(spec, name);
else
s = strcasestr(spec, name);

if (s != NULL) {
prev = (s == spec ? ',' : *(s - 1));
next = *(s + strlen(name));

/* Explicit match: skip iff the spec is exclusive. */
if (prev == ',' && (next == '\0' || next == ','))
return exclude;
}

/* No explicit match: skip message iff spec is inclusive. */
return !exclude;
}

/*
* Logs a message to the appropriate log files, users, etc. based on the
* priority. Log messages are always formatted according to RFC 3164,
Expand Down Expand Up @@ -1774,6 +1819,9 @@ static void logmsg(struct buf_msg *buffer)
((f->f_pmask[fac] & (1 << prilev)) == 0))
continue;

if (skip_message(buffer->app_name ?: "", f->f_program, 1))
continue;

/* skip message to console if it has already been printed */
if (f->f_type == F_CONSOLE && (buffer->flags & IGN_CONS))
continue;
Expand Down Expand Up @@ -2644,6 +2692,8 @@ static void close_open_log_files(void)
break;
}

if (f->f_program)
free(f->f_program);
free(f);
}
}
Expand Down Expand Up @@ -3055,6 +3105,9 @@ static void init(void)
break;
}

if (f->f_program)
printf(" (%s)", f->f_program);

if (f->f_flags & RFC5424)
printf("\t;RFC5424");
else if (f->f_flags & RFC3164)
Expand Down Expand Up @@ -3169,7 +3222,7 @@ static void cfopts(char *ptr, struct filed *f)
/*
* Crack a configuration file line
*/
static struct filed *cfline(char *line)
static struct filed *cfline(char *line, const char *prog)
{
char buf[LINE_MAX];
char *p, *q, *bp;
Expand Down Expand Up @@ -3417,6 +3470,9 @@ static struct filed *cfline(char *line)
else
logit("BSD format enabled\n");

if (prog && *prog != '*')
f->f_program = strdup(prog);

return f;
}

Expand Down Expand Up @@ -3463,8 +3519,9 @@ const struct cfkey *cfkey_match(char *cline)
static int cfparse(FILE *fp, struct files *newf)
{
const struct cfkey *cfk;
struct filed *f;
char prog[64] = "*";
char cbuf[BUFSIZ];
struct filed *f;
char *cline;
char *p;

Expand All @@ -3478,12 +3535,37 @@ static int cfparse(FILE *fp, struct files *newf)
while (fgets(cline, sizeof(cbuf) - (cline - cbuf), fp) != NULL) {
/*
* check for end-of-section, comments, strip off trailing
* spaces and newline character.
* spaces and newline character. #!prog is treated specially:
* following lines apply only to that program.
*/
for (p = cline; isspace(*p); ++p)
;
if (*p == '\0' || *p == '#')
if (*p == '\0')
continue;
if (*p == '#') {
p++;
if (*p == '\0' || !strchr("!", *p))
continue;
}

if (*p == '!') {
size_t i;

p++;
while (isspace(*p))
p++;
if (*p == '\0' || *p == '*') {
(void)strlcpy(prog, "*", sizeof(prog));
continue;
}
for (i = 0; i < sizeof(prog) - 1; i++) {
if (!isprint(p[i]) || isspace(p[i]))
break;
prog[i] = p[i];
}
prog[i] = '\0';
continue;
}

memmove(cline, p, strlen(p) + 1);
for (p = strchr(cline, '\0'); isspace(*--p);)
Expand Down Expand Up @@ -3537,7 +3619,7 @@ static int cfparse(FILE *fp, struct files *newf)
if (cfk)
continue;

f = cfline(cline);
f = cfline(cline, prog);
if (!f)
continue;

Expand Down
1 change: 1 addition & 0 deletions src/syslogd.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ struct filed {
short f_file; /* file descriptor */
time_t f_time; /* time this was last written */
char *f_host; /* host from which to recd. */
char *f_program; /* program(s) this applies to */
u_char f_pmask[LOG_NFACILITIES + 1]; /* priority mask */
union {
char f_uname[MAXUNAMES][UNAMESZ + 1];
Expand Down

0 comments on commit 42c87d7

Please sign in to comment.