On Thursday 09 March 2006 11:06, Steve Grubb wrote:
> I'll take a hack at proposing an API and send it in a little
while.
The audit library parser could have the following functions:
I think we are in basic agreement...so this is another round of updates with
more details fleshed out. (A CDR if you will.)
Audit Event Parsing Library
====================
All functions that begin with ausearch are related to searching for a subset
of events based on certain criteria. All functions that begin with auparse
are used to access events, records, and fields sequentially and without
regard to any search options that may be in effect. All functions return 1 on
success and 0 on failure unless otherwise noted. Where the return type is a
char, NULL will indicate failure. The data structures would be hidden from
the external application. Access to fields is a name/value style. You access
the fields through functions that either return string pointer or ints.
typedef enum { AUSOURCE_LOGS, AUSOURCE_FILE, AUSOURCE_BUFFER } source_t;
int auparse_init(source_t source, void *b) - allow init of library. Set data
source: logs, file, buffer. The pointer, b, is used to set the file name or
pass the buff when those types are given.
typedef enum { AUSEARCH_STOP_EVENT, AUSEARCH_STOP_RECORD, AUSEARCH_STOP_FIELD
} stop_t;
int ausearch_set_param(const char *field, const char *op, const char *value,
stop_t where) - set search options. The field would be the left hand side of
the audit name value pairs. The op would be how to match, =,!=,>,<, <=, >=.
The value would be the right hand side of the audit field name value pairs.
The where parameter tells the search library where to place the internal
cursor when a match is found. It could be on first field of first record,
first field of record containing the match, or the field that matches.
int ausearch_next_event(void) - traverse to the next event that yields a match
based on the given search criteria.
int auparse_next_event(void) - traverse to next event. This allows access to
time and serial number.
typedef struct
{
time_t sec; // Event seconds
unsigned int milli; // millisecond of the timestamp
unsigned long serial; // Serial number of the event
} event_t;
event_t auparse_get_timestamp(void) - retrieve time stamp of current record
time_t auparse_get_time(void) - retrieve time in seconds of current record
time_t auparse_get_milli(void) - retrieve milliseconds time of current record
unsigned long auparse_get_serial(void) - retrieve serial number of current
record
int auparse_first_record(void) - set iterator to first record in current event
int auparse_next_record(void) - traverse to next record in event. this allows
access to the event type
int auparse_get_type(void) - retrieve type of current record
int auparse_first_field(void) - set field pointer to first in current record
int auparse_next_field(void) - traverse the fields in a record
const char *auparse_find_field(const char *name) - find a given field in a
event or record. Name is the left hand side of the name/value pair. Returns
pointer to the value as ascii text.
const char *auparse_find_field_next(void ) - find the next occurance of that
field in the same record. Returns pointer to the value as ascii text.
const char *auparse_get_field_str(void) - return current field value as a
string
int auparse_get_field_int(void) - return current field value as an int
const char *auparse_interpret_field(void) - interpret the current field
int auparse_destroy(void) - free all data structures and close file
descriptors
This would allow the following kind of programming:
int main(void)
{
if (!auparse_init(AUSOURCE_LOGS, NULL))
return 1;
if (!ausearch_set_param("auid", "=", "500",
AUSEARCH_STOP_RECORD))
return 1;
while (ausearch_next_event()) {
if (auparse_find_field("auid"))
printf("auid=%s\n", auparse_interpret_field());
}
return 0;
}