Hi DJ, Recently I used audisp-remote function and I found in audisp-remote.conf there is "remote_ending_action" parameter. From the manpage, it's the same with "disk_error_action". But from the codes, its meaning seems to be "the action taken when the remote audit ends". So I set it as "syslog" and then stopped the remote audit, then the local audisp-remote stopped but no message about "remote ending". I think if "network_retry_time" is reached, whatever the "fail-safe"(e.g. remote_ending_action) action is set in audisp-remote.conf. The audisp-remote will exit. Is that true?
Regards Chu Li > -----Original Message----- > From: [email protected] [mailto:[email protected]] > On > Behalf Of DJ Delorie > Sent: Friday, August 29, 2008 2:48 AM > To: [email protected] > Subject: [PATCH] Add error-handling actions to audisp-remote > > > Third in a series. > (http://www.redhat.com/archives/linux-audit/2008-August/msg00118.html) > > The goal of this patch is to robustify the error handling in the > client end of the remote protocol. The following changes are made > by this patch: > > * Failure to send a record to the aggregator results in a series of > retry attempts, tunable by the administrator. > > * Overall network failure (after retries) and server-indicated error > conditions now have admin-specified actions associated with them. > > * Miscellaneous additional error handling for reads and writes. > > Comments? > > DJ > > > diff -x .svn -U 3 -r pristine/audisp/plugins/remote/audisp-remote.c > trunk/audisp/plugins/remote/audisp-remote.c > --- pristine/audisp/plugins/remote/audisp-remote.c 2008-08-27 > 18:55:41.000000000 -0400 > +++ trunk/audisp/plugins/remote/audisp-remote.c 2008-08-28 > 14:15:42.000000000 -0400 > @@ -40,15 +40,27 @@ > #define CONFIG_FILE "/etc/audisp/audisp-remote.conf" > #define BUF_SIZE 32 > > +/* Error types */ > +#define ET_SUCCESS 0 > +#define ET_PERMANENT -1 > +#define ET_TEMPORARY -2 > + > /* Global Data */ > static volatile int stop = 0; > static volatile int hup = 0; > +static volatile int suspend = 0; > static remote_conf_t config; > static int sock=-1; > > +static const char *SINGLE = "1"; > +static const char *HALT = "0"; > + > +static int transport_ok = 0; > + > /* Local function declarations */ > static int relay_event(const char *s, size_t len); > static int init_transport(void); > +static int stop_transport(void); > > > /* > @@ -69,10 +81,19 @@ > > static void reload_config(void) > { > + stop_transport (); > hup = 0; > } > > /* > + * SIGSUR2 handler: resume logging > + */ > +static void user2_handler( int sig ) > +{ > + suspend = 0; > +} > + > +/* > * Handlers for various events coming back from the remote server. > * Return -1 if the remote dispatcher should exit. > */ > @@ -81,45 +102,135 @@ > static int sync_error_handler (const char *why) > { > /* "why" has human-readable details on why we've lost (or will > - be losing) sync. */ > - syslog (LOG_ERR, "lost/losing sync, %s", why); > - return -1; > + be losing) sync. Sync errors are transient - if a retry > + doesn't fix it, we eventually call network_failure_handler > + which has all the user-tweakable actions. */ > + if (config.network_failure_action == FA_SYSLOG) > + syslog (LOG_ERR, "lost/losing sync, %s", why); > + return 0; > +} > + > +static void change_runlevel(const char *level) > +{ > + char *argv[3]; > + int pid; > + static const char *init_pgm = "/sbin/init"; > + > + pid = fork(); > + if (pid < 0) { > + syslog(LOG_ALERT, > + "Audit daemon failed to fork switching runlevels"); > + return; > + } > + if (pid) /* Parent */ > + return; > + /* Child */ > + argv[0] = (char *)init_pgm; > + argv[1] = (char *)level; > + argv[2] = NULL; > + execve(init_pgm, argv, NULL); > + syslog(LOG_ALERT, "Audit daemon failed to exec %s", init_pgm); > + exit(1); > +} > + > +static void safe_exec(const char *exe, const char *message) > +{ > + char *argv[3]; > + int pid; > + > + pid = fork(); > + if (pid < 0) { > + syslog(LOG_ALERT, > + "Audit daemon failed to fork doing safe_exec"); > + return; > + } > + if (pid) /* Parent */ > + return; > + /* Child */ > + argv[0] = (char *)exe; > + argv[1] = (char *)message; > + argv[2] = NULL; > + execve(exe, argv, NULL); > + syslog(LOG_ALERT, "Audit daemon failed to exec %s", exe); > + exit(1); > +} > + > +static int do_action (const char *desc, const char *message, > + int log_level, > + failure_action_t action, const char *exe) > +{ > + switch (action) > + { > + case FA_IGNORE: > + return 0; > + case FA_SYSLOG: > + syslog (log_level, "%s, %s", desc, message); > + return 0; > + case FA_EXEC: > + safe_exec (exe, message); > + return 0; > + case FA_SUSPEND: > + suspend = 1; > + return 0; > + case FA_SINGLE: > + change_runlevel(SINGLE); > + return 1; > + case FA_HALT: > + change_runlevel(HALT); > + return 1; > + case FA_STOP: > + syslog (log_level, "stopping due to %s, %s", desc, message); > + stop = 1; > + return 1; > + } > +} > + > +static int network_failure_handler (const char *message) > +{ > + return do_action ("network failure", message, > + LOG_WARNING, > + config.network_failure_action, > config.network_failure_exe); > } > > static int remote_disk_low_handler (const char *message) > { > - syslog (LOG_WARNING, "remote disk low, %s", message); > - return 0; > + return do_action ("remote disk low", message, > + LOG_WARNING, > + config.disk_low_action, config.disk_low_exe); > } > > static int remote_disk_full_handler (const char *message) > { > - syslog (LOG_ERR, "remote disk full, %s", message); > - return -1; > + return do_action ("remote disk full", message, > + LOG_ERR, > + config.disk_full_action, config.disk_full_exe); > } > > static int remote_disk_error_handler (const char *message) > { > - syslog (LOG_ERR, "remote disk error, %s", message); > - return -1; > + return do_action ("remote disk error", message, > + LOG_ERR, > + config.disk_error_action, config.disk_error_exe); > } > > static int remote_server_ending_handler (const char *message) > { > - syslog (LOG_INFO, "remote server ending, %s", message); > - return -1; > + return do_action ("remote server ending", message, > + LOG_INFO, > + config.remote_ending_action, > config.remote_ending_exe); > } > > static int generic_remote_error_handler (const char *message) > { > - stop = 1; > - syslog(LOG_INFO, "audisp-remote: remote error: %s", message); > - return -1; > + return do_action ("unrecognized remote error", message, > + LOG_ERR, > + config.generic_error_action, > config.generic_error_exe); > } > static int generic_remote_warning_handler (const char *message) > { > - syslog(LOG_INFO, "audisp-remote: remote warning: %s", message); > - return 0; > + return do_action ("unrecognized remote warning", message, > + LOG_WARNING, > + config.generic_warning_action, > config.generic_warning_exe); > } > > > @@ -137,11 +248,16 @@ > sigaction(SIGTERM, &sa, NULL); > sa.sa_handler = hup_handler; > sigaction(SIGHUP, &sa, NULL); > + sa.sa_handler = user2_handler; > + sigaction(SIGUSR2, &sa, NULL); > if (load_config(&config, CONFIG_FILE)) > return 6; > > + /* We fail here if the transport can't be initialized because > + * of some permenent (i.e. operator) problem, such as > + * misspelled host name. */ > rc = init_transport(); > - if (rc < 0) > + if (rc == ET_PERMANENT) > return 1; > > syslog(LOG_INFO, "audisp-remote is ready for events"); > @@ -155,10 +271,12 @@ > /* Now the event loop */ > while (fgets_unlocked(tmp, MAX_AUDIT_MESSAGE_LENGTH, stdin) && > hup==0 && stop==0) { > - rc = relay_event(tmp, strnlen(tmp, > - MAX_AUDIT_MESSAGE_LENGTH)); > - if (rc < 0) { > - break; > + if (!suspend) { > + rc = relay_event(tmp, strnlen(tmp, > + > MAX_AUDIT_MESSAGE_LENGTH)); > + if (rc < 0) { > + break; > + } > } > } > if (feof(stdin)) > @@ -186,14 +304,14 @@ > if (rc) { > syslog(LOG_ERR, "Error looking up remote host: %s - exiting", > gai_strerror(rc)); > - return -1; > + return ET_PERMANENT; > } > sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); > if (sock < 0) { > syslog(LOG_ERR, "Error creating socket: %s - exiting", > strerror(errno)); > freeaddrinfo(ai); > - return -1; > + return ET_TEMPORARY; > } > > setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (int)); > @@ -210,7 +328,7 @@ > syslog(LOG_ERR, "Cannot bind local socket to port %d - > exiting", > config.local_port); > close(sock); > - return -1; > + return ET_TEMPORARY; > } > > } > @@ -218,14 +336,22 @@ > syslog(LOG_ERR, "Error connecting to %s: %s - exiting", > config.remote_server, strerror(errno)); > freeaddrinfo(ai); > - return -1; > + return ET_TEMPORARY; > } > > setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof (int)); > - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof (int)); > + > + /* The idea here is to minimize the time between the message > + and the ACK, assuming that individual messages are > + infrequent enough that we can ignore the inefficiency of > + sending the header and message in separate packets. */ > + if (config.format == F_MANAGED) > + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof > (int)); > + > + transport_ok = 1; > > freeaddrinfo(ai); > - return 0; > + return ET_SUCCESS; > } > > static int init_transport(void) > @@ -238,6 +364,28 @@ > rc = init_sock(); > break; > default: > + rc = ET_PERMANENT; > + break; > + } > + return rc; > +} > + > +static int stop_sock(void) > +{ > + close (sock); > + transport_ok = 0; > +} > + > +static int stop_transport(void) > +{ > + int rc; > + > + switch (config.transport) > + { > + case T_TCP: > + rc = stop_sock(); > + break; > + default: > rc = -1; > break; > } > @@ -246,10 +394,19 @@ > > static int ar_write (int sock, const void *buf, int len) > { > - int rc; > - do { > - rc = write(sock, buf, len); > - } while (rc < 0 && errno == EINTR); > + int rc = 0, r; > + while (len > 0) { > + do { > + r = write(sock, buf, len); > + } while (r < 0 && errno == EINTR); > + if (r < 0) > + return r; > + if (r == 0) > + break; > + rc += r; > + buf = (void *)((char *)buf + r); > + len -= r; > + } > return rc; > } > > @@ -275,6 +432,10 @@ > { > int rc; > > + if (!transport_ok) > + if (init_transport ()) > + return -1; > + > rc = ar_write(sock, s, len); > if (rc <= 0) { > stop = 1; > @@ -294,53 +455,103 @@ > int hver, mver; > uint32_t type, rlen, seq; > char msg[MAX_AUDIT_MESSAGE_LENGTH+1]; > + int n_tries_this_message = 0; > + time_t now, then; > > sequence_id ++; > + > + time (&then); > +try_again: > + time (&now); > + > + /* We want the first retry to be quick, in case the network > + failed for some fail-once reason. In this case, it goes > + "failure - reconnect - send". Only if this quick retry > + fails do we start pausing between retries to prevent > + swamping the local computer and the network. */ > + if (n_tries_this_message > 1) > + sleep (config.network_retry_time); > + > + if (n_tries_this_message > config.max_tries_per_record) { > + network_failure_handler ("max retries exhausted"); > + return -1; > + } > + if ((now - then) > config.max_time_per_record) { > + network_failure_handler ("max retry time exhausted"); > + return -1; > + } > + > + n_tries_this_message ++; > + > + if (!transport_ok) { > + if (init_transport ()) > + goto try_again; > + } > + > AUDIT_RMW_PACK_HEADER (header, 0, 0, len, sequence_id); > rc = ar_write(sock, header, AUDIT_RMW_HEADER_SIZE); > if (rc <= 0) { > - stop = 1; > - syslog(LOG_ERR, "connection to %s closed unexpectedly - > exiting", > - config.remote_server); > - return -1; > + if (config.network_failure_action == FA_SYSLOG) > + syslog(LOG_ERR, "connection to %s closed unexpectedly", > + config.remote_server); > + stop_transport(); > + goto try_again; > } > > rc = ar_write(sock, s, len); > if (rc <= 0) { > - stop = 1; > - syslog(LOG_ERR, "connection to %s closed unexpectedly - > exiting", > - config.remote_server); > - return -1; > + if (config.network_failure_action == FA_SYSLOG) > + syslog(LOG_ERR, "connection to %s closed unexpectedly", > + config.remote_server); > + stop_transport(); > + goto try_again; > } > > rc = ar_read (sock, header, AUDIT_RMW_HEADER_SIZE); > if (rc < 16) { > - stop = 1; > - syslog(LOG_ERR, "connection to %s closed unexpectedly - > exiting", > - config.remote_server); > - return -1; > + if (config.network_failure_action == FA_SYSLOG) > + syslog(LOG_ERR, "connection to %s closed unexpectedly", > + config.remote_server); > + stop_transport(); > + goto try_again; > } > > > - if (! AUDIT_RMW_IS_MAGIC (header, AUDIT_RMW_HEADER_SIZE)) > + if (! AUDIT_RMW_IS_MAGIC (header, AUDIT_RMW_HEADER_SIZE)) { > /* FIXME: the right thing to do here is close the socket and > start a new > one. */ > - return sync_error_handler ("bad magic number"); > + if (sync_error_handler ("bad magic number")) > + return -1; > + stop_transport(); > + goto try_again; > + } > > AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, rlen, seq); > > - if (rlen > MAX_AUDIT_MESSAGE_LENGTH) > - return sync_error_handler ("message too long"); > + if (rlen > MAX_AUDIT_MESSAGE_LENGTH) { > + if (sync_error_handler ("message too long")) > + return -1; > + stop_transport(); > + goto try_again; > + } > > if (rlen > 0 > - && ar_read (sock, msg, rlen) < rlen) > - return sync_error_handler ("ran out of data reading reply"); > + && ar_read (sock, msg, rlen) < rlen) { > + if (sync_error_handler ("ran out of data reading reply")) > + return -1; > + stop_transport(); > + goto try_again; > + } > msg[rlen] = 0; > > - if (seq != sequence_id) > + if (seq != sequence_id) { > /* FIXME: should we read another header and > see if it matches? If so, we need to deal > with timeouts. */ > - return sync_error_handler ("mismatched response"); > + if (sync_error_handler ("mismatched response")) > + return -1; > + stop_transport(); > + goto try_again; > + } > > /* Specific errors we know how to deal with. */ > > diff -x .svn -U 3 -r pristine/audisp/plugins/remote/audisp-remote.conf > trunk/audisp/plugins/remote/audisp-remote.conf > --- pristine/audisp/plugins/remote/audisp-remote.conf 2008-08-15 > 15:52:05.000000000 -0400 > +++ trunk/audisp/plugins/remote/audisp-remote.conf 2008-08-28 > 14:34:48.000000000 -0400 > @@ -9,5 +9,15 @@ > transport = tcp > mode = immediate > queue_depth = 20 > -fail_action = SYSLOG > format = managed > +network_retry_time = 1 > +max_tries_per_record = 3 > +max_time_per_record = 5 > + > +network_failure_action = stop > +disk_low_action = ignore > +disk_full_action = ignore > +disk_error_action = syslog > +remote_ending_action = suspend > +generic_error_action = syslog > +generic_warning_action = syslog > diff -x .svn -U 3 -r pristine/audisp/plugins/remote/audisp-remote.conf.5 > trunk/audisp/plugins/remote/audisp-remote.conf.5 > --- pristine/audisp/plugins/remote/audisp-remote.conf.5 2008-08-15 > 15:52:05.000000000 -0400 > +++ trunk/audisp/plugins/remote/audisp-remote.conf.5 2008-08-28 > 11:45:55.000000000 -0400 > @@ -45,24 +45,52 @@ > .I mode > option. The default depth is 20. > .TP > -.I fail_action > +.I network_failure_action > This parameter tells the system what action to take whenever there is an > error > -detected when sending audit events to the remote system, or if the remote > system > reports an error. Valid values are > -.IR ignore ", " syslog ", " exec ", " suspend ", " single ", and " halt . > +detected when sending audit events to the remote system. Valid values are > +.IR ignore ", " syslog ", " exec ", " suspend ", " single ", " halt ", and " > stop . > If set to > .IR ignore , > the audit daemon does nothing. > .I Syslog > -means that it will issue a warning to syslog. > +means that it will issue a warning to syslog. This is the default. > .I exec > /path-to-script will execute the script. You cannot pass parameters to the > script. > .I Suspend > will cause the remote logging app to stop sending records to the remote > system. > The logging app will still be alive. The > .I single > -option will cause the remote logging app to put the computer system in > single > user > mode. > +option will cause the remote logging app to put the computer system in > single > user > mode. The > +.I stop > +option will cause the remote logging app to exit, but leave other plugins > running. > The > .I halt > option will cause the remote logging app to shutdown the computer system. > .TP > +.I disk_low_action > +Likewise, this parameter tells the system what action to take if the > +remote end signals a disk low error. The default is to ignore it. > +.TP > +.I disk_full_action > +Likewise, this parameter tells the system what action to take if the > +remote end signals a disk full error. The default is to ignore it. > +.TP > +.I disk_error_action > +Likewise, this parameter tells the system what action to take if the > +remote end signals a disk error. The default is to log it to syslog. > +.TP > +.I remote_ending_action > +Likewise, this parameter tells the system what action to take if the > +remote end signals a disk error. The default is to suspend logging. > +.TP > +.I generic_error_action > +Likewise, this parameter tells the system what action to take if the > +remote end signals an error we don't recognize. The default is to log > +it to syslog. > +.TP > +.I generic_warning_action > +Likewise, this parameter tells the system what action to take if the > +remote end signals a warning we don't recognize. The default is to > +log it to syslog. > +.TP > .I format > This parameter tells the remote logging app what data format will be > used for the messages sent over the network. The default is > @@ -73,11 +101,43 @@ > .I ascii > is given instead, each message is a simple ASCII text line with no > overhead at all. > +.TP > +.I network_retry_time > +The time, in seconds, between retries when a network error is > +detected. Note that this pause applies starting after the second > +attempt, so as to avoid unneeded delays if a reconnect is sufficient > +to fix the problem. The default is 1 second. > +.TP > +.I max_tries_per_record > +The maximum number of times an attempt is made to deliver each > +message. The minimum value is one, as even a completely successful > +delivery requires at least one try. If too many attempts are made, > +the network_failure_action action is performed. The default is 3. > +.TP > +.I max_time_per_record > +The maximum amount of time, in seconds, spent attempting to deliver > +each message. Note that both this and > +.I max_tries_per_record > +should be set, as each try may take a long time to time out. The > +default value is 5 seconds. If too much time is used on a message, > +the network_failure_action action is performed. > > .SH "NOTES" > Specifying a local port may make it difficult to restart the audit > subsystem due to the previous connection being in a TIME_WAIT state, > if you're reconnecting to and from the same hosts and ports as before. > + > +The network failure logic works as follows: The first attempt to > +deliver normally "just works". If it doesn't, a second attempt is > +immediately made, perhaps after reconnecting to the server. If > +the second attempt also fails, > +.I audispd-remote > +pauses for the configured time and tries again. It continues to pause > +and retry until either too many attempts have been made or the allowed > +time expires. Note that these times govern the maximum amount of time > +the remote server is allowed in order to reboot, if you want to > +maintain logging across a reboot. > + > .SH "SEE ALSO" > .BR audispd (8), > .BR audisp-remote(8). > diff -x .svn -U 3 -r pristine/audisp/plugins/remote/remote-config.c > trunk/audisp/plugins/remote/remote-config.c > --- pristine/audisp/plugins/remote/remote-config.c 2008-08-15 > 15:52:05.000000000 -0400 > +++ trunk/audisp/plugins/remote/remote-config.c 2008-08-28 > 11:45:38.000000000 -0400 > @@ -74,6 +74,22 @@ > remote_conf_t *config); > static int format_parser(struct nv_pair *nv, int line, > remote_conf_t *config); > +static int network_retry_time_parser(struct nv_pair *nv, int line, > + remote_conf_t *config); > +static int max_tries_per_record_parser(struct nv_pair *nv, int line, > + remote_conf_t *config); > +static int max_time_per_record_parser(struct nv_pair *nv, int line, > + remote_conf_t *config); > +#define AP(x) static int x##_action_parser(struct nv_pair *nv, int line, \ > + remote_conf_t *config); > +AP(network_failure) > +AP(disk_low) > +AP(disk_full) > +AP(disk_error) > +AP(remote_ending) > +AP(generic_error) > +AP(generic_warning) > +#undef AP > static int sanity_check(remote_conf_t *config, const char *file); > > static const struct kw_pair keywords[] = > @@ -84,8 +100,17 @@ > {"transport", transport_parser, 0 }, > {"mode", mode_parser, 0 }, > {"queue_depth", depth_parser, 0 }, > - {"fail_action", fail_action_parser, 0 }, > {"format", format_parser, 0 }, > + {"network_retry_time", network_retry_time_parser, 0 }, > + {"max_tries_per_record", max_tries_per_record_parser, 0 }, > + {"max_time_per_record", max_time_per_record_parser, 0 }, > + {"network_failure_action", network_failure_action_parser, 0 }, > + {"disk_low_action", disk_low_action_parser, 0 }, > + {"disk_full_action", disk_full_action_parser, 0 }, > + {"disk_error_action", disk_error_action_parser, 0 }, > + {"remote_ending_action", remote_ending_action_parser, 0 }, > + {"generic_error_action", generic_error_action_parser, 0 }, > + {"generic_warning_action", generic_warning_action_parser, 0 }, > { NULL, NULL } > }; > > @@ -104,12 +129,13 @@ > > static const struct nv_list fail_action_words[] = > { > - {"ignore", F_IGNORE }, > - {"syslog", F_SYSLOG }, > - {"exec", F_EXEC }, > - {"suspend", F_SUSPEND }, > - {"single", F_SINGLE }, > - {"halt", F_HALT }, > + {"ignore", FA_IGNORE }, > + {"syslog", FA_SYSLOG }, > + {"exec", FA_EXEC }, > + {"suspend", FA_SUSPEND }, > + {"single", FA_SINGLE }, > + {"halt", FA_HALT }, > + {"stop", FA_STOP }, > { NULL, 0 } > }; > > @@ -131,9 +157,21 @@ > config->port = T_TCP; > config->mode = M_IMMEDIATE; > config->queue_depth = 20; > - config->fail_action = F_SYSLOG; > - config->fail_exe = NULL; > config->format = F_MANAGED; > + > + config->network_retry_time = 1; > + config->max_tries_per_record = 3; > + config->max_time_per_record = 5; > + > +#define IA(x,f) config->x##_action = f; config->x##_exe = NULL > + IA(network_failure, FA_STOP); > + IA(disk_low, FA_IGNORE); > + IA(disk_full, FA_IGNORE); > + IA(disk_error, FA_SYSLOG); > + IA(remote_ending, FA_SUSPEND); > + IA(generic_error, FA_SYSLOG); > + IA(generic_warning, FA_SYSLOG); > +#undef IA > } > > int load_config(remote_conf_t *config, const char *file) > @@ -372,10 +410,10 @@ > return 0; > } > > -static int port_parser(struct nv_pair *nv, int line, remote_conf_t *config) > +static int parse_uint (struct nv_pair *nv, int line, unsigned int *valp, > unsigned > int min, unsigned int max) > { > const char *ptr = nv->value; > - int i; > + unsigned int i; > > /* check that all chars are numbers */ > for (i=0; ptr[i]; i++) { > @@ -397,56 +435,32 @@ > return 1; > } > /* Check its range */ > - if (i > INT_MAX) { > + if (min != 0 && i < (int)min) { > syslog(LOG_ERR, > - "Error - converted number (%s) is too large - line %d", > + "Error - converted number (%s) is too small - line %d", > nv->value, line); > return 1; > } > - config->port = (unsigned int)i; > - return 0; > -} > - > -static int local_port_parser(struct nv_pair *nv, int line, remote_conf_t > *config) > -{ > - const char *ptr = nv->value; > - int i; > - > - if (strcasecmp (ptr, "any") == 0) { > - config->local_port = 0; > - return 0; > - } > - > - /* check that all chars are numbers */ > - for (i=0; ptr[i]; i++) { > - if (!isdigit(ptr[i])) { > - syslog(LOG_ERR, > - "Value %s should only be numbers - line %d", > - nv->value, line); > - return 1; > - } > - } > - > - /* convert to unsigned int */ > - errno = 0; > - i = strtoul(nv->value, NULL, 10); > - if (errno) { > - syslog(LOG_ERR, > - "Error converting string to a number (%s) - line %d", > - strerror(errno), line); > - return 1; > - } > - /* Check its range */ > - if (i > INT_MAX) { > + if (max != 0 && i > max) { > syslog(LOG_ERR, > "Error - converted number (%s) is too large - line %d", > nv->value, line); > return 1; > } > - config->local_port = (unsigned int)i; > + *valp = (unsigned int)i; > return 0; > } > > +static int port_parser(struct nv_pair *nv, int line, remote_conf_t *config) > +{ > + return parse_uint (nv, line, &(config->port), 0, INT_MAX); > +} > + > +static int local_port_parser(struct nv_pair *nv, int line, remote_conf_t > *config) > +{ > + return parse_uint (nv, line, &(config->local_port), 0, INT_MAX); > +} > + > static int transport_parser(struct nv_pair *nv, int line, remote_conf_t > *config) > { > int i; > @@ -476,54 +490,24 @@ > static int depth_parser(struct nv_pair *nv, int line, > remote_conf_t *config) > { > - const char *ptr = nv->value; > - int i; > - > - /* check that all chars are numbers */ > - for (i=0; ptr[i]; i++) { > - if (!isdigit(ptr[i])) { > - syslog(LOG_ERR, > - "Value %s should only be numbers - line %d", > - nv->value, line); > - return 1; > - } > - } > - > - /* convert to unsigned int */ > - errno = 0; > - i = strtoul(nv->value, NULL, 10); > - if (errno) { > - syslog(LOG_ERR, > - "Error converting string to a number (%s) - line %d", > - strerror(errno), line); > - return 1; > - } > - /* Check its range */ > - if (i > INT_MAX) { > - syslog(LOG_ERR, > - "Error - converted number (%s) is too large - line %d", > - nv->value, line); > - return 1; > - } > - config->queue_depth = (unsigned int)i; > - return 0; > + return parse_uint (nv, line, &(config->queue_depth), 1, INT_MAX); > } > > -static int fail_action_parser(struct nv_pair *nv, int line, > - remote_conf_t *config) > +static int action_parser(struct nv_pair *nv, int line, > + failure_action_t *actp, const char **exep) > { > int i; > for (i=0; fail_action_words[i].name != NULL; i++) { > if (strcasecmp(nv->value, fail_action_words[i].name) == 0) { > - config->fail_action = fail_action_words[i].option; > + *actp = fail_action_words[i].option; > return 0; > - } else if (i == F_EXEC) { > + } else if (i == FA_EXEC) { > if (strncasecmp(fail_action_words[i].name, > nv->value, 4) == 0){ > if (check_exe_name(nv->option)) > return 1; > - config->fail_exe = strdup(nv->option); > - config->fail_action = F_EXEC; > + *exep = strdup(nv->option); > + *actp = FA_EXEC; > return 0; > } > } > @@ -532,6 +516,22 @@ > return 1; > } > > +#define AP(x) \ > +static int x##_action_parser(struct nv_pair *nv, int line, \ > + remote_conf_t *config) \ > +{ \ > + return action_parser (nv, line, &(config->x##_action), > &(config->x##_exe)); > \ > +} \ > + > +AP(network_failure) > +AP(disk_low) > +AP(disk_full) > +AP(disk_error) > +AP(remote_ending) > +AP(generic_error) > +AP(generic_warning) > +#undef AP > + > static int format_parser(struct nv_pair *nv, int line, > remote_conf_t *config) > { > @@ -546,6 +546,24 @@ > return 1; > } > > +static int network_retry_time_parser(struct nv_pair *nv, int line, > + remote_conf_t *config) > +{ > + return parse_uint (nv, line, &(config->network_retry_time), 1, INT_MAX); > +} > + > +static int max_tries_per_record_parser(struct nv_pair *nv, int line, > + remote_conf_t *config) > +{ > + return parse_uint (nv, line, &(config->max_tries_per_record), 1, > INT_MAX); > +} > + > +static int max_time_per_record_parser(struct nv_pair *nv, int line, > + remote_conf_t *config) > +{ > + return parse_uint (nv, line, &(config->max_time_per_record), 1, > INT_MAX); > +} > + > /* > * This function is where we do the integrated check of the audispd config > * options. At this point, all fields have been read. Returns 0 if no > diff -x .svn -U 3 -r pristine/audisp/plugins/remote/remote-config.h > trunk/audisp/plugins/remote/remote-config.h > --- pristine/audisp/plugins/remote/remote-config.h 2008-08-15 > 15:52:05.000000000 -0400 > +++ trunk/audisp/plugins/remote/remote-config.h 2008-08-28 > 14:18:18.000000000 -0400 > @@ -26,8 +26,9 @@ > > typedef enum { M_IMMEDIATE, M_STORE_AND_FORWARD } mode_t; > typedef enum { T_TCP, T_SSL, T_GSSAPI, T_LABELED } transport_t; > -typedef enum { F_IGNORE, F_SYSLOG, F_EXEC, F_SUSPEND, F_SINGLE, F_HALT } > fail_t; > typedef enum { F_ASCII, F_MANAGED } format_t; > +typedef enum { FA_IGNORE, FA_SYSLOG, FA_EXEC, FA_SUSPEND, > + FA_SINGLE, FA_HALT, FA_STOP } failure_action_t; > > typedef struct remote_conf > { > @@ -37,9 +38,25 @@ > transport_t transport; > mode_t mode; > unsigned int queue_depth; > - fail_t fail_action; > - const char *fail_exe; > format_t format; > + unsigned int network_retry_time; > + unsigned int max_tries_per_record; > + unsigned int max_time_per_record; > + > + failure_action_t network_failure_action; > + const char *network_failure_exe; > + failure_action_t disk_low_action; > + const char *disk_low_exe; > + failure_action_t disk_full_action; > + const char *disk_full_exe; > + failure_action_t disk_error_action; > + const char *disk_error_exe; > + failure_action_t remote_ending_action; > + const char *remote_ending_exe; > + failure_action_t generic_error_action; > + const char *generic_error_exe; > + failure_action_t generic_warning_action; > + const char *generic_warning_exe; > } remote_conf_t; > > void clear_config(remote_conf_t *config); > diff -x .svn -U 3 -r pristine/src/auditd-event.c trunk/src/auditd-event.c > --- pristine/src/auditd-event.c 2008-08-15 15:52:05.000000000 -0400 > +++ trunk/src/auditd-event.c 2008-08-16 01:04:33.000000000 -0400 > @@ -398,6 +398,9 @@ > if (data->head->ack_socket) { > unsigned char header[AUDIT_RMW_HEADER_SIZE]; > > + if (fs_space_warning) > + ack_type = AUDIT_RMW_TYPE_DISKLOW; > + > AUDIT_RMW_PACK_HEADER (header, 0, ack_type, strlen(msg), > data->head->sequence_id); > > ar_write (data->head->ack_socket, header, > AUDIT_RMW_HEADER_SIZE); > > -- > Linux-audit mailing list > [email protected] > https://www.redhat.com/mailman/listinfo/linux-audit -- Linux-audit mailing list [email protected] https://www.redhat.com/mailman/listinfo/linux-audit
