aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/audit/src/ausearch-lol.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/audit/src/ausearch-lol.c')
-rw-r--r--framework/src/audit/src/ausearch-lol.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/framework/src/audit/src/ausearch-lol.c b/framework/src/audit/src/ausearch-lol.c
new file mode 100644
index 00000000..48005126
--- /dev/null
+++ b/framework/src/audit/src/ausearch-lol.c
@@ -0,0 +1,296 @@
+/*
+* ausearch-lol.c - linked list of linked lists library
+* Copyright (c) 2008,2010,2014 Red Hat Inc., Durham, North Carolina.
+* All Rights Reserved.
+*
+* This software may be freely redistributed and/or modified under the
+* terms of the GNU General Public License as published by the Free
+* Software Foundation; either version 2, or (at your option) any
+* later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; see the file COPYING. If not, write to the
+* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Authors:
+* Steve Grubb <sgrubb@redhat.com>
+*/
+
+#include "ausearch-lol.h"
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include "ausearch-common.h"
+#include "private.h"
+
+#define ARRAY_LIMIT 80
+static int ready = 0;
+
+void lol_create(lol *lo)
+{
+ int size = ARRAY_LIMIT * sizeof(lolnode);
+
+ lo->maxi = -1;
+ lo->limit = ARRAY_LIMIT;
+ lo->array = (lolnode *)malloc(size);
+ memset(lo->array, 0, size);
+}
+
+void lol_clear(lol *lo)
+{
+ int i;
+
+ for (i=0; i<=lo->maxi; i++) {
+ if (lo->array[i].status) {
+ list_clear(lo->array[i].l);
+ free(lo->array[i].l);
+ }
+ }
+ free(lo->array);
+ lo->array = NULL;
+ lo->maxi = -1;
+}
+
+static void lol_append(lol *lo, llist *l)
+{
+ int i;
+ size_t new_size;
+ lolnode *ptr;
+
+ for(i=0; i<lo->limit; i++) {
+ lolnode *cur = &lo->array[i];
+ if (cur->status == L_EMPTY) {
+ cur->l = l;
+ cur->status = L_BUILDING;
+ if (i > lo->maxi)
+ lo->maxi = i;
+ return;
+ }
+ }
+ // Overran the array...lets make it bigger
+ new_size = sizeof(lolnode) * (lo->limit + ARRAY_LIMIT);
+ ptr = realloc(lo->array, new_size);
+ if (ptr) {
+ lo->array = ptr;
+ memset(&lo->array[lo->limit], 0, sizeof(lolnode) * ARRAY_LIMIT);
+ lo->array[i].l = l;
+ lo->array[i].status = L_BUILDING;
+ lo->maxi = i;
+ lo->limit += ARRAY_LIMIT;
+ }
+}
+
+static int str2event(char *s, event *e)
+{
+ char *ptr;
+
+ errno = 0;
+ ptr = strchr(s+10, ':');
+ if (ptr) {
+ e->serial = strtoul(ptr+1, NULL, 10);
+ *ptr = 0;
+ if (errno)
+ return -1;
+ } else
+ e->serial = 0;
+ ptr = strchr(s, '.');
+ if (ptr) {
+ e->milli = strtoul(ptr+1, NULL, 10);
+ *ptr = 0;
+ if (errno)
+ return -1;
+ } else
+ e->milli = 0;
+ e->sec = strtoul(s, NULL, 10);
+ if (errno)
+ return -1;
+ return 0;
+}
+
+static int inline events_are_equal(event *e1, event *e2)
+{
+ if (!(e1->serial == e2->serial && e1->milli == e2->milli &&
+ e1->sec == e2->sec))
+ return 0;
+ if (e1->node && e2->node) {
+ if (strcmp(e1->node, e2->node))
+ return 0;
+ } else if (e1->node || e2->node)
+ return 0;
+ return 1;
+}
+
+/*
+ * This function will look at the line and pick out pieces of it.
+ */
+static int extract_timestamp(const char *b, event *e)
+{
+ char *ptr, *tmp, *tnode, *ttype;
+
+ e->node = NULL;
+ if (*b == 'n')
+ tmp = strndupa(b, 340);
+ else
+ tmp = strndupa(b, 80);
+ ptr = audit_strsplit(tmp);
+ if (ptr) {
+ // Check to see if this is the node info
+ if (*ptr == 'n') {
+ tnode = ptr+5;
+ ptr = audit_strsplit(NULL);
+ } else
+ tnode = NULL;
+
+ // at this point we have type=
+ ttype = ptr+5;
+
+ // Now should be pointing to msg=
+ ptr = audit_strsplit(NULL);
+ if (ptr) {
+ if (*(ptr+9) == '(')
+ ptr+=9;
+ else
+ ptr = strchr(ptr, '(');
+ if (ptr) {
+ // now we should be pointed at the timestamp
+ char *eptr;
+ ptr++;
+ eptr = strchr(ptr, ')');
+ if (eptr)
+ *eptr = 0;
+ if (str2event(ptr, e)) {
+ fprintf(stderr,
+ "Error extracting time stamp (%s)\n",
+ ptr);
+ return 0;
+ } else if ((start_time && e->sec < start_time)
+ || (end_time && e->sec > end_time))
+ return 0;
+ else {
+ if (tnode)
+ e->node = strdup(tnode);
+ e->type = audit_name_to_msg_type(ttype);
+ }
+ return 1;
+ }
+ // else we have a bad line
+ }
+ // else we have a bad line
+ }
+ // else we have a bad line
+ return 0;
+}
+
+// This function will check events to see if they are complete
+// FIXME: Can we think of other ways to determine if the event is done?
+static void check_events(lol *lo, time_t sec)
+{
+ int i;
+
+ for(i=0;i<=lo->maxi; i++) {
+ lolnode *cur = &lo->array[i];
+ if (cur->status == L_BUILDING) {
+ // If 2 seconds have elapsed, we are done
+ if (cur->l->e.sec + 2 < sec) {
+ cur->status = L_COMPLETE;
+ ready++;
+ } else if (cur->l->e.type < AUDIT_FIRST_EVENT ||
+ cur->l->e.type >= AUDIT_FIRST_ANOM_MSG) {
+ // If known to be 1 record event, we are done
+ cur->status = L_COMPLETE;
+ ready++;
+ }
+ }
+ }
+}
+
+// This function adds a new record to an existing linked list
+// or creates a new one if its a new event
+int lol_add_record(lol *lo, char *buff)
+{
+ int i;
+ lnode n;
+ event e;
+ char *ptr;
+ llist *l;
+
+ // Short circuit if event is not of interest
+ if (extract_timestamp(buff, &e) == 0)
+ return 0;
+
+ ptr = strrchr(buff, 0x0a);
+ if (ptr) {
+ *ptr = 0;
+ n.mlen = ptr - buff;
+ } else
+ n.mlen = MAX_AUDIT_MESSAGE_LENGTH;
+ n.message=strdup(buff);
+ n.type = e.type;
+
+ // Now see where this belongs
+ for (i=0; i<=lo->maxi; i++) {
+ if (lo->array[i].status == L_BUILDING) {
+ l = lo->array[i].l;
+ if (events_are_equal(&l->e, &e)) {
+ free((char *)e.node);
+ list_append(l, &n);
+ return 1;
+ }
+ }
+ }
+ // Create new event and fill it in
+ l = malloc(sizeof(llist));
+ list_create(l);
+ l->e.milli = e.milli;
+ l->e.sec = e.sec;
+ l->e.serial = e.serial;
+ l->e.node = e.node;
+ l->e.type = e.type;
+ list_append(l, &n);
+ lol_append(lo, l);
+ check_events(lo, e.sec);
+ return 1;
+}
+
+// This function will mark all events as "done"
+void terminate_all_events(lol *lo)
+{
+ int i;
+
+ for (i=0; i<=lo->maxi; i++) {
+ lolnode *cur = &lo->array[i];
+ if (cur->status == L_BUILDING) {
+ cur->status = L_COMPLETE;
+ ready++;
+ }
+ }
+//printf("maxi = %d\n",lo->maxi);
+}
+
+/* Search the list for any event that is ready to go. The caller
+ * takes custody of the memory */
+llist* get_ready_event(lol *lo)
+{
+ int i;
+
+ if (ready == 0)
+ return NULL;
+
+ for (i=0; i<=lo->maxi; i++) {
+ lolnode *cur = &lo->array[i];
+ if (cur->status == L_COMPLETE) {
+ cur->status = L_EMPTY;
+ ready--;
+ return cur->l;
+ }
+ }
+
+ return NULL;
+}
+