[syslog-ng]config questions

Andrew Fort afort@staff.webcentral.com.au
Mon, 27 Nov 2000 15:44:14 +1000


Okay, I think I see what you mean now, since I see this behaviour also.

We noticed this since we have a couple of "catch-all" rules in our confile
file, i.e., log {} entries with a source and destination, but no filter.
For instance,

log { source(s_sys); destination(d_tty12); };

to write everything logged at source s_sys to destination d_tty12, no
exceptions.

However, this changes the behaviour of the DEFAULT filter.

One of our other sysadmins and I have traced through the soruce, and he
(Matthew Melvin) has written a patch, which I'll attempt to explain.

When the config file syslog-ng.conf is read (from beginning to end), the
linked list "self" (ptr stuct syslog_config) is created, inside
"do_init_config()" (src/cfgfile.c)
When you create a linked list, the easiest way is to link the ptr to the
list as the 'next' variable in the current list entry, essentially pushing
list entries onto the stack.  So when the list is read forwards, you're
reading _backwards_ through the order in the config file (the list reads;
last entry through to first entry in the config file, in other words).

In center.c, function do_distribute_list evaluates the linked list to write
the log message being currently processed to all valid destinations.  The
logic in the code provided is to always treat the DEFAULT rule last - no
matter its position within the linked list, and treat all other rules first.
However, if you have a catch-all rule (no filter), the code which causes the
log message to be handled sets a "match" flag to true.

When we get to the end, and it's time to handle the default rule, it checks
to see if the log message being currently processed has already been matched
and if a DEFAULT rule is set:

        if (!match && def_connection) {

Since we've already matched everything, the DEFAULT rule does nothing.

Matthew's patch changes this logic so that all rules are evaluated in the
exact order they appear in the linked list (remember, this is the reverse
order they appear in the config file).  So, by applying this patch, then
placing your "catch-all" rule(s) first in the config file, then the DEFAULT
rule next, then any other rules, you should get the behaviour that you
expect.

Credits for this patch go to Matthew Melvin
(matthewm@staff.webcentral.com.au)

To apply the patch below:

Since we've modified center.c, make_class must run, so you'll need to have
scsh (scheme shell) installed, and you'll need to rebuild libol if you've
updated the scheme shell libraries (otherwise you'll get a segfault when
running the updated syslog-ng).  If you're having problems with the
scheme_shell bit, you may need to modify make_class to point at scheme
shell's path explicitly.

Apply the patch via changing to the directory you extracted the syslog-ng
source into (e.g. /usr/local/src/syslog-ng-1.4.9a/), save the patch file
below to a file, and run

patch -p0 < /path/to/patchfile.below

Then rebuild syslog-ng: ./configure, make, make install.

--snip--

--- src/center.c.old        Mon Nov 27 14:20:14 2000
+++ src/center.c    Mon Nov 27 15:08:38 2000
@@ -71,14 +71,21 @@
 static void do_distribute_log(struct log_handler *c, struct log_info *msg)
 {
        CAST(log_center, self, c);
-       struct log_connection *p, *def_connection = NULL;
+       struct log_connection *p;
        int match = 0;

        for (p = self->connections; p; p = p->next) {
                struct log_endpoint_info *s;

                if (p->flags & LOG_CONN_DEFAULT) {
-                       def_connection = p;
+                       struct log_endpoint_info *d;
+                       if (match) continue;
+                       for (d = p->nodes; d; d = d->next) {
+                               if (d->type == EP_DESTINATION) {
+                                       assert(d->ref);
+                                       HANDLE_LOG(d->ref,
log_info_use(msg));
+                               }
+                       }
                        continue;
                }
                for (s = p->nodes; s; s = s->next) {
@@ -107,16 +114,6 @@

        next_connection:
        }
-       if (!match && def_connection) {
-               struct log_endpoint_info *d;
-               for (d = def_connection->nodes; d; d = d->next) {
-                       if (d->type == EP_DESTINATION) {
-                               assert(d->ref);
-                               HANDLE_LOG(d->ref, log_info_use(msg));
-                       }
-               }
-       }
-       log_info_free(msg);
 }

 struct log_handler *make_log_center(struct log_connection *connections)

--snip--

An example of what I mean by our filter rules is:

log { source(s_sys); destination(d_tty12); };
log { source(s_sys); filter(DEFAULT); destination(d_mesg); };
log { source(s_sys); filter(f_PAM); destination(d_pam); };
log { source(s_sys); filter(f_auth); destination(d_auth); };
log { source(s_sys); filter(f_filter4); destination(d_mail); };

I hope this helps! Balazs, this may not be your preferred method of handling
this logic, but Matthew and I would appreciate hearing from you about it..

--
Andrew Fort
Webcentral

> >>>>> "AF" == Andrew Fort <afort@staff.webcentral.com.au> writes:
> 
> AF> Is any local logging working? If not, is your local source input
> AF> configured correctly for your operating system?
> 
> Apart from filter(DEFAULT), everything seems dandy: