diff options
Diffstat (limited to 'framework/src/audit/src')
67 files changed, 0 insertions, 27598 deletions
diff --git a/framework/src/audit/src/Makefile.am b/framework/src/audit/src/Makefile.am deleted file mode 100644 index 8d1af865..00000000 --- a/framework/src/audit/src/Makefile.am +++ /dev/null @@ -1,57 +0,0 @@ -# Makefile.am-- -# Copyright 2004-2006, 2008,2011-15 Red Hat Inc., Durham, North Carolina. -# All Rights Reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Authors: -# Steve Grubb <sgrubb@redhat.com> -# - -CONFIG_CLEAN_FILES = *.rej *.orig -AUTOMAKE_OPTIONS = no-dependencies -SUBDIRS = test -AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/lib -I${top_srcdir}/src/libev -I${top_srcdir}/auparse -sbin_PROGRAMS = auditd auditctl aureport ausearch autrace -AM_CFLAGS = -D_GNU_SOURCE -noinst_HEADERS = auditd-config.h auditd-event.h auditd-listen.h ausearch-llist.h ausearch-options.h auditctl-llist.h aureport-options.h ausearch-parse.h aureport-scan.h ausearch-lookup.h ausearch-int.h auditd-dispatch.h ausearch-string.h ausearch-nvpair.h ausearch-common.h ausearch-avc.h ausearch-time.h ausearch-lol.h auditctl-listing.h ausearch-checkpt.h - -auditd_SOURCES = auditd.c auditd-event.c auditd-config.c auditd-reconfig.c auditd-sendmail.c auditd-dispatch.c -if ENABLE_LISTENER -auditd_SOURCES += auditd-listen.c -endif -auditd_CFLAGS = -fPIE -DPIE -g -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pthread -auditd_LDFLAGS = -pie -Wl,-z,relro -Wl,-z,now -auditd_DEPENDENCIES = mt/libauditmt.a libev/libev.a -auditd_LDADD = @LIBWRAP_LIBS@ -Llibev -lev -Lmt -lauditmt -lpthread -lrt -lm $(gss_libs) - -auditctl_SOURCES = auditctl.c auditctl-llist.c delete_all.c auditctl-listing.c -auditctl_CFLAGS = -fPIE -DPIE -g -D_GNU_SOURCE -auditctl_LDFLAGS = -pie -Wl,-z,relro -Wl,-z,now -auditctl_LDADD = -L${top_builddir}/lib -laudit -L${top_builddir}/auparse -lauparse - -aureport_SOURCES = aureport.c auditd-config.c ausearch-llist.c aureport-options.c ausearch-string.c ausearch-parse.c aureport-scan.c aureport-output.c ausearch-lookup.c ausearch-int.c ausearch-time.c ausearch-nvpair.c ausearch-avc.c ausearch-lol.c -aureport_LDADD = -L${top_builddir}/lib -laudit - -ausearch_SOURCES = ausearch.c auditd-config.c ausearch-llist.c ausearch-options.c ausearch-report.c ausearch-match.c ausearch-string.c ausearch-parse.c ausearch-int.c ausearch-time.c ausearch-nvpair.c ausearch-lookup.c ausearch-avc.c ausearch-lol.c ausearch-checkpt.c -ausearch_LDADD = -L${top_builddir}/lib -laudit -L${top_builddir}/auparse -lauparse - -autrace_SOURCES = autrace.c delete_all.c auditctl-llist.c -autrace_LDADD = -L${top_builddir}/lib -laudit - -mt/libauditmt.a: - make -C mt -libev/libev.a: - make -C libev diff --git a/framework/src/audit/src/auditctl-listing.c b/framework/src/audit/src/auditctl-listing.c deleted file mode 100644 index 88dac6c8..00000000 --- a/framework/src/audit/src/auditctl-listing.c +++ /dev/null @@ -1,577 +0,0 @@ -/* auditctl-listing.c -- - * Copyright 2014 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - */ - -#include "config.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "auditctl-listing.h" -#include "private.h" -#include "auditctl-llist.h" -#include "auparse-idata.h" - -/* Global vars */ -static llist l; -static int printed; -extern int list_requested, interpret; -extern char key[AUDIT_MAX_KEY_LEN+1]; -extern const char key_sep[2]; - -/* - * Returns 1 if rule should be printed & 0 if not - */ -int key_match(const struct audit_rule_data *r) -{ - int i; - size_t boffset = 0; - - if (key[0] == 0) - return 1; - - // At this point, we have a key - for (i = 0; i < r->field_count; i++) { - int field = r->fields[i] & ~AUDIT_OPERATORS; - if (field == AUDIT_FILTERKEY) { - char *keyptr; - if (asprintf(&keyptr, "%.*s", r->values[i], - &r->buf[boffset]) < 0) - keyptr = NULL; - else if (strstr(keyptr, key)) { - free(keyptr); - return 1; - } - free(keyptr); - } - if (((field >= AUDIT_SUBJ_USER && field <= AUDIT_OBJ_LEV_HIGH) - && field != AUDIT_PPID) || field == AUDIT_WATCH || - field == AUDIT_DIR || field == AUDIT_FILTERKEY) { - boffset += r->values[i]; - } - } - return 0; -} - -/* - * This function detects if we have a watch. A watch is detected when we - * have syscall == all and a perm field. - */ -static int is_watch(const struct audit_rule_data *r) -{ - int i, perm = 0, all = 1; - - for (i = 0; i < r->field_count; i++) { - int field = r->fields[i] & ~AUDIT_OPERATORS; - if (field == AUDIT_PERM) - perm = 1; - // Watches can have only 4 field types - if (field != AUDIT_PERM && field != AUDIT_FILTERKEY && - field != AUDIT_DIR && field != AUDIT_WATCH) - return 0; - } - - if (((r->flags & AUDIT_FILTER_MASK) != AUDIT_FILTER_USER) && - ((r->flags & AUDIT_FILTER_MASK) != AUDIT_FILTER_TASK) && - ((r->flags & AUDIT_FILTER_MASK) != AUDIT_FILTER_EXCLUDE)) { - for (i = 0; i < (AUDIT_BITMASK_SIZE-1); i++) { - if (r->mask[i] != (uint32_t)~0) { - all = 0; - break; - } - } - } - if (perm && all) - return 1; - return 0; -} - -static int print_arch(unsigned int value, int op) -{ - int machine; - _audit_elf = value; - machine = audit_elf_to_machine(_audit_elf); - if (machine < 0) - printf(" -F arch%s0x%X", audit_operator_to_symbol(op), - (unsigned)value); - else { - if (interpret == 0) { - if (__AUDIT_ARCH_64BIT & _audit_elf) - printf(" -F arch%sb64", - audit_operator_to_symbol(op)); - else - printf(" -F arch%sb32", - audit_operator_to_symbol(op)); - } else { - const char *ptr = audit_machine_to_name(machine); - printf(" -F arch%s%s", audit_operator_to_symbol(op), - ptr); - } - } - return machine; -} - -static int print_syscall(const struct audit_rule_data *r, unsigned int *sc) -{ - int count = 0; - int all = 1; - unsigned int i; - int machine = audit_detect_machine(); - - /* Rules on the following filters do not take a syscall */ - if (((r->flags & AUDIT_FILTER_MASK) == AUDIT_FILTER_USER) || - ((r->flags & AUDIT_FILTER_MASK) == AUDIT_FILTER_TASK) || - ((r->flags &AUDIT_FILTER_MASK) == AUDIT_FILTER_EXCLUDE)) - return 0; - - /* See if its all or specific syscalls */ - for (i = 0; i < (AUDIT_BITMASK_SIZE-1); i++) { - if (r->mask[i] != (uint32_t)~0) { - all = 0; - break; - } - } - - if (all) { - printf(" -S all"); - count = i; - } else for (i = 0; i < AUDIT_BITMASK_SIZE * 32; i++) { - int word = AUDIT_WORD(i); - int bit = AUDIT_BIT(i); - if (r->mask[word] & bit) { - const char *ptr; - if (_audit_elf) - machine = audit_elf_to_machine(_audit_elf); - if (machine < 0) - ptr = NULL; - else - ptr = audit_syscall_to_name(i, machine); - if (!count) - printf(" -S "); - if (ptr) - printf("%s%s", !count ? "" : ",", ptr); - else - printf("%s%d", !count ? "" : ",", i); - count++; - *sc = i; - } - } - return count; -} - -static void print_field_cmp(int value, int op) -{ - switch (value) - { - case AUDIT_COMPARE_UID_TO_OBJ_UID: - printf(" -C uid%sobj_uid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_GID_TO_OBJ_GID: - printf(" -C gid%sobj_gid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_EUID_TO_OBJ_UID: - printf(" -C euid%sobj_uid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_EGID_TO_OBJ_GID: - printf(" -C egid%sobj_gid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_AUID_TO_OBJ_UID: - printf(" -C auid%sobj_uid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_SUID_TO_OBJ_UID: - printf(" -C suid%sobj_uid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_SGID_TO_OBJ_GID: - printf(" -C sgid%sobj_gid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_FSUID_TO_OBJ_UID: - printf(" -C fsuid%sobj_uid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_FSGID_TO_OBJ_GID: - printf(" -C fsgid%sobj_gid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_UID_TO_AUID: - printf(" -C uid%sauid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_UID_TO_EUID: - printf(" -C uid%seuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_UID_TO_FSUID: - printf(" -C uid%sfsuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_UID_TO_SUID: - printf(" -C uid%ssuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_AUID_TO_FSUID: - printf(" -C auid%sfsuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_AUID_TO_SUID: - printf(" -C auid%ssuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_AUID_TO_EUID: - printf(" -C auid%seuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_EUID_TO_SUID: - printf(" -C euid%ssuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_EUID_TO_FSUID: - printf(" -C euid%sfsuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_SUID_TO_FSUID: - printf(" -C suid%sfsuid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_GID_TO_EGID: - printf(" -C gid%segid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_GID_TO_FSGID: - printf(" -C gid%sfsgid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_GID_TO_SGID: - printf(" -C gid%ssgid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_EGID_TO_FSGID: - printf(" -C egid%sfsgid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_EGID_TO_SGID: - printf(" -C egid%ssgid", - audit_operator_to_symbol(op)); - break; - case AUDIT_COMPARE_SGID_TO_FSGID: - printf(" -C sgid%sfsgid", - audit_operator_to_symbol(op)); - break; - } -} - -/* - * This function prints 1 rule from the kernel reply - */ -static void print_rule(const struct audit_rule_data *r) -{ - unsigned int i, count = 0, sc = 0; - size_t boffset = 0; - int mach = -1, watch = is_watch(r); - unsigned long long a0 = 0, a1 = 0; - - if (!watch) { /* This is syscall auditing */ - printf("-a %s,%s", - audit_action_to_name((int)r->action), - audit_flag_to_name(r->flags)); - - // Now find the arch and print it - for (i = 0; i < r->field_count; i++) { - int field = r->fields[i] & ~AUDIT_OPERATORS; - if (field == AUDIT_ARCH) { - int op = r->fieldflags[i] & AUDIT_OPERATORS; - mach = print_arch(r->values[i], op); - } - } - // And last do the syscalls - count = print_syscall(r, &sc); - } - - // Now iterate over the fields - for (i = 0; i < r->field_count; i++) { - const char *name; - int op = r->fieldflags[i] & AUDIT_OPERATORS; - int field = r->fields[i] & ~AUDIT_OPERATORS; - - if (field == AUDIT_ARCH) - continue; // already printed - - name = audit_field_to_name(field); - if (name) { - // Special cases to print the different field types - // in a meaningful way. - if (field == AUDIT_MSGTYPE) { - if (!audit_msg_type_to_name(r->values[i])) - printf(" -F %s%s%d", name, - audit_operator_to_symbol(op), - r->values[i]); - else - printf(" -F %s%s%s", name, - audit_operator_to_symbol(op), - audit_msg_type_to_name( - r->values[i])); - } else if ((field >= AUDIT_SUBJ_USER && - field <= AUDIT_OBJ_LEV_HIGH) - && field != AUDIT_PPID) { - printf(" -F %s%s%.*s", name, - audit_operator_to_symbol(op), - r->values[i], &r->buf[boffset]); - boffset += r->values[i]; - } else if (field == AUDIT_WATCH) { - if (watch) - printf("-w %.*s", r->values[i], - &r->buf[boffset]); - else - printf(" -F path=%.*s", r->values[i], - &r->buf[boffset]); - boffset += r->values[i]; - } else if (field == AUDIT_DIR) { - if (watch) - printf("-w %.*s/", r->values[i], - &r->buf[boffset]); - else - printf(" -F dir=%.*s", r->values[i], - &r->buf[boffset]); - - boffset += r->values[i]; - } else if (field == AUDIT_FILTERKEY) { - char *rkey, *ptr, *saved; - if (asprintf(&rkey, "%.*s", r->values[i], - &r->buf[boffset]) < 0) - rkey = NULL; - boffset += r->values[i]; - ptr = strtok_r(rkey, key_sep, &saved); - while (ptr) { - if (watch) - printf(" -k %s", ptr); - else - printf(" -F key=%s", ptr); - ptr = strtok_r(NULL, key_sep, &saved); - } - free(rkey); - } else if (field == AUDIT_PERM) { - char perms[5]; - int val=r->values[i]; - perms[0] = 0; - if (val & AUDIT_PERM_READ) - strcat(perms, "r"); - if (val & AUDIT_PERM_WRITE) - strcat(perms, "w"); - if (val & AUDIT_PERM_EXEC) - strcat(perms, "x"); - if (val & AUDIT_PERM_ATTR) - strcat(perms, "a"); - if (watch) - printf(" -p %s", perms); - else - printf(" -F perm=%s", perms); - } else if (field == AUDIT_INODE) { - // This is unsigned - printf(" -F %s%s%u", name, - audit_operator_to_symbol(op), - r->values[i]); - } else if (field == AUDIT_FIELD_COMPARE) { - print_field_cmp(r->values[i], op); - } else if (field >= AUDIT_ARG0 && field <= AUDIT_ARG3){ - if (field == AUDIT_ARG0) - a0 = r->values[i]; - else if (field == AUDIT_ARG1) - a1 = r->values[i]; - - // Show these as hex - if (count > 1 || interpret == 0) - printf(" -F %s%s0x%X", name, - audit_operator_to_symbol(op), - r->values[i]); - else { // Use ignore to mean interpret - const char *out; - idata id; - char val[32]; - int type; - - id.syscall = sc; - id.machine = mach; - id.a0 = a0; - id.a1 = a1; - id.name = name; - snprintf(val, 32, "%x", r->values[i]); - id.val = val; - type = auparse_interp_adjust_type( - AUDIT_SYSCALL, name, val); - out = auparse_do_interpretation(type, - &id); - printf(" -F %s%s%s", name, - audit_operator_to_symbol(op), - out); - free((void *)out); - } - } else if (field == AUDIT_EXIT) { - int e = abs((int)r->values[i]); - const char *err = audit_errno_to_name(e); - - if (((int)r->values[i] < 0) && err) - printf(" -F %s%s-%s", name, - audit_operator_to_symbol(op), - err); - else - printf(" -F %s%s%d", name, - audit_operator_to_symbol(op), - (int)r->values[i]); - } else { - // The default is signed decimal - printf(" -F %s%s%d", name, - audit_operator_to_symbol(op), - r->values[i]); - } - } else { - // The field name is unknown - printf(" f%d%s%d", r->fields[i], - audit_operator_to_symbol(op), - r->values[i]); - } - } - printf("\n"); -} - -void audit_print_init(void) -{ - printed = 0; - list_create(&l); -} - -const char *get_enable(unsigned e) -{ - switch (e) - { - case 0: - return "disable"; - case 1: - return "enabled"; - case 2: - return "enabl;ed+immutable"; - default: - return "unknown"; - } -} - -const char *get_failure(unsigned f) -{ - switch (f) - { - case 0: - return "silent"; - case 1: - return "printk"; - case 2: - return "panic"; - default: - return "unknown"; - } -} - -/* - * This function interprets the reply and prints it to stdout. It returns - * 0 if no more should be read and 1 to indicate that more messages of this - * type may need to be read. - */ -int audit_print_reply(struct audit_reply *rep, int fd) -{ - _audit_elf = 0; - - switch (rep->type) { - case NLMSG_NOOP: - return 1; - case NLMSG_DONE: - // Close the socket so kernel can do other things - audit_close(fd); - if (printed == 0) - printf("No rules\n"); - else { - lnode *n; - list_first(&l); - n = l.cur; - while (n) { - print_rule(n->r); - n = list_next(&l); - } - list_clear(&l); - } - break; - case NLMSG_ERROR: - printf("NLMSG_ERROR %d (%s)\n", - -rep->error->error, - strerror(-rep->error->error)); - printed = 1; - break; - case AUDIT_GET: - if (interpret) - printf("enabled %s\nfailure %s\n", - get_enable(rep->status->enabled), - get_failure(rep->status->failure)); - else - printf("enabled %u\nfailure %u\n", - rep->status->enabled, rep->status->failure); - printf("pid %u\nrate_limit %u\nbacklog_limit %u\n" - "lost %u\nbacklog %u\n", - rep->status->pid, rep->status->rate_limit, - rep->status->backlog_limit, rep->status->lost, - rep->status->backlog); -#if HAVE_DECL_AUDIT_VERSION_BACKLOG_WAIT_TIME - printf("backlog_wait_time %u\n", - rep->status->backlog_wait_time); -#endif - printed = 1; - break; -#if HAVE_DECL_AUDIT_FEATURE_VERSION - case AUDIT_GET_FEATURE: - { - uint32_t mask = AUDIT_FEATURE_TO_MASK(AUDIT_FEATURE_LOGINUID_IMMUTABLE); - if (rep->features->mask & mask) - printf("loginuid_immutable %u %s\n", - !!(rep->features->features & mask), - rep->features->lock & mask ? "locked" : - "unlocked"); - } - printed = 1; - break; -#endif - case AUDIT_LIST_RULES: - list_requested = 0; - if (key_match(rep->ruledata)) - list_append(&l, rep->ruledata, - sizeof(struct audit_rule_data) + - rep->ruledata->buflen); - printed = 1; - return 1; - default: - printf("Unknown: type=%d, len=%d\n", rep->type, - rep->nlh->nlmsg_len); - printed = 1; - break; - } - return 0; -} - diff --git a/framework/src/audit/src/auditctl-listing.h b/framework/src/audit/src/auditctl-listing.h deleted file mode 100644 index 8a412ef3..00000000 --- a/framework/src/audit/src/auditctl-listing.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* auditctl-listing.h - Header file for ausearch-llist.c -* Copyright (c) 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> -*/ - -#ifndef CTLLISTING_HEADER -#define CTLLISTING_HEADER - -#include "config.h" -#include "libaudit.h" - -void audit_print_init(void); -int audit_print_reply(struct audit_reply *rep, int fd); -int key_match(const struct audit_rule_data *r); - -#endif diff --git a/framework/src/audit/src/auditctl-llist.c b/framework/src/audit/src/auditctl-llist.c deleted file mode 100644 index 175310d7..00000000 --- a/framework/src/audit/src/auditctl-llist.c +++ /dev/null @@ -1,105 +0,0 @@ -/* -* ausearch-llist.c - Minimal linked list library -* Copyright (c) 2005 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 <stdlib.h> -#include <string.h> -#include "auditctl-llist.h" - -void list_create(llist *l) -{ - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - -void list_first(llist *l) -{ - l->cur = l->head; -} - -void list_last(llist *l) -{ - register lnode* window; - - if (l->head == NULL) - return; - - window = l->head; - while (window->next) - window = window->next; - l->cur = window; -} - -lnode *list_next(llist *l) -{ - if (l->cur == NULL) - return NULL; - l->cur = l->cur->next; - return l->cur; -} - -void list_append(llist *l, struct audit_rule_data *r, size_t sz) -{ - lnode* newnode; - - newnode = malloc(sizeof(lnode)); - - if (r) { - void *rr = malloc(sz); - if (rr) - memcpy(rr, r, sz); - newnode->r = rr; - } else - newnode->r = NULL; - - newnode->size = sz; - newnode->next = 0; - - // if we are at top, fix this up - if (l->head == NULL) - l->head = newnode; - else // Otherwise add pointer to newnode - l->cur->next = newnode; - - // make newnode current - l->cur = newnode; - l->cnt++; -} - -void list_clear(llist* l) -{ - lnode* nextnode; - register lnode* current; - - current = l->head; - while (current) { - nextnode=current->next; - free(current->r); - free(current); - current=nextnode; - } - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - diff --git a/framework/src/audit/src/auditctl-llist.h b/framework/src/audit/src/auditctl-llist.h deleted file mode 100644 index 371d0d7e..00000000 --- a/framework/src/audit/src/auditctl-llist.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -* auditctl-llist.h - Header file for ausearch-llist.c -* Copyright (c) 2005 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> -*/ - -#ifndef CTLLIST_HEADER -#define CTLLIST_HEADER - -#include "config.h" -#include <sys/types.h> -#include "libaudit.h" - -/* This is the node of the linked list. message & item are the only elements - * at this time. Any data elements that are per item goes here. */ -typedef struct _lnode{ - struct audit_rule_data *r; // The rule from the kernel - size_t size; // Size of the rule struct - struct _lnode *next; // Next node pointer -} lnode; - -/* This is the linked list head. Only data elements that are 1 per - * event goes here. */ -typedef struct { - lnode *head; // List head - lnode *cur; // Pointer to current node - unsigned int cnt; // How many items in this list -} llist; - -void list_create(llist *l); -void list_first(llist *l); -void list_last(llist *l); -lnode *list_next(llist *l); -static inline lnode *list_get_cur(llist *l) { return l->cur; } -void list_append(llist *l, struct audit_rule_data *r, size_t sz); -void list_clear(llist* l); - -#endif - diff --git a/framework/src/audit/src/auditctl.c b/framework/src/audit/src/auditctl.c deleted file mode 100644 index 334f8021..00000000 --- a/framework/src/audit/src/auditctl.c +++ /dev/null @@ -1,1472 +0,0 @@ -/* auditctl.c -- - * Copyright 2004-2015 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * Rickard E. (Rik) Faith <faith@redhat.com> - */ - -#include "config.h" -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> /* strdup needs xopen define */ -#include <getopt.h> -#include <time.h> -#include <sys/stat.h> -#include <ctype.h> -#include <unistd.h> -#include <sys/utsname.h> -#include <fcntl.h> -#include <errno.h> -#include <libgen.h> /* For basename */ -#include <limits.h> /* PATH_MAX */ -#include "libaudit.h" -#include "auditctl-listing.h" -#include "private.h" - -/* This define controls the size of the line that we will request when - * reading in rules from a file. - */ -#define LINE_SIZE 6144 - - -/* Global functions */ -static int handle_request(int status); -static void get_reply(void); -extern int delete_all_rules(int fd); - -/* Global vars */ -int list_requested = 0, interpret = 0; -char key[AUDIT_MAX_KEY_LEN+1]; -const char key_sep[2] = { AUDIT_KEY_SEPARATOR, 0 }; -static int keylen; -static int fd = -1; -static int add = AUDIT_FILTER_UNSET, del = AUDIT_FILTER_UNSET, action = -1; -static int ignore = 0, continue_error = 0; -static int exclude = 0; -static int multiple = 0; -static struct audit_rule_data *rule_new = NULL; - -/* - * This function will reset everything used for each loop when loading - * a ruleset from a file. - */ -static int reset_vars(void) -{ - list_requested = 0; - _audit_syscalladded = 0; - _audit_permadded = 0; - _audit_archadded = 0; - _audit_elf = 0; - add = AUDIT_FILTER_UNSET; - del = AUDIT_FILTER_UNSET; - action = -1; - exclude = 0; - multiple = 0; - - free(rule_new); - rule_new = malloc(sizeof(struct audit_rule_data)); - memset(rule_new, 0, sizeof(struct audit_rule_data)); - if (fd < 0) { - if ((fd = audit_open()) < 0) { - audit_msg(LOG_ERR, "Cannot open netlink audit socket"); - return 1; - } - } - return 0; -} - -static void usage(void) -{ - printf( - "usage: auditctl [options]\n" - " -a <l,a> Append rule to end of <l>ist with <a>ction\n" - " -A <l,a> Add rule at beginning of <l>ist with <a>ction\n" - " -b <backlog> Set max number of outstanding audit buffers\n" - " allowed Default=64\n" - " -c Continue through errors in rules\n" - " -C f=f Compare collected fields if available:\n" - " Field name, operator(=,!=), field name\n" - " -d <l,a> Delete rule from <l>ist with <a>ction\n" - " l=task,exit,user,exclude\n" - " a=never,always\n" - " -D Delete all rules and watches\n" - " -e [0..2] Set enabled flag\n" - " -f [0..2] Set failure flag\n" - " 0=silent 1=printk 2=panic\n" - " -F f=v Build rule: field name, operator(=,!=,<,>,<=,\n" - " >=,&,&=) value\n" - " -h Help\n" - " -i Ignore errors when reading rules from file\n" - " -k <key> Set filter key on audit rule\n" - " -l List rules\n" - " -m text Send a user-space message\n" - " -p [r|w|x|a] Set permissions filter on watch\n" - " r=read, w=write, x=execute, a=attribute\n" - " -q <mount,subtree> make subtree part of mount point's dir watches\n" - " -r <rate> Set limit in messages/sec (0=none)\n" - " -R <file> read rules from file\n" - " -s Report status\n" - " -S syscall Build rule: syscall name or number\n" - " -t Trim directory watches\n" - " -v Version\n" - " -w <path> Insert watch at <path>\n" - " -W <path> Remove watch at <path>\n" - " --loginuid-immutable Make loginuids unchangeable once set\n" - " --backlog_wait_time Set the kernel backlog_wait_time\n" - ); -} - -static int lookup_filter(const char *str, int *filter) -{ - if (strcmp(str, "task") == 0) - *filter = AUDIT_FILTER_TASK; - else if (strcmp(str, "entry") == 0) - *filter = AUDIT_FILTER_ENTRY; - else if (strcmp(str, "exit") == 0) - *filter = AUDIT_FILTER_EXIT; - else if (strcmp(str, "user") == 0) - *filter = AUDIT_FILTER_USER; - else if (strcmp(str, "exclude") == 0) { - *filter = AUDIT_FILTER_EXCLUDE; - exclude = 1; - } else - return 2; - return 0; -} - -static int lookup_action(const char *str, int *act) -{ - if (strcmp(str, "never") == 0) - *act = AUDIT_NEVER; - else if (strcmp(str, "possible") == 0) - return 1; - else if (strcmp(str, "always") == 0) - *act = AUDIT_ALWAYS; - else - return 2; - return 0; -} - -/* - * Returns 0 ok, 1 deprecated action, 2 rule error, - * 3 multiple rule insert/delete - */ -static int audit_rule_setup(char *opt, int *filter, int *act, int lineno) -{ - int rc; - char *p; - - if (++multiple != 1) - return 3; - - p = strchr(opt, ','); - if (p == NULL || strchr(p+1, ',')) - return 2; - *p = 0; - - /* Try opt both ways */ - if (lookup_filter(opt, filter) == 2) { - rc = lookup_action(opt, act); - if (rc != 0) { - *p = ','; - return rc; - } - } - - /* Repair the string */ - *p = ','; - opt = p+1; - - /* If flags are empty, p+1 must be the filter */ - if (*filter == AUDIT_FILTER_UNSET) - lookup_filter(opt, filter); - else { - rc = lookup_action(opt, act); - if (rc != 0) - return rc; - } - - /* Make sure we set both */ - if (*filter == AUDIT_FILTER_UNSET || *act == -1) - return 2; - - /* Consolidate rules on exit filter */ - if (*filter == AUDIT_FILTER_ENTRY) { - *filter = AUDIT_FILTER_EXIT; - if (lineno) - audit_msg(LOG_INFO, "Warning - entry rules deprecated, changing to exit rule in line %d", lineno); - else - audit_msg(LOG_INFO, - "Warning - entry rules deprecated, changing to exit rule"); - } - - return 0; -} - -/* - * This function will check the path before accepting it. It returns - * 1 on error and 0 on success. - */ -static int check_path(const char *path) -{ - char *ptr, *base; - size_t nlen; - size_t plen = strlen(path); - if (plen >= PATH_MAX) { - audit_msg(LOG_ERR, "The path passed for the watch is too big"); - return 1; - } - if (path[0] != '/') { - audit_msg(LOG_ERR, "The path must start with '/'"); - return 1; - } - ptr = strdup(path); - base = basename(ptr); - nlen = strlen(base); - free(ptr); - if (nlen > NAME_MAX) { - audit_msg(LOG_ERR, "The base name of the path is too big"); - return 1; - } - - /* These are warnings, not errors */ - if (strstr(path, "..")) - audit_msg(LOG_WARNING, - "Warning - relative path notation is not supported"); - if (strchr(path, '*') || strchr(path, '?')) - audit_msg(LOG_WARNING, - "Warning - wildcard notation is not supported"); - - return 0; -} - -/* - * Setup a watch. The "name" of the watch in userspace will be the <path> to - * the watch. When this potential watch reaches the kernel, it will resolve - * down to <name> (of terminating file or directory). - * Returns a 1 on success & -1 on failure. - */ -static int audit_setup_watch_name(struct audit_rule_data **rulep, char *path) -{ - int type = AUDIT_WATCH; - size_t len; - struct stat buf; - - if (check_path(path)) - return -1; - - // Trim trailing '/' should they exist - len = strlen(path); - if (len > 2 && path[len-1] == '/') { - while (path[len-1] == '/' && len > 1) { - path[len-1] = 0; - len--; - } - } - if (stat(path, &buf) == 0) { - if (S_ISDIR(buf.st_mode)) - type = AUDIT_DIR; - } - /* FIXME: might want to check to see that rule is empty */ - if (audit_add_watch_dir(type, rulep, path)) - return -1; - - return 1; -} - -/* - * Setup a watch permissions. - * Returns a 1 on success & -1 on failure. - */ -static int audit_setup_perms(struct audit_rule_data *rule, const char *opt) -{ - unsigned int i, len, val = 0; - - len = strlen(opt); - if (len > 4) - return -1; - - for (i = 0; i < len; i++) { - switch (tolower(opt[i])) { - case 'r': - val |= AUDIT_PERM_READ; - break; - case 'w': - val |= AUDIT_PERM_WRITE; - break; - case 'x': - val |= AUDIT_PERM_EXEC; - break; - case 'a': - val |= AUDIT_PERM_ATTR; - break; - default: - audit_msg(LOG_ERR, - "Permission %c isn't supported", - opt[i]); - return -1; - } - } - - if (audit_update_watch_perms(rule_new, val) == 0) { - _audit_permadded = 1; - return 1; - } - return -1; -} - -/* 0 success, -1 failure */ -static int lookup_itype(const char *kind) -{ - if (strcmp(kind, "sys") == 0) - return 0; - if (strcmp(kind, "file") == 0) - return 0; - if (strcmp(kind, "exec") == 0) - return 0; - if (strcmp(kind, "mkexe") == 0) - return 0; - return -1; -} - -/* 0 success, -1 failure */ -static int lookup_iseverity(const char *severity) -{ - if (strncmp(severity, "inf", 3) == 0) - return 0; - if (strncmp(severity, "low", 3) == 0) - return 0; - if (strncmp(severity, "med", 3) == 0) - return 0; - if (strncmp(severity, "hi", 2) == 0) - return 0; - return -1; -} - -/* 0 success, -1 failure */ -static int check_ids_key(const char *k) -{ - char *ptr, *kindptr, *ratingptr; - char keyptr[AUDIT_MAX_KEY_LEN+1]; - - if (strlen(k) > AUDIT_MAX_KEY_LEN) - goto fail_exit; - - strncpy(keyptr, k, sizeof(keyptr)); - keyptr[AUDIT_MAX_KEY_LEN] = 0; - ptr = strchr(keyptr, '-'); // There has to be a - because strncmp - kindptr = ptr + 1; - if (*kindptr == 0) - goto fail_exit; - - ptr = strchr(kindptr, '-'); - if (ptr) { - *ptr = 0; - ratingptr = ptr +1; - } else // The rules are misconfigured - goto fail_exit; - if (*ratingptr == 0) - goto fail_exit; - - if (lookup_itype(kindptr)) { - audit_msg(LOG_ERR, "ids key type is bad"); - return -1; - } - if (lookup_iseverity(ratingptr)) { - audit_msg(LOG_ERR, "ids key severity is bad"); - return -1; - } - return 0; - -fail_exit: - audit_msg(LOG_ERR, "ids key is bad"); - return -1; -} - -static int equiv_parse(char *optarg, char **mp, char **sub) -{ - char *ptr = strchr(optarg, ','); - if (ptr == NULL) - return -1; // no comma - *ptr = 0; - ptr++; - if (*ptr == 0) - return -1; // ends with comma - *mp = optarg; - *sub = ptr; - if (strchr(*sub, ',')) - return -1; // too many commas - return 0; -} - -int audit_request_rule_list(int fd) -{ - if (audit_request_rules_list_data(fd) > 0) { - list_requested = 1; - get_reply(); - return 1; - } - return 0; -} - -void check_rule_mismatch(int lineno, const char *option) -{ - struct audit_rule_data tmprule; - unsigned int old_audit_elf = _audit_elf; - int rc = 0; - - switch (_audit_elf) - { - case AUDIT_ARCH_X86_64: - _audit_elf = AUDIT_ARCH_I386; - break; - case AUDIT_ARCH_PPC64: - _audit_elf = AUDIT_ARCH_PPC; - break; - case AUDIT_ARCH_S390X: - _audit_elf = AUDIT_ARCH_S390; - break; - } - memset(&tmprule, 0, sizeof(struct audit_rule_data)); - audit_rule_syscallbyname_data(&tmprule, option); - if (memcmp(tmprule.mask, rule_new->mask, AUDIT_BITMASK_SIZE)) - rc = 1; - _audit_elf = old_audit_elf; - if (rc) { - if (lineno) - audit_msg(LOG_WARNING, "WARNING - 32/64 bit syscall mismatch in line %d, you should specify an arch", lineno); - else - audit_msg(LOG_WARNING, "WARNING - 32/64 bit syscall mismatch, you should specify an arch"); - } -} - -int report_status(int fd) -{ - int retval; - - retval = audit_request_status(fd); - if (retval == -1) { - if (errno == ECONNREFUSED) - fprintf(stderr, "The audit system is disabled\n"); - return -1; - } - get_reply(); - retval = audit_request_features(fd); - if (retval == -1) { - // errno is EINVAL if the kernel does support features API - if (errno == EINVAL) - return -2; - return -1; - } - get_reply(); - return -2; -} - -int parse_syscall(struct audit_rule_data *rule_new, const char *optarg) -{ - int retval = 0; - char *saved; - - if (strchr(optarg, ',')) { - char *ptr, *tmp = strdup(optarg); - if (tmp == NULL) - return -1; - ptr = strtok_r(tmp, ",", &saved); - while (ptr) { - retval = audit_rule_syscallbyname_data(rule_new, ptr); - if (retval != 0) { - if (retval == -1) { - audit_msg(LOG_ERR, - "Syscall name unknown: %s", - ptr); - retval = -3; // error reported - } - break; - } - ptr = strtok_r(NULL, ",", &saved); - } - free(tmp); - return retval; - } - - return audit_rule_syscallbyname_data(rule_new, optarg); -} - -struct option long_opts[] = -{ - {"loginuid-immutable", 0, NULL, 1}, - {"backlog_wait_time", 1, NULL, 2}, - {NULL, 0, NULL, 0} -}; - -// FIXME: Change these to enums -/* - * returns: -3 deprecated, -2 success - no reply, -1 error - noreply, - * 0 success - reply, > 0 success - rule - */ -static int setopt(int count, int lineno, char *vars[]) -{ - int c; - int retval = 0, rc; - - optind = 0; - opterr = 0; - key[0] = 0; - keylen = AUDIT_MAX_KEY_LEN; - - while ((retval >= 0) && (c = getopt_long(count, vars, - "hicslDvtC:e:f:r:b:a:A:d:S:F:m:R:w:W:k:p:q:", - long_opts, NULL)) != EOF) { - int flags = AUDIT_FILTER_UNSET; - rc = 10; // Init to something impossible to see if unused. - switch (c) { - case 'h': - usage(); - retval = -1; - break; - case 'i': - ignore = 1; - retval = -2; - break; - case 'c': - ignore = 1; - continue_error = 1; - retval = -2; - break; - case 's': - if (count > 3) { - audit_msg(LOG_ERR, - "Too many options for status command"); - retval = -1; - break; - } else if (optind == 2 && count == 3) { - if (strcmp(vars[optind], "-i") == 0) { - interpret = 1; - count -= 1; - } else { - audit_msg(LOG_ERR, - "Only -i option is allowed"); - retval = -1; - break; - } - } - retval = report_status(fd); - break; - case 'e': - if (optarg && ((strcmp(optarg, "0") == 0) || - (strcmp(optarg, "1") == 0) || - (strcmp(optarg, "2") == 0))) { - if (audit_set_enabled(fd, strtoul(optarg,NULL,0)) > 0) - audit_request_status(fd); - else - retval = -1; - } else { - audit_msg(LOG_ERR, "Enable must be 0, 1, or 2 was %s", - optarg); - retval = -1; - } - break; - case 'f': - if (optarg && ((strcmp(optarg, "0") == 0) || - (strcmp(optarg, "1") == 0) || - (strcmp(optarg, "2") == 0))) { - if (audit_set_failure(fd, strtoul(optarg,NULL,0)) > 0) - audit_request_status(fd); - else - return -1; - } else { - audit_msg(LOG_ERR, "Failure must be 0, 1, or 2 was %s", - optarg); - retval = -1; - } - break; - case 'r': - if (optarg && isdigit(optarg[0])) { - uint32_t rate; - errno = 0; - rate = strtoul(optarg,NULL,0); - if (errno) { - audit_msg(LOG_ERR, "Error converting rate"); - return -1; - } - if (audit_set_rate_limit(fd, rate) > 0) - audit_request_status(fd); - else - return -1; - } else { - audit_msg(LOG_ERR,"Rate must be a numeric value was %s", - optarg); - retval = -1; - } - break; - case 'b': - if (optarg && isdigit(optarg[0])) { - uint32_t limit; - errno = 0; - limit = strtoul(optarg,NULL,0); - if (errno) { - audit_msg(LOG_ERR, "Error converting backlog"); - return -1; - } - if (audit_set_backlog_limit(fd, limit) > 0) - audit_request_status(fd); - else - return -1; - } else { - audit_msg(LOG_ERR, - "Backlog must be a numeric value was %s", - optarg); - retval = -1; - } - break; - case 'l': - if (count > 4) { - audit_msg(LOG_ERR, - "Wrong number of options for list request"); - retval = -1; - break; - } - if (count == 3) { - if (strcmp(vars[optind], "-i") == 0) { - interpret = 1; - count -= 1; - } else { - audit_msg(LOG_ERR, - "Only -k or -i options are allowed"); - retval = -1; - } - } else if (count == 4) { - if (vars[optind] && strcmp(vars[optind], "-k") == 0) { - strncat(key, vars[3], keylen); - count -= 2; - } else { - audit_msg(LOG_ERR, - "Only -k or -i options are allowed"); - retval = -1; - break; - } - } - if (audit_request_rule_list(fd)) { - list_requested = 1; - retval = -2; - } else - retval = -1; - break; - case 'a': - if (strstr(optarg, "task") && _audit_syscalladded) { - audit_msg(LOG_ERR, - "Syscall auditing requested for task list"); - retval = -1; - } else { - rc = audit_rule_setup(optarg, &add, &action, lineno); - if (rc == 3) { - audit_msg(LOG_ERR, - "Multiple rule insert/delete operations are not allowed\n"); - retval = -1; - } else if (rc == 2) { - audit_msg(LOG_ERR, - "Append rule - bad keyword %s", - optarg); - retval = -1; - } else if (rc == 1) { - audit_msg(LOG_ERR, - "Append rule - possible is deprecated"); - return -3; /* deprecated - eat it */ - } else - retval = 1; /* success - please send */ - } - break; - case 'A': - if (strstr(optarg, "task") && _audit_syscalladded) { - audit_msg(LOG_ERR, - "Error: syscall auditing requested for task list"); - retval = -1; - } else { - rc = audit_rule_setup(optarg, &add, &action, lineno); - if (rc == 3) { - audit_msg(LOG_ERR, - "Multiple rule insert/delete operations are not allowed"); - retval = -1; - } else if (rc == 2) { - audit_msg(LOG_ERR, - "Add rule - bad keyword %s", optarg); - retval = -1; - } else if (rc == 1) { - audit_msg(LOG_WARNING, - "Append rule - possible is deprecated"); - return -3; /* deprecated - eat it */ - } else { - add |= AUDIT_FILTER_PREPEND; - retval = 1; /* success - please send */ - } - } - break; - case 'd': - rc = audit_rule_setup(optarg, &del, &action, lineno); - if (rc == 3) { - audit_msg(LOG_ERR, - "Multiple rule insert/delete operations are not allowed"); - retval = -1; - } else if (rc == 2) { - audit_msg(LOG_ERR, "Delete rule - bad keyword %s", - optarg); - retval = -1; - } else if (rc == 1) { - audit_msg(LOG_INFO, - "Delete rule - possible is deprecated"); - return -3; /* deprecated - eat it */ - } else - retval = 1; /* success - please send */ - break; - case 'S': { - int unknown_arch = !_audit_elf; - /* Do some checking to make sure that we are not adding a - * syscall rule to a list that does not make sense. */ - if (((add & (AUDIT_FILTER_MASK|AUDIT_FILTER_UNSET)) == - AUDIT_FILTER_TASK || (del & - (AUDIT_FILTER_MASK|AUDIT_FILTER_UNSET)) == - AUDIT_FILTER_TASK)) { - audit_msg(LOG_ERR, - "Error: syscall auditing being added to task list"); - return -1; - } else if (((add & (AUDIT_FILTER_MASK|AUDIT_FILTER_UNSET)) == - AUDIT_FILTER_USER || (del & - (AUDIT_FILTER_MASK|AUDIT_FILTER_UNSET)) == - AUDIT_FILTER_USER)) { - audit_msg(LOG_ERR, - "Error: syscall auditing being added to user list"); - return -1; - } else if (exclude) { - audit_msg(LOG_ERR, - "Error: syscall auditing cannot be put on exclude list"); - return -1; - } else { - if (unknown_arch) { - int machine; - unsigned int elf; - machine = audit_detect_machine(); - if (machine < 0) { - audit_msg(LOG_ERR, - "Error detecting machine type"); - return -1; - } - elf = audit_machine_to_elf(machine); - if (elf == 0) { - audit_msg(LOG_ERR, - "Error looking up elf type %d", - machine); - return -1; - } - _audit_elf = elf; - } - } - rc = parse_syscall(rule_new, optarg); - switch (rc) - { - case 0: - _audit_syscalladded = 1; - if (unknown_arch && add != AUDIT_FILTER_UNSET) - check_rule_mismatch(lineno, optarg); - break; - case -1: - audit_msg(LOG_ERR, "Syscall name unknown: %s", - optarg); - retval = -1; - break; - case -2: - audit_msg(LOG_ERR, "Elf type unknown: 0x%x", - _audit_elf); - retval = -1; - break; - case -3: // Error reported - do nothing here - retval = -1; - break; - }} - break; - case 'F': - if (add != AUDIT_FILTER_UNSET) - flags = add & AUDIT_FILTER_MASK; - else if (del != AUDIT_FILTER_UNSET) - flags = del & AUDIT_FILTER_MASK; - // if the field is arch & there is a -t option...we - // can allow it - else if ((optind >= count) || (strstr(optarg, "arch=") == NULL) - || (strcmp(vars[optind], "-t") != 0)) { - audit_msg(LOG_ERR, "List must be given before field"); - retval = -1; - break; - } - - rc = audit_rule_fieldpair_data(&rule_new,optarg,flags); - if (rc != 0) { - audit_number_to_errmsg(rc, optarg); - retval = -1; - } else { - if (rule_new->fields[rule_new->field_count-1] == - AUDIT_PERM) - _audit_permadded = 1; - } - - break; - case 'C': - if (add != AUDIT_FILTER_UNSET) - flags = add & AUDIT_FILTER_MASK; - else if (del != AUDIT_FILTER_UNSET) - flags = del & AUDIT_FILTER_MASK; - - rc = audit_rule_interfield_comp_data(&rule_new, optarg, flags); - if (rc != 0) { - audit_number_to_errmsg(rc, optarg); - retval = -1; - } else { - if (rule_new->fields[rule_new->field_count - 1] == - AUDIT_PERM) - _audit_permadded = 1; - } - break; - case 'm': - if (count > 3) { - audit_msg(LOG_ERR, - "The -m option must be only the only option and takes 1 parameter"); - retval = -1; - } else { - const char*s = optarg; - while (*s) { - if (*s < 32) { - audit_msg(LOG_ERR, - "Illegal character in audit event"); - return -1; - } - s++; - } - if (audit_log_user_message( fd, AUDIT_USER, - optarg, NULL, NULL, NULL, 1) <= 0) - retval = -1; - else - return -2; // success - no reply for this - } - break; - case 'R': - audit_msg(LOG_ERR, "Error - nested rule files not supported"); - retval = -1; - break; - case 'D': - if (count > 4 || count == 3) { - audit_msg(LOG_ERR, - "Wrong number of options for Delete all request"); - retval = -1; - break; - } - if (count == 4) { - if (strcmp(vars[optind], "-k") == 0) { - strncat(key, vars[3], keylen); - count -= 2; - } else { - audit_msg(LOG_ERR, - "Only the -k option is allowed"); - retval = -1; - break; - } - } - retval = delete_all_rules(fd); - if (retval == 0) { - (void)audit_request_rule_list(fd); - key[0] = 0; - retval = -2; - } - break; - case 'w': - if (add != AUDIT_FILTER_UNSET || - del != AUDIT_FILTER_UNSET) { - audit_msg(LOG_ERR, - "watch option can't be given with a syscall"); - retval = -1; - } else if (optarg) { - add = AUDIT_FILTER_EXIT; - action = AUDIT_ALWAYS; - _audit_syscalladded = 1; - retval = audit_setup_watch_name(&rule_new, optarg); - } else { - audit_msg(LOG_ERR, "watch option needs a path"); - retval = -1; - } - break; - case 'W': - if (optarg) { - del = AUDIT_FILTER_EXIT; - action = AUDIT_ALWAYS; - _audit_syscalladded = 1; - retval = audit_setup_watch_name(&rule_new, optarg); - } else { - audit_msg(LOG_ERR, "watch option needs a path"); - retval = -1; - } - break; - case 'k': - if (!(_audit_syscalladded || _audit_permadded ) || - (add==AUDIT_FILTER_UNSET && - del==AUDIT_FILTER_UNSET)) { - audit_msg(LOG_ERR, - "key option needs a watch or syscall given prior to it"); - retval = -1; - } else if (!optarg) { - audit_msg(LOG_ERR, "key option needs a value"); - retval = -1; - } else if ((strlen(optarg)+strlen(key)+(!!key[0])) > - AUDIT_MAX_KEY_LEN) { - audit_msg(LOG_ERR, "key option exceeds size limit"); - retval = -1; - } else { - if (strncmp(optarg, "ids-", 4) == 0) { - if (check_ids_key(optarg)) { - retval = -1; - break; - } - } - if (strchr(optarg, AUDIT_KEY_SEPARATOR)) - audit_msg(LOG_ERR, - "key %s has illegal character", optarg); - if (key[0]) { // Add the separator if we need to - strcat(key, key_sep); - keylen--; - } - strncat(key, optarg, keylen); - keylen = AUDIT_MAX_KEY_LEN - strlen(key); - } - break; - case 'p': - if (!add && !del) { - audit_msg(LOG_ERR, - "permission option needs a watch given prior to it"); - retval = -1; - } else if (!optarg) { - audit_msg(LOG_ERR, "permission option needs a filter"); - retval = -1; - } else - retval = audit_setup_perms(rule_new, optarg); - break; - case 'q': - if (_audit_syscalladded) { - audit_msg(LOG_ERR, - "Syscall auditing requested for make equivalent"); - retval = -1; - } else { - char *mp, *sub; - retval = equiv_parse(optarg, &mp, &sub); - if (retval < 0) { - audit_msg(LOG_ERR, - "Error parsing equivalent parts"); - retval = -1; - } else { - retval = audit_make_equivalent(fd, mp, sub); - if (retval <= 0) { - retval = -1; - } else - return -2; // success - no reply needed - } - } - break; - case 't': - retval = audit_trim_subtrees(fd); - if (retval <= 0) - retval = -1; - else - return -2; // success - no reply for this - break; - case 'v': - printf("auditctl version %s\n", VERSION); - retval = -2; - break; - // Now the long options - case 1: - retval = audit_set_loginuid_immutable(fd); - if (retval <= 0) - retval = -1; - else - return -2; // success - no reply for this - break; - case 2: -#if HAVE_DECL_AUDIT_VERSION_BACKLOG_WAIT_TIME - if (optarg && isdigit(optarg[0])) { - uint32_t bwt; - errno = 0; - bwt = strtoul(optarg,NULL,0); - if (errno) { - audit_msg(LOG_ERR, - "Error converting backlog_wait_time"); - return -1; - } - if (audit_set_backlog_wait_time(fd, bwt) > 0) - audit_request_status(fd); - else - return -1; - } else { - audit_msg(LOG_ERR, - "Backlog_wait_time must be a numeric value was %s", - optarg); - retval = -1; - } -#else - audit_msg(LOG_ERR, - "backlog_wait_time is not supported on your kernel"); - retval = -1; -#endif - break; - default: - usage(); - retval = -1; - break; - } - } - /* catch extra args or errors where the user types "- s" */ - if (optind == 1) - retval = -1; - else if ((optind < count) && (retval != -1)) { - audit_msg(LOG_ERR, "parameter passed without an option given"); - retval = -1; - } - - /* See if we were adding a key */ - if (key[0] && list_requested == 0) { - int flags = 0; - char *cmd=NULL; - - /* Get the flag */ - if (add != AUDIT_FILTER_UNSET) - flags = add & AUDIT_FILTER_MASK; - else if (del != AUDIT_FILTER_UNSET) - flags = del & AUDIT_FILTER_MASK; - - /* Build the command */ - if (asprintf(&cmd, "key=%s", key) < 0) { - cmd = NULL; - audit_msg(LOG_ERR, "Out of memory adding key"); - retval = -1; - } else { - /* Add this to the rule */ - int ret = audit_rule_fieldpair_data(&rule_new, cmd, flags); - if (ret < 0) - retval = -1; - free(cmd); - } - } - if (retval == -1 && errno == ECONNREFUSED) - audit_msg(LOG_ERR, "The audit system is disabled"); - return retval; -} - -static char *get_line(FILE *f, char *buf) -{ - if (fgets_unlocked(buf, LINE_SIZE, f)) { - /* remove newline */ - char *ptr = strchr(buf, 0x0a); - if (ptr) - *ptr = 0; - return buf; - } - return NULL; -} - - -void preprocess(char *buf) -{ - unsigned int i = 0; - bool esc_ctx = false; - - while (buf[i]) { - if (buf[i] == '\\' && esc_ctx == false) - esc_ctx = true; - else { - if (esc_ctx == true) { - if (buf[i] == ' ') { - buf[i] = 0x07; - buf[i - 1] = 0x07; - } else if (buf[i] == '\\') { - buf[i] = 0x04; - buf[i - 1] = 0x04; - } - - esc_ctx = false; - } - } - - i++; - } -} - - -void postprocess(char *buf) -{ - char *str = strdup(buf); - char *pos1 = str; - char *pos2 = buf; - - if (!str) - return; - - while (*pos1) { - if (*pos1 == 0x07) { - *pos2 = ' '; - pos1 += 2; - pos2++; - continue; - } else if (*pos1 == 0x04) { - *pos2 = '\\'; - pos1 += 2; - pos2++; - continue; - } - - *pos2 = *pos1; - pos2++; - pos1++; - } - - *pos2 = 0; - free(str); -} - - -/* - * This function reads the given file line by line and executes the rule. - * It returns 0 if everything went OK, 1 if there are problems before reading - * the file and -1 on error conditions after executing some of the rules. - * It will abort reading the file if it encounters any problems. - */ -static int fileopt(const char *file) -{ - int i, tfd, rc, lineno = 1; - struct stat st; - FILE *f; - char buf[LINE_SIZE]; - - /* Does the file exist? */ - rc = open(file, O_RDONLY); - if (rc < 0) { - if (errno != ENOENT) { - audit_msg(LOG_ERR,"Error opening %s (%s)", - file, strerror(errno)); - return 1; - } - audit_msg(LOG_INFO, "file %s doesn't exist, skipping", file); - return 0; - } - tfd = rc; - - /* Is the file permissions sane? */ - if (fstat(tfd, &st) < 0) { - audit_msg(LOG_ERR, "Error fstat'ing %s (%s)", - file, strerror(errno)); - close(tfd); - return 1; - } - if (st.st_uid != 0) { - audit_msg(LOG_ERR, "Error - %s isn't owned by root", file); - close(tfd); - return 1; - } - if ((st.st_mode & S_IWOTH) == S_IWOTH) { - audit_msg(LOG_ERR, "Error - %s is world writable", file); - close(tfd); - return 1; - } - if (!S_ISREG(st.st_mode)) { - audit_msg(LOG_ERR, "Error - %s is not a regular file", file); - close(tfd); - return 1; - } - - f = fdopen(tfd, "rm"); - if (f == NULL) { - audit_msg(LOG_ERR, "Error - fdopen failed (%s)", - strerror(errno)); - close(tfd); - return 1; - } - - /* Read until eof, lineno starts as 1 */ - while (get_line(f, buf)) { - char *ptr, **fields; - int idx=0, nf = (strlen(buf)/3) + 3; - - /* Weed out blank lines */ - while (buf[idx] == ' ') - idx++; - if (buf[idx] == 0) { - lineno++; - continue; - } - - preprocess(buf); - ptr = audit_strsplit(buf); - if (ptr == NULL) - break; - - /* allow comments */ - if (ptr[0] == '#') { - lineno++; - continue; - } - i = 0; - fields = malloc(nf * sizeof(char *)); - fields[i++] = "auditctl"; - fields[i++] = ptr; - while( (ptr=audit_strsplit(NULL)) && (i < nf-1)) { - postprocess(ptr); - fields[i++] = ptr; - } - - fields[i] = NULL; - - /* Parse it */ - if (reset_vars()) { - free(fields); - fclose(f); - return -1; - } - rc = setopt(i, lineno, fields); - free(fields); - - /* handle reply or send rule */ - if (rc != -3) { - if (handle_request(rc) == -1) { - if (errno != ECONNREFUSED) - audit_msg(LOG_ERR, - "There was an error in line %d of %s", - lineno, file); - else { - audit_msg(LOG_ERR, - "The audit system is disabled"); - fclose(f); - return 0; - } - if (ignore == 0) { - fclose(f); - return -1; - } - if (continue_error) - continue_error = -1; - } - } - lineno++; - } - fclose(f); - return 0; -} - -/* Return 1 if ready, 0 otherwise */ -static int is_ready(int fd) -{ - if (audit_is_enabled(fd) == 2) { - audit_msg(LOG_ERR, "The audit system is in immutable mode," - " no rule changes allowed"); - return 0; - } else if (errno == ECONNREFUSED) { - audit_msg(LOG_ERR, "The audit system is disabled"); - return 0; - } - return 1; -} - -int main(int argc, char *argv[]) -{ - int retval = 1; - - set_aumessage_mode(MSG_STDERR, DBG_NO); - - if (argc == 1) { - usage(); - return 1; - } -#ifndef DEBUG - /* Make sure we are root if we do anything except help */ - if (!(argc == 2 && (strcmp(argv[1], "--help")==0 || - strcmp(argv[1], "-h") == 0)) && (geteuid() != 0)) { - audit_msg(LOG_WARNING, "You must be root to run this program."); - return 4; - } -#endif - /* Check where the rules are coming from: commandline or file */ - if ((argc == 3) && (strcmp(argv[1], "-R") == 0)) { - // If reading a file, its most likely start up. Send problems - // to syslog where they will persist for later review - set_aumessage_mode(MSG_SYSLOG, DBG_NO); - fd = audit_open(); - if (is_ready(fd) == 0) - return 0; - else if (fileopt(argv[2])) { - free(rule_new); - return 1; - } else { - free(rule_new); - if (continue_error < 0) - return 1; - return 0; - } - } else { - if (reset_vars()) { - free(rule_new); - return 1; - } - retval = setopt(argc, 0, argv); - if (retval == -3) { - free(rule_new); - return 0; - } - } - - if (add != AUDIT_FILTER_UNSET || del != AUDIT_FILTER_UNSET) { - fd = audit_open(); - if (is_ready(fd) == 0) { - free(rule_new); - return 0; - } - } - retval = handle_request(retval); - free(rule_new); - return retval; -} - -/* - * This function is called after setopt to handle the return code. - * On entry, status = 0 means just get the reply. Greater than 0 means we - * are adding or deleting a rule or watch. -1 means an error occurred. - * -2 means everything is OK and no reply needed. Even if there's an - * error, we need to call this routine to close up the audit fd. - * The return code from this function is 0 success and -1 error. - */ -static int handle_request(int status) -{ - if (status == 0) { - if (_audit_syscalladded) { - audit_msg(LOG_ERR, "Error - no list specified"); - return -1; - } - get_reply(); - } else if (status == -2) - status = 0; // report success - else if (status > 0) { - int rc; - if (add != AUDIT_FILTER_UNSET) { - // if !task add syscall any if not specified - if ((add & AUDIT_FILTER_MASK) != AUDIT_FILTER_TASK && - _audit_syscalladded != 1) { - audit_rule_syscallbyname_data( - rule_new, "all"); - } - set_aumessage_mode(MSG_QUIET, DBG_NO); - rc = audit_add_rule_data(fd, rule_new, add, action); - set_aumessage_mode(MSG_STDERR, DBG_NO); - /* Retry for legacy kernels */ - if (rc < 0) { - if (errno == EINVAL && - rule_new->fields[0] == AUDIT_DIR) { - rule_new->fields[0] = AUDIT_WATCH; - rc = audit_add_rule_data(fd, rule_new, - add, action); - } else { - audit_msg(LOG_ERR, - "Error sending add rule data request (%s)", - errno == EEXIST ? - "Rule exists" : strerror(-rc)); - } - } - } - else if (del != AUDIT_FILTER_UNSET) { - if ((del & AUDIT_FILTER_MASK) != AUDIT_FILTER_TASK && - _audit_syscalladded != 1) { - audit_rule_syscallbyname_data( - rule_new, "all"); - } - set_aumessage_mode(MSG_QUIET, DBG_NO); - rc = audit_delete_rule_data(fd, rule_new, - del, action); - set_aumessage_mode(MSG_STDERR, DBG_NO); - /* Retry for legacy kernels */ - if (rc < 0) { - if (errno == EINVAL && - rule_new->fields[0] == AUDIT_DIR) { - rule_new->fields[0] = AUDIT_WATCH; - rc = audit_delete_rule_data(fd,rule_new, - del, action); - } else { - audit_msg(LOG_ERR, - "Error sending delete rule data request (%s)", - errno == EEXIST ? - "Rule exists" : strerror(-rc)); - } - } - } else { - usage(); - audit_close(fd); - exit(1); - } - if (rc <= 0) - status = -1; - else - status = 0; - } else - status = -1; - - if (!list_requested) - audit_close(fd); - fd = -1; - return status; -} - -/* - * A reply from the kernel is expected. Get and display it. - */ -static void get_reply(void) -{ - int i, retval; - int timeout = 40; /* loop has delay of .1 - so this is 4 seconds */ - struct audit_reply rep; - fd_set read_mask; - FD_ZERO(&read_mask); - FD_SET(fd, &read_mask); - - // Reset printing counter - audit_print_init(); - - for (i = 0; i < timeout; i++) { - struct timeval t; - - t.tv_sec = 0; - t.tv_usec = 100000; /* .1 second */ - do { - retval=select(fd+1, &read_mask, NULL, NULL, &t); - } while (retval < 0 && errno == EINTR); - // We'll try to read just in case - retval = audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0); - if (retval > 0) { - if (rep.type == NLMSG_ERROR && rep.error->error == 0) { - i = 0; /* reset timeout */ - continue; /* This was an ack */ - } - - if ((retval = audit_print_reply(&rep, fd)) == 0) - break; - else - i = 0; /* If getting more, reset timeout */ - } - } -} - diff --git a/framework/src/audit/src/auditd-config.c b/framework/src/audit/src/auditd-config.c deleted file mode 100644 index 0a99ffe0..00000000 --- a/framework/src/audit/src/auditd-config.c +++ /dev/null @@ -1,1744 +0,0 @@ -/* auditd-config.c -- - * Copyright 2004-2011,2013-14 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#include "config.h" -#include <stdio.h> -#include <unistd.h> -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <dirent.h> -#include <ctype.h> -#include <stdlib.h> -#include <netdb.h> -#include <fcntl.h> /* O_NOFOLLOW needs gnu defined */ -#include <libgen.h> -#include <arpa/inet.h> -#include <limits.h> /* INT_MAX */ -#include "auditd-config.h" -#include "libaudit.h" -#include "private.h" - -#define TCP_PORT_MAX 65535 - -/* Local prototypes */ -struct nv_pair -{ - const char *name; - const char *value; - const char *option; -}; - -struct kw_pair -{ - const char *name; - int (*parser)(struct nv_pair *, int, struct daemon_conf *); - int max_options; -}; - -struct nv_list -{ - const char *name; - int option; -}; - -static char *get_line(FILE *f, char *buf, unsigned size, int *lineno, - const char *file); -static int nv_split(char *buf, struct nv_pair *nv); -static const struct kw_pair *kw_lookup(const char *val); -static int log_file_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int num_logs_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int log_group_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int qos_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int dispatch_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int name_format_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int name_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int max_log_size_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int max_log_size_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int log_format_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int flush_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int freq_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int space_left_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int space_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int action_mail_acct_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int admin_space_left_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int admin_space_left_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int disk_full_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int disk_error_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int priority_boost_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int tcp_listen_port_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int tcp_listen_queue_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int tcp_max_per_addr_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int use_libwrap_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int tcp_client_ports_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int tcp_client_max_idle_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int enable_krb5_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int krb5_principal_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int krb5_key_file_parser(struct nv_pair *nv, int line, - struct daemon_conf *config); -static int sanity_check(struct daemon_conf *config); - -static const struct kw_pair keywords[] = -{ - {"log_file", log_file_parser, 0 }, - {"log_format", log_format_parser, 0 }, - {"log_group", log_group_parser, 0 }, - {"flush", flush_parser, 0 }, - {"freq", freq_parser, 0 }, - {"num_logs", num_logs_parser, 0 }, - {"dispatcher", dispatch_parser, 0 }, - {"name_format", name_format_parser, 0 }, - {"name", name_parser, 0 }, - {"disp_qos", qos_parser, 0 }, - {"max_log_file", max_log_size_parser, 0 }, - {"max_log_file_action", max_log_size_action_parser, 0 }, - {"space_left", space_left_parser, 0 }, - {"space_left_action", space_action_parser, 1 }, - {"action_mail_acct", action_mail_acct_parser, 0 }, - {"admin_space_left", admin_space_left_parser, 0 }, - {"admin_space_left_action", admin_space_left_action_parser, 1 }, - {"disk_full_action", disk_full_action_parser, 1 }, - {"disk_error_action", disk_error_action_parser, 1 }, - {"priority_boost", priority_boost_parser, 0 }, - {"tcp_listen_port", tcp_listen_port_parser, 0 }, - {"tcp_listen_queue", tcp_listen_queue_parser, 0 }, - {"tcp_max_per_addr", tcp_max_per_addr_parser, 0 }, - {"use_libwrap", use_libwrap_parser, 0 }, - {"tcp_client_ports", tcp_client_ports_parser, 0 }, - {"tcp_client_max_idle", tcp_client_max_idle_parser, 0 }, - {"enable_krb5", enable_krb5_parser, 0 }, - {"krb5_principal", krb5_principal_parser, 0 }, - {"krb5_key_file", krb5_key_file_parser, 0 }, - { NULL, NULL } -}; - -static const struct nv_list log_formats[] = -{ - {"raw", LF_RAW }, - {"nolog", LF_NOLOG }, - { NULL, 0 } -}; - -static const struct nv_list flush_techniques[] = -{ - {"none", FT_NONE }, - {"incremental", FT_INCREMENTAL }, - {"data", FT_DATA }, - {"sync", FT_SYNC }, - { NULL, 0 } -}; - -static const struct nv_list failure_actions[] = -{ - {"ignore", FA_IGNORE }, - {"syslog", FA_SYSLOG }, - {"rotate", FA_ROTATE }, - {"email", FA_EMAIL }, - {"exec", FA_EXEC }, - {"suspend", FA_SUSPEND }, - {"single", FA_SINGLE }, - {"halt", FA_HALT }, - { NULL, 0 } -}; - -// Future ideas: e-mail, run command -static const struct nv_list size_actions[] = -{ - {"ignore", SZ_IGNORE }, - {"syslog", SZ_SYSLOG }, - {"suspend", SZ_SUSPEND }, - {"rotate", SZ_ROTATE }, - {"keep_logs", SZ_KEEP_LOGS}, - { NULL, 0 } -}; - -static const struct nv_list qos_options[] = -{ - {"lossy", QOS_NON_BLOCKING }, - {"lossless", QOS_BLOCKING }, - { NULL, 0 } -}; - -static const struct nv_list node_name_formats[] = -{ - {"none", N_NONE }, - {"hostname", N_HOSTNAME }, - {"fqd", N_FQD }, - {"numeric", N_NUMERIC }, - {"user", N_USER }, - { NULL, 0 } -}; - -static const struct nv_list yes_no_values[] = -{ - {"yes", 1 }, - {"no", 0 }, - { NULL, 0 } -}; - -const char *email_command = "/usr/lib/sendmail"; -static int allow_links = 0; - - -void set_allow_links(int allow) -{ - allow_links = allow; -} - -/* - * Set everything to its default value -*/ -void clear_config(struct daemon_conf *config) -{ - config->qos = QOS_NON_BLOCKING; - config->sender_uid = 0; - config->sender_pid = 0; - config->sender_ctx = NULL; - config->log_file = strdup("/var/log/audit/audit.log"); - config->log_format = LF_RAW; - config->log_group = 0; - config->priority_boost = 4; - config->flush = FT_NONE; - config->freq = 0; - config->num_logs = 0L; - config->dispatcher = NULL; - config->node_name_format = N_NONE; - config->node_name = NULL; - config->max_log_size = 0L; - config->max_log_size_action = SZ_IGNORE; - config->space_left = 0L; - config->space_left_action = FA_IGNORE; - config->space_left_exe = NULL; - config->action_mail_acct = strdup("root"); - config->admin_space_left= 0L; - config->admin_space_left_action = FA_IGNORE; - config->admin_space_left_exe = NULL; - config->disk_full_action = FA_IGNORE; - config->disk_full_exe = NULL; - config->disk_error_action = FA_SYSLOG; - config->disk_error_exe = NULL; - config->tcp_listen_port = 0; - config->tcp_listen_queue = 5; - config->tcp_max_per_addr = 1; - config->use_libwrap = 1; - config->tcp_client_min_port = 0; - config->tcp_client_max_port = TCP_PORT_MAX; - config->tcp_client_max_idle = 0; - config->enable_krb5 = 0; - config->krb5_principal = NULL; - config->krb5_key_file = NULL; -} - -static log_test_t log_test = TEST_AUDITD; -int load_config(struct daemon_conf *config, log_test_t lt) -{ - int fd, rc, mode, lineno = 1; - struct stat st; - FILE *f; - char buf[160]; - - clear_config(config); - log_test = lt; - - /* open the file */ - mode = O_RDONLY; - if (allow_links == 0) - mode |= O_NOFOLLOW; - rc = open(CONFIG_FILE, mode); - if (rc < 0) { - if (errno != ENOENT) { - audit_msg(LOG_ERR, "Error opening config file (%s)", - strerror(errno)); - return 1; - } - audit_msg(LOG_WARNING, - "Config file %s doesn't exist, skipping", CONFIG_FILE); - return 0; - } - fd = rc; - - /* check the file's permissions: owned by root, not world writable, - * not symlink. - */ - audit_msg(LOG_DEBUG, "Config file %s opened for parsing", - CONFIG_FILE); - if (fstat(fd, &st) < 0) { - audit_msg(LOG_ERR, "Error fstat'ing config file (%s)", - strerror(errno)); - close(fd); - return 1; - } - if (st.st_uid != 0) { - audit_msg(LOG_ERR, "Error - %s isn't owned by root", - CONFIG_FILE); - close(fd); - return 1; - } - if ((st.st_mode & S_IWOTH) == S_IWOTH) { - audit_msg(LOG_ERR, "Error - %s is world writable", - CONFIG_FILE); - close(fd); - return 1; - } - if (!S_ISREG(st.st_mode)) { - audit_msg(LOG_ERR, "Error - %s is not a regular file", - CONFIG_FILE); - close(fd); - return 1; - } - - /* it's ok, read line by line */ - f = fdopen(fd, "rm"); - if (f == NULL) { - audit_msg(LOG_ERR, "Error - fdopen failed (%s)", - strerror(errno)); - close(fd); - return 1; - } - - while (get_line(f, buf, sizeof(buf), &lineno, CONFIG_FILE)) { - // convert line into name-value pair - const struct kw_pair *kw; - struct nv_pair nv; - rc = nv_split(buf, &nv); - switch (rc) { - case 0: // fine - break; - case 1: // not the right number of tokens. - audit_msg(LOG_ERR, - "Wrong number of arguments for line %d in %s", - lineno, CONFIG_FILE); - break; - case 2: // no '=' sign - audit_msg(LOG_ERR, - "Missing equal sign for line %d in %s", - lineno, CONFIG_FILE); - break; - default: // something else went wrong... - audit_msg(LOG_ERR, - "Unknown error for line %d in %s", - lineno, CONFIG_FILE); - break; - } - if (nv.name == NULL) { - lineno++; - continue; - } - if (nv.value == NULL) { - fclose(f); - audit_msg(LOG_ERR, - "Not processing any more lines in %s", - CONFIG_FILE); - return 1; - } - - /* identify keyword or error */ - kw = kw_lookup(nv.name); - if (kw->name == NULL) { - audit_msg(LOG_ERR, - "Unknown keyword \"%s\" in line %d of %s", - nv.name, lineno, CONFIG_FILE); - fclose(f); - return 1; - } - - /* Check number of options */ - if (kw->max_options == 0 && nv.option != NULL) { - audit_msg(LOG_ERR, - "Keyword \"%s\" has invalid option " - "\"%s\" in line %d of %s", - nv.name, nv.option, lineno, CONFIG_FILE); - fclose(f); - return 1; - } - - /* dispatch to keyword's local parser */ - rc = kw->parser(&nv, lineno, config); - if (rc != 0) { - fclose(f); - return 1; // local parser puts message out - } - - lineno++; - } - - fclose(f); - if (lineno > 1) - return sanity_check(config); - return 0; -} - -static char *get_line(FILE *f, char *buf, unsigned size, int *lineno, - const char *file) -{ - int too_long = 0; - - while (fgets_unlocked(buf, size, f)) { - /* remove newline */ - char *ptr = strchr(buf, 0x0a); - if (ptr) { - if (!too_long) { - *ptr = 0; - return buf; - } - // Reset and start with the next line - too_long = 0; - *lineno = *lineno + 1; - } else { - // If a line is too long skip it. - // Only output 1 warning - if (!too_long) - audit_msg(LOG_ERR, - "Skipping line %d in %s: too long", - *lineno, file); - too_long = 1; - } - } - return NULL; -} - -static int nv_split(char *buf, struct nv_pair *nv) -{ - /* Get the name part */ - char *ptr; - - nv->name = NULL; - nv->value = NULL; - nv->option = NULL; - ptr = audit_strsplit(buf); - if (ptr == NULL) - return 0; /* If there's nothing, go to next line */ - if (ptr[0] == '#') - return 0; /* If there's a comment, go to next line */ - nv->name = ptr; - - /* Check for a '=' */ - ptr = audit_strsplit(NULL); - if (ptr == NULL) - return 1; - if (strcmp(ptr, "=") != 0) - return 2; - - /* get the value */ - ptr = audit_strsplit(NULL); - if (ptr == NULL) - return 1; - nv->value = ptr; - - /* See if there's an option */ - ptr = audit_strsplit(NULL); - if (ptr) { - nv->option = ptr; - - /* Make sure there's nothing else */ - ptr = audit_strsplit(NULL); - if (ptr) - return 1; - } - - /* Everything is OK */ - return 0; -} - -static const struct kw_pair *kw_lookup(const char *val) -{ - int i = 0; - while (keywords[i].name != NULL) { - if (strcasecmp(keywords[i].name, val) == 0) - break; - i++; - } - return &keywords[i]; -} - -static int log_file_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - char *dir = NULL, *tdir; - DIR *d; - int fd, mode; - struct stat buf; - - audit_msg(LOG_DEBUG, "log_file_parser called with: %s", nv->value); - - /* get dir from name. */ - tdir = strdup(nv->value); - if (tdir) - dir = dirname(tdir); - if (dir == NULL || strlen(dir) < 4) { // '/var' is shortest dirname - audit_msg(LOG_ERR, - "The directory name: %s is too short - line %d", - dir, line); - free((void *)tdir); - return 1; - } - - /* verify the directory path exists */ - d = opendir(dir); - if (d == NULL) { - audit_msg(LOG_ERR, "Could not open dir %s (%s)", dir, - strerror(errno)); - free((void *)tdir); - return 1; - } - free((void *)tdir); - closedir(d); - - /* if the file exists, see that its regular, owned by root, - * and not world anything */ - if (log_test == TEST_AUDITD) - mode = O_APPEND; - else - mode = O_RDONLY; - - fd = open(nv->value, mode); - if (fd < 0) { - if (errno == ENOENT) { - fd = create_log_file(nv->value); - if (fd < 0) - return 1; - } else { - audit_msg(LOG_ERR, "Unable to open %s (%s)", nv->value, - strerror(errno)); - return 1; - } - } - if (fstat(fd, &buf) < 0) { - audit_msg(LOG_ERR, "Unable to stat %s (%s)", - nv->value, strerror(errno)); - close(fd); - return 1; - } - close(fd); - if (!S_ISREG(buf.st_mode)) { - audit_msg(LOG_ERR, "%s is not a regular file", nv->value); - return 1; - } - if (buf.st_uid != 0) { - audit_msg(LOG_ERR, "%s is not owned by root", nv->value); - return 1; - } - if ( (buf.st_mode & (S_IXUSR|S_IWGRP|S_IXGRP|S_IRWXO)) ) { - audit_msg(LOG_ERR, "%s permissions should be 0600 or 0640", - nv->value); - return 1; - } - if ( !(buf.st_mode & S_IWUSR) ) { - audit_msg(LOG_ERR, "audit log is not writable by owner"); - return 1; - } - - free((void *)config->log_file); - config->log_file = strdup(nv->value); - if (config->log_file == NULL) - return 1; - return 0; -} - -static int num_logs_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "num_logs_parser called with: %s", nv->value); - - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(LOG_ERR, - "Value %s should only be numbers - line %d", - nv->value, line); - return 1; - } - } - - /* convert to unsigned long */ - errno = 0; - i = strtoul(nv->value, NULL, 10); - if (errno) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - if (i > 99) { - audit_msg(LOG_ERR, "num_logs must be 99 or less"); - return 1; - } - config->num_logs = i; - return 0; -} - -static int qos_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "qos_parser called with: %s", nv->value); - for (i=0; qos_options[i].name != NULL; i++) { - if (strcasecmp(nv->value, qos_options[i].name) == 0) { - config->qos = qos_options[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int dispatch_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - char *dir = NULL, *tdir; - int fd; - struct stat buf; - - audit_msg(LOG_DEBUG, "dispatch_parser called with: %s", nv->value); - if (nv->value == NULL) { - config->dispatcher = NULL; - return 0; - } - - /* get dir from name. */ - tdir = strdup(nv->value); - if (tdir) - dir = dirname(tdir); - if (dir == NULL || strlen(dir) < 4) { // '/var' is shortest dirname - audit_msg(LOG_ERR, - "The directory name: %s is too short - line %d", - dir, line); - free(tdir); - return 1; - } - - free((void *)tdir); - - /* Bypass the perms check if group is not root since - * this will fail under normal circumstances */ - if ((config->log_group != 0 && getuid() != 0) || - (log_test == TEST_SEARCH)) - goto bypass; - - /* if the file exists, see that its regular, owned by root, - * and not world anything */ - fd = open(nv->value, O_RDONLY); - if (fd < 0) { - audit_msg(LOG_ERR, "Unable to open %s (%s)", nv->value, - strerror(errno)); - return 1; - } - if (fstat(fd, &buf) < 0) { - audit_msg(LOG_ERR, "Unable to stat %s (%s)", nv->value, - strerror(errno)); - close(fd); - return 1; - } - close(fd); - if (!S_ISREG(buf.st_mode)) { - audit_msg(LOG_ERR, "%s is not a regular file", nv->value); - return 1; - } - if (buf.st_uid != 0) { - audit_msg(LOG_ERR, "%s is not owned by root", nv->value); - return 1; - } - if ((buf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != - (S_IRWXU|S_IRGRP|S_IXGRP) && - (buf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != - (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) { - audit_msg(LOG_ERR, "%s permissions should be 0750 or 0755", - nv->value); - return 1; - } -bypass: - free((void *)config->dispatcher); - config->dispatcher = strdup(nv->value); - if (config->dispatcher == NULL) - return 1; - return 0; -} - -static int name_format_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "name_format_parser called with: %s", nv->value); - for (i=0; node_name_formats[i].name != NULL; i++) { - if (strcasecmp(nv->value, node_name_formats[i].name) == 0) { - config->node_name_format = node_name_formats[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int name_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - audit_msg(LOG_DEBUG, "name_parser called with: %s", nv->value); - if (nv->value == NULL) - config->node_name = NULL; - else - config->node_name = strdup(nv->value); - return 0; -} - -static int max_log_size_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "max_log_size_parser called with: %s", nv->value); - - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(LOG_ERR, - "Value %s should only be numbers - line %d", - nv->value, line); - return 1; - } - } - - /* convert to unsigned long */ - errno = 0; - i = strtoul(nv->value, NULL, 10); - if (errno) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - config->max_log_size = i; - return 0; -} - -static int max_log_size_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "max_log_size_action_parser called with: %s", - nv->value); - for (i=0; size_actions[i].name != NULL; i++) { - if (strcasecmp(nv->value, size_actions[i].name) == 0) { - config->max_log_size_action = size_actions[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int log_format_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "log_format_parser called with: %s", nv->value); - for (i=0; log_formats[i].name != NULL; i++) { - if (strcasecmp(nv->value, log_formats[i].name) == 0) { - config->log_format = log_formats[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int log_group_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - gid_t gid = 0; - - audit_msg(LOG_DEBUG, "log_group_parser called with: %s", - nv->value); - if (isdigit(nv->value[0])) { - errno = 0; - gid = strtoul(nv->value,NULL,10); - if (errno) { - audit_msg(LOG_ERR, - "Numeric group ID conversion error (%s) for %s - line %d\n", - strerror(errno), nv->value, line); - return 1; - } - } else { - struct group *gr ; - - gr = getgrnam(nv->value); - if (gr == NULL) { - audit_msg(LOG_ERR, - "Group ID is non-numeric and unknown (%s) - line %d\n", - nv->value, line); - return 1; - } - gid = gr->gr_gid; - } - config->log_group = gid; - return 0; -} - -static int flush_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "flush_parser called with: %s", nv->value); - for (i=0; flush_techniques[i].name != NULL; i++) { - if (strcasecmp(nv->value, flush_techniques[i].name) == 0) { - config->flush = flush_techniques[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int freq_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "freq_parser called with: %s", nv->value); - - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(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) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - /* Check its range */ - if (i > INT_MAX) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too large - line %d", - nv->value, line); - return 1; - } - config->freq = (unsigned int)i; - return 0; -} - -static int space_left_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "space_left_parser called with: %s", nv->value); - - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(LOG_ERR, - "Value %s should only be numbers - line %d", - nv->value, line); - return 1; - } - } - - /* convert to unsigned long */ - errno = 0; - i = strtoul(nv->value, NULL, 10); - if (errno) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - config->space_left = i; - return 0; -} - -static int check_exe_name(const char *val, int line) -{ - struct stat buf; - - if (val == NULL) { - audit_msg(LOG_ERR, "Executable path needed for line %d", line); - return -1; - } - - if (*val != '/') { - audit_msg(LOG_ERR, "Absolute path needed for %s - line %d", - val, line); - return -1; - } - - if (stat(val, &buf) < 0) { - audit_msg(LOG_ERR, "Unable to stat %s (%s) - line %d", val, - strerror(errno), line); - return -1; - } - if (!S_ISREG(buf.st_mode)) { - audit_msg(LOG_ERR, "%s is not a regular file - line %d", val, - line); - return -1; - } - if (buf.st_uid != 0) { - audit_msg(LOG_ERR, "%s is not owned by root - line %d", val, - line); - return -1; - } - if ((buf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != - (S_IRWXU|S_IRGRP|S_IXGRP) && - (buf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != - (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) { - audit_msg(LOG_ERR, - "%s permissions should be 0750 or 0755 - line %d", - val, line); - return -1; - } - return 0; -} - -static int space_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "space_action_parser called with: %s", nv->value); - for (i=0; failure_actions[i].name != NULL; i++) { - if (strcasecmp(nv->value, failure_actions[i].name) == 0) { - if (failure_actions[i].option == FA_EMAIL) { - if (access(email_command, X_OK)) { - audit_msg(LOG_ERR, - "Email option is specified but %s doesn't seem executable.", - email_command); - } - } else if (failure_actions[i].option == FA_EXEC) { - if (check_exe_name(nv->option, line)) - return 1; - config->space_left_exe = strdup(nv->option); - } - config->space_left_action = failure_actions[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -// returns 0 if OK, 1 on temp error, 2 on permanent error -static int validate_email(const char *acct) -{ - int i, len; - char *ptr1; - - if (acct == NULL) - return 2; - - len = strlen(acct); - if (len < 2) { - audit_msg(LOG_ERR, - "email: %s is too short, expecting at least 2 characters", - acct); - return 2; - } - - // look for illegal char - for (i=0; i<len; i++) { - if (! (isalnum(acct[i]) || (acct[i] == '@') || - (acct[i]=='.') || (acct[i]=='-') || - (acct[i] == '_')) ) { - audit_msg(LOG_ERR, "email: %s has illegal character", - acct); - return 2; - } - } - - if ((ptr1 = strchr(acct, '@'))) { - char *ptr2; - struct hostent *t_addr; - - ptr2 = strrchr(acct, '.'); // get last dot - sb after @ - if ((ptr2 == NULL) || (ptr1 > ptr2)) { - audit_msg(LOG_ERR, "email: %s should have . after @", - acct); - return 2; - } - - t_addr = gethostbyname(ptr1+1); - if (t_addr == 0) { - if ((h_errno == HOST_NOT_FOUND) || - (h_errno == NO_RECOVERY)) { - audit_msg(LOG_ERR, - "validate_email: failed looking up host for %s", - ptr1+1); - // FIXME: gethostbyname is having trouble - // telling when we have a temporary vs permanent - // dns failure. So, for now, treat all as temp - return 1; - } - else if (h_errno == TRY_AGAIN) - audit_msg(LOG_DEBUG, - "validate_email: temporary failure looking up domain for %s", - ptr1+1); - return 1; - } - } - return 0; -} - -static int action_mail_acct_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - char *tmail; - - audit_msg(LOG_DEBUG, "action_mail_acct_parser called with: %s", - nv->value); - tmail = strdup(nv->value); - if (tmail == NULL) - return 1; - - if (validate_email(tmail) > 1) { - free(tmail); - return 1; - } - - - if (config->action_mail_acct) - free((void *)config->action_mail_acct); - config->action_mail_acct = tmail; - return 0; -} - -static int admin_space_left_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "admin_space_left_parser called with: %s", - nv->value); - - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(LOG_ERR, - "Value %s should only be numbers - line %d", - nv->value, line); - return 1; - } - } - - /* convert to unsigned long */ - errno = 0; - i = strtoul(nv->value, NULL, 10); - if (errno) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - config->admin_space_left = i; - return 0; -} - -static int admin_space_left_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "admin_space_left_action_parser called with: %s", - nv->value); - for (i=0; failure_actions[i].name != NULL; i++) { - if (strcasecmp(nv->value, failure_actions[i].name) == 0) { - if (failure_actions[i].option == FA_EMAIL) { - if (access(email_command, X_OK)) { - audit_msg(LOG_ERR, - "Email option is specified but %s doesn't seem executable.", - email_command); - } - } else if (failure_actions[i].option == FA_EXEC) { - if (check_exe_name(nv->option, line)) - return 1; - config->admin_space_left_exe = - strdup(nv->option); - } - config->admin_space_left_action = - failure_actions[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int disk_full_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "disk_full_action_parser called with: %s", - nv->value); - for (i=0; failure_actions[i].name != NULL; i++) { - if (strcasecmp(nv->value, failure_actions[i].name) == 0) { - if (failure_actions[i].option == FA_EMAIL) { - audit_msg(LOG_ERR, - "Illegal option %s for disk_full_action - line %d", - nv->value, line); - return 1; - } else if (failure_actions[i].option == FA_EXEC) { - if (check_exe_name(nv->option, line)) - return 1; - config->disk_full_exe = strdup(nv->option); - } - config->disk_full_action = failure_actions[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int disk_error_action_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - int i; - - audit_msg(LOG_DEBUG, "disk_error_action_parser called with: %s", - nv->value); - for (i=0; failure_actions[i].name != NULL; i++) { - if (strcasecmp(nv->value, failure_actions[i].name) == 0) { - if (failure_actions[i].option == FA_EMAIL || - failure_actions[i].option == FA_ROTATE) { - audit_msg(LOG_ERR, - "Illegal option %s for disk_error_action - line %d", - nv->value, line); - return 1; - } else if (failure_actions[i].option == FA_EXEC) { - if (check_exe_name(nv->option, line)) - return 1; - config->disk_error_exe = strdup(nv->option); - } - config->disk_error_action = failure_actions[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int priority_boost_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "priority_boost_parser called with: %s", - nv->value); - - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(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) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - /* Check its range */ - if (i > INT_MAX) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too large - line %d", - nv->value, line); - return 1; - } - config->priority_boost = (unsigned int)i; - return 0; -} - -static int tcp_listen_port_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "tcp_listen_port_parser called with: %s", - nv->value); - -#ifndef USE_LISTENER - audit_msg(LOG_DEBUG, - "Listener support is not enabled, ignoring value at line %d", - line); - return 0; -#else - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(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) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - /* Check its range */ - if (i > TCP_PORT_MAX) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too large - line %d", - nv->value, line); - return 1; - } - if (i < 1) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too small - line %d", - nv->value, line); - return 1; - } - config->tcp_listen_port = (unsigned int)i; - return 0; -#endif -} - -static int tcp_listen_queue_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "tcp_listen_queue_parser called with: %s", - nv->value); - -#ifndef USE_LISTENER - audit_msg(LOG_DEBUG, - "Listener support is not enabled, ignoring value at line %d", - line); - return 0; -#else - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(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) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - /* Check its range. While this value is technically - unlimited, it's limited by the kernel, and we limit it here - for sanity. */ - if (i > TCP_PORT_MAX) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too large - line %d", - nv->value, line); - return 1; - } - if (i < 1) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too small - line %d", - nv->value, line); - return 1; - } - config->tcp_listen_queue = (unsigned int)i; - return 0; -#endif -} - - -static int tcp_max_per_addr_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "tcp_max_per_addr_parser called with: %s", - nv->value); - -#ifndef USE_LISTENER - audit_msg(LOG_DEBUG, - "Listener support is not enabled, ignoring value at line %d", - line); - return 0; -#else - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(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) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - /* Check its range. While this value is technically - unlimited, it's limited by the kernel, and we limit it here - for sanity. */ - if (i > 1024) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too large - line %d", - nv->value, line); - return 1; - } - if (i < 1) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too small - line %d", - nv->value, line); - return 1; - } - config->tcp_max_per_addr = (unsigned int)i; - return 0; -#endif -} - -static int use_libwrap_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - unsigned long i; - - audit_msg(LOG_DEBUG, "use_libwrap_parser called with: %s", - nv->value); - - for (i=0; yes_no_values[i].name != NULL; i++) { - if (strcasecmp(nv->value, yes_no_values[i].name) == 0) { - config->use_libwrap = yes_no_values[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -} - -static int tcp_client_ports_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i, minv, maxv; - const char *saw_dash = NULL; - - audit_msg(LOG_DEBUG, "tcp_listen_queue_parser called with: %s", - nv->value); - -#ifndef USE_LISTENER - audit_msg(LOG_DEBUG, - "Listener support is not enabled, ignoring value at line %d", - line); - return 0; -#else - /* check that all chars are numbers, with an optional inclusive '-'. */ - for (i=0; ptr[i]; i++) { - if (i > 0 && ptr[i] == '-' && ptr[i+1] != '\0') { - saw_dash = ptr + i; - continue; - } - if (!isdigit(ptr[i])) { - audit_msg(LOG_ERR, - "Value %s should only be numbers, or " - "two numbers separated by a dash - line %d", - nv->value, line); - return 1; - } - } - for (; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(LOG_ERR, - "Value %s should only be numbers, or " - "two numbers separated by a dash - line %d", - nv->value, line); - return 1; - } - } - - /* convert to unsigned int */ - errno = 0; - maxv = minv = strtoul(nv->value, NULL, 10); - if (errno) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - if (saw_dash) { - maxv = strtoul(saw_dash + 1, NULL, 10); - if (errno) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - } - /* Check their ranges. */ - if (minv > TCP_PORT_MAX) { - audit_msg(LOG_ERR, - "Error - converted number (%ld) is too large - line %d", - minv, line); - return 1; - } - if (maxv > TCP_PORT_MAX) { - audit_msg(LOG_ERR, - "Error - converted number (%ld) is too large - line %d", - maxv, line); - return 1; - } - if (minv > maxv) { - audit_msg(LOG_ERR, - "Error - converted range (%ld-%ld) is reversed - line %d", - minv, maxv, line); - return 1; - } - config->tcp_client_min_port = (unsigned int)minv; - config->tcp_client_max_port = (unsigned int)maxv; - return 0; -#endif -} - -static int tcp_client_max_idle_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - const char *ptr = nv->value; - unsigned long i; - - audit_msg(LOG_DEBUG, "tcp_client_max_idle_parser called with: %s", - nv->value); - -#ifndef USE_LISTENER - audit_msg(LOG_DEBUG, - "Listener support is not enabled, ignoring value at line %d", - line); - return 0; -#else - /* check that all chars are numbers */ - for (i=0; ptr[i]; i++) { - if (!isdigit(ptr[i])) { - audit_msg(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) { - audit_msg(LOG_ERR, - "Error converting string to a number (%s) - line %d", - strerror(errno), line); - return 1; - } - /* Check its range. While this value is technically - unlimited, it's limited by the kernel, and we limit it here - for sanity. */ - if (i > INT_MAX) { - audit_msg(LOG_ERR, - "Error - converted number (%s) is too large - line %d", - nv->value, line); - return 1; - } - config->tcp_client_max_idle = (unsigned int)i; - return 0; -#endif -} - -static int enable_krb5_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - audit_msg(LOG_DEBUG, "enable_krb5_parser called with: %s", - nv->value); - -#ifndef USE_GSSAPI - audit_msg(LOG_DEBUG, - "GSSAPI support is not enabled, ignoring value at line %d", - line); - return 0; -#else - unsigned long i; - - for (i=0; yes_no_values[i].name != NULL; i++) { - if (strcasecmp(nv->value, yes_no_values[i].name) == 0) { - config->enable_krb5 = yes_no_values[i].option; - return 0; - } - } - audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line); - return 1; -#endif -} - -static int krb5_principal_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - audit_msg(LOG_DEBUG,"krb5_principal_parser called with: %s",nv->value); -#ifndef USE_GSSAPI - audit_msg(LOG_DEBUG, - "GSSAPI support is not enabled, ignoring value at line %d", - line); -#else - config->krb5_principal = strdup(nv->value); -#endif - return 0; -} - -static int krb5_key_file_parser(struct nv_pair *nv, int line, - struct daemon_conf *config) -{ - audit_msg(LOG_DEBUG, "krb5_key_file_parser called with: %s", nv->value); -#ifndef USE_GSSAPI - audit_msg(LOG_DEBUG, - "GSSAPI support is not enabled, ignoring value at line %d", - line); -#else - config->krb5_key_file = strdup(nv->value); -#endif - return 0; -} - -/* - * This function is where we do the integrated check of the audit config - * options. At this point, all fields have been read. Returns 0 if no - * problems and 1 if problems detected. - */ -static int sanity_check(struct daemon_conf *config) -{ - /* Error checking */ - if (config->space_left <= config->admin_space_left) { - audit_msg(LOG_ERR, - "Error - space_left(%lu) must be larger than admin_space_left(%lu)", - config->space_left, config->admin_space_left); - return 1; - } - if (config->flush == FT_INCREMENTAL && config->freq == 0) { - audit_msg(LOG_ERR, - "Error - incremental flushing chosen, but 0 selected for freq"); - return 1; - } - /* Warnings */ - if (config->flush > FT_INCREMENTAL && config->freq != 0) { - audit_msg(LOG_WARNING, - "Warning - freq is non-zero and incremental flushing not selected."); - } - return 0; -} - -const char *audit_lookup_format(int fmt) -{ - int i; - - for (i=0; log_formats[i].name != NULL; i++) { - if (log_formats[i].option == fmt) - return log_formats[i].name; - } - return NULL; -} - -int create_log_file(const char *val) -{ - int fd; - - umask(S_IRWXO); - fd = open(val, O_CREAT|O_EXCL|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP); - if (fd < 0) - audit_msg(LOG_ERR, "Unable to create %s (%s)", val, - strerror(errno)); - return fd; -} - -void free_config(struct daemon_conf *config) -{ - free((void *)config->sender_ctx); - free((void *)config->log_file); - free((void *)config->dispatcher); - free((void *)config->node_name); - free((void *)config->action_mail_acct); - free((void *)config->space_left_exe); - free((void *)config->admin_space_left_exe); - free((void *)config->disk_full_exe); - free((void *)config->disk_error_exe); - free((void *)config->krb5_principal); - free((void *)config->krb5_key_file); -} - -int resolve_node(struct daemon_conf *config) -{ - int rc = 0; - char tmp_name[255]; - - /* Get the host name representation */ - switch (config->node_name_format) - { - case N_NONE: - break; - case N_HOSTNAME: - if (gethostname(tmp_name, sizeof(tmp_name))) { - audit_msg(LOG_ERR, - "Unable to get machine name"); - rc = -1; - } else - config->node_name = strdup(tmp_name); - break; - case N_USER: - if (config->node_name == NULL) { - audit_msg(LOG_ERR, "User defined name missing"); - rc = -1; - } - break; - case N_FQD: - if (gethostname(tmp_name, sizeof(tmp_name))) { - audit_msg(LOG_ERR, - "Unable to get machine name"); - rc = -1; - } else { - int rc2; - struct addrinfo *ai; - struct addrinfo hints; - - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME; - hints.ai_socktype = SOCK_STREAM; - - rc2 = getaddrinfo(tmp_name, NULL, &hints, &ai); - if (rc2 != 0) { - audit_msg(LOG_ERR, - "Cannot resolve hostname %s (%s)", - tmp_name, gai_strerror(rc)); - rc = -1; - break; - } - config->node_name = strdup(ai->ai_canonname); - freeaddrinfo(ai); - } - break; - case N_NUMERIC: - if (gethostname(tmp_name, sizeof(tmp_name))) { - audit_msg(LOG_ERR, - "Unable to get machine name"); - rc = -1; - } else { - int rc2; - struct addrinfo *ai; - struct addrinfo hints; - - audit_msg(LOG_DEBUG, - "Resolving numeric address for %s", - tmp_name); - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; - hints.ai_socktype = SOCK_STREAM; - - rc2 = getaddrinfo(tmp_name, NULL, &hints, &ai); - if (rc2) { - audit_msg(LOG_ERR, - "Cannot resolve hostname %s (%s)", - tmp_name, gai_strerror(rc2)); - rc = -1; - break; - } - inet_ntop(ai->ai_family, - ai->ai_family == AF_INET ? - (void *) &((struct sockaddr_in *)ai->ai_addr)->sin_addr : - (void *) &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, - tmp_name, INET6_ADDRSTRLEN); - freeaddrinfo(ai); - config->node_name = strdup(tmp_name); - } - break; - } - if (rc == 0 && config->node_name) - audit_msg(LOG_DEBUG, "Resolved node name: %s", - config->node_name); - return rc; -} - diff --git a/framework/src/audit/src/auditd-config.h b/framework/src/audit/src/auditd-config.h deleted file mode 100644 index 5a3eb6bb..00000000 --- a/framework/src/audit/src/auditd-config.h +++ /dev/null @@ -1,100 +0,0 @@ -/* auditd-config.h -- - * Copyright 2004-2009,2014 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#ifndef AUDITD_CONFIG_H -#define AUDITD_CONFIG_H - -#include "libaudit.h" -#include <grp.h> -#define CONFIG_FILE "/etc/audit/auditd.conf" -#define MEGABYTE 1048576UL - -typedef enum { D_FOREGROUND, D_BACKGROUND } daemon_t; -typedef enum { LF_RAW, LF_NOLOG } logging_formats; -typedef enum { FT_NONE, FT_INCREMENTAL, FT_DATA, FT_SYNC } flush_technique; -typedef enum { FA_IGNORE, FA_SYSLOG, FA_ROTATE, FA_EMAIL, FA_EXEC, FA_SUSPEND, - FA_SINGLE, FA_HALT } failure_action_t; -typedef enum { SZ_IGNORE, SZ_SYSLOG, SZ_SUSPEND, SZ_ROTATE, - SZ_KEEP_LOGS } size_action; -typedef enum { QOS_NON_BLOCKING, QOS_BLOCKING } qos_t; -typedef enum { TEST_AUDITD, TEST_SEARCH } log_test_t; -typedef enum { N_NONE, N_HOSTNAME, N_FQD, N_NUMERIC, N_USER } node_t; - -struct daemon_conf -{ - daemon_t daemonize; - qos_t qos; /* use blocking/non-blocking sockets */ - uid_t sender_uid; /* the uid for sender of sighup */ - pid_t sender_pid; /* the pid for sender of sighup */ - const char *sender_ctx; /* the context for the sender of sighup */ - const char *log_file; - logging_formats log_format; - gid_t log_group; - unsigned int priority_boost; - flush_technique flush; - unsigned int freq; - unsigned int num_logs; - const char *dispatcher; - node_t node_name_format; - const char *node_name; - unsigned long max_log_size; - size_action max_log_size_action; - unsigned long space_left; - failure_action_t space_left_action; - const char *space_left_exe; - const char *action_mail_acct; - unsigned long admin_space_left; - failure_action_t admin_space_left_action; - const char *admin_space_left_exe; - failure_action_t disk_full_action; - const char *disk_full_exe; - failure_action_t disk_error_action; - const char *disk_error_exe; - unsigned long tcp_listen_port; - unsigned long tcp_listen_queue; - unsigned long tcp_max_per_addr; - int use_libwrap; - unsigned long tcp_client_min_port; - unsigned long tcp_client_max_port; - unsigned long tcp_client_max_idle; - int enable_krb5; - const char *krb5_principal; - const char *krb5_key_file; -}; - -void set_allow_links(int allow); -int load_config(struct daemon_conf *config, log_test_t lt); -void clear_config(struct daemon_conf *config); -const char *audit_lookup_format(int fmt); -int create_log_file(const char *val); -int resolve_node(struct daemon_conf *config); - -void init_config_manager(void); -#ifdef AUDITD_EVENT_H -int start_config_manager(struct auditd_reply_list *rep); -#endif -void shutdown_config(void); -void free_config(struct daemon_conf *config); - -#endif - diff --git a/framework/src/audit/src/auditd-dispatch.c b/framework/src/audit/src/auditd-dispatch.c deleted file mode 100644 index 02681f03..00000000 --- a/framework/src/audit/src/auditd-dispatch.c +++ /dev/null @@ -1,213 +0,0 @@ -/* auditd-dispatch.c -- - * Copyright 2005-07,2013 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * Junji Kanemaru <junji.kanemaru@linuon.com> - */ - -#include "config.h" -#include <unistd.h> -#include <sys/uio.h> -#include <fcntl.h> -#include <signal.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include "libaudit.h" -#include "private.h" -#include "auditd-dispatch.h" - -/* This is the communications channel between auditd & the dispatcher */ -static int disp_pipe[2] = {-1, -1}; -static pid_t pid = 0; -static int n_errs = 0; -#define REPORT_LIMIT 10 - -int dispatcher_pid(void) -{ - return pid; -} - -void dispatcher_reaped(void) -{ - audit_msg(LOG_INFO, "dispatcher %d reaped\n", pid); - pid = 0; - shutdown_dispatcher(); -} - -/* set_flags: to set flags to file desc */ -static int set_flags(int fn, int flags) -{ - int fl; - - if ((fl = fcntl(fn, F_GETFL, 0)) < 0) { - audit_msg(LOG_ERR, "fcntl failed. Cannot get flags (%s)\n", - strerror(errno)); - return fl; - } - - fl |= flags; - - return fcntl(fn, F_SETFL, fl); -} - -/* This function returns 1 on error & 0 on success */ -int init_dispatcher(const struct daemon_conf *config) -{ - struct sigaction sa; - - if (config->dispatcher == NULL) - return 0; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, disp_pipe)) { - audit_msg(LOG_ERR, "Failed creating disp_pipe"); - return 1; - } - - /* Make both disp_pipe non-blocking */ - if (config->qos == QOS_NON_BLOCKING) { - if (set_flags(disp_pipe[0], O_NONBLOCK) < 0 || - set_flags(disp_pipe[1], O_NONBLOCK) < 0) { - audit_msg(LOG_ERR, "Failed to set O_NONBLOCK flag"); - return 1; - } - } - - // do the fork - pid = fork(); - switch(pid) { - case 0: // child - dup2(disp_pipe[0], 0); - close(disp_pipe[0]); - close(disp_pipe[1]); - sigfillset (&sa.sa_mask); - sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); - setsid(); - execl(config->dispatcher, config->dispatcher, NULL); - audit_msg(LOG_ERR, "exec() failed"); - exit(1); - break; - case -1: // error - return 1; - break; - default: // parent - close(disp_pipe[0]); - disp_pipe[0] = -1; - /* Avoid leaking this */ - if (fcntl(disp_pipe[1], F_SETFD, FD_CLOEXEC) < 0) { - audit_msg(LOG_ERR, - "Failed to set FD_CLOEXEC flag"); - return 1; - } - audit_msg(LOG_INFO, "Started dispatcher: %s pid: %u", - config->dispatcher, pid); - break; - } - - return 0; -} - -void shutdown_dispatcher(void) -{ - // kill child - if (pid) - kill(pid, SIGTERM); - // wait for term - // if not in time, send sigkill - pid = 0; - - // cleanup comm pipe - if (disp_pipe[0] >= 0) { - close(disp_pipe[0]); - disp_pipe[0] = -1; - } - if (disp_pipe[1] >= 0) { - close(disp_pipe[1]); - disp_pipe[1] = -1; - } -} - -void reconfigure_dispatcher(const struct daemon_conf *config) -{ - // signal child or start it so it can see if config changed - if (pid) - kill(pid, SIGHUP); - else - init_dispatcher(config); -} - -/* Returns -1 on err, 0 on success, and 1 if eagain occurred and not an err */ -int dispatch_event(const struct audit_reply *rep, int is_err) -{ - int rc, count = 0; - struct iovec vec[2]; - struct audit_dispatcher_header hdr; - - if (disp_pipe[1] == -1) - return 0; - - // Don't send reconfig or rotate as they are purely internal to daemon - if (rep->type == AUDIT_DAEMON_RECONFIG || - rep->type == AUDIT_DAEMON_ROTATE) - return 0; - - hdr.ver = AUDISP_PROTOCOL_VER; /* Hard-coded to current protocol */ - hdr.hlen = sizeof(struct audit_dispatcher_header); - hdr.type = rep->type; - hdr.size = rep->len; - - vec[0].iov_base = (void*)&hdr; - vec[0].iov_len = sizeof(hdr); - vec[1].iov_base = (void*)rep->message; - vec[1].iov_len = rep->len; - - do { - rc = writev(disp_pipe[1], vec, 2); - } while (rc < 0 && errno == EAGAIN && count++ < 8); - - // close pipe if no child or peer has been lost - if (rc <= 0) { - if (errno == EPIPE) { - shutdown_dispatcher(); - n_errs = 0; - } else if (errno == EAGAIN && !is_err) { - return 1; - } else { - if (n_errs <= REPORT_LIMIT) { - audit_msg(LOG_ERR, - "dispatch err (%s) event lost", - errno == EAGAIN ? "pipe full" : - strerror(errno)); - n_errs++; - } - if (n_errs == REPORT_LIMIT) { - audit_msg(LOG_ERR, - "dispatch error reporting limit" - " reached - ending report" - " notification."); - n_errs++; - } - return -1; - } - } else - n_errs = 0; - return 0; -} - diff --git a/framework/src/audit/src/auditd-dispatch.h b/framework/src/audit/src/auditd-dispatch.h deleted file mode 100644 index 25d32352..00000000 --- a/framework/src/audit/src/auditd-dispatch.h +++ /dev/null @@ -1,37 +0,0 @@ -/* auditd-dispatch.h -- - * Copyright 2005,2007,2013 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#ifndef AUDITD_DISPATCH_H -#define AUDITD_DISPATCH_H - -#include "auditd-config.h" - -int dispatcher_pid(void); -void dispatcher_reaped(void); -int init_dispatcher(const struct daemon_conf *config); -void shutdown_dispatcher(void); -void reconfigure_dispatcher(const struct daemon_conf *config); -int dispatch_event(const struct audit_reply *rep, int is_err); - -#endif - diff --git a/framework/src/audit/src/auditd-event.c b/framework/src/audit/src/auditd-event.c deleted file mode 100644 index ed0272e2..00000000 --- a/framework/src/audit/src/auditd-event.c +++ /dev/null @@ -1,1407 +0,0 @@ -/* auditd-event.c -- - * Copyright 2004-08,2011,2013 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#include "config.h" -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <pthread.h> -#include <signal.h> -#include <fcntl.h> /* O_NOFOLLOW needs gnu defined */ -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <sys/time.h> -#include <sys/vfs.h> -#include <limits.h> /* POSIX_HOST_NAME_MAX */ -#include "auditd-event.h" -#include "auditd-dispatch.h" -#include "auditd-listen.h" -#include "libaudit.h" -#include "private.h" - -/* This is defined in auditd.c */ -extern volatile int stop; - -struct auditd_consumer_data { - struct daemon_conf *config; - pthread_mutex_t queue_lock; - pthread_cond_t queue_nonempty; - struct auditd_reply_list *head; - struct auditd_reply_list *tail; - int log_fd; - FILE *log_file; -}; - -/* Local function prototypes */ -static void *event_thread_main(void *arg); -static void handle_event(struct auditd_consumer_data *data); -static void write_to_log(const char *buf, struct auditd_consumer_data *data); -static void check_log_file_size(struct auditd_consumer_data *data); -static void check_space_left(int lfd, struct auditd_consumer_data *data); -static void do_space_left_action(struct auditd_consumer_data *data, int admin); -static void do_disk_full_action(struct auditd_consumer_data *data); -static void do_disk_error_action(const char *func, struct daemon_conf *config, - int err); -static void check_excess_logs(struct auditd_consumer_data *data); -static void rotate_logs_now(struct auditd_consumer_data *data); -static void rotate_logs(struct auditd_consumer_data *data, - unsigned int num_logs); -static void shift_logs(struct auditd_consumer_data *data); -static int open_audit_log(struct auditd_consumer_data *data); -static void change_runlevel(const char *level); -static void safe_exec(const char *exe); -static char *format_raw(const struct audit_reply *rep, - struct daemon_conf *config); -static void reconfigure(struct auditd_consumer_data *data); - - -/* Local Data */ -static struct auditd_consumer_data consumer_data; -static pthread_t event_thread; -static unsigned int disk_err_warning = 0; -static int fs_space_warning = 0; -static int fs_admin_space_warning = 0; -static int fs_space_left = 1; -static int logging_suspended = 0; -static const char *SINGLE = "1"; -static const char *HALT = "0"; -static char *format_buf = NULL; -static off_t log_size = 0; - - -void shutdown_events(void) -{ - /* Give it 5 seconds to clear the queue */ - alarm(5); - pthread_join(event_thread, NULL); - free((void *)format_buf); - fclose(consumer_data.log_file); -} - -int init_event(struct daemon_conf *config) -{ - /* Store the netlink descriptor and config info away */ - consumer_data.config = config; - consumer_data.log_fd = -1; - - /* Setup IPC mechanisms */ - pthread_mutex_init(&consumer_data.queue_lock, NULL); - pthread_cond_init(&consumer_data.queue_nonempty, NULL); - - /* Reset the queue */ - consumer_data.head = consumer_data.tail = NULL; - - /* Now open the log */ - if (config->daemonize == D_BACKGROUND) { - if (open_audit_log(&consumer_data)) - return 1; - } else { - consumer_data.log_fd = 1; // stdout - consumer_data.log_file = fdopen(consumer_data.log_fd, "a"); - if (consumer_data.log_file == NULL) { - audit_msg(LOG_ERR, - "Error setting up stdout descriptor (%s)", - strerror(errno)); - return 1; - } - /* Set it to line buffering */ - setlinebuf(consumer_data.log_file); - } - - /* Create the worker thread */ - if (pthread_create(&event_thread, NULL, - event_thread_main, &consumer_data) < 0) { - audit_msg(LOG_ERR, "Couldn't create event thread, exiting"); - fclose(consumer_data.log_file); - return 1; - } - - if (config->daemonize == D_BACKGROUND) { - check_log_file_size(&consumer_data); - check_excess_logs(&consumer_data); - check_space_left(consumer_data.log_fd, &consumer_data); - } - format_buf = (char *)malloc(MAX_AUDIT_MESSAGE_LENGTH + - _POSIX_HOST_NAME_MAX); - if (format_buf == NULL) { - audit_msg(LOG_ERR, "No memory for formatting, exiting"); - fclose(consumer_data.log_file); - return 1; - } - return 0; -} - -/* This function takes a malloc'd rep and places it on the queue. The - dequeue'r is responsible for freeing the memory. */ -void enqueue_event(struct auditd_reply_list *rep) -{ - char *buf = NULL; - int len; - - rep->ack_func = 0; - rep->ack_data = 0; - rep->sequence_id = 0; - - if (rep->reply.type != AUDIT_DAEMON_RECONFIG) { - switch (consumer_data.config->log_format) - { - case LF_RAW: - buf = format_raw(&rep->reply, consumer_data.config); - break; - case LF_NOLOG: - // We need the rotate event to get enqueued - if (rep->reply.type != AUDIT_DAEMON_ROTATE ) { - // Internal DAEMON messages should be free'd - if (rep->reply.type >= AUDIT_FIRST_DAEMON && - rep->reply.type <= AUDIT_LAST_DAEMON) - free((void *)rep->reply.message); - free(rep); - return; - } - break; - default: - audit_msg(LOG_ERR, - "Illegal log format detected %d", - consumer_data.config->log_format); - // Internal DAEMON messages should be free'd - if (rep->reply.type >= AUDIT_FIRST_DAEMON && - rep->reply.type <= AUDIT_LAST_DAEMON) - free((void *)rep->reply.message); - free(rep); - return; - } - - if (buf) { - len = strlen(buf); - if (len < MAX_AUDIT_MESSAGE_LENGTH - 1) - memcpy(rep->reply.msg.data, buf, len+1); - else { - // FIXME: is truncation the right thing to do? - memcpy(rep->reply.msg.data, buf, - MAX_AUDIT_MESSAGE_LENGTH-1); - rep->reply.msg.data[MAX_AUDIT_MESSAGE_LENGTH-1] = 0; - } - } - } - - rep->next = NULL; /* new packet goes at end - so zero this */ - - pthread_mutex_lock(&consumer_data.queue_lock); - if (consumer_data.head == NULL) { - consumer_data.head = consumer_data.tail = rep; - pthread_cond_signal(&consumer_data.queue_nonempty); - } else { - /* FIXME: wait for room on the queue */ - - /* OK there's room...add it in */ - consumer_data.tail->next = rep; /* link in at end */ - consumer_data.tail = rep; /* move end to newest */ - } - pthread_mutex_unlock(&consumer_data.queue_lock); -} - -/* This function takes a preformatted message and places it on the - queue. The dequeue'r is responsible for freeing the memory. */ -void enqueue_formatted_event(char *msg, ack_func_type ack_func, void *ack_data, uint32_t sequence_id) -{ - int len; - struct auditd_reply_list *rep; - - rep = (struct auditd_reply_list *) calloc (1, sizeof (*rep)); - if (rep == NULL) { - audit_msg(LOG_ERR, "Cannot allocate audit reply"); - return; - } - - rep->ack_func = ack_func; - rep->ack_data = ack_data; - rep->sequence_id = sequence_id; - - len = strlen (msg); - if (len < MAX_AUDIT_MESSAGE_LENGTH - 1) - memcpy (rep->reply.msg.data, msg, len+1); - else { - /* FIXME: is truncation the right thing to do? */ - memcpy (rep->reply.msg.data, msg, MAX_AUDIT_MESSAGE_LENGTH-1); - rep->reply.msg.data[MAX_AUDIT_MESSAGE_LENGTH-1] = 0; - } - - pthread_mutex_lock(&consumer_data.queue_lock); - if (consumer_data.head == NULL) { - consumer_data.head = consumer_data.tail = rep; - pthread_cond_signal(&consumer_data.queue_nonempty); - } else { - /* FIXME: wait for room on the queue */ - - /* OK there's room...add it in */ - consumer_data.tail->next = rep; /* link in at end */ - consumer_data.tail = rep; /* move end to newest */ - } - pthread_mutex_unlock(&consumer_data.queue_lock); -} - -void resume_logging(void) -{ - logging_suspended = 0; - fs_space_left = 1; - disk_err_warning = 0; - fs_space_warning = 0; - fs_admin_space_warning = 0; - audit_msg(LOG_ERR, "Audit daemon is attempting to resume logging."); -} - -static void *event_thread_main(void *arg) -{ - struct auditd_consumer_data *data = arg; - sigset_t sigs; - - /* This is a worker thread. Don't handle signals. */ - sigemptyset(&sigs); - sigaddset(&sigs, SIGALRM); - sigaddset(&sigs, SIGTERM); - sigaddset(&sigs, SIGHUP); - sigaddset(&sigs, SIGUSR1); - sigaddset(&sigs, SIGUSR2); - pthread_sigmask(SIG_SETMASK, &sigs, NULL); - - while (1) { - struct auditd_reply_list *cur; - int stop_req = 0; -// FIXME: wait for data - pthread_mutex_lock(&data->queue_lock); - while (data->head == NULL) { - pthread_cond_wait(&data->queue_nonempty, - &data->queue_lock); - } -// FIXME: at this point we can use data->head unlocked since it won't change. - handle_event(data); - cur = data->head; -// FIXME: relock at this point - if (data->tail == data->head) - data->tail = NULL; - data->head = data->head->next; - if (data->head == NULL && stop && - ( cur->reply.type == AUDIT_DAEMON_END || - cur->reply.type == AUDIT_DAEMON_ABORT) ) - stop_req = 1; - pthread_mutex_unlock(&data->queue_lock); - - /* Internal DAEMON messages should be free'd */ - if (cur->reply.type >= AUDIT_FIRST_DAEMON && - cur->reply.type <= AUDIT_LAST_DAEMON) { - free((void *)cur->reply.message); - } - free(cur); - if (stop_req) - break; - } - return NULL; -} - - -/* This function takes the newly dequeued event and handles it. */ -static unsigned int count = 0L; -static void handle_event(struct auditd_consumer_data *data) -{ - char *buf = data->head->reply.msg.data; - - if (data->head->reply.type == AUDIT_DAEMON_RECONFIG) { - reconfigure(data); - switch (consumer_data.config->log_format) - { - case LF_RAW: - buf = format_raw(&data->head->reply, consumer_data.config); - break; - case LF_NOLOG: - return; - default: - audit_msg(LOG_ERR, - "Illegal log format detected %d", - consumer_data.config->log_format); - return; - } - } else if (data->head->reply.type == AUDIT_DAEMON_ROTATE) { - rotate_logs_now(data); - if (consumer_data.config->log_format == LF_NOLOG) - return; - } - if (!logging_suspended) { - - write_to_log(buf, data); - - /* See if we need to flush to disk manually */ - if (data->config->flush == FT_INCREMENTAL) { - count++; - if ((count % data->config->freq) == 0) { - int rc; - errno = 0; - do { - rc = fflush(data->log_file); - } while (rc < 0 && errno == EINTR); - if (errno) { - if (errno == ENOSPC && - fs_space_left == 1) { - fs_space_left = 0; - do_disk_full_action(data); - } else - //EIO is only likely failure mode - do_disk_error_action("flush", - data->config, errno); - } - - /* EIO is only likely failure mode */ - if ((data->config->daemonize == D_BACKGROUND)&& - (fsync(data->log_fd) != 0)) { - do_disk_error_action("fsync", - data->config, errno); - } - } - } - } -} - -static void send_ack(struct auditd_consumer_data *data, int ack_type, - const char *msg) -{ - if (data->head->ack_func) { - unsigned char header[AUDIT_RMW_HEADER_SIZE]; - - AUDIT_RMW_PACK_HEADER(header, 0, ack_type, strlen(msg), - data->head->sequence_id); - - data->head->ack_func(data->head->ack_data, header, msg); - } -} - -/* This function writes the given buf to the current log file */ -static void write_to_log(const char *buf, struct auditd_consumer_data *data) -{ - int rc; - FILE *f = data->log_file; - struct daemon_conf *config = data->config; - int ack_type = AUDIT_RMW_TYPE_ACK; - const char *msg = ""; - - /* write it to disk */ - rc = fprintf(f, "%s\n", buf); - - /* error? Handle it */ - if (rc < 0) { - if (errno == ENOSPC) { - ack_type = AUDIT_RMW_TYPE_DISKFULL; - msg = "disk full"; - send_ack(data, ack_type, msg); - if (fs_space_left == 1) { - fs_space_left = 0; - do_disk_full_action(data); - } - } else { - int saved_errno = errno; - ack_type = AUDIT_RMW_TYPE_DISKERROR; - msg = "disk write error"; - send_ack(data, ack_type, msg); - do_disk_error_action("write", config, saved_errno); - } - } else { - /* check log file size & space left on partition */ - if (config->daemonize == D_BACKGROUND) { - // If either of these fail, I consider it an - // inconvenience as opposed to something that is - // actionable. There may be some temporary condition - // that the system recovers from. The real error - // occurs on write. - log_size += rc; - check_log_file_size(data); - check_space_left(data->log_fd, data); - } - - if (fs_space_warning) - ack_type = AUDIT_RMW_TYPE_DISKLOW; - send_ack(data, ack_type, msg); - disk_err_warning = 0; - } -} - -static void check_log_file_size(struct auditd_consumer_data *data) -{ - struct daemon_conf *config = data->config; - - /* did we cross the size limit? */ - off_t sz = log_size / MEGABYTE; - - if (sz >= config->max_log_size && (config->daemonize == D_BACKGROUND)) { - switch (config->max_log_size_action) - { - case SZ_IGNORE: - break; - case SZ_SYSLOG: - audit_msg(LOG_ERR, - "Audit daemon log file is larger than max size"); - break; - case SZ_SUSPEND: - audit_msg(LOG_ERR, - "Audit daemon is suspending logging due to logfile size."); - logging_suspended = 1; - break; - case SZ_ROTATE: - if (data->config->num_logs > 1) { - audit_msg(LOG_NOTICE, - "Audit daemon rotating log files"); - rotate_logs(data, 0); - } - break; - case SZ_KEEP_LOGS: - audit_msg(LOG_NOTICE, - "Audit daemon rotating log files with keep option"); - shift_logs(data); - break; - default: - audit_msg(LOG_ALERT, - "Audit daemon log file is larger than max size and unknown action requested"); - break; - } - } -} - -static void check_space_left(int lfd, struct auditd_consumer_data *data) -{ - int rc; - struct statfs buf; - struct daemon_conf *config = data->config; - - rc = fstatfs(lfd, &buf); - if (rc == 0) { - if (buf.f_bavail < 5) { - /* we won't consume the last 5 blocks */ - fs_space_left = 0; - do_disk_full_action(data); - } else { - unsigned long blocks; - unsigned long block_size = buf.f_bsize; - blocks = config->space_left * (MEGABYTE/block_size); - if (buf.f_bavail < blocks) { - if (fs_space_warning == 0) { - do_space_left_action(data, 0); - fs_space_warning = 1; - } - } else if (fs_space_warning && - config->space_left_action == FA_SYSLOG){ - // Auto reset only if failure action is syslog - fs_space_warning = 0; - } - blocks=config->admin_space_left * (MEGABYTE/block_size); - if (buf.f_bavail < blocks) { - if (fs_admin_space_warning == 0) { - do_space_left_action(data, 1); - fs_admin_space_warning = 1; - } - } else if (fs_admin_space_warning && - config->admin_space_left_action == FA_SYSLOG) { - // Auto reset only if failure action is syslog - fs_admin_space_warning = 0; - } - } - } - else audit_msg(LOG_DEBUG, "fstatfs returned:%d, %s", rc, - strerror(errno)); -} - -extern int sendmail(const char *subject, const char *content, - const char *mail_acct); -static void do_space_left_action(struct auditd_consumer_data *data, int admin) -{ - int action; - struct daemon_conf *config = data->config; - - if (admin) - action = config->admin_space_left_action; - else - action = config->space_left_action; - - switch (action) - { - case FA_IGNORE: - break; - case FA_SYSLOG: - audit_msg(LOG_ALERT, - "Audit daemon is low on disk space for logging"); - break; - case FA_ROTATE: - if (config->num_logs > 1) { - audit_msg(LOG_NOTICE, - "Audit daemon rotating log files"); - rotate_logs(data, 0); - } - break; - case FA_EMAIL: - if (admin == 0) { - sendmail("Audit Disk Space Alert", - "The audit daemon is low on disk space for logging! Please take action\nto ensure no loss of service.", - config->action_mail_acct); - audit_msg(LOG_ALERT, - "Audit daemon is low on disk space for logging"); - } else { - sendmail("Audit Admin Space Alert", - "The audit daemon is very low on disk space for logging! Immediate action\nis required to ensure no loss of service.", - config->action_mail_acct); - audit_msg(LOG_ALERT, - "Audit daemon is very low on disk space for logging"); - } - break; - case FA_EXEC: - if (admin) - safe_exec(config->admin_space_left_exe); - else - safe_exec(config->space_left_exe); - break; - case FA_SUSPEND: - audit_msg(LOG_ALERT, - "Audit daemon is suspending logging due to low disk space."); - logging_suspended = 1; - break; - case FA_SINGLE: - audit_msg(LOG_ALERT, - "The audit daemon is now changing the system to single user mode"); - change_runlevel(SINGLE); - break; - case FA_HALT: - audit_msg(LOG_ALERT, - "The audit daemon is now halting the system"); - change_runlevel(HALT); - break; - default: - audit_msg(LOG_ALERT, - "Audit daemon is low on disk space for logging and unknown action requested"); - break; - } -} - -static void do_disk_full_action(struct auditd_consumer_data *data) -{ - struct daemon_conf *config = data->config; - - audit_msg(LOG_ALERT, - "Audit daemon has no space left on logging partition"); - switch (config->disk_full_action) - { - case FA_IGNORE: - case FA_SYSLOG: /* Message is syslogged above */ - break; - case FA_ROTATE: - if (config->num_logs > 1) { - audit_msg(LOG_NOTICE, - "Audit daemon rotating log files"); - rotate_logs(data, 0); - } - break; - case FA_EXEC: - safe_exec(config->disk_full_exe); - break; - case FA_SUSPEND: - audit_msg(LOG_ALERT, - "Audit daemon is suspending logging due to no space left on logging partition."); - logging_suspended = 1; - break; - case FA_SINGLE: - audit_msg(LOG_ALERT, - "The audit daemon is now changing the system to single user mode due to no space left on logging partition"); - change_runlevel(SINGLE); - break; - case FA_HALT: - audit_msg(LOG_ALERT, - "The audit daemon is now halting the system due to no space left on logging partition"); - change_runlevel(HALT); - break; - default: - audit_msg(LOG_ALERT, "Unknown disk full action requested"); - break; - } -} - -static void do_disk_error_action(const char * func, struct daemon_conf *config, - int err) -{ - char text[128]; - - switch (config->disk_error_action) - { - case FA_IGNORE: - break; - case FA_SYSLOG: - if (disk_err_warning < 5) { - snprintf(text, sizeof(text), - "%s: Audit daemon detected an error writing an event to disk (%s)", - func, strerror(err)); - audit_msg(LOG_ALERT, "%s", text); - disk_err_warning++; - } - break; - case FA_EXEC: - safe_exec(config->disk_error_exe); - break; - case FA_SUSPEND: - audit_msg(LOG_ALERT, - "Audit daemon is suspending logging due to previously mentioned write error"); - logging_suspended = 1; - break; - case FA_SINGLE: - audit_msg(LOG_ALERT, - "The audit daemon is now changing the system to single user mode due to previously mentioned write error"); - change_runlevel(SINGLE); - break; - case FA_HALT: - audit_msg(LOG_ALERT, - "The audit daemon is now halting the system due to previously mentioned write error."); - change_runlevel(HALT); - break; - default: - audit_msg(LOG_ALERT, - "Unknown disk error action requested"); - break; - } -} - -static void rotate_logs_now(struct auditd_consumer_data *data) -{ - struct daemon_conf *config = data->config; - - if (config->max_log_size_action == SZ_KEEP_LOGS) - shift_logs(data); - else - rotate_logs(data, 0); -} - -/* Check for and remove excess logs so that we don't run out of room */ -static void check_excess_logs(struct auditd_consumer_data *data) -{ - int rc; - unsigned int i, len; - char *name; - - // Only do this if rotate is the log size action - // and we actually have a limit - if (data->config->max_log_size_action != SZ_ROTATE || - data->config->num_logs < 2) - return; - - len = strlen(data->config->log_file) + 16; - name = (char *)malloc(len); - if (name == NULL) { /* Not fatal - just messy */ - audit_msg(LOG_ERR, "No memory checking excess logs"); - return; - } - - // We want 1 beyond the normal logs - i=data->config->num_logs; - rc=0; - while (rc == 0) { - snprintf(name, len, "%s.%d", data->config->log_file, i++); - rc=unlink(name); - if (rc == 0) - audit_msg(LOG_NOTICE, - "Log %s removed as it exceeds num_logs parameter", - name); - } - free(name); -} - -static void rotate_logs(struct auditd_consumer_data *data, - unsigned int num_logs) -{ - int rc; - unsigned int len, i; - char *oldname, *newname; - - if (data->config->max_log_size_action == SZ_ROTATE && - data->config->num_logs < 2) - return; - - /* Close audit file. fchmod and fchown errors are not fatal because we - * already adjusted log file permissions and ownership when opening the - * log file. */ - if (fchmod(data->log_fd, data->config->log_group ? S_IRUSR|S_IRGRP : - S_IRUSR) < 0) { - audit_msg(LOG_NOTICE, "Couldn't change permissions while " - "rotating log file (%s)", strerror(errno)); - } - if (fchown(data->log_fd, 0, data->config->log_group) < 0) { - audit_msg(LOG_NOTICE, "Couldn't change ownership while " - "rotating log file (%s)", strerror(errno)); - } - fclose(data->log_file); - - /* Rotate */ - len = strlen(data->config->log_file) + 16; - oldname = (char *)malloc(len); - if (oldname == NULL) { /* Not fatal - just messy */ - audit_msg(LOG_ERR, "No memory rotating logs"); - logging_suspended = 1; - return; - } - newname = (char *)malloc(len); - if (newname == NULL) { /* Not fatal - just messy */ - audit_msg(LOG_ERR, "No memory rotating logs"); - free(oldname); - logging_suspended = 1; - return; - } - - /* If we are rotating, get number from config */ - if (num_logs == 0) - num_logs = data->config->num_logs; - - /* Handle this case first since it will not enter the for loop */ - if (num_logs == 2) - snprintf(oldname, len, "%s.1", data->config->log_file); - - for (i=num_logs - 1; i>1; i--) { - snprintf(oldname, len, "%s.%d", data->config->log_file, i-1); - snprintf(newname, len, "%s.%d", data->config->log_file, i); - /* if the old file exists */ - rc = rename(oldname, newname); - if (rc == -1 && errno != ENOENT) { - // Likely errors: ENOSPC, ENOMEM, EBUSY - int saved_errno = errno; - audit_msg(LOG_ERR, - "Error rotating logs from %s to %s (%s)", - oldname, newname, strerror(errno)); - if (saved_errno == ENOSPC && fs_space_left == 1) { - fs_space_left = 0; - do_disk_full_action(data); - } else - do_disk_error_action("rotate", data->config, - saved_errno); - } - } - free(newname); - - /* At this point, oldname should point to lowest number - use it */ - newname = oldname; - rc = rename(data->config->log_file, newname); - if (rc == -1 && errno != ENOENT) { - // Likely errors: ENOSPC, ENOMEM, EBUSY - int saved_errno = errno; - audit_msg(LOG_ERR, "Error rotating logs from %s to %s (%s)", - data->config->log_file, newname, strerror(errno)); - if (saved_errno == ENOSPC && fs_space_left == 1) { - fs_space_left = 0; - do_disk_full_action(data); - } else - do_disk_error_action("rotate2", data->config, - saved_errno); - - /* At this point, we've failed to rotate the original log. - * So, let's make the old log writable and try again next - * time */ - chmod(data->config->log_file, - data->config->log_group ? S_IWUSR|S_IRUSR|S_IRGRP : - S_IWUSR|S_IRUSR); - } - free(newname); - - /* open new audit file */ - if (open_audit_log(data)) { - int saved_errno = errno; - audit_msg(LOG_NOTICE, - "Could not reopen a log after rotating."); - logging_suspended = 1; - do_disk_error_action("reopen", data->config, saved_errno); - } -} - -static int last_log = 1; -static void shift_logs(struct auditd_consumer_data *data) -{ - // The way this has to work is to start scanning from .1 up until - // no file is found. Then do the rotate algorithm using that number - // instead of log_max. - unsigned int num_logs, len; - char *name; - - len = strlen(data->config->log_file) + 16; - name = (char *)malloc(len); - if (name == NULL) { /* Not fatal - just messy */ - audit_msg(LOG_ERR, "No memory shifting logs"); - return; - } - - // Find last log - num_logs = last_log; - while (num_logs) { - snprintf(name, len, "%s.%d", data->config->log_file, - num_logs); - if (access(name, R_OK) != 0) - break; - num_logs++; - } - - /* Our last known file disappeared, start over... */ - if (num_logs <= last_log && last_log > 1) { - audit_msg(LOG_WARNING, "Last known log disappeared (%s)", name); - num_logs = last_log = 1; - while (num_logs) { - snprintf(name, len, "%s.%d", data->config->log_file, - num_logs); - if (access(name, R_OK) != 0) - break; - num_logs++; - } - audit_msg(LOG_INFO, "Next log to use will be %s", name); - } - last_log = num_logs; - rotate_logs(data, num_logs+1); - free(name); -} - -/* - * This function handles opening a descriptor for the audit log - * file and ensuring the correct options are applied to the descriptor. - * It returns 0 on success and 1 on failure. - */ -static int open_audit_log(struct auditd_consumer_data *data) -{ - int flags, lfd; - - // Likely errors for open: Almost anything - // Likely errors on rotate: ENFILE, ENOMEM, ENOSPC -retry: - lfd = open(data->config->log_file, O_WRONLY|O_APPEND|O_NOFOLLOW); - if (lfd < 0) { - if (errno == ENOENT) { - lfd = create_log_file(data->config->log_file); - if (lfd < 0) { - audit_msg(LOG_ERR, - "Couldn't create log file %s (%s)", - data->config->log_file, - strerror(errno)); - return 1; - } - close(lfd); - lfd = open(data->config->log_file, - O_WRONLY|O_APPEND|O_NOFOLLOW); - log_size = 0; - } else if (errno == ENFILE) { - // All system descriptors used, try again... - goto retry; - } - if (lfd < 0) { - audit_msg(LOG_ERR, "Couldn't open log file %s (%s)", - data->config->log_file, strerror(errno)); - return 1; - } - } else { - // Get initial size - struct stat st; - - int rc = fstat(lfd, &st); - if (rc == 0) - log_size = st.st_size; - else { - close(lfd); - return 1; - } - } - - if (fcntl(lfd, F_SETFD, FD_CLOEXEC) == -1) { - close(lfd); - audit_msg(LOG_ERR, "Error setting log file CLOEXEC flag (%s)", - strerror(errno)); - return 1; - } - if (data->config->flush == FT_DATA) { - flags = fcntl(lfd, F_GETFL); - if (flags < 0) { - audit_msg(LOG_ERR, "Couldn't get log file flags (%s)", - strerror(errno)); - close(lfd); - return 1; - } - if (fcntl(lfd, F_SETFL, flags|O_DSYNC) < 0) { - audit_msg(LOG_ERR, - "Couldn't set data sync mode on log file (%s)", - strerror(errno)); - close(lfd); - return 1; - } - } - else if (data->config->flush == FT_SYNC){ - flags = fcntl(lfd, F_GETFL); - if (flags < 0) { - audit_msg(LOG_ERR, "Couldn't get log file flags (%s)", - strerror(errno)); - close(lfd); - return 1; - } - if (fcntl(lfd, F_SETFL, flags|O_SYNC) < 0) { - audit_msg(LOG_ERR, - "Couldn't set sync mode on log file (%s)", - strerror(errno)); - close(lfd); - return 1; - } - } - if (fchmod(lfd, data->config->log_group ? S_IRUSR|S_IWUSR|S_IRGRP : - S_IRUSR|S_IWUSR) < 0) { - audit_msg(LOG_ERR, - "Couldn't change permissions of log file (%s)", - strerror(errno)); - close(lfd); - return 1; - } - if (fchown(lfd, 0, data->config->log_group) < 0) { - audit_msg(LOG_ERR, "Couldn't change ownership of log file (%s)", - strerror(errno)); - close(lfd); - return 1; - } - - data->log_fd = lfd; - data->log_file = fdopen(lfd, "a"); - if (data->log_file == NULL) { - audit_msg(LOG_ERR, "Error setting up log descriptor (%s)", - strerror(errno)); - close(lfd); - return 1; - } - - /* Set it to line buffering */ - setlinebuf(consumer_data.log_file); - return 0; -} - -static void change_runlevel(const char *level) -{ - char *argv[3]; - int pid; - struct sigaction sa; - static const char *init_pgm = "/sbin/init"; - - pid = fork(); - if (pid < 0) { - audit_msg(LOG_ALERT, - "Audit daemon failed to fork switching runlevels"); - return; - } - if (pid) /* Parent */ - return; - /* Child */ - sigfillset (&sa.sa_mask); - sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); - - argv[0] = (char *)init_pgm; - argv[1] = (char *)level; - argv[2] = NULL; - execve(init_pgm, argv, NULL); - audit_msg(LOG_ALERT, "Audit daemon failed to exec %s", init_pgm); - exit(1); -} - -static void safe_exec(const char *exe) -{ - char *argv[2]; - int pid; - struct sigaction sa; - - if (exe == NULL) { - audit_msg(LOG_ALERT, - "Safe_exec passed NULL for program to execute"); - return; - } - - pid = fork(); - if (pid < 0) { - audit_msg(LOG_ALERT, - "Audit daemon failed to fork doing safe_exec"); - return; - } - if (pid) /* Parent */ - return; - /* Child */ - sigfillset (&sa.sa_mask); - sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); - - argv[0] = (char *)exe; - argv[1] = NULL; - execve(exe, argv, NULL); - audit_msg(LOG_ALERT, "Audit daemon failed to exec %s", exe); - exit(1); -} - -/* -* This function will take an audit structure and return a -* text buffer that's unformatted for writing to disk. If there -* is an error the return value is NULL. -*/ -static char *format_raw(const struct audit_reply *rep, - struct daemon_conf *config) -{ - char *ptr; - - if (rep==NULL) { - if (config->node_name_format != N_NONE) - snprintf(format_buf, MAX_AUDIT_MESSAGE_LENGTH + - _POSIX_HOST_NAME_MAX - 32, - "node=%s type=DAEMON msg=NULL reply", - config->node_name); - else - snprintf(format_buf, MAX_AUDIT_MESSAGE_LENGTH, - "type=DAEMON msg=NULL reply"); - } else { - int len, nlen; - const char *type, *message; - char unknown[32]; - type = audit_msg_type_to_name(rep->type); - if (type == NULL) { - snprintf(unknown, sizeof(unknown), - "UNKNOWN[%d]", rep->type); - type = unknown; - } - if (rep->message == NULL) { - message = "msg lost"; - len = 8; - } else { - message = rep->message; - len = rep->len; - } - - // Note: This can truncate messages if - // MAX_AUDIT_MESSAGE_LENGTH is too small - if (config->node_name_format != N_NONE) - nlen = snprintf(format_buf, MAX_AUDIT_MESSAGE_LENGTH + - _POSIX_HOST_NAME_MAX - 32, - "node=%s type=%s msg=%.*s\n", - config->node_name, type, len, message); - else - nlen = snprintf(format_buf, - MAX_AUDIT_MESSAGE_LENGTH - 32, - "type=%s msg=%.*s", type, len, message); - - /* Replace \n with space so it looks nicer. */ - ptr = format_buf; - while ((ptr = strchr(ptr, 0x0A)) != NULL) - *ptr = ' '; - - /* Trim trailing space off since it wastes space */ - if (format_buf[nlen-1] == ' ') - format_buf[nlen-1] = 0; - } - return format_buf; -} - -static void reconfigure(struct auditd_consumer_data *data) -{ - struct daemon_conf *nconf = data->head->reply.conf; - struct daemon_conf *oconf = data->config; - uid_t uid = nconf->sender_uid; - pid_t pid = nconf->sender_pid; - const char *ctx = nconf->sender_ctx; - struct timeval tv; - char txt[MAX_AUDIT_MESSAGE_LENGTH]; - char date[40]; - unsigned int seq_num; - int need_size_check = 0, need_reopen = 0, need_space_check = 0; - - snprintf(txt, sizeof(txt), - "config change requested by pid=%d auid=%u subj=%s", - pid, uid, ctx); - audit_msg(LOG_NOTICE, "%s", txt); - - /* Do the reconfiguring. These are done in a specific - * order from least invasive to most invasive. We will - * start with general system parameters. */ - - // start with disk error action. - oconf->disk_error_action = nconf->disk_error_action; - free((char *)oconf->disk_error_exe); - oconf->disk_error_exe = nconf->disk_error_exe; - disk_err_warning = 0; - - // numlogs is next - oconf->num_logs = nconf->num_logs; - - // flush freq - oconf->freq = nconf->freq; - - // priority boost - if (oconf->priority_boost != nconf->priority_boost) { - int rc; - - oconf->priority_boost = nconf->priority_boost; - errno = 0; - rc = nice(-oconf->priority_boost); - if (rc == -1 && errno) - audit_msg(LOG_NOTICE, "Cannot change priority in " - "reconfigure (%s)", strerror(errno)); - } - - // log format - oconf->log_format = nconf->log_format; - - // action_mail_acct - if (strcmp(oconf->action_mail_acct, nconf->action_mail_acct)) { - free((void *)oconf->action_mail_acct); - oconf->action_mail_acct = nconf->action_mail_acct; - } else - free((void *)nconf->action_mail_acct); - - // node_name - if (oconf->node_name_format != nconf->node_name_format || - (oconf->node_name && nconf->node_name && - strcmp(oconf->node_name, nconf->node_name) != 0)) { - oconf->node_name_format = nconf->node_name_format; - free((char *)oconf->node_name); - oconf->node_name = nconf->node_name; - } - - /* Now look at audit dispatcher changes */ - oconf->qos = nconf->qos; // dispatcher qos - - // do the dispatcher app change - if (oconf->dispatcher || nconf->dispatcher) { - // none before, start new one - if (oconf->dispatcher == NULL) { - oconf->dispatcher = strdup(nconf->dispatcher); - if (oconf->dispatcher == NULL) { - int saved_errno = errno; - audit_msg(LOG_NOTICE, - "Could not allocate dispatcher memory" - " in reconfigure"); - // Likely errors: ENOMEM - do_disk_error_action("reconfig", data->config, - saved_errno); - } - if(init_dispatcher(oconf)) {// dispatcher & qos is used - int saved_errno = errno; - audit_msg(LOG_NOTICE, - "Could not start dispatcher %s" - " in reconfigure", oconf->dispatcher); - // Likely errors: Socketpairs or exec perms - do_disk_error_action("reconfig", data->config, - saved_errno); - } - } - // have one, but none after this - else if (nconf->dispatcher == NULL) { - shutdown_dispatcher(); - free((char *)oconf->dispatcher); - oconf->dispatcher = NULL; - } - // they are different apps - else if (strcmp(oconf->dispatcher, nconf->dispatcher)) { - shutdown_dispatcher(); - free((char *)oconf->dispatcher); - oconf->dispatcher = strdup(nconf->dispatcher); - if (oconf->dispatcher == NULL) { - int saved_errno = errno; - audit_msg(LOG_NOTICE, - "Could not allocate dispatcher memory" - " in reconfigure"); - // Likely errors: ENOMEM - do_disk_error_action("reconfig", data->config, - saved_errno); - } - if(init_dispatcher(oconf)) {// dispatcher & qos is used - int saved_errno = errno; - audit_msg(LOG_NOTICE, - "Could not start dispatcher %s" - " in reconfigure", oconf->dispatcher); - // Likely errors: Socketpairs or exec perms - do_disk_error_action("reconfig", data->config, - saved_errno); - } - } - // they are the same app - just signal it - else { - reconfigure_dispatcher(oconf); - free((char *)nconf->dispatcher); - nconf->dispatcher = NULL; - } - } - - // network listener - auditd_tcp_listen_reconfigure(nconf, oconf); - - /* At this point we will work on the items that are related to - * a single log file. */ - - // max logfile action - if (oconf->max_log_size_action != nconf->max_log_size_action) { - oconf->max_log_size_action = nconf->max_log_size_action; - need_size_check = 1; - } - - // max log size - if (oconf->max_log_size != nconf->max_log_size) { - oconf->max_log_size = nconf->max_log_size; - need_size_check = 1; - } - - if (need_size_check) { - logging_suspended = 0; - check_log_file_size(data); - } - - // flush technique - if (oconf->flush != nconf->flush) { - oconf->flush = nconf->flush; - need_reopen = 1; - } - - // logfile - if (strcmp(oconf->log_file, nconf->log_file)) { - free((void *)oconf->log_file); - oconf->log_file = nconf->log_file; - need_reopen = 1; - need_space_check = 1; // might be on new partition - } else - free((void *)nconf->log_file); - - if (need_reopen) { - fclose(data->log_file); - if (open_audit_log(data)) { - int saved_errno = errno; - audit_msg(LOG_NOTICE, - "Could not reopen a log after reconfigure"); - logging_suspended = 1; - // Likely errors: ENOMEM, ENOSPC - do_disk_error_action("reconfig", data->config, - saved_errno); - } else { - logging_suspended = 0; - check_log_file_size(data); - } - } - - /* At this point we will start working on items that are - * related to the amount of space on the partition. */ - - // space left - if (oconf->space_left != nconf->space_left) { - oconf->space_left = nconf->space_left; - need_space_check = 1; - } - - // space left action - if (oconf->space_left_action != nconf->space_left_action) { - oconf->space_left_action = nconf->space_left_action; - need_space_check = 1; - } - - // space left exe - if (oconf->space_left_exe || nconf->space_left_exe) { - if (nconf->space_left_exe == NULL) - ; /* do nothing if new one is blank */ - else if (oconf->space_left_exe == NULL && nconf->space_left_exe) - need_space_check = 1; - else if (strcmp(oconf->space_left_exe, nconf->space_left_exe)) - need_space_check = 1; - free((char *)oconf->space_left_exe); - oconf->space_left_exe = nconf->space_left_exe; - } - - // admin space left - if (oconf->admin_space_left != nconf->admin_space_left) { - oconf->admin_space_left = nconf->admin_space_left; - need_space_check = 1; - } - - // admin space action - if (oconf->admin_space_left_action != nconf->admin_space_left_action) { - oconf->admin_space_left_action = nconf->admin_space_left_action; - need_space_check = 1; - } - - // admin space left exe - if (oconf->admin_space_left_exe || nconf->admin_space_left_exe) { - if (nconf->admin_space_left_exe == NULL) - ; /* do nothing if new one is blank */ - else if (oconf->admin_space_left_exe == NULL && - nconf->admin_space_left_exe) - need_space_check = 1; - else if (strcmp(oconf->admin_space_left_exe, - nconf->admin_space_left_exe)) - need_space_check = 1; - free((char *)oconf->admin_space_left_exe); - oconf->admin_space_left_exe = nconf->admin_space_left_exe; - } - // disk full action - if (oconf->disk_full_action != nconf->disk_full_action) { - oconf->disk_full_action = nconf->disk_full_action; - need_space_check = 1; - } - - // disk full exe - if (oconf->disk_full_exe || nconf->disk_full_exe) { - if (nconf->disk_full_exe == NULL) - ; /* do nothing if new one is blank */ - else if (oconf->disk_full_exe == NULL && nconf->disk_full_exe) - need_space_check = 1; - else if (strcmp(oconf->disk_full_exe, nconf->disk_full_exe)) - need_space_check = 1; - free((char *)oconf->disk_full_exe); - oconf->disk_full_exe = nconf->disk_full_exe; - } - - if (need_space_check) { - /* note save suspended flag, then do space_left. If suspended - * is still 0, then copy saved suspended back. This avoids - * having to call check_log_file_size to restore it. */ - int saved_suspend = logging_suspended; - - fs_space_warning = 0; - fs_admin_space_warning = 0; - fs_space_left = 1; - logging_suspended = 0; - check_excess_logs(data); - check_space_left(data->log_fd, data); - if (logging_suspended == 0) - logging_suspended = saved_suspend; - } - - // Next document the results - srand(time(NULL)); - seq_num = rand()%10000; - if (gettimeofday(&tv, NULL) == 0) { - snprintf(date, sizeof(date), "audit(%lu.%03u:%u)", tv.tv_sec, - (unsigned)(tv.tv_usec/1000), seq_num); - } else { - snprintf(date, sizeof(date), - "audit(%lu.%03u:%u)", (unsigned long)time(NULL), - 0, seq_num); - } - - data->head->reply.len = snprintf(txt, sizeof(txt), - "%s config changed, auid=%u pid=%d subj=%s res=success", date, - uid, pid, ctx ); - audit_msg(LOG_NOTICE, "%s", txt); - data->head->reply.type = AUDIT_DAEMON_CONFIG; - data->head->reply.message = strdup(txt); - if (!data->head->reply.message) { - data->head->reply.len = 0; - audit_msg(LOG_ERR, "Cannot allocate config message"); - // FIXME: Should call some error handler - } - free((char *)ctx); -} - diff --git a/framework/src/audit/src/auditd-event.h b/framework/src/audit/src/auditd-event.h deleted file mode 100644 index 71678259..00000000 --- a/framework/src/audit/src/auditd-event.h +++ /dev/null @@ -1,49 +0,0 @@ -/* auditd-event.h -- - * Copyright 2004, 2005, 2008 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#ifndef AUDITD_EVENT_H -#define AUDITD_EVENT_H - -#include "libaudit.h" - -typedef void (*ack_func_type)(void *ack_data, const unsigned char *header, const char *msg); - -struct auditd_reply_list { - struct audit_reply reply; - struct auditd_reply_list *next; - ack_func_type ack_func; - void *ack_data; - unsigned long sequence_id; -}; - -#include "auditd-config.h" - -void shutdown_events(void); -int init_event(struct daemon_conf *config); -void resume_logging(void); -void enqueue_event(struct auditd_reply_list *rep); -void enqueue_formatted_event(char *msg, ack_func_type ack_func, void *ack_data, uint32_t sequence_id); -void *consumer_thread_main(void *arg); - -#endif - diff --git a/framework/src/audit/src/auditd-listen.c b/framework/src/audit/src/auditd-listen.c deleted file mode 100644 index d1977c63..00000000 --- a/framework/src/audit/src/auditd-listen.c +++ /dev/null @@ -1,1065 +0,0 @@ -/* auditd-listen.c -- - * Copyright 2008,2009,2011 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * DJ Delorie <dj@redhat.com> - * - */ - -#include "config.h" -#include <stdio.h> -#include <unistd.h> -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <dirent.h> -#include <ctype.h> -#include <stdlib.h> -#include <netdb.h> -#include <fcntl.h> /* O_NOFOLLOW needs gnu defined */ -#include <libgen.h> -#include <arpa/inet.h> -#include <limits.h> /* INT_MAX */ -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#ifdef HAVE_LIBWRAP -#include <tcpd.h> -#endif -#ifdef USE_GSSAPI -#include <gssapi/gssapi.h> -#include <gssapi/gssapi_generic.h> -#include <krb5.h> -#endif -#include "libaudit.h" -#include "auditd-event.h" -#include "auditd-config.h" -#include "private.h" - -#include "ev.h" - -extern volatile int stop; -extern int send_audit_event(int type, const char *str); -#define DEFAULT_BUF_SZ 192 - -typedef struct ev_tcp { - struct ev_io io; - struct sockaddr_in addr; - struct ev_tcp *next, *prev; - unsigned int bufptr; - int client_active; -#ifdef USE_GSSAPI - /* This holds the negotiated security context for this client. */ - gss_ctx_id_t gss_context; - char *remote_name; - int remote_name_len; -#endif - unsigned char buffer [MAX_AUDIT_MESSAGE_LENGTH + 17]; -} ev_tcp; - -static int listen_socket; -static struct ev_io tcp_listen_watcher; -static struct ev_periodic periodic_watcher; -static int min_port, max_port, max_per_addr; -static int use_libwrap = 1; -#ifdef USE_GSSAPI -/* This is used to hold our own private key. */ -static gss_cred_id_t server_creds; -static char *my_service_name, *my_gss_realm; -static int use_gss = 0; -static char msgbuf[MAX_AUDIT_MESSAGE_LENGTH + 1]; -#endif - -static struct ev_tcp *client_chain = NULL; - -static char *sockaddr_to_ipv4(struct sockaddr_in *addr) -{ - unsigned char *uaddr = (unsigned char *)&(addr->sin_addr); - static char buf[40]; - - snprintf(buf, sizeof(buf), "%u.%u.%u.%u", - uaddr[0], uaddr[1], uaddr[2], uaddr[3]); - return buf; -} - -static char *sockaddr_to_addr4(struct sockaddr_in *addr) -{ - unsigned char *uaddr = (unsigned char *)&(addr->sin_addr); - static char buf[40]; - - snprintf(buf, sizeof(buf), "%u.%u.%u.%u:%u", - uaddr[0], uaddr[1], uaddr[2], uaddr[3], - ntohs (addr->sin_port)); - return buf; -} - -static void set_close_on_exec (int fd) -{ - int flags = fcntl (fd, F_GETFD); - if (flags == -1) - flags = 0; - flags |= FD_CLOEXEC; - fcntl (fd, F_SETFD, flags); -} - -static void release_client(struct ev_tcp *client) -{ - char emsg[DEFAULT_BUF_SZ]; - - snprintf(emsg, sizeof(emsg), "addr=%s port=%d res=success", - sockaddr_to_ipv4(&client->addr), ntohs (client->addr.sin_port)); - send_audit_event(AUDIT_DAEMON_CLOSE, emsg); -#ifdef USE_GSSAPI - if (client->remote_name) - free (client->remote_name); -#endif - shutdown(client->io.fd, SHUT_RDWR); - close(client->io.fd); - if (client_chain == client) - client_chain = client->next; - if (client->next) - client->next->prev = client->prev; - if (client->prev) - client->prev->next = client->next; -} - -static void close_client(struct ev_tcp *client) -{ - release_client (client); - free (client); -} - -static int ar_write (int sock, const void *buf, int len) -{ - int rc = 0, w; - while (len > 0) { - do { - w = write(sock, buf, len); - } while (w < 0 && errno == EINTR); - if (w < 0) - return w; - if (w == 0) - break; - rc += w; - len -= w; - buf = (const void *)((const char *)buf + w); - } - return rc; -} - -#ifdef USE_GSSAPI -static int ar_read (int sock, void *buf, int len) -{ - int rc = 0, r; - while (len > 0) { - do { - r = read(sock, buf, len); - } while (r < 0 && errno == EINTR); - if (r < 0) - return r; - if (r == 0) - break; - rc += r; - len -= r; - buf = (void *)((char *)buf + r); - } - return rc; -} - - -/* Communications under GSS is done by token exchanges. Each "token" - may contain a message, perhaps signed, perhaps encrypted. The - messages within are what we're interested in, but the network sees - the tokens. The protocol we use for transferring tokens is to send - the length first, four bytes MSB first, then the token data. We - return nonzero on error. */ -static int recv_token (int s, gss_buffer_t tok) -{ - int ret; - unsigned char lenbuf[4]; - unsigned int len; - - ret = ar_read(s, (char *) lenbuf, 4); - if (ret < 0) { - audit_msg(LOG_ERR, "GSS-API error reading token length"); - return -1; - } else if (!ret) { - return 0; - } else if (ret != 4) { - audit_msg(LOG_ERR, "GSS-API error reading token length"); - return -1; - } - - len = ((lenbuf[0] << 24) - | (lenbuf[1] << 16) - | (lenbuf[2] << 8) - | lenbuf[3]); - if (len > MAX_AUDIT_MESSAGE_LENGTH) { - audit_msg(LOG_ERR, - "GSS-API error: event length excedes MAX_AUDIT_LENGTH"); - return -1; - } - tok->length = len; - - tok->value = (char *) malloc(tok->length ? tok->length : 1); - if (tok->length && tok->value == NULL) { - audit_msg(LOG_ERR, "Out of memory allocating token data"); - return -1; - } - - ret = ar_read(s, (char *) tok->value, tok->length); - if (ret < 0) { - audit_msg(LOG_ERR, "GSS-API error reading token data"); - free(tok->value); - return -1; - } else if (ret != (int) tok->length) { - audit_msg(LOG_ERR, "GSS-API error reading token data"); - free(tok->value); - return -1; - } - - return 1; -} - -/* Same here. */ -int send_token(int s, gss_buffer_t tok) -{ - int ret; - unsigned char lenbuf[4]; - unsigned int len; - - if (tok->length > 0xffffffffUL) - return -1; - len = tok->length; - lenbuf[0] = (len >> 24) & 0xff; - lenbuf[1] = (len >> 16) & 0xff; - lenbuf[2] = (len >> 8) & 0xff; - lenbuf[3] = len & 0xff; - - ret = ar_write(s, (char *) lenbuf, 4); - if (ret < 0) { - audit_msg(LOG_ERR, "GSS-API error sending token length"); - return -1; - } else if (ret != 4) { - audit_msg(LOG_ERR, "GSS-API error sending token length"); - return -1; - } - - ret = ar_write(s, tok->value, tok->length); - if (ret < 0) { - audit_msg(LOG_ERR, "GSS-API error sending token data"); - return -1; - } else if (ret != (int) tok->length) { - audit_msg(LOG_ERR, "GSS-API error sending token data"); - return -1; - } - - return 0; -} - - -static void gss_failure_2 (const char *msg, int status, int type) -{ - OM_uint32 message_context = 0; - OM_uint32 min_status = 0; - gss_buffer_desc status_string; - - do { - gss_display_status (&min_status, - status, - type, - GSS_C_NO_OID, - &message_context, - &status_string); - - audit_msg (LOG_ERR, "GSS error: %s: %s", - msg, (char *)status_string.value); - - gss_release_buffer(&min_status, &status_string); - } while (message_context != 0); -} - -static void gss_failure (const char *msg, int major_status, int minor_status) -{ - gss_failure_2 (msg, major_status, GSS_C_GSS_CODE); - if (minor_status) - gss_failure_2 (msg, minor_status, GSS_C_MECH_CODE); -} - -#define KCHECK(x,f) if (x) { \ - const char *kstr = krb5_get_error_message(kcontext, x); \ - audit_msg(LOG_ERR, "krb5 error: %s in %s\n", kstr, f); \ - krb5_free_error_message(kcontext, kstr); \ - return -1; } - -/* These are our private credentials, which come from a key file on - our server. They are aquired once, at program start. */ -static int server_acquire_creds(const char *service_name, - gss_cred_id_t *server_creds) -{ - gss_buffer_desc name_buf; - gss_name_t server_name; - OM_uint32 major_status, minor_status; - - krb5_context kcontext = NULL; - int krberr; - - my_service_name = strdup (service_name); - name_buf.value = (char *)service_name; - name_buf.length = strlen(name_buf.value) + 1; - major_status = gss_import_name(&minor_status, &name_buf, - (gss_OID) gss_nt_service_name, - &server_name); - if (major_status != GSS_S_COMPLETE) { - gss_failure("importing name", major_status, minor_status); - return -1; - } - - major_status = gss_acquire_cred(&minor_status, - server_name, GSS_C_INDEFINITE, - GSS_C_NULL_OID_SET, GSS_C_ACCEPT, - server_creds, NULL, NULL); - if (major_status != GSS_S_COMPLETE) { - gss_failure("acquiring credentials", - major_status, minor_status); - return -1; - } - - (void) gss_release_name(&minor_status, &server_name); - - krberr = krb5_init_context (&kcontext); - KCHECK (krberr, "krb5_init_context"); - krberr = krb5_get_default_realm (kcontext, &my_gss_realm); - KCHECK (krberr, "krb5_get_default_realm"); - - audit_msg(LOG_DEBUG, "GSS creds for %s acquired", service_name); - - return 0; -} - -/* This is where we negotiate a security context with the client. In - the case of Kerberos, this is where the key exchange happens. - FIXME: While everything else is strictly nonblocking, this - negotiation blocks. */ -static int negotiate_credentials (ev_tcp *io) -{ - gss_buffer_desc send_tok, recv_tok; - gss_name_t client; - OM_uint32 maj_stat, min_stat, acc_sec_min_stat; - gss_ctx_id_t *context; - OM_uint32 sess_flags; - char *slashptr, *atptr; - - context = & io->gss_context; - *context = GSS_C_NO_CONTEXT; - - maj_stat = GSS_S_CONTINUE_NEEDED; - do { - /* STEP 1 - get a token from the client. */ - - if (recv_token(io->io.fd, &recv_tok) <= 0) { - audit_msg(LOG_ERR, - "TCP session from %s will be closed, error ignored", - sockaddr_to_addr4(&io->addr)); - return -1; - } - if (recv_tok.length == 0) - continue; - - /* STEP 2 - let GSS process that token. */ - - maj_stat = gss_accept_sec_context(&acc_sec_min_stat, - context, server_creds, - &recv_tok, - GSS_C_NO_CHANNEL_BINDINGS, &client, - NULL, &send_tok, &sess_flags, - NULL, NULL); - if (recv_tok.value) { - free(recv_tok.value); - recv_tok.value = NULL; - } - if (maj_stat != GSS_S_COMPLETE - && maj_stat != GSS_S_CONTINUE_NEEDED) { - gss_release_buffer(&min_stat, &send_tok); - if (*context != GSS_C_NO_CONTEXT) - gss_delete_sec_context(&min_stat, context, - GSS_C_NO_BUFFER); - gss_failure("accepting context", maj_stat, - acc_sec_min_stat); - return -1; - } - - /* STEP 3 - send any tokens to the client that GSS may - ask us to send. */ - - if (send_tok.length != 0) { - if (send_token(io->io.fd, &send_tok) < 0) { - gss_release_buffer(&min_stat, &send_tok); - audit_msg(LOG_ERR, - "TCP session from %s will be closed, error ignored", - sockaddr_to_addr4(&io->addr)); - if (*context != GSS_C_NO_CONTEXT) - gss_delete_sec_context(&min_stat, - context, GSS_C_NO_BUFFER); - return -1; - } - gss_release_buffer(&min_stat, &send_tok); - } - } while (maj_stat == GSS_S_CONTINUE_NEEDED); - - maj_stat = gss_display_name(&min_stat, client, &recv_tok, NULL); - gss_release_name(&min_stat, &client); - - if (maj_stat != GSS_S_COMPLETE) { - gss_failure("displaying name", maj_stat, min_stat); - return -1; - } - - audit_msg(LOG_INFO, "GSS-API Accepted connection from: %s", - (char *)recv_tok.value); - io->remote_name = strdup (recv_tok.value); - io->remote_name_len = strlen (recv_tok.value); - gss_release_buffer(&min_stat, &recv_tok); - - slashptr = strchr (io->remote_name, '/'); - atptr = strchr (io->remote_name, '@'); - - if (!slashptr || !atptr) { - audit_msg(LOG_ERR, "Invalid GSS name from remote client: %s", - io->remote_name); - return -1; - } - - *slashptr = 0; - if (strcmp (io->remote_name, my_service_name)) { - audit_msg(LOG_ERR, "Unauthorized GSS client name: %s (not %s)", - io->remote_name, my_service_name); - return -1; - } - *slashptr = '/'; - - if (strcmp (atptr+1, my_gss_realm)) { - audit_msg(LOG_ERR, "Unauthorized GSS client realm: %s (not %s)", - atptr+1, my_gss_realm); - return -1; - } - - return 0; -} -#endif /* USE_GSSAPI */ - -/* This is called from auditd-event after the message has been logged. - The header is already filled in. */ -static void client_ack (void *ack_data, const unsigned char *header, - const char *msg) -{ - ev_tcp *io = (ev_tcp *)ack_data; -#ifdef USE_GSSAPI - if (use_gss) { - OM_uint32 major_status, minor_status; - gss_buffer_desc utok, etok; - int rc, mlen; - - mlen = strlen (msg); - utok.length = AUDIT_RMW_HEADER_SIZE + mlen; - utok.value = malloc (utok.length + 1); - - memcpy (utok.value, header, AUDIT_RMW_HEADER_SIZE); - memcpy (utok.value+AUDIT_RMW_HEADER_SIZE, msg, mlen); - - /* Wrapping the message creates a token for the - client. Then we just have to worry about sending - the token. */ - - major_status = gss_wrap (&minor_status, - io->gss_context, - 1, - GSS_C_QOP_DEFAULT, - &utok, - NULL, - &etok); - if (major_status != GSS_S_COMPLETE) { - gss_failure("encrypting message", major_status, - minor_status); - free (utok.value); - return; - } - // FIXME: What were we going to do with rc? - rc = send_token (io->io.fd, &etok); - free (utok.value); - (void) gss_release_buffer(&minor_status, &etok); - - return; - } -#endif - // Send the header and a text error message if it exists - ar_write (io->io.fd, header, AUDIT_RMW_HEADER_SIZE); - if (msg[0]) - ar_write (io->io.fd, msg, strlen(msg)); -} - -static void client_message (struct ev_tcp *io, unsigned int length, - unsigned char *header) -{ - unsigned char ch; - uint32_t type, mlen, seq; - int hver, mver; - - if (AUDIT_RMW_IS_MAGIC (header, length)) { - AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, mlen, seq) - - ch = header[length]; - header[length] = 0; - if (length > 1 && header[length-1] == '\n') - header[length-1] = 0; - if (type == AUDIT_RMW_TYPE_HEARTBEAT) { - unsigned char ack[AUDIT_RMW_HEADER_SIZE]; - AUDIT_RMW_PACK_HEADER (ack, 0, AUDIT_RMW_TYPE_ACK, - 0, seq); - client_ack (io, ack, ""); - } else - enqueue_formatted_event(header+AUDIT_RMW_HEADER_SIZE, - client_ack, io, seq); - header[length] = ch; - } else { - header[length] = 0; - if (length > 1 && header[length-1] == '\n') - header[length-1] = 0; - enqueue_formatted_event (header, NULL, NULL, 0); - } -} - -static void auditd_tcp_client_handler( struct ev_loop *loop, - struct ev_io *_io, int revents ) -{ - struct ev_tcp *io = (struct ev_tcp *) _io; - int i, r; - int total_this_call = 0; - - io->client_active = 1; - - /* The socket is non-blocking, but we have a limited buffer - size. In the event that we get a packet that's bigger than - our buffer, we need to read it in multiple parts. Thus, we - keep reading/parsing/processing until we run out of ready - data. */ -read_more: - r = read (io->io.fd, - io->buffer + io->bufptr, - MAX_AUDIT_MESSAGE_LENGTH - io->bufptr); - - if (r < 0 && errno == EAGAIN) - r = 0; - - /* We need to keep track of the difference between "no data - * because it's closed" and "no data because we've read it - * all". */ - if (r == 0 && total_this_call > 0) { - return; - } - - /* If the connection is gracefully closed, the first read we - try will return zero. If the connection times out or - otherwise fails, the read will return -1. */ - if (r <= 0) { - if (r < 0) - audit_msg (LOG_WARNING, - "client %s socket closed unexpectedly", - sockaddr_to_addr4(&io->addr)); - - /* There may have been a final message without a LF. */ - if (io->bufptr) { - client_message (io, io->bufptr, io->buffer); - - } - - ev_io_stop (loop, _io); - close_client (io); - return; - } - - total_this_call += r; - -more_messages: -#ifdef USE_GSSAPI - /* If we're using GSS at all, everything will be encrypted, - one record per token. */ - if (use_gss) { - gss_buffer_desc utok, etok; - io->bufptr += r; - uint32_t len; - OM_uint32 major_status, minor_status; - - /* We need at least four bytes to test the length. If - we have more than four bytes, we can tell if we - have a whole token (or more). */ - - if (io->bufptr < 4) - return; - - len = ( ((uint32_t)(io->buffer[0] & 0xFF) << 24) - | ((uint32_t)(io->buffer[1] & 0xFF) << 16) - | ((uint32_t)(io->buffer[2] & 0xFF) << 8) - | (uint32_t)(io->buffer[3] & 0xFF)); - - /* Make sure we got something big enough and not too big */ - if (io->bufptr < 4 + len || len > MAX_AUDIT_MESSAGE_LENGTH) - return; - i = len + 4; - - etok.length = len; - etok.value = io->buffer + 4; - - /* Unwrapping the token gives us the original message, - which we know is already a single record. */ - major_status = gss_unwrap (&minor_status, io->gss_context, - &etok, &utok, NULL, NULL); - - if (major_status != GSS_S_COMPLETE) { - gss_failure("decrypting message", major_status, - minor_status); - } else { - /* client_message() wants to NUL terminate it, - so copy it to a bigger buffer. Plus, we - want to add our own tag. */ - memcpy (msgbuf, utok.value, utok.length); - while (utok.length > 0 && msgbuf[utok.length-1] == '\n') - utok.length --; - snprintf (msgbuf + utok.length, - MAX_AUDIT_MESSAGE_LENGTH - utok.length, - " krb5=%s", io->remote_name); - utok.length += 6 + io->remote_name_len; - client_message (io, utok.length, msgbuf); - gss_release_buffer(&minor_status, &utok); - } - } else -#endif - if (AUDIT_RMW_IS_MAGIC (io->buffer, (io->bufptr+r))) { - uint32_t type, len, seq; - int hver, mver; - unsigned char *header = (unsigned char *)io->buffer; - - io->bufptr += r; - - if (io->bufptr < AUDIT_RMW_HEADER_SIZE) - return; - - AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, len, seq); - - /* Make sure len is not too big */ - if (len > MAX_AUDIT_MESSAGE_LENGTH) - return; - - i = len; - i += AUDIT_RMW_HEADER_SIZE; - - /* See if we have enough bytes to extract the whole message. */ - if (io->bufptr < i) - return; - - /* We have an I-byte message in buffer. Send ACK */ - client_message (io, i, io->buffer); - - } else { - /* At this point, the buffer has IO->BUFPTR+R bytes in it. - The first IO->BUFPTR bytes do not have a LF in them (we've - already checked), we must check the R new bytes. */ - - for (i = io->bufptr; i < io->bufptr + r; i ++) - if (io->buffer [i] == '\n') - break; - - io->bufptr += r; - - /* Check for a partial message, with no LF yet. */ - if (i == io->bufptr) - return; - - i++; - - /* We have an I-byte message in buffer. Send ACK */ - client_message (io, i, io->buffer); - } - - /* Now copy any remaining bytes to the beginning of the - buffer. */ - memmove(io->buffer, io->buffer + i, io->bufptr - i); - io->bufptr -= i; - - /* See if this packet had more than one message in it. */ - if (io->bufptr > 0) { - r = io->bufptr; - io->bufptr = 0; - goto more_messages; - } - - /* Go back and see if there's more data to read. */ - goto read_more; -} - -#ifndef HAVE_LIBWRAP -#define auditd_tcpd_check(s) ({ 0; }) -#else -int allow_severity = LOG_INFO, deny_severity = LOG_NOTICE; -static int auditd_tcpd_check(int sock) -{ - struct request_info request; - - request_init(&request, RQ_DAEMON, "auditd", RQ_FILE, sock, 0); - fromhost(&request); - if (! hosts_access(&request)) - return 1; - return 0; -} -#endif - -/* - * This function counts the number of concurrent connections and returns - * a 1 if there are too many and a 0 otherwise. It assumes the incoming - * connection has not been added to the linked list yet. - */ -static int check_num_connections(struct sockaddr_in *aaddr) -{ - int num = 0; - struct ev_tcp *client = client_chain; - - while (client) { - if (memcmp(&aaddr->sin_addr, &client->addr.sin_addr, - sizeof(struct in_addr)) == 0) { - num++; - if (num >= max_per_addr) - return 1; - } - client = client->next; - } - return 0; -} - -static void auditd_tcp_listen_handler( struct ev_loop *loop, - struct ev_io *_io, int revents ) -{ - int one=1; - int afd; - socklen_t aaddrlen; - struct sockaddr_in aaddr; - struct ev_tcp *client; - char emsg[DEFAULT_BUF_SZ]; - - /* Accept the connection and see where it's coming from. */ - aaddrlen = sizeof(aaddr); - afd = accept (listen_socket, (struct sockaddr *)&aaddr, &aaddrlen); - if (afd == -1) { - audit_msg(LOG_ERR, "Unable to accept TCP connection"); - return; - } - - if (use_libwrap) { - if (auditd_tcpd_check(afd)) { - shutdown(afd, SHUT_RDWR); - close(afd); - audit_msg(LOG_ERR, "TCP connection from %s rejected", - sockaddr_to_addr4(&aaddr)); - snprintf(emsg, sizeof(emsg), - "op=wrap addr=%s port=%d res=no", - sockaddr_to_ipv4(&aaddr), - ntohs (aaddr.sin_port)); - send_audit_event(AUDIT_DAEMON_ACCEPT, emsg); - return; - } - } - - /* Verify it's coming from an authorized port. We assume the firewall - * will block attempts from unauthorized machines. */ - if (min_port > ntohs (aaddr.sin_port) || - ntohs (aaddr.sin_port) > max_port) { - audit_msg(LOG_ERR, "TCP connection from %s rejected", - sockaddr_to_addr4(&aaddr)); - snprintf(emsg, sizeof(emsg), - "op=port addr=%s port=%d res=no", - sockaddr_to_ipv4(&aaddr), - ntohs (aaddr.sin_port)); - send_audit_event(AUDIT_DAEMON_ACCEPT, emsg); - shutdown(afd, SHUT_RDWR); - close(afd); - return; - } - - /* Make sure we don't have too many connections */ - if (check_num_connections(&aaddr)) { - audit_msg(LOG_ERR, "Too many connections from %s - rejected", - sockaddr_to_addr4(&aaddr)); - snprintf(emsg, sizeof(emsg), - "op=dup addr=%s port=%d res=no", - sockaddr_to_ipv4(&aaddr), - ntohs (aaddr.sin_port)); - send_audit_event(AUDIT_DAEMON_ACCEPT, emsg); - shutdown(afd, SHUT_RDWR); - close(afd); - return; - } - - /* Connection is accepted...start setting it up */ - setsockopt(afd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (int)); - setsockopt(afd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof (int)); - setsockopt(afd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof (int)); - set_close_on_exec (afd); - - /* Make the client data structure */ - client = (struct ev_tcp *) malloc (sizeof (struct ev_tcp)); - if (client == NULL) { - audit_msg(LOG_CRIT, "Unable to allocate TCP client data"); - snprintf(emsg, sizeof(emsg), - "op=alloc addr=%s port=%d res=no", - sockaddr_to_ipv4(&aaddr), - ntohs (aaddr.sin_port)); - send_audit_event(AUDIT_DAEMON_ACCEPT, emsg); - shutdown(afd, SHUT_RDWR); - close(afd); - return; - } - - memset (client, 0, sizeof (struct ev_tcp)); - client->client_active = 1; - - // Was watching for EV_ERROR, but libev 3.48 took it away - ev_io_init (&(client->io), auditd_tcp_client_handler, afd, EV_READ); - - memcpy (&client->addr, &aaddr, sizeof (struct sockaddr_in)); - -#ifdef USE_GSSAPI - if (use_gss && negotiate_credentials (client)) { - shutdown(afd, SHUT_RDWR); - close(afd); - free(client); - return; - } -#endif - - fcntl(afd, F_SETFL, O_NONBLOCK | O_NDELAY); - ev_io_start (loop, &(client->io)); - - /* Add the new connection to a linked list of active clients. */ - client->next = client_chain; - if (client->next) - client->next->prev = client; - client_chain = client; - - /* And finally log that we accepted the connection */ - snprintf(emsg, sizeof(emsg), - "addr=%s port=%d res=success", sockaddr_to_ipv4(&aaddr), - ntohs (aaddr.sin_port)); - send_audit_event(AUDIT_DAEMON_ACCEPT, emsg); -} - -static void auditd_set_ports(int minp, int maxp, int max_p_addr) -{ - min_port = minp; - max_port = maxp; - max_per_addr = max_p_addr; -} - -static void periodic_handler(struct ev_loop *loop, struct ev_periodic *per, - int revents ) -{ - struct daemon_conf *config = (struct daemon_conf *) per->data; - struct ev_tcp *ev, *next = NULL; - int active; - - if (!config->tcp_client_max_idle) - return; - - for (ev = client_chain; ev; ev = next) { - active = ev->client_active; - ev->client_active = 0; - if (active) - continue; - - audit_msg(LOG_NOTICE, - "client %s idle too long - closing connection\n", - sockaddr_to_addr4(&(ev->addr))); - ev_io_stop (loop, &ev->io); - release_client(ev); - next = ev->next; - free(ev); - } -} - -int auditd_tcp_listen_init ( struct ev_loop *loop, struct daemon_conf *config ) -{ - struct sockaddr_in address; - int one = 1; - - ev_periodic_init (&periodic_watcher, periodic_handler, - 0, config->tcp_client_max_idle, NULL); - periodic_watcher.data = config; - if (config->tcp_client_max_idle) - ev_periodic_start (loop, &periodic_watcher); - - /* If the port is not set, that means we aren't going to - listen for connections. */ - if (config->tcp_listen_port == 0) - return 0; - - listen_socket = socket (AF_INET, SOCK_STREAM, 0); - if (listen_socket < 0) { - audit_msg(LOG_ERR, "Cannot create tcp listener socket"); - return 1; - } - - set_close_on_exec (listen_socket); - setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, - (char *)&one, sizeof (int)); - - memset (&address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_port = htons(config->tcp_listen_port); - address.sin_addr.s_addr = htonl(INADDR_ANY); - - /* This avoids problems if auditd needs to be restarted. */ - setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, - (char *)&one, sizeof (int)); - - if (bind(listen_socket, (struct sockaddr *)&address, sizeof(address))){ - audit_msg(LOG_ERR, - "Cannot bind tcp listener socket to port %ld", - config->tcp_listen_port); - close(listen_socket); - return 1; - } - - listen(listen_socket, config->tcp_listen_queue); - - audit_msg(LOG_DEBUG, "Listening on TCP port %ld", - config->tcp_listen_port); - - ev_io_init (&tcp_listen_watcher, auditd_tcp_listen_handler, - listen_socket, EV_READ); - ev_io_start (loop, &tcp_listen_watcher); - - use_libwrap = config->use_libwrap; - auditd_set_ports(config->tcp_client_min_port, - config->tcp_client_max_port, - config->tcp_max_per_addr); - -#ifdef USE_GSSAPI - if (config->enable_krb5) { - const char *princ = config->krb5_principal; - const char *key_file; - struct stat st; - - if (!princ) - princ = "auditd"; - use_gss = 1; - /* This may fail, but we don't care. */ - unsetenv ("KRB5_KTNAME"); - if (config->krb5_key_file) - key_file = config->krb5_key_file; - else - key_file = "/etc/audit/audit.key"; - setenv ("KRB5_KTNAME", key_file, 1); - - if (stat (key_file, &st) == 0) { - if ((st.st_mode & 07777) != 0400) { - audit_msg (LOG_ERR, - "%s is not mode 0400 (it's %#o) - compromised key?", - key_file, st.st_mode & 07777); - return -1; - } - if (st.st_uid != 0) { - audit_msg (LOG_ERR, - "%s is not owned by root (it's %d) - compromised key?", - key_file, st.st_uid); - return -1; - } - } - - server_acquire_creds(princ, &server_creds); - } -#endif - - return 0; -} - -void auditd_tcp_listen_uninit ( struct ev_loop *loop, - struct daemon_conf *config ) -{ -#ifdef USE_GSSAPI - OM_uint32 status; -#endif - - ev_io_stop ( loop, &tcp_listen_watcher ); - close ( listen_socket ); - -#ifdef USE_GSSAPI - if (use_gss) { - use_gss = 0; - gss_release_cred(&status, &server_creds); - } -#endif - - while (client_chain) { - unsigned char ack[AUDIT_RMW_HEADER_SIZE]; - - AUDIT_RMW_PACK_HEADER (ack, 0, AUDIT_RMW_TYPE_ENDING, 0, 0); - client_ack (client_chain, ack, ""); - ev_io_stop (loop, &client_chain->io); - close_client (client_chain); - } - - if (config->tcp_client_max_idle) - ev_periodic_stop (loop, &periodic_watcher); -} - -static void periodic_reconfigure(struct daemon_conf *config) -{ - struct ev_loop *loop = ev_default_loop (EVFLAG_AUTO); - if (config->tcp_client_max_idle) { - ev_periodic_set (&periodic_watcher, ev_now (loop), - config->tcp_client_max_idle, NULL); - ev_periodic_start (loop, &periodic_watcher); - } else { - ev_periodic_stop (loop, &periodic_watcher); - } -} - -void auditd_tcp_listen_reconfigure ( struct daemon_conf *nconf, - struct daemon_conf *oconf ) -{ - /* Look at network things that do not need restarting */ - if (oconf->tcp_client_min_port != nconf->tcp_client_min_port || - oconf->tcp_client_max_port != nconf->tcp_client_max_port || - oconf->tcp_max_per_addr != nconf->tcp_max_per_addr) { - oconf->tcp_client_min_port = nconf->tcp_client_min_port; - oconf->tcp_client_max_port = nconf->tcp_client_max_port; - oconf->tcp_max_per_addr = nconf->tcp_max_per_addr; - auditd_set_ports(oconf->tcp_client_min_port, - oconf->tcp_client_max_port, - oconf->tcp_max_per_addr); - } - if (oconf->tcp_client_max_idle != nconf->tcp_client_max_idle) { - oconf->tcp_client_max_idle = nconf->tcp_client_max_idle; - periodic_reconfigure(oconf); - } - if (oconf->tcp_listen_port != nconf->tcp_listen_port || - oconf->tcp_listen_queue != nconf->tcp_listen_queue) { - oconf->tcp_listen_port = nconf->tcp_listen_port; - oconf->tcp_listen_queue = nconf->tcp_listen_queue; - // FIXME: need to restart the network stuff - } -} diff --git a/framework/src/audit/src/auditd-listen.h b/framework/src/audit/src/auditd-listen.h deleted file mode 100644 index 69f9310a..00000000 --- a/framework/src/audit/src/auditd-listen.h +++ /dev/null @@ -1,55 +0,0 @@ -/* auditd-config.h -- - * Copyright 2004-2007 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * DJ Delorie <dj@redhat.com> - * - */ - -#ifndef AUDITD_LISTEN_H -#define AUDITD_LISTEN_H - -#include "ev.h" - -#ifdef USE_LISTENER -int auditd_tcp_listen_init ( struct ev_loop *loop, struct daemon_conf *config ); -void auditd_tcp_listen_uninit ( struct ev_loop *loop, - struct daemon_conf *config ); -void auditd_tcp_listen_reconfigure ( struct daemon_conf *nconf, - struct daemon_conf *oconf ); -#else -static inline int auditd_tcp_listen_init ( struct ev_loop *loop, - struct daemon_conf *config ) -{ - return 0; -} - -static inline void auditd_tcp_listen_uninit ( struct ev_loop *loop, - struct daemon_conf *config ) -{ - return; -} - -static inline void auditd_tcp_listen_reconfigure ( struct daemon_conf *nconf, - struct daemon_conf *oconf ) -{ - return; -} -#endif /* USE_LISTENER */ - -#endif diff --git a/framework/src/audit/src/auditd-reconfig.c b/framework/src/audit/src/auditd-reconfig.c deleted file mode 100644 index ac3bd030..00000000 --- a/framework/src/audit/src/auditd-reconfig.c +++ /dev/null @@ -1,128 +0,0 @@ -/* auditd-reconfig.c -- - * Copyright 2005 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#include "config.h" -#include <pthread.h> -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include "libaudit.h" -#include "auditd-event.h" -#include "auditd-config.h" -#include "private.h" - -/* This is the configuration manager code */ -static pthread_t config_thread; -static pthread_mutex_t config_lock; -static void *config_thread_main(void *arg); - -void init_config_manager(void) -{ - pthread_mutex_init(&config_lock, NULL); - audit_msg(LOG_DEBUG, "config_manager init complete"); -} - -int start_config_manager(struct auditd_reply_list *rep) -{ - int retval, rc = 0; - - retval = pthread_mutex_trylock(&config_lock); - if (retval == 0) { - pthread_attr_t detached; - - pthread_attr_init(&detached); - pthread_attr_setdetachstate(&detached, - PTHREAD_CREATE_DETACHED); - - if (pthread_create(&config_thread, &detached, - config_thread_main, rep) < 0) { - audit_msg(LOG_ERR, - "Couldn't create config thread, no config changes"); - free(rep); - pthread_mutex_unlock(&config_lock); - rc = 1; - } - pthread_attr_destroy(&detached); - } else { - audit_msg(LOG_ERR, - "Config thread already running, no config changes"); - free(rep); - rc = 1; - } - return rc; -} - -void shutdown_config(void) -{ - pthread_cancel(config_thread); -} - -static void *config_thread_main(void *arg) -{ - sigset_t sigs; - struct auditd_reply_list *rep = (struct auditd_reply_list *)arg; - struct daemon_conf new_config; - extern int send_audit_event(int type, const char *str); - - /* This is a worker thread. Don't handle signals. */ - sigemptyset(&sigs); - sigaddset(&sigs, SIGALRM); - sigaddset(&sigs, SIGTERM); - sigaddset(&sigs, SIGHUP); - sigaddset(&sigs, SIGUSR1); - sigaddset(&sigs, SIGUSR2); - pthread_sigmask(SIG_SETMASK, &sigs, NULL); - - if (load_config(&new_config, TEST_AUDITD) == 0) { - /* We will re-use the current reply */ - new_config.sender_uid = rep->reply.signal_info->uid; - new_config.sender_pid = rep->reply.signal_info->pid; - if (rep->reply.len > 24) - new_config.sender_ctx = - strdup(rep->reply.signal_info->ctx); - else - new_config.sender_ctx = strdup("?"); - memcpy(rep->reply.msg.data, &new_config, sizeof(new_config)); - rep->reply.conf = (struct daemon_conf *)rep->reply.msg.data; - rep->reply.type = AUDIT_DAEMON_RECONFIG; - enqueue_event(rep); - } else { - // need to send a failed event message - char txt[MAX_AUDIT_MESSAGE_LENGTH]; - snprintf(txt, sizeof(txt), - "reconfig aborted, sending auid=%u pid=%d subj=%s res=failed", - rep->reply.signal_info->uid, - rep->reply.signal_info->pid, - (rep->reply.len > 24) ? - rep->reply.signal_info->ctx : "?"); - send_audit_event(AUDIT_DAEMON_CONFIG, txt); - free_config(&new_config); - free(rep); - } - - pthread_mutex_unlock(&config_lock); - return NULL; -} - diff --git a/framework/src/audit/src/auditd-sendmail.c b/framework/src/audit/src/auditd-sendmail.c deleted file mode 100644 index ab0b901f..00000000 --- a/framework/src/audit/src/auditd-sendmail.c +++ /dev/null @@ -1,116 +0,0 @@ -/* auditd-sendmail.c -- - * Copyright 2005 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#include "config.h" -#include <stdio.h> -#include <unistd.h> // for access() -#include <string.h> -#include <stdlib.h> -#include <signal.h> -#include "libaudit.h" -#include "private.h" -#include "auditd-config.h" - -extern const char *email_command; -static int safe_popen(pid_t *pid, const char *mail_acct); - -// returns 1 on error & 0 if OK -int sendmail(const char *subject, const char *content, const char *mail_acct) -{ - pid_t pid; - - if (access(email_command, 01) == 0) - { - FILE *mail; - int fd; - - fd = safe_popen(&pid, mail_acct); - if (fd < 0) - return 1; - mail = fdopen(fd, "w"); - if (mail == NULL) { - kill(pid, SIGKILL); - close(fd); - audit_msg(LOG_ERR, "Error - starting mail"); - return 1; - } - - fprintf(mail, "To: %s\n", mail_acct); - fprintf(mail, "From: root\n"); -// fprintf(mail, "X-Sender: %s\n", mail_acct); - fprintf(mail, "Subject: %s\n\n", subject); // End of Header - fprintf(mail, "%s\n", content); - fprintf(mail, ".\n\n"); // Close it up... - fclose(mail); - return 0; - } else - audit_msg(LOG_ERR, "Error - %s isn't executable", - email_command); - return 1; -} - -static int safe_popen(pid_t *pid, const char *mail_acct) -{ - char *argv[4]; - char acct[256]; - int pipe_fd[2]; - struct sigaction sa; - - if (pipe(pipe_fd)) { - audit_msg(LOG_ALERT, - "Audit daemon failed to create pipe while sending email alert"); - return -1; - } - - *pid = fork(); - if (*pid < 0) { - close(pipe_fd[0]); - close(pipe_fd[1]); - audit_msg(LOG_ALERT, - "Audit daemon failed to fork while sending email alert"); - return -1; - } - if (*pid) { /* Parent */ - close(pipe_fd[0]); // adjust pipe - return pipe_fd[1]; - } - /* Child */ - sigfillset (&sa.sa_mask); - sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); - - close(pipe_fd[1]); // adjust pipe - dup2(pipe_fd[0], 0); - - /* Make email acct param */ - snprintf(acct, sizeof(acct), "-f%s", mail_acct); - - /* Stuff arg list */ - argv[0] = (char *)email_command; - argv[1] = (char *)"-t"; - argv[2] = acct; - argv[3] = NULL; - execve(email_command, argv, NULL); - audit_msg(LOG_ALERT, "Audit daemon failed to exec %s", email_command); - exit(1); -} - diff --git a/framework/src/audit/src/auditd.c b/framework/src/audit/src/auditd.c deleted file mode 100644 index 5afebac2..00000000 --- a/framework/src/audit/src/auditd.c +++ /dev/null @@ -1,917 +0,0 @@ -/* auditd.c -- - * Copyright 2004-09,2011,2013 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * Rickard E. (Rik) Faith <faith@redhat.com> - */ - -#include "config.h" -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <stdlib.h> -#include <signal.h> -#include <errno.h> -#include <string.h> -#include <time.h> -#include <sys/resource.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <fcntl.h> -#include <pthread.h> -#include <sys/utsname.h> -#include <getopt.h> - -#include "libaudit.h" -#include "auditd-event.h" -#include "auditd-config.h" -#include "auditd-dispatch.h" -#include "auditd-listen.h" -#include "private.h" - -#include "ev.h" - -#define EV_STOP() ev_unloop (ev_default_loop (EVFLAG_AUTO), EVUNLOOP_ALL), stop = 1; - -#define DEFAULT_BUF_SZ 448 -#define DMSG_SIZE (DEFAULT_BUF_SZ + 48) -#define SUCCESS 0 -#define FAILURE 1 -#define SUBJ_LEN 4097 - -/* Global Data */ -volatile int stop = 0; - -/* Local data */ -static int fd = -1; -static struct daemon_conf config; -static const char *pidfile = "/var/run/auditd.pid"; -static int init_pipe[2]; -static int do_fork = 1; -static struct auditd_reply_list *rep = NULL; -static int hup_info_requested = 0; -static int usr1_info_requested = 0, usr2_info_requested = 0; -static char subj[SUBJ_LEN]; - -/* Local function prototypes */ -int send_audit_event(int type, const char *str); -static void close_down(void); -static void clean_exit(void); -static int get_reply(int fd, struct audit_reply *rep, int seq); -static char *getsubj(char *subj); - -enum startup_state {startup_disable=0, startup_enable, startup_nochange, - startup_INVALID}; -static const char *startup_states[] = {"disable", "enable", "nochange"}; - -/* - * Output a usage message - */ -static void usage(void) -{ - fprintf(stderr, "Usage: auditd [-f] [-l] [-n] [-s %s|%s|%s]\n", - startup_states[startup_disable], - startup_states[startup_enable], - startup_states[startup_nochange]); - - exit(2); -} - - -/* - * SIGTERM handler - */ -static void term_handler(struct ev_loop *loop, struct ev_signal *sig, - int revents) -{ - EV_STOP (); -} - -/* - * Used with sigalrm to force exit - */ -static void thread_killer( int sig ) -{ - exit(0); -} - -/* - * Used with sigalrm to force exit - */ -static void hup_handler( struct ev_loop *loop, struct ev_signal *sig, int revents ) -{ - int rc; - - rc = audit_request_signal_info(fd); - if (rc < 0) - send_audit_event(AUDIT_DAEMON_CONFIG, - "auditd error getting hup info - no change, sending auid=? pid=? subj=? res=failed"); - else - hup_info_requested = 1; -} - -/* - * Used to force log rotation - */ -static void user1_handler(struct ev_loop *loop, struct ev_signal *sig, - int revents) -{ - int rc; - - rc = audit_request_signal_info(fd); - if (rc < 0) - send_audit_event(AUDIT_DAEMON_ROTATE, - "auditd error getting usr1 info - no change, sending auid=? pid=? subj=? res=failed"); - else - usr1_info_requested = 1; -} - -/* - * Used to resume logging - */ -static void user2_handler( struct ev_loop *loop, struct ev_signal *sig, int revents ) -{ - int rc; - - rc = audit_request_signal_info(fd); - if (rc < 0) { - resume_logging(); - send_audit_event(AUDIT_DAEMON_RESUME, - "auditd resuming logging, sending auid=? pid=? subj=? res=success"); - } else - usr2_info_requested = 1; -} - -/* - * Used with email alerts to cleanup - */ -static void child_handler(struct ev_loop *loop, struct ev_signal *sig, - int revents) -{ - int pid; - - while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) { - if (pid == dispatcher_pid()) - dispatcher_reaped(); - } -} - -static void distribute_event(struct auditd_reply_list *rep) -{ - int attempt = 0; - - /* Make first attempt to send to plugins */ - if (dispatch_event(&rep->reply, attempt) == 1) - attempt++; /* Failed sending, retry after writing to disk */ - - /* End of Event is for realtime interface - skip local logging of it */ - if (rep->reply.type != AUDIT_EOE) { - int yield = rep->reply.type <= AUDIT_LAST_DAEMON && - rep->reply.type >= AUDIT_FIRST_DAEMON ? 1 : 0; - /* Write to local disk */ - enqueue_event(rep); - if (yield) { - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 2 * 1000 * 1000; // 2 milliseconds - nanosleep(&ts, NULL); // Let other thread try to log it - } - } else - free(rep); // This function takes custody of the memory - - // FIXME: This is commented out since it fails to work. The - // problem is that the logger thread free's the buffer. Probably - // need a way to flag in the buffer if logger thread should free or - // move the free to this function. - - /* Last chance to send...maybe the pipe is empty now. */ -// if (attempt) -// dispatch_event(&rep->reply, attempt); -} - -/* - * This function is used to send start, stop, and abort messages - * to the audit log. - */ -static unsigned seq_num = 0; -int send_audit_event(int type, const char *str) -{ - struct auditd_reply_list *rep; - struct timeval tv; - - if ((rep = malloc(sizeof(*rep))) == NULL) { - audit_msg(LOG_ERR, "Cannot allocate audit reply"); - return 1; - } - - rep->reply.type = type; - rep->reply.message = (char *)malloc(DMSG_SIZE); - if (rep->reply.message == NULL) { - free(rep); - audit_msg(LOG_ERR, "Cannot allocate local event message"); - return 1; - } - if (seq_num == 0) { - srand(time(NULL)); - seq_num = rand()%10000; - } else - seq_num++; - if (gettimeofday(&tv, NULL) == 0) { - rep->reply.len = snprintf((char *)rep->reply.message, - DMSG_SIZE, "audit(%lu.%03u:%u): %s", - tv.tv_sec, (unsigned)(tv.tv_usec/1000), seq_num, str); - } else { - rep->reply.len = snprintf((char *)rep->reply.message, - DMSG_SIZE, "audit(%lu.%03u:%u): %s", - (unsigned long)time(NULL), 0, seq_num, str); - } - if (rep->reply.len > DMSG_SIZE) - rep->reply.len = DMSG_SIZE; - - distribute_event(rep); - return 0; -} - -static int write_pid_file(void) -{ - int pidfd, len; - char val[16]; - - len = snprintf(val, sizeof(val), "%u\n", getpid()); - if (len <= 0) { - audit_msg(LOG_ERR, "Pid error (%s)", strerror(errno)); - pidfile = 0; - return 1; - } - pidfd = open(pidfile, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644); - if (pidfd < 0) { - audit_msg(LOG_ERR, "Unable to set pidfile (%s)", - strerror(errno)); - pidfile = 0; - return 1; - } - if (write(pidfd, val, (unsigned int)len) != len) { - audit_msg(LOG_ERR, "Unable to write pidfile (%s)", - strerror(errno)); - close(pidfd); - pidfile = 0; - return 1; - } - close(pidfd); - return 0; -} - -static void avoid_oom_killer(void) -{ - int oomfd, len, rc; - char *score = NULL; - - /* New kernels use different technique */ - if ((oomfd = open("/proc/self/oom_score_adj", - O_NOFOLLOW | O_WRONLY)) >= 0) { - score = "-1000"; - } else if ((oomfd = open("/proc/self/oom_adj", - O_NOFOLLOW | O_WRONLY)) >= 0) { - score = "-17"; - } else { - audit_msg(LOG_NOTICE, "Cannot open out of memory adjuster"); - return; - } - - len = strlen(score); - rc = write(oomfd, score, len); - if (rc != len) - audit_msg(LOG_NOTICE, "Unable to adjust out of memory score"); - - close(oomfd); -} - -/* - * This function will take care of becoming a daemon. The parent - * will wait until the child notifies it by writing into a special - * pipe to signify that it successfully initialized. This prevents - * a race in the init script where rules get loaded before the daemon - * is ready and they wind up in syslog. The child returns 0 on success - * and nonzero on failure. The parent returns nonzero on failure. On - * success, the parent calls _exit with 0. - */ -static int become_daemon(void) -{ - int fd, rc; - pid_t pid; - int status; - - if (do_fork) { - if (pipe(init_pipe) || - fcntl(init_pipe[0], F_SETFD, FD_CLOEXEC) || - fcntl(init_pipe[0], F_SETFD, FD_CLOEXEC)) - return -1; - pid = fork(); - } else - pid = 0; - - switch (pid) - { - case 0: - /* No longer need this... */ - if (do_fork) - close(init_pipe[0]); - - /* Open stdin,out,err to /dev/null */ - fd = open("/dev/null", O_RDWR); - if (fd < 0) { - audit_msg(LOG_ERR, "Cannot open /dev/null"); - return -1; - } - if ((dup2(fd, 0) < 0) || (dup2(fd, 1) < 0) || - (dup2(fd, 2) < 0)) { - audit_msg(LOG_ERR, - "Cannot reassign descriptors to /dev/null"); - close(fd); - return -1; - } - close(fd); - - /* Change to '/' */ - rc = chdir("/"); - if (rc < 0) { - audit_msg(LOG_ERR, - "Cannot change working directory to /"); - return -1; - } - - /* Become session/process group leader */ - setsid(); - break; - case -1: - return -1; - break; - default: - /* Wait for the child to say its done */ - rc = read(init_pipe[0], &status, sizeof(status)); - if (rc < 0) - return -1; - - /* Success - die a happy death */ - if (status == SUCCESS) - _exit(0); - else - return -1; - break; - } - - return 0; -} - -static void tell_parent(int status) -{ - int rc; - - if (config.daemonize != D_BACKGROUND || do_fork == 0) - return; - do { - rc = write(init_pipe[1], &status, sizeof(status)); - } while (rc < 0 && errno == EINTR); -} - -static void netlink_handler(struct ev_loop *loop, struct ev_io *io, - int revents) -{ - if (rep == NULL) { - if ((rep = malloc(sizeof(*rep))) == NULL) { - char emsg[DEFAULT_BUF_SZ]; - if (*subj) - snprintf(emsg, sizeof(emsg), - "auditd error halt, auid=%u pid=%d subj=%s res=failed", - audit_getloginuid(), getpid(), subj); - else - snprintf(emsg, sizeof(emsg), - "auditd error halt, auid=%u pid=%d res=failed", - audit_getloginuid(), getpid()); - EV_STOP (); - send_audit_event(AUDIT_DAEMON_ABORT, emsg); - audit_msg(LOG_ERR, - "Cannot allocate audit reply, exiting"); - close_down(); - if (pidfile) - unlink(pidfile); - shutdown_dispatcher(); - return; - } - } - if (audit_get_reply(fd, &rep->reply, - GET_REPLY_NONBLOCKING, 0) > 0) { - switch (rep->reply.type) - { /* For now dont process these */ - case NLMSG_NOOP: - case NLMSG_DONE: - case NLMSG_ERROR: - case AUDIT_GET: /* Or these */ - case AUDIT_LIST_RULES: - case AUDIT_FIRST_DAEMON...AUDIT_LAST_DAEMON: - break; - case AUDIT_SIGNAL_INFO: - if (hup_info_requested) { - audit_msg(LOG_DEBUG, - "HUP detected, starting config manager"); - if (start_config_manager(rep)) { - send_audit_event( - AUDIT_DAEMON_CONFIG, - "auditd error getting hup info - no change," - " sending auid=? pid=? subj=? res=failed"); - } - rep = NULL; - hup_info_requested = 0; - } else if (usr1_info_requested) { - char usr1[MAX_AUDIT_MESSAGE_LENGTH]; - if (rep->reply.len == 24) { - snprintf(usr1, sizeof(usr1), - "auditd sending auid=? pid=? subj=?"); - } else { - snprintf(usr1, sizeof(usr1), - "auditd sending auid=%u pid=%d subj=%s", - rep->reply.signal_info->uid, - rep->reply.signal_info->pid, - rep->reply.signal_info->ctx); - } - send_audit_event(AUDIT_DAEMON_ROTATE, usr1); - usr1_info_requested = 0; - } else if (usr2_info_requested) { - char usr2[MAX_AUDIT_MESSAGE_LENGTH]; - if (rep->reply.len == 24) { - snprintf(usr2, sizeof(usr2), - "auditd resuming logging, " - "sending auid=? pid=? subj=? " - "res=success"); - } else { - snprintf(usr2, sizeof(usr2), - "auditd resuming logging, " - "sending auid=%u pid=%d subj=%s res=success", - rep->reply.signal_info->uid, - rep->reply.signal_info->pid, - rep->reply.signal_info->ctx); - } - resume_logging(); - send_audit_event(AUDIT_DAEMON_RESUME, usr2); - usr2_info_requested = 0; - } - break; - default: - distribute_event(rep); - rep = NULL; - break; - } - } else { - if (errno == EFBIG) { - // FIXME do err action - } - } -} - -int main(int argc, char *argv[]) -{ - struct sigaction sa; - struct rlimit limit; - int i, c, rc; - int opt_foreground = 0, opt_allow_links = 0; - enum startup_state opt_startup = startup_enable; - extern char *optarg; - extern int optind; - struct ev_loop *loop; - struct ev_io netlink_watcher; - struct ev_signal sigterm_watcher; - struct ev_signal sighup_watcher; - struct ev_signal sigusr1_watcher; - struct ev_signal sigusr2_watcher; - struct ev_signal sigchld_watcher; - - /* Get params && set mode */ - while ((c = getopt(argc, argv, "flns:")) != -1) { - switch (c) { - case 'f': - opt_foreground = 1; - break; - case 'l': - opt_allow_links=1; - break; - case 'n': - do_fork = 0; - break; - case 's': - for (i=0; i<startup_INVALID; i++) { - if (strncmp(optarg, startup_states[i], - strlen(optarg)) == 0) { - opt_startup = i; - break; - } - } - if (i == startup_INVALID) { - fprintf(stderr, "unknown startup mode '%s'\n", - optarg); - usage(); - } - break; - default: - usage(); - } - } - - /* check for trailing command line following options */ - if (optind < argc) { - usage(); - } - - if (opt_allow_links) - set_allow_links(1); - - if (opt_foreground) { - config.daemonize = D_FOREGROUND; - set_aumessage_mode(MSG_STDERR, DBG_YES); - } else { - config.daemonize = D_BACKGROUND; - set_aumessage_mode(MSG_SYSLOG, DBG_NO); - (void) umask( umask( 077 ) | 022 ); - } - -#ifndef DEBUG - /* Make sure we are root */ - if (getuid() != 0) { - fprintf(stderr, "You must be root to run this program.\n"); - return 4; - } -#endif - - /* Register sighandlers */ - sa.sa_flags = 0 ; - sigemptyset( &sa.sa_mask ) ; - /* Ignore all signals by default */ - sa.sa_handler = SIG_IGN; - for (i=1; i<NSIG; i++) - sigaction( i, &sa, NULL ); - - atexit(clean_exit); - - /* Raise the rlimits in case we're being started from a shell - * with restrictions. Not a fatal error. */ - limit.rlim_cur = RLIM_INFINITY; - limit.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_FSIZE, &limit); - setrlimit(RLIMIT_CPU, &limit); - - /* Load the Configuration File */ - if (load_config(&config, TEST_AUDITD)) - return 6; - - if (config.priority_boost != 0) { - errno = 0; - rc = nice((int)-config.priority_boost); - if (rc == -1 && errno) { - audit_msg(LOG_ERR, "Cannot change priority (%s)", - strerror(errno)); - return 1; - } - } - - /* Daemonize or stay in foreground for debugging */ - if (config.daemonize == D_BACKGROUND) { - if (become_daemon() != 0) { - audit_msg(LOG_ERR, "Cannot daemonize (%s)", - strerror(errno)); - tell_parent(FAILURE); - return 1; - } - openlog("auditd", LOG_PID, LOG_DAEMON); - } - - /* Init netlink */ - if ((fd = audit_open()) < 0) { - audit_msg(LOG_ERR, "Cannot open netlink audit socket"); - tell_parent(FAILURE); - return 1; - } - - /* Init the event handler thread */ - write_pid_file(); - if (init_event(&config)) { - if (pidfile) - unlink(pidfile); - tell_parent(FAILURE); - return 1; - } - - if (init_dispatcher(&config)) { - if (pidfile) - unlink(pidfile); - tell_parent(FAILURE); - return 1; - } - - /* Get machine name ready for use */ - if (resolve_node(&config)) { - if (pidfile) - unlink(pidfile); - tell_parent(FAILURE); - return 1; - } - - /* Write message to log that we are alive */ - { - struct utsname ubuf; - char start[DEFAULT_BUF_SZ]; - const char *fmt = audit_lookup_format((int)config.log_format); - if (fmt == NULL) - fmt = "UNKNOWN"; - if (uname(&ubuf) != 0) { - if (pidfile) - unlink(pidfile); - tell_parent(FAILURE); - return 1; - } - if (getsubj(subj)) - snprintf(start, sizeof(start), - "auditd start, ver=%s format=%s " - "kernel=%.56s auid=%u pid=%d subj=%s res=success", - VERSION, fmt, ubuf.release, - audit_getloginuid(), getpid(), subj); - else - snprintf(start, sizeof(start), - "auditd start, ver=%s format=%s " - "kernel=%.56s auid=%u pid=%d res=success", - VERSION, fmt, ubuf.release, - audit_getloginuid(), getpid()); - if (send_audit_event(AUDIT_DAEMON_START, start)) { - audit_msg(LOG_ERR, "Cannot send start message"); - if (pidfile) - unlink(pidfile); - shutdown_dispatcher(); - tell_parent(FAILURE); - return 1; - } - } - - /* Tell kernel not to kill us */ - avoid_oom_killer(); - - /* let config manager init */ - init_config_manager(); - - if (opt_startup != startup_nochange && (audit_is_enabled(fd) < 2) && - audit_set_enabled(fd, (int)opt_startup) < 0) { - char emsg[DEFAULT_BUF_SZ]; - if (*subj) - snprintf(emsg, sizeof(emsg), - "auditd error halt, auid=%u pid=%d subj=%s res=failed", - audit_getloginuid(), getpid(), subj); - else - snprintf(emsg, sizeof(emsg), - "auditd error halt, auid=%u pid=%d res=failed", - audit_getloginuid(), getpid()); - stop = 1; - send_audit_event(AUDIT_DAEMON_ABORT, emsg); - audit_msg(LOG_ERR, - "Unable to set initial audit startup state to '%s', exiting", - startup_states[opt_startup]); - close_down(); - if (pidfile) - unlink(pidfile); - shutdown_dispatcher(); - tell_parent(FAILURE); - return 1; - } - - /* Tell the kernel we are alive */ - if (audit_set_pid(fd, getpid(), WAIT_YES) < 0) { - char emsg[DEFAULT_BUF_SZ]; - if (*subj) - snprintf(emsg, sizeof(emsg), - "auditd error halt, auid=%u pid=%d subj=%s res=failed", - audit_getloginuid(), getpid(), subj); - else - snprintf(emsg, sizeof(emsg), - "auditd error halt, auid=%u pid=%d res=failed", - audit_getloginuid(), getpid()); - stop = 1; - send_audit_event(AUDIT_DAEMON_ABORT, emsg); - audit_msg(LOG_ERR, "Unable to set audit pid, exiting"); - close_down(); - if (pidfile) - unlink(pidfile); - shutdown_dispatcher(); - tell_parent(FAILURE); - return 1; - } - - /* Depending on value of opt_startup (-s) set initial audit state */ - loop = ev_default_loop (EVFLAG_NOENV); - - ev_io_init (&netlink_watcher, netlink_handler, fd, EV_READ); - ev_io_start (loop, &netlink_watcher); - - ev_signal_init (&sigterm_watcher, term_handler, SIGTERM); - ev_signal_start (loop, &sigterm_watcher); - - ev_signal_init (&sighup_watcher, hup_handler, SIGHUP); - ev_signal_start (loop, &sighup_watcher); - - ev_signal_init (&sigusr1_watcher, user1_handler, SIGUSR1); - ev_signal_start (loop, &sigusr1_watcher); - - ev_signal_init (&sigusr2_watcher, user2_handler, SIGUSR2); - ev_signal_start (loop, &sigusr2_watcher); - - ev_signal_init (&sigchld_watcher, child_handler, SIGCHLD); - ev_signal_start (loop, &sigchld_watcher); - - if (auditd_tcp_listen_init (loop, &config)) { - char emsg[DEFAULT_BUF_SZ]; - if (*subj) - snprintf(emsg, sizeof(emsg), - "auditd error halt, auid=%u pid=%d subj=%s res=failed", - audit_getloginuid(), getpid(), subj); - else - snprintf(emsg, sizeof(emsg), - "auditd error halt, auid=%u pid=%d res=failed", - audit_getloginuid(), getpid()); - stop = 1; - send_audit_event(AUDIT_DAEMON_ABORT, emsg); - tell_parent(FAILURE); - } else { - /* Now tell parent that everything went OK */ - tell_parent(SUCCESS); - audit_msg(LOG_NOTICE, - "Init complete, auditd %s listening for events (startup state %s)", - VERSION, - startup_states[opt_startup]); - } - - /* Parent should be gone by now... */ - if (do_fork) - close(init_pipe[1]); - - // Init complete, start event loop - if (!stop) - ev_loop (loop, 0); - - auditd_tcp_listen_uninit (loop, &config); - - // Tear down IO watchers Part 1 - ev_signal_stop (loop, &sighup_watcher); - ev_signal_stop (loop, &sigusr1_watcher); - ev_signal_stop (loop, &sigusr2_watcher); - ev_signal_stop (loop, &sigterm_watcher); - - /* Write message to log that we are going down */ - rc = audit_request_signal_info(fd); - if (rc > 0) { - struct audit_reply trep; - - rc = get_reply(fd, &trep, rc); - if (rc > 0) { - char txt[MAX_AUDIT_MESSAGE_LENGTH]; - snprintf(txt, sizeof(txt), - "auditd normal halt, sending auid=%u " - "pid=%d subj=%s res=success", - trep.signal_info->uid, - trep.signal_info->pid, - trep.signal_info->ctx); - send_audit_event(AUDIT_DAEMON_END, txt); - } - } - if (rc <= 0) - send_audit_event(AUDIT_DAEMON_END, - "auditd normal halt, sending auid=? " - "pid=? subj=? res=success"); - free(rep); - - // Tear down IO watchers Part 2 - ev_io_stop (loop, &netlink_watcher); - - // Give DAEMON_END event a little time to be sent in case - // of remote logging - usleep(10000); // 10 milliseconds - shutdown_dispatcher(); - - // Tear down IO watchers Part 3 - ev_signal_stop (loop, &sigchld_watcher); - - close_down(); - free_config(&config); - ev_default_destroy(); - - return 0; -} - -static void close_down(void) -{ - struct sigaction sa; - - /* We are going down. Give the event thread a chance to shutdown. - Just in case it hangs, set a timer to get us out of trouble. */ - sa.sa_flags = 0 ; - sigemptyset( &sa.sa_mask ) ; - sa.sa_handler = thread_killer; - sigaction( SIGALRM, &sa, NULL ); - shutdown_events(); -} - - -/* - * A clean exit means : - * 1) we log that we are going down - * 2) deregister with kernel - * 3) close the netlink socket - */ -static void clean_exit(void) -{ - audit_msg(LOG_INFO, "The audit daemon is exiting."); - if (fd >= 0) { - audit_set_pid(fd, 0, WAIT_NO); - audit_close(fd); - } - if (pidfile) - unlink(pidfile); - closelog(); -} - -/* - * This function is used to get the reply for term info. - * Returns 1 on success & -1 on failure. - */ -static int get_reply(int fd, struct audit_reply *rep, int seq) -{ - int rc, i; - int timeout = 30; /* tenths of seconds */ - - for (i = 0; i < timeout; i++) { - struct timeval t; - fd_set read_mask; - - t.tv_sec = 0; - t.tv_usec = 100000; /* .1 second */ - FD_ZERO(&read_mask); - FD_SET(fd, &read_mask); - do { - rc = select(fd+1, &read_mask, NULL, NULL, &t); - } while (rc < 0 && errno == EINTR); - rc = audit_get_reply(fd, rep, - GET_REPLY_NONBLOCKING, 0); - if (rc > 0) { - /* Don't make decisions based on wrong packet */ - if (rep->nlh->nlmsg_seq != seq) - continue; - - /* If its not what we are expecting, keep looping */ - if (rep->type == AUDIT_SIGNAL_INFO) - return 1; - - /* If we get done or error, break out */ - if (rep->type == NLMSG_DONE || rep->type == NLMSG_ERROR) - break; - } - } - return -1; -} - -//get the subj of the daemon -static char *getsubj(char *subj) -{ - pid_t pid = getpid(); - char filename[48]; - ssize_t num_read; - int fd; - - snprintf(filename, sizeof(filename), "/proc/%u/attr/current", pid); - fd = open(filename, O_RDONLY); - if(fd == -1) { - subj[0] = 0; - return NULL; - } - do { - num_read = read(fd, subj, SUBJ_LEN-1); - } while (num_read < 0 && errno == EINTR); - close(fd); - if(num_read <= 0) { - subj[0] = 0; - return NULL; - } - subj[num_read] = '\0'; - return subj; -} - diff --git a/framework/src/audit/src/aureport-options.c b/framework/src/audit/src/aureport-options.c deleted file mode 100644 index 7508417f..00000000 --- a/framework/src/audit/src/aureport-options.c +++ /dev/null @@ -1,722 +0,0 @@ -/* aureport-options.c - parse commandline options and configure aureport - * Copyright 2005-08,2010-11,2014 Red Hat Inc., Durham, North Carolina. - * Copyright (c) 2011 IBM Corp. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * Marcelo Henrique Cerri <mhcerri@br.ibm.com> - */ - -#include "config.h" -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <pwd.h> -#include <grp.h> -#include <time.h> -#include "aureport-options.h" -#include "ausearch-time.h" -#include "libaudit.h" - - -/* Global vars that will be accessed by the main program */ -char *user_file = NULL; -int force_logs = 0; -int no_config = 0; - -/* These are for compatibility with parser */ -unsigned int event_id = -1; -uid_t event_uid = -1, event_loginuid = -2, event_euid = -1; -gid_t event_gid = -1, event_egid = -1; -slist *event_node_list = NULL; -const char *event_key = NULL; -const char *event_filename = NULL; -const char *event_exe = NULL; -const char *event_comm = NULL; -const char *event_hostname = NULL; -const char *event_terminal = NULL; -const char *event_subject = NULL; -const char *event_object = NULL; -const char *event_uuid = NULL; -const char *event_vmname = NULL; -long long event_exit = 0; -int event_exit_is_set = 0; -int event_ppid = -1, event_session_id = -2; -int event_debug = 0, event_machine = -1; - -/* These are used by aureport */ -const char *dummy = "dummy"; -report_type_t report_type = RPT_UNSET; -report_det_t report_detail = D_UNSET; -report_t report_format = RPT_DEFAULT; -failed_t event_failed = F_BOTH; -conf_act_t event_conf_act = C_NEITHER; -success_t event_success = S_SUCCESS; -int event_pid = 0; - -struct nv_pair { - int value; - const char *name; -}; - -enum { R_INFILE, R_TIME_END, R_TIME_START, R_VERSION, R_SUMMARY, R_LOG_TIMES, - R_CONFIGS, R_LOGINS, R_USERS, R_TERMINALS, R_HOSTS, R_EXES, R_FILES, - R_AVCS, R_SYSCALLS, R_PIDS, R_EVENTS, R_ACCT_MODS, - R_INTERPRET, R_HELP, R_ANOMALY, R_RESPONSE, R_SUMMARY_DET, R_CRYPTO, - R_MAC, R_FAILED, R_SUCCESS, R_ADD, R_DEL, R_AUTH, R_NODE, R_IN_LOGS, - R_KEYS, R_TTY, R_NO_CONFIG, R_COMM, R_VIRT, R_INTEG }; - -static struct nv_pair optiontab[] = { - { R_AUTH, "-au" }, - { R_AUTH, "--auth" }, - { R_AVCS, "-a" }, - { R_AVCS, "--avc" }, - { R_ADD, "--add" }, - { R_CONFIGS, "-c" }, - { R_COMM, "--comm" }, - { R_CONFIGS, "--config" }, - { R_CRYPTO, "-cr" }, - { R_CRYPTO, "--crypto" }, - { R_DEL, "--delete" }, - { R_EVENTS, "-e" }, - { R_EVENTS, "--event" }, - { R_FILES, "-f" }, - { R_FILES, "--file" }, - { R_FAILED, "--failed" }, - { R_HOSTS, "-h" }, - { R_HOSTS, "--host" }, - { R_HELP, "--help" }, - { R_INTERPRET, "-i" }, - { R_INTERPRET, "--interpret" }, - { R_INFILE, "-if" }, - { R_INFILE, "--input" }, - { R_IN_LOGS, "--input-logs" }, - { R_INTEG, "--integrity" }, - { R_KEYS, "-k" }, - { R_KEYS, "--key" }, - { R_LOGINS, "-l" }, - { R_LOGINS, "--login" }, - { R_ACCT_MODS, "-m" }, - { R_ACCT_MODS, "--mods" }, - { R_MAC, "-ma" }, - { R_MAC, "--mac" }, - { R_NODE, "--node" }, - { R_NO_CONFIG, "-nc" }, - { R_NO_CONFIG, "--no-config" }, - { R_ANOMALY, "-n" }, - { R_ANOMALY, "--anomaly" }, - { R_PIDS, "-p" }, - { R_PIDS, "--pid" }, - { R_RESPONSE, "-r" }, - { R_RESPONSE, "--response" }, - { R_SYSCALLS, "-s" }, - { R_SYSCALLS, "--syscall" }, - { R_SUCCESS, "--success" }, - { R_SUMMARY_DET, "--summary" }, - { R_LOG_TIMES, "-t" }, - { R_LOG_TIMES, "--log" }, - { R_TIME_END, "-te"}, - { R_TIME_END, "--end"}, - { R_TERMINALS, "-tm"}, // don't like this - { R_TERMINALS, "--terminal"}, // don't like this - { R_TIME_START, "-ts" }, - { R_TTY, "--tty" }, - { R_TIME_START, "--start" }, - { R_USERS, "-u" }, - { R_USERS, "--user" }, - { R_VERSION, "-v" }, - { R_VERSION, "--version" }, - { R_EXES, "-x" }, - { R_EXES, "--executable" }, - { R_VIRT, "--virt" } -}; -#define OPTION_NAMES (sizeof(optiontab)/sizeof(optiontab[0])) - - -static int audit_lookup_option(const char *name) -{ - int i; - - for (i = 0; i < OPTION_NAMES; i++) - if (!strcmp(optiontab[i].name, name)) - return optiontab[i].value; - return -1; -} - -static void usage(void) -{ - printf("usage: aureport [options]\n" - "\t-a,--avc\t\t\tAvc report\n" - "\t-au,--auth\t\t\tAuthentication report\n" - "\t--comm\t\t\t\tCommands run report\n" - "\t-c,--config\t\t\tConfig change report\n" - "\t-cr,--crypto\t\t\tCrypto report\n" - "\t-e,--event\t\t\tEvent report\n" - "\t-f,--file\t\t\tFile name report\n" - "\t--failed\t\t\tonly failed events in report\n" - "\t-h,--host\t\t\tRemote Host name report\n" - "\t--help\t\t\t\thelp\n" - "\t-i,--interpret\t\t\tInterpretive mode\n" - "\t-if,--input <Input File name>\tuse this file as input\n" - "\t--input-logs\t\t\tUse the logs even if stdin is a pipe\n" - "\t--integrity\t\t\tIntegrity event report\n" - "\t-l,--login\t\t\tLogin report\n" - "\t-k,--key\t\t\tKey report\n" - "\t-m,--mods\t\t\tModification to accounts report\n" - "\t-ma,--mac\t\t\tMandatory Access Control (MAC) report\n" - "\t-n,--anomaly\t\t\taNomaly report\n" - "\t-nc,--no-config\t\t\tDon't include config events\n" - "\t--node <node name>\t\tOnly events from a specific node\n" - "\t-p,--pid\t\t\tPid report\n" - "\t-r,--response\t\t\tResponse to anomaly report\n" - "\t-s,--syscall\t\t\tSyscall report\n" - "\t--success\t\t\tonly success events in report\n" - "\t--summary\t\t\tsorted totals for main object in report\n" - "\t-t,--log\t\t\tLog time range report\n" - "\t-te,--end [end date] [end time]\tending date & time for reports\n" - "\t-tm,--terminal\t\t\tTerMinal name report\n" - "\t-ts,--start [start date] [start time]\tstarting data & time for reports\n" - "\t--tty\t\t\t\tReport about tty keystrokes\n" - "\t-u,--user\t\t\tUser name report\n" - "\t-v,--version\t\t\tVersion\n" - "\t--virt\t\t\t\tVirtualization report\n" - "\t-x,--executable\t\t\teXecutable name report\n" - "\tIf no report is given, the summary report will be displayed\n" - ); -} - -static int set_report(report_type_t r) -{ - if (report_type == RPT_UNSET) { - report_type = r; - return 0; - } else { - fprintf(stderr, "Error - only one report can be specified"); - return 1; - } -} - -static int set_detail(report_det_t d) -{ - if (report_detail == D_UNSET) { - report_detail = d; - return 0; - } else if (d == D_SUM) { - report_detail = d; - return 0; - } else { - return 1; - } -} - -/* - * This function examines the commandline parameters and sets various - * search options. It returns a 0 on success and < 0 on failure - */ -int check_params(int count, char *vars[]) -{ - int c = 1; - int retval = 0; - const char *optarg; - - while (c < count && retval == 0) { - // Go ahead and point to the next argument - if (c+1 < count) { - if (vars[c+1][0] != '-') - optarg = vars[c+1]; - else - optarg = NULL; - } else - optarg = NULL; - - switch (audit_lookup_option(vars[c])) { - case R_INFILE: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - user_file = strdup(optarg); - if (user_file == NULL) - retval = -1; - c++; - } - break; - case R_LOG_TIMES: - if (set_report(RPT_TIME)) - retval = -1; - else - set_detail(D_DETAILED); - break; - case R_AVCS: - if (set_report(RPT_AVC)) - retval = -1; - else { - set_detail(D_DETAILED); - event_comm = dummy; - event_subject = dummy; - event_object = dummy; - } - break; - case R_AUTH: - if (set_report(RPT_AUTH)) - retval = -1; - else { - set_detail(D_DETAILED); - event_exe = dummy; - event_hostname = dummy; - event_terminal = dummy; - event_uid = 1; - } - break; - case R_MAC: - if (set_report(RPT_MAC)) - retval = -1; - else { - set_detail(D_DETAILED); - event_loginuid = 1; - } - break; - case R_INTEG: - if (set_report(RPT_INTEG)) - retval = -1; - else { - set_detail(D_DETAILED); - event_loginuid = 1; - } - break; - case R_VIRT: - if (set_report(RPT_VIRT)) - retval = -1; - else { - set_detail(D_DETAILED); - } - break; - case R_CONFIGS: - if (set_report(RPT_CONFIG)) - retval = -1; - else { - set_detail(D_DETAILED); - event_loginuid = 1; - } - break; - case R_CRYPTO: - if (set_report(RPT_CRYPTO)) - retval = -1; - else { - set_detail(D_DETAILED); - event_loginuid = 1; - } - break; - case R_LOGINS: - if (set_report(RPT_LOGIN)) - retval = -1; - else { - set_detail(D_DETAILED); - event_exe = dummy; - event_hostname = dummy; - event_terminal = dummy; - event_loginuid = 1; - } - break; - case R_ACCT_MODS: - if (set_report(RPT_ACCT_MOD)) - retval = -1; - else { - set_detail(D_DETAILED); - event_exe = dummy; - event_hostname = dummy; - event_terminal = dummy; - event_loginuid = 1; - } - break; - case R_EVENTS: - if (set_report(RPT_EVENT)) - retval = -1; - else { -// if (!optarg) { - set_detail(D_DETAILED); - event_loginuid = 1; -// } else { -// UNIMPLEMENTED; -// set_detail(D_SPECIFIC); -// if (isdigit(optarg[0])) { -// errno = 0; -// event_id = strtoul(optarg, -// NULL, 10); -// if (errno) { -// fprintf(stderr, -// "Illegal value for audit event ID"); -// retval = -1; -// } -// c++; -// } else { -// fprintf(stderr, -// "Audit event id must be a numeric value, was %s\n", -// optarg); -// retval = -1; -// } -// } - } - break; - case R_FILES: - if (set_report(RPT_FILE)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_filename = dummy; - event_exe = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_HOSTS: - if (set_report(RPT_HOST)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_hostname = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_INTERPRET: - report_format = RPT_INTERP; - if (optarg) { - fprintf(stderr, - "Argument is NOT required for %s\n", - vars[c]); - retval = -1; - } - break; - case R_PIDS: - if (set_report(RPT_PID)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_exe = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_SYSCALLS: - if (set_report(RPT_SYSCALL)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_comm = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_TERMINALS: - if (set_report(RPT_TERM)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_terminal = dummy; - event_hostname = dummy; - event_exe = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_USERS: - if (set_report(RPT_USER)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_terminal = dummy; - event_hostname = dummy; - event_exe = dummy; - event_uid = 1; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_EXES: - if (set_report(RPT_EXE)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_terminal = dummy; - event_hostname = dummy; - event_exe = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_COMM: - if (set_report(RPT_COMM)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_terminal = dummy; - event_hostname = dummy; - event_comm = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_ANOMALY: - if (set_report(RPT_ANOMALY)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_terminal = dummy; - event_hostname = dummy; - event_exe = dummy; - event_comm = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_RESPONSE: - if (set_report(RPT_RESPONSE)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - } else { - UNIMPLEMENTED; - } - } - break; - case R_KEYS: - if (set_report(RPT_KEY)) - retval = -1; - else { - if (!optarg) { - set_detail(D_DETAILED); - event_exe = dummy; - event_key = dummy; - event_loginuid = 1; - } else { - UNIMPLEMENTED; - } - } - break; - case R_TTY: - if (set_report(RPT_TTY)) - retval = -1; - else { - set_detail(D_DETAILED); - event_session_id = 1; - event_loginuid = 1; - event_terminal = dummy; - event_comm = dummy; - } - break; - case R_TIME_END: - if (optarg) { - if ( (c+2 < count) && vars[c+2] && - (vars[c+2][0] != '-') ) { - /* Have both date and time - check order*/ - if (strchr(optarg, ':')) { - if (ausearch_time_end(vars[c+2], - optarg) != 0) - retval = -1; - } else { - if (ausearch_time_end(optarg, - vars[c+2]) != 0) - retval = -1; - } - c++; - } else { - // Check against recognized words - int t = lookup_time(optarg); - if (t >= 0) { - if (ausearch_time_end(optarg, - NULL) != 0) - retval = -1; - } else if ( (strchr(optarg, ':')) == NULL) { - /* Only have date */ - if (ausearch_time_end(optarg, - NULL) != 0) - retval = -1; - } else { - /* Only have time */ - if (ausearch_time_end(NULL, - optarg) != 0) - retval = -1; - } - } - c++; - break; - } - fprintf(stderr, - "%s requires either date and/or time\n", - vars[c]); - retval = -1; - break; - case R_TIME_START: - if (optarg) { - if ( (c+2 < count) && vars[c+2] && - (vars[c+2][0] != '-') ) { - /* Have both date and time - check order */ - if (strchr(optarg, ':')) { - if (ausearch_time_start( - vars[c+2], optarg) != 0) - retval = -1; - } else { - if (ausearch_time_start(optarg, - vars[c+2]) != 0) - retval = -1; - } - c++; - } else { - // Check against recognized words - int t = lookup_time(optarg); - if (t >= 0) { - if (ausearch_time_start(optarg, - "00:00:00") != 0) - retval = -1; - } else if ( strchr(optarg, ':') == NULL) { - /* Only have date */ - if (ausearch_time_start(optarg, - "00:00:00") != 0) - retval = -1; - } else { - /* Only have time */ - if (ausearch_time_start(NULL, - optarg) != 0) - retval = -1; - } - } - c++; - break; - } - fprintf(stderr, - "%s requires either date and/or time\n", - vars[c]); - retval = -1; - break; - case R_NODE: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - snode sn; - c++; - - if (!event_node_list) { - event_node_list = malloc(sizeof (slist)); - if (!event_node_list) { - retval = -1; - break; - } - slist_create(event_node_list); - } - - sn.str = strdup(optarg); - sn.key = NULL; - sn.hits=0; - slist_append(event_node_list, &sn); - } - break; - case R_SUMMARY_DET: - set_detail(D_SUM); - break; - case R_FAILED: - event_failed = F_FAILED; - break; - case R_SUCCESS: - event_failed = F_SUCCESS; - break; - case R_ADD: - event_conf_act = C_ADD; - break; - case R_DEL: - event_conf_act = C_DEL; - break; - case R_IN_LOGS: - force_logs = 1; - break; - case R_NO_CONFIG: - no_config = 1; - break; - case R_VERSION: - printf("aureport version %s\n", VERSION); - exit(0); - break; - case R_HELP: - usage(); - exit(0); - break; - default: - fprintf(stderr, "%s is an unsupported option\n", - vars[c]); - retval = -1; - break; - } - c++; - } - - if (retval >= 0) { - if (report_type == RPT_UNSET) { - if (set_report(RPT_SUMMARY)) - retval = -1; - else { - set_detail(D_SUM); - event_filename = dummy; - event_hostname = dummy; - event_terminal = dummy; - event_exe = dummy; - event_comm = dummy; - event_key = dummy; - event_loginuid = 1; - } - } - } else - usage(); - - return retval; -} - diff --git a/framework/src/audit/src/aureport-options.h b/framework/src/audit/src/aureport-options.h deleted file mode 100644 index a559f645..00000000 --- a/framework/src/audit/src/aureport-options.h +++ /dev/null @@ -1,55 +0,0 @@ -/* aureport-options.h -- - * Copyright 2005-06, 2008,2014 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#ifndef AUREPORT_OPTIONS_H -#define AUREPORT_OPTIONS_H - -#include <time.h> -#include <sys/types.h> -#include "ausearch-common.h" - -/* Global variables that describe what search is to be performed */ -extern const char *event_context; - -typedef enum { RPT_UNSET, RPT_TIME, RPT_SUMMARY, RPT_AVC, RPT_MAC, - RPT_CONFIG, RPT_EVENT, RPT_FILE, RPT_HOST, RPT_LOGIN, - RPT_ACCT_MOD, RPT_PID, RPT_SYSCALL, RPT_TERM, RPT_USER, - RPT_EXE, RPT_ANOMALY, RPT_RESPONSE, RPT_CRYPTO, - RPT_AUTH, RPT_KEY, RPT_TTY, RPT_COMM, RPT_VIRT, - RPT_INTEG } report_type_t; - -typedef enum { D_UNSET, D_SUM, D_DETAILED, D_SPECIFIC } report_det_t; - -extern report_type_t report_type; -extern report_det_t report_detail; -extern report_t report_format; - - -/* Function to process commandline options */ -extern int check_params(int count, char *vars[]); - -#include <stdlib.h> -#define UNIMPLEMENTED { fprintf(stderr,"Unimplemented option\n"); exit(1); } - -#endif - diff --git a/framework/src/audit/src/aureport-output.c b/framework/src/audit/src/aureport-output.c deleted file mode 100644 index 9125d5ff..00000000 --- a/framework/src/audit/src/aureport-output.c +++ /dev/null @@ -1,1023 +0,0 @@ -/* -* aureport-output.c - Print the report -* Copyright (c) 2005-06,2008,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 "config.h" -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include "aureport-scan.h" -#include "aureport-options.h" -#include "ausearch-lookup.h" - -/* Locale functions */ -static void print_title_summary(void); -static void print_title_detailed(void); -static void do_summary_output(void); -static void do_file_summary_output(slist *sptr); -static void do_string_summary_output(slist *sptr); -static void do_user_summary_output(slist *sptr); -static void do_int_summary_output(ilist *sptr); -static void do_syscall_summary_output(ilist *sptr); -static void do_type_summary_output(ilist *sptr); - -/* Local Data */ -unsigned int line_item; - - -void print_title(void) -{ - line_item = 0U; - printf("\n"); - switch (report_detail) - { - case D_SUM: - print_title_summary(); - break; - case D_DETAILED: - print_title_detailed(); - break; - case D_SPECIFIC: - default: - break; - } -} - -static void print_title_summary(void) -{ - if (event_failed == F_FAILED) printf("Failed "); - if (event_failed == F_SUCCESS) printf("Success "); - switch (report_type) - { - case RPT_SUMMARY: - printf("Summary Report\n"); - printf("======================\n"); - break; - case RPT_AVC: - printf("Avc Object Summary Report\n"); - printf("=================================\n"); - printf("total obj\n"); - printf("=================================\n"); - break; - case RPT_MAC: - printf("MAC Summary Report\n"); - printf("==================\n"); - printf("total type\n"); - printf("==================\n"); - break; - case RPT_INTEG: - printf("Integrity Summary Report\n"); - printf("========================\n"); - printf("total type\n"); - printf("========================\n"); - break; - case RPT_VIRT: - printf("Virtualization Summary Report\n"); - printf("=============================\n"); - printf("total type\n"); - printf("=============================\n"); - break; - case RPT_CONFIG: - printf("Config Change Summary Report\n"); - printf("============================\n"); - printf("total type\n"); - printf("============================\n"); - break; - case RPT_AUTH: - printf("Authentication Summary Report\n"); - printf("=============================\n"); - printf("total acct\n"); - printf("=============================\n"); - break; - case RPT_LOGIN: - printf("Login Summary Report\n"); - printf("============================\n"); - printf("total auid\n"); - printf("============================\n"); - break; - case RPT_ACCT_MOD: - printf("Acct Modification Summary Report\n"); - printf("================================\n"); - printf("total type\n"); - printf("================================\n"); - break; - case RPT_TIME: - UNIMPLEMENTED; - break; - case RPT_EVENT: - printf("Event Summary Report\n"); - printf("======================\n"); - printf("total type\n"); - printf("======================\n"); - break; - case RPT_FILE: - printf("File Summary Report\n"); - printf("===========================\n"); - printf("total file\n"); - printf("===========================\n"); - break; - case RPT_HOST: - printf("Host Summary Report\n"); - printf("===========================\n"); - printf("total host\n"); - printf("===========================\n"); - break; - case RPT_PID: - printf("Pid Summary Report\n"); - printf("==========================\n"); - printf("total pid\n"); - printf("==========================\n"); - break; - case RPT_SYSCALL: - printf("Syscall Summary Report\n"); - printf("==========================\n"); - printf("total syscall\n"); - printf("==========================\n"); - break; - case RPT_TERM: - printf("Terminal Summary Report\n"); - printf("===============================\n"); - printf("total terminal\n"); - printf("===============================\n"); - break; - case RPT_USER: - printf("User Summary Report\n"); - printf("===========================\n"); - printf("total auid\n"); - printf("===========================\n"); - break; - case RPT_EXE: - printf("Executable Summary Report\n"); - printf("=================================\n"); - printf("total file\n"); - printf("=================================\n"); - break; - case RPT_COMM: - printf("Command Summary Report\n"); - printf("=================================\n"); - printf("total command\n"); - printf("=================================\n"); - break; - case RPT_ANOMALY: - printf("Anomaly Summary Report\n"); - printf("======================\n"); - printf("total type\n"); - printf("======================\n"); - break; - case RPT_RESPONSE: - printf("Anomaly Response Summary Report\n"); - printf("===============================\n"); - printf("total type\n"); - printf("===============================\n"); - break; - case RPT_CRYPTO: - printf("Crypto Summary Report\n"); - printf("=====================\n"); - printf("total type\n"); - printf("=====================\n"); - break; - case RPT_KEY: - printf("Key Summary Report\n"); - printf("===========================\n"); - printf("total key\n"); - printf("===========================\n"); - break; - case RPT_TTY: - UNIMPLEMENTED; - break; - default: - break; - } -} - -static void print_title_detailed(void) -{ - switch (report_type) - { - case RPT_AVC: - printf("AVC Report\n"); - printf( - "========================================================\n"); - printf( - "# date time comm subj syscall class permission obj event\n"); - printf( - "========================================================\n"); - break; - case RPT_CONFIG: - printf("Config Change Report\n"); - printf("===================================\n"); - printf("# date time type auid success event\n"); - printf("===================================\n"); - break; - case RPT_AUTH: - printf("Authentication Report\n"); - printf( - "============================================\n"); - printf( - "# date time acct host term exe success event\n"); - printf( - "============================================\n"); - break; - case RPT_LOGIN: - printf("Login Report\n"); - printf( - "============================================\n"); - printf( - "# date time auid host term exe success event\n"); - printf( - "============================================\n"); - break; - case RPT_ACCT_MOD: - printf("Account Modifications Report\n"); - printf( - "=================================================\n"); - printf( - "# date time auid addr term exe acct success event\n"); - printf( - "=================================================\n"); - break; - case RPT_TIME: - printf("Log Time Range Report\n"); - printf("=====================\n"); - break; - case RPT_EVENT: - if (report_detail == D_DETAILED) { - printf("Event Report\n"); - printf("===================================\n"); - printf("# date time event type auid success\n"); - printf("===================================\n"); - } else { - printf("Specific Event Report\n"); - printf("=====================\n"); - } - break; - case RPT_FILE: - if (report_detail == D_DETAILED) { - printf("File Report\n"); - printf( - "===============================================\n"); - printf( - "# date time file syscall success exe auid event\n"); - printf( - "===============================================\n"); - } else { - printf("Specific File Report\n"); - printf("====================\n"); - } - break; - case RPT_HOST: - if (report_detail == D_DETAILED) { - printf("Host Report\n"); - printf("===================================\n"); - printf("# date time host syscall auid event\n"); - printf("===================================\n"); - } else { - printf("Specific Host Report\n"); - printf("====================\n"); - } - break; - case RPT_PID: - if (report_detail == D_DETAILED) { - printf("Process ID Report\n"); - printf( - "======================================\n"); - printf( - "# date time pid exe syscall auid event\n"); - printf( - "======================================\n"); - } else { - printf("Specific Process ID Report\n"); - printf("==========================\n"); - } - break; - case RPT_SYSCALL: - if (report_detail == D_DETAILED) { - printf("Syscall Report\n"); - printf( - "=======================================\n"); - printf( - "# date time syscall pid comm auid event\n"); - printf( - "=======================================\n"); - } else { - printf("Specific Syscall Report\n"); - printf("=======================\n"); - } - break; - case RPT_TERM: - if (report_detail == D_DETAILED) { - printf("Terminal Report\n"); - printf( - "====================================\n"); - printf( - "# date time term host exe auid event\n"); - printf( - "====================================\n"); - } else { - printf("Specific Terminal Report\n"); - printf("========================\n"); - } - break; - case RPT_USER: - if (report_detail == D_DETAILED) { - printf("User ID Report\n"); - printf( - "====================================\n"); - printf( - "# date time auid term host exe event\n"); - printf( - "====================================\n"); - } else { - printf("Specific User ID Report\n"); - printf("=======================\n"); - } - break; - case RPT_EXE: - if (report_detail == D_DETAILED) { - printf("Executable Report\n"); - printf( - "====================================\n"); - printf( - "# date time exe term host auid event\n"); - printf( - "====================================\n"); - } else { - printf("Specific Executable Report\n"); - printf("==========================\n"); - } - break; - case RPT_COMM: - if (report_detail == D_DETAILED) { - printf("Command Report\n"); - printf( - "====================================\n"); - printf( - "# date time comm term host auid event\n"); - printf( - "=====================================\n"); - } else { - printf("Specific command Report\n"); - printf("=======================\n"); - } - break; - case RPT_ANOMALY: - if (report_detail == D_DETAILED) { - printf("Anomaly Report\n"); - printf( - "=========================================\n"); - printf( - "# date time type exe term host auid event\n"); - printf( - "=========================================\n"); - } else { - printf("Specific Anomaly Report\n"); - printf("=======================\n"); - } - break; - case RPT_RESPONSE: - if (report_detail == D_DETAILED) { - printf("Response to Anomaly Report\n"); - printf("==============================\n"); - printf("# date time type success event\n"); - printf("==============================\n"); - } else { - printf("Specific Response to Anomaly Report\n"); - printf("===================================\n"); - } - break; - case RPT_MAC: - if (report_detail == D_DETAILED) { - printf("MAC Report\n"); - printf("===================================\n"); - printf("# date time auid type success event\n"); - printf("===================================\n"); - } else { - printf("Specific Mandatory Access Control (MAC) Report\n"); - printf("===================================\n"); - } - break; - case RPT_INTEG: - if (report_detail == D_DETAILED) { - printf("Integrity Report\n"); - printf("==============================\n"); - printf("# date time type success event\n"); - printf("==============================\n"); - } else { - printf("Specific Integrity Report\n"); - printf("==============================\n"); - } - break; - case RPT_VIRT: - if (report_detail == D_DETAILED) { - printf("Virtualization Report\n"); - printf("==============================\n"); - printf("# date time type success event\n"); - printf("==============================\n"); - } else { - printf("Specific Virtualization Report\n"); - printf("==============================\n"); - } - break; - case RPT_CRYPTO: - if (report_detail == D_DETAILED) { - printf("Crypto Report\n"); - printf("===================================\n"); - printf("# date time auid type success event\n"); - printf("===================================\n"); - } else { - printf("Specific Crypto Report\n"); - printf("===================================\n"); - } - break; - case RPT_KEY: - if (report_detail == D_DETAILED) { - printf("Key Report\n"); - printf( - "===============================================\n"); - printf( - "# date time key success exe auid event\n"); - printf( - "===============================================\n"); - } else { - printf("Specific Key Report\n"); - printf("====================\n"); - } - break; - case RPT_TTY: - if (report_detail == D_DETAILED) { - printf("TTY Report\n"); - printf( - "===============================================\n"); - printf( - "# date time event auid term sess comm data\n"); - printf( - "===============================================\n"); - } else { - printf("Specific TTY Report\n"); - printf("====================\n"); - } - break; - default: - break; - } -} - -void print_per_event_item(llist *l) -{ - char buf[128]; - char name[64]; - char date[32]; - struct tm *tv; - - // The beginning is common to all reports - tv = localtime(&l->e.sec); - strftime(date, sizeof(date), "%x %T", tv); - if (report_type != RPT_AVC) { - line_item++; - printf("%u. %s ", line_item, date); - } - - switch (report_type) - { - case RPT_AVC: - alist_find_avc(l->s.avc); - do { - anode *an = l->s.avc->cur; - line_item++; - printf("%u. %s ", line_item, date); - // command subject syscall action obj res event - safe_print_string(l->s.comm ? l->s.comm : "?", 0); - printf(" %s %s %s %s %s %s %lu\n", - an->scontext, - aulookup_syscall(l, buf,sizeof(buf)), - an->avc_class, an->avc_perm, - an->tcontext, aulookup_result(an->avc_result), - l->e.serial); -//printf("items:%d\n", l->s.avc->cnt); - } while (alist_next_avc(l->s.avc)); - break; - case RPT_CONFIG: - // FIXME:who, action, what, outcome, event - // NOW: type auid success event - printf("%s %s %s %lu\n", - audit_msg_type_to_name(l->head->type), - aulookup_uid(l->s.loginuid, name, sizeof(name)), - aulookup_success(l->s.success), l->e.serial); - break; - case RPT_AUTH: - // who, addr, terminal, exe, success, event - // Special note...uid is used here because that is - // the way that the message works. This is because - // on failed logins, loginuid is not set. - safe_print_string(l->s.acct ? l->s.acct : - aulookup_uid(l->s.uid, name, sizeof(name)), 0); - printf(" %s %s %s %s %lu\n", - l->s.hostname, l->s.terminal, - l->s.exe, aulookup_success(l->s.success), - l->e.serial); - break; - case RPT_LOGIN: - // who, addr, terminal, exe, success, event - // Special note...uid is used here because that is - // the way that the message works. This is because - // on failed logins, loginuid is not set. - safe_print_string(((l->s.success == S_FAILED) && - l->s.acct) ? l->s.acct : - aulookup_uid(l->s.uid, name, sizeof(name)), 0); - printf(" %s %s %s %s %lu\n", - l->s.hostname, l->s.terminal, - l->s.exe, aulookup_success(l->s.success), - l->e.serial); - break; - case RPT_ACCT_MOD: - // who, addr, terminal, exe, success, event - safe_print_string( - aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %s %s %s %s %s %lu\n", - l->s.hostname ? l->s.hostname : "?", - l->s.terminal ? l->s.terminal : "?", - l->s.exe ? l->s.exe : "?", - l->s.acct ? l->s.acct : "?", - aulookup_success(l->s.success), - l->e.serial); - break; - case RPT_EVENT: // report_detail == D_DETAILED - // event, type, who, success - printf("%lu %s ", - l->e.serial, - audit_msg_type_to_name(l->head->type)); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %s\n", aulookup_success(l->s.success)); - break; - case RPT_FILE: // report_detail == D_DETAILED - // file, syscall, success, exe, who, event - slist_first(l->s.filename); - safe_print_string(l->s.filename->cur->str,0); - printf(" %s %s ", - aulookup_syscall(l,buf,sizeof(buf)), - aulookup_success(l->s.success)); - safe_print_string(l->s.exe ? l->s.exe : "?", 0); - putchar(' '); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_HOST: // report_detail == D_DETAILED - // host, syscall, who, event - printf("%s %s ", - l->s.hostname, - aulookup_syscall(l,buf,sizeof(buf))); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_PID: // report_detail == D_DETAILED - // pid, exe, syscall, who, event - printf("%u ", l->s.pid); - safe_print_string(l->s.exe ? l->s.exe : "?", 0); - printf(" %s ", aulookup_syscall(l,buf,sizeof(buf))); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_SYSCALL: // report_detail == D_DETAILED - // syscall, pid, comm, who, event - printf("%s %u ", aulookup_syscall(l,buf,sizeof(buf)), - l->s.pid); - safe_print_string(l->s.comm ? l->s.comm : "?", 0); - putchar(' '); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_TERM: // report_detail == D_DETAILED - // terminal, host, exe, who, event - printf("%s %s ", - l->s.terminal, l->s.hostname); - safe_print_string(l->s.exe, 0); - putchar(' '); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_USER: // report_detail == D_DETAILED - // who, terminal, host, exe, event - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %s %s ", - l->s.terminal ? l->s.terminal : "?", - l->s.hostname ? l->s.hostname : "?"); - safe_print_string(l->s.exe ? l->s.exe : "?", 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_EXE: // report_detail == D_DETAILED - // exe, terminal, host, who, event - safe_print_string(l->s.exe ? l->s.exe : "?", 0); - printf(" %s %s ", - l->s.terminal ? l->s.terminal : "?", - l->s.hostname ? l->s.hostname : "?"); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_COMM: // report_detail == D_DETAILED - // comm, terminal, host, who, event - safe_print_string(l->s.comm ? l->s.comm : "?", 0); - printf(" %s %s ", - l->s.terminal ? l->s.terminal : "?", - l->s.hostname ? l->s.hostname : "?"); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_ANOMALY: // report_detail == D_DETAILED - // type exe term host auid event - printf("%s ", audit_msg_type_to_name(l->head->type)); - safe_print_string(l->s.exe ? l->s.exe : - l->s.comm ? l->s.comm: "?", 0); - printf(" %s %s ", - l->s.terminal ? l->s.terminal : "?", - l->s.hostname ? l->s.hostname : "?"); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_RESPONSE: // report_detail == D_DETAILED - // type success event - printf("%s %s %lu\n", - audit_msg_type_to_name(l->head->type), - aulookup_success(l->s.success), - l->e.serial); - break; - case RPT_MAC: - // auid type success event - printf("%s %s %s %lu\n", - aulookup_uid(l->s.loginuid, name, sizeof(name)), - audit_msg_type_to_name(l->head->type), - aulookup_success(l->s.success), - l->e.serial); - break; - case RPT_INTEG: - // type success event - printf("%s %s %lu\n", - audit_msg_type_to_name(l->head->type), - aulookup_success(l->s.success), - l->e.serial); - break; - case RPT_VIRT: - // type success event - printf("%s %s %lu\n", - audit_msg_type_to_name(l->head->type), - aulookup_success(l->s.success), - l->e.serial); - break; - case RPT_CRYPTO: - // auid type success event - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %s %s %lu\n", - audit_msg_type_to_name(l->head->type), - aulookup_success(l->s.success), - l->e.serial); - break; - case RPT_KEY: // report_detail == D_DETAILED - // key, success, exe, who, event - slist_first(l->s.key); - printf("%s %s ", l->s.key->cur->str, - aulookup_success(l->s.success)); - safe_print_string(l->s.exe ? l->s.exe : "?", 0); - putchar(' '); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %lu\n", l->e.serial); - break; - case RPT_TTY: { - char *ch, *ptr = strstr(l->head->message, "data="); - if (!ptr) - break; - ptr += 5; - ch = strrchr(ptr, ' '); - if (ch) - *ch = 0; - // event who term sess data - printf("%lu ", l->e.serial); - safe_print_string(aulookup_uid(l->s.loginuid, name, - sizeof(name)), 0); - printf(" %s %u ", - l->s.terminal ? l->s.terminal : "?", - l->s.session_id); - safe_print_string(l->s.comm ? l->s.comm: "?", 0); - putchar(' '); - print_tty_data(ptr); - printf("\n"); - } - break; - default: - break; - } -} - -void print_wrap_up(void) -{ - if (report_detail != D_SUM) - return; - - switch (report_type) - { - case RPT_SUMMARY: - do_summary_output(); - break; - case RPT_AVC: - slist_sort_by_hits(&sd.avc_objs); - do_string_summary_output(&sd.avc_objs); - break; - case RPT_CONFIG: /* We will borrow the pid list */ - ilist_sort_by_hits(&sd.pids); - do_type_summary_output(&sd.pids); - break; - case RPT_AUTH: - slist_sort_by_hits(&sd.users); - do_user_summary_output(&sd.users); - break; - case RPT_LOGIN: - slist_sort_by_hits(&sd.users); - do_user_summary_output(&sd.users); - break; - case RPT_ACCT_MOD: /* We will borrow the pid list */ - ilist_sort_by_hits(&sd.pids); - do_type_summary_output(&sd.pids); - break; - case RPT_EVENT: /* We will borrow the pid list */ - ilist_sort_by_hits(&sd.pids); - do_type_summary_output(&sd.pids); - break; - case RPT_FILE: - slist_sort_by_hits(&sd.files); - do_file_summary_output(&sd.files); - break; - case RPT_HOST: - slist_sort_by_hits(&sd.hosts); - do_string_summary_output(&sd.hosts); - break; - case RPT_PID: - ilist_sort_by_hits(&sd.pids); - do_int_summary_output(&sd.pids); - break; - case RPT_SYSCALL: - ilist_sort_by_hits(&sd.sys_list); - do_syscall_summary_output(&sd.sys_list); - break; - case RPT_TERM: - slist_sort_by_hits(&sd.terms); - do_string_summary_output(&sd.terms); - break; - case RPT_USER: - slist_sort_by_hits(&sd.users); - do_user_summary_output(&sd.users); - break; - case RPT_EXE: - slist_sort_by_hits(&sd.exes); - do_file_summary_output(&sd.exes); - break; - case RPT_COMM: - slist_sort_by_hits(&sd.comms); - do_file_summary_output(&sd.comms); - break; - case RPT_ANOMALY: - ilist_sort_by_hits(&sd.anom_list); - do_type_summary_output(&sd.anom_list); - break; - case RPT_RESPONSE: - ilist_sort_by_hits(&sd.resp_list); - do_type_summary_output(&sd.resp_list); - break; - case RPT_MAC: - ilist_sort_by_hits(&sd.mac_list); - do_type_summary_output(&sd.mac_list); - break; - case RPT_INTEG: - ilist_sort_by_hits(&sd.integ_list); - do_type_summary_output(&sd.integ_list); - break; - case RPT_VIRT: - ilist_sort_by_hits(&sd.virt_list); - do_type_summary_output(&sd.virt_list); - break; - case RPT_CRYPTO: - ilist_sort_by_hits(&sd.crypto_list); - do_type_summary_output(&sd.crypto_list); - break; - case RPT_KEY: - slist_sort_by_hits(&sd.keys); - do_file_summary_output(&sd.keys); - break; - default: - break; - } -} - -static void do_summary_output(void) -{ - extern event very_first_event; - extern event very_last_event; - - printf("Range of time in logs: "); - { - struct tm *btm; - char tmp[48]; - - btm = localtime(&very_first_event.sec); - strftime(tmp, sizeof(tmp), "%x %T", btm); - printf("%s.%03d - ", tmp, very_first_event.milli); - btm = localtime(&very_last_event.sec); - strftime(tmp, sizeof(tmp), "%x %T", btm); - printf("%s.%03d\n", tmp, very_last_event.milli); - } - printf("Selected time for report: "); - { - struct tm *btm; - char tmp[48]; - - if (start_time) - btm = localtime(&start_time); - else - btm = localtime(&very_first_event.sec); - strftime(tmp, sizeof(tmp), "%x %T", btm); - printf("%s - ", tmp); - if (end_time) - btm = localtime(&end_time); - else - btm = localtime(&very_last_event.sec); - strftime(tmp, sizeof(tmp), "%x %T", btm); - if (end_time) - printf("%s\n", tmp); - else - printf("%s.%03d\n", tmp, very_last_event.milli); - } - printf("Number of changes in configuration: %lu\n", sd.changes); - printf("Number of changes to accounts, groups, or roles: %lu\n", - sd.acct_changes); - printf("Number of logins: %lu\n", sd.good_logins); - printf("Number of failed logins: %lu\n", sd.bad_logins); - printf("Number of authentications: %lu\n", sd.good_auth); - printf("Number of failed authentications: %lu\n", sd.bad_auth); - printf("Number of users: %u\n", sd.users.cnt); - printf("Number of terminals: %u\n", sd.terms.cnt); - printf("Number of host names: %u\n", sd.hosts.cnt); - printf("Number of executables: %u\n", sd.exes.cnt); - printf("Number of commands: %u\n", sd.comms.cnt); - printf("Number of files: %u\n", sd.files.cnt); - printf("Number of AVC's: %lu\n", sd.avcs); - printf("Number of MAC events: %lu\n", sd.mac); - printf("Number of failed syscalls: %lu\n", sd.failed_syscalls); - printf("Number of anomaly events: %lu\n", sd.anomalies); - printf("Number of responses to anomaly events: %lu\n", sd.responses); - printf("Number of crypto events: %lu\n", sd.crypto); - printf("Number of integrity events: %lu\n", sd.integ); - printf("Number of virt events: %lu\n", sd.virt); - printf("Number of keys: %u\n", sd.keys.cnt); - printf("Number of process IDs: %u\n", sd.pids.cnt); - printf("Number of events: %lu\n", sd.events); - printf("\n"); -} - -static void do_file_summary_output(slist *sptr) -{ - const snode *sn; - - if (sptr->cnt == 0) { - printf("<no events of interest were found>\n\n"); - return; - } - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn) { - printf("%u ", sn->hits); - safe_print_string(sn->str, 1); - sn=slist_next(sptr); - } -} - -static void do_string_summary_output(slist *sptr) -{ - const snode *sn; - - if (sptr->cnt == 0) { - printf("<no events of interest were found>\n\n"); - return; - } - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn) { - printf("%u %s\n", sn->hits, sn->str); - sn=slist_next(sptr); - } -} - -static void do_user_summary_output(slist *sptr) -{ - const snode *sn; - - if (sptr->cnt == 0) { - printf("<no events of interest were found>\n\n"); - return; - } - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn) { - long uid; - char name[64]; - - if (sn->str[0] == '-' || isdigit(sn->str[0])) { - uid = strtol(sn->str, NULL, 10); - printf("%u ", sn->hits); - safe_print_string(aulookup_uid(uid, name, - sizeof(name)), 1); - } else { - printf("%u ", sn->hits); - safe_print_string(sn->str, 1); - } - sn=slist_next(sptr); - } -} - -static void do_int_summary_output(ilist *sptr) -{ - const int_node *in; - - if (sptr->cnt == 0) { - printf("<no events of interest were found>\n\n"); - return; - } - ilist_first(sptr); - in=ilist_get_cur(sptr); - while (in) { - printf("%u %d\n", in->hits, in->num); - in=ilist_next(sptr); - } -} - -static void do_syscall_summary_output(ilist *sptr) -{ - const int_node *in; - - if (sptr->cnt == 0) { - printf("<no events of interest were found>\n\n"); - return; - } - ilist_first(sptr); - in=ilist_get_cur(sptr); - while (in) { - const char *sys = NULL; - int machine = audit_elf_to_machine(in->aux1); - if (machine >= 0) - sys = audit_syscall_to_name(in->num, machine); - if (sys) - printf("%u %s\n", in->hits, sys); - else - printf("%u %d\n", in->hits, in->num); - in=ilist_next(sptr); - } -} - -static void do_type_summary_output(ilist *sptr) -{ - const int_node *in; - - if (sptr->cnt == 0) { - printf("<no events of interest were found>\n\n"); - return; - } - ilist_first(sptr); - in=ilist_get_cur(sptr); - while (in) { - const char *name = audit_msg_type_to_name(in->num); - if (report_format == RPT_DEFAULT) - printf("%u %d\n", in->hits, in->num); - else - printf("%u %s\n", in->hits, name); - in=ilist_next(sptr); - } -} - diff --git a/framework/src/audit/src/aureport-scan.c b/framework/src/audit/src/aureport-scan.c deleted file mode 100644 index 6b2f5ee6..00000000 --- a/framework/src/audit/src/aureport-scan.c +++ /dev/null @@ -1,974 +0,0 @@ -/* -* aureport-scan.c - Extract interesting fields and check for match -* Copyright (c) 2005-06,2008,2011,2014-15 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 "config.h" -#include <string.h> -#include <stdio.h> -#include <pwd.h> -#include "libaudit.h" -#include "aureport-options.h" -#include "ausearch-parse.h" -#include "ausearch-string.h" -#include "ausearch-lookup.h" -#include "aureport-scan.h" - -static void do_summary_total(llist *l); -static int per_event_summary(llist *l); -static int per_event_detailed(llist *l); - -summary_data sd; - -/* This function inits the counters */ -void reset_counters(void) -{ - sd.changes = 0UL; - sd.crypto = 0UL; - sd.acct_changes = 0UL; - sd.good_logins = 0UL; - sd.bad_logins = 0UL; - sd.good_auth = 0UL; - sd.bad_auth = 0UL; - sd.events = 0UL; - sd.avcs = 0UL; - sd.mac = 0UL; - sd.failed_syscalls = 0UL; - sd.anomalies = 0UL; - sd.responses = 0UL; - sd.virt = 0UL; - sd.integ = 0UL; - slist_create(&sd.users); - slist_create(&sd.terms); - slist_create(&sd.files); - slist_create(&sd.hosts); - slist_create(&sd.exes); - slist_create(&sd.comms); - slist_create(&sd.avc_objs); - slist_create(&sd.keys); - ilist_create(&sd.pids); - ilist_create(&sd.sys_list); - ilist_create(&sd.anom_list); - ilist_create(&sd.mac_list); - ilist_create(&sd.resp_list); - ilist_create(&sd.crypto_list); - ilist_create(&sd.virt_list); - ilist_create(&sd.integ_list); -} - -/* This function inits the counters */ -void destroy_counters(void) -{ - sd.changes = 0UL; - sd.crypto = 0UL; - sd.acct_changes = 0UL; - sd.good_logins = 0UL; - sd.bad_logins = 0UL; - sd.good_auth = 0UL; - sd.bad_auth = 0UL; - sd.events = 0UL; - sd.avcs = 0UL; - sd.mac = 0UL; - sd.failed_syscalls = 0UL; - sd.anomalies = 0UL; - sd.responses = 0UL; - sd.virt = 0UL; - sd.integ = 0UL; - slist_clear(&sd.users); - slist_clear(&sd.terms); - slist_clear(&sd.files); - slist_clear(&sd.hosts); - slist_clear(&sd.exes); - slist_clear(&sd.comms); - slist_clear(&sd.avc_objs); - slist_clear(&sd.keys); - ilist_clear(&sd.pids); - ilist_clear(&sd.sys_list); - ilist_clear(&sd.anom_list); - ilist_create(&sd.mac_list); - ilist_clear(&sd.resp_list); - ilist_create(&sd.crypto_list); - ilist_create(&sd.virt_list); - ilist_create(&sd.integ_list); -} - -/* This function will return 0 on no match and 1 on match */ -int classify_success(const llist *l) -{ -//printf("%d,succ=%d:%d\n", l->head->type, event_failed, l->s.success); - // If match only failed... - if (event_failed == F_FAILED) - return l->s.success == S_FAILED ? 1 : 0; - // If match only success... - if (event_failed == F_SUCCESS) - return l->s.success == S_SUCCESS ? 1 : 0; - // Otherwise...we don't care so pretend it matched - return 1; -} - -/* This function will return 0 on no match and 1 on match */ -int classify_conf(const llist *l) -{ - int rc = 1; - extern int no_config; - - switch (l->head->type) - { - case AUDIT_CONFIG_CHANGE: - if (no_config) - rc = 0; - break; - case AUDIT_USYS_CONFIG: - break; - case AUDIT_ADD_USER: - if (event_conf_act == C_DEL) - rc = 0; - break; - case AUDIT_DEL_USER: - if (event_conf_act == C_ADD) - rc = 0; - break; - case AUDIT_ADD_GROUP: - if (event_conf_act == C_DEL) - rc = 0; - break; - case AUDIT_DEL_GROUP: - if (event_conf_act == C_ADD) - rc = 0; - break; - case AUDIT_MAC_CIPSOV4_ADD: - if (event_conf_act == C_DEL) - rc = 0; - break; - case AUDIT_MAC_CIPSOV4_DEL: - if (event_conf_act == C_ADD) - rc = 0; - break; - case AUDIT_MAC_MAP_ADD: - if (event_conf_act == C_DEL) - rc = 0; - break; - case AUDIT_MAC_MAP_DEL: - if (event_conf_act == C_ADD) - rc = 0; - break; - case AUDIT_MAC_IPSEC_ADDSA: - if (event_conf_act == C_DEL) - rc = 0; - break; - case AUDIT_MAC_IPSEC_DELSA: - if (event_conf_act == C_ADD) - rc = 0; - break; - case AUDIT_MAC_IPSEC_ADDSPD: - if (event_conf_act == C_DEL) - rc = 0; - break; - case AUDIT_MAC_IPSEC_DELSPD: - if (event_conf_act == C_ADD) - rc = 0; - break; - case AUDIT_MAC_UNLBL_STCADD: - if (event_conf_act == C_DEL) - rc = 0; - break; - case AUDIT_MAC_UNLBL_STCDEL: - if (event_conf_act == C_ADD) - rc = 0; - break; - default: - break; - } -//printf("conf=%d:%d\n", l->head->type, rc); - return rc; -} - -/* - * This function performs that matching of search params with the record. - * It returns 1 on a match, and 0 if no match. - */ -int scan(llist *l) -{ - // Are we within time range? - if (start_time == 0 || l->e.sec >= start_time) { - if (end_time == 0 || l->e.sec <= end_time) { - // OK - do the heavier checking - int rc = extract_search_items(l); - if (rc == 0) { - if (event_node_list) { - const snode *sn; - int found=0; - slist *sptr = event_node_list; - - if (l->e.node == NULL) - return 0; - - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn && !found) { - if (sn->str && (!strcmp(sn->str, l->e.node))) - found++; - else - sn=slist_next(sptr); - } - - if (!found) - return 0; - } - if (classify_success(l) && classify_conf(l)) - return 1; - return 0; - } - } - } - return 0; -} - -int per_event_processing(llist *l) -{ - int rc; - - switch (report_detail) - { - case D_SUM: - rc = per_event_summary(l); - break; - case D_DETAILED: - rc = per_event_detailed(l); - break; - case D_SPECIFIC: - default: - rc = 0; - break; - } - return rc; -} - -static int per_event_summary(llist *l) -{ - int rc = 0; - - switch (report_type) - { - case RPT_SUMMARY: - do_summary_total(l); - rc = 1; - break; - case RPT_AVC: - if (list_find_msg(l, AUDIT_AVC)) { - if (alist_find_avc(l->s.avc)) { - do { - slist_add_if_uniq(&sd.avc_objs, - l->s.avc->cur->tcontext); - } while (alist_next_avc(l->s.avc)); - } - } else { - if (list_find_msg(l, AUDIT_USER_AVC)) { - if (alist_find_avc(l->s.avc)) { - do { - slist_add_if_uniq( - &sd.avc_objs, - l->s.avc->cur->tcontext); - } while (alist_next_avc( - l->s.avc)); - } - } - } - break; - case RPT_MAC: - if (list_find_msg_range(l, AUDIT_MAC_POLICY_LOAD, - AUDIT_MAC_MAP_DEL)) { - ilist_add_if_uniq(&sd.mac_list, - l->head->type, 0); - } else { - if (list_find_msg_range(l, - AUDIT_FIRST_USER_LSPP_MSG, - AUDIT_LAST_USER_LSPP_MSG)) { - ilist_add_if_uniq(&sd.mac_list, - l->head->type, 0); - } - } - break; - case RPT_INTEG: - if (list_find_msg_range(l, - AUDIT_INTEGRITY_FIRST_MSG, - AUDIT_INTEGRITY_LAST_MSG)) { - ilist_add_if_uniq(&sd.integ_list, - l->head->type, 0); - } - break; - case RPT_VIRT: - if (list_find_msg_range(l, - AUDIT_FIRST_VIRT_MSG, - AUDIT_LAST_VIRT_MSG)) { - ilist_add_if_uniq(&sd.virt_list, - l->head->type, 0); - } - break; - case RPT_CONFIG: /* We will borrow the pid list */ - if (list_find_msg(l, AUDIT_CONFIG_CHANGE) || - list_find_msg(l, AUDIT_DAEMON_CONFIG) || - list_find_msg(l, AUDIT_USYS_CONFIG) || - list_find_msg(l, AUDIT_NETFILTER_CFG) || - list_find_msg(l, AUDIT_FEATURE_CHANGE) || - list_find_msg(l, AUDIT_USER_MAC_CONFIG_CHANGE)|| - list_find_msg_range(l, - AUDIT_MAC_POLICY_LOAD, - AUDIT_MAC_UNLBL_STCDEL)) { - ilist_add_if_uniq(&sd.pids, l->head->type, 0); - } - break; - case RPT_AUTH: - if (list_find_msg(l, AUDIT_USER_AUTH)) { - if (l->s.loginuid == -2 && l->s.acct) - slist_add_if_uniq(&sd.users, l->s.acct); - else { - char name[64]; - - slist_add_if_uniq(&sd.users, - aulookup_uid(l->s.loginuid, - name, - sizeof(name)) - ); - } - } else if (list_find_msg(l, AUDIT_USER_MGMT)) { - // Only count the failures - if (l->s.success == S_FAILED) { - if (l->s.loginuid == -2 && - l->s.acct != NULL) - slist_add_if_uniq(&sd.users, l->s.acct); - else { - char name[64]; - - slist_add_if_uniq(&sd.users, - aulookup_uid( - l->s.loginuid, - name, - sizeof(name)) - ); - } - } - } - break; - case RPT_LOGIN: - if (list_find_msg(l, AUDIT_USER_LOGIN)) { - if ((int)l->s.loginuid < 0 && l->s.acct) - slist_add_if_uniq(&sd.users, l->s.acct); - else { - char name[64]; - - slist_add_if_uniq(&sd.users, - aulookup_uid(l->s.loginuid, - name, - sizeof(name)) - ); - } - } - break; - case RPT_ACCT_MOD: /* We will borrow the pid list */ - if (list_find_msg(l, AUDIT_USER_CHAUTHTOK) || - list_find_msg_range(l, - AUDIT_ADD_USER, AUDIT_DEL_GROUP) || - list_find_msg(l, AUDIT_USER_MGMT) || - list_find_msg(l, AUDIT_GRP_MGMT) || - list_find_msg_range(l, - AUDIT_ROLE_ASSIGN, - AUDIT_ROLE_REMOVE)) { - ilist_add_if_uniq(&sd.pids, l->head->type, 0); - } - break; - case RPT_EVENT: /* We will borrow the pid list */ - if (l->head->type != -1) { - ilist_add_if_uniq(&sd.pids, l->head->type, 0); - } - break; - case RPT_FILE: - if (l->s.filename) { - const snode *sn; - slist *sptr = l->s.filename; - - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn) { - if (sn->str) - slist_add_if_uniq(&sd.files, - sn->str); - sn=slist_next(sptr); - } - } - break; - case RPT_HOST: - if (l->s.hostname) - slist_add_if_uniq(&sd.hosts, l->s.hostname); - break; - case RPT_PID: - if (l->s.pid != -1) { - ilist_add_if_uniq(&sd.pids, l->s.pid, 0); - } - break; - case RPT_SYSCALL: - if (l->s.syscall > 0) { - ilist_add_if_uniq(&sd.sys_list, - l->s.syscall, l->s.arch); - } - break; - case RPT_TERM: - if (l->s.terminal) - slist_add_if_uniq(&sd.terms, l->s.terminal); - break; - case RPT_USER: - if (l->s.loginuid != -2) { - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%d", l->s.loginuid); - slist_add_if_uniq(&sd.users, tmp); - } - break; - case RPT_EXE: - if (l->s.exe) - slist_add_if_uniq(&sd.exes, l->s.exe); - break; - case RPT_COMM: - if (l->s.comm) - slist_add_if_uniq(&sd.comms, l->s.comm); - break; - case RPT_ANOMALY: - if (list_find_msg_range(l, AUDIT_FIRST_ANOM_MSG, - AUDIT_LAST_ANOM_MSG)) { - ilist_add_if_uniq(&sd.anom_list, - l->head->type, 0); - } else { - if (list_find_msg_range(l, - AUDIT_FIRST_KERN_ANOM_MSG, - AUDIT_LAST_KERN_ANOM_MSG)) { - ilist_add_if_uniq(&sd.anom_list, - l->head->type, 0); - } - } - break; - case RPT_RESPONSE: - if (list_find_msg_range(l, AUDIT_FIRST_ANOM_RESP, - AUDIT_LAST_ANOM_RESP)) { - ilist_add_if_uniq(&sd.resp_list, - l->head->type, 0); - } - break; - case RPT_CRYPTO: - if (list_find_msg_range(l, AUDIT_FIRST_KERN_CRYPTO_MSG, - AUDIT_LAST_KERN_CRYPTO_MSG)) { - ilist_add_if_uniq(&sd.crypto_list, - l->head->type, 0); - } else { - if (list_find_msg_range(l, - AUDIT_FIRST_CRYPTO_MSG, - AUDIT_LAST_CRYPTO_MSG)) { - ilist_add_if_uniq(&sd.crypto_list, - l->head->type, 0); - } - } - break; - case RPT_KEY: - if (l->s.key) { - const snode *sn; - slist *sptr = l->s.key; - - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn) { - if (sn->str && - strcmp(sn->str, "(null)")) - slist_add_if_uniq(&sd.keys, - sn->str); - sn=slist_next(sptr); - } - } - break; - case RPT_TTY: - UNIMPLEMENTED; - break; - default: - break; - } - return rc; -} - -static int per_event_detailed(llist *l) -{ - int rc = 0; - - switch (report_type) - { - case RPT_AVC: - if (list_find_msg(l, AUDIT_AVC)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, AUDIT_USER_AVC)) { - print_per_event_item(l); - rc = 1; - } - break; - case RPT_MAC: - if (report_detail == D_DETAILED) { - if (list_find_msg_range(l, - AUDIT_MAC_POLICY_LOAD, - AUDIT_MAC_UNLBL_STCDEL)) { - print_per_event_item(l); - rc = 1; - } else { - if (list_find_msg_range(l, - AUDIT_FIRST_USER_LSPP_MSG, - AUDIT_LAST_USER_LSPP_MSG)) { - print_per_event_item(l); - rc = 1; - } - } - } - break; - case RPT_INTEG: - if (report_detail == D_DETAILED) { - if (list_find_msg_range(l, - AUDIT_INTEGRITY_FIRST_MSG, - AUDIT_INTEGRITY_LAST_MSG)) { - print_per_event_item(l); - rc = 1; - } - } - break; - case RPT_VIRT: - if (report_detail == D_DETAILED) { - if (list_find_msg_range(l, - AUDIT_FIRST_VIRT_MSG, - AUDIT_LAST_VIRT_MSG)) { - print_per_event_item(l); - rc = 1; - } - } - break; - case RPT_CONFIG: - if (list_find_msg(l, AUDIT_CONFIG_CHANGE)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, AUDIT_DAEMON_CONFIG)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, AUDIT_USYS_CONFIG)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, AUDIT_NETFILTER_CFG)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, AUDIT_FEATURE_CHANGE)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, - AUDIT_USER_MAC_CONFIG_CHANGE)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg_range(l, - AUDIT_MAC_POLICY_LOAD, - AUDIT_MAC_UNLBL_STCDEL)) { - print_per_event_item(l); - rc = 1; - } - break; - case RPT_AUTH: - if (list_find_msg(l, AUDIT_USER_AUTH)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, AUDIT_USER_MGMT)) { - // Only count the failed acct - if (l->s.success == S_FAILED) { - print_per_event_item(l); - rc = 1; - } - } - break; - case RPT_LOGIN: - if (list_find_msg(l, AUDIT_USER_LOGIN)) { - print_per_event_item(l); - rc = 1; - } - break; - case RPT_ACCT_MOD: - if (list_find_msg(l, AUDIT_USER_CHAUTHTOK)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg_range(l, - AUDIT_ADD_USER, AUDIT_DEL_GROUP)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, AUDIT_USER_MGMT)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg(l, AUDIT_GRP_MGMT)) { - print_per_event_item(l); - rc = 1; - } else if (list_find_msg_range(l, - AUDIT_ROLE_ASSIGN, - AUDIT_ROLE_REMOVE)) { - print_per_event_item(l); - rc = 1; - } - break; - case RPT_EVENT: - list_first(l); - if (report_detail == D_DETAILED) { - print_per_event_item(l); - rc = 1; - } else { // specific event report - UNIMPLEMENTED; - } - break; - case RPT_FILE: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.filename) { - print_per_event_item(l); - rc = 1; - } - } else { // specific file report - UNIMPLEMENTED; - } - break; - case RPT_HOST: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.hostname) { - print_per_event_item(l); - rc = 1; - } - } else { // specific host report - UNIMPLEMENTED; - } - break; - case RPT_PID: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.pid >= 0) { - print_per_event_item(l); - rc = 1; - } - } else { // specific pid report - UNIMPLEMENTED; - } - break; - case RPT_SYSCALL: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.syscall) { - print_per_event_item(l); - rc = 1; - } - } else { // specific syscall report - UNIMPLEMENTED; - } - break; - case RPT_TERM: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.terminal) { - print_per_event_item(l); - rc = 1; - } - } else { // specific terminal report - UNIMPLEMENTED; - } - break; - case RPT_USER: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.uid != -1) { - print_per_event_item(l); - rc = 1; - } - } else { // specific user report - UNIMPLEMENTED; - } - break; - case RPT_EXE: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.exe) { - print_per_event_item(l); - rc = 1; - } - } else { // specific exe report - UNIMPLEMENTED; - } - break; - case RPT_COMM: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.comm) { - print_per_event_item(l); - rc = 1; - } - } else { // specific exe report - UNIMPLEMENTED; - } - break; - case RPT_ANOMALY: - if (report_detail == D_DETAILED) { - if (list_find_msg_range(l, - AUDIT_FIRST_ANOM_MSG, - AUDIT_LAST_ANOM_MSG)) { - print_per_event_item(l); - rc = 1; - } else { - if (list_find_msg_range(l, - AUDIT_FIRST_KERN_ANOM_MSG, - AUDIT_LAST_KERN_ANOM_MSG)) { - print_per_event_item(l); - rc = 1; - } - } - } else { // FIXME: specific anom report - UNIMPLEMENTED; - } - break; - case RPT_RESPONSE: - if (report_detail == D_DETAILED) { - if (list_find_msg_range(l, - AUDIT_FIRST_ANOM_RESP, - AUDIT_LAST_ANOM_RESP)) { - print_per_event_item(l); - rc = 1; - } - } else { // FIXME: specific resp report - UNIMPLEMENTED; - } - break; - case RPT_CRYPTO: - if (report_detail == D_DETAILED) { - if (list_find_msg_range(l, - AUDIT_FIRST_KERN_CRYPTO_MSG, - AUDIT_LAST_KERN_CRYPTO_MSG)) { - print_per_event_item(l); - rc = 1; - } else { - if (list_find_msg_range(l, - AUDIT_FIRST_CRYPTO_MSG, - AUDIT_LAST_CRYPTO_MSG)) { - print_per_event_item(l); - rc = 1; - } - } - } else { // FIXME: specific crypto report - UNIMPLEMENTED; - } - break; - case RPT_KEY: - list_first(l); - if (report_detail == D_DETAILED) { - if (l->s.key) { - slist_first(l->s.key); - if (strcmp(l->s.key->cur->str, - "(null)")) { - print_per_event_item(l); - rc = 1; - } - } - } else { // specific key report - UNIMPLEMENTED; - } - break; - case RPT_TTY: - if (l->head->type == AUDIT_TTY || - l->head->type == AUDIT_USER_TTY) { - print_per_event_item(l); - rc = 1; - } - break; - default: - break; - } - return rc; -} - -static void do_summary_total(llist *l) -{ - // add events - sd.events++; - - // add config changes - if (list_find_msg(l, AUDIT_CONFIG_CHANGE)) - sd.changes++; - if (list_find_msg(l, AUDIT_DAEMON_CONFIG)) - sd.changes++; - if (list_find_msg(l, AUDIT_USYS_CONFIG)) - sd.changes++; - if (list_find_msg(l, AUDIT_NETFILTER_CFG)) - sd.changes++; - if (list_find_msg(l, AUDIT_FEATURE_CHANGE)) - sd.changes++; - if (list_find_msg(l, AUDIT_USER_MAC_CONFIG_CHANGE)) - sd.changes++; - list_first(l); - if (list_find_msg_range(l, AUDIT_MAC_POLICY_LOAD, - AUDIT_MAC_UNLBL_STCDEL)) - sd.changes++; - - // add acct changes - if (list_find_msg(l, AUDIT_USER_CHAUTHTOK)) - sd.acct_changes++; - if (list_find_msg_range(l, AUDIT_ADD_USER, AUDIT_DEL_GROUP)) - sd.acct_changes++; - if (list_find_msg(l, AUDIT_USER_MGMT)) - sd.acct_changes++; - if (list_find_msg(l, AUDIT_GRP_MGMT)) - sd.acct_changes++; - list_first(l); - if (list_find_msg_range(l, AUDIT_ROLE_ASSIGN, AUDIT_ROLE_REMOVE)) - sd.acct_changes++; - - // Crypto - list_first(l); - if (list_find_msg_range(l, AUDIT_FIRST_KERN_CRYPTO_MSG, - AUDIT_LAST_KERN_CRYPTO_MSG)) - sd.crypto++; - if (list_find_msg_range(l, AUDIT_FIRST_CRYPTO_MSG, - AUDIT_LAST_CRYPTO_MSG)) - sd.crypto++; - - // add logins - if (list_find_msg(l, AUDIT_USER_LOGIN)) { - if (l->s.success == S_SUCCESS) - sd.good_logins++; - else if (l->s.success == S_FAILED) - sd.bad_logins++; - } - - // add use of auth - if (list_find_msg(l, AUDIT_USER_AUTH)) { - if (l->s.success == S_SUCCESS) - sd.good_auth++; - else if (l->s.success == S_FAILED) - sd.bad_auth++; - } else if (list_find_msg(l, AUDIT_USER_MGMT)) { - // Only count the failures - if (l->s.success == S_FAILED) - sd.bad_auth++; - } else if (list_find_msg(l, AUDIT_GRP_AUTH)) { - if (l->s.success == S_SUCCESS) - sd.good_auth++; - else if (l->s.success == S_FAILED) - sd.bad_auth++; - } - - // add users - if (l->s.loginuid != -2) { - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%d", l->s.loginuid); - slist_add_if_uniq(&sd.users, tmp); - } - - // add terminals - if (l->s.terminal) - slist_add_if_uniq(&sd.terms, l->s.terminal); - - // add hosts - if (l->s.hostname) - slist_add_if_uniq(&sd.hosts, l->s.hostname); - - // add execs - if (l->s.exe) - slist_add_if_uniq(&sd.exes, l->s.exe); - - // add comms - if (l->s.comm) - slist_add_if_uniq(&sd.comms, l->s.comm); - - // add files - if (l->s.filename) { - const snode *sn; - slist *sptr = l->s.filename; - - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn) { - if (sn->str) - slist_add_if_uniq(&sd.files, sn->str); - sn=slist_next(sptr); - } - } - - // add avcs - if (list_find_msg(l, AUDIT_AVC)) - sd.avcs++; - else if (list_find_msg(l, AUDIT_USER_AVC)) - sd.avcs++; - - // MAC - list_first(l); - if (list_find_msg_range(l, AUDIT_MAC_POLICY_LOAD, - AUDIT_MAC_UNLBL_STCDEL)) - sd.mac++; - if (list_find_msg_range(l, AUDIT_FIRST_USER_LSPP_MSG, - AUDIT_LAST_USER_LSPP_MSG)) - sd.mac++; - - // Virt - list_first(l); - if (list_find_msg_range(l, AUDIT_FIRST_VIRT_MSG, - AUDIT_LAST_VIRT_MSG)) - sd.virt++; - - // Integrity - list_first(l); - if (list_find_msg_range(l, AUDIT_INTEGRITY_FIRST_MSG, - AUDIT_INTEGRITY_LAST_MSG)) - sd.integ++; - - // add failed syscalls - if (l->s.success == S_FAILED && l->s.syscall > 0) - sd.failed_syscalls++; - - // add pids - if (l->s.pid != -1) { - ilist_add_if_uniq(&sd.pids, l->s.pid, 0); - } - - // add anomalies - if (list_find_msg_range(l, AUDIT_FIRST_ANOM_MSG, AUDIT_LAST_ANOM_MSG)) - sd.anomalies++; - if (list_find_msg_range(l, AUDIT_FIRST_KERN_ANOM_MSG, - AUDIT_LAST_KERN_ANOM_MSG)) - sd.anomalies++; - - // add response to anomalies - if (list_find_msg_range(l, AUDIT_FIRST_ANOM_RESP, AUDIT_LAST_ANOM_RESP)) - sd.responses++; - - // add keys - if (l->s.key) { - const snode *sn; - slist *sptr = l->s.key; - - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn) { - if (sn->str && strcmp(sn->str, "(null)")) { - slist_add_if_uniq(&sd.keys, sn->str); - } - sn=slist_next(sptr); - } - } -} - diff --git a/framework/src/audit/src/aureport-scan.h b/framework/src/audit/src/aureport-scan.h deleted file mode 100644 index 5044d96d..00000000 --- a/framework/src/audit/src/aureport-scan.h +++ /dev/null @@ -1,76 +0,0 @@ -/* aureport-scan.h -- - * Copyright 2005-06,2008,2014 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#ifndef AUREPORT_SCAN_H -#define AUREPORT_SCAN_H - -#include "ausearch-llist.h" -#include "ausearch-int.h" - -typedef struct sdata { - slist users; - slist terms; - slist files; - slist hosts; - slist exes; - slist comms; - slist avc_objs; - slist keys; - ilist pids; - ilist sys_list; - ilist anom_list; - ilist resp_list; - ilist mac_list; - ilist crypto_list; - ilist virt_list; - ilist integ_list; - unsigned long changes; - unsigned long crypto; - unsigned long acct_changes; - unsigned long good_logins; - unsigned long bad_logins; - unsigned long good_auth; - unsigned long bad_auth; - unsigned long events; - unsigned long avcs; - unsigned long mac; - unsigned long failed_syscalls; - unsigned long anomalies; - unsigned long responses; - unsigned long virt; - unsigned long integ; -} summary_data; - -void reset_counters(void); -void destroy_counters(void); -int scan(llist *l); -int per_event_processing(llist *l); - -void print_title(void); -void print_per_event_item(llist *l); -void print_wrap_up(void); - -extern summary_data sd; - -#endif - diff --git a/framework/src/audit/src/aureport.c b/framework/src/audit/src/aureport.c deleted file mode 100644 index 98511e01..00000000 --- a/framework/src/audit/src/aureport.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * aureport.c - main file for aureport utility - * Copyright 2005-08, 2010,11,2013 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - */ - -#include "config.h" -#include <stdio.h> -#include <stdio_ext.h> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <unistd.h> -#include <ctype.h> -#include <time.h> -#include <errno.h> -#include <sys/resource.h> -#include <sys/stat.h> -#include <locale.h> -#include <sys/param.h> -#include "libaudit.h" -#include "auditd-config.h" -#include "aureport-options.h" -#include "aureport-scan.h" -#include "ausearch-lol.h" -#include "ausearch-lookup.h" - - -event very_first_event, very_last_event; -static FILE *log_fd = NULL; -static lol lo; -static int found = 0; -static int files_to_process = 0; // Logs left when processing multiple -static int userfile_is_dir = 0; -static int process_logs(void); -static int process_log_fd(const char *filename); -static int process_stdin(void); -static int process_file(char *filename); -static int get_record(llist **); - -extern char *user_file; -extern int force_logs; - - -static int is_pipe(int fd) -{ - struct stat st; - - if (fstat(fd, &st) == 0) { - if (S_ISFIFO(st.st_mode)) - return 1; - } - return 0; -} - -int main(int argc, char *argv[]) -{ - struct rlimit limit; - int rc; - - /* Check params and build regexpr */ - setlocale (LC_ALL, ""); - if (check_params(argc, argv)) - return 1; - - /* Raise the rlimits in case we're being started from a shell - * with restrictions. Not a fatal error. */ - limit.rlim_cur = RLIM_INFINITY; - limit.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_FSIZE, &limit); - setrlimit(RLIMIT_CPU, &limit); - set_aumessage_mode(MSG_STDERR, DBG_NO); - (void) umask( umask( 077 ) | 027 ); - very_first_event.sec = 0; - reset_counters(); - - print_title(); - lol_create(&lo); - if (user_file) { - struct stat sb; - if (stat(user_file, &sb) == -1) { - perror("stat"); - return 1; - } else { - switch (sb.st_mode & S_IFMT) { - case S_IFDIR: - userfile_is_dir = 1; - rc = process_logs(); - break; - case S_IFREG: - default: - rc = process_file(user_file); - break; - } - } - } else if (force_logs) - rc = process_logs(); - else if (is_pipe(0)) - rc = process_stdin(); - else - rc = process_logs(); - lol_clear(&lo); - if (rc) - return rc; - - if (!found && report_detail == D_DETAILED && report_type != RPT_TIME) { - printf("<no events of interest were found>\n\n"); - destroy_counters(); - aulookup_destroy_uid_list(); - aulookup_destroy_gid_list(); - return 1; - } else - print_wrap_up(); - destroy_counters(); - aulookup_destroy_uid_list(); - aulookup_destroy_gid_list(); - free(user_file); - return 0; -} - -static int process_logs(void) -{ - struct daemon_conf config; - char *filename; - int len, num = 0; - - if (user_file && userfile_is_dir) { - char dirname[MAXPATHLEN]; - clear_config (&config); - - strcpy(dirname, user_file); - if (dirname[strlen(dirname)-1] != '/') - strcat(dirname, "/"); - strcat (dirname, "audit.log"); - free((void *)config.log_file); - config.log_file=strdup(dirname); - fprintf(stderr, "NOTE - using logs in %s\n", config.log_file); - } else { - /* Load config so we know where logs are */ - if (load_config(&config, TEST_SEARCH)) - fprintf(stderr, "NOTE - using built-in logs: %s\n", - config.log_file); - } - - /* for each file */ - len = strlen(config.log_file) + 16; - filename = malloc(len); - if (!filename) { - fprintf(stderr, "No memory\n"); - free_config(&config); - return 1; - } - /* Find oldest log file */ - snprintf(filename, len, "%s", config.log_file); - do { - if (access(filename, R_OK) != 0) - break; -// FIXME: do a time check and put them on linked list for later - num++; - snprintf(filename, len, "%s.%d", config.log_file, num); - } while (1); - num--; - /* - * We note how many files we need to process - */ - files_to_process = num; - - /* Got it, now process logs from last to first */ - if (num > 0) - snprintf(filename, len, "%s.%d", config.log_file, num); - else - snprintf(filename, len, "%s", config.log_file); - do { - int ret; - if ((ret = process_file(filename))) { - free(filename); - free_config(&config); - return ret; - } - - /* Get next log file */ - files_to_process--; /* one less file to process */ - num--; - if (num > 0) - snprintf(filename, len, "%s.%d", config.log_file, num); - else if (num == 0) - snprintf(filename, len, "%s", config.log_file); - else - break; - } while (1); - free(filename); - free_config(&config); - return 0; -} - -static int process_log_fd(const char *filename) -{ - llist *entries; // entries in a record - int ret; - int first = 0; - event first_event, last_event; - - last_event.sec = 0; - last_event.milli = 0; - - /* For each record in file */ - do { - ret = get_record(&entries); - if ((ret != 0)||(entries->cnt == 0)) - break; - // If report is RPT_TIME or RPT_SUMMARY, get - if (report_type <= RPT_SUMMARY) { - if (first == 0) { - list_get_event(entries, &first_event); - first = 1; - if (very_first_event.sec == 0) - list_get_event(entries, - &very_first_event); - } - list_get_event(entries, &last_event); - } - if (scan(entries)) { - // This is the per entry action item - if (per_event_processing(entries)) - found = 1; - } - list_clear(entries); - free(entries); - } while (ret == 0); - fclose(log_fd); - // This is the per file action items - very_last_event.sec = last_event.sec; - very_last_event.milli = last_event.milli; - if (report_type == RPT_TIME) { - if (first == 0) { - printf("%s: no records\n", filename); - } else { - struct tm *btm; - char tmp[32]; - - printf("%s: ", filename); - btm = localtime(&first_event.sec); - strftime(tmp, sizeof(tmp), "%x %T", btm); - printf("%s.%03d - ", tmp, first_event.milli); - btm = localtime(&last_event.sec); - strftime(tmp, sizeof(tmp), "%x %T", btm); - printf("%s.%03d\n", tmp, last_event.milli); - } - } - - return 0; -} - -static int process_stdin(void) -{ - log_fd = stdin; - - return process_log_fd("stdin"); -} - -static int process_file(char *filename) -{ - log_fd = fopen(filename, "rm"); - if (log_fd == NULL) { - fprintf(stderr, "Error opening %s (%s)\n", filename, - strerror(errno)); - return 1; - } - - __fsetlocking(log_fd, FSETLOCKING_BYCALLER); - return process_log_fd(filename); -} - -/* - * This function returns a malloc'd buffer of the next record in the audit - * logs. It returns 0 on success, 1 on eof, -1 on error. - */ -static int get_record(llist **l) -{ - char *rc; - char *buff = NULL; - - *l = get_ready_event(&lo); - if (*l) - return 0; - - while (1) { - if (!buff) { - buff = malloc(MAX_AUDIT_MESSAGE_LENGTH); - if (!buff) - return -1; - } - rc = fgets_unlocked(buff, MAX_AUDIT_MESSAGE_LENGTH, - log_fd); - if (rc) { - if (lol_add_record(&lo, buff)) { - *l = get_ready_event(&lo); - if (*l) - break; - } - } else { - free(buff); - if (feof_unlocked(log_fd)) { - // Only mark all events complete if this is - // the last file. - if (files_to_process == 0) { - terminate_all_events(&lo); - } - *l = get_ready_event(&lo); - if (*l) - return 0; - else - return 1; - } else - return -1; - } - } - free(buff); - return 0; -} - diff --git a/framework/src/audit/src/ausearch-avc.c b/framework/src/audit/src/ausearch-avc.c deleted file mode 100644 index 2d3b3199..00000000 --- a/framework/src/audit/src/ausearch-avc.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -* ausearch-avc.c - Minimal linked list library for avcs -* Copyright (c) 2006,2008,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 "config.h" -#include <stdlib.h> -#include <string.h> -#include "ausearch-avc.h" - - -void alist_create(alist *l) -{ - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - -anode *alist_next(alist *l) -{ - if (l->cur == NULL) - return NULL; - l->cur = l->cur->next; - return l->cur; -} - -static void alist_last(alist *l) -{ - register anode* cur; - - if (l->head == NULL) - return; - - // Start with cur in hopes that we don't start at beginning - if (l->cur) - cur = l->cur; - else - cur = l->head; - - // Loop until no next value - while (cur->next) - cur = cur->next; - l->cur = cur; -} - -void alist_append(alist *l, anode *node) -{ - anode* newnode; - - newnode = malloc(sizeof(anode)); - - if (node->scontext) - newnode->scontext = node->scontext; - else - newnode->scontext = NULL; - - if (node->tcontext) - newnode->tcontext = node->tcontext; - else - newnode->tcontext = NULL; - - newnode->avc_result = node->avc_result; - - if (node->avc_perm) - newnode->avc_perm = node->avc_perm; - else - newnode->avc_perm = NULL; - - if (node->avc_class) - newnode->avc_class = node->avc_class; - else - newnode->avc_class = NULL; - - newnode->next = NULL; - - // Make sure cursor is at the end - alist_last(l); - - // if we are at top, fix this up - if (l->head == NULL) - l->head = newnode; - else // Otherwise add pointer to newnode - l->cur->next = newnode; - - // make newnode current - l->cur = newnode; - l->cnt++; -} - -int alist_find_subj(alist *l) -{ - register anode* window = l->head; - - while (window) { - if (window->scontext) { - l->cur = window; - return 1; - } - else - window = window->next; - } - return 0; -} - -anode *alist_next_subj(alist *l) -{ - if (l->cur == NULL) - return NULL; - while (l->cur->next) { - l->cur=l->cur->next; - if (l->cur->scontext) - return l->cur; - } - return NULL; -} - -int alist_find_obj(alist *l) -{ - register anode* window = l->head; - - while (window) { - if (window->tcontext) { - l->cur = window; - return 1; - } - else - window = window->next; - } - return 0; -} - -anode *alist_next_obj(alist *l) -{ - if (l->cur == NULL) - return NULL; - while (l->cur->next) { - l->cur=l->cur->next; - if (l->cur->tcontext) - return l->cur; - } - return NULL; -} - -int alist_find_avc(alist *l) -{ - register anode* window = l->head; - - while (window) { - if (window->avc_result != AVC_UNSET) { - l->cur = window; - return 1; - } - else - window = window->next; - } - return 0; -} - -anode *alist_next_avc(alist *l) -{ - if (l->cur == NULL) - return NULL; - while (l->cur->next) { - l->cur=l->cur->next; - if (l->cur->avc_result != AVC_UNSET) - return l->cur; - } - return NULL; -} - -void alist_clear(alist* l) -{ - anode* nextnode; - register anode* current; - - current = l->head; - while (current) { - nextnode=current->next; - anode_clear(current); - free(current); - current=nextnode; - } - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - -void anode_init(anode *an) -{ - an->scontext = NULL; - an->tcontext = NULL; - an->avc_result = AVC_UNSET; - an->avc_perm = NULL; - an->avc_class = NULL; -} - -void anode_clear(anode *an) -{ - free(an->scontext); - free(an->tcontext); - free(an->avc_perm); - free(an->avc_class); -} - diff --git a/framework/src/audit/src/ausearch-avc.h b/framework/src/audit/src/ausearch-avc.h deleted file mode 100644 index c31293e1..00000000 --- a/framework/src/audit/src/ausearch-avc.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -* ausearch-avc.h - Header file for ausearch-string.c -* Copyright (c) 2006,2008 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> -*/ - -#ifndef AU_AVC_HEADER -#define AU_AVC_HEADER - -#include "config.h" -#include <sys/types.h> -#include "libaudit.h" - -typedef enum { AVC_UNSET, AVC_DENIED, AVC_GRANTED } avc_t; - -/* This is the node of the linked list. message & item are the only elements - * at this time. Any data elements that are per item goes here. */ -typedef struct _anode{ - char *scontext; // se linux subject context - char *tcontext; // se linux object context - avc_t avc_result; // se linux avc denied/granted - char *avc_perm; // se linux avc permission mentioned - char *avc_class; // se linux class mentioned - struct _anode* next; // Next string node pointer -} anode; - -/* This is the linked list head. Only data elements that are 1 per - * event goes here. */ -typedef struct { - anode *head; // List head - anode *cur; // Pointer to current node - unsigned int cnt; // How many items in this list -} alist; - -void alist_create(alist *l); -static inline void alist_first(alist *l) { l->cur = l->head; } -anode *alist_next(alist *l); -static inline anode *alist_get_cur(alist *l) { return l->cur; } -void alist_append(alist *l, anode *node); -void anode_init(anode *an); -void anode_clear(anode *an); -void alist_clear(alist* l); - -/* See if any subj exists in list */ -int alist_find_subj(alist *l); -anode *alist_next_subj(alist *l); -/* See if any obj exists in list */ -int alist_find_obj(alist *l); -anode *alist_next_obj(alist *l); -/* See if any avc exists in list */ -int alist_find_avc(alist *l); -anode *alist_next_avc(alist *l); - -#endif - diff --git a/framework/src/audit/src/ausearch-checkpt.c b/framework/src/audit/src/ausearch-checkpt.c deleted file mode 100644 index e0d0022c..00000000 --- a/framework/src/audit/src/ausearch-checkpt.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * ausearch-checkpt.c - ausearch checkpointing feature - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <stdlib.h> -#include <errno.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include "ausearch-checkpt.h" - -#define DBG 0 /* set to non-zero for debug */ - -/* Remember why we failed */ -unsigned checkpt_failure = 0; - -/* - * Remember the file we were processing when we had incomplete events. - * We remember this via it's dev and inode - */ -static dev_t checkpt_dev = (dev_t)NULL; -static ino_t checkpt_ino = (ino_t)NULL; - -/* Remember the last event output */ -static event last_event = {0, 0, 0, NULL, 0}; - -/* Loaded values from a given checkpoint file */ -dev_t chkpt_input_dev = (dev_t)NULL; -ino_t chkpt_input_ino = (ino_t)NULL; -event chkpt_input_levent = {0, 0, 0, NULL, 0}; - -/* - * Record the dev_t and ino_t of the given file - * - * Returns: - * 1 Failed to get status - * 0 OK - */ -int set_ChkPtFileDetails(const char *fn) -{ - struct stat sbuf; - - if (stat(fn, &sbuf) != 0) { - fprintf(stderr, "Cannot stat audit file for checkpoint " - "details - %s: %s\n", fn, strerror(errno)); - checkpt_failure |= CP_STATFAILED; - return 1; - } - checkpt_dev = sbuf.st_dev; - checkpt_ino = sbuf.st_ino; - - return 0; -} - -/* - * Save the given event in the last_event record - * Returns: - * 1 no memory - * 0 OK - */ -int set_ChkPtLastEvent(const event *e) -{ - /* Set the event node if necessary */ - if (e->node) { - if (last_event.node) { - if (strcmp(e->node, last_event.node) != 0) { - free((void *)last_event.node); - last_event.node = strdup(e->node); - } - } else - last_event.node = strdup(e->node); - if (last_event.node == NULL) { - fprintf(stderr, "No memory to allocate " - "checkpoint last event node name\n"); - return 1; - } - } else { - if (last_event.node) - free((void *)last_event.node); - last_event.node = NULL; - } - last_event.sec = e->sec; - last_event.milli = e->milli; - last_event.serial = e->serial; - last_event.type = e->type; - - return 0; -} - -/* Free all checkpoint memory */ -void free_ChkPtMemory(void) -{ - if (last_event.node) - (void)free((void *)last_event.node); - last_event.node = NULL; - if (chkpt_input_levent.node) - (void)free((void *)chkpt_input_levent.node); - chkpt_input_levent.node = NULL; -} - -/* - * Save the checkpoint to the given file - * Returns: - * 1 io error - * 0 OK - */ -void save_ChkPt(const char *fn) -{ - FILE *fd; - - if ((fd = fopen(fn, "w")) == NULL) { - fprintf(stderr, "Cannot open checkpoint file - %s: %s\n", - fn, strerror(errno)); - checkpt_failure |= CP_STATUSIO; - return; - } - fprintf(fd, "dev=0x%X\ninode=0x%X\n", - (unsigned int)checkpt_dev, (unsigned int)checkpt_ino); - fprintf(fd, "output=%s %lu.%03u:%lu 0x%X\n", - last_event.node ? last_event.node : "-", - (long unsigned int)last_event.sec, last_event.milli, - last_event.serial, last_event.type); - fclose(fd); -} - -/* - * Parse a checkpoint file "output=" record - * Returns - * 1 failed to parse or no memory - * 0 parsed OK - */ -static int parse_checkpt_event(char *lbuf, int ndix, event *e) -{ - char *rest; - - /* - * Find the space after the node, then make it '\0' so - * we terminate the node value. We leave 'rest' at the start - * of the event time/serial element - */ - rest = strchr(&lbuf[ndix], ' '); - if (rest == NULL) { - fprintf(stderr, "Malformed output/event checkpoint line " - "near node - [%s]\n", lbuf); - checkpt_failure |= CP_STATUSBAD; - return 1; - } - *rest++ = '\0'; - - if (lbuf[ndix] == '-') - e->node = NULL; - else { - e->node = strdup(&lbuf[ndix]); - if (e->node == NULL) { - fprintf(stderr, "No memory for node when loading " - "checkpoint line - [%s]\n", lbuf); - checkpt_failure |= CP_NOMEM; - return 1; - } - } - if (sscanf(rest, "%lu.%03u:%lu 0x%X", &e->sec, &e->milli, - &e->serial, &e->type) != 4) { - fprintf(stderr, "Malformed output/event checkpoint line " - "after node - [%s]\n", lbuf); - checkpt_failure |= CP_STATUSBAD; - return 1; - } - - return 0; -} - -/* - * Load the checkpoint from the given file - * Returns: - * < -1 error - * == -1 no file present - * == 0 loaded data - */ -int load_ChkPt(const char *fn) -{ -#define MAX_LN 1023 - FILE *fd; - char lbuf[MAX_LN]; - - if ((fd = fopen(fn, "r")) == NULL) { - if (errno == ENOENT) - return -1; - fprintf(stderr, "Cannot open checkpoint file - %s: %s\n", - fn, strerror(errno)); - return -2; - } - while (fgets(lbuf, MAX_LN, fd) != NULL) { - size_t len = strlen(lbuf); - - if (len && lbuf[len - 1] == '\n') /* drop the newline */ - lbuf[len - 1] = '\0'; - - if (strncmp(lbuf, "dev=", 4) == 0) { - errno = 0; - chkpt_input_dev = strtoul(&lbuf[4], NULL, 16); - if (errno) { - fprintf(stderr, "Malformed dev checkpoint " - "line - [%s]\n", lbuf); - checkpt_failure |= CP_STATUSBAD; - break; - } - } else if (strncmp(lbuf, "inode=", 6) == 0) { - errno = 0; - chkpt_input_ino = strtoul(&lbuf[6], NULL, 16); - if (errno) { - fprintf(stderr, "Malformed inode checkpoint " - "line - [%s]\n", lbuf); - checkpt_failure |= CP_STATUSBAD; - break; - } - } else if (strncmp(lbuf, "output=", 7) == 0) { - if (parse_checkpt_event(lbuf, 7, &chkpt_input_levent)) - break; - } else { - fprintf(stderr, "Unknown checkpoint line - [%s]\n", - lbuf); - checkpt_failure |= CP_STATUSBAD; - break; - } - } - if ( (chkpt_input_ino == (ino_t)NULL) || - (chkpt_input_dev == (dev_t)NULL) ) { - fprintf(stderr, "Missing dev/inode lines from checkpoint " - "file %s\n", fn); - checkpt_failure |= CP_STATUSBAD; - } - fclose(fd); - - if (checkpt_failure) - return -3; - -#if DBG - { - fprintf(stderr, "Loaded %s - dev: 0x%X, ino: 0x%X\n", - fn, chkpt_input_dev, chkpt_input_ino); - fprintf(stderr, "output:%s %d.%03d:%lu 0x%X\n", - chkpt_input_levent.node ? chkpt_input_levent.node : "-", - chkpt_input_levent.sec, chkpt_input_levent.milli, - chkpt_input_levent.serial, chkpt_input_levent.type); - } -#endif /* DBG */ - return 0; -} - diff --git a/framework/src/audit/src/ausearch-checkpt.h b/framework/src/audit/src/ausearch-checkpt.h deleted file mode 100644 index db66c254..00000000 --- a/framework/src/audit/src/ausearch-checkpt.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * ausearch-checkpt.h - ausearch checkpointing feature header file - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef CHECKPT_HEADER -#define CHECKPT_HEADER - -#include <sys/types.h> -#include "ausearch-llist.h" - -int set_ChkPtFileDetails(const char *fn); -int set_ChkPtLastEvent(const event *e); -void free_ChkPtMemory(void); -void save_ChkPt(const char *fn); -int load_ChkPt(const char *fn); - -#define CP_NOMEM 0x0001 /* no memory when creating checkpoint list */ -#define CP_STATFAILED 0x0002 /* stat() call on last log file failed */ -#define CP_STATUSIO 0x0004 /* cannot open/read/write checkpoint file */ -#define CP_STATUSBAD 0x0008 /* malformed status checkpoint entries */ -#define CP_CORRUPTED 0x0010 /* corrupted times in checkpoint file */ - -extern unsigned checkpt_failure; - -extern dev_t chkpt_input_dev; -extern ino_t chkpt_input_ino; -extern event chkpt_input_levent; - -#endif /* CHECKPT_HEADER */ diff --git a/framework/src/audit/src/ausearch-common.h b/framework/src/audit/src/ausearch-common.h deleted file mode 100644 index 96b59c85..00000000 --- a/framework/src/audit/src/ausearch-common.h +++ /dev/null @@ -1,73 +0,0 @@ -/* ausearch-common.h -- - * Copyright 2006-08,2010,2014 Red Hat Inc., Durham, North Carolina. - * Copyright (c) 2011 IBM Corp. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * Marcelo Henrique Cerri <mhcerri@br.ibm.com> - * - */ - -#ifndef AUREPORT_COMMON_H -#define AUREPORT_COMMON_H - -#include "ausearch-string.h" - -/* - * MAX_EVENT_DELTA_SECS is the maximum number of seconds it would take for - * auditd and the kernel to emit all of an events' records. Thus, when scanning - * a list of audit records without any End of Event marker, we can determine if - * all an event's records have been collected if we compare that event's time - * with the time of the event we are currently scanning. If - * MAX_EVENT_DELTA_SECS have passed, then the event is deamed to be complete - * and we have all it's records. - */ -#define MAX_EVENT_DELTA_SECS 2 - -/* Global variables that describe what search is to be performed */ -extern time_t start_time, end_time; -extern unsigned int event_id; -extern gid_t event_gid, event_egid; -extern pid_t event_pid; -extern int event_exact_match; -extern uid_t event_uid, event_euid, event_loginuid; -slist *event_node_list; -extern const char *event_comm; -extern const char *event_filename; -extern const char *event_hostname; -extern const char *event_terminal; -extern int event_syscall; -extern int event_machine; -extern const char *event_exe; -extern int event_ua, event_ga; -extern long long event_exit; -extern int event_exit_is_set; -extern const char *event_uuid; -extern const char *event_vmname; - -typedef enum { F_BOTH, F_FAILED, F_SUCCESS } failed_t; -typedef enum { C_NEITHER, C_ADD, C_DEL } conf_act_t; -typedef enum { S_UNSET=-1, S_FAILED, S_SUCCESS } success_t; -typedef enum { RPT_RAW, RPT_DEFAULT, RPT_INTERP, RPT_PRETTY } report_t; - -extern failed_t event_failed; -extern conf_act_t event_conf_act; -extern success_t event_success; - -#endif - diff --git a/framework/src/audit/src/ausearch-int.c b/framework/src/audit/src/ausearch-int.c deleted file mode 100644 index a6bf8eb4..00000000 --- a/framework/src/audit/src/ausearch-int.c +++ /dev/null @@ -1,162 +0,0 @@ -/* -* ausearch-int.c - Minimal linked list library for integers -* Copyright (c) 2005,2008 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 "config.h" -#include <stdlib.h> -#include <string.h> -#include "ausearch-int.h" - -void ilist_create(ilist *l) -{ - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - -int_node *ilist_next(ilist *l) -{ - if (l->cur == NULL) - return NULL; - l->cur = l->cur->next; - return l->cur; -} - -void ilist_append(ilist *l, int num, unsigned int hits, int aux) -{ - int_node* newnode; - - newnode = malloc(sizeof(int_node)); - - newnode->num = num; - newnode->hits = hits; - newnode->aux1 = aux; - newnode->next = NULL; - - // if we are at top, fix this up - if (l->head == NULL) - l->head = newnode; - else // Otherwise add pointer to newnode - l->cur->next = newnode; - - // make newnode current - l->cur = newnode; - l->cnt++; -} - -void ilist_clear(ilist* l) -{ - int_node* nextnode; - register int_node* current; - - if (l == NULL) - return; - - current = l->head; - while (current) { - nextnode=current->next; - free(current); - current=nextnode; - } - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - -int ilist_add_if_uniq(ilist *l, int num, int aux) -{ - register int_node *cur, *prev; - - prev = cur = l->head; - while (cur) { - if (cur->num == num) { - cur->hits++; - return 0; - } else if (num > cur->num) { - prev = cur; - cur = cur->next; - } else { - int head = 0; - - // Insert so list is from low to high - if (cur == l->head) { - l->head = NULL; - head = 1; - } else - l->cur = prev; - ilist_append(l, num, 1, aux); - if (head) - l->cur->next = prev; - else - l->cur->next = cur; - return 1; - } - } - - if (prev) - l->cur = prev; - - /* No matches, append to the end */ - ilist_append(l, num, 1, aux); - return 1; -} - -// If lprev would be NULL, use l->head -static void swap_nodes(int_node *lprev, int_node *left, int_node *right) -{ - int_node *t = right->next; - if (lprev) - lprev->next = right; - right->next = left; - left->next = t; -} - -// This will sort the list from most hits to least -void ilist_sort_by_hits(ilist *l) -{ - register int_node* cur, *prev; - - if (l->cnt <= 1) - return; - - prev = cur = l->head; - while (cur && cur->next) { - /* If the next node is bigger */ - if (cur->hits < cur->next->hits) { - if (cur == l->head) { - // Update the actual list head - l->head = cur->next; - prev = NULL; - } - swap_nodes(prev, cur, cur->next); - - // start over - prev = cur = l->head; - continue; - } - prev = cur; - cur = cur->next; - } - // End with cur pointing at first record - l->cur = l->head; -} - diff --git a/framework/src/audit/src/ausearch-int.h b/framework/src/audit/src/ausearch-int.h deleted file mode 100644 index bc2c51fc..00000000 --- a/framework/src/audit/src/ausearch-int.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -* ausearch-int.h - Header file for ausearch-int.c -* Copyright (c) 2005,2008 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> -*/ - -#ifndef AUINT_HEADER -#define AUINT_HEADER - -#include "config.h" - -/* This is the node of the linked list. Number & item are the only elements - * at this time. Any data elements that are per item goes here. */ -typedef struct _int_node{ - int num; // The number - unsigned int hits; // The number of times this was attempted to be added - int aux1; // Extra spot for data - struct _int_node* next; // Next string node pointer -} int_node; - -/* This is the linked list head. Only data elements that are 1 per - * event goes here. */ -typedef struct { - int_node *head; // List head - int_node *cur; // Pointer to current node - unsigned int cnt; // How many items in this list -} ilist; - -void ilist_create(ilist *l); -static inline void ilist_first(ilist *l) { l->cur = l->head; } -int_node *ilist_next(ilist *l); -static inline int_node *ilist_get_cur(ilist *l) { return l->cur; } -void ilist_append(ilist *l, int num, unsigned int hits, int aux); -void ilist_clear(ilist* l); - -/* append a number if its not already on the list */ -int ilist_add_if_uniq(ilist *l, int num, int aux); -void ilist_sort_by_hits(ilist *l); - -#endif - diff --git a/framework/src/audit/src/ausearch-llist.c b/framework/src/audit/src/ausearch-llist.c deleted file mode 100644 index 973941c5..00000000 --- a/framework/src/audit/src/ausearch-llist.c +++ /dev/null @@ -1,257 +0,0 @@ -/* -* ausearch-llist.c - Minimal linked list library -* Copyright (c) 2005-2008, 2011 Red Hat Inc., Durham, North Carolina. -* Copyright (c) 2011 IBM Corp. -* 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> -* Marcelo Henrique Cerri <mhcerri@br.ibm.com> -*/ - -#include <stdlib.h> -#include <string.h> -#include "ausearch-llist.h" - -void list_create(llist *l) -{ - l->head = NULL; - l->cur = NULL; - l->cnt = 0; - l->e.milli = 0L; - l->e.sec = 0L; - l->e.serial = 0L; - l->e.node = NULL; - l->e.type = 0; - l->s.gid = -1; - l->s.egid = -1; - l->s.ppid = -1; - l->s.pid = -1; - l->s.success = S_UNSET; - l->s.uid = -1; - l->s.euid = -1; - l->s.loginuid = -2; - l->s.hostname = NULL; - l->s.filename = NULL; - l->s.terminal = NULL; - l->s.cwd = NULL; - l->s.exe = NULL; - l->s.key = NULL; - l->s.comm = NULL; - l->s.avc = NULL; - l->s.acct = NULL; - l->s.arch = 0; - l->s.syscall = 0; - l->s.session_id = -2; - l->s.uuid = NULL; - l->s.vmname = NULL; - l->s.exit = 0; - l->s.exit_is_set = 0; -} - -void list_last(llist *l) -{ - register lnode* window; - - if (l->head == NULL) - return; - - window = l->head; - while (window->next) - window = window->next; - l->cur = window; -} - -lnode *list_next(llist *l) -{ - if (l->cur == NULL) - return NULL; - l->cur = l->cur->next; - return l->cur; -} - -lnode *list_prev(llist *l) -{ - if (l->cur == NULL) - return NULL; - - if (l->cur->item == 0) - return NULL; - - list_find_item(l, l->cur->item-1); - return l->cur; -} - -void list_append(llist *l, lnode *node) -{ - lnode* newnode; - - newnode = malloc(sizeof(lnode)); - - if (node->message) - newnode->message = node->message; - else - newnode->message = NULL; - - newnode->mlen = node->mlen; - newnode->type = node->type; - newnode->a0 = node->a0; - newnode->a1 = node->a1; - newnode->item = l->cnt; - newnode->next = NULL; - - // if we are at top, fix this up - if (l->head == NULL) - l->head = newnode; - else // Otherwise add pointer to newnode - l->cur->next = newnode; - - // make newnode current - l->cur = newnode; - l->cnt++; -} - -int list_find_item(llist *l, unsigned int i) -{ - register lnode* window; - - if (l->cur && (l->cur->item <= i)) - window = l->cur; /* Try to use where we are */ - else - window = l->head; /* Can't, start over */ - - while (window) { - if (window->item == i) { - l->cur = window; - return 1; - } else - window = window->next; - } - return 0; -} - -void list_clear(llist* l) -{ - lnode* nextnode; - register lnode* current; - - current = l->head; - while (current) { - nextnode=current->next; - free(current->message); - free(current); - current=nextnode; - } - l->head = NULL; - l->cur = NULL; - l->cnt = 0; - l->e.milli = 0L; - l->e.sec = 0L; - l->e.serial = 0L; - free((char *)l->e.node); - l->e.node = NULL; - l->e.type = 0; - l->s.gid = -1; - l->s.egid = -1; - l->s.ppid = -1; - l->s.pid = -1; - l->s.success = S_UNSET; - l->s.uid = -1; - l->s.euid = -1; - l->s.loginuid = -2; - free(l->s.hostname); - l->s.hostname = NULL; - if (l->s.filename) { - slist_clear(l->s.filename); - free(l->s.filename); - l->s.filename = NULL; - } - free(l->s.terminal); - l->s.terminal = NULL; - free(l->s.cwd); - l->s.cwd = NULL; - free(l->s.exe); - l->s.exe = NULL; - if (l->s.key) { - slist_clear(l->s.key); - free(l->s.key); - l->s.key = NULL; - } - free(l->s.comm); - l->s.comm = NULL; - if (l->s.avc) { - alist_clear(l->s.avc); - free(l->s.avc); - l->s.avc = NULL; - } - free(l->s.acct); - l->s.acct = NULL; - l->s.arch = 0; - l->s.syscall = 0; - l->s.session_id = -2; - free(l->s.uuid); - l->s.uuid = NULL; - free(l->s.vmname); - l->s.vmname = NULL; - l->s.exit = 0; - l->s.exit_is_set = 0; -} - -int list_get_event(llist* l, event *e) -{ - if (l == NULL || e == NULL) - return 0; - - e->sec = l->e.sec; - e->milli = l->e.milli; - e->serial = l->e.serial; - return 1; -} - -lnode *list_find_msg(llist *l, int i) -{ - register lnode* window; - - window = l->head; /* start at the beginning */ - while (window) { - if (window->type == i) { - l->cur = window; - return window; - } else - window = window->next; - } - return NULL; -} - -lnode *list_find_msg_range(llist *l, int low, int high) -{ - register lnode* window; - - if (high <= low) - return NULL; - - window = l->head; /* Start at the beginning */ - while (window) { - if (window->type >= low && window->type <= high) { - l->cur = window; - return window; - } else - window = window->next; - } - return NULL; -} - diff --git a/framework/src/audit/src/ausearch-llist.h b/framework/src/audit/src/ausearch-llist.h deleted file mode 100644 index ada8ec81..00000000 --- a/framework/src/audit/src/ausearch-llist.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -* ausearch-llist.h - Header file for ausearch-llist.c -* Copyright (c) 2005-2008, 2013-14 Red Hat Inc., Durham, North Carolina. -* Copyright (c) 2011 IBM Corp. -* 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> -* Marcelo Henrique Cerri <mhcerri@br.ibm.com> -*/ - -#ifndef AULIST_HEADER -#define AULIST_HEADER - -#include "config.h" -#include <sys/types.h> -#include "ausearch-string.h" -#include "ausearch-avc.h" -#include "ausearch-common.h" - - -typedef struct -{ - time_t sec; // Event seconds - unsigned int milli; // millisecond of the timestamp - unsigned long serial; // Serial number of the event - const char *node; // Machine's node name - int type; // type of first event -} event; - -typedef struct -{ - pid_t ppid; // parent process ID - pid_t pid; // process ID - uid_t uid; // user ID - uid_t euid; // effective user ID - uid_t loginuid; // login user ID - gid_t gid; // group ID - gid_t egid; // effective group ID - success_t success; // success flag, 1 = yes, 0 = no, -1 = unset - int arch; // arch - int syscall; // syscall - uint32_t session_id; // Login session id - long long exit; // Syscall exit code - int exit_is_set; // Syscall exit code is valid - char *hostname; // remote hostname - slist *filename; // filename list - char *cwd; // current working dir - char *exe; // executable - slist *key; // key field - char *terminal; // terminal - char *comm; // comm name - alist *avc; // avcs for the event - char *acct; // account used when uid is invalid - char *uuid; // virtual machine unique universal identifier - char *vmname; // virtual machine name -} search_items; - -/* This is the node of the linked list. Any data elements that are per - * record goes here. */ -typedef struct _lnode{ - char *message; // The whole unparsed message - unsigned mlen; // Length of the message - int type; // message type (KERNEL, USER, LOGIN, etc) - unsigned long long a0; // argv 0 - unsigned long long a1; // argv 1 - unsigned int item; // Which item of the same event - struct _lnode* next; // Next node pointer -} lnode; - -/* This is the linked list head. Only data elements that are 1 per - * event goes here. */ -typedef struct { - lnode *head; // List head - lnode *cur; // Pointer to current node - unsigned int cnt; // How many items in this list - - // Data we add as 1 per event - event e; // event - time & serial number - search_items s; // items in master rec that are searchable -} llist; - -void list_create(llist *l); -static inline void list_first(llist *l) { l->cur = l->head; } -void list_last(llist *l); -lnode *list_next(llist *l); -lnode *list_prev(llist *l); -static inline lnode *list_get_cur(llist *l) { return l->cur; } -void list_append(llist *l, lnode *node); -void list_clear(llist* l); -int list_get_event(llist* l, event *e); - -/* Given a numeric index, find that record. */ -int list_find_item(llist *l, unsigned int i); - -/* Given a message type, find the matching node */ -lnode *list_find_msg(llist *l, int i); - -/* Given two message types, find the first matching node */ -lnode *list_find_msg_range(llist *l, int low, int high); - -#endif - diff --git a/framework/src/audit/src/ausearch-lol.c b/framework/src/audit/src/ausearch-lol.c deleted file mode 100644 index 48005126..00000000 --- a/framework/src/audit/src/ausearch-lol.c +++ /dev/null @@ -1,296 +0,0 @@ -/* -* 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; -} - diff --git a/framework/src/audit/src/ausearch-lol.h b/framework/src/audit/src/ausearch-lol.h deleted file mode 100644 index 36b6bbca..00000000 --- a/framework/src/audit/src/ausearch-lol.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* ausearch-lol.h - linked list of linked lists library header -* Copyright (c) 2008 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> -*/ - -#ifndef AUSEARCH_LOL_HEADER -#define AUSEARCH_LOL_HEADER - -#include "config.h" -#include "ausearch-llist.h" - -typedef enum { L_EMPTY, L_BUILDING, L_COMPLETE } lol_t; - -/* This is the node of the linked list. message & item are the only elements - * at this time. Any data elements that are per item goes here. */ -typedef struct _lolnode{ - llist *l; // The linked list - int status; // 0 = empty, 1 in use, 2 complete -} lolnode; - -/* This is the linked list head. Only data elements that are 1 per - * event goes here. */ -typedef struct { - lolnode *array; - int maxi; // Largest index used - int limit; // Number of nodes in the array -} lol; - -void lol_create(lol *lo); -void lol_clear(lol *lo); -int lol_add_record(lol *lo, char *buff); -void terminate_all_events(lol *lo); -llist* get_ready_event(lol *lo); - -#endif - diff --git a/framework/src/audit/src/ausearch-lookup.c b/framework/src/audit/src/ausearch-lookup.c deleted file mode 100644 index 10a219a5..00000000 --- a/framework/src/audit/src/ausearch-lookup.c +++ /dev/null @@ -1,500 +0,0 @@ -/* -* ausearch-lookup.c - Lookup values to something more readable -* Copyright (c) 2005-06,2011-12,2015 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 "config.h" -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <linux/net.h> -#include "ausearch-lookup.h" -#include "ausearch-options.h" -#include "ausearch-nvpair.h" - -/* This is the name/value pair used by search tables */ -struct nv_pair { - int value; - const char *name; -}; - - -/* The machine based on elf type */ -static int machine = 0; -static const char *Q = "?"; -static const char *results[3]= { "unset", "denied", "granted" }; -static const char *success[3]= { "unset", "no", "yes" }; -static const char *aulookup_socketcall(long sc); -static const char *aulookup_ipccall(long ic); - -const char *aulookup_result(avc_t result) -{ - return results[result]; -} - -const char *aulookup_success(int s) -{ - switch (s) - { - default: - return success[0]; - break; - case S_FAILED: - return success[1]; - break; - case S_SUCCESS: - return success[2]; - break; - } -} - -const char *aulookup_syscall(llist *l, char *buf, size_t size) -{ - const char *sys; - - if (report_format <= RPT_DEFAULT) { - snprintf(buf, size, "%d", l->s.syscall); - return buf; - } - machine = audit_elf_to_machine(l->s.arch); - if (machine < 0) - return Q; - sys = audit_syscall_to_name(l->s.syscall, machine); - if (sys) { - const char *func = NULL; - if (strcmp(sys, "socketcall") == 0) { - if (list_find_item(l, AUDIT_SYSCALL)) - func = aulookup_socketcall((long)l->cur->a0); - } else if (strcmp(sys, "ipc") == 0) { - if(list_find_item(l, AUDIT_SYSCALL)) - func = aulookup_ipccall((long)l->cur->a0); - } - if (func) { - snprintf(buf, size, "%s(%s)", sys, func); - return buf; - } - return sys; - } - snprintf(buf, size, "%d", l->s.syscall); - return buf; -} - -// See include/linux/net.h -static struct nv_pair socktab[] = { - {SYS_SOCKET, "socket"}, - {SYS_BIND, "bind"}, - {SYS_CONNECT, "connect"}, - {SYS_LISTEN, "listen"}, - {SYS_ACCEPT, "accept"}, - {SYS_GETSOCKNAME, "getsockname"}, - {SYS_GETPEERNAME, "getpeername"}, - {SYS_SOCKETPAIR, "socketpair"}, - {SYS_SEND, "send"}, - {SYS_RECV, "recv"}, - {SYS_SENDTO, "sendto"}, - {SYS_RECVFROM, "recvfrom"}, - {SYS_SHUTDOWN, "shutdown"}, - {SYS_SETSOCKOPT, "setsockopt"}, - {SYS_GETSOCKOPT, "getsockopt"}, - {SYS_SENDMSG, "sendmsg"}, - {SYS_RECVMSG, "recvmsg"}, - {SYS_ACCEPT4, "accept4"}, - {19, "recvmmsg"}, - {20, "sendmmsg"} -}; -#define SOCK_NAMES (sizeof(socktab)/sizeof(socktab[0])) - -static const char *aulookup_socketcall(long sc) -{ - int i; - - for (i = 0; i < SOCK_NAMES; i++) - if (socktab[i].value == sc) - return socktab[i].name; - - return NULL; -} - -/* This is from asm/ipc.h. Copying it for now as some platforms - * have broken headers. */ -#define SEMOP 1 -#define SEMGET 2 -#define SEMCTL 3 -#define SEMTIMEDOP 4 -#define MSGSND 11 -#define MSGRCV 12 -#define MSGGET 13 -#define MSGCTL 14 -#define SHMAT 21 -#define SHMDT 22 -#define SHMGET 23 -#define SHMCTL 24 - -/* - * This table maps ipc calls to their text name - */ -static struct nv_pair ipctab[] = { - {SEMOP, "semop"}, - {SEMGET, "semget"}, - {SEMCTL, "semctl"}, - {SEMTIMEDOP, "semtimedop"}, - {MSGSND, "msgsnd"}, - {MSGRCV, "msgrcv"}, - {MSGGET, "msgget"}, - {MSGCTL, "msgctl"}, - {SHMAT, "shmat"}, - {SHMDT, "shmdt"}, - {SHMGET, "shmget"}, - {SHMCTL, "shmctl"} -}; -#define IPC_NAMES (sizeof(ipctab)/sizeof(ipctab[0])) - -static const char *aulookup_ipccall(long ic) -{ - int i; - - for (i = 0; i < IPC_NAMES; i++) - if (ipctab[i].value == ic) - return ipctab[i].name; - - return NULL; -} - -static nvlist uid_nvl; -static int uid_list_created=0; -const char *aulookup_uid(uid_t uid, char *buf, size_t size) -{ - char *name = NULL; - int rc; - - if (report_format <= RPT_DEFAULT) { - snprintf(buf, size, "%d", uid); - return buf; - } - if (uid == -1) { - snprintf(buf, size, "unset"); - return buf; - } - - // Check the cache first - if (uid_list_created == 0) { - nvlist_create(&uid_nvl); - nvlist_clear(&uid_nvl); - uid_list_created = 1; - } - rc = nvlist_find_val(&uid_nvl, uid); - if (rc) { - name = uid_nvl.cur->name; - } else { - // Add it to cache - struct passwd *pw; - pw = getpwuid(uid); - if (pw) { - nvnode nv; - nv.name = strdup(pw->pw_name); - nv.val = uid; - nvlist_append(&uid_nvl, &nv); - name = uid_nvl.cur->name; - } - } - if (name != NULL) - snprintf(buf, size, "%s", name); - else - snprintf(buf, size, "unknown(%d)", uid); - return buf; -} - -void aulookup_destroy_uid_list(void) -{ - if (uid_list_created == 0) - return; - - nvlist_clear(&uid_nvl); - uid_list_created = 0; -} - -static nvlist gid_nvl; -static int gid_list_created=0; -const char *aulookup_gid(gid_t gid, char *buf, size_t size) -{ - char *name = NULL; - int rc; - - if (report_format <= RPT_DEFAULT) { - snprintf(buf, size, "%d", gid); - return buf; - } - if (gid == -1) { - snprintf(buf, size, "unset"); - return buf; - } - - // Check the cache first - if (gid_list_created == 0) { - nvlist_create(&gid_nvl); - nvlist_clear(&gid_nvl); - gid_list_created = 1; - } - rc = nvlist_find_val(&gid_nvl, gid); - if (rc) { - name = gid_nvl.cur->name; - } else { - // Add it to cache - struct group *gr; - gr = getgrgid(gid); - if (gr) { - nvnode nv; - nv.name = strdup(gr->gr_name); - nv.val = gid; - nvlist_append(&gid_nvl, &nv); - name = gid_nvl.cur->name; - } - } - if (name != NULL) - snprintf(buf, size, "%s", name); - else - snprintf(buf, size, "unknown(%d)", gid); - return buf; -} - -void aulookup_destroy_gid_list(void) -{ - if (gid_list_created == 0) - return; - - nvlist_clear(&gid_nvl); - gid_list_created = 0; -} - -int is_hex_string(const char *str) -{ - int c=0; - while (*str) { - if (!isxdigit(*str)) - return 0; - str++; - c++; - } - return 1; -} -/* - * This function will take a pointer to a 2 byte Ascii character buffer and - * return the actual hex value. - */ -static unsigned char x2c(unsigned char *buf) -{ - static const char AsciiArray[17] = "0123456789ABCDEF"; - char *ptr; - unsigned char total=0; - - ptr = strchr(AsciiArray, (char)toupper(buf[0])); - if (ptr) - total = (unsigned char)(((ptr-AsciiArray) & 0x0F)<<4); - ptr = strchr(AsciiArray, (char)toupper(buf[1])); - if (ptr) - total += (unsigned char)((ptr-AsciiArray) & 0x0F); - - return total; -} - -/* returns a freshly malloc'ed and converted buffer */ -char *unescape(const char *buf) -{ - int len, i; - char *str, *strptr; - const char *ptr = buf; - - /* Find the end of the name */ - if (*ptr == '(') { - ptr = strchr(ptr, ')'); - if (ptr == NULL) - return NULL; - else - ptr++; - } else { - while (isxdigit(*ptr)) - ptr++; - } - str = strndup(buf, ptr - buf); - - if (*buf == '(') - return str; - - /* We can get away with this since the buffer is 2 times - * bigger than what we are putting there. - */ - len = strlen(str); - if (len < 2) { - free(str); - return NULL; - } - strptr = str; - for (i=0; i<len; i+=2) { - *strptr = x2c((unsigned char *)&str[i]); - strptr++; - } - *strptr = 0; - return str; -} - -int need_sanitize(const unsigned char *s, unsigned int len) -{ - unsigned int i = 0; - while (i < len) { - if (s[i] < 32) - return 1; - i++; - } - return 0; -} - -void sanitize(const char *s, unsigned int len) -{ - unsigned int i = 0; - while (i < len) { - if ((unsigned char)s[i] < 32) { - putchar('\\'); - putchar('0' + ((s[i] & 0300) >> 6)); - putchar('0' + ((s[i] & 0070) >> 3)); - putchar('0' + (s[i] & 0007)); - } else - putchar(s[i]); - i++; - } -} - -void safe_print_string_n(const char *s, unsigned int len, int ret) -{ - if (need_sanitize(s, len)) { - sanitize(s, len); - if (ret) - putchar('\n'); - } else if (ret) - puts(s); - else - printf("%s", s); -} - -void safe_print_string(const char *s, int ret) -{ - safe_print_string_n(s, strlen(s), ret); -} - -/* Represent c as a character within a quoted string, and append it to buf. */ -static void tty_printable_char(unsigned char c) -{ - if (c < 0x20 || c > 0x7E) { - putchar('\\'); - putchar('0' + ((c >> 6) & 07)); - putchar('0' + ((c >> 3) & 07)); - putchar('0' + (c & 07)); - } else { - if (c == '\\' || c == '"') - putchar('\\'); - putchar(c); - } -} - -/* Search for a name of a sequence of TTY bytes. - * If found, return the name and advance *INPUT. - * Return NULL otherwise. - */ -static const char *tty_find_named_key(unsigned char **input, size_t input_len) -{ - /* NUL-terminated list of (sequence, NUL, name, NUL) entries. - First match wins, even if a longer match were possible later */ - static const unsigned char named_keys[] = -#define E(SEQ, NAME) SEQ "\0" NAME "\0" -#include "auparse/tty_named_keys.h" -#undef E - "\0"; - - unsigned char *src; - const unsigned char *nk; - - src = *input; - if (*src >= ' ' && (*src < 0x7F || *src >= 0xA0)) - return NULL; /* Fast path */ - nk = named_keys; - do { - const unsigned char *p; - size_t nk_len; - - p = strchr((const char *)nk, '\0'); - nk_len = p - nk; - if (nk_len <= input_len && memcmp(src, nk, nk_len) == 0) { - *input += nk_len; - return (const char *)(p + 1); - } - nk = strchr((const char *)p + 1, '\0') + 1; - } while (*nk != '\0'); - return NULL; -} - -void print_tty_data(const char *val) -{ - int need_comma, in_printable = 0; - unsigned char *data, *data_pos, *data_end; - - if (!is_hex_string(val)) { - printf("%s", val); - return; - } - - if ((data = unescape((char *)val)) == NULL) { - printf("conversion error(%s)", val); - return; - } - - data_end = data + strlen(val) / 2; - data_pos = data; - need_comma = 0; - while (data_pos < data_end) { - /* FIXME: Unicode */ - const char *desc; - - desc = tty_find_named_key(&data_pos, data_end - data_pos); - if (desc != NULL) { - if (in_printable != 0) { - putchar('"'); - in_printable = 0; - } - if (need_comma != 0) - putchar(','); - printf("<%s>", desc); - } else { - if (in_printable == 0) { - if (need_comma != 0) - putchar(','); - putchar('"'); - in_printable = 1; - } - tty_printable_char(*data_pos); - data_pos++; - } - need_comma = 1; - } - if (in_printable != 0) - putchar('"'); - free(data); -} - diff --git a/framework/src/audit/src/ausearch-lookup.h b/framework/src/audit/src/ausearch-lookup.h deleted file mode 100644 index ab12e176..00000000 --- a/framework/src/audit/src/ausearch-lookup.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -* ausearch-lookup.h - Header file for ausearch-lookup.c -* Copyright (c) 2005-06,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> -*/ - -#ifndef AULOOKUP_HEADER -#define AULOOKUP_HEADER - -#include "config.h" -#include <pwd.h> -#include <grp.h> -#include "libaudit.h" -#include "ausearch-llist.h" - - -const char *aulookup_result(avc_t result); -const char *aulookup_success(int s); -const char *aulookup_syscall(llist *l, char *buf, size_t size); -const char *aulookup_uid(uid_t uid, char *buf, size_t size); -void aulookup_destroy_uid_list(void); -const char *aulookup_gid(gid_t gid, char *buf, size_t size); -void aulookup_destroy_gid_list(void); -char *unescape(const char *buf); -int is_hex_string(const char *str); -void print_tty_data(const char *val); -int need_sanitize(const unsigned char *s, unsigned int len); -void sanitize(const char *s, unsigned int len); -void safe_print_string_n(const char *s, unsigned int len, int ret); -void safe_print_string(const char *s, int ret); - -#endif - diff --git a/framework/src/audit/src/ausearch-match.c b/framework/src/audit/src/ausearch-match.c deleted file mode 100644 index 44c60887..00000000 --- a/framework/src/audit/src/ausearch-match.c +++ /dev/null @@ -1,364 +0,0 @@ -/* -* ausearch-match.c - Extract interesting fields and check for match -* Copyright (c) 2005-08, 2011 Red Hat Inc., Durham, North Carolina. -* Copyright (c) 2011 IBM Corp. -* 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> -* Marcelo Henrique Cerri <mhcerri@br.ibm.com> -*/ - -#include "config.h" -#include <string.h> -#include "libaudit.h" -#include "ausearch-options.h" -#include "ausearch-parse.h" - -static int strmatch(const char *needle, const char *haystack); -static int user_match(llist *l); -static int group_match(llist *l); -static int context_match(llist *l); - -/* - * This function performs that matching of search params with the record. - * It returns 1 on a match, and 0 if no match. The way that this function - * works is that it will try to determine if there is not a match and exit - * as soon as possible. We can do this since all command line params form - * an 'and' statement. If anything does not match, no need to evaluate the - * rest of the params. - */ -#include <stdio.h> -int match(llist *l) -{ - // Are we within time range? - if (start_time == 0 || l->e.sec >= start_time) { - if (end_time == 0 || l->e.sec <= end_time) { - if (event_id == -1 || event_id == l->e.serial) { - // OK - do the heavier checking - if (extract_search_items(l)) { - return 0; - } - - // perform additional tests for the field - if (event_node_list) { - const snode *sn; - int found=0; - slist *sptr = event_node_list; - - if (l->e.node == NULL) - return 0; - - slist_first(sptr); - sn=slist_get_cur(sptr); - while (sn && !found) { - if (sn->str && (!strcmp(sn->str, l->e.node))) - found++; - else - sn=slist_next(sptr); - } - if (!found) - return 0; - } - if (user_match(l) == 0) - return 0; - if (group_match(l) == 0) - return 0; - if ((event_ppid != -1) && - (event_ppid != l->s.ppid)) - return 0; - if ((event_pid != -1) && - (event_pid != l->s.pid)) - return 0; - if (event_machine != -1 && - (event_machine != - audit_elf_to_machine(l->s.arch))) - return 0; - if ((event_syscall != -1) && - (event_syscall != l->s.syscall)) - return 0; - if ((event_session_id != -2) && - (event_session_id != l->s.session_id)) - return 0; - if (event_exit_is_set) { - if (l->s.exit_is_set == 0) - return 0; - if (event_exit != l->s.exit) - return 0; - } - - if ((event_success != S_UNSET) && - (event_success != l->s.success)) - return 0; - // event_type requires looking at each item - if (event_type != NULL) { - int found = 0; - const lnode *n; - - list_first(l); - n = list_get_cur(l); - do { - int_node *in; - ilist_first(event_type); - in = ilist_get_cur(event_type); - do { - if (in->num == n->type){ - found = 1; - break; - } - } while((in = - ilist_next(event_type))); - if (found) - break; - } while ((n = list_next(l))); - if (!found) - return 0; - } - - // Done all the easy compares, now do the - // string searches. - if (event_filename) { - int found = 0; - if (l->s.filename == NULL && l->s.cwd == NULL) - return 0; - if (l->s.filename) { - const snode *sn; - slist *sptr = l->s.filename; - - slist_first(sptr); - sn=slist_get_cur(sptr); - do { - if (sn->str == NULL) - return 0; - if (strmatch( - event_filename, - sn->str)) { - found = 1; - break; - } - } while ((sn=slist_next(sptr))); - - if (!found && l->s.cwd == NULL) - return 0; - } - if (l->s.cwd && !found) { - /* Check cwd, too */ - if (strmatch(event_filename, - l->s.cwd) == 0) - return 0; - } - } - if (event_hostname) { - if (l->s.hostname == NULL) - return 0; - if (strmatch(event_hostname, - l->s.hostname) == 0) - return 0; - } - if (event_terminal) { - if (l->s.terminal == NULL) - return 0; - if (strmatch(event_terminal, - l->s.terminal) == 0) - return 0; - } - if (event_exe) { - if (l->s.exe == NULL) - return 0; - if (strmatch(event_exe, - l->s.exe) == 0) - return 0; - } - if (event_comm) { - if (l->s.comm == NULL) - return 0; - if (strmatch(event_comm, - l->s.comm) == 0) - return 0; - } - if (event_key) { - if (l->s.key == NULL) - return 0; - else { - int found = 0; - const snode *sn; - slist *sptr = l->s.key; - - slist_first(sptr); - sn=slist_get_cur(sptr); - do { - if (sn->str == NULL) - return 0; - if (strmatch( - event_key, - sn->str)) { - found = 1; - break; - } - } while ((sn=slist_next(sptr))); - if (!found) - return 0; - } - } - if (event_vmname) { - if (l->s.vmname == NULL) - return 0; - if (strmatch(event_vmname, - l->s.vmname) == 0) - return 0; - } - if (event_uuid) { - if (l->s.uuid == NULL) - return 0; - if (strmatch(event_uuid, - l->s.uuid) == 0) - return 0; - } - if (context_match(l) == 0) - return 0; - return 1; - } - } - } - return 0; -} - -/* - * This function compares strings. It returns a 0 if no match and a 1 if - * there is a match - */ -static int strmatch(const char *needle, const char *haystack) -{ - if (event_exact_match) { - if (strcmp(haystack, needle) != 0) - return 0; - } else { - if (strstr(haystack, needle) == NULL) - return 0; - } - return 1; -} - -/* - * This function compares user id's. It returns a 0 if no match and a 1 if - * there is a match - */ -static int user_match(llist *l) -{ - if (event_ua) { - // This will "or" the user tests - if (event_uid == l->s.uid) - return 1; - if (event_euid == l->s.euid) - return 1; - if (event_loginuid == l->s.loginuid) - return 1; - return 0; - } else { - // This will "and" the user tests - if ((event_uid != -1) && (event_uid != l->s.uid)) - return 0; - if ((event_euid != -1) &&(event_euid != l->s.euid)) - return 0; - if ((event_loginuid != -2) && - (event_loginuid != l->s.loginuid)) - return 0; - } - return 1; -} - -/* - * This function compares group id's. It returns a 0 if no match and a 1 if - * there is a match - */ -static int group_match(llist *l) -{ - if (event_ga) { - // This will "or" the group tests - if (event_gid == l->s.gid) - return 1; - if (event_egid == l->s.egid) - return 1; - return 0; - } else { - // This will "and" the group tests - if ((event_gid != -1) && (event_gid != l->s.gid)) - return 0; - if ((event_egid != -1) &&(event_egid != l->s.egid)) - return 0; - } - return 1; -} - -/* - * This function compares contexts. It returns a 0 if no match and a 1 if - * there is a match - */ -static int context_match(llist *l) -{ - if (event_se) { /* This does the "or" check if -se test */ - if (event_subject) { - if (l->s.avc && alist_find_subj(l->s.avc)) { - do { - if (strmatch(event_subject, - l->s.avc->cur->scontext)) - return 1; - } while(alist_next_subj(l->s.avc)); - } - } - if (event_object) { - if (l->s.avc) { - alist_first(l->s.avc); - if (alist_find_obj(l->s.avc)) { - do { - if (strmatch(event_object, - l->s.avc->cur->tcontext)) - return 1; - } while(alist_next_obj(l->s.avc)); - } - } - } - return 0; - } else { - if (event_subject) { - if (l->s.avc == NULL) - return 0; - if (alist_find_subj(l->s.avc)) { - do { - if (strmatch(event_subject, - l->s.avc->cur->scontext)) - return 1; - } while(alist_next_subj(l->s.avc)); - } - return 0; - } - if (event_object) { - if (l->s.avc == NULL) - return 0; - if (alist_find_obj(l->s.avc)) { - do { - if (strmatch(event_object, - l->s.avc->cur->tcontext)) - return 1; - } while(alist_next_obj(l->s.avc)); - } - return 0; - } - } - return 1; -} - diff --git a/framework/src/audit/src/ausearch-nvpair.c b/framework/src/audit/src/ausearch-nvpair.c deleted file mode 100644 index 3dfadb60..00000000 --- a/framework/src/audit/src/ausearch-nvpair.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -* ausearch-nvpair.c - Minimal linked list library for name-value pairs -* Copyright (c) 2006-08 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 "config.h" -#include <stdlib.h> -#include "ausearch-nvpair.h" - - -void nvlist_create(nvlist *l) -{ - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - -nvnode *nvlist_next(nvlist *l) -{ - if (l->cur == NULL) - return NULL; - l->cur = l->cur->next; - return l->cur; -} - -void nvlist_append(nvlist *l, nvnode *node) -{ - nvnode* newnode = malloc(sizeof(nvnode)); - - newnode->name = node->name; - newnode->val = node->val; - newnode->next = NULL; - - // if we are at top, fix this up - if (l->head == NULL) - l->head = newnode; - else { // Add pointer to newnode and make sure we are at the end - while (l->cur->next) - l->cur = l->cur->next; - l->cur->next = newnode; - } - - // make newnode current - l->cur = newnode; - l->cnt++; -} - -int nvlist_find_val(nvlist *l, long val) -{ - register nvnode* window = l->head; - - while (window) { - if (window->val == val) { - l->cur = window; - return 1; - } - else - window = window->next; - } - return 0; -} - -void nvlist_clear(nvlist* l) -{ - nvnode* nextnode; - register nvnode* current; - - current = l->head; - while (current) { - nextnode=current->next; - free(current->name); - free(current); - current=nextnode; - } - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - diff --git a/framework/src/audit/src/ausearch-nvpair.h b/framework/src/audit/src/ausearch-nvpair.h deleted file mode 100644 index 9fb91ba9..00000000 --- a/framework/src/audit/src/ausearch-nvpair.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* ausearch-nvpair.h - Header file for ausearch-nvpair.c -* Copyright (c) 2006-08 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> -*/ - -#ifndef AUNVPAIR_HEADER -#define AUNVPAIR_HEADER - -#include "config.h" -#include <sys/types.h> - -/* This is the node of the linked list. message & item are the only elements - * at this time. Any data elements that are per item goes here. */ -typedef struct _nvnode{ - char *name; // The name string - long val; // The value field - struct _nvnode* next; // Next nvpair node pointer -} nvnode; - -/* This is the linked list head. Only data elements that are 1 per - * event goes here. */ -typedef struct { - nvnode *head; // List head - nvnode *cur; // Pointer to current node - unsigned int cnt; // How many items in this list -} nvlist; - -void nvlist_create(nvlist *l); -static inline void nvlist_first(nvlist *l) { l->cur = l->head; } -nvnode *nvlist_next(nvlist *l); -static inline nvnode *nvlist_get_cur(nvlist *l) { return l->cur; } -void nvlist_append(nvlist *l, nvnode *node); -void nvlist_clear(nvlist* l); - -/* Given a numeric index, find that record. */ -int nvlist_find_val(nvlist *l, long val); - -#endif - diff --git a/framework/src/audit/src/ausearch-options.c b/framework/src/audit/src/ausearch-options.c deleted file mode 100644 index 50469723..00000000 --- a/framework/src/audit/src/ausearch-options.c +++ /dev/null @@ -1,1175 +0,0 @@ -/* ausearch-options.c - parse commandline options and configure ausearch - * Copyright 2005-08,2010-11,2014 Red Hat Inc., Durham, North Carolina. - * Copyright (c) 2011 IBM Corp. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Debora Velarde <dvelarde@us.ibm.com> - * Steve Grubb <sgrubb@redhat.com> - * Marcelo Henrique Cerri <mhcerri@br.ibm.com> - */ - -#include "config.h" -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <pwd.h> -#include <grp.h> -#include "ausearch-options.h" -#include "ausearch-time.h" -#include "ausearch-int.h" -#include "libaudit.h" - - -/* Global vars that will be accessed by the main program */ -char *user_file = NULL; -int force_logs = 0; - -/* Global vars that will be accessed by the match model */ -unsigned int event_id = -1; -gid_t event_gid = -1, event_egid = -1; -ilist *event_type = NULL; -pid_t event_pid = -1, event_ppid = -1; -success_t event_success = S_UNSET; -int event_exact_match = 0; -uid_t event_uid = -1, event_euid = -1, event_loginuid = -2; -int event_syscall = -1, event_machine = -1; -int event_ua = 0, event_ga = 0, event_se = 0; -int just_one = 0; -uint32_t event_session_id = -2; -long long event_exit = 0; -int event_exit_is_set = 0; -int line_buffered = 0; -int event_debug = 0; -int checkpt_timeonly = 0; -const char *event_key = NULL; -const char *event_filename = NULL; -const char *event_exe = NULL; -const char *event_comm = NULL; -const char *event_hostname = NULL; -const char *event_terminal = NULL; -const char *event_subject = NULL; -const char *event_object = NULL; -const char *event_uuid = NULL; -const char *event_vmname = NULL; -const char *checkpt_filename = NULL; /* checkpoint filename if present */ -report_t report_format = RPT_DEFAULT; -ilist *event_type; - -slist *event_node_list = NULL; - -struct nv_pair { - int value; - const char *name; -}; - - -enum { S_EVENT, S_COMM, S_FILENAME, S_ALL_GID, S_EFF_GID, S_GID, S_HELP, -S_HOSTNAME, S_INTERP, S_INFILE, S_MESSAGE_TYPE, S_PID, S_SYSCALL, S_OSUCCESS, -S_TIME_END, S_TIME_START, S_TERMINAL, S_ALL_UID, S_EFF_UID, S_UID, S_LOGINID, -S_VERSION, S_EXACT_MATCH, S_EXECUTABLE, S_CONTEXT, S_SUBJECT, S_OBJECT, -S_PPID, S_KEY, S_RAW, S_NODE, S_IN_LOGS, S_JUST_ONE, S_SESSION, S_EXIT, -S_LINEBUFFERED, S_UUID, S_VMNAME, S_DEBUG, S_CHECKPOINT, S_ARCH }; - -static struct nv_pair optiontab[] = { - { S_EVENT, "-a" }, - { S_ARCH, "--arch" }, - { S_EVENT, "--event" }, - { S_COMM, "-c" }, - { S_COMM, "--comm" }, - { S_CHECKPOINT, "--checkpoint" }, - { S_DEBUG, "--debug" }, - { S_EXIT, "-e" }, - { S_EXIT, "--exit" }, - { S_FILENAME, "-f" }, - { S_FILENAME, "--file" }, - { S_ALL_GID, "-ga" }, - { S_ALL_GID, "--gid-all" }, - { S_EFF_GID, "-ge" }, - { S_EFF_GID, "--gid-effective" }, - { S_GID, "-gi" }, - { S_GID, "--gid" }, - { S_HELP, "-h" }, - { S_HELP, "--help" }, - { S_HOSTNAME, "-hn" }, - { S_HOSTNAME, "--host" }, - { S_INTERP, "-i" }, - { S_INTERP, "--interpret" }, - { S_INFILE, "-if" }, - { S_INFILE, "--input" }, - { S_IN_LOGS, "--input-logs" }, - { S_JUST_ONE, "--just-one" }, - { S_KEY, "-k" }, - { S_KEY, "--key" }, - { S_LINEBUFFERED, "-l" }, - { S_LINEBUFFERED, "--line-buffered" }, - { S_MESSAGE_TYPE, "-m" }, - { S_MESSAGE_TYPE, "--message" }, - { S_NODE, "-n" }, - { S_NODE, "--node" }, - { S_OBJECT, "-o" }, - { S_OBJECT, "--object" }, - { S_PID, "-p" }, - { S_PID, "--pid" }, - { S_PPID, "-pp" }, - { S_PPID, "--ppid" }, - { S_RAW, "-r" }, - { S_RAW, "--raw" }, - { S_SYSCALL, "-sc" }, - { S_SYSCALL, "--syscall" }, - { S_CONTEXT, "-se" }, - { S_CONTEXT, "--context" }, - { S_SESSION, "--session" }, - { S_SUBJECT, "-su" }, - { S_SUBJECT, "--subject" }, - { S_OSUCCESS, "-sv" }, - { S_OSUCCESS, "--success" }, - { S_TIME_END, "-te"}, - { S_TIME_END, "--end"}, - { S_TIME_START, "-ts" }, - { S_TIME_START, "--start" }, - { S_TERMINAL, "-tm" }, - { S_TERMINAL, "--terminal" }, - { S_ALL_UID, "-ua" }, - { S_ALL_UID, "--uid-all" }, - { S_EFF_UID, "-ue" }, - { S_EFF_UID, "--uid-effective" }, - { S_UID, "-ui" }, - { S_UID, "--uid" }, - { S_UUID, "-uu" }, - { S_UUID, "--uuid" }, - { S_LOGINID, "-ul" }, - { S_LOGINID, "--loginuid" }, - { S_VERSION, "-v" }, - { S_VERSION, "--version" }, - { S_VMNAME, "-vm" }, - { S_VMNAME, "--vm-name" }, - { S_EXACT_MATCH, "-w" }, - { S_EXACT_MATCH, "--word" }, - { S_EXECUTABLE, "-x" }, - { S_EXECUTABLE, "--executable" } -}; -#define OPTION_NAMES (sizeof(optiontab)/sizeof(optiontab[0])) - - -static int audit_lookup_option(const char *name) -{ - int i; - - for (i = 0; i < OPTION_NAMES; i++) - if (!strcmp(optiontab[i].name, name)) - return optiontab[i].value; - return -1; -} - -static void usage(void) -{ - printf("usage: ausearch [options]\n" - "\t-a,--event <Audit event id>\tsearch based on audit event id\n" - "\t--arch <CPU>\t\t\tsearch based on the CPU architecture\n" - "\t-c,--comm <Comm name>\t\tsearch based on command line name\n" - "\t--checkpoint <checkpoint file>\tsearch from last complete event\n" - "\t--debug\t\t\tWrite malformed events that are skipped to stderr\n" - "\t-e,--exit <Exit code or errno>\tsearch based on syscall exit code\n" - "\t-f,--file <File name>\t\tsearch based on file name\n" - "\t-ga,--gid-all <all Group id>\tsearch based on All group ids\n" - "\t-ge,--gid-effective <effective Group id> search based on Effective\n\t\t\t\t\tgroup id\n" - "\t-gi,--gid <Group Id>\t\tsearch based on group id\n" - "\t-h,--help\t\t\thelp\n" - "\t-hn,--host <Host Name>\t\tsearch based on remote host name\n" - "\t-i,--interpret\t\t\tInterpret results to be human readable\n" - "\t-if,--input <Input File name>\tuse this file instead of current logs\n" - "\t--input-logs\t\t\tUse the logs even if stdin is a pipe\n" - "\t--just-one\t\t\tEmit just one event\n" - "\t-k,--key <key string>\t\tsearch based on key field\n" - "\t-l, --line-buffered\t\tFlush output on every line\n" - "\t-m,--message <Message type>\tsearch based on message type\n" - "\t-n,--node <Node name>\t\tsearch based on machine's name\n" - "\t-o,--object <SE Linux Object context> search based on context of object\n" - "\t-p,--pid <Process id>\t\tsearch based on process id\n" - "\t-pp,--ppid <Parent Process id>\tsearch based on parent process id\n" - "\t-r,--raw\t\t\toutput is completely unformatted\n" - "\t-sc,--syscall <SysCall name>\tsearch based on syscall name or number\n" - "\t-se,--context <SE Linux context> search based on either subject or\n\t\t\t\t\t object\n" - "\t--session <login session id>\tsearch based on login session id\n" - "\t-su,--subject <SE Linux context> search based on context of the Subject\n" - "\t-sv,--success <Success Value>\tsearch based on syscall or event\n\t\t\t\t\tsuccess value\n" - "\t-te,--end [end date] [end time]\tending date & time for search\n" - "\t-ts,--start [start date] [start time]\tstarting data & time for search\n" - "\t-tm,--terminal <TerMinal>\tsearch based on terminal\n" - "\t-ua,--uid-all <all User id>\tsearch based on All user id's\n" - "\t-ue,--uid-effective <effective User id> search based on Effective\n\t\t\t\t\tuser id\n" - "\t-ui,--uid <User Id>\t\tsearch based on user id\n" - "\t-ul,--loginuid <login id>\tsearch based on the User's Login id\n" - "\t-uu,--uuid <guest UUID>\t\tsearch for events related to the virtual\n" - "\t\t\t\t\tmachine with the given UUID.\n" - "\t-v,--version\t\t\tversion\n" - "\t-vm,--vm-name <guest name>\tsearch for events related to the virtual\n" - "\t\t\t\t\tmachine with the name.\n" - "\t-w,--word\t\t\tstring matches are whole word\n" - "\t-x,--executable <executable name> search based on executable name\n" - ); -} - -static int convert_str_to_msg(const char *optarg) -{ - int tmp, retval = 0; - - if (isdigit(optarg[0])) { - errno = 0; - tmp = strtoul(optarg, NULL, 10); - if (errno) { - fprintf(stderr, - "Numeric message type conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else { - tmp = audit_name_to_msg_type(optarg); - if (tmp < 0) - retval = -1; - } - if (retval == 0) { - if (event_type == NULL) { - event_type = malloc(sizeof(ilist)); - if (event_type == NULL) - return -1; - ilist_create(event_type); - } - ilist_append(event_type, tmp, 1, 0); - } - return retval; -} - -static int parse_msg(const char *optarg) -{ - int retval = 0; - char *saved; - - if (strchr(optarg, ',')) { - char *ptr, *tmp = strdup(optarg); - if (tmp == NULL) - return -1; - ptr = strtok_r(tmp, ",", &saved); - while (ptr) { - retval = convert_str_to_msg(ptr); - if (retval != 0) - break; - ptr = strtok_r(NULL, ",", &saved); - } - free(tmp); - return retval; - } - - return convert_str_to_msg(optarg); -} - -/* - * This function examines the commandline parameters and sets various - * search options. It returns a 0 on success and < 0 on failure - */ -int check_params(int count, char *vars[]) -{ - int c = 1; - int retval = 0; - const char *optarg; - - if (count < 2) { - usage(); - return -1; - } - while (c < count && retval == 0) { - // Go ahead and point to the next argument - if (c+1 < count) { - if (vars[c+1][0] != '-') - optarg = vars[c+1]; - else - optarg = NULL; - } else - optarg = NULL; - - switch (audit_lookup_option(vars[c])) { - case S_EVENT: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_id = strtoul(optarg, NULL, 10); - if (errno) { - fprintf(stderr, - "Illegal value for audit event ID"); - retval = -1; - } - c++; - } else { - fprintf(stderr, - "Audit event id must be a numeric value, was %s\n", - optarg); - retval = -1; - } - break; - case S_COMM: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } else { - event_comm = strdup(optarg); - if (event_comm == NULL) - retval = -1; - c++; - } - break; - case S_FILENAME: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - event_filename = strdup(optarg); - if (event_filename == NULL) - retval = -1; - c++; - } - break; - case S_KEY: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - event_key = strdup(optarg); - if (event_key == NULL) - retval = -1; - c++; - } - break; - case S_ALL_GID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_gid = strtoul(optarg,NULL,10); - if (errno) { - fprintf(stderr, - "Numeric group ID conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else { - struct group *gr ; - - gr = getgrnam(optarg) ; - if (gr == NULL) { - fprintf(stderr, - "Group ID is non-numeric and unknown (%s)\n", - optarg); - retval = -1; - break; - } - event_gid = gr->gr_gid; - } - event_egid = event_gid; - event_ga = 1; - c++; - break; - case S_EFF_GID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_egid = strtoul(optarg,NULL,10); - if (errno) { - fprintf(stderr, - "Numeric group ID conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else { - struct group *gr ; - - gr = getgrnam(optarg) ; - if (gr == NULL) { - fprintf(stderr, - "Effective group ID is non-numeric and unknown (%s)\n", - optarg); - retval = -1; - break; - } - event_egid = gr->gr_gid; - } - c++; - break; - case S_GID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_gid = strtoul(optarg,NULL,10); - if (errno) { - fprintf(stderr, - "Numeric group ID conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else { - struct group *gr ; - - gr = getgrnam(optarg) ; - if (gr == NULL) { - fprintf(stderr, - "Group ID is non-numeric and unknown (%s)\n", - optarg); - retval = -1; - break; - } - event_gid = gr->gr_gid; - } - c++; - break; - case S_HELP: - usage(); - exit(0); - break; - case S_HOSTNAME: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - event_hostname = strdup(optarg); - if (event_hostname == NULL) - retval = -1; - c++; - } - break; - case S_INTERP: - if (report_format == RPT_DEFAULT) - report_format = RPT_INTERP; - else { - fprintf(stderr, - "Conflicting output format %s\n", - vars[c]); - retval = -1; - } - if (optarg) { - fprintf(stderr, - "Argument is NOT required for %s\n", - vars[c]); - retval = -1; - } - break; - case S_INFILE: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - user_file = strdup(optarg); - if (user_file == NULL) - retval = -1; - c++; - } - break; - case S_MESSAGE_TYPE: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - if (strcasecmp(optarg, "ALL") != 0) { - retval = parse_msg(optarg); - } - c++; - } - if (retval < 0) { - int i; - fprintf(stderr, - "Valid message types are: ALL "); - for (i=AUDIT_USER;i<=AUDIT_LAST_VIRT_MSG;i++){ - const char *name; - if (i == AUDIT_WATCH_INS) // Skip a few - i = AUDIT_FIRST_USER_MSG; - name = audit_msg_type_to_name(i); - if (name) - fprintf(stderr, "%s ", name); - } - fprintf(stderr, "\n"); - } - break; - case S_OBJECT: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } else { - event_object = strdup(optarg); - if (event_object == NULL) - retval = -1; - c++; - } - break; - case S_PPID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_ppid = strtol(optarg,NULL,10); - if (errno) - retval = -1; - c++; - } else { - fprintf(stderr, - "Parent process id must be a numeric value, was %s\n", - optarg); - retval = -1; - } - break; - case S_PID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_pid = strtol(optarg,NULL,10); - if (errno) - retval = -1; - c++; - } else { - fprintf(stderr, - "Process id must be a numeric value, was %s\n", - optarg); - retval = -1; - } - break; - case S_RAW: - if (report_format == RPT_DEFAULT) - report_format = RPT_RAW; - else { - fprintf(stderr, - "Conflicting output format --raw\n"); - retval = -1; - } - if (optarg) { - fprintf(stderr, - "Argument is NOT required for --raw\n"); - retval = -1; - } - break; - case S_NODE: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - snode sn; - c++; - - if (!event_node_list) { - event_node_list = malloc(sizeof (slist)); - if (!event_node_list) { - retval = -1; - break; - } - slist_create(event_node_list); - } - - sn.str = strdup(optarg); - sn.key = NULL; - sn.hits=0; - slist_append(event_node_list, &sn); - } - break; - case S_SYSCALL: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_syscall = (int)strtoul(optarg, NULL, 10); - if (errno) { - fprintf(stderr, - "Syscall numeric conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else { - if (event_machine == -1) { - int machine; - machine = audit_detect_machine(); - if (machine < 0) { - fprintf(stderr, - "Error detecting machine type"); - retval = -1; - break; - } - event_machine = machine; - } - event_syscall = audit_name_to_syscall(optarg, - event_machine); - if (event_syscall == -1) { - fprintf(stderr, - "Syscall %s not found\n", - optarg); - retval = -1; - } - } - c++; - break; - case S_CONTEXT: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } else { - event_subject = strdup(optarg); - if (event_subject == NULL) - retval = -1; - event_object = strdup(optarg); - if (event_object == NULL) - retval = -1; - event_se = 1; - c++; - } - break; - case S_SUBJECT: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } else { - event_subject = strdup(optarg); - if (event_subject == NULL) - retval = -1; - c++; - } - break; - case S_OSUCCESS: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if ( (strstr(optarg, "yes")!=NULL) || - (strstr(optarg, "no")!=NULL) ) { - if (strcmp(optarg, "yes") == 0) - event_success = S_SUCCESS; - else - event_success = S_FAILED; - } else { - fprintf(stderr, - "Success must be 'yes' or 'no'.\n"); - retval = -1; - } - c++; - break; - case S_SESSION: - if (!optarg) { - if ((c+1 < count) && vars[c+1]) - optarg = vars[c+1]; - else { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - } - { - size_t len = strlen(optarg); - if (isdigit(optarg[0])) { - errno = 0; - event_session_id = strtoul(optarg,NULL,10); - if (errno) - retval = -1; - c++; - } else if (len >= 2 && *(optarg)=='-' && - (isdigit(optarg[1]))) { - errno = 0; - event_session_id = strtoul(optarg, NULL, 0); - if (errno) { - retval = -1; - fprintf(stderr, "Error converting %s\n", - optarg); - } - c++; - } else { - fprintf(stderr, - "Session id must be a numeric value, was %s\n", - optarg); - retval = -1; - } - } - break; - case S_EXIT: - if (!optarg) { - if ((c+1 < count) && vars[c+1]) - optarg = vars[c+1]; - else { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - } - { - size_t len = strlen(optarg); - if (isdigit(optarg[0])) { - errno = 0; - event_exit = strtoll(optarg, NULL, 0); - if (errno) { - retval = -1; - fprintf(stderr, "Error converting %s\n", - optarg); - } - } else if (len >= 2 && *(optarg)=='-' && - (isdigit(optarg[1]))) { - errno = 0; - event_exit = strtoll(optarg, NULL, 0); - if (errno) { - retval = -1; - fprintf(stderr, "Error converting %s\n", - optarg); - } - } else { - event_exit = audit_name_to_errno(optarg); - if (event_exit == 0) { - retval = -1; - fprintf(stderr, - "Unknown errno, was %s\n", - optarg); - } - } - c++; - if (retval != -1) - event_exit_is_set = 1; - } - break; - case S_TIME_END: - if (optarg) { - if ( (c+2 < count) && vars[c+2] && - (vars[c+2][0] != '-') ) { - /* Have both date and time - check order*/ - if (strchr(optarg, ':')) { - if (ausearch_time_end(vars[c+2], - optarg) != 0) - retval = -1; - } else { - if (ausearch_time_end(optarg, - vars[c+2]) != 0) - retval = -1; - } - c++; - } else { - // Check against recognized words - int t = lookup_time(optarg); - if (t >= 0) { - if (ausearch_time_end(optarg, - NULL) != 0) - retval = -1; - } else if ( (strchr(optarg, ':')) == NULL) { - /* Only have date */ - if (ausearch_time_end(optarg, - NULL) != 0) - retval = -1; - } else { - /* Only have time */ - if (ausearch_time_end(NULL, - optarg) != 0) - retval = -1; - } - } - c++; - break; - } - fprintf(stderr, - "%s requires either date and/or time\n", - vars[c]); - retval = -1; - break; - case S_TIME_START: - if (optarg) { - if ( (c+2 < count) && vars[c+2] && - (vars[c+2][0] != '-') ) { - /* Have both date and time - check order */ - if (strchr(optarg, ':')) { - if (ausearch_time_start( - vars[c+2], optarg) != 0) - retval = -1; - } else { - if (ausearch_time_start(optarg, - vars[c+2]) != 0) - retval = -1; - } - c++; - } else { - // Check against recognized words - int t = lookup_time(optarg); - if (t >= 0) { - if (ausearch_time_start(optarg, - "00:00:00") != 0) - retval = -1; - } else if (strcmp(optarg, - "checkpoint") == 0) { - // Only use the timestamp from within - // the checkpoint file - checkpt_timeonly++; - } else if (strchr(optarg, ':') == NULL){ - /* Only have date */ - if (ausearch_time_start(optarg, - "00:00:00") != 0) - retval = -1; - } else { - /* Only have time */ - if (ausearch_time_start(NULL, - optarg) != 0) - retval = -1; - } - } - c++; - break; - } - fprintf(stderr, - "%s requires either date and/or time\n", - vars[c]); - retval = -1; - break; - case S_TERMINAL: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - event_terminal = strdup(optarg); - if (event_terminal == NULL) - retval = -1; - c++; - } - break; - case S_UID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_uid = strtoul(optarg,NULL,10); - if (errno) { - fprintf(stderr, - "Numeric user ID conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else { - struct passwd *pw; - - pw = getpwnam(optarg); - if (pw == NULL) { - fprintf(stderr, - "Effective user ID is non-numeric and unknown (%s)\n", - optarg); - retval = -1; - break; - } - event_uid = pw->pw_uid; - } - c++; - break; - case S_EFF_UID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_euid = strtoul(optarg,NULL,10); - if (errno) { - fprintf(stderr, - "Numeric user ID conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else { - struct passwd *pw ; - - pw = getpwnam(optarg) ; - if (pw == NULL) { - fprintf(stderr, - "User ID is non-numeric and unknown (%s)\n", - optarg); - retval = -1; - break; - } - event_euid = pw->pw_uid; - } - c++; - break; - case S_ALL_UID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (isdigit(optarg[0])) { - errno = 0; - event_uid = strtoul(optarg,NULL,10); - if (errno) { - fprintf(stderr, - "Numeric user ID conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else { - struct passwd *pw ; - - pw = getpwnam(optarg) ; - if (pw == NULL) { - fprintf(stderr, - "User ID is non-numeric and unknown (%s)\n", - optarg); - retval = -1; - break; - } - event_uid = pw->pw_uid; - } - event_ua = 1; - event_euid = event_uid; - event_loginuid = event_uid; - c++; - break; - case S_LOGINID: - if (!optarg) { - if ((c+1 < count) && vars[c+1]) - optarg = vars[c+1]; - else { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - } - { - size_t len = strlen(optarg); - if (isdigit(optarg[0])) { - errno = 0; - event_loginuid = strtoul(optarg,NULL,10); - if (errno) { - fprintf(stderr, - "Numeric user ID conversion error (%s) for %s\n", - strerror(errno), optarg); - retval = -1; - } - } else if (len >= 2 && *(optarg)=='-' && - (isdigit(optarg[1]))) { - errno = 0; - event_loginuid = strtol(optarg, NULL, 0); - if (errno) { - retval = -1; - fprintf(stderr, "Error converting %s\n", - optarg); - } - } else { - struct passwd *pw ; - - pw = getpwnam(optarg) ; - if (pw == NULL) { - fprintf(stderr, - "Login user ID is non-numeric and unknown (%s)\n", - optarg); - retval = -1; - break; - } - event_loginuid = pw->pw_uid; - } - } - c++; - break; - case S_UUID: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - event_uuid = strdup(optarg); - if (event_uuid == NULL) { - retval = -1; - } - c++; - } - break; - case S_VMNAME: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - event_vmname= strdup(optarg); - if (event_vmname == NULL) { - retval = -1; - } - c++; - } - break; - case S_VERSION: - printf("ausearch version %s\n", VERSION); - exit(0); - break; - case S_EXACT_MATCH: - event_exact_match=1; - break; - case S_IN_LOGS: - force_logs = 1; - break; - case S_JUST_ONE: - just_one = 1; - break; - case S_EXECUTABLE: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - event_exe = strdup(optarg); - if (event_exe == NULL) - retval = -1; - c++; - } - break; - case S_LINEBUFFERED: - line_buffered = 1; - break; - case S_DEBUG: - event_debug = 1; - break; - case S_CHECKPOINT: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - } else { - checkpt_filename = strdup(optarg); - if (checkpt_filename == NULL) - retval = -1; - c++; - } - break; - case S_ARCH: - if (!optarg) { - fprintf(stderr, - "Argument is required for %s\n", - vars[c]); - retval = -1; - break; - } - if (event_machine != -1) { - if (event_syscall != -1) - fprintf(stderr, - "Arch needs to be defined before the syscall\n"); - else - fprintf(stderr, - "Arch is already defined\n"); - retval = -1; - break; - } else { - int machine = audit_determine_machine(optarg); - if (machine < 0) { - fprintf(stderr, "Unknown arch %s\n", - optarg); - retval = -1; - } - event_machine = machine; - } - c++; - break; - default: - fprintf(stderr, "%s is an unsupported option\n", - vars[c]); - retval = -1; - break; - } - c++; - } - - return retval; -} - diff --git a/framework/src/audit/src/ausearch-options.h b/framework/src/audit/src/ausearch-options.h deleted file mode 100644 index 1372762b..00000000 --- a/framework/src/audit/src/ausearch-options.h +++ /dev/null @@ -1,52 +0,0 @@ -/* ausearch-options.h -- - * Copyright 2005,2008,2010 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - * - */ - -#ifndef AUSEARCH_OPTIONS_H -#define AUSEARCH_OPTIONS_H - -#include <time.h> -#include <sys/types.h> -#include <stdint.h> -#include "ausearch-common.h" -#include "ausearch-int.h" - -/* Global variables that describe what search is to be performed */ -extern const char *event_key; -extern const char *event_subject; -extern const char *event_object; -extern int event_se; -extern int just_one; -extern int line_buffered; -extern int event_debug; -extern pid_t event_ppid; -extern uint32_t event_session_id; -extern ilist *event_type; - -/* Data type to govern output format */ -extern report_t report_format; - -/* Function to process commandline options */ -extern int check_params(int count, char *vars[]); - -#endif - diff --git a/framework/src/audit/src/ausearch-parse.c b/framework/src/audit/src/ausearch-parse.c deleted file mode 100644 index 1fb1c151..00000000 --- a/framework/src/audit/src/ausearch-parse.c +++ /dev/null @@ -1,2310 +0,0 @@ -/* -* ausearch-parse.c - Extract interesting fields and check for match -* Copyright (c) 2005-08,2011,2013-14 Red Hat Inc., Durham, North Carolina. -* Copyright (c) 2011 IBM Corp. -* 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> -* Marcelo Henrique Cerri <mhcerri@br.ibm.com> -*/ - -#include "config.h" -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <netdb.h> -#include <limits.h> /* PATH_MAX */ -#include <ctype.h> -#include "libaudit.h" -#include "ausearch-options.h" -#include "ausearch-lookup.h" -#include "ausearch-parse.h" - -#define NAME_OFFSET 36 -static const char key_sep[2] = { AUDIT_KEY_SEPARATOR, 0 }; - -static int parse_syscall(lnode *n, search_items *s); -static int parse_dir(const lnode *n, search_items *s); -static int common_path_parser(search_items *s, char *path); -static int avc_parse_path(const lnode *n, search_items *s); -static int parse_path(const lnode *n, search_items *s); -static int parse_user(const lnode *n, search_items *s); -static int parse_obj(const lnode *n, search_items *s); -static int parse_login(const lnode *n, search_items *s); -static int parse_daemon1(const lnode *n, search_items *s); -static int parse_daemon2(const lnode *n, search_items *s); -static int parse_sockaddr(const lnode *n, search_items *s); -static int parse_avc(const lnode *n, search_items *s); -static int parse_integrity(const lnode *n, search_items *s); -static int parse_kernel_anom(const lnode *n, search_items *s); -static int parse_simple_message(const lnode *n, search_items *s); -static int parse_tty(const lnode *n, search_items *s); -static int parse_pkt(const lnode *n, search_items *s); - - -static int audit_avc_init(search_items *s) -{ - if (s->avc == NULL) { - //create - s->avc = malloc(sizeof(alist)); - if (s->avc == NULL) - return -1; - alist_create(s->avc); - } - return 0; -} - -/* - * This function will take the list and extract the searchable fields from it. - * It returns 0 on success and 1 on failure. - */ -int extract_search_items(llist *l) -{ - int ret = 0; - lnode *n; - search_items *s = &l->s; - list_first(l); - n = list_get_cur(l); - if (n) { - do { - switch (n->type) { - case AUDIT_SYSCALL: - ret = parse_syscall(n, s); - break; - case AUDIT_CWD: - ret = parse_dir(n, s); - break; - case AUDIT_AVC_PATH: - ret = avc_parse_path(n, s); - break; - case AUDIT_PATH: - ret = parse_path(n, s); - break; - case AUDIT_USER: - case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: - case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2: - ret = parse_user(n, s); - break; - case AUDIT_SOCKADDR: - ret = parse_sockaddr(n, s); - break; - case AUDIT_LOGIN: - ret = parse_login(n, s); - break; - case AUDIT_IPC: - case AUDIT_OBJ_PID: - ret = parse_obj(n, s); - break; - case AUDIT_DAEMON_START: - case AUDIT_DAEMON_END: - case AUDIT_DAEMON_ABORT: - case AUDIT_DAEMON_CONFIG: - case AUDIT_DAEMON_ROTATE: - case AUDIT_DAEMON_RESUME: - ret = parse_daemon1(n, s); - break; - case AUDIT_DAEMON_ACCEPT: - case AUDIT_DAEMON_CLOSE: - ret = parse_daemon2(n, s); - break; - case AUDIT_CONFIG_CHANGE: - ret = parse_simple_message(n, s); - // We use AVC parser because it just looks for - // the one field. We don't care about return - // code since older events don't have path= - avc_parse_path(n, s); - break; - case AUDIT_AVC: - ret = parse_avc(n, s); - break; - case AUDIT_NETFILTER_PKT: - ret = parse_pkt(n, s); - break; - case AUDIT_SECCOMP: - case - AUDIT_FIRST_KERN_ANOM_MSG...AUDIT_LAST_KERN_ANOM_MSG: - ret = parse_kernel_anom(n, s); - break; - case AUDIT_MAC_POLICY_LOAD...AUDIT_MAC_UNLBL_STCDEL: - ret = parse_simple_message(n, s); - break; - case AUDIT_INTEGRITY_DATA...AUDIT_INTEGRITY_RULE: - ret = parse_integrity(n, s); - break; - case AUDIT_KERNEL: - case AUDIT_SELINUX_ERR: - case AUDIT_EXECVE: - case AUDIT_IPC_SET_PERM: - case AUDIT_MQ_OPEN: - case AUDIT_MQ_SENDRECV: - case AUDIT_MQ_NOTIFY: - case AUDIT_MQ_GETSETATTR: - case AUDIT_FD_PAIR: - case AUDIT_BPRM_FCAPS: - case AUDIT_CAPSET: - case AUDIT_MMAP: - case AUDIT_NETFILTER_CFG: - // Nothing to parse - break; - case AUDIT_TTY: - ret = parse_tty(n, s); - break; - default: - if (event_debug) - fprintf(stderr, - "Unparsed type:%d\n - skipped", - n->type); - break; - } - if (event_debug && ret) - fprintf(stderr, - "Malformed event skipped, rc=%d. %s\n", - ret, n->message); - } while ((n=list_next(l)) && ret == 0); - } - return ret; -} - -static int parse_syscall(lnode *n, search_items *s) -{ - char *ptr, *str, *term; - extern int event_machine; - - term = n->message; - if (report_format > RPT_DEFAULT || event_machine != -1) { - // get arch - str = strstr(term, "arch="); - if (str == NULL) - return 1; - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 2; - *term = 0; - errno = 0; - s->arch = (int)strtoul(ptr, NULL, 16); - if (errno) - return 3; - *term = ' '; - } - // get syscall - str = strstr(term, "syscall="); - if (str == NULL) - return 4; - ptr = str + 8; - term = strchr(ptr, ' '); - if (term == NULL) - return 5; - *term = 0; - errno = 0; - s->syscall = (int)strtoul(ptr, NULL, 10); - if (errno) - return 6; - *term = ' '; - // get success - if (event_success != S_UNSET) { - str = strstr(term, "success="); - if (str) { // exit_group does not set success !?! - ptr = str + 8; - term = strchr(ptr, ' '); - if (term == NULL) - return 7; - *term = 0; - if (strcmp(ptr, "yes") == 0) - s->success = S_SUCCESS; - else - s->success = S_FAILED; - *term = ' '; - } - } - // get exit - if (event_exit_is_set) { - str = strstr(term, "exit="); - if (str == NULL) - return 8; - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 9; - *term = 0; - errno = 0; - s->exit = strtoll(ptr, NULL, 0); - if (errno) - return 10; - s->exit_is_set = 1; - *term = ' '; - } - // get a0 - str = strstr(term, "a0="); - if (str == NULL) - return 11; - ptr = str + 3; - term = strchr(ptr, ' '); - if (term == NULL) - return 12; - *term = 0; - errno = 0; - // 64 bit dump on 32 bit machine looks bad here - need long long - n->a0 = strtoull(ptr, NULL, 16); // Hex - if (errno) - return 13; - *term = ' '; - // get a1 - str = strstr(term, "a1="); - if (str == NULL) - return 11; - ptr = str + 3; - term = strchr(ptr, ' '); - if (term == NULL) - return 12; - *term = 0; - errno = 0; - // 64 bit dump on 32 bit machine looks bad here - need long long - n->a1 = strtoull(ptr, NULL, 16); // Hex - if (errno) - return 13; - *term = ' '; - // ppid - if (event_ppid != -1) { - str = strstr(term, "ppid="); - if (str != NULL) { // ppid is an optional field - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 14; - *term = 0; - errno = 0; - s->ppid = strtoul(ptr, NULL, 10); - if (errno) - return 15; - *term = ' '; - } - } - // pid - if (event_pid != -1) { - str = strstr(term, " pid="); - if (str == NULL) - return 16; - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 17; - *term = 0; - errno = 0; - s->pid = strtoul(ptr, NULL, 10); - if (errno) - return 18; - *term = ' '; - } - // optionally get loginuid - if (event_loginuid != -2) { - str = strstr(term, "auid="); - if (str == NULL) { - str = strstr(term, "loginuid="); - if (str == NULL) - return 19; - ptr = str + 9; - } else - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 20; - *term = 0; - errno = 0; - s->loginuid = strtoul(ptr, NULL, 10); - if (errno) - return 21; - *term = ' '; - } - // optionally get uid - if (event_uid != -1) { - str = strstr(term, "uid="); - if (str == NULL) - return 22; - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 23; - *term = 0; - errno = 0; - s->uid = strtoul(ptr, NULL, 10); - if (errno) - return 24; - *term = ' '; - } - - // optionally get gid - if (event_gid != -1) { - str = strstr(term, "gid="); - if (str == NULL) - return 25; - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 26; - *term = 0; - errno = 0; - s->gid = strtoul(ptr, NULL, 10); - if (errno) - return 27; - *term = ' '; - } - - // euid - if (event_euid != -1) { - str = strstr(term, "euid="); - if (str == NULL) - return 28; - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 29; - *term = 0; - errno = 0; - s->euid = strtoul(ptr, NULL, 10); - if (errno) - return 30; - *term = ' '; - } - - // egid - if (event_egid != -1) { - str = strstr(term, "egid="); - if (str == NULL) - return 31; - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 32; - *term = 0; - errno = 0; - s->egid = strtoul(ptr, NULL, 10); - if (errno) - return 33; - *term = ' '; - } - - if (event_terminal) { - // dont do this search unless needed - str = strstr(term, "tty="); - if (str) { - str += 4; - term = strchr(str, ' '); - if (term == NULL) - return 34; - *term = 0; - s->terminal = strdup(str); - *term = ' '; - } - } - // ses - if (event_session_id != -2 ) { - str = strstr(term, "ses="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 35; - *term = 0; - errno = 0; - s->session_id = strtoul(ptr, NULL, 10); - if (errno) - return 36; - *term = ' '; - } - } - if (event_comm) { - // dont do this search unless needed - str = strstr(term, "comm="); - if (str) { - /* Make the syscall one override */ - if (s->comm) - free(s->comm); - str += 5; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 37; - *term = 0; - s->comm = strdup(str); - *term = '"'; - } else - s->comm = unescape(str); - } else - return 38; - } - if (event_exe) { - // dont do this search unless needed - str = strstr(n->message, "exe="); - if (str) { - str += 4; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 39; - *term = 0; - s->exe = strdup(str); - *term = '"'; - } else - s->exe = unescape(str); - } else - return 40; - } - if (event_subject) { - // scontext - str = strstr(term, "subj="); - if (str != NULL) { - str += 5; - term = strchr(str, ' '); - if (term == NULL) - return 41; - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - *term = ' '; - } else - return 42; - } - } - if (event_key) { - str = strstr(term, "key="); - if (str) { - if (!s->key) { - //create - s->key = malloc(sizeof(slist)); - if (s->key == NULL) - return 43; - slist_create(s->key); - } - str += 4; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 44; - *term = 0; - if (s->key) { - // append - snode sn; - sn.str = strdup(str); - sn.key = NULL; - sn.hits = 1; - slist_append(s->key, &sn); - } - *term = '"'; - } else { - if (s->key) { - char *saved; - char *keyptr = unescape(str); - char *kptr = strtok_r(keyptr, - key_sep, &saved); - while (kptr) { - snode sn; - // append - sn.str = strdup(kptr); - sn.key = NULL; - sn.hits = 1; - slist_append(s->key, &sn); - kptr = strtok_r(NULL, - key_sep, &saved); - } - free(keyptr); - - } - } - } - } - return 0; -} - -static int parse_dir(const lnode *n, search_items *s) -{ - char *str, *term; - - if (event_filename) { - // dont do this search unless needed - str = strstr(n->message+NAME_OFFSET, " cwd="); - if (str) { - str += 5; - if (*str == '"') { - /* string is normal */ - str++; - term = strchr(str, '"'); - if (term == NULL) - return 1; - *term = 0; - if (!s->cwd) - s->cwd = strdup(str); - *term = '"'; - } else if (!s->cwd) - s->cwd = unescape(str); - } - } - return 0; -} - -static int common_path_parser(search_items *s, char *path) -{ - char *term; - - if (!s->filename) { - //create - s->filename = malloc(sizeof(slist)); - if (s->filename == NULL) - return 1; - slist_create(s->filename); - } - if (*path == '"') { - /* string is normal */ - path++; - term = strchr(path, '"'); - if (term == NULL) - return 2; - *term = 0; - if (s->filename) { - // append - snode sn; - sn.str = strdup(path); - sn.key = NULL; - sn.hits = 1; - // Attempt to rebuild path if relative - if ((sn.str[0] == '.') && ((sn.str[1] == '.') || - (sn.str[1] == '/')) && s->cwd) { - char *tmp = malloc(PATH_MAX); - if (tmp == NULL) { - free(sn.str); - return 3; - } - snprintf(tmp, PATH_MAX, - "%s/%s", s->cwd, sn.str); - free(sn.str); - sn.str = tmp; - } - slist_append(s->filename, &sn); - } - *term = '"'; - } else { - if (s->filename) { - // append - snode sn; - sn.key = NULL; - sn.hits = 1; - if (strncmp(path, "(null)", 6) == 0) { - sn.str = strdup("(null)"); - goto append; - } - if (!isxdigit(path[0])) - return 4; - if (path[0] == '0' && path[1] == '0') - sn.str = unescape(&path[2]); // Abstract name - else { - term = strchr(path, ' '); - if (term == NULL) - return 5; - *term = 0; - sn.str = unescape(path); - *term = ' '; - } - // Attempt to rebuild path if relative - if ((sn.str[0] == '.') && ((sn.str[1] == '.') || - (sn.str[1] == '/')) && s->cwd) { - char *tmp = malloc(PATH_MAX); - if (tmp == NULL) - return 6; - snprintf(tmp, PATH_MAX, "%s/%s", - s->cwd, sn.str); - free(sn.str); - sn.str = tmp; - } -append: - slist_append(s->filename, &sn); - } - } - return 0; -} - -/* Older AVCs have path separate from the AVC record */ -static int avc_parse_path(const lnode *n, search_items *s) -{ - char *str; - - if (event_filename) { - // dont do this search unless needed - str = strstr(n->message, " path="); - if (str) { - str += 6; - return common_path_parser(s, str); - } - return 1; - } - return 0; -} - -static int parse_path(const lnode *n, search_items *s) -{ - // We add 32 to message because we do not nee to look at - // anything before that. Its only time and type. - char *str, *term = n->message+NAME_OFFSET; - - if (event_filename) { - // dont do this search unless needed - str = strstr(term, " name="); - if (str) { - int rc; - str += 6; - rc = common_path_parser(s, str); - if (rc) - return rc; - } - } - if (event_object) { - // tcontext - str = strstr(term, "obj="); - if (str != NULL) { - str += 4; - term = strchr(str, ' '); - if (term) - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.tcontext = strdup(str); - alist_append(s->avc, &an); - if (term) - *term = ' '; - } else - return 7; - } - } - return 0; -} - -static int parse_obj(const lnode *n, search_items *s) -{ - char *str, *term; - - term = n->message; - if (event_object) { - // obj context - str = strstr(term, "obj="); - if (str != NULL) { - str += 4; - term = strchr(str, ' '); - if (term) - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.tcontext = strdup(str); - alist_append(s->avc, &an); - if (term) - *term = ' '; - } else - return 1; - } - } - return 0; -} - -static int parse_user(const lnode *n, search_items *s) -{ - char *ptr, *str, *term, saved, *mptr; - - term = n->message; - - // get pid - if (event_pid != -1) { - str = strstr(term, "pid="); - if (str == NULL) - return 1; - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 2; - *term = 0; - errno = 0; - s->pid = strtoul(ptr, NULL, 10); - if (errno) - return 3; - *term = ' '; - } - // optionally get uid - if (event_uid != -1) { - str = strstr(term, "uid="); - if (str == NULL) - return 4; - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 5; - *term = 0; - errno = 0; - s->uid = strtoul(ptr, NULL, 10); - if (errno) - return 6; - *term = ' '; - } - // optionally get loginuid - if (event_loginuid != -2) { - *term = ' '; - str = strstr(term, "auid="); - if (str == NULL) { // Try the older one - str = strstr(term, "loginuid="); - if (str == NULL) - return 7; - ptr = str + 9; - } else - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 8; - *term = 0; - errno = 0; - s->loginuid = strtoul(ptr, NULL, 10); - if (errno) - return 9; - *term = ' '; - } - // ses - if (event_session_id != -2 ) { - str = strstr(term, "ses="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 10; - *term = 0; - errno = 0; - s->session_id = strtoul(ptr, NULL, 10); - if (errno) - return 11; - *term = ' '; - } - } - if (event_subject) { - // scontext - str = strstr(term, "subj="); - if (str != NULL) { - str += 5; - term = strchr(str, ' '); - if (term == NULL) - return 12; - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - *term = ' '; - } else - return 13; - } - } - // optionally get gid - if (event_gid != -1) { - if (n->type == AUDIT_ADD_GROUP || n->type == AUDIT_DEL_GROUP || - n->type == AUDIT_GRP_MGMT) { - str = strstr(term, " id="); - // Take second shot in the case of MGMT events - if (str == NULL && n->type == AUDIT_GRP_MGMT) - str = strstr(term, "gid="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 31; - *term = 0; - errno = 0; - s->gid = strtoul(ptr, NULL, 10); - if (errno) - return 32; - *term = ' '; - } - } - } - if (event_vmname) { - str = strstr(term, "vm="); - if (str) { - str += 3; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 23; - *term = 0; - s->vmname = strdup(str); - *term = '"'; - } else - s->vmname = unescape(str); - } - } - if (event_uuid) { - str = strstr(term, "uuid="); - if (str) { - str += 5; - term = str; - while (*term != ' ' && *term != ':') - term++; - if (term == str) - return 24; - saved = *term; - *term = 0; - s->uuid = strdup(str); - *term = saved; - } - } - if (event_subject) { - str = strstr(term, "vm-ctx="); - if (str != NULL) { - str += 7; - term = strchr(str, ' '); - if (term == NULL) - return 27; - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - *term = ' '; - } else - return 28; - } - } - if (event_object) { - str = strstr(term, "img-ctx="); - if (str != NULL) { - str += 8; - term = strchr(str, ' '); - if (term == NULL) - return 29; - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.tcontext = strdup(str); - alist_append(s->avc, &an); - *term = ' '; - } else - return 30; - } - } - // optionally get uid - some records the second uid is what we want. - // USER_LOGIN for example. - if (event_uid != -1) { - str = strstr(term, "uid="); - if (str) { - if (*(str - 1) == 'a' || *(str - 1) == 's' || - *(str - 1) == 'u') - goto skip; - if (!(*(str - 1) == '\'' || *(str - 1) == ' ')) - return 25; - ptr = str + 4; - term = ptr; - while (isdigit(*term)) - term++; - if (term == ptr) - return 14; - - saved = *term; - *term = 0; - errno = 0; - s->uid = strtoul(ptr, NULL, 10); - if (errno) - return 15; - *term = saved; - } - } -skip: - mptr = term + 1; - - if (event_comm) { - // dont do this search unless needed - str = strstr(mptr, "comm="); - if (str) { - str += 5; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 16; - *term = 0; - s->comm = strdup(str); - *term = '"'; - } else - s->comm = unescape(str); - } - } - - // Get acct for user/group add/del - str = strstr(mptr, "acct="); - if (str != NULL) { - ptr = str + 5; - term = ptr + 1; - if (*ptr == '"') { - while (*term != '"') - term++; - saved = *term; - *term = 0; - ptr++; - s->acct = strdup(ptr); - *term = saved; - } else { - /* Handle legacy accts */ - char *end = ptr; - int legacy = 0; - - while (*end != ' ') { - if (!isxdigit(*end)) - legacy = 1; - end++; - } - term = end; - if (!legacy) - s->acct = unescape(ptr); - else { - saved = *term; - *term = 0; - s->acct = strdup(ptr); - *term = saved; - } - } - } - mptr = term + 1; - - // get hostname - if (event_hostname) { - // dont do this search unless needed - str = strstr(mptr, "hostname="); - if (str) { - str += 9; - term = strchr(str, ','); - if (term == NULL) { - term = strchr(str, ' '); - if (term == NULL) - return 17; - } - saved = *term; - *term = 0; - s->hostname = strdup(str); - *term = saved; - - // Lets see if there is something more - // meaningful in addr - if (strcmp(s->hostname, "?") == 0) { - term++; - str = strstr(term, "addr="); - if (str) { - str += 5; - term = strchr(str, ','); - if (term == NULL) { - term = strchr(str, ' '); - if (term == NULL) - return 18; - } - saved = *term; - *term = 0; - free(s->hostname); - s->hostname = strdup(str); - *term = saved; - } - } - } - } - if (event_filename) { - // dont do this search unless needed - str = strstr(mptr, "cwd="); - if (str) { - str += 4; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 20; - *term = 0; - s->cwd = strdup(str); - *term = '"'; - } else { - char *end = str; - int legacy = 0; - - while (*end != ' ') { - if (!isxdigit(*end)) { - legacy = 1; - } - end++; - } - term = end; - if (!legacy) - s->cwd = unescape(str); - else { - saved = *term; - *term = 0; - s->cwd = strdup(str); - *term = saved; - } - } - } - } - if (event_terminal) { - // dont do this search unless needed - str = strstr(mptr, "terminal="); - if (str) { - str += 9; - term = strchr(str, ' '); - if (term == NULL) { - term = strchr(str, ')'); - if (term == NULL) - return 19; - } - *term = 0; - s->terminal = strdup(str); - *term = ' '; - } - } - if (event_exe) { - // dont do this search unless needed - str = strstr(mptr, "exe="); - if (str) { - str += 4; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 26; - *term = 0; - s->exe = strdup(str); - *term = '"'; - } else { - char *end = str; - int legacy = 0; - - while (*end != ' ') { - if (!isxdigit(*end)) { - legacy = 1; - } - end++; - } - term = end; - if (!legacy) - s->exe = unescape(str); - else { - saved = *term; - *term = 0; - s->exe = strdup(str); - *term = saved; - } - } - } - } - - // get success - if (event_success != S_UNSET) { - str = strstr(mptr, "res="); - if (str) { - ptr = str + 4; - term = strchr(ptr, '\''); - if (term == NULL) - return 21; - *term = 0; - if (strncmp(ptr, "failed", 6) == 0) - s->success = S_FAILED; - else - s->success = S_SUCCESS; - *term = '\''; - } else if ((str = strstr(mptr, "result="))) { - ptr = str + 7; - term = strchr(ptr, ')'); - if (term == NULL) - return 22; - *term = 0; - if (strcasecmp(ptr, "success") == 0) - s->success = S_SUCCESS; - else - s->success = S_FAILED; - *term = ')'; - } - } - /* last return code used = 24 */ - return 0; -} - -static int parse_login(const lnode *n, search_items *s) -{ - char *ptr, *str, *term = n->message; - - // get pid - if (event_pid != -1) { - str = strstr(term, "pid="); - if (str == NULL) - return 1; - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 2; - *term = 0; - errno = 0; - s->pid = strtoul(ptr, NULL, 10); - if (errno) - return 3; - *term = ' '; - } - // optionally get uid - if (event_uid != -1) { - str = strstr(term, "uid="); - if (str == NULL) - return 4; - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 5; - *term = 0; - errno = 0; - s->uid = strtoul(ptr, NULL, 10); - if (errno) - return 6; - *term = ' '; - } - // optionally get subj - if (event_subject) { - str = strstr(term, "subj="); - if (str) { - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 12; - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - *term = ' '; - } else - return 13; - *term = ' '; - } - } - // optionally get loginuid - if (event_loginuid != -2) { - str = strstr(term, "new auid="); - if (str == NULL) { - // 3.14 kernel changed it to the next line - str = strstr(term, " auid="); - if (str == NULL) { - str = strstr(term, "new loginuid="); - if (str == NULL) - return 7; - ptr = str + 13; - } else - ptr = str + 6; - } else - ptr = str + 9; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->loginuid = strtoul(ptr, NULL, 10); - if (errno) - return 8; - if (term) - *term = ' '; - } - - // success - if (event_success != S_UNSET) { - if (term == NULL) - term = n->message; - str = strstr(term, "res="); - if (str != NULL) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->success = strtoul(ptr, NULL, 10); - if (errno) - return 9; - if (term) - *term = ' '; - } else // Assume older kernel where always successful - s->success = S_SUCCESS; - } - // ses - if (event_session_id != -2 ) { - if (term == NULL) - term = n->message; - str = strstr(term, "new ses="); - if (str == NULL) { - // The 3.14 kernel changed it to the next line - str = strstr(term, " ses="); - if (str == NULL) - return 14; - ptr = str + 5; - } - else - ptr = str + 8; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->session_id = strtoul(ptr, NULL, 10); - if (errno) - return 11; - if (term) - *term = ' '; - } - return 0; -} - -static int parse_daemon1(const lnode *n, search_items *s) -{ - char *ptr, *str, *term, saved, *mptr; - - // Not all messages have a ')', use it if its there - mptr = strchr(n->message, ')'); - if (mptr == NULL) - mptr = n->message; - term = mptr; - - // optionally get auid - if (event_loginuid != -2 ) { - str = strstr(mptr, "auid="); - if (str == NULL) - return 1; - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 2; - saved = *term; - *term = 0; - errno = 0; - s->loginuid = strtoul(ptr, NULL, 10); - if (errno) - return 3; - *term = saved; - } - - // pid - if (event_pid != -1) { - str = strstr(term, "pid="); - if (str == NULL) - return 4; - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 5; - saved = *term; - *term = 0; - errno = 0; - s->pid = strtoul(ptr, NULL, 10); - if (errno) - return 6; - *term = saved; - } - - if (event_subject) { - // scontext - str = strstr(term, "subj="); - if (str != NULL) { - str += 5; - term = strchr(str, ' '); - if (term) - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - } else - return 7; - if (term) - *term = ' '; - } - } - - // success - if (event_success != S_UNSET) { - str = strstr(mptr, "res="); - if (str) { - ptr = term = str + 4; - while (isalpha(*term)) - term++; - if (term == ptr) - return 9; - saved = *term; - *term = 0; - if (strncmp(ptr, "failed", 6) == 0) - s->success = S_FAILED; - else - s->success = S_SUCCESS; - *term = saved; - } - } - - return 0; -} - -static int parse_daemon2(const lnode *n, search_items *s) -{ - char *str, saved, *term = n->message; - - if (event_hostname) { - str = strstr(term, "addr="); - if (str) { - str += 5; - term = strchr(str, ':'); - if (term == NULL) { - term = strchr(str, ' '); - if (term == NULL) - return 1; - } - saved = *term; - *term = 0; - free(s->hostname); - s->hostname = strdup(str); - *term = saved; - } - } - - if (event_success != S_UNSET) { - char *str = strstr(term, "res="); - if (str) { - char *ptr, *term, saved; - - ptr = term = str + 4; - while (isalpha(*term)) - term++; - if (term == ptr) - return 2; - saved = *term; - *term = 0; - if (strncmp(ptr, "failed", 6) == 0) - s->success = S_FAILED; - else - s->success = S_SUCCESS; - *term = saved; - } - } - - return 0; -} - -static int parse_sockaddr(const lnode *n, search_items *s) -{ - char *str; - - if (event_hostname || event_filename) { - str = strstr(n->message, "saddr="); - if (str) { - int len; - struct sockaddr *saddr; - char name[NI_MAXHOST]; - - str += 6; - len = strlen(str)/2; - s->hostname = unescape(str); - saddr = (struct sockaddr *)s->hostname; - if (saddr->sa_family == AF_INET) { - if (len < sizeof(struct sockaddr_in)) { - fprintf(stderr, - "sockaddr len too short\n"); - return 1; - } - len = sizeof(struct sockaddr_in); - } else if (saddr->sa_family == AF_INET6) { - if (len < sizeof(struct sockaddr_in6)) { - fprintf(stderr, - "sockaddr6 len too short\n"); - return 2; - } - len = sizeof(struct sockaddr_in6); - } else if (saddr->sa_family == AF_UNIX) { - struct sockaddr_un *un = - (struct sockaddr_un *)saddr; - if (un->sun_path[0]) - len = strlen(un->sun_path); - else // abstract name - len = strlen(&un->sun_path[1]); - if (len == 0) { - fprintf(stderr, - "sun_path len too short\n"); - return 3; - } - if (event_filename) { - if (!s->filename) { - //create - s->filename = - malloc(sizeof(slist)); - if (s->filename == NULL) - return 4; - slist_create(s->filename); - } - if (s->filename) { - // append - snode sn; - sn.str = strdup(un->sun_path); - sn.key = NULL; - sn.hits = 1; - slist_append(s->filename, &sn); - } - free(s->hostname); - s->hostname = NULL; - return 0; - } else { // No file name - no need for socket - free(s->hostname); - s->hostname = NULL; - return 0; - } - } else { - // addr family we don't care about - free(s->hostname); - s->hostname = NULL; - return 0; - } - if (!event_hostname) { - // we entered here for files - discard - free(s->hostname); - s->hostname = NULL; - return 0; - } - if (getnameinfo(saddr, len, name, NI_MAXHOST, - NULL, 0, NI_NUMERICHOST) ) { - free(s->hostname); - s->hostname = NULL; - } else { - free(s->hostname); - s->hostname = strdup(name); - } - } - } - return 0; -} - -static int parse_integrity(const lnode *n, search_items *s) -{ - char *ptr, *str, *term; - - term = n->message; - // get pid - str = strstr(term, "pid="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 1; - *term = 0; - errno = 0; - s->pid = strtoul(ptr, NULL, 10); - if (errno) - return 2; - *term = ' '; - } - - // optionally get uid - if (event_uid != -1) { - str = strstr(term, " uid="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 3; - *term = 0; - errno = 0; - s->uid = strtoul(ptr, NULL, 10); - if (errno) - return 4; - *term = ' '; - } - } - - // optionally get loginuid - if (event_loginuid != -2) { - str = strstr(n->message, "auid="); - if (str) { - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 5; - *term = 0; - errno = 0; - s->loginuid = strtoul(ptr, NULL, 10); - if (errno) - return 6; - *term = ' '; - } - } - - // ses - if (event_session_id != -2 ) { - str = strstr(term, "ses="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 10; - *term = 0; - errno = 0; - s->session_id = strtoul(ptr, NULL, 10); - if (errno) - return 11; - *term = ' '; - } - } - - if (event_subject) { - // scontext - str = strstr(term, "subj="); - if (str) { - str += 5; - term = strchr(str, ' '); - if (term == NULL) - return 12; - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - *term = ' '; - } else - return 13; - } - } - - if (event_comm) { - str = strstr(term, "comm="); - if (str) { - str += 5; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 7; - *term = 0; - s->comm = strdup(str); - *term = '"'; - } else - s->comm = unescape(str); - } - } - - if (event_filename) { - str = strstr(term, " name="); - if (str) { - str += 6; - if (common_path_parser(s, str)) - return 8; - } - } - - // and results (usually last) - if (event_success != S_UNSET) { - str = strstr(term, "res="); - if (str != NULL) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->success = strtoul(ptr, NULL, 10); - if (errno) - return 9; - if (term) - *term = ' '; - } - } - - return 0; -} - - -/* FIXME: If they are in permissive mode or hit an auditallow, there can - * be more that 1 avc in the same syscall. For now, we pickup just the first. - */ -static int parse_avc(const lnode *n, search_items *s) -{ - char *str, *term; - anode an; - int rc=0; - - term = n->message; - anode_init(&an); - - // get the avc message info. - str = strstr(term, "avc: "); - if (str) { - str += 5; - term = strchr(str, '{'); - if (term == NULL) - return 1; - if (event_success != S_UNSET) { - *term = 0; - // FIXME. Do not override syscall success if already - // set. Syscall pass/fail is the authoritative value. - if (strstr(str, "denied")) { - s->success = S_FAILED; - an.avc_result = AVC_DENIED; - } else { - s->success = S_SUCCESS; - an.avc_result = AVC_GRANTED; - } - *term = '{'; - } - - // Now get permission - str = term + 1; - while (*str == ' ') - str++; - term = strchr(str, '}'); - if (term == NULL) - return 2; - while (*(term-1) == ' ') - term--; - *term = 0; - an.avc_perm = strdup(str); - *term = ' '; - } - - // get pid - if (event_pid != -1) { - str = strstr(term, "pid="); - if (str) { - str = str + 4; - term = strchr(str, ' '); - if (term == NULL) { - rc = 3; - goto err; - } - *term = 0; - errno = 0; - s->pid = strtoul(str, NULL, 10); - if (errno) { - rc = 4; - goto err; - } - *term = ' '; - } - } - - if (event_comm && s->comm == NULL) { - // dont do this search unless needed - str = strstr(term, "comm="); - if (str == NULL) { - rc = 5; - goto err; - } - str += 5; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) { - rc = 6; - goto err; - } - *term = 0; - s->comm = strdup(str); - *term = '"'; - } else { - s->comm = unescape(str); - term = str + 6; - } - } - if (event_filename) { - // do we have a path? - str = strstr(term, " path="); - if (str) { - str += 6; - rc = common_path_parser(s, str); - if (rc) - goto err; - term += 7; - } else { - str = strstr(term, " name="); - if (str) { - str += 6; - rc = common_path_parser(s, str); - if (rc) - goto err; - term += 7; - } - } - } - if (event_subject) { - // scontext - str = strstr(term, "scontext="); - if (str != NULL) { - str += 9; - term = strchr(str, ' '); - if (term == NULL) { - rc = 7; - goto err; - } - *term = 0; - an.scontext = strdup(str); - *term = ' '; - } - } - - if (event_object) { - // tcontext - str = strstr(term, "tcontext="); - if (str != NULL) { - str += 9; - term = strchr(str, ' '); - if (term == NULL) { - rc = 8; - goto err; - } - *term = 0; - an.tcontext = strdup(str); - *term = ' '; - } - } - - // Now get the class...its at the end, so we do things different - str = strstr(term, "tclass="); - if (str == NULL) { - rc = 9; - goto err; - } - str += 7; - term = strchr(str, ' '); - if (term) - *term = 0; - an.avc_class = strdup(str); - if (term) - *term = ' '; - - if (audit_avc_init(s) == 0) { - alist_append(s->avc, &an); - } else { - rc = 10; - goto err; - } - - return 0; -err: - anode_clear(&an); - return rc; -} - -static int parse_kernel_anom(const lnode *n, search_items *s) -{ - char *str, *ptr, *term = n->message; - - // optionally get loginuid - if (event_loginuid != -2) { - str = strstr(term, "auid="); - if (str == NULL) - return 1; - ptr = str + 5; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->loginuid = strtoul(ptr, NULL, 10); - if (errno) - return 2; - if (term) - *term = ' '; - else - term = ptr; - } - - // optionally get uid - if (event_uid != -1) { - str = strstr(term, "uid="); // if promiscuous, we start over - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 3; - *term = 0; - errno = 0; - s->uid = strtoul(ptr, NULL, 10); - if (errno) - return 4; - *term = ' '; - } - } - - // optionally get gid - if (event_gid != -1) { - str = strstr(term, "gid="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 5; - *term = 0; - errno = 0; - s->gid = strtoul(ptr, NULL, 10); - if (errno) - return 6; - *term = ' '; - } - } - - if (event_session_id != -2) { - str = strstr(term, "ses="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->session_id = strtoul(ptr, NULL, 10); - if (errno) - return 7; - if (term) - *term = ' '; - else - term = ptr; - } - } - - if (event_subject) { - // scontext - str = strstr(term, "subj="); - if (str) { - str += 5; - term = strchr(str, ' '); - if (term == NULL) - return 8; - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - *term = ' '; - } else - return 9; - } - } - - // get pid - if (event_pid != -1) { - str = strstr(term, "pid="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 10; - *term = 0; - errno = 0; - s->pid = strtoul(ptr, NULL, 10); - if (errno) - return 11; - *term = ' '; - } - } - - if (event_comm) { - // dont do this search unless needed - str = strstr(term, "comm="); - if (str) { - str += 5; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 12; - *term = 0; - s->comm = strdup(str); - *term = '"'; - } else - s->comm = unescape(str); - } - } - - if (n->type == AUDIT_SECCOMP) { - if (event_exe) { - // dont do this search unless needed - str = strstr(n->message, "exe="); - if (str) { - str += 4; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 13; - *term = 0; - s->exe = strdup(str); - *term = '"'; - } else - s->exe = unescape(str); - } else - return 14; - } - - // get arch - str = strstr(term, "arch="); - if (str == NULL) - return 0; // A few kernel versions don't have it - ptr = str + 5; - term = strchr(ptr, ' '); - if (term == NULL) - return 15; - *term = 0; - errno = 0; - s->arch = (int)strtoul(ptr, NULL, 16); - if (errno) - return 16; - *term = ' '; - // get syscall - str = strstr(term, "syscall="); - if (str == NULL) - return 17; - ptr = str + 8; - term = strchr(ptr, ' '); - if (term == NULL) - return 18; - *term = 0; - errno = 0; - s->syscall = (int)strtoul(ptr, NULL, 10); - if (errno) - return 19; - *term = ' '; - } - - return 0; -} - -// This is for messages that only have the loginuid as the item -// of interest. -static int parse_simple_message(const lnode *n, search_items *s) -{ - char *str, *ptr, *term = n->message; - - // optionally get loginuid - old kernels skip auid for CONFIG_CHANGE - if (event_loginuid != -2) { - str = strstr(term, "auid="); - if (str == NULL && n->type != AUDIT_CONFIG_CHANGE) - return 1; - if (str) { - ptr = str + 5; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->loginuid = strtoul(ptr, NULL, 10); - if (errno) - return 2; - if (term) - *term = ' '; - else - term = ptr; - } - } - - // ses - if (event_session_id != -2 ) { - str = strstr(term, "ses="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->session_id = strtoul(ptr, NULL, 10); - if (errno) - return 3; - if (term) - *term = ' '; - else - term = ptr; - } - } - - // Now get subj label - if (event_subject) { - // scontext - str = strstr(term, "subj="); - if (str != NULL) { - str += 5; - term = strchr(str, ' '); - if (term) - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - if (term) - *term = ' '; - else // Set it back to something sane - term = str; - } else - return 4; - } - } - - if (event_key) { - str = strstr(term, "key="); - if (str != NULL) { - if (!s->key) { - //create - s->key = malloc(sizeof(slist)); - if (s->key == NULL) - return 5; - slist_create(s->key); - } - ptr = str + 4; - if (*ptr == '"') { - ptr++; - term = strchr(ptr, '"'); - if (term != NULL) { - *term = 0; - if (s->key) { - // append - snode sn; - sn.str = strdup(ptr); - sn.key = NULL; - sn.hits = 1; - slist_append(s->key, &sn); - } - *term = '"'; - } else - return 6; - } else { - if (s->key) { - char *saved; - char *keyptr = unescape(ptr); - char *kptr = strtok_r(keyptr, - key_sep, &saved); - while (kptr) { - snode sn; - // append - sn.str = strdup(kptr); - sn.key = NULL; - sn.hits = 1; - slist_append(s->key, &sn); - kptr = strtok_r(NULL, - key_sep, &saved); - } - free(keyptr); - } - } - } - } - - // defaulting this to 1 for these messages. The kernel generally - // does not log the res since it can be nothing but success. - // But it can still be overriden below if res= is found in the event - if (n->type == AUDIT_CONFIG_CHANGE) - s->success = S_SUCCESS; - - // and results (usually last) - if (event_success != S_UNSET) { - str = strstr(term, "res="); - if (str != NULL) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->success = strtoul(ptr, NULL, 10); - if (errno) - return 7; - if (term) - *term = ' '; - } - } - - return 0; -} - -static int parse_tty(const lnode *n, search_items *s) -{ - char *str, *ptr, *term=n->message; - - // get pid - if (event_pid != -1) { - str = strstr(n->message, "pid="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 1; - *term = 0; - errno = 0; - s->pid = strtoul(ptr, NULL, 10); - if (errno) - return 2; - *term = ' '; - } - } - - // optionally get uid - if (event_uid != -1) { - str = strstr(term, " uid="); // if promiscuous, we start over - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 3; - *term = 0; - errno = 0; - s->uid = strtoul(ptr, NULL, 10); - if (errno) - return 4; - *term = ' '; - } - } - - // optionally get loginuid - if (event_loginuid != -2) { - str = strstr(term, "auid="); - if (str == NULL) - return 5; - ptr = str + 5; - term = strchr(ptr, ' '); - if (term) - *term = 0; - errno = 0; - s->loginuid = strtoul(ptr, NULL, 10); - if (errno) - return 6; - if (term) - *term = ' '; - else - term = ptr; - } - - // ses - if (event_session_id != -2 ) { - str = strstr(term, "ses="); - if (str) { - ptr = str + 4; - term = strchr(ptr, ' '); - if (term == NULL) - return 7; - *term = 0; - errno = 0; - s->session_id = strtoul(ptr, NULL, 10); - if (errno) - return 8; - *term = ' '; - } - } - -/* if (event_subject) { - // scontext - str = strstr(term, "subj="); - if (str) { - str += 5; - term = strchr(str, ' '); - if (term == NULL) - return 9; - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.scontext = strdup(str); - alist_append(s->avc, &an); - *term = ' '; - } else - return 10; - } - } */ - - if (event_comm) { - // dont do this search unless needed - str = strstr(term, "comm="); - if (str) { - str += 5; - if (*str == '"') { - str++; - term = strchr(str, '"'); - if (term == NULL) - return 11; - *term = 0; - s->comm = strdup(str); - *term = '"'; - } else - s->comm = unescape(str); - } - } - - return 0; -} - -static int parse_pkt(const lnode *n, search_items *s) -{ - char *str, *ptr, *term=n->message; - - // get hostname - if (event_hostname) { - str = strstr(n->message, "saddr="); - if (str) { - ptr = str + 6; - term = strchr(ptr, ' '); - if (term == NULL) - return 1; - *term = 0; - s->hostname = strdup(ptr); - *term = ' '; - } - } - - // obj context - if (event_object) { - str = strstr(term, "obj="); - if (str != NULL) { - str += 4; - term = strchr(str, ' '); - if (term) - *term = 0; - if (audit_avc_init(s) == 0) { - anode an; - - anode_init(&an); - an.tcontext = strdup(str); - alist_append(s->avc, &an); - if (term) - *term = ' '; - } else - return 2; - } - } - - return 0; -} - diff --git a/framework/src/audit/src/ausearch-parse.h b/framework/src/audit/src/ausearch-parse.h deleted file mode 100644 index 36557105..00000000 --- a/framework/src/audit/src/ausearch-parse.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -* ausearch-parse.h - Header file for ausearch-llist.c -* Copyright (c) 2005 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> -*/ - -#ifndef AUPARSE_HEADER -#define AUPARSE_HEADER - -#include "config.h" -#include "ausearch-llist.h" - -int extract_search_items(llist *l); - -#endif - diff --git a/framework/src/audit/src/ausearch-report.c b/framework/src/audit/src/ausearch-report.c deleted file mode 100644 index a4f1e15d..00000000 --- a/framework/src/audit/src/ausearch-report.c +++ /dev/null @@ -1,362 +0,0 @@ -/* -* ausearch-report.c - Format and output events -* Copyright (c) 2005-09,2011-13 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 "config.h" -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include "libaudit.h" -#include "ausearch-options.h" -#include "ausearch-parse.h" -#include "ausearch-lookup.h" -#include "auparse-idata.h" -#include "auparse-defs.h" - -/* Local functions */ -static void output_raw(llist *l); -static void output_default(llist *l); -static void output_interpreted(llist *l); -static void output_interpreted_node(const lnode *n, const event *e); -static void interpret(char *name, char *val, int comma, int rtype); - -/* The machine based on elf type */ -static unsigned long machine = -1; -static int cur_syscall = -1; - -/* The first syscall argument */ -static unsigned long long a0, a1; - -/* This function branches to the correct output format */ -void output_record(llist *l) -{ - switch (report_format) { - case RPT_RAW: - output_raw(l); - break; - case RPT_DEFAULT: - output_default(l); - break; - case RPT_INTERP: - output_interpreted(l); - break; - case RPT_PRETTY: - break; - default: - fprintf(stderr, "Report format error"); - exit(1); - } -} - -/* This function will output the record as is */ -static void output_raw(llist *l) -{ - const lnode *n; - - list_first(l); - n = list_get_cur(l); - if (!n) { - fprintf(stderr, "Error - no elements in record."); - return; - } - do { - puts(n->message); - } while ((n=list_next(l))); -} - -/* - * This function will take the linked list and format it for output. No - * interpretation is performed. The output order is lifo for everything. - */ -static void output_default(llist *l) -{ - const lnode *n; - - list_last(l); - n = list_get_cur(l); - printf("----\ntime->%s", ctime(&l->e.sec)); - if (!n) { - fprintf(stderr, "Error - no elements in record."); - return; - } - if (n->type >= AUDIT_DAEMON_START && n->type < AUDIT_SYSCALL) - puts(n->message); // No injection possible - else { - do { - safe_print_string_n(n->message, n->mlen, 1); - } while ((n=list_prev(l))); - } -} - -/* - * This function will take the linked list and format it for output. - * Interpretation is performed to aid understanding of records. The output - * order is lifo for everything. - */ -static void output_interpreted(llist *l) -{ - const lnode *n; - - list_last(l); - n = list_get_cur(l); - printf("----\n"); - if (!n) { - fprintf(stderr, "Error - no elements in record."); - return; - } - if (n->type >= AUDIT_DAEMON_START && n->type < AUDIT_SYSCALL) - output_interpreted_node(n, &(l->e)); - else { - do { - output_interpreted_node(n, &(l->e)); - } while ((n=list_prev(l))); - } -} - -/* - * This function will cycle through a single record and lookup each field's - * value that it finds. - */ -static void output_interpreted_node(const lnode *n, const event *e) -{ - char *ptr, *str = n->message; - int found, comma = 0; - int num = n->type; - struct tm *btm; - char tmp[32]; - - // Reset these because each record could be different - machine = -1; - cur_syscall = -1; - - /* Check and see if we start with a node - * If we do, and there is a space in the line - * move the pointer to the first character past - * the space - */ - if (e->node) { - if ((ptr=strchr(str, ' ')) != NULL) { - str = ptr+1; - } - } - - // First locate time stamp. - ptr = strchr(str, '('); - if (ptr == NULL) { - fprintf(stderr, "can't find time stamp\n"); - return; - } - - *ptr++ = 0; /* move to the start of the timestamp */ - - // print everything up to it. - if (num >= 0) { - const char * bptr; - bptr = audit_msg_type_to_name(num); - if (bptr) { - if (e->node) - printf("node=%s ", e->node); - printf("type=%s msg=audit(", bptr); - goto no_print; - } - } - if (e->node) - printf("node=%s ", e->node); - printf("%s(", str); -no_print: - - str = strchr(ptr, ')'); - if(str == NULL) - return; - *str++ = 0; - btm = localtime(&e->sec); - strftime(tmp, sizeof(tmp), "%x %T", btm); - printf("%s", tmp); - printf(".%03d:%lu) ", e->milli, e->serial); - - if (n->type == AUDIT_SYSCALL) { - a0 = n->a0; - a1 = n->a1; - } - - // for each item. - found = 0; - while (str && *str && (ptr = strchr(str, '='))) { - char *name, *val; - comma = 0; - found = 1; - - // look back to last space - this is name - name = ptr; - while (*name != ' ' && name > str) - --name; - *ptr++ = 0; - - // print everything up to the '=' - printf("%s=", str); - - // Some user messages have msg='uid=500 in this case - // skip the msg= piece since the real stuff is the uid= - if (strcmp(name, "msg") == 0) { - str = ptr; - continue; - } - - // In the above case, after msg= we need to trim the ' from uid - if (*name == '\'') - name++; - - // get string after = to the next space or end - this is value - if (*ptr == '\'' || *ptr == '"') { - str = strchr(ptr+1, *ptr); - if (str) { - str++; - if (*str) - *str++ = 0; - } - } else { - str = strchr(ptr, ','); - val = strchr(ptr, ' '); - if (str && val && (str < val)) { - // Value side has commas and another field exists - // Known: LABEL_LEVEL_CHANGE banners=none,none - // Known: ROLL_ASSIGN new-role=r,r - // Known: any MAC LABEL can potentially have commas - int ftype = auparse_interp_adjust_type(n->type, - name, val); - if (ftype == AUPARSE_TYPE_MAC_LABEL) { - str = val; - *str++ = 0; - } else { - *str++ = 0; - comma = 1; - } - } else if (str && (val == NULL)) { - // Goes all the way to the end. Done parsing - // Known: MCS context in PATH rec obj=u:r:t:s0:c2,c7 - int ftype = auparse_interp_adjust_type(n->type, - name, ptr); - if (ftype == AUPARSE_TYPE_MAC_LABEL) - str = NULL; - else { - *str++ = 0; - comma = 1; - } - } else if (val) { - // There is another field, point to next (normal path) - str = val; - *str++ = 0; - } - } - // val points to begin & str 1 past end - val = ptr; - - // print interpreted string - interpret(name, val, comma, n->type); - } - // If nothing found, just print out as is - if (!found && ptr == NULL && str) - safe_print_string(str, 1); - - // If last field had comma, output the rest - else if (comma) - safe_print_string(str, 1); - printf("\n"); -} - -static void interpret(char *name, char *val, int comma, int rtype) -{ - int type; - idata id; - - while (*name == ' '||*name == '(') - name++; - - if (*name == 'a' && strcmp(name, "acct") == 0) { - // Remove trailing punctuation - int len = strlen(val); - if (val[len-1] == ':') - val[len-1] = 0; - } - type = auparse_interp_adjust_type(rtype, name, val); - - if (rtype == AUDIT_SYSCALL || rtype == AUDIT_SECCOMP) { - if (machine == (unsigned long)-1) - machine = audit_detect_machine(); - if (*name == 'a' && strcmp(name, "arch") == 0) { - unsigned long ival; - errno = 0; - ival = strtoul(val, NULL, 16); - if (errno) { - printf("arch conversion error(%s) ", val); - return; - } - machine = audit_elf_to_machine(ival); - } - if (cur_syscall < 0 && *name == 's' && - strcmp(name, "syscall") == 0) { - unsigned long ival; - errno = 0; - ival = strtoul(val, NULL, 10); - if (errno) { - printf("syscall conversion error(%s) ", val); - return; - } - cur_syscall = ival; - } - id.syscall = cur_syscall; - } else - id.syscall = 0; - id.machine = machine; - id.a0 = a0; - id.a1 = a1; - id.name = name; - id.val = val; - - char *out = auparse_do_interpretation(type, &id); - if (type == AUPARSE_TYPE_UNCLASSIFIED) - printf("%s%c", val, comma ? ',' : ' '); - else if (name[0] == 'k' && strcmp(name, "key") == 0) { - char *str, *ptr = out; - int count = 0; - while ((str = strchr(ptr, AUDIT_KEY_SEPARATOR))) { - *str = 0; - if (count == 0) { - printf("%s", ptr); - count++; - } else - printf(" key=%s", ptr); - ptr = str+1; - } - if (count == 0) - printf("%s ", out); - else - printf(" key=%s ", ptr); - } else if (type == AUPARSE_TYPE_TTY_DATA) - printf("%s", out); - else - printf("%s ", out); - - free(out); -} - diff --git a/framework/src/audit/src/ausearch-string.c b/framework/src/audit/src/ausearch-string.c deleted file mode 100644 index 3c5c55e3..00000000 --- a/framework/src/audit/src/ausearch-string.c +++ /dev/null @@ -1,178 +0,0 @@ -/* -* ausearch-string.c - Minimal linked list library for strings -* Copyright (c) 2005,2008,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-string.h" -#include <stdlib.h> -#include <string.h> - - -void slist_create(slist *l) -{ - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - -void slist_last(slist *l) -{ - register snode* cur; - - if (l->head == NULL) - return; - - // Try using cur so that we don't have to start at beginnning - if (l->cur) - cur = l->cur; - else - cur = l->head; - - // Loop until no next value - while (cur->next) - cur = cur->next; - l->cur = cur; -} - -snode *slist_next(slist *l) -{ - if (l->cur == NULL) - return NULL; - l->cur = l->cur->next; - return l->cur; -} - -void slist_append(slist *l, snode *node) -{ - snode* newnode; - - newnode = malloc(sizeof(snode)); - - if (node->str) - newnode->str = node->str; - else - newnode->str = NULL; - - if (node->key) - newnode->key = node->key; - else - newnode->key = NULL; - - newnode->hits = node->hits; - newnode->next = NULL; - - // Make sure cursor is at the end - slist_last(l); - - // if we are at top, fix this up - if (l->head == NULL) - l->head = newnode; - else // Otherwise add pointer to newnode - l->cur->next = newnode; - - // make newnode current - l->cur = newnode; - l->cnt++; -} - -void slist_clear(slist* l) -{ - snode* nextnode; - register snode* current; - - current = l->head; - while (current) { - nextnode=current->next; - free(current->str); - free(current->key); - free(current); - current=nextnode; - } - l->head = NULL; - l->cur = NULL; - l->cnt = 0; -} - -/* This function dominates the timing of aureport. Needs to be more efficient */ -int slist_add_if_uniq(slist *l, const char *str) -{ - snode sn; - register snode *cur; - - cur = l->head; - while (cur) { - if (strcmp(str, cur->str) == 0) { - cur->hits++; - l->cur = cur; - return 0; - } else - cur = cur->next; - } - - /* No matches, append to the end */ - sn.str = strdup(str); - sn.key = NULL; - sn.hits = 1; - slist_append(l, &sn); - return 1; -} - -// If lprev would be NULL, use l->head -static void swap_nodes(snode *lprev, snode *left, snode *right) -{ - snode *t = right->next; - if (lprev) - lprev->next = right; - right->next = left; - left->next = t; -} - -// This will sort the list from most hits to least -void slist_sort_by_hits(slist *l) -{ - register snode* cur, *prev; - - if (l->cnt <= 1) - return; - - prev = cur = l->head; - - while (cur && cur->next) { - /* If the next node is bigger */ - if (cur->hits < cur->next->hits) { - if (cur == l->head) { - // Update the actual list head - l->head = cur->next; - prev = NULL; - } - swap_nodes(prev, cur, cur->next); - - // start over - prev = cur = l->head; - continue; - } - prev = cur; - cur = cur->next; - } - // End with cur pointing at first record - l->cur = l->head; -} - diff --git a/framework/src/audit/src/ausearch-string.h b/framework/src/audit/src/ausearch-string.h deleted file mode 100644 index 08cf2ffc..00000000 --- a/framework/src/audit/src/ausearch-string.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* ausearch-string.h - Header file for ausearch-string.c -* Copyright (c) 2005,2008 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> -*/ - -#ifndef AUSTRING_HEADER -#define AUSTRING_HEADER - -#include "config.h" - -/* This is the node of the linked list. message & item are the only elements - * at this time. Any data elements that are per item goes here. */ -typedef struct _snode{ - char *str; // The string - char *key; // The key string - unsigned int hits; // Number of times this string was attempted to be added - struct _snode* next; // Next string node pointer -} snode; - -/* This is the linked list head. Only data elements that are 1 per - * event goes here. */ -typedef struct { - snode *head; // List head - snode *cur; // Pointer to current node - unsigned int cnt; // How many items in this list -} slist; - -void slist_create(slist *l); -static inline void slist_first(slist *l) { l->cur = l->head; } -void slist_last(slist *l); -snode *slist_next(slist *l); -static inline snode *slist_get_cur(slist *l) { return l->cur; } -void slist_append(slist *l, snode *node); -void slist_clear(slist* l); - -/* append a string if its not already on the list */ -int slist_add_if_uniq(slist *l, const char *str); -void slist_sort_by_hits(slist *l); - -#endif - diff --git a/framework/src/audit/src/ausearch-time.c b/framework/src/audit/src/ausearch-time.c deleted file mode 100644 index 3cd33c87..00000000 --- a/framework/src/audit/src/ausearch-time.c +++ /dev/null @@ -1,412 +0,0 @@ -/* ausearch-time.c - time handling utility functions - * Copyright 2006-08,2011 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - */ - -#include "config.h" -#include <stdio.h> -#include <string.h> -#include "ausearch-time.h" - - -#define SECONDS_IN_DAY 24*60*60 -static void clear_tm(struct tm *t); -static void replace_time(struct tm *t1, struct tm *t2); -static void replace_date(struct tm *t1, struct tm *t2); - - -time_t start_time = 0, end_time = 0; - -struct nv_pair { - int value; - const char *name; -}; - -static struct nv_pair timetab[] = { - { T_NOW, "now" }, - { T_RECENT, "recent" }, - { T_TODAY, "today" }, - { T_YESTERDAY, "yesterday" }, - { T_THIS_WEEK, "this-week" }, - { T_WEEK_AGO, "week-ago" }, - { T_THIS_MONTH, "this-month" }, - { T_THIS_YEAR, "this-year" }, -}; -#define TIME_NAMES (sizeof(timetab)/sizeof(timetab[0])) - -int lookup_time(const char *name) -{ - int i; - - for (i = 0; i < TIME_NAMES; i++) { - if (strcmp(timetab[i].name, name) == 0) { - return timetab[i].value; - } - } - return -1; - -} - -static void clear_tm(struct tm *t) -{ - t->tm_sec = 0; /* seconds */ - t->tm_min = 0; /* minutes */ - t->tm_hour = 0; /* hours */ - t->tm_mday = 0; /* day of the month */ - t->tm_mon = 0; /* month */ - t->tm_year = 0; /* year */ - t->tm_isdst = 0; /* DST flag */ -} - -static void set_tm_now(struct tm *d) -{ - time_t t = time(NULL); - struct tm *tv = localtime(&t); - replace_time(d, tv); - replace_date(d, tv); -} - -static void set_tm_today(struct tm *d) -{ - time_t t = time(NULL); - struct tm *tv = localtime(&t); - d->tm_sec = 0; /* seconds */ - d->tm_min = 0; /* minutes */ - d->tm_hour = 0; /* hours */ - replace_date(d, tv); -} - -static void set_tm_yesterday(struct tm *d) -{ - time_t t = time(NULL) - (time_t)(SECONDS_IN_DAY); - struct tm *tv = localtime(&t); - d->tm_sec = 0; /* seconds */ - d->tm_min = 0; /* minutes */ - d->tm_hour = 0; /* hours */ - replace_date(d, tv); -} - -static void set_tm_recent(struct tm *d) -{ - time_t t = time(NULL) - (time_t)(10*60); /* 10 minutes ago */ - struct tm *tv = localtime(&t); - replace_time(d, tv); - replace_date(d, tv); -} - -static void set_tm_this_week(struct tm *d) -{ - time_t t = time(NULL); - struct tm *tv = localtime(&t); - d->tm_sec = 0; /* seconds */ - d->tm_min = 0; /* minutes */ - d->tm_hour = 0; /* hours */ - t -= (time_t)(tv->tm_wday*SECONDS_IN_DAY); - tv = localtime(&t); - replace_date(d, tv); -} - -static void set_tm_week_ago(struct tm *d) -{ - time_t t = time(NULL); - struct tm *tv; - d->tm_sec = 0; /* seconds */ - d->tm_min = 0; /* minutes */ - d->tm_hour = 0; /* hours */ - t -= (time_t)(7*SECONDS_IN_DAY); - tv = localtime(&t); - replace_date(d, tv); -} - -static void set_tm_this_month(struct tm *d) -{ - time_t t = time(NULL); - struct tm *tv = localtime(&t); - d->tm_sec = 0; /* seconds */ - d->tm_min = 0; /* minutes */ - d->tm_hour = 0; /* hours */ - replace_date(d, tv); - d->tm_mday = 1; /* override day of month */ -} - -static void set_tm_this_year(struct tm *d) -{ - time_t t = time(NULL); - struct tm *tv = localtime(&t); - d->tm_sec = 0; /* seconds */ - d->tm_min = 0; /* minutes */ - d->tm_hour = 0; /* hours */ - replace_date(d, tv); - d->tm_mday = 1; /* override day of month */ - d->tm_mon = 0; /* override month */ -} - -/* Combine date & time into 1 struct. Results in date. */ -static void add_tm(struct tm *d, struct tm *t) -{ - time_t dst; - struct tm *lt; - - replace_time(d, t); - - /* Now we need to figure out if DST is in effect */ - dst = time(NULL); - lt = localtime(&dst); - d->tm_isdst = lt->tm_isdst; -} - -/* The time in t1 is replaced by t2 */ -static void replace_time(struct tm *t1, struct tm *t2) -{ - t1->tm_sec = t2->tm_sec; /* seconds */ - t1->tm_min = t2->tm_min; /* minutes */ - t1->tm_hour = t2->tm_hour; /* hours */ -} - -/* The date in t1 is replaced by t2 */ -static void replace_date(struct tm *t1, struct tm *t2) -{ - t1->tm_mday = t2->tm_mday; /* day */ - t1->tm_mon = t2->tm_mon; /* month */ - t1->tm_year = t2->tm_year; /* year */ - t1->tm_isdst = t2->tm_isdst; /* daylight savings time */ -} - -/* Given 2 char strings, create a time struct * -void set_time(struct tm *t, int num, const char *t1, const char *t2) -{ - switch (num) - { - case 1: - // if keyword, init time - // elif time use today and replace time - // elif date, set to 00:00:01 and replace date - // else error - break; - case 2: - // if keyword - // init time with it - // get other time str and replace - // otherwise, figure out which is time - // and set time adding them - break; - default: - break; - } -} */ - -static int lookup_and_set_time(const char *da, struct tm *d) -{ - int retval = lookup_time(da); - if (retval >= 0) { - switch (retval) - { - case T_NOW: - set_tm_now(d); - break; - case T_RECENT: - set_tm_recent(d); - break; - case T_TODAY: - set_tm_today(d); - break; - case T_YESTERDAY: - set_tm_yesterday(d); - break; - case T_THIS_WEEK: - set_tm_this_week(d); - break; - case T_WEEK_AGO: - set_tm_week_ago(d); - break; - case T_THIS_MONTH: - set_tm_this_month(d); - break; - case T_THIS_YEAR: - set_tm_this_year(d); - break; - } - return 0; - } else - return -1; -} - -/* static void print_time(struct tm *d) -{ - char outstr[200]; - strftime(outstr, sizeof(outstr), "%c", d); - printf("%s\n", outstr); -} */ - -int ausearch_time_start(const char *da, const char *ti) -{ -/* If da == NULL, use current date */ -/* If ti == NULL, then use midnight 00:00:00 */ - int rc = 0; - struct tm d, t; - char *ret; - - if (da == NULL) - set_tm_now(&d); - else { - if (lookup_and_set_time(da, &d) < 0) { - ret = strptime(da, "%x", &d); - if (ret == NULL) { - fprintf(stderr, - "Invalid start date (%s). Month, Day, and Year are required.\n", - da); - return 1; - } - if (*ret != 0) { - fprintf(stderr, - "Error parsing start date (%s)\n", da); - return 1; - } - } else { - int keyword=lookup_time(da); - if (keyword == T_RECENT || keyword == T_NOW) { - if (ti == NULL || strcmp(ti, "00:00:00") == 0) - goto set_it; - } - } - } - - if (ti != NULL) { - char tmp_t[36]; - - if (strlen(ti) <= 5) { - snprintf(tmp_t, sizeof(tmp_t), "%s:00", ti); - } else { - tmp_t[0]=0; - strncat(tmp_t, ti, sizeof(tmp_t)-1); - } - ret = strptime(tmp_t, "%X", &t); - if (ret == NULL) { - fprintf(stderr, - "Invalid start time (%s). Hour, Minute, and Second are required.\n", - ti); - return 1; - } - if (*ret != 0) { - fprintf(stderr, "Error parsing start time (%s)\n", ti); - return 1; - } - } else - clear_tm(&t); - - add_tm(&d, &t); - if (d.tm_year < 104) { - fprintf(stderr, "Error - year is %d\n", d.tm_year+1900); - return -1; - } -set_it: - // printf("start is: %s\n", ctime(&start_time)); - start_time = mktime(&d); - if (start_time == -1) { - fprintf(stderr, "Error converting start time\n"); - rc = -1; - } - return rc; -} - -int ausearch_time_end(const char *da, const char *ti) -{ -/* If date == NULL, use current date */ -/* If ti == NULL, use current time */ - int rc = 0; - struct tm d, t; - char *ret; - - if (da == NULL) - set_tm_now(&d); - else { - if (lookup_and_set_time(da, &d) < 0) { - ret = strptime(da, "%x", &d); - if (ret == NULL) { - fprintf(stderr, - "Invalid end date (%s). Month, Day, and Year are required.\n", - da); - return 1; - } - if (*ret != 0) { - fprintf(stderr, - "Error parsing end date (%s)\n", da); - return 1; - } - } else { - int keyword=lookup_time(da); - if (keyword == T_RECENT || keyword == T_NOW) { - if (ti == NULL || strcmp(ti, "00:00:00") == 0) - goto set_it; - } - // Special case today - if (keyword == T_TODAY) { - set_tm_now(&d); - if (ti == NULL || strcmp(ti, "00:00:00") == 0) - goto set_it; - } - } - } - - if (ti != NULL) { - char tmp_t[36]; - - if (strlen(ti) <= 5) { - snprintf(tmp_t, sizeof(tmp_t), "%s:00", ti); - } else { - tmp_t[0]=0; - strncat(tmp_t, ti, sizeof(tmp_t)-1); - } - ret = strptime(tmp_t, "%X", &t); - if (ret == NULL) { - fprintf(stderr, - "Invalid end time (%s). Hour, Minute, and Second are required.\n", - ti); - return 1; - } - if (*ret != 0) { - fprintf(stderr, "Error parsing end time (%s)\n", ti); - return 1; - } - } else { - time_t tt = time(NULL); - struct tm *tv = localtime(&tt); - clear_tm(&t); - t.tm_hour = tv->tm_hour; - t.tm_min = tv->tm_min; - t.tm_sec = tv->tm_sec; - t.tm_isdst = tv->tm_isdst; - - } - add_tm(&d, &t); - if (d.tm_year < 104) { - fprintf(stderr, "Error - year is %d\n", d.tm_year+1900); - return -1; - } -set_it: - // printf("end is: %s\n", ctime(&end_time)); - end_time = mktime(&d); - if (end_time == -1) { - fprintf(stderr, "Error converting end time\n"); - rc = -1; - } - return rc; -} - diff --git a/framework/src/audit/src/ausearch-time.h b/framework/src/audit/src/ausearch-time.h deleted file mode 100644 index 15051a5a..00000000 --- a/framework/src/audit/src/ausearch-time.h +++ /dev/null @@ -1,38 +0,0 @@ -/* ausearch-time.h - header file for ausearch-time.c - * Copyright 2006-07 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - */ - -#ifndef AUSEARCH_TIME_HEADERS -#define AUSEARCH_TIME_HEADERS - -#include <time.h> - -enum { T_NOW, T_RECENT, T_TODAY, T_YESTERDAY, T_THIS_WEEK, T_WEEK_AGO, - T_THIS_MONTH, T_THIS_YEAR }; - -extern time_t start_time, end_time; - -int lookup_time(const char *name); -int ausearch_time_start(const char *da, const char *ti); -int ausearch_time_end(const char *da, const char *ti); - -#endif - diff --git a/framework/src/audit/src/ausearch.c b/framework/src/audit/src/ausearch.c deleted file mode 100644 index 06213f8b..00000000 --- a/framework/src/audit/src/ausearch.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * ausearch.c - main file for ausearch utility - * Copyright 2005-08,2010,2013,2014 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - */ - -#include "config.h" -#include <stdio.h> -#include <stdio_ext.h> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <unistd.h> -#include <ctype.h> -#include <time.h> -#include <errno.h> -#include <sys/resource.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <locale.h> -#include <signal.h> -#include "libaudit.h" -#include "auditd-config.h" -#include "ausearch-options.h" -#include "ausearch-lol.h" -#include "ausearch-lookup.h" -#include "auparse.h" -#include "ausearch-checkpt.h" - - -static FILE *log_fd = NULL; -static lol lo; -static int found = 0; -static int input_is_pipe = 0; -static int timeout_interval = 3; /* timeout in seconds */ -static int files_to_process = 0; /* number of log files yet to process when reading multiple */ -static int process_logs(void); -static int process_log_fd(void); -static int process_stdin(void); -static int process_file(char *filename); -static int get_record(llist **); - -extern const char *checkpt_filename; /* checkpoint file name */ -extern int checkpt_timeonly; /* use timestamp from within checkpoint file */ -static int have_chkpt_data = 0; /* have checkpt need to compare wit */ -extern char *user_file; -extern int force_logs; -extern int match(llist *l); -extern void output_record(llist *l); - -static int userfile_is_dir = 0; - -static int is_pipe(int fd) -{ - struct stat st; - int pipe_mode=0; - - if (fstat(fd, &st) == 0) { - if (S_ISFIFO(st.st_mode)) - pipe_mode = 1; - } - return pipe_mode; -} - -int main(int argc, char *argv[]) -{ - struct rlimit limit; - int rc; - struct stat sb; - - /* Check params and build regexpr */ - setlocale (LC_ALL, ""); - if (check_params(argc, argv)) - return 1; - - /* Raise the rlimits in case we're being started from a shell - * with restrictions. Not a fatal error. */ - limit.rlim_cur = RLIM_INFINITY; - limit.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_FSIZE, &limit); - setrlimit(RLIMIT_CPU, &limit); - set_aumessage_mode(MSG_STDERR, DBG_NO); - (void) umask( umask( 077 ) | 027 ); - - /* Load the checkpoint file if requested */ - if (checkpt_filename) { - rc = load_ChkPt(checkpt_filename); - /* - * If < -1, then some load/parse error - * If == -1 then no file present (OK) - * If == 0, then checkpoint has data - */ - if (rc < -1) { - (void)free((void *)checkpt_filename); - free_ChkPtMemory(); - return 10; /* bad checkpoint status file */ - } else if (rc == -1) { - /* - * No file, so no checking required. This just means - * we have never checkpointed before and this is the - * first time. - */ - have_chkpt_data = 0; - } else { - /* We will need to check */ - have_chkpt_data++; - } - } - - lol_create(&lo); - if (user_file) { - if (stat(user_file, &sb) == -1) { - perror("stat"); - return 1; - } - switch (sb.st_mode & S_IFMT) { - case S_IFDIR: - userfile_is_dir = 1; - rc = process_logs(); - break; - case S_IFREG: - default: - rc = process_file(user_file); - break; - } - } else if (force_logs) - rc = process_logs(); - else if (is_pipe(0)) - rc = process_stdin(); - else - rc = process_logs(); - - /* Generate a checkpoint if required */ - if (checkpt_filename) { - /* Providing we found something and haven't failed */ - if (!checkpt_failure && found) - save_ChkPt(checkpt_filename); - free_ChkPtMemory(); - free((void *)checkpt_filename); - /* - * A checkpoint failure at this point means either - * - we failed in attempting to create the checkpouint file - * and so we will return 11 - * - we had a corrupted checkpoint file and so we will return 12 - */ - if (checkpt_failure) { - rc = ((checkpt_failure & CP_CORRUPTED) == - CP_CORRUPTED) ? 12 : 11; - } - } - - lol_clear(&lo); - ilist_clear(event_type); - free(event_type); - free(user_file); - free((char *)event_key); - auparse_destroy(NULL); - if (rc) - return rc; - if (!found) { - if (report_format != RPT_RAW) - fprintf(stderr, "<no matches>\n"); - return 1; - } - return 0; -} - -static int process_logs(void) -{ - struct daemon_conf config; - char *filename; - int len, num = 0; - int found_chkpt_file = -1; - int ret; - - if (user_file && userfile_is_dir) { - char dirname[MAXPATHLEN]; - clear_config (&config); - - strcpy(dirname, user_file); - if (dirname[strlen(dirname)-1] != '/') - strcat(dirname, "/"); - strcat (dirname, "audit.log"); - free((void *)config.log_file); - config.log_file=strdup(dirname); - fprintf(stderr, "NOTE - using logs in %s\n", config.log_file); - } - else { - /* Load config so we know where logs are */ - if (load_config(&config, TEST_SEARCH)) { - fprintf(stderr, - "NOTE - using built-in logs: %s\n", - config.log_file); - } - } - - /* for each file */ - len = strlen(config.log_file) + 16; - filename = malloc(len); - if (!filename) { - fprintf(stderr, "No memory\n"); - free_config(&config); - return 1; - } - /* Find oldest log file */ - snprintf(filename, len, "%s", config.log_file); - do { - if (access(filename, R_OK) != 0) - break; - - /* - * If we have prior checkpoint data, we ignore files till we - * find the file we last checkpointed from - */ - if (checkpt_filename && have_chkpt_data) { - struct stat sbuf; - - if (stat(filename, &sbuf)) { - fprintf(stderr, "Error stat'ing %s (%s)\n", - filename, strerror(errno)); - free(filename); - free_config(&config); - return 1; - } - /* - * Have we accessed the checkpointed file? - * If so, stop checking further files. - */ - if ( (sbuf.st_dev == chkpt_input_dev) && - (sbuf.st_ino == chkpt_input_ino) ) { - /* - * If we are ignoing all but time, then we - * don't stop checking more files and just - * let this loop go to completion and hence - * we will find the 'oldest' file. - */ - if (!checkpt_timeonly) { - found_chkpt_file = num++; - break; - } - } - } - - num++; - snprintf(filename, len, "%s.%d", config.log_file, num); - } while (1); - - /* If a checkpoint is loaded but can't find it's file, and we - * are not only just checking the timestamp from the checkpoint file, - * we need to error */ - if (checkpt_filename && have_chkpt_data && found_chkpt_file == -1 - && !checkpt_timeonly) { - free(filename); - free_config(&config); - return 10; - } - - num--; - - /* We note how many files we need to process */ - files_to_process = num; - - /* Got it, now process logs from last to first */ - if (num > 0) - snprintf(filename, len, "%s.%d", config.log_file, num); - else - snprintf(filename, len, "%s", config.log_file); - do { - if ((ret = process_file(filename))) { - free(filename); - free_config(&config); - return ret; - } - if (just_one && found) - break; - files_to_process--; /* one less file to process */ - - /* Get next log file */ - num--; - if (num > 0) - snprintf(filename, len, "%s.%d", config.log_file, num); - else if (num == 0) - snprintf(filename, len, "%s", config.log_file); - else - break; - } while (1); - /* - * If performing a checkpoint, set the checkpointed - * file details - ie remember the last file processed - */ - ret = 0; - if (checkpt_filename) - ret = set_ChkPtFileDetails(filename); - - free(filename); - free_config(&config); - return ret; -} - -/* - * Decide if we should start outputing events given we loaded a checkpoint. - * - * The previous checkpoint will have recorded the last event outputted, - * if there was one. If nothing is to be output, either the audit.log file - * is empty, all the events in it were incomplete, or ??? - * - * We can return - * 0 no output - * 1 can output - * 2 can output but not this event - * 3 we have found an event whose time is > MAX_EVENT_DELTA_SECS secs - * past our checkpoint time, which means this particulare event is - * complete. This should not happen, for we should have found our - * checkpoint event before ANY other completed event. - * - */ -static int chkpt_output_decision(event * e) -{ - static int can_output = 0; - - /* Short cut. Once we made the decision, it's made for good */ - if (can_output) - return 1; - - /* If there was no checkpoint file, we turn on output */ - if (have_chkpt_data == 0) { - can_output = 1; - return 1; /* can output on this event */ - } - - /* - * If the previous checkpoint had no recorded output, then - * we assume everything was partial so we turn on output - */ - if (chkpt_input_levent.sec == 0) { - can_output = 1; - return 1; /* can output on this event */ - } - - /* - * If we are ignoring all but event time from within the checkpoint - * file, then we output if the current event's time is greater than - * or equal to the checkpoint time. - */ - if (checkpt_timeonly) { - if ( (chkpt_input_levent.sec < e->sec) || - ( (chkpt_input_levent.sec == e->sec) && - (chkpt_input_levent.milli <= e->milli) ) ) { - can_output = 1; - return 1; /* can output on this event */ - } - } - - if (chkpt_input_levent.sec == e->sec && - chkpt_input_levent.milli == e->milli && - chkpt_input_levent.serial == e->serial && - chkpt_input_levent.type == e->type ) { - - /* So far a match, so now check the nodes */ - if (chkpt_input_levent.node == NULL && e->node == NULL) { - can_output = 1; - return 2; /* output after this event */ - } - if (chkpt_input_levent.node && e->node && - (strcmp(chkpt_input_levent.node, e->node) == 0) ) { - can_output = 1; - return 2; /* output after this event */ - } - /* - * The nodes are different. Drop through to further checks. - */ - } - /* - * If the event we are looking at is more than MAX_EVENT_DELTA_SECS - * seconds past our checkpoint event, then by definition we should - * have had a complete event (ie a complete event is one where at - * least MAX_EVENT_DELTA_SECS seconds have passed since it's last - * output record). - * This means there is a problem, for the recorded checkpoint event was - * the last complete event in the file when we last processed it. - * Normally we see this if the checkpoint is very old and the system - * has used the same inode again in an audit log file. - */ - if ( (chkpt_input_levent.sec < e->sec) && - ((e->sec - chkpt_input_levent.sec) > MAX_EVENT_DELTA_SECS) ) { -/* fprintf(stderr, "%s %lu.%03u:%lu vs %s %lu.%03u:%lu\n", - chkpt_input_levent.host ? chkpt_input_levent.host : "-", - chkpt_input_levent.sec, chkpt_input_levent.milli, - chkpt_input_levent.serial, - e->host, e->sec, e->milli, e->serial); */ - return 3; - } - - return 0; -} - -static int process_log_fd(void) -{ - llist *entries; // entries in a record - int ret; - int do_output = 1; - - /* For each record in file */ - do { - ret = get_record(&entries); - if ((ret != 0)||(entries->cnt == 0)) { - break; - } - /* - * We flush all events on the last log file being processed. - * Thus incomplete events are 'carried forward' to be - * completed from the rest of it's records we expect to find - * in the next file we are about to process. - */ - if (match(entries)) { - /* - * If we are checkpointing, decide if we output - * this event - */ - if (checkpt_filename) - do_output = chkpt_output_decision(&entries->e); - - if (do_output == 1) { - found = 1; - output_record(entries); - - /* Remember this event if checkpointing */ - if (checkpt_filename) { - if (set_ChkPtLastEvent(&entries->e)) { - list_clear(entries); - free(entries); - fclose(log_fd); - return 4; /* no memory */ - } - } - } else if (do_output == 3) { - fprintf(stderr, - "Corrupted checkpoint file. Inode match, but newer complete event (%lu.%03u:%lu) found before loaded checkpoint %lu.%03u:%lu\n", - entries->e.sec, entries->e.milli, - entries->e.serial, - chkpt_input_levent.sec, - chkpt_input_levent.milli, - chkpt_input_levent.serial); - checkpt_failure |= CP_CORRUPTED; - list_clear(entries); - free(entries); - fclose(log_fd); - return 10; - } - if (just_one) { - list_clear(entries); - free(entries); - break; - } - if (line_buffered) - fflush(stdout); - } - list_clear(entries); - free(entries); - } while (ret == 0); - fclose(log_fd); - - return 0; -} - -static void alarm_handler(int signal) -{ - /* will interrupt current syscall */ -} - -static int process_stdin(void) -{ - log_fd = stdin; - input_is_pipe=1; - - if (signal(SIGALRM, alarm_handler) == SIG_ERR || - siginterrupt(SIGALRM, 1) == -1) - return -1; - - return process_log_fd(); -} - -static int process_file(char *filename) -{ - log_fd = fopen(filename, "rm"); - if (log_fd == NULL) { - fprintf(stderr, "Error opening %s (%s)\n", filename, - strerror(errno)); - return 1; - } - - __fsetlocking(log_fd, FSETLOCKING_BYCALLER); - return process_log_fd(); -} - -/* - * This function returns a malloc'd buffer of the next record in the audit - * logs. It returns 0 on success, 1 on eof, -1 on error. - */ -static int get_record(llist **l) -{ - char *rc; - char *buff = NULL; - int rcount = 0, timer_running = 0; - - /* - * If we have any events ready to print ie have all records that - * make up the event, we just return. If not, we read more lines - * from the files until we get a complete event or finish reading - * input - */ - *l = get_ready_event(&lo); - if (*l) - return 0; - - while (1) { - rcount++; - - if (!buff) { - buff = malloc(MAX_AUDIT_MESSAGE_LENGTH); - if (!buff) - return -1; - } - - if (input_is_pipe && rcount > 1) { - timer_running = 1; - alarm(timeout_interval); - } - - rc = fgets_unlocked(buff, MAX_AUDIT_MESSAGE_LENGTH, - log_fd); - - if (timer_running) { - /* timer may have fired but thats ok */ - timer_running = 0; - alarm(0); - } - - if (rc) { - if (lol_add_record(&lo, buff)) { - *l = get_ready_event(&lo); - if (*l) - break; - } - } else { - free(buff); - /* - * If we get an EINTR error or we are at EOF, we check - * to see if we have any events to print and return - * appropriately. If we are the last file being - * processed, we mark all incomplete events as - * complete so they will be printed. - */ - if ((ferror_unlocked(log_fd) && - errno == EINTR) || feof_unlocked(log_fd)) { - /* - * Only mark all events as L_COMPLETE if we are - * the last file being processed. - * We DO NOT do this if we are checkpointing. - */ - if (files_to_process == 0) { - if (!checkpt_filename) - terminate_all_events(&lo); - } - *l = get_ready_event(&lo); - if (*l) - return 0; - else - return 1; - } else - return -1; /* all other errors are terminal */ - } - } - free(buff); - return 0; -} - diff --git a/framework/src/audit/src/autrace.c b/framework/src/audit/src/autrace.c deleted file mode 100644 index 03c0b556..00000000 --- a/framework/src/audit/src/autrace.c +++ /dev/null @@ -1,329 +0,0 @@ -/* autrace.c -- - * Copyright 2005-09,2011,2015 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - */ - -#include "config.h" -#include <stdio.h> -#include <string.h> -#include <sys/wait.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdlib.h> -#include <errno.h> -#include <time.h> -#include <linux/net.h> -#include "libaudit.h" -#include "private.h" - -/* - * This program will add the audit rules to trace a process similar - * to strace. It will then execute the process. - */ -static int threat = 0; -static int count_rules(void); -static int count_em(int fd); -extern int delete_all_rules(int fd); - -static void usage(void) -{ - fprintf(stderr, "usage: autrace [-r] program\n"); -} - -static int insert_rule(int audit_fd, const char *field) -{ - int rc; - int flags = AUDIT_FILTER_EXIT; - int action = AUDIT_ALWAYS; - struct audit_rule_data *rule = malloc(sizeof(struct audit_rule_data)); - int machine = audit_detect_machine(); - char *t_field = NULL; - - if (rule == NULL) - goto err; - memset(rule, 0, sizeof(struct audit_rule_data)); - if (threat) { - rc = 0; - if (machine != MACH_AARCH64) { - rc |= audit_rule_syscallbyname_data(rule, "open"); - rc |= audit_rule_syscallbyname_data(rule, "creat"); - rc |= audit_rule_syscallbyname_data(rule, "rename"); - rc |= audit_rule_syscallbyname_data(rule, "unlink"); - rc |= audit_rule_syscallbyname_data(rule, "mknod"); - rc |= audit_rule_syscallbyname_data(rule, "mkdir"); - rc |= audit_rule_syscallbyname_data(rule, "rmdir"); - rc |= audit_rule_syscallbyname_data(rule, "chown"); - rc |= audit_rule_syscallbyname_data(rule, "lchown"); - rc |= audit_rule_syscallbyname_data(rule, "chmod"); - rc |= audit_rule_syscallbyname_data(rule, "link"); - rc |= audit_rule_syscallbyname_data(rule, "symlink"); - rc |= audit_rule_syscallbyname_data(rule, "readlink"); - } - rc |= audit_rule_syscallbyname_data(rule, "openat"); - rc |= audit_rule_syscallbyname_data(rule, "truncate"); - rc |= audit_rule_syscallbyname_data(rule, "renameat"); - rc |= audit_rule_syscallbyname_data(rule, "unlinkat"); - rc |= audit_rule_syscallbyname_data(rule, "mknodat"); - rc |= audit_rule_syscallbyname_data(rule, "mkdirat"); - rc |= audit_rule_syscallbyname_data(rule, "chdir"); - rc |= audit_rule_syscallbyname_data(rule, "fchownat"); - rc |= audit_rule_syscallbyname_data(rule, "fchmodat"); - rc |= audit_rule_syscallbyname_data(rule, "linkat"); - rc |= audit_rule_syscallbyname_data(rule, "symlinkat"); - rc |= audit_rule_syscallbyname_data(rule, "readlinkat"); - rc |= audit_rule_syscallbyname_data(rule, "execve"); - rc |= audit_rule_syscallbyname_data(rule, "name_to_handle_at"); - - if (machine != MACH_X86 && machine != MACH_S390X && - machine != MACH_S390) { - rc |= audit_rule_syscallbyname_data(rule, "connect"); - rc |= audit_rule_syscallbyname_data(rule, "bind"); - rc |= audit_rule_syscallbyname_data(rule, "accept"); - rc |= audit_rule_syscallbyname_data(rule, "sendto"); - rc |= audit_rule_syscallbyname_data(rule, "recvfrom"); - rc |= audit_rule_syscallbyname_data(rule, "accept4"); - } - - rc |= audit_rule_syscallbyname_data(rule, "sendfile"); - } else - rc = audit_rule_syscallbyname_data(rule, "all"); - if (rc < 0) - goto err; - t_field = strdup(field); - rc = audit_rule_fieldpair_data(&rule, t_field, flags); - free(t_field); - if (rc < 0) - goto err; - rc = audit_add_rule_data(audit_fd, rule, flags, action); - if (rc < 0) - goto err; - - // Now if i386, lets add its network rules - if (machine == MACH_X86 || machine == MACH_S390X || - machine == MACH_S390) { - int i, a0[6] = { SYS_CONNECT, SYS_BIND, SYS_ACCEPT, SYS_SENDTO, - SYS_RECVFROM, SYS_ACCEPT4 }; - for (i=0; i<6; i++) { - char pair[32]; - - memset(rule, 0, sizeof(struct audit_rule_data)); - rc |= audit_rule_syscallbyname_data(rule, "socketcall"); - snprintf(pair, sizeof(pair), "a0=%d", a0[i]); - rc |= audit_rule_fieldpair_data(&rule, pair, flags); - t_field = strdup(field); - rc |= audit_rule_fieldpair_data(&rule, t_field, flags); - free(t_field); - rc |= audit_add_rule_data(audit_fd, rule, flags, action); - } - } - free(rule); - return 0; -err: - fprintf(stderr, "Error inserting audit rule for %s\n", field); - free(rule); - return 1; -} - -int key_match(struct audit_reply *rep) -{ - return 1; -} - -/* - * Algorithm: - * check that user is root - * check to see if program exists - * if so fork, child waits for parent - * parent clears audit rules, loads audit all syscalls with child's pid - * parent tells child to go & waits for sigchld - * child exec's program - * parent deletes rules after getting sigchld - */ -int main(int argc, char *argv[]) -{ - int fd[2]; - int pid,cmd=1; - char buf[2]; - - if (argc < 2) { - usage(); - return 1; - } - if (strcmp(argv[cmd], "-h") == 0) { - usage(); - return 1; - } - if (strcmp(argv[cmd], "-r") == 0) { - threat = 1; - cmd++; - } - if (getuid() != 0) { - fprintf(stderr, "You must be root to run this program.\n"); - return 1; - } - if (access(argv[cmd], X_OK)) { - if (errno == ENOENT) - fprintf(stderr, "Error - can't find: %s\n", argv[cmd]); - else - fprintf(stderr, "Error checking %s (%s)\n", - argv[cmd], strerror(errno)); - return 1; - } - set_aumessage_mode(MSG_STDERR, DBG_NO); - switch (count_rules()) - { - case -1: - if (errno == ECONNREFUSED) - fprintf(stderr, - "The audit system is disabled\n"); - else - fprintf(stderr, - "Error - can't get rule count.\n"); - return 1; - case 0: - break; - default: - fprintf(stderr, - "autrace cannot be run with rules loaded.\n" - "Please delete all rules using 'auditctl -D' if you " - "really wanted to\nrun this command.\n"); - return 1; - } - if (pipe(fd) != 0) { - fprintf(stderr, "Error creating pipe.\n"); - return 1; - } - - switch ((pid=fork())) - { - case -1: - fprintf(stderr, "Error forking.\n"); - return 1; - case 0: /* Child */ - close(fd[1]); - printf("Waiting to execute: %s\n", argv[cmd]); - while (read(fd[0], buf, 1) == -1 && errno == EINTR) - /* blank */ ; - close(fd[0]); - execvp(argv[cmd], &argv[cmd]); - fprintf(stderr, "Failed to exec %s\n", argv[cmd]); - return 1; - default: /* Parent */ - close(fd[0]); - fcntl(fd[1], F_SETFD, FD_CLOEXEC); - { - char field[16]; - int audit_fd; - audit_fd = audit_open(); - if (audit_fd < 0) - exit(1); - snprintf(field, sizeof(field), "pid=%d", pid); - if (insert_rule(audit_fd, field)) { - kill(pid,SIGTERM); - (void)delete_all_rules(audit_fd); - exit(1); - } - snprintf(field, sizeof(field), "ppid=%d", pid); - if (insert_rule(audit_fd, field)) { - kill(pid,SIGTERM); - (void)delete_all_rules(audit_fd); - exit(1); - } - sleep(1); - if (write(fd[1],"1", 1) != 1) { - kill(pid,SIGTERM); - (void)delete_all_rules(audit_fd); - exit(1); - } - waitpid(pid, NULL, 0); - close(fd[1]); - puts("Cleaning up..."); - (void)delete_all_rules(audit_fd); - close(audit_fd); - } - printf("Trace complete. " - "You can locate the records with " - "\'ausearch -i -p %d\'\n", - pid); - break; - } - - return 0; -} - -static int count_rules(void) -{ - int fd, total, rc; - - fd = audit_open(); - if (fd < 0) - return -1; - - rc = audit_request_rules_list_data(fd); - if (rc > 0) - total = count_em(fd); - else - total = -1; - - close(fd); - return total; -} - -static int count_em(int fd) -{ - int i, retval, count = 0; - int timeout = 40; /* loop has delay of .1 - this is 4 seconds */ - struct audit_reply rep; - fd_set read_mask; - - FD_ZERO(&read_mask); - FD_SET(fd, &read_mask); - - for (i = 0; i < timeout; i++) { - retval = audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0); - if (retval > 0) { - struct timeval t; - - if (rep.type == NLMSG_ERROR && - rep.error->error == 0) - continue; - t.tv_sec = 0; - t.tv_usec = 100000; /* .1 second */ - do { - retval=select(fd+1, &read_mask, NULL, NULL, &t); - } while (retval < 0 && errno == EINTR); - switch (rep.type) - { - case NLMSG_DONE: - return count; - case AUDIT_LIST_RULES: - i = 0; - count++; - break; - case NLMSG_ERROR: - return -1; - default: - break; - } - } - } - return count; -} - diff --git a/framework/src/audit/src/delete_all.c b/framework/src/audit/src/delete_all.c deleted file mode 100644 index 4e0feed1..00000000 --- a/framework/src/audit/src/delete_all.c +++ /dev/null @@ -1,109 +0,0 @@ -/* delete_all.c -- - * Copyright 2005-06, 2008-09,2014 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: - * Steve Grubb <sgrubb@redhat.com> - */ -#include "config.h" -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "libaudit.h" -#include "private.h" - -#include "auditctl-llist.h" - -extern int key_match(const struct audit_rule_data *r); - -/* Returns 0 for success and -1 for failure */ -int delete_all_rules(int fd) -{ - int seq, i, rc; - int timeout = 40; /* tenths of seconds */ - struct audit_reply rep; - fd_set read_mask; - llist l; - lnode *n; - - /* list the rules */ - seq = audit_request_rules_list_data(fd); - if (seq <= 0) - return -1; - - FD_ZERO(&read_mask); - FD_SET(fd, &read_mask); - list_create(&l); - - for (i = 0; i < timeout; i++) { - struct timeval t; - - t.tv_sec = 0; - t.tv_usec = 100000; /* .1 second */ - do { - rc = select(fd+1, &read_mask, NULL, NULL, &t); - } while (rc < 0 && errno == EINTR); - // We'll try to read just in case - rc = audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0); - if (rc > 0) { - /* Reset timeout */ - i = 0; - - /* Don't make decisions based on wrong packet */ - if (rep.nlh->nlmsg_seq != seq) - continue; - - /* If we get done or error, break out */ - if (rep.type == NLMSG_DONE) - break; - - if (rep.type == NLMSG_ERROR && rep.error->error) { - audit_msg(LOG_ERR, - "Error receiving rules list (%s)", - strerror(-rep.error->error)); - return -1; - } - - /* If its not what we are expecting, keep looping */ - if (rep.type != AUDIT_LIST_RULES) - continue; - - if (key_match(rep.ruledata)) - list_append(&l, rep.ruledata, - sizeof(struct audit_rule_data) + - rep.ruledata->buflen); - - } - } - list_first(&l); - n = l.cur; - while (n) { - /* Bounce it right back with delete */ - rc = audit_send(fd, AUDIT_DEL_RULE, n->r, n->size); - if (rc < 0) { - audit_msg(LOG_ERR, "Error deleting rule (%s)", - strerror(-rc)); - return -1; - } - n = list_next(&l); - } - list_clear(&l); - - return 0; -} - diff --git a/framework/src/audit/src/libev/Makefile.am b/framework/src/audit/src/libev/Makefile.am deleted file mode 100644 index a35e7b0d..00000000 --- a/framework/src/audit/src/libev/Makefile.am +++ /dev/null @@ -1,29 +0,0 @@ -# Makefile.am-- -# Copyright 2008,2011-12 Red Hat Inc., Durham, North Carolina. -# All Rights Reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Authors: -# Steve Grubb <sgrubb@redhat.com> -# -VERSION_INFO = 4:0:0 -EXTRA_DIST = README ev_epoll.c ev_poll.c ev_select.c libev.m4 -AM_CFLAGS = -fPIC -DPIC -g -fno-strict-aliasing ${DEBUG} - -noinst_HEADERS = ev.h ev_vars.h ev_wrap.h event.h -noinst_LIBRARIES = libev.a - -libev_a_SOURCES = ev.c event.c diff --git a/framework/src/audit/src/libev/README b/framework/src/audit/src/libev/README deleted file mode 100644 index 31f61938..00000000 --- a/framework/src/audit/src/libev/README +++ /dev/null @@ -1,58 +0,0 @@ -libev is a high-performance event loop/event model with lots of features. -(see benchmark at http://libev.schmorp.de/bench.html) - - -ABOUT - - Homepage: http://software.schmorp.de/pkg/libev - Mailinglist: libev@lists.schmorp.de - http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev - Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod - - Libev is modelled (very losely) after libevent and the Event perl - module, but is faster, scales better and is more correct, and also more - featureful. And also smaller. Yay. - - Some of the specialties of libev not commonly found elsewhere are: - - - extensive and detailed, readable documentation (not doxygen garbage). - - fully supports fork, can detect fork in various ways and automatically - re-arms kernel mechanisms that do not support fork. - - highly optimised select, poll, epoll, kqueue and event ports backends. - - filesystem object (path) watching (with optional linux inotify support). - - wallclock-based times (using absolute time, cron-like). - - relative timers/timeouts (handle time jumps). - - fast intra-thread communication between multiple - event loops (with optional fast linux eventfd backend). - - extremely easy to embed (fully documented, no dependencies, - autoconf supported but optional). - - very small codebase, no bloated library, simple code. - - fully extensible by being able to plug into the event loop, - integrate other event loops, integrate other event loop users. - - very little memory use (small watchers, small event loop data). - - optional C++ interface allowing method and function callbacks - at no extra memory or runtime overhead. - - optional Perl interface with similar characteristics (capable - of running Glib/Gtk2 on libev). - - support for other languages (multiple C++ interfaces, D, Ruby, - Python) available from third-parties. - - Examples of programs that embed libev: the EV perl module, node.js, - auditd, rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the - Deliantra MMORPG server (http://www.deliantra.net/), Rubinius (a - next-generation Ruby VM), the Ebb web server, the Rev event toolkit. - - -CONTRIBUTORS - - libev was written and designed by Marc Lehmann and Emanuele Giaquinta. - - The following people sent in patches or made other noteworthy - contributions to the design (for minor patches, see the Changes - file. If I forgot to include you, please shout at me, it was an - accident): - - W.C.A. Wijngaards - Christopher Layne - Chris Brody - diff --git a/framework/src/audit/src/libev/ev.c b/framework/src/audit/src/libev/ev.c deleted file mode 100644 index 3e7013f9..00000000 --- a/framework/src/audit/src/libev/ev.c +++ /dev/null @@ -1,4971 +0,0 @@ -/* - * libev event processing core, watcher management - * - * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -/* this big block deduces configuration from config.h */ -#ifndef EV_STANDALONE -# ifdef EV_CONFIG_H -# include EV_CONFIG_H -# else -# include "config.h" -# endif - -# if HAVE_FLOOR -# ifndef EV_USE_FLOOR -# define EV_USE_FLOOR 1 -# endif -# endif - -# if HAVE_CLOCK_SYSCALL -# ifndef EV_USE_CLOCK_SYSCALL -# define EV_USE_CLOCK_SYSCALL 1 -# ifndef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -# endif -# ifndef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 1 -# endif -# endif -# elif !defined EV_USE_CLOCK_SYSCALL -# define EV_USE_CLOCK_SYSCALL 0 -# endif - -# if HAVE_CLOCK_GETTIME -# ifndef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 1 -# endif -# ifndef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -# endif -# else -# ifndef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 0 -# endif -# ifndef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -# endif -# endif - -# if HAVE_NANOSLEEP -# ifndef EV_USE_NANOSLEEP -# define EV_USE_NANOSLEEP EV_FEATURE_OS -# endif -# else -# undef EV_USE_NANOSLEEP -# define EV_USE_NANOSLEEP 0 -# endif - -# if HAVE_SELECT && HAVE_SYS_SELECT_H -# ifndef EV_USE_SELECT -# define EV_USE_SELECT EV_FEATURE_BACKENDS -# endif -# else -# undef EV_USE_SELECT -# define EV_USE_SELECT 0 -# endif - -# if HAVE_POLL && HAVE_POLL_H -# ifndef EV_USE_POLL -# define EV_USE_POLL EV_FEATURE_BACKENDS -# endif -# else -# undef EV_USE_POLL -# define EV_USE_POLL 0 -# endif - -# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H -# ifndef EV_USE_EPOLL -# define EV_USE_EPOLL EV_FEATURE_BACKENDS -# endif -# else -# undef EV_USE_EPOLL -# define EV_USE_EPOLL 0 -# endif - -# if HAVE_KQUEUE && HAVE_SYS_EVENT_H -# ifndef EV_USE_KQUEUE -# define EV_USE_KQUEUE EV_FEATURE_BACKENDS -# endif -# else -# undef EV_USE_KQUEUE -# define EV_USE_KQUEUE 0 -# endif - -# if HAVE_PORT_H && HAVE_PORT_CREATE -# ifndef EV_USE_PORT -# define EV_USE_PORT EV_FEATURE_BACKENDS -# endif -# else -# undef EV_USE_PORT -# define EV_USE_PORT 0 -# endif - -# if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H -# ifndef EV_USE_INOTIFY -# define EV_USE_INOTIFY EV_FEATURE_OS -# endif -# else -# undef EV_USE_INOTIFY -# define EV_USE_INOTIFY 0 -# endif - -# if HAVE_SIGNALFD && HAVE_SYS_SIGNALFD_H -# ifndef EV_USE_SIGNALFD -# define EV_USE_SIGNALFD EV_FEATURE_OS -# endif -# else -# undef EV_USE_SIGNALFD -# define EV_USE_SIGNALFD 0 -# endif - -# if HAVE_EVENTFD -# ifndef EV_USE_EVENTFD -# define EV_USE_EVENTFD EV_FEATURE_OS -# endif -# else -# undef EV_USE_EVENTFD -# define EV_USE_EVENTFD 0 -# endif - -#endif - -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <stddef.h> - -#include <stdio.h> - -#include <assert.h> -#include <errno.h> -#include <sys/types.h> -#include <time.h> -#include <limits.h> - -#include <signal.h> - -#ifdef EV_H -# include EV_H -#else -# include "ev.h" -#endif - -#if EV_NO_THREADS -# undef EV_NO_SMP -# define EV_NO_SMP 1 -# undef ECB_NO_THREADS -# define ECB_NO_THREADS 1 -#endif -#if EV_NO_SMP -# undef EV_NO_SMP -# define ECB_NO_SMP 1 -#endif - -#ifndef _WIN32 -# include <sys/time.h> -# include <sys/wait.h> -# include <unistd.h> -#else -# include <io.h> -# define WIN32_LEAN_AND_MEAN -# include <winsock2.h> -# include <windows.h> -# ifndef EV_SELECT_IS_WINSOCKET -# define EV_SELECT_IS_WINSOCKET 1 -# endif -# undef EV_AVOID_STDIO -#endif - -/* OS X, in its infinite idiocy, actually HARDCODES - * a limit of 1024 into their select. Where people have brains, - * OS X engineers apparently have a vacuum. Or maybe they were - * ordered to have a vacuum, or they do anything for money. - * This might help. Or not. - */ -#define _DARWIN_UNLIMITED_SELECT 1 - -/* this block tries to deduce configuration from header-defined symbols and defaults */ - -/* try to deduce the maximum number of signals on this platform */ -#if defined EV_NSIG -/* use what's provided */ -#elif defined NSIG -# define EV_NSIG (NSIG) -#elif defined _NSIG -# define EV_NSIG (_NSIG) -#elif defined SIGMAX -# define EV_NSIG (SIGMAX+1) -#elif defined SIG_MAX -# define EV_NSIG (SIG_MAX+1) -#elif defined _SIG_MAX -# define EV_NSIG (_SIG_MAX+1) -#elif defined MAXSIG -# define EV_NSIG (MAXSIG+1) -#elif defined MAX_SIG -# define EV_NSIG (MAX_SIG+1) -#elif defined SIGARRAYSIZE -# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */ -#elif defined _sys_nsig -# define EV_NSIG (_sys_nsig) /* Solaris 2.5 */ -#else -# define EV_NSIG (8 * sizeof (sigset_t) + 1) -#endif - -#ifndef EV_USE_FLOOR -# define EV_USE_FLOOR 0 -#endif - -#ifndef EV_USE_CLOCK_SYSCALL -# if __linux && __GLIBC__ == 2 && __GLIBC_MINOR__ < 17 -# define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS -# else -# define EV_USE_CLOCK_SYSCALL 0 -# endif -#endif - -#if !(_POSIX_TIMERS > 0) -# ifndef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 0 -# endif -# ifndef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -# endif -#endif - -#ifndef EV_USE_MONOTONIC -# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0 -# define EV_USE_MONOTONIC EV_FEATURE_OS -# else -# define EV_USE_MONOTONIC 0 -# endif -#endif - -#ifndef EV_USE_REALTIME -# define EV_USE_REALTIME !EV_USE_CLOCK_SYSCALL -#endif - -#ifndef EV_USE_NANOSLEEP -# if _POSIX_C_SOURCE >= 199309L -# define EV_USE_NANOSLEEP EV_FEATURE_OS -# else -# define EV_USE_NANOSLEEP 0 -# endif -#endif - -#ifndef EV_USE_SELECT -# define EV_USE_SELECT EV_FEATURE_BACKENDS -#endif - -#ifndef EV_USE_POLL -# ifdef _WIN32 -# define EV_USE_POLL 0 -# else -# define EV_USE_POLL EV_FEATURE_BACKENDS -# endif -#endif - -#ifndef EV_USE_EPOLL -# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4)) -# define EV_USE_EPOLL EV_FEATURE_BACKENDS -# else -# define EV_USE_EPOLL 0 -# endif -#endif - -#ifndef EV_USE_KQUEUE -# define EV_USE_KQUEUE 0 -#endif - -#ifndef EV_USE_PORT -# define EV_USE_PORT 0 -#endif - -#ifndef EV_USE_INOTIFY -# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4)) -# define EV_USE_INOTIFY EV_FEATURE_OS -# else -# define EV_USE_INOTIFY 0 -# endif -#endif - -#ifndef EV_PID_HASHSIZE -# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1 -#endif - -#ifndef EV_INOTIFY_HASHSIZE -# define EV_INOTIFY_HASHSIZE EV_FEATURE_DATA ? 16 : 1 -#endif - -#ifndef EV_USE_EVENTFD -# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)) -# define EV_USE_EVENTFD EV_FEATURE_OS -# else -# define EV_USE_EVENTFD 0 -# endif -#endif - -#ifndef EV_USE_SIGNALFD -# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)) -# define EV_USE_SIGNALFD EV_FEATURE_OS -# else -# define EV_USE_SIGNALFD 0 -# endif -#endif - -#if 0 /* debugging */ -# define EV_VERIFY 3 -# define EV_USE_4HEAP 1 -# define EV_HEAP_CACHE_AT 1 -#endif - -#ifndef EV_VERIFY -# define EV_VERIFY (EV_FEATURE_API ? 1 : 0) -#endif - -#ifndef EV_USE_4HEAP -# define EV_USE_4HEAP EV_FEATURE_DATA -#endif - -#ifndef EV_HEAP_CACHE_AT -# define EV_HEAP_CACHE_AT EV_FEATURE_DATA -#endif - -#ifdef ANDROID -/* supposedly, android doesn't typedef fd_mask */ -# undef EV_USE_SELECT -# define EV_USE_SELECT 0 -/* supposedly, we need to include syscall.h, not sys/syscall.h, so just disable */ -# undef EV_USE_CLOCK_SYSCALL -# define EV_USE_CLOCK_SYSCALL 0 -#endif - -/* aix's poll.h seems to cause lots of trouble */ -#ifdef _AIX -/* AIX has a completely broken poll.h header */ -# undef EV_USE_POLL -# define EV_USE_POLL 0 -#endif - -/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */ -/* which makes programs even slower. might work on other unices, too. */ -#if EV_USE_CLOCK_SYSCALL -# include <sys/syscall.h> -# ifdef SYS_clock_gettime -# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts)) -# undef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 1 -# else -# undef EV_USE_CLOCK_SYSCALL -# define EV_USE_CLOCK_SYSCALL 0 -# endif -#endif - -/* this block fixes any misconfiguration where we know we run into trouble otherwise */ - -#ifndef CLOCK_MONOTONIC -# undef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 0 -#endif - -#ifndef CLOCK_REALTIME -# undef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -#endif - -#if !EV_STAT_ENABLE -# undef EV_USE_INOTIFY -# define EV_USE_INOTIFY 0 -#endif - -#if !EV_USE_NANOSLEEP -/* hp-ux has it in sys/time.h, which we unconditionally include above */ -# if !defined _WIN32 && !defined __hpux -# include <sys/select.h> -# endif -#endif - -#if EV_USE_INOTIFY -# include <sys/statfs.h> -# include <sys/inotify.h> -/* some very old inotify.h headers don't have IN_DONT_FOLLOW */ -# ifndef IN_DONT_FOLLOW -# undef EV_USE_INOTIFY -# define EV_USE_INOTIFY 0 -# endif -#endif - -#if EV_USE_EVENTFD -/* our minimum requirement is glibc 2.7 which has the stub, but not the header */ -# include <stdint.h> -# ifndef EFD_NONBLOCK -# define EFD_NONBLOCK O_NONBLOCK -# endif -# ifndef EFD_CLOEXEC -# ifdef O_CLOEXEC -# define EFD_CLOEXEC O_CLOEXEC -# else -# define EFD_CLOEXEC 02000000 -# endif -# endif -EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags); -#endif - -#if EV_USE_SIGNALFD -/* our minimum requirement is glibc 2.7 which has the stub, but not the header */ -# include <stdint.h> -# ifndef SFD_NONBLOCK -# define SFD_NONBLOCK O_NONBLOCK -# endif -# ifndef SFD_CLOEXEC -# ifdef O_CLOEXEC -# define SFD_CLOEXEC O_CLOEXEC -# else -# define SFD_CLOEXEC 02000000 -# endif -# endif -EV_CPP (extern "C") int signalfd (int fd, const sigset_t *mask, int flags); - -struct signalfd_siginfo -{ - uint32_t ssi_signo; - char pad[128 - sizeof (uint32_t)]; -}; -#endif - -/**/ - -#if EV_VERIFY >= 3 -# define EV_FREQUENT_CHECK ev_verify (EV_A) -#else -# define EV_FREQUENT_CHECK do { } while (0) -#endif - -/* - * This is used to work around floating point rounding problems. - * This value is good at least till the year 4000. - */ -#define MIN_INTERVAL 0.0001220703125 /* 1/2**13, good till 4000 */ -/*#define MIN_INTERVAL 0.00000095367431640625 * 1/2**20, good till 2200 */ - -#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ -#define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */ - -#define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0) -#define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0) - -/* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */ -/* ECB.H BEGIN */ -/* - * libecb - http://software.schmorp.de/pkg/libecb - * - * Copyright (©) 2009-2015 Marc Alexander Lehmann <libecb@schmorp.de> - * Copyright (©) 2011 Emanuele Giaquinta - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#ifndef ECB_H -#define ECB_H - -/* 16 bits major, 16 bits minor */ -#define ECB_VERSION 0x00010004 - -#ifdef _WIN32 - typedef signed char int8_t; - typedef unsigned char uint8_t; - typedef signed short int16_t; - typedef unsigned short uint16_t; - typedef signed int int32_t; - typedef unsigned int uint32_t; - #if __GNUC__ - typedef signed long long int64_t; - typedef unsigned long long uint64_t; - #else /* _MSC_VER || __BORLANDC__ */ - typedef signed __int64 int64_t; - typedef unsigned __int64 uint64_t; - #endif - #ifdef _WIN64 - #define ECB_PTRSIZE 8 - typedef uint64_t uintptr_t; - typedef int64_t intptr_t; - #else - #define ECB_PTRSIZE 4 - typedef uint32_t uintptr_t; - typedef int32_t intptr_t; - #endif -#else - #include <inttypes.h> - #if UINTMAX_MAX > 0xffffffffU - #define ECB_PTRSIZE 8 - #else - #define ECB_PTRSIZE 4 - #endif -#endif - -#define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__) -#define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64) - -/* work around x32 idiocy by defining proper macros */ -#if ECB_GCC_AMD64 || ECB_MSVC_AMD64 - #if _ILP32 - #define ECB_AMD64_X32 1 - #else - #define ECB_AMD64 1 - #endif -#endif - -/* many compilers define _GNUC_ to some versions but then only implement - * what their idiot authors think are the "more important" extensions, - * causing enormous grief in return for some better fake benchmark numbers. - * or so. - * we try to detect these and simply assume they are not gcc - if they have - * an issue with that they should have done it right in the first place. - */ -#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__ - #define ECB_GCC_VERSION(major,minor) 0 -#else - #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) -#endif - -#define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor))) - -#if __clang__ && defined __has_builtin - #define ECB_CLANG_BUILTIN(x) __has_builtin (x) -#else - #define ECB_CLANG_BUILTIN(x) 0 -#endif - -#if __clang__ && defined __has_extension - #define ECB_CLANG_EXTENSION(x) __has_extension (x) -#else - #define ECB_CLANG_EXTENSION(x) 0 -#endif - -#define ECB_CPP (__cplusplus+0) -#define ECB_CPP11 (__cplusplus >= 201103L) - -#if ECB_CPP - #define ECB_C 0 - #define ECB_STDC_VERSION 0 -#else - #define ECB_C 1 - #define ECB_STDC_VERSION __STDC_VERSION__ -#endif - -#define ECB_C99 (ECB_STDC_VERSION >= 199901L) -#define ECB_C11 (ECB_STDC_VERSION >= 201112L) - -#if ECB_CPP - #define ECB_EXTERN_C extern "C" - #define ECB_EXTERN_C_BEG ECB_EXTERN_C { - #define ECB_EXTERN_C_END } -#else - #define ECB_EXTERN_C extern - #define ECB_EXTERN_C_BEG - #define ECB_EXTERN_C_END -#endif - -/*****************************************************************************/ - -/* ECB_NO_THREADS - ecb is not used by multiple threads, ever */ -/* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */ - -#if ECB_NO_THREADS - #define ECB_NO_SMP 1 -#endif - -#if ECB_NO_SMP - #define ECB_MEMORY_FENCE do { } while (0) -#endif - -/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */ -#if __xlC__ && ECB_CPP - #include <builtins.h> -#endif - -#ifndef ECB_MEMORY_FENCE - #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110 - #if __i386 || __i386__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory") - #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory") - #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("") - #elif ECB_GCC_AMD64 - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory") - #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory") - #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("") - #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory") - #elif defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ \ - || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory") - #elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \ - || defined __ARM_ARCH_7M__ || defined __ARM_ARCH_7R__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory") - #elif __aarch64__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb ish" : : : "memory") - #elif (__sparc || __sparc__) && !__sparcv8 - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory") - #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory") - #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore") - #elif defined __s390__ || defined __s390x__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("bcr 15,0" : : : "memory") - #elif defined __mips__ - /* GNU/Linux emulates sync on mips1 architectures, so we force its use */ - /* anybody else who still uses mips1 is supposed to send in their version, with detection code. */ - #define ECB_MEMORY_FENCE __asm__ __volatile__ (".set mips2; sync; .set mips0" : : : "memory") - #elif defined __alpha__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mb" : : : "memory") - #elif defined __hppa__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory") - #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("") - #elif defined __ia64__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mf" : : : "memory") - #elif defined __m68k__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory") - #elif defined __m88k__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("tb1 0,%%r0,128" : : : "memory") - #elif defined __sh__ - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory") - #endif - #endif -#endif - -#ifndef ECB_MEMORY_FENCE - #if ECB_GCC_VERSION(4,7) - /* see comment below (stdatomic.h) about the C11 memory model. */ - #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST) - #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE) - #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE) - - #elif ECB_CLANG_EXTENSION(c_atomic) - /* see comment below (stdatomic.h) about the C11 memory model. */ - #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST) - #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE) - #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE) - - #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ - #define ECB_MEMORY_FENCE __sync_synchronize () - #elif _MSC_VER >= 1500 /* VC++ 2008 */ - /* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */ - #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) - #define ECB_MEMORY_FENCE _ReadWriteBarrier (); MemoryBarrier() - #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */ - #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier() - #elif _MSC_VER >= 1400 /* VC++ 2005 */ - #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) - #define ECB_MEMORY_FENCE _ReadWriteBarrier () - #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */ - #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier () - #elif defined _WIN32 - #include <WinNT.h> - #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */ - #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110 - #include <mbarrier.h> - #define ECB_MEMORY_FENCE __machine_rw_barrier () - #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier () - #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier () - #elif __xlC__ - #define ECB_MEMORY_FENCE __sync () - #endif -#endif - -#ifndef ECB_MEMORY_FENCE - #if ECB_C11 && !defined __STDC_NO_ATOMICS__ - /* we assume that these memory fences work on all variables/all memory accesses, */ - /* not just C11 atomics and atomic accesses */ - #include <stdatomic.h> - /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */ - /* any fence other than seq_cst, which isn't very efficient for us. */ - /* Why that is, we don't know - either the C11 memory model is quite useless */ - /* for most usages, or gcc and clang have a bug */ - /* I *currently* lean towards the latter, and inefficiently implement */ - /* all three of ecb's fences as a seq_cst fence */ - /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */ - /* for all __atomic_thread_fence's except seq_cst */ - #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) - #endif -#endif - -#ifndef ECB_MEMORY_FENCE - #if !ECB_AVOID_PTHREADS - /* - * if you get undefined symbol references to pthread_mutex_lock, - * or failure to find pthread.h, then you should implement - * the ECB_MEMORY_FENCE operations for your cpu/compiler - * OR provide pthread.h and link against the posix thread library - * of your system. - */ - #include <pthread.h> - #define ECB_NEEDS_PTHREADS 1 - #define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1 - - static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER; - #define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0) - #endif -#endif - -#if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE - #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE -#endif - -#if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE - #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE -#endif - -/*****************************************************************************/ - -#if ECB_CPP - #define ecb_inline static inline -#elif ECB_GCC_VERSION(2,5) - #define ecb_inline static __inline__ -#elif ECB_C99 - #define ecb_inline static inline -#else - #define ecb_inline static -#endif - -#if ECB_GCC_VERSION(3,3) - #define ecb_restrict __restrict__ -#elif ECB_C99 - #define ecb_restrict restrict -#else - #define ecb_restrict -#endif - -typedef int ecb_bool; - -#define ECB_CONCAT_(a, b) a ## b -#define ECB_CONCAT(a, b) ECB_CONCAT_(a, b) -#define ECB_STRINGIFY_(a) # a -#define ECB_STRINGIFY(a) ECB_STRINGIFY_(a) -#define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr)) - -#define ecb_function_ ecb_inline - -#if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8) - #define ecb_attribute(attrlist) __attribute__ (attrlist) -#else - #define ecb_attribute(attrlist) -#endif - -#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_constant_p) - #define ecb_is_constant(expr) __builtin_constant_p (expr) -#else - /* possible C11 impl for integral types - typedef struct ecb_is_constant_struct ecb_is_constant_struct; - #define ecb_is_constant(expr) _Generic ((1 ? (struct ecb_is_constant_struct *)0 : (void *)((expr) - (expr)), ecb_is_constant_struct *: 0, default: 1)) */ - - #define ecb_is_constant(expr) 0 -#endif - -#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_expect) - #define ecb_expect(expr,value) __builtin_expect ((expr),(value)) -#else - #define ecb_expect(expr,value) (expr) -#endif - -#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_prefetch) - #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality) -#else - #define ecb_prefetch(addr,rw,locality) -#endif - -/* no emulation for ecb_decltype */ -#if ECB_CPP11 - // older implementations might have problems with decltype(x)::type, work around it - template<class T> struct ecb_decltype_t { typedef T type; }; - #define ecb_decltype(x) ecb_decltype_t<decltype (x)>::type -#elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8) - #define ecb_decltype(x) __typeof__ (x) -#endif - -#if _MSC_VER >= 1300 - #define ecb_deprecated __declspec (deprecated) -#else - #define ecb_deprecated ecb_attribute ((__deprecated__)) -#endif - -#if _MSC_VER >= 1500 - #define ecb_deprecated_message(msg) __declspec (deprecated (msg)) -#elif ECB_GCC_VERSION(4,5) - #define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg)) -#else - #define ecb_deprecated_message(msg) ecb_deprecated -#endif - -#if _MSC_VER >= 1400 - #define ecb_noinline __declspec (noinline) -#else - #define ecb_noinline ecb_attribute ((__noinline__)) -#endif - -#define ecb_unused ecb_attribute ((__unused__)) -#define ecb_const ecb_attribute ((__const__)) -#define ecb_pure ecb_attribute ((__pure__)) - -#if ECB_C11 || __IBMC_NORETURN - /* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */ - #define ecb_noreturn _Noreturn -#elif ECB_CPP11 - #define ecb_noreturn [[noreturn]] -#elif _MSC_VER >= 1200 - /* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */ - #define ecb_noreturn __declspec (noreturn) -#else - #define ecb_noreturn ecb_attribute ((__noreturn__)) -#endif - -#if ECB_GCC_VERSION(4,3) - #define ecb_artificial ecb_attribute ((__artificial__)) - #define ecb_hot ecb_attribute ((__hot__)) - #define ecb_cold ecb_attribute ((__cold__)) -#else - #define ecb_artificial - #define ecb_hot - #define ecb_cold -#endif - -/* put around conditional expressions if you are very sure that the */ -/* expression is mostly true or mostly false. note that these return */ -/* booleans, not the expression. */ -#define ecb_expect_false(expr) ecb_expect (!!(expr), 0) -#define ecb_expect_true(expr) ecb_expect (!!(expr), 1) -/* for compatibility to the rest of the world */ -#define ecb_likely(expr) ecb_expect_true (expr) -#define ecb_unlikely(expr) ecb_expect_false (expr) - -/* count trailing zero bits and count # of one bits */ -#if ECB_GCC_VERSION(3,4) \ - || (ECB_CLANG_BUILTIN(__builtin_clz) && ECB_CLANG_BUILTIN(__builtin_clzll) \ - && ECB_CLANG_BUILTIN(__builtin_ctz) && ECB_CLANG_BUILTIN(__builtin_ctzll) \ - && ECB_CLANG_BUILTIN(__builtin_popcount)) - /* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */ - #define ecb_ld32(x) (__builtin_clz (x) ^ 31) - #define ecb_ld64(x) (__builtin_clzll (x) ^ 63) - #define ecb_ctz32(x) __builtin_ctz (x) - #define ecb_ctz64(x) __builtin_ctzll (x) - #define ecb_popcount32(x) __builtin_popcount (x) - /* no popcountll */ -#else - ecb_function_ ecb_const int ecb_ctz32 (uint32_t x); - ecb_function_ ecb_const int - ecb_ctz32 (uint32_t x) - { - int r = 0; - - x &= ~x + 1; /* this isolates the lowest bit */ - -#if ECB_branchless_on_i386 - r += !!(x & 0xaaaaaaaa) << 0; - r += !!(x & 0xcccccccc) << 1; - r += !!(x & 0xf0f0f0f0) << 2; - r += !!(x & 0xff00ff00) << 3; - r += !!(x & 0xffff0000) << 4; -#else - if (x & 0xaaaaaaaa) r += 1; - if (x & 0xcccccccc) r += 2; - if (x & 0xf0f0f0f0) r += 4; - if (x & 0xff00ff00) r += 8; - if (x & 0xffff0000) r += 16; -#endif - - return r; - } - - ecb_function_ ecb_const int ecb_ctz64 (uint64_t x); - ecb_function_ ecb_const int - ecb_ctz64 (uint64_t x) - { - int shift = x & 0xffffffffU ? 0 : 32; - return ecb_ctz32 (x >> shift) + shift; - } - - ecb_function_ ecb_const int ecb_popcount32 (uint32_t x); - ecb_function_ ecb_const int - ecb_popcount32 (uint32_t x) - { - x -= (x >> 1) & 0x55555555; - x = ((x >> 2) & 0x33333333) + (x & 0x33333333); - x = ((x >> 4) + x) & 0x0f0f0f0f; - x *= 0x01010101; - - return x >> 24; - } - - ecb_function_ ecb_const int ecb_ld32 (uint32_t x); - ecb_function_ ecb_const int ecb_ld32 (uint32_t x) - { - int r = 0; - - if (x >> 16) { x >>= 16; r += 16; } - if (x >> 8) { x >>= 8; r += 8; } - if (x >> 4) { x >>= 4; r += 4; } - if (x >> 2) { x >>= 2; r += 2; } - if (x >> 1) { r += 1; } - - return r; - } - - ecb_function_ ecb_const int ecb_ld64 (uint64_t x); - ecb_function_ ecb_const int ecb_ld64 (uint64_t x) - { - int r = 0; - - if (x >> 32) { x >>= 32; r += 32; } - - return r + ecb_ld32 (x); - } -#endif - -ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x); -ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); } -ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x); -ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); } - -ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x); -ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x) -{ - return ( (x * 0x0802U & 0x22110U) - | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16; -} - -ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x); -ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x) -{ - x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1); - x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2); - x = ((x >> 4) & 0x0f0f) | ((x & 0x0f0f) << 4); - x = ( x >> 8 ) | ( x << 8); - - return x; -} - -ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x); -ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x) -{ - x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1); - x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2); - x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4); - x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8); - x = ( x >> 16 ) | ( x << 16); - - return x; -} - -/* popcount64 is only available on 64 bit cpus as gcc builtin */ -/* so for this version we are lazy */ -ecb_function_ ecb_const int ecb_popcount64 (uint64_t x); -ecb_function_ ecb_const int -ecb_popcount64 (uint64_t x) -{ - return ecb_popcount32 (x) + ecb_popcount32 (x >> 32); -} - -ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count); -ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count); -ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count); -ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count); -ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count); -ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count); -ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count); -ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count); - -ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); } -ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); } -ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); } -ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); } -ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); } -ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); } -ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); } -ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); } - -#if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64)) - #if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16) - #define ecb_bswap16(x) __builtin_bswap16 (x) - #else - #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16) - #endif - #define ecb_bswap32(x) __builtin_bswap32 (x) - #define ecb_bswap64(x) __builtin_bswap64 (x) -#elif _MSC_VER - #include <stdlib.h> - #define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x))) - #define ecb_bswap32(x) ((uint32_t)_byteswap_ulong ((uint32_t)(x))) - #define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x))) -#else - ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x); - ecb_function_ ecb_const uint16_t - ecb_bswap16 (uint16_t x) - { - return ecb_rotl16 (x, 8); - } - - ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x); - ecb_function_ ecb_const uint32_t - ecb_bswap32 (uint32_t x) - { - return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16); - } - - ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x); - ecb_function_ ecb_const uint64_t - ecb_bswap64 (uint64_t x) - { - return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32); - } -#endif - -#if ECB_GCC_VERSION(4,5) || ECB_CLANG_BUILTIN(__builtin_unreachable) - #define ecb_unreachable() __builtin_unreachable () -#else - /* this seems to work fine, but gcc always emits a warning for it :/ */ - ecb_inline ecb_noreturn void ecb_unreachable (void); - ecb_inline ecb_noreturn void ecb_unreachable (void) { } -#endif - -/* try to tell the compiler that some condition is definitely true */ -#define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0 - -ecb_inline ecb_const unsigned char ecb_byteorder_helper (void); -ecb_inline ecb_const unsigned char -ecb_byteorder_helper (void) -{ - /* the union code still generates code under pressure in gcc, */ - /* but less than using pointers, and always seems to */ - /* successfully return a constant. */ - /* the reason why we have this horrible preprocessor mess */ - /* is to avoid it in all cases, at least on common architectures */ - /* or when using a recent enough gcc version (>= 4.6) */ -#if ((__i386 || __i386__) && !__VOS__) || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64 - return 0x44; -#elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - return 0x44; -#elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return 0x11; -#else - union - { - uint32_t i; - uint8_t c; - } u = { 0x11223344 }; - return u.c; -#endif -} - -ecb_inline ecb_const ecb_bool ecb_big_endian (void); -ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; } -ecb_inline ecb_const ecb_bool ecb_little_endian (void); -ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; } - -#if ECB_GCC_VERSION(3,0) || ECB_C99 - #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0)) -#else - #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n))) -#endif - -#if ECB_CPP - template<typename T> - static inline T ecb_div_rd (T val, T div) - { - return val < 0 ? - ((-val + div - 1) / div) : (val ) / div; - } - template<typename T> - static inline T ecb_div_ru (T val, T div) - { - return val < 0 ? - ((-val ) / div) : (val + div - 1) / div; - } -#else - #define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val) ) / (div)) - #define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val) ) / (div)) : ((val) + (div) - 1) / (div)) -#endif - -#if ecb_cplusplus_does_not_suck - /* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */ - template<typename T, int N> - static inline int ecb_array_length (const T (&arr)[N]) - { - return N; - } -#else - #define ecb_array_length(name) (sizeof (name) / sizeof (name [0])) -#endif - -/*******************************************************************************/ -/* floating point stuff, can be disabled by defining ECB_NO_LIBM */ - -/* basically, everything uses "ieee pure-endian" floating point numbers */ -/* the only noteworthy exception is ancient armle, which uses order 43218765 */ -#if 0 \ - || __i386 || __i386__ \ - || ECB_GCC_AMD64 \ - || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \ - || defined __s390__ || defined __s390x__ \ - || defined __mips__ \ - || defined __alpha__ \ - || defined __hppa__ \ - || defined __ia64__ \ - || defined __m68k__ \ - || defined __m88k__ \ - || defined __sh__ \ - || defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \ - || (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \ - || defined __aarch64__ - #define ECB_STDFP 1 - #include <string.h> /* for memcpy */ -#else - #define ECB_STDFP 0 -#endif - -#ifndef ECB_NO_LIBM - - #include <math.h> /* for frexp*, ldexp*, INFINITY, NAN */ - - /* only the oldest of old doesn't have this one. solaris. */ - #ifdef INFINITY - #define ECB_INFINITY INFINITY - #else - #define ECB_INFINITY HUGE_VAL - #endif - - #ifdef NAN - #define ECB_NAN NAN - #else - #define ECB_NAN ECB_INFINITY - #endif - - #if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L - #define ecb_ldexpf(x,e) ldexpf ((x), (e)) - #define ecb_frexpf(x,e) frexpf ((x), (e)) - #else - #define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e)) - #define ecb_frexpf(x,e) (float) frexp ((double) (x), (e)) - #endif - - /* converts an ieee half/binary16 to a float */ - ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x); - ecb_function_ ecb_const float - ecb_binary16_to_float (uint16_t x) - { - int e = (x >> 10) & 0x1f; - int m = x & 0x3ff; - float r; - - if (!e ) r = ecb_ldexpf (m , -24); - else if (e != 31) r = ecb_ldexpf (m + 0x400, e - 25); - else if (m ) r = ECB_NAN; - else r = ECB_INFINITY; - - return x & 0x8000 ? -r : r; - } - - /* convert a float to ieee single/binary32 */ - ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x); - ecb_function_ ecb_const uint32_t - ecb_float_to_binary32 (float x) - { - uint32_t r; - - #if ECB_STDFP - memcpy (&r, &x, 4); - #else - /* slow emulation, works for anything but -0 */ - uint32_t m; - int e; - - if (x == 0e0f ) return 0x00000000U; - if (x > +3.40282346638528860e+38f) return 0x7f800000U; - if (x < -3.40282346638528860e+38f) return 0xff800000U; - if (x != x ) return 0x7fbfffffU; - - m = ecb_frexpf (x, &e) * 0x1000000U; - - r = m & 0x80000000U; - - if (r) - m = -m; - - if (e <= -126) - { - m &= 0xffffffU; - m >>= (-125 - e); - e = -126; - } - - r |= (e + 126) << 23; - r |= m & 0x7fffffU; - #endif - - return r; - } - - /* converts an ieee single/binary32 to a float */ - ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x); - ecb_function_ ecb_const float - ecb_binary32_to_float (uint32_t x) - { - float r; - - #if ECB_STDFP - memcpy (&r, &x, 4); - #else - /* emulation, only works for normals and subnormals and +0 */ - int neg = x >> 31; - int e = (x >> 23) & 0xffU; - - x &= 0x7fffffU; - - if (e) - x |= 0x800000U; - else - e = 1; - - /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */ - r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126); - - r = neg ? -r : r; - #endif - - return r; - } - - /* convert a double to ieee double/binary64 */ - ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x); - ecb_function_ ecb_const uint64_t - ecb_double_to_binary64 (double x) - { - uint64_t r; - - #if ECB_STDFP - memcpy (&r, &x, 8); - #else - /* slow emulation, works for anything but -0 */ - uint64_t m; - int e; - - if (x == 0e0 ) return 0x0000000000000000U; - if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U; - if (x < -1.79769313486231470e+308) return 0xfff0000000000000U; - if (x != x ) return 0X7ff7ffffffffffffU; - - m = frexp (x, &e) * 0x20000000000000U; - - r = m & 0x8000000000000000;; - - if (r) - m = -m; - - if (e <= -1022) - { - m &= 0x1fffffffffffffU; - m >>= (-1021 - e); - e = -1022; - } - - r |= ((uint64_t)(e + 1022)) << 52; - r |= m & 0xfffffffffffffU; - #endif - - return r; - } - - /* converts an ieee double/binary64 to a double */ - ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x); - ecb_function_ ecb_const double - ecb_binary64_to_double (uint64_t x) - { - double r; - - #if ECB_STDFP - memcpy (&r, &x, 8); - #else - /* emulation, only works for normals and subnormals and +0 */ - int neg = x >> 63; - int e = (x >> 52) & 0x7ffU; - - x &= 0xfffffffffffffU; - - if (e) - x |= 0x10000000000000U; - else - e = 1; - - /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */ - r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022); - - r = neg ? -r : r; - #endif - - return r; - } - -#endif - -#endif - -/* ECB.H END */ - -#if ECB_MEMORY_FENCE_NEEDS_PTHREADS -/* if your architecture doesn't need memory fences, e.g. because it is - * single-cpu/core, or if you use libev in a project that doesn't use libev - * from multiple threads, then you can define ECB_AVOID_PTHREADS when compiling - * libev, in which cases the memory fences become nops. - * alternatively, you can remove this #error and link against libpthread, - * which will then provide the memory fences. - */ -# error "memory fences not defined for your architecture, please report" -#endif - -#ifndef ECB_MEMORY_FENCE -# define ECB_MEMORY_FENCE do { } while (0) -# define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE -# define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE -#endif - -#define expect_false(cond) ecb_expect_false (cond) -#define expect_true(cond) ecb_expect_true (cond) -#define noinline ecb_noinline - -#define inline_size ecb_inline - -#if EV_FEATURE_CODE -# define inline_speed ecb_inline -#else -# define inline_speed static noinline -#endif - -#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1) - -#if EV_MINPRI == EV_MAXPRI -# define ABSPRI(w) (((W)w), 0) -#else -# define ABSPRI(w) (((W)w)->priority - EV_MINPRI) -#endif - -#define EMPTY /* required for microsofts broken pseudo-c compiler */ -#define EMPTY2(a,b) /* used to suppress some warnings */ - -typedef ev_watcher *W; -typedef ev_watcher_list *WL; -typedef ev_watcher_time *WT; - -#define ev_active(w) ((W)(w))->active -#define ev_at(w) ((WT)(w))->at - -#if EV_USE_REALTIME -/* sig_atomic_t is used to avoid per-thread variables or locking but still */ -/* giving it a reasonably high chance of working on typical architectures */ -static EV_ATOMIC_T have_realtime; /* did clock_gettime (CLOCK_REALTIME) work? */ -#endif - -#if EV_USE_MONOTONIC -static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ -#endif - -#ifndef EV_FD_TO_WIN32_HANDLE -# define EV_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd) -#endif -#ifndef EV_WIN32_HANDLE_TO_FD -# define EV_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0) -#endif -#ifndef EV_WIN32_CLOSE_FD -# define EV_WIN32_CLOSE_FD(fd) close (fd) -#endif - -#ifdef _WIN32 -# include "ev_win32.c" -#endif - -/*****************************************************************************/ - -/* define a suitable floor function (only used by periodics atm) */ - -#if EV_USE_FLOOR -# include <math.h> -# define ev_floor(v) floor (v) -#else - -#include <float.h> - -/* a floor() replacement function, should be independent of ev_tstamp type */ -static ev_tstamp noinline -ev_floor (ev_tstamp v) -{ - /* the choice of shift factor is not terribly important */ -#if FLT_RADIX != 2 /* assume FLT_RADIX == 10 */ - const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 10000000000000000000. : 1000000000.; -#else - const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.; -#endif - - /* argument too large for an unsigned long? */ - if (expect_false (v >= shift)) - { - ev_tstamp f; - - if (v == v - 1.) - return v; /* very large number */ - - f = shift * ev_floor (v * (1. / shift)); - return f + ev_floor (v - f); - } - - /* special treatment for negative args? */ - if (expect_false (v < 0.)) - { - ev_tstamp f = -ev_floor (-v); - - return f - (f == v ? 0 : 1); - } - - /* fits into an unsigned long */ - return (unsigned long)v; -} - -#endif - -/*****************************************************************************/ - -#ifdef __linux -# include <sys/utsname.h> -#endif - -static unsigned int noinline ecb_cold -ev_linux_version (void) -{ -#ifdef __linux - unsigned int v = 0; - struct utsname buf; - int i; - char *p = buf.release; - - if (uname (&buf)) - return 0; - - for (i = 3+1; --i; ) - { - unsigned int c = 0; - - for (;;) - { - if (*p >= '0' && *p <= '9') - c = c * 10 + *p++ - '0'; - else - { - p += *p == '.'; - break; - } - } - - v = (v << 8) | c; - } - - return v; -#else - return 0; -#endif -} - -/*****************************************************************************/ - -#if EV_AVOID_STDIO -static void noinline ecb_cold -ev_printerr (const char *msg) -{ - int rc; - do { - rc = write (STDERR_FILENO, msg, strlen (msg)); - } while (errno == EINTR && rc < 0); -} -#endif - -static void (*syserr_cb)(const char *msg) EV_THROW; - -void ecb_cold -ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW -{ - syserr_cb = cb; -} - -static void noinline ecb_cold -ev_syserr (const char *msg) -{ - if (!msg) - msg = "(libev) system error"; - - if (syserr_cb) - syserr_cb (msg); - else - { -#if EV_AVOID_STDIO - ev_printerr (msg); - ev_printerr (": "); - ev_printerr (strerror (errno)); - ev_printerr ("\n"); -#else - perror (msg); -#endif - abort (); - } -} - -static void * -ev_realloc_emul (void *ptr, long size) EV_THROW -{ - /* some systems, notably openbsd and darwin, fail to properly - * implement realloc (x, 0) (as required by both ansi c-89 and - * the single unix specification, so work around them here. - * recently, also (at least) fedora and debian started breaking it, - * despite documenting it otherwise. - */ - - if (size) - return realloc (ptr, size); - - free (ptr); - return 0; -} - -static void *(*alloc)(void *ptr, long size) EV_THROW = ev_realloc_emul; - -void ecb_cold -ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW -{ - alloc = cb; -} - -inline_speed void * -ev_realloc (void *ptr, long size) -{ - ptr = alloc (ptr, size); - - if (!ptr && size) - { -#if EV_AVOID_STDIO - ev_printerr ("(libev) memory allocation failed, aborting.\n"); -#else - fprintf (stderr, "(libev) cannot allocate %ld bytes, aborting.", size); -#endif - abort (); - } - - return ptr; -} - -#define ev_malloc(size) ev_realloc (0, (size)) -#define ev_free(ptr) free (ptr) - -/*****************************************************************************/ - -/* set in reify when reification needed */ -#define EV_ANFD_REIFY 1 - -/* file descriptor info structure */ -typedef struct -{ - WL head; - unsigned char events; /* the events watched for */ - unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */ - unsigned char emask; /* the epoll backend stores the actual kernel mask in here */ - unsigned char unused; -#if EV_USE_EPOLL - unsigned int egen; /* generation counter to counter epoll bugs */ -#endif -#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP - SOCKET handle; -#endif -#if EV_USE_IOCP - OVERLAPPED or, ow; -#endif -} ANFD; - -/* stores the pending event set for a given watcher */ -typedef struct -{ - W w; - int events; /* the pending event set for the given watcher */ -} ANPENDING; - -#if EV_USE_INOTIFY -/* hash table entry per inotify-id */ -typedef struct -{ - WL head; -} ANFS; -#endif - -/* Heap Entry */ -#if EV_HEAP_CACHE_AT - /* a heap element */ - typedef struct { - ev_tstamp at; - WT w; - } ANHE; - - #define ANHE_w(he) (he).w /* access watcher, read-write */ - #define ANHE_at(he) (he).at /* access cached at, read-only */ - #define ANHE_at_cache(he) (he).at = (he).w->at /* update at from watcher */ -#else - /* a heap element */ - typedef WT ANHE; - - #define ANHE_w(he) (he) - #define ANHE_at(he) (he)->at - #define ANHE_at_cache(he) -#endif - -#if EV_MULTIPLICITY - - struct ev_loop - { - ev_tstamp ev_rt_now; - #define ev_rt_now ((loop)->ev_rt_now) - #define VAR(name,decl) decl; - #include "ev_vars.h" - #undef VAR - }; - #include "ev_wrap.h" - - static struct ev_loop default_loop_struct; - EV_API_DECL struct ev_loop *ev_default_loop_ptr = 0; /* needs to be initialised to make it a definition despite extern */ - -#else - - EV_API_DECL ev_tstamp ev_rt_now = 0; /* needs to be initialised to make it a definition despite extern */ - #define VAR(name,decl) static decl; - #include "ev_vars.h" - #undef VAR - - static int ev_default_loop_ptr; - -#endif - -#if EV_FEATURE_API -# define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A) -# define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A) -# define EV_INVOKE_PENDING invoke_cb (EV_A) -#else -# define EV_RELEASE_CB (void)0 -# define EV_ACQUIRE_CB (void)0 -# define EV_INVOKE_PENDING ev_invoke_pending (EV_A) -#endif - -#define EVBREAK_RECURSE 0x80 - -/*****************************************************************************/ - -#ifndef EV_HAVE_EV_TIME -ev_tstamp -ev_time (void) EV_THROW -{ -#if EV_USE_REALTIME - if (expect_true (have_realtime)) - { - struct timespec ts; - clock_gettime (CLOCK_REALTIME, &ts); - return ts.tv_sec + ts.tv_nsec * 1e-9; - } -#endif - - struct timeval tv; - gettimeofday (&tv, 0); - return tv.tv_sec + tv.tv_usec * 1e-6; -} -#endif - -inline_size ev_tstamp -get_clock (void) -{ -#if EV_USE_MONOTONIC - if (expect_true (have_monotonic)) - { - struct timespec ts; - clock_gettime (CLOCK_MONOTONIC, &ts); - return ts.tv_sec + ts.tv_nsec * 1e-9; - } -#endif - - return ev_time (); -} - -#if EV_MULTIPLICITY -ev_tstamp -ev_now (EV_P) EV_THROW -{ - return ev_rt_now; -} -#endif - -void -ev_sleep (ev_tstamp delay) EV_THROW -{ - if (delay > 0.) - { -#if EV_USE_NANOSLEEP - struct timespec ts; - - EV_TS_SET (ts, delay); - nanosleep (&ts, 0); -#elif defined _WIN32 - Sleep ((unsigned long)(delay * 1e3)); -#else - struct timeval tv; - - /* here we rely on sys/time.h + sys/types.h + unistd.h providing select */ - /* something not guaranteed by newer posix versions, but guaranteed */ - /* by older ones */ - EV_TV_SET (tv, delay); - select (0, 0, 0, 0, &tv); -#endif - } -} - -/*****************************************************************************/ - -#define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */ - -/* find a suitable new size for the given array, */ -/* hopefully by rounding to a nice-to-malloc size */ -inline_size int -array_nextsize (int elem, int cur, int cnt) -{ - int ncur = cur + 1; - - do - ncur <<= 1; - while (cnt > ncur); - - /* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */ - if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4) - { - ncur *= elem; - ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1); - ncur = ncur - sizeof (void *) * 4; - ncur /= elem; - } - - return ncur; -} - -static void * noinline ecb_cold -array_realloc (int elem, void *base, int *cur, int cnt) -{ - *cur = array_nextsize (elem, *cur, cnt); - return ev_realloc (base, elem * *cur); -} - -#define array_init_zero(base,count) \ - memset ((void *)(base), 0, sizeof (*(base)) * (count)) - -#define array_needsize(type,base,cur,cnt,init) \ - if (expect_false ((cnt) > (cur))) \ - { \ - int ecb_unused ocur_ = (cur); \ - (base) = (type *)array_realloc \ - (sizeof (type), (base), &(cur), (cnt)); \ - init ((base) + (ocur_), (cur) - ocur_); \ - } - -#if 0 -#define array_slim(type,stem) \ - if (stem ## max < array_roundsize (stem ## cnt >> 2)) \ - { \ - stem ## max = array_roundsize (stem ## cnt >> 1); \ - base = (type *)ev_realloc (base, sizeof (type) * (stem ## max));\ - fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\ - } -#endif - -#define array_free(stem, idx) \ - ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; stem ## s idx = 0 - -/*****************************************************************************/ - -/* dummy callback for pending events */ -static void noinline -pendingcb (EV_P_ ev_prepare *w, int revents) -{ -} - -void noinline -ev_feed_event (EV_P_ void *w, int revents) EV_THROW -{ - W w_ = (W)w; - int pri = ABSPRI (w_); - - if (expect_false (w_->pending)) - pendings [pri][w_->pending - 1].events |= revents; - else - { - w_->pending = ++pendingcnt [pri]; - array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2); - pendings [pri][w_->pending - 1].w = w_; - pendings [pri][w_->pending - 1].events = revents; - } - - pendingpri = NUMPRI - 1; -} - -inline_speed void -feed_reverse (EV_P_ W w) -{ - array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, EMPTY2); - rfeeds [rfeedcnt++] = w; -} - -inline_size void -feed_reverse_done (EV_P_ int revents) -{ - do - ev_feed_event (EV_A_ rfeeds [--rfeedcnt], revents); - while (rfeedcnt); -} - -inline_speed void -queue_events (EV_P_ W *events, int eventcnt, int type) -{ - int i; - - for (i = 0; i < eventcnt; ++i) - ev_feed_event (EV_A_ events [i], type); -} - -/*****************************************************************************/ - -inline_speed void -fd_event_nocheck (EV_P_ int fd, int revents) -{ - ANFD *anfd = anfds + fd; - ev_io *w; - - for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next) - { - int ev = w->events & revents; - - if (ev) - ev_feed_event (EV_A_ (W)w, ev); - } -} - -/* do not submit kernel events for fds that have reify set */ -/* because that means they changed while we were polling for new events */ -inline_speed void -fd_event (EV_P_ int fd, int revents) -{ - ANFD *anfd = anfds + fd; - - if (expect_true (!anfd->reify)) - fd_event_nocheck (EV_A_ fd, revents); -} - -void -ev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW -{ - if (fd >= 0 && fd < anfdmax) - fd_event_nocheck (EV_A_ fd, revents); -} - -/* make sure the external fd watch events are in-sync */ -/* with the kernel/libev internal state */ -inline_size void -fd_reify (EV_P) -{ - int i; - -#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP - for (i = 0; i < fdchangecnt; ++i) - { - int fd = fdchanges [i]; - ANFD *anfd = anfds + fd; - - if (anfd->reify & EV__IOFDSET && anfd->head) - { - SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd); - - if (handle != anfd->handle) - { - unsigned long arg; - - assert (("libev: only socket fds supported in this configuration", ioctlsocket (handle, FIONREAD, &arg) == 0)); - - /* handle changed, but fd didn't - we need to do it in two steps */ - backend_modify (EV_A_ fd, anfd->events, 0); - anfd->events = 0; - anfd->handle = handle; - } - } - } -#endif - - for (i = 0; i < fdchangecnt; ++i) - { - int fd = fdchanges [i]; - ANFD *anfd = anfds + fd; - ev_io *w; - - unsigned char o_events = anfd->events; - unsigned char o_reify = anfd->reify; - - anfd->reify = 0; - - /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */ - { - anfd->events = 0; - - for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next) - anfd->events |= (unsigned char)w->events; - - if (o_events != anfd->events) - o_reify = EV__IOFDSET; /* actually |= */ - } - - if (o_reify & EV__IOFDSET) - backend_modify (EV_A_ fd, o_events, anfd->events); - } - - fdchangecnt = 0; -} - -/* something about the given fd changed */ -inline_size void -fd_change (EV_P_ int fd, int flags) -{ - unsigned char reify = anfds [fd].reify; - anfds [fd].reify |= flags; - - if (expect_true (!reify)) - { - ++fdchangecnt; - array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2); - fdchanges [fdchangecnt - 1] = fd; - } -} - -/* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */ -inline_speed void ecb_cold -fd_kill (EV_P_ int fd) -{ - ev_io *w; - - while ((w = (ev_io *)anfds [fd].head)) - { - ev_io_stop (EV_A_ w); - ev_feed_event (EV_A_ (W)w, EV_ERROR | EV_READ | EV_WRITE); - } -} - -/* check whether the given fd is actually valid, for error recovery */ -inline_size int ecb_cold -fd_valid (int fd) -{ -#ifdef _WIN32 - return EV_FD_TO_WIN32_HANDLE (fd) != -1; -#else - return fcntl (fd, F_GETFD) != -1; -#endif -} - -/* called on EBADF to verify fds */ -static void noinline ecb_cold -fd_ebadf (EV_P) -{ - int fd; - - for (fd = 0; fd < anfdmax; ++fd) - if (anfds [fd].events) - if (!fd_valid (fd) && errno == EBADF) - fd_kill (EV_A_ fd); -} - -/* called on ENOMEM in select/poll to kill some fds and retry */ -static void noinline ecb_cold -fd_enomem (EV_P) -{ - int fd; - - for (fd = anfdmax; fd--; ) - if (anfds [fd].events) - { - fd_kill (EV_A_ fd); - break; - } -} - -/* usually called after fork if backend needs to re-arm all fds from scratch */ -static void noinline -fd_rearm_all (EV_P) -{ - int fd; - - for (fd = 0; fd < anfdmax; ++fd) - if (anfds [fd].events) - { - anfds [fd].events = 0; - anfds [fd].emask = 0; - fd_change (EV_A_ fd, EV__IOFDSET | EV_ANFD_REIFY); - } -} - -/* used to prepare libev internal fd's */ -/* this is not fork-safe */ -inline_speed void -fd_intern (int fd) -{ -#ifdef _WIN32 - unsigned long arg = 1; - ioctlsocket (EV_FD_TO_WIN32_HANDLE (fd), FIONBIO, &arg); -#else - fcntl (fd, F_SETFD, FD_CLOEXEC); - fcntl (fd, F_SETFL, O_NONBLOCK); -#endif -} - -/*****************************************************************************/ - -/* - * the heap functions want a real array index. array index 0 is guaranteed to not - * be in-use at any time. the first heap entry is at array [HEAP0]. DHEAP gives - * the branching factor of the d-tree. - */ - -/* - * at the moment we allow libev the luxury of two heaps, - * a small-code-size 2-heap one and a ~1.5kb larger 4-heap - * which is more cache-efficient. - * the difference is about 5% with 50000+ watchers. - */ -#if EV_USE_4HEAP - -#define DHEAP 4 -#define HEAP0 (DHEAP - 1) /* index of first element in heap */ -#define HPARENT(k) ((((k) - HEAP0 - 1) / DHEAP) + HEAP0) -#define UPHEAP_DONE(p,k) ((p) == (k)) - -/* away from the root */ -inline_speed void -downheap (ANHE *heap, int N, int k) -{ - ANHE he = heap [k]; - ANHE *E = heap + N + HEAP0; - - for (;;) - { - ev_tstamp minat; - ANHE *minpos; - ANHE *pos = heap + DHEAP * (k - HEAP0) + HEAP0 + 1; - - /* find minimum child */ - if (expect_true (pos + DHEAP - 1 < E)) - { - /* fast path */ (minpos = pos + 0), (minat = ANHE_at (*minpos)); - if ( ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos)); - if ( ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos)); - if ( ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos)); - } - else if (pos < E) - { - /* slow path */ (minpos = pos + 0), (minat = ANHE_at (*minpos)); - if (pos + 1 < E && ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos)); - if (pos + 2 < E && ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos)); - if (pos + 3 < E && ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos)); - } - else - break; - - if (ANHE_at (he) <= minat) - break; - - heap [k] = *minpos; - ev_active (ANHE_w (*minpos)) = k; - - k = minpos - heap; - } - - heap [k] = he; - ev_active (ANHE_w (he)) = k; -} - -#else /* 4HEAP */ - -#define HEAP0 1 -#define HPARENT(k) ((k) >> 1) -#define UPHEAP_DONE(p,k) (!(p)) - -/* away from the root */ -inline_speed void -downheap (ANHE *heap, int N, int k) -{ - ANHE he = heap [k]; - - for (;;) - { - int c = k << 1; - - if (c >= N + HEAP0) - break; - - c += c + 1 < N + HEAP0 && ANHE_at (heap [c]) > ANHE_at (heap [c + 1]) - ? 1 : 0; - - if (ANHE_at (he) <= ANHE_at (heap [c])) - break; - - heap [k] = heap [c]; - ev_active (ANHE_w (heap [k])) = k; - - k = c; - } - - heap [k] = he; - ev_active (ANHE_w (he)) = k; -} -#endif - -/* towards the root */ -inline_speed void -upheap (ANHE *heap, int k) -{ - ANHE he = heap [k]; - - for (;;) - { - int p = HPARENT (k); - - if (UPHEAP_DONE (p, k) || ANHE_at (heap [p]) <= ANHE_at (he)) - break; - - heap [k] = heap [p]; - ev_active (ANHE_w (heap [k])) = k; - k = p; - } - - heap [k] = he; - ev_active (ANHE_w (he)) = k; -} - -/* move an element suitably so it is in a correct place */ -inline_size void -adjustheap (ANHE *heap, int N, int k) -{ - if (k > HEAP0 && ANHE_at (heap [k]) <= ANHE_at (heap [HPARENT (k)])) - upheap (heap, k); - else - downheap (heap, N, k); -} - -/* rebuild the heap: this function is used only once and executed rarely */ -inline_size void -reheap (ANHE *heap, int N) -{ - int i; - - /* we don't use floyds algorithm, upheap is simpler and is more cache-efficient */ - /* also, this is easy to implement and correct for both 2-heaps and 4-heaps */ - for (i = 0; i < N; ++i) - upheap (heap, i + HEAP0); -} - -/*****************************************************************************/ - -/* associate signal watchers to a signal signal */ -typedef struct -{ - EV_ATOMIC_T pending; -#if EV_MULTIPLICITY - EV_P; -#endif - WL head; -} ANSIG; - -static ANSIG signals [EV_NSIG]; - -/*****************************************************************************/ - -#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE - -static void noinline ecb_cold -evpipe_init (EV_P) -{ - if (!ev_is_active (&pipe_w)) - { - int fds [2]; - -# if EV_USE_EVENTFD - fds [0] = -1; - fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC); - if (fds [1] < 0 && errno == EINVAL) - fds [1] = eventfd (0, 0); - - if (fds [1] < 0) -# endif - { - while (pipe (fds)) - ev_syserr ("(libev) error creating signal/async pipe"); - - fd_intern (fds [0]); - } - - evpipe [0] = fds [0]; - - if (evpipe [1] < 0) - evpipe [1] = fds [1]; /* first call, set write fd */ - else - { - /* on subsequent calls, do not change evpipe [1] */ - /* so that evpipe_write can always rely on its value. */ - /* this branch does not do anything sensible on windows, */ - /* so must not be executed on windows */ - - dup2 (fds [1], evpipe [1]); - close (fds [1]); - } - - fd_intern (evpipe [1]); - - ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ); - ev_io_start (EV_A_ &pipe_w); - ev_unref (EV_A); /* watcher should not keep loop alive */ - } -} - -inline_speed void -evpipe_write (EV_P_ EV_ATOMIC_T *flag) -{ - ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */ - - if (expect_true (*flag)) - return; - - *flag = 1; - ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */ - - pipe_write_skipped = 1; - - ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */ - - if (pipe_write_wanted) - { - int old_errno, rc; - - pipe_write_skipped = 0; - ECB_MEMORY_FENCE_RELEASE; - - old_errno = errno; /* save errno because write will clobber it */ - -#if EV_USE_EVENTFD - if (evpipe [0] < 0) - { - uint64_t counter = 1; - do { - rc = write (evpipe [1], &counter, sizeof (uint64_t)); - } while (errno == EINTR && rc < 0); - } - else -#endif - { -#ifdef _WIN32 - WSABUF buf; - DWORD sent; - buf.buf = &buf; - buf.len = 1; - WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0); -#else - do { - rc = write (evpipe [1], &(evpipe [1]), 1); - } while (errno == EINTR && rc < 0); -#endif - } - - errno = old_errno; - } -} - -/* called whenever the libev signal pipe */ -/* got some events (signal, async) */ -static void -pipecb (EV_P_ ev_io *iow, int revents) -{ - int i; - - if (revents & EV_READ) - { -#if EV_USE_EVENTFD - if (evpipe [0] < 0) - { - uint64_t counter; - read (evpipe [1], &counter, sizeof (uint64_t)); - } - else -#endif - { - char dummy[4]; -#ifdef _WIN32 - WSABUF buf; - DWORD recvd; - DWORD flags = 0; - buf.buf = dummy; - buf.len = sizeof (dummy); - WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0); -#else - read (evpipe [0], &dummy, sizeof (dummy)); -#endif - } - } - - pipe_write_skipped = 0; - - ECB_MEMORY_FENCE; /* push out skipped, acquire flags */ - -#if EV_SIGNAL_ENABLE - if (sig_pending) - { - sig_pending = 0; - - ECB_MEMORY_FENCE; - - for (i = EV_NSIG - 1; i--; ) - if (expect_false (signals [i].pending)) - ev_feed_signal_event (EV_A_ i + 1); - } -#endif - -#if EV_ASYNC_ENABLE - if (async_pending) - { - async_pending = 0; - - ECB_MEMORY_FENCE; - - for (i = asynccnt; i--; ) - if (asyncs [i]->sent) - { - asyncs [i]->sent = 0; - ECB_MEMORY_FENCE_RELEASE; - ev_feed_event (EV_A_ asyncs [i], EV_ASYNC); - } - } -#endif -} - -/*****************************************************************************/ - -void -ev_feed_signal (int signum) EV_THROW -{ -#if EV_MULTIPLICITY - EV_P; - ECB_MEMORY_FENCE_ACQUIRE; - EV_A = signals [signum - 1].loop; - - if (!EV_A) - return; -#endif - - signals [signum - 1].pending = 1; - evpipe_write (EV_A_ &sig_pending); -} - -static void -ev_sighandler (int signum) -{ -#ifdef _WIN32 - signal (signum, ev_sighandler); -#endif - - ev_feed_signal (signum); -} - -void noinline -ev_feed_signal_event (EV_P_ int signum) EV_THROW -{ - WL w; - - if (expect_false (signum <= 0 || signum >= EV_NSIG)) - return; - - --signum; - -#if EV_MULTIPLICITY - /* it is permissible to try to feed a signal to the wrong loop */ - /* or, likely more useful, feeding a signal nobody is waiting for */ - - if (expect_false (signals [signum].loop != EV_A)) - return; -#endif - - signals [signum].pending = 0; - ECB_MEMORY_FENCE_RELEASE; - - for (w = signals [signum].head; w; w = w->next) - ev_feed_event (EV_A_ (W)w, EV_SIGNAL); -} - -#if EV_USE_SIGNALFD -static void -sigfdcb (EV_P_ ev_io *iow, int revents) -{ - struct signalfd_siginfo si[2], *sip; /* these structs are big */ - - for (;;) - { - ssize_t res = read (sigfd, si, sizeof (si)); - - /* not ISO-C, as res might be -1, but works with SuS */ - for (sip = si; (char *)sip < (char *)si + res; ++sip) - ev_feed_signal_event (EV_A_ sip->ssi_signo); - - if (res < (ssize_t)sizeof (si)) - break; - } -} -#endif - -#endif - -/*****************************************************************************/ - -#if EV_CHILD_ENABLE -static WL childs [EV_PID_HASHSIZE]; - -static ev_signal childev; - -#ifndef WIFCONTINUED -# define WIFCONTINUED(status) 0 -#endif - -/* handle a single child status event */ -inline_speed void -child_reap (EV_P_ int chain, int pid, int status) -{ - ev_child *w; - int traced = WIFSTOPPED (status) || WIFCONTINUED (status); - - for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next) - { - if ((w->pid == pid || !w->pid) - && (!traced || (w->flags & 1))) - { - ev_set_priority (w, EV_MAXPRI); /* need to do it *now*, this *must* be the same prio as the signal watcher itself */ - w->rpid = pid; - w->rstatus = status; - ev_feed_event (EV_A_ (W)w, EV_CHILD); - } - } -} - -#ifndef WCONTINUED -# define WCONTINUED 0 -#endif - -/* called on sigchld etc., calls waitpid */ -static void -childcb (EV_P_ ev_signal *sw, int revents) -{ - int pid, status; - - /* some systems define WCONTINUED but then fail to support it (linux 2.4) */ - if (0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED))) - if (!WCONTINUED - || errno != EINVAL - || 0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED))) - return; - - /* make sure we are called again until all children have been reaped */ - /* we need to do it this way so that the callback gets called before we continue */ - ev_feed_event (EV_A_ (W)sw, EV_SIGNAL); - - child_reap (EV_A_ pid, pid, status); - if ((EV_PID_HASHSIZE) > 1) - child_reap (EV_A_ 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */ -} - -#endif - -/*****************************************************************************/ - -#if EV_USE_IOCP -# include "ev_iocp.c" -#endif -#if EV_USE_PORT -# include "ev_port.c" -#endif -#if EV_USE_KQUEUE -# include "ev_kqueue.c" -#endif -#if EV_USE_EPOLL -# include "ev_epoll.c" -#endif -#if EV_USE_POLL -# include "ev_poll.c" -#endif -#if EV_USE_SELECT -# include "ev_select.c" -#endif - -int ecb_cold -ev_version_major (void) EV_THROW -{ - return EV_VERSION_MAJOR; -} - -int ecb_cold -ev_version_minor (void) EV_THROW -{ - return EV_VERSION_MINOR; -} - -/* return true if we are running with elevated privileges and should ignore env variables */ -int inline_size ecb_cold -enable_secure (void) -{ -#ifdef _WIN32 - return 0; -#else - return getuid () != geteuid () - || getgid () != getegid (); -#endif -} - -unsigned int ecb_cold -ev_supported_backends (void) EV_THROW -{ - unsigned int flags = 0; - - if (EV_USE_PORT ) flags |= EVBACKEND_PORT; - if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE; - if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL; - if (EV_USE_POLL ) flags |= EVBACKEND_POLL; - if (EV_USE_SELECT) flags |= EVBACKEND_SELECT; - - return flags; -} - -unsigned int ecb_cold -ev_recommended_backends (void) EV_THROW -{ - unsigned int flags = ev_supported_backends (); - -#ifndef __NetBSD__ - /* kqueue is borked on everything but netbsd apparently */ - /* it usually doesn't work correctly on anything but sockets and pipes */ - flags &= ~EVBACKEND_KQUEUE; -#endif -#ifdef __APPLE__ - /* only select works correctly on that "unix-certified" platform */ - flags &= ~EVBACKEND_KQUEUE; /* horribly broken, even for sockets */ - flags &= ~EVBACKEND_POLL; /* poll is based on kqueue from 10.5 onwards */ -#endif -#ifdef __FreeBSD__ - flags &= ~EVBACKEND_POLL; /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */ -#endif - - return flags; -} - -unsigned int ecb_cold -ev_embeddable_backends (void) EV_THROW -{ - int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT; - - /* epoll embeddability broken on all linux versions up to at least 2.6.23 */ - if (ev_linux_version () < 0x020620) /* disable it on linux < 2.6.32 */ - flags &= ~EVBACKEND_EPOLL; - - return flags; -} - -unsigned int -ev_backend (EV_P) EV_THROW -{ - return backend; -} - -#if EV_FEATURE_API -unsigned int -ev_iteration (EV_P) EV_THROW -{ - return loop_count; -} - -unsigned int -ev_depth (EV_P) EV_THROW -{ - return loop_depth; -} - -void -ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW -{ - io_blocktime = interval; -} - -void -ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW -{ - timeout_blocktime = interval; -} - -void -ev_set_userdata (EV_P_ void *data) EV_THROW -{ - userdata = data; -} - -void * -ev_userdata (EV_P) EV_THROW -{ - return userdata; -} - -void -ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW -{ - invoke_cb = invoke_pending_cb; -} - -void -ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW -{ - release_cb = release; - acquire_cb = acquire; -} -#endif - -/* initialise a loop structure, must be zero-initialised */ -static void noinline ecb_cold -loop_init (EV_P_ unsigned int flags) EV_THROW -{ - if (!backend) - { - origflags = flags; - -#if EV_USE_REALTIME - if (!have_realtime) - { - struct timespec ts; - - if (!clock_gettime (CLOCK_REALTIME, &ts)) - have_realtime = 1; - } -#endif - -#if EV_USE_MONOTONIC - if (!have_monotonic) - { - struct timespec ts; - - if (!clock_gettime (CLOCK_MONOTONIC, &ts)) - have_monotonic = 1; - } -#endif - - /* pid check not overridable via env */ -#ifndef _WIN32 - if (flags & EVFLAG_FORKCHECK) - curpid = getpid (); -#endif - - if (!(flags & EVFLAG_NOENV) - && !enable_secure () - && getenv ("LIBEV_FLAGS")) - flags = atoi (getenv ("LIBEV_FLAGS")); - - ev_rt_now = ev_time (); - mn_now = get_clock (); - now_floor = mn_now; - rtmn_diff = ev_rt_now - mn_now; -#if EV_FEATURE_API - invoke_cb = ev_invoke_pending; -#endif - - io_blocktime = 0.; - timeout_blocktime = 0.; - backend = 0; - backend_fd = -1; - sig_pending = 0; -#if EV_ASYNC_ENABLE - async_pending = 0; -#endif - pipe_write_skipped = 0; - pipe_write_wanted = 0; - evpipe [0] = -1; - evpipe [1] = -1; -#if EV_USE_INOTIFY - fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2; -#endif -#if EV_USE_SIGNALFD - sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1; -#endif - - if (!(flags & EVBACKEND_MASK)) - flags |= ev_recommended_backends (); - -#if EV_USE_IOCP - if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags); -#endif -#if EV_USE_PORT - if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags); -#endif -#if EV_USE_KQUEUE - if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags); -#endif -#if EV_USE_EPOLL - if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags); -#endif -#if EV_USE_POLL - if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags); -#endif -#if EV_USE_SELECT - if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags); -#endif - - ev_prepare_init (&pending_w, pendingcb); - -#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE - ev_init (&pipe_w, pipecb); - ev_set_priority (&pipe_w, EV_MAXPRI); -#endif - } -} - -/* free up a loop structure */ -void ecb_cold -ev_loop_destroy (EV_P) -{ - int i; - -#if EV_MULTIPLICITY - /* mimic free (0) */ - if (!EV_A) - return; -#endif - -#if EV_CLEANUP_ENABLE - /* queue cleanup watchers (and execute them) */ - if (expect_false (cleanupcnt)) - { - queue_events (EV_A_ (W *)cleanups, cleanupcnt, EV_CLEANUP); - EV_INVOKE_PENDING; - } -#endif - -#if EV_CHILD_ENABLE - if (ev_is_default_loop (EV_A) && ev_is_active (&childev)) - { - ev_ref (EV_A); /* child watcher */ - ev_signal_stop (EV_A_ &childev); - } -#endif - - if (ev_is_active (&pipe_w)) - { - /*ev_ref (EV_A);*/ - /*ev_io_stop (EV_A_ &pipe_w);*/ - - if (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]); - if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]); - } - -#if EV_USE_SIGNALFD - if (ev_is_active (&sigfd_w)) - close (sigfd); -#endif - -#if EV_USE_INOTIFY - if (fs_fd >= 0) - close (fs_fd); -#endif - - if (backend_fd >= 0) - close (backend_fd); - -#if EV_USE_IOCP - if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A); -#endif -#if EV_USE_PORT - if (backend == EVBACKEND_PORT ) port_destroy (EV_A); -#endif -#if EV_USE_KQUEUE - if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A); -#endif -#if EV_USE_EPOLL - if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A); -#endif -#if EV_USE_POLL - if (backend == EVBACKEND_POLL ) poll_destroy (EV_A); -#endif -#if EV_USE_SELECT - if (backend == EVBACKEND_SELECT) select_destroy (EV_A); -#endif - - for (i = NUMPRI; i--; ) - { - array_free (pending, [i]); -#if EV_IDLE_ENABLE - array_free (idle, [i]); -#endif - } - - ev_free (anfds); anfds = 0; anfdmax = 0; - - /* have to use the microsoft-never-gets-it-right macro */ - array_free (rfeed, EMPTY); - array_free (fdchange, EMPTY); - array_free (timer, EMPTY); -#if EV_PERIODIC_ENABLE - array_free (periodic, EMPTY); -#endif -#if EV_FORK_ENABLE - array_free (fork, EMPTY); -#endif -#if EV_CLEANUP_ENABLE - array_free (cleanup, EMPTY); -#endif - array_free (prepare, EMPTY); - array_free (check, EMPTY); -#if EV_ASYNC_ENABLE - array_free (async, EMPTY); -#endif - - backend = 0; - -#if EV_MULTIPLICITY - if (ev_is_default_loop (EV_A)) -#endif - ev_default_loop_ptr = 0; -#if EV_MULTIPLICITY - else - ev_free (EV_A); -#endif -} - -#if EV_USE_INOTIFY -inline_size void infy_fork (EV_P); -#endif - -inline_size void -loop_fork (EV_P) -{ -#if EV_USE_PORT - if (backend == EVBACKEND_PORT ) port_fork (EV_A); -#endif -#if EV_USE_KQUEUE - if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A); -#endif -#if EV_USE_EPOLL - if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A); -#endif -#if EV_USE_INOTIFY - infy_fork (EV_A); -#endif - -#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE - if (ev_is_active (&pipe_w)) - { - /* pipe_write_wanted must be false now, so modifying fd vars should be safe */ - - ev_ref (EV_A); - ev_io_stop (EV_A_ &pipe_w); - - if (evpipe [0] >= 0) - EV_WIN32_CLOSE_FD (evpipe [0]); - - evpipe_init (EV_A); - /* iterate over everything, in case we missed something before */ - ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); - } -#endif - - postfork = 0; -} - -#if EV_MULTIPLICITY - -struct ev_loop * ecb_cold -ev_loop_new (unsigned int flags) EV_THROW -{ - EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop)); - - memset (EV_A, 0, sizeof (struct ev_loop)); - loop_init (EV_A_ flags); - - if (ev_backend (EV_A)) - return EV_A; - - ev_free (EV_A); - return 0; -} - -#endif /* multiplicity */ - -#if EV_VERIFY -static void noinline ecb_cold -verify_watcher (EV_P_ W w) -{ - assert (("libev: watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI)); - - if (w->pending) - assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w)); -} - -static void noinline ecb_cold -verify_heap (EV_P_ ANHE *heap, int N) -{ - int i; - - for (i = HEAP0; i < N + HEAP0; ++i) - { - assert (("libev: active index mismatch in heap", ev_active (ANHE_w (heap [i])) == i)); - assert (("libev: heap condition violated", i == HEAP0 || ANHE_at (heap [HPARENT (i)]) <= ANHE_at (heap [i]))); - assert (("libev: heap at cache mismatch", ANHE_at (heap [i]) == ev_at (ANHE_w (heap [i])))); - - verify_watcher (EV_A_ (W)ANHE_w (heap [i])); - } -} - -static void noinline ecb_cold -array_verify (EV_P_ W *ws, int cnt) -{ - while (cnt--) - { - assert (("libev: active index mismatch", ev_active (ws [cnt]) == cnt + 1)); - verify_watcher (EV_A_ ws [cnt]); - } -} -#endif - -#if EV_FEATURE_API -void ecb_cold -ev_verify (EV_P) EV_THROW -{ -#if EV_VERIFY - int i; - WL w, w2; - - assert (activecnt >= -1); - - assert (fdchangemax >= fdchangecnt); - for (i = 0; i < fdchangecnt; ++i) - assert (("libev: negative fd in fdchanges", fdchanges [i] >= 0)); - - assert (anfdmax >= 0); - for (i = 0; i < anfdmax; ++i) - { - int j = 0; - - for (w = w2 = anfds [i].head; w; w = w->next) - { - verify_watcher (EV_A_ (W)w); - - if (j++ & 1) - { - assert (("libev: io watcher list contains a loop", w != w2)); - w2 = w2->next; - } - - assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1)); - assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i)); - } - } - - assert (timermax >= timercnt); - verify_heap (EV_A_ timers, timercnt); - -#if EV_PERIODIC_ENABLE - assert (periodicmax >= periodiccnt); - verify_heap (EV_A_ periodics, periodiccnt); -#endif - - for (i = NUMPRI; i--; ) - { - assert (pendingmax [i] >= pendingcnt [i]); -#if EV_IDLE_ENABLE - assert (idleall >= 0); - assert (idlemax [i] >= idlecnt [i]); - array_verify (EV_A_ (W *)idles [i], idlecnt [i]); -#endif - } - -#if EV_FORK_ENABLE - assert (forkmax >= forkcnt); - array_verify (EV_A_ (W *)forks, forkcnt); -#endif - -#if EV_CLEANUP_ENABLE - assert (cleanupmax >= cleanupcnt); - array_verify (EV_A_ (W *)cleanups, cleanupcnt); -#endif - -#if EV_ASYNC_ENABLE - assert (asyncmax >= asynccnt); - array_verify (EV_A_ (W *)asyncs, asynccnt); -#endif - -#if EV_PREPARE_ENABLE - assert (preparemax >= preparecnt); - array_verify (EV_A_ (W *)prepares, preparecnt); -#endif - -#if EV_CHECK_ENABLE - assert (checkmax >= checkcnt); - array_verify (EV_A_ (W *)checks, checkcnt); -#endif - -# if 0 -#if EV_CHILD_ENABLE - for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next) - for (signum = EV_NSIG - 1; signum--; ) if (signals [signum].pending) -#endif -# endif -#endif -} -#endif - -#if EV_MULTIPLICITY -struct ev_loop * ecb_cold -#else -int -#endif -ev_default_loop (unsigned int flags) EV_THROW -{ - if (!ev_default_loop_ptr) - { -#if EV_MULTIPLICITY - EV_P = ev_default_loop_ptr = &default_loop_struct; -#else - ev_default_loop_ptr = 1; -#endif - - loop_init (EV_A_ flags); - - if (ev_backend (EV_A)) - { -#if EV_CHILD_ENABLE - ev_signal_init (&childev, childcb, SIGCHLD); - ev_set_priority (&childev, EV_MAXPRI); - ev_signal_start (EV_A_ &childev); - ev_unref (EV_A); /* child watcher should not keep loop alive */ -#endif - } - else - ev_default_loop_ptr = 0; - } - - return ev_default_loop_ptr; -} - -void -ev_loop_fork (EV_P) EV_THROW -{ - postfork = 1; -} - -/*****************************************************************************/ - -void -ev_invoke (EV_P_ void *w, int revents) -{ - EV_CB_INVOKE ((W)w, revents); -} - -unsigned int -ev_pending_count (EV_P) EV_THROW -{ - int pri; - unsigned int count = 0; - - for (pri = NUMPRI; pri--; ) - count += pendingcnt [pri]; - - return count; -} - -void noinline -ev_invoke_pending (EV_P) -{ - pendingpri = NUMPRI; - - while (pendingpri) /* pendingpri possibly gets modified in the inner loop */ - { - --pendingpri; - - while (pendingcnt [pendingpri]) - { - ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri]; - - p->w->pending = 0; - EV_CB_INVOKE (p->w, p->events); - EV_FREQUENT_CHECK; - } - } -} - -#if EV_IDLE_ENABLE -/* make idle watchers pending. this handles the "call-idle */ -/* only when higher priorities are idle" logic */ -inline_size void -idle_reify (EV_P) -{ - if (expect_false (idleall)) - { - int pri; - - for (pri = NUMPRI; pri--; ) - { - if (pendingcnt [pri]) - break; - - if (idlecnt [pri]) - { - queue_events (EV_A_ (W *)idles [pri], idlecnt [pri], EV_IDLE); - break; - } - } - } -} -#endif - -/* make timers pending */ -inline_size void -timers_reify (EV_P) -{ - EV_FREQUENT_CHECK; - - if (timercnt && ANHE_at (timers [HEAP0]) < mn_now) - { - do - { - ev_timer *w = (ev_timer *)ANHE_w (timers [HEAP0]); - - /*assert (("libev: inactive timer on timer heap detected", ev_is_active (w)));*/ - - /* first reschedule or stop timer */ - if (w->repeat) - { - ev_at (w) += w->repeat; - if (ev_at (w) < mn_now) - ev_at (w) = mn_now; - - assert (("libev: negative ev_timer repeat value found while processing timers", w->repeat > 0.)); - - ANHE_at_cache (timers [HEAP0]); - downheap (timers, timercnt, HEAP0); - } - else - ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */ - - EV_FREQUENT_CHECK; - feed_reverse (EV_A_ (W)w); - } - while (timercnt && ANHE_at (timers [HEAP0]) < mn_now); - - feed_reverse_done (EV_A_ EV_TIMER); - } -} - -#if EV_PERIODIC_ENABLE - -static void noinline -periodic_recalc (EV_P_ ev_periodic *w) -{ - ev_tstamp interval = w->interval > MIN_INTERVAL ? w->interval : MIN_INTERVAL; - ev_tstamp at = w->offset + interval * ev_floor ((ev_rt_now - w->offset) / interval); - - /* the above almost always errs on the low side */ - while (at <= ev_rt_now) - { - ev_tstamp nat = at + w->interval; - - /* when resolution fails us, we use ev_rt_now */ - if (expect_false (nat == at)) - { - at = ev_rt_now; - break; - } - - at = nat; - } - - ev_at (w) = at; -} - -/* make periodics pending */ -inline_size void -periodics_reify (EV_P) -{ - EV_FREQUENT_CHECK; - - while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now) - { - do - { - ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]); - - /*assert (("libev: inactive timer on periodic heap detected", ev_is_active (w)));*/ - - /* first reschedule or stop timer */ - if (w->reschedule_cb) - { - ev_at (w) = w->reschedule_cb (w, ev_rt_now); - - assert (("libev: ev_periodic reschedule callback returned time in the past", ev_at (w) >= ev_rt_now)); - - ANHE_at_cache (periodics [HEAP0]); - downheap (periodics, periodiccnt, HEAP0); - } - else if (w->interval) - { - periodic_recalc (EV_A_ w); - ANHE_at_cache (periodics [HEAP0]); - downheap (periodics, periodiccnt, HEAP0); - } - else - ev_periodic_stop (EV_A_ w); /* nonrepeating: stop timer */ - - EV_FREQUENT_CHECK; - feed_reverse (EV_A_ (W)w); - } - while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now); - - feed_reverse_done (EV_A_ EV_PERIODIC); - } -} - -/* simply recalculate all periodics */ -/* TODO: maybe ensure that at least one event happens when jumping forward? */ -static void noinline ecb_cold -periodics_reschedule (EV_P) -{ - int i; - - /* adjust periodics after time jump */ - for (i = HEAP0; i < periodiccnt + HEAP0; ++i) - { - ev_periodic *w = (ev_periodic *)ANHE_w (periodics [i]); - - if (w->reschedule_cb) - ev_at (w) = w->reschedule_cb (w, ev_rt_now); - else if (w->interval) - periodic_recalc (EV_A_ w); - - ANHE_at_cache (periodics [i]); - } - - reheap (periodics, periodiccnt); -} -#endif - -/* adjust all timers by a given offset */ -static void noinline ecb_cold -timers_reschedule (EV_P_ ev_tstamp adjust) -{ - int i; - - for (i = 0; i < timercnt; ++i) - { - ANHE *he = timers + i + HEAP0; - ANHE_w (*he)->at += adjust; - ANHE_at_cache (*he); - } -} - -/* fetch new monotonic and realtime times from the kernel */ -/* also detect if there was a timejump, and act accordingly */ -inline_speed void -time_update (EV_P_ ev_tstamp max_block) -{ -#if EV_USE_MONOTONIC - if (expect_true (have_monotonic)) - { - int i; - ev_tstamp odiff = rtmn_diff; - - mn_now = get_clock (); - - /* only fetch the realtime clock every 0.5*MIN_TIMEJUMP seconds */ - /* interpolate in the meantime */ - if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5)) - { - ev_rt_now = rtmn_diff + mn_now; - return; - } - - now_floor = mn_now; - ev_rt_now = ev_time (); - - /* loop a few times, before making important decisions. - * on the choice of "4": one iteration isn't enough, - * in case we get preempted during the calls to - * ev_time and get_clock. a second call is almost guaranteed - * to succeed in that case, though. and looping a few more times - * doesn't hurt either as we only do this on time-jumps or - * in the unlikely event of having been preempted here. - */ - for (i = 4; --i; ) - { - ev_tstamp diff; - rtmn_diff = ev_rt_now - mn_now; - - diff = odiff - rtmn_diff; - - if (expect_true ((diff < 0. ? -diff : diff) < MIN_TIMEJUMP)) - return; /* all is well */ - - ev_rt_now = ev_time (); - mn_now = get_clock (); - now_floor = mn_now; - } - - /* no timer adjustment, as the monotonic clock doesn't jump */ - /* timers_reschedule (EV_A_ rtmn_diff - odiff) */ -# if EV_PERIODIC_ENABLE - periodics_reschedule (EV_A); -# endif - } - else -#endif - { - ev_rt_now = ev_time (); - - if (expect_false (mn_now > ev_rt_now || ev_rt_now > mn_now + max_block + MIN_TIMEJUMP)) - { - /* adjust timers. this is easy, as the offset is the same for all of them */ - timers_reschedule (EV_A_ ev_rt_now - mn_now); -#if EV_PERIODIC_ENABLE - periodics_reschedule (EV_A); -#endif - } - - mn_now = ev_rt_now; - } -} - -int -ev_run (EV_P_ int flags) -{ -#if EV_FEATURE_API - ++loop_depth; -#endif - - assert (("libev: ev_loop recursion during release detected", loop_done != EVBREAK_RECURSE)); - - loop_done = EVBREAK_CANCEL; - - EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */ - - do - { -#if EV_VERIFY >= 2 - ev_verify (EV_A); -#endif - -#ifndef _WIN32 - if (expect_false (curpid)) /* penalise the forking check even more */ - if (expect_false (getpid () != curpid)) - { - curpid = getpid (); - postfork = 1; - } -#endif - -#if EV_FORK_ENABLE - /* we might have forked, so queue fork handlers */ - if (expect_false (postfork)) - if (forkcnt) - { - queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK); - EV_INVOKE_PENDING; - } -#endif - -#if EV_PREPARE_ENABLE - /* queue prepare watchers (and execute them) */ - if (expect_false (preparecnt)) - { - queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE); - EV_INVOKE_PENDING; - } -#endif - - if (expect_false (loop_done)) - break; - - /* we might have forked, so reify kernel state if necessary */ - if (expect_false (postfork)) - loop_fork (EV_A); - - /* update fd-related kernel structures */ - fd_reify (EV_A); - - /* calculate blocking time */ - { - ev_tstamp waittime = 0.; - ev_tstamp sleeptime = 0.; - - /* remember old timestamp for io_blocktime calculation */ - ev_tstamp prev_mn_now = mn_now; - - /* update time to cancel out callback processing overhead */ - time_update (EV_A_ 1e100); - - /* from now on, we want a pipe-wake-up */ - pipe_write_wanted = 1; - - ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */ - - if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped))) - { - waittime = MAX_BLOCKTIME; - - if (timercnt) - { - ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now; - if (waittime > to) waittime = to; - } - -#if EV_PERIODIC_ENABLE - if (periodiccnt) - { - ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now; - if (waittime > to) waittime = to; - } -#endif - - /* don't let timeouts decrease the waittime below timeout_blocktime */ - if (expect_false (waittime < timeout_blocktime)) - waittime = timeout_blocktime; - - /* at this point, we NEED to wait, so we have to ensure */ - /* to pass a minimum nonzero value to the backend */ - if (expect_false (waittime < backend_mintime)) - waittime = backend_mintime; - - /* extra check because io_blocktime is commonly 0 */ - if (expect_false (io_blocktime)) - { - sleeptime = io_blocktime - (mn_now - prev_mn_now); - - if (sleeptime > waittime - backend_mintime) - sleeptime = waittime - backend_mintime; - - if (expect_true (sleeptime > 0.)) - { - ev_sleep (sleeptime); - waittime -= sleeptime; - } - } - } - -#if EV_FEATURE_API - ++loop_count; -#endif - assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */ - backend_poll (EV_A_ waittime); - assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ - - pipe_write_wanted = 0; /* just an optimisation, no fence needed */ - - ECB_MEMORY_FENCE_ACQUIRE; - if (pipe_write_skipped) - { - assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); - ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); - } - - - /* update ev_rt_now, do magic */ - time_update (EV_A_ waittime + sleeptime); - } - - /* queue pending timers and reschedule them */ - timers_reify (EV_A); /* relative timers called last */ -#if EV_PERIODIC_ENABLE - periodics_reify (EV_A); /* absolute timers called first */ -#endif - -#if EV_IDLE_ENABLE - /* queue idle watchers unless other events are pending */ - idle_reify (EV_A); -#endif - -#if EV_CHECK_ENABLE - /* queue check watchers, to be executed first */ - if (expect_false (checkcnt)) - queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK); -#endif - - EV_INVOKE_PENDING; - } - while (expect_true ( - activecnt - && !loop_done - && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT)) - )); - - if (loop_done == EVBREAK_ONE) - loop_done = EVBREAK_CANCEL; - -#if EV_FEATURE_API - --loop_depth; -#endif - - return activecnt; -} - -void -ev_break (EV_P_ int how) EV_THROW -{ - loop_done = how; -} - -void -ev_ref (EV_P) EV_THROW -{ - ++activecnt; -} - -void -ev_unref (EV_P) EV_THROW -{ - --activecnt; -} - -void -ev_now_update (EV_P) EV_THROW -{ - time_update (EV_A_ 1e100); -} - -void -ev_suspend (EV_P) EV_THROW -{ - ev_now_update (EV_A); -} - -void -ev_resume (EV_P) EV_THROW -{ - ev_tstamp mn_prev = mn_now; - - ev_now_update (EV_A); - timers_reschedule (EV_A_ mn_now - mn_prev); -#if EV_PERIODIC_ENABLE - /* TODO: really do this? */ - periodics_reschedule (EV_A); -#endif -} - -/*****************************************************************************/ -/* singly-linked list management, used when the expected list length is short */ - -inline_size void -wlist_add (WL *head, WL elem) -{ - elem->next = *head; - *head = elem; -} - -inline_size void -wlist_del (WL *head, WL elem) -{ - while (*head) - { - if (expect_true (*head == elem)) - { - *head = elem->next; - break; - } - - head = &(*head)->next; - } -} - -/* internal, faster, version of ev_clear_pending */ -inline_speed void -clear_pending (EV_P_ W w) -{ - if (w->pending) - { - pendings [ABSPRI (w)][w->pending - 1].w = (W)&pending_w; - w->pending = 0; - } -} - -int -ev_clear_pending (EV_P_ void *w) EV_THROW -{ - W w_ = (W)w; - int pending = w_->pending; - - if (expect_true (pending)) - { - ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1; - p->w = (W)&pending_w; - w_->pending = 0; - return p->events; - } - else - return 0; -} - -inline_size void -pri_adjust (EV_P_ W w) -{ - int pri = ev_priority (w); - pri = pri < EV_MINPRI ? EV_MINPRI : pri; - pri = pri > EV_MAXPRI ? EV_MAXPRI : pri; - ev_set_priority (w, pri); -} - -inline_speed void -ev_start (EV_P_ W w, int active) -{ - pri_adjust (EV_A_ w); - w->active = active; - ev_ref (EV_A); -} - -inline_size void -ev_stop (EV_P_ W w) -{ - ev_unref (EV_A); - w->active = 0; -} - -/*****************************************************************************/ - -void noinline -ev_io_start (EV_P_ ev_io *w) EV_THROW -{ - int fd = w->fd; - - if (expect_false (ev_is_active (w))) - return; - - assert (("libev: ev_io_start called with negative fd", fd >= 0)); - assert (("libev: ev_io_start called with illegal event mask", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE)))); - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, 1); - array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero); - wlist_add (&anfds[fd].head, (WL)w); - - /* common bug, apparently */ - assert (("libev: ev_io_start called with corrupted watcher", ((WL)w)->next != (WL)w)); - - fd_change (EV_A_ fd, (w->events & EV__IOFDSET) | EV_ANFD_REIFY); - w->events &= ~EV__IOFDSET; - - EV_FREQUENT_CHECK; -} - -void noinline -ev_io_stop (EV_P_ ev_io *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - assert (("libev: ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax)); - - EV_FREQUENT_CHECK; - - wlist_del (&anfds[w->fd].head, (WL)w); - ev_stop (EV_A_ (W)w); - - fd_change (EV_A_ w->fd, EV_ANFD_REIFY); - - EV_FREQUENT_CHECK; -} - -void noinline -ev_timer_start (EV_P_ ev_timer *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - ev_at (w) += mn_now; - - assert (("libev: ev_timer_start called with negative timer repeat value", w->repeat >= 0.)); - - EV_FREQUENT_CHECK; - - ++timercnt; - ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1); - array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2); - ANHE_w (timers [ev_active (w)]) = (WT)w; - ANHE_at_cache (timers [ev_active (w)]); - upheap (timers, ev_active (w)); - - EV_FREQUENT_CHECK; - - /*assert (("libev: internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/ -} - -void noinline -ev_timer_stop (EV_P_ ev_timer *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - assert (("libev: internal timer heap corruption", ANHE_w (timers [active]) == (WT)w)); - - --timercnt; - - if (expect_true (active < timercnt + HEAP0)) - { - timers [active] = timers [timercnt + HEAP0]; - adjustheap (timers, timercnt, active); - } - } - - ev_at (w) -= mn_now; - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} - -void noinline -ev_timer_again (EV_P_ ev_timer *w) EV_THROW -{ - EV_FREQUENT_CHECK; - - clear_pending (EV_A_ (W)w); - - if (ev_is_active (w)) - { - if (w->repeat) - { - ev_at (w) = mn_now + w->repeat; - ANHE_at_cache (timers [ev_active (w)]); - adjustheap (timers, timercnt, ev_active (w)); - } - else - ev_timer_stop (EV_A_ w); - } - else if (w->repeat) - { - ev_at (w) = w->repeat; - ev_timer_start (EV_A_ w); - } - - EV_FREQUENT_CHECK; -} - -ev_tstamp -ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW -{ - return ev_at (w) - (ev_is_active (w) ? mn_now : 0.); -} - -#if EV_PERIODIC_ENABLE -void noinline -ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - if (w->reschedule_cb) - ev_at (w) = w->reschedule_cb (w, ev_rt_now); - else if (w->interval) - { - assert (("libev: ev_periodic_start called with negative interval value", w->interval >= 0.)); - periodic_recalc (EV_A_ w); - } - else - ev_at (w) = w->offset; - - EV_FREQUENT_CHECK; - - ++periodiccnt; - ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1); - array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, EMPTY2); - ANHE_w (periodics [ev_active (w)]) = (WT)w; - ANHE_at_cache (periodics [ev_active (w)]); - upheap (periodics, ev_active (w)); - - EV_FREQUENT_CHECK; - - /*assert (("libev: internal periodic heap corruption", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/ -} - -void noinline -ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - assert (("libev: internal periodic heap corruption", ANHE_w (periodics [active]) == (WT)w)); - - --periodiccnt; - - if (expect_true (active < periodiccnt + HEAP0)) - { - periodics [active] = periodics [periodiccnt + HEAP0]; - adjustheap (periodics, periodiccnt, active); - } - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} - -void noinline -ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW -{ - /* TODO: use adjustheap and recalculation */ - ev_periodic_stop (EV_A_ w); - ev_periodic_start (EV_A_ w); -} -#endif - -#ifndef SA_RESTART -# define SA_RESTART 0 -#endif - -#if EV_SIGNAL_ENABLE - -void noinline -ev_signal_start (EV_P_ ev_signal *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - assert (("libev: ev_signal_start called with illegal signal number", w->signum > 0 && w->signum < EV_NSIG)); - -#if EV_MULTIPLICITY - assert (("libev: a signal must not be attached to two different loops", - !signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop)); - - signals [w->signum - 1].loop = EV_A; - ECB_MEMORY_FENCE_RELEASE; -#endif - - EV_FREQUENT_CHECK; - -#if EV_USE_SIGNALFD - if (sigfd == -2) - { - sigfd = signalfd (-1, &sigfd_set, SFD_NONBLOCK | SFD_CLOEXEC); - if (sigfd < 0 && errno == EINVAL) - sigfd = signalfd (-1, &sigfd_set, 0); /* retry without flags */ - - if (sigfd >= 0) - { - fd_intern (sigfd); /* doing it twice will not hurt */ - - sigemptyset (&sigfd_set); - - ev_io_init (&sigfd_w, sigfdcb, sigfd, EV_READ); - ev_set_priority (&sigfd_w, EV_MAXPRI); - ev_io_start (EV_A_ &sigfd_w); - ev_unref (EV_A); /* signalfd watcher should not keep loop alive */ - } - } - - if (sigfd >= 0) - { - /* TODO: check .head */ - sigaddset (&sigfd_set, w->signum); - sigprocmask (SIG_BLOCK, &sigfd_set, 0); - - signalfd (sigfd, &sigfd_set, 0); - } -#endif - - ev_start (EV_A_ (W)w, 1); - wlist_add (&signals [w->signum - 1].head, (WL)w); - - if (!((WL)w)->next) -# if EV_USE_SIGNALFD - if (sigfd < 0) /*TODO*/ -# endif - { -# ifdef _WIN32 - evpipe_init (EV_A); - - signal (w->signum, ev_sighandler); -# else - struct sigaction sa; - - evpipe_init (EV_A); - - sa.sa_handler = ev_sighandler; - sigfillset (&sa.sa_mask); - sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */ - sigaction (w->signum, &sa, 0); - - if (origflags & EVFLAG_NOSIGMASK) - { - sigemptyset (&sa.sa_mask); - sigaddset (&sa.sa_mask, w->signum); - sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); - } -#endif - } - - EV_FREQUENT_CHECK; -} - -void noinline -ev_signal_stop (EV_P_ ev_signal *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - wlist_del (&signals [w->signum - 1].head, (WL)w); - ev_stop (EV_A_ (W)w); - - if (!signals [w->signum - 1].head) - { -#if EV_MULTIPLICITY - signals [w->signum - 1].loop = 0; /* unattach from signal */ -#endif -#if EV_USE_SIGNALFD - if (sigfd >= 0) - { - sigset_t ss; - - sigemptyset (&ss); - sigaddset (&ss, w->signum); - sigdelset (&sigfd_set, w->signum); - - signalfd (sigfd, &sigfd_set, 0); - sigprocmask (SIG_UNBLOCK, &ss, 0); - } - else -#endif - signal (w->signum, SIG_DFL); - } - - EV_FREQUENT_CHECK; -} - -#endif - -#if EV_CHILD_ENABLE - -void -ev_child_start (EV_P_ ev_child *w) EV_THROW -{ -#if EV_MULTIPLICITY - assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr)); -#endif - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, 1); - wlist_add (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w); - - EV_FREQUENT_CHECK; -} - -void -ev_child_stop (EV_P_ ev_child *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - wlist_del (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w); - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} - -#endif - -#if EV_STAT_ENABLE - -# ifdef _WIN32 -# undef lstat -# define lstat(a,b) _stati64 (a,b) -# endif - -#define DEF_STAT_INTERVAL 5.0074891 -#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */ -#define MIN_STAT_INTERVAL 0.1074891 - -static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents); - -#if EV_USE_INOTIFY - -/* the * 2 is to allow for alignment padding, which for some reason is >> 8 */ -# define EV_INOTIFY_BUFSIZE (sizeof (struct inotify_event) * 2 + NAME_MAX) - -static void noinline -infy_add (EV_P_ ev_stat *w) -{ - w->wd = inotify_add_watch (fs_fd, w->path, - IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY - | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO - | IN_DONT_FOLLOW | IN_MASK_ADD); - - if (w->wd >= 0) - { - struct statfs sfs; - - /* now local changes will be tracked by inotify, but remote changes won't */ - /* unless the filesystem is known to be local, we therefore still poll */ - /* also do poll on <2.6.25, but with normal frequency */ - - if (!fs_2625) - w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL; - else if (!statfs (w->path, &sfs) - && (sfs.f_type == 0x1373 /* devfs */ - || sfs.f_type == 0x4006 /* fat */ - || sfs.f_type == 0x4d44 /* msdos */ - || sfs.f_type == 0xEF53 /* ext2/3 */ - || sfs.f_type == 0x72b6 /* jffs2 */ - || sfs.f_type == 0x858458f6 /* ramfs */ - || sfs.f_type == 0x5346544e /* ntfs */ - || sfs.f_type == 0x3153464a /* jfs */ - || sfs.f_type == 0x9123683e /* btrfs */ - || sfs.f_type == 0x52654973 /* reiser3 */ - || sfs.f_type == 0x01021994 /* tmpfs */ - || sfs.f_type == 0x58465342 /* xfs */)) - w->timer.repeat = 0.; /* filesystem is local, kernel new enough */ - else - w->timer.repeat = w->interval ? w->interval : NFS_STAT_INTERVAL; /* remote, use reduced frequency */ - } - else - { - /* can't use inotify, continue to stat */ - w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL; - - /* if path is not there, monitor some parent directory for speedup hints */ - /* note that exceeding the hardcoded path limit is not a correctness issue, */ - /* but an efficiency issue only */ - if ((errno == ENOENT || errno == EACCES) && strlen (w->path) < 4096) - { - char path [4096]; - strcpy (path, w->path); - - do - { - int mask = IN_MASK_ADD | IN_DELETE_SELF | IN_MOVE_SELF - | (errno == EACCES ? IN_ATTRIB : IN_CREATE | IN_MOVED_TO); - - char *pend = strrchr (path, '/'); - - if (!pend || pend == path) - break; - - *pend = 0; - w->wd = inotify_add_watch (fs_fd, path, mask); - } - while (w->wd < 0 && (errno == ENOENT || errno == EACCES)); - } - } - - if (w->wd >= 0) - wlist_add (&fs_hash [w->wd & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w); - - /* now re-arm timer, if required */ - if (ev_is_active (&w->timer)) ev_ref (EV_A); - ev_timer_again (EV_A_ &w->timer); - if (ev_is_active (&w->timer)) ev_unref (EV_A); -} - -static void noinline -infy_del (EV_P_ ev_stat *w) -{ - int slot; - int wd = w->wd; - - if (wd < 0) - return; - - w->wd = -2; - slot = wd & ((EV_INOTIFY_HASHSIZE) - 1); - wlist_del (&fs_hash [slot].head, (WL)w); - - /* remove this watcher, if others are watching it, they will rearm */ - inotify_rm_watch (fs_fd, wd); -} - -static void noinline -infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev) -{ - if (slot < 0) - /* overflow, need to check for all hash slots */ - for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot) - infy_wd (EV_A_ slot, wd, ev); - else - { - WL w_; - - for (w_ = fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head; w_; ) - { - ev_stat *w = (ev_stat *)w_; - w_ = w_->next; /* lets us remove this watcher and all before it */ - - if (w->wd == wd || wd == -1) - { - if (ev->mask & (IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF)) - { - wlist_del (&fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w); - w->wd = -1; - infy_add (EV_A_ w); /* re-add, no matter what */ - } - - stat_timer_cb (EV_A_ &w->timer, 0); - } - } - } -} - -static void -infy_cb (EV_P_ ev_io *w, int revents) -{ - char buf [EV_INOTIFY_BUFSIZE]; - int ofs; - int len = read (fs_fd, buf, sizeof (buf)); - - for (ofs = 0; ofs < len; ) - { - struct inotify_event *ev = (struct inotify_event *)(buf + ofs); - infy_wd (EV_A_ ev->wd, ev->wd, ev); - ofs += sizeof (struct inotify_event) + ev->len; - } -} - -inline_size void ecb_cold -ev_check_2625 (EV_P) -{ - /* kernels < 2.6.25 are borked - * http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html - */ - if (ev_linux_version () < 0x020619) - return; - - fs_2625 = 1; -} - -inline_size int -infy_newfd (void) -{ -#if defined IN_CLOEXEC && defined IN_NONBLOCK - int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK); - if (fd >= 0) - return fd; -#endif - return inotify_init (); -} - -inline_size void -infy_init (EV_P) -{ - if (fs_fd != -2) - return; - - fs_fd = -1; - - ev_check_2625 (EV_A); - - fs_fd = infy_newfd (); - - if (fs_fd >= 0) - { - fd_intern (fs_fd); - ev_io_init (&fs_w, infy_cb, fs_fd, EV_READ); - ev_set_priority (&fs_w, EV_MAXPRI); - ev_io_start (EV_A_ &fs_w); - ev_unref (EV_A); - } -} - -inline_size void -infy_fork (EV_P) -{ - int slot; - - if (fs_fd < 0) - return; - - ev_ref (EV_A); - ev_io_stop (EV_A_ &fs_w); - close (fs_fd); - fs_fd = infy_newfd (); - - if (fs_fd >= 0) - { - fd_intern (fs_fd); - ev_io_set (&fs_w, fs_fd, EV_READ); - ev_io_start (EV_A_ &fs_w); - ev_unref (EV_A); - } - - for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot) - { - WL w_ = fs_hash [slot].head; - fs_hash [slot].head = 0; - - while (w_) - { - ev_stat *w = (ev_stat *)w_; - w_ = w_->next; /* lets us add this watcher */ - - w->wd = -1; - - if (fs_fd >= 0) - infy_add (EV_A_ w); /* re-add, no matter what */ - else - { - w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL; - if (ev_is_active (&w->timer)) ev_ref (EV_A); - ev_timer_again (EV_A_ &w->timer); - if (ev_is_active (&w->timer)) ev_unref (EV_A); - } - } - } -} - -#endif - -#ifdef _WIN32 -# define EV_LSTAT(p,b) _stati64 (p, b) -#else -# define EV_LSTAT(p,b) lstat (p, b) -#endif - -void -ev_stat_stat (EV_P_ ev_stat *w) EV_THROW -{ - if (lstat (w->path, &w->attr) < 0) - w->attr.st_nlink = 0; - else if (!w->attr.st_nlink) - w->attr.st_nlink = 1; -} - -static void noinline -stat_timer_cb (EV_P_ ev_timer *w_, int revents) -{ - ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer)); - - ev_statdata prev = w->attr; - ev_stat_stat (EV_A_ w); - - /* memcmp doesn't work on netbsd, they.... do stuff to their struct stat */ - if ( - prev.st_dev != w->attr.st_dev - || prev.st_ino != w->attr.st_ino - || prev.st_mode != w->attr.st_mode - || prev.st_nlink != w->attr.st_nlink - || prev.st_uid != w->attr.st_uid - || prev.st_gid != w->attr.st_gid - || prev.st_rdev != w->attr.st_rdev - || prev.st_size != w->attr.st_size - || prev.st_atime != w->attr.st_atime - || prev.st_mtime != w->attr.st_mtime - || prev.st_ctime != w->attr.st_ctime - ) { - /* we only update w->prev on actual differences */ - /* in case we test more often than invoke the callback, */ - /* to ensure that prev is always different to attr */ - w->prev = prev; - - #if EV_USE_INOTIFY - if (fs_fd >= 0) - { - infy_del (EV_A_ w); - infy_add (EV_A_ w); - ev_stat_stat (EV_A_ w); /* avoid race... */ - } - #endif - - ev_feed_event (EV_A_ w, EV_STAT); - } -} - -void -ev_stat_start (EV_P_ ev_stat *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - ev_stat_stat (EV_A_ w); - - if (w->interval < MIN_STAT_INTERVAL && w->interval) - w->interval = MIN_STAT_INTERVAL; - - ev_timer_init (&w->timer, stat_timer_cb, 0., w->interval ? w->interval : DEF_STAT_INTERVAL); - ev_set_priority (&w->timer, ev_priority (w)); - -#if EV_USE_INOTIFY - infy_init (EV_A); - - if (fs_fd >= 0) - infy_add (EV_A_ w); - else -#endif - { - ev_timer_again (EV_A_ &w->timer); - ev_unref (EV_A); - } - - ev_start (EV_A_ (W)w, 1); - - EV_FREQUENT_CHECK; -} - -void -ev_stat_stop (EV_P_ ev_stat *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - -#if EV_USE_INOTIFY - infy_del (EV_A_ w); -#endif - - if (ev_is_active (&w->timer)) - { - ev_ref (EV_A); - ev_timer_stop (EV_A_ &w->timer); - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_IDLE_ENABLE -void -ev_idle_start (EV_P_ ev_idle *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - pri_adjust (EV_A_ (W)w); - - EV_FREQUENT_CHECK; - - { - int active = ++idlecnt [ABSPRI (w)]; - - ++idleall; - ev_start (EV_A_ (W)w, active); - - array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2); - idles [ABSPRI (w)][active - 1] = w; - } - - EV_FREQUENT_CHECK; -} - -void -ev_idle_stop (EV_P_ ev_idle *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - idles [ABSPRI (w)][active - 1] = idles [ABSPRI (w)][--idlecnt [ABSPRI (w)]]; - ev_active (idles [ABSPRI (w)][active - 1]) = active; - - ev_stop (EV_A_ (W)w); - --idleall; - } - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_PREPARE_ENABLE -void -ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, ++preparecnt); - array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2); - prepares [preparecnt - 1] = w; - - EV_FREQUENT_CHECK; -} - -void -ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - prepares [active - 1] = prepares [--preparecnt]; - ev_active (prepares [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_CHECK_ENABLE -void -ev_check_start (EV_P_ ev_check *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, ++checkcnt); - array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2); - checks [checkcnt - 1] = w; - - EV_FREQUENT_CHECK; -} - -void -ev_check_stop (EV_P_ ev_check *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - checks [active - 1] = checks [--checkcnt]; - ev_active (checks [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_EMBED_ENABLE -void noinline -ev_embed_sweep (EV_P_ ev_embed *w) EV_THROW -{ - ev_run (w->other, EVRUN_NOWAIT); -} - -static void -embed_io_cb (EV_P_ ev_io *io, int revents) -{ - ev_embed *w = (ev_embed *)(((char *)io) - offsetof (ev_embed, io)); - - if (ev_cb (w)) - ev_feed_event (EV_A_ (W)w, EV_EMBED); - else - ev_run (w->other, EVRUN_NOWAIT); -} - -static void -embed_prepare_cb (EV_P_ ev_prepare *prepare, int revents) -{ - ev_embed *w = (ev_embed *)(((char *)prepare) - offsetof (ev_embed, prepare)); - - { - EV_P = w->other; - - while (fdchangecnt) - { - fd_reify (EV_A); - ev_run (EV_A_ EVRUN_NOWAIT); - } - } -} - -static void -embed_fork_cb (EV_P_ ev_fork *fork_w, int revents) -{ - ev_embed *w = (ev_embed *)(((char *)fork_w) - offsetof (ev_embed, fork)); - - ev_embed_stop (EV_A_ w); - - { - EV_P = w->other; - - ev_loop_fork (EV_A); - ev_run (EV_A_ EVRUN_NOWAIT); - } - - ev_embed_start (EV_A_ w); -} - -#if 0 -static void -embed_idle_cb (EV_P_ ev_idle *idle, int revents) -{ - ev_idle_stop (EV_A_ idle); -} -#endif - -void -ev_embed_start (EV_P_ ev_embed *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - { - EV_P = w->other; - assert (("libev: loop to be embedded is not embeddable", backend & ev_embeddable_backends ())); - ev_io_init (&w->io, embed_io_cb, backend_fd, EV_READ); - } - - EV_FREQUENT_CHECK; - - ev_set_priority (&w->io, ev_priority (w)); - ev_io_start (EV_A_ &w->io); - - ev_prepare_init (&w->prepare, embed_prepare_cb); - ev_set_priority (&w->prepare, EV_MINPRI); - ev_prepare_start (EV_A_ &w->prepare); - - ev_fork_init (&w->fork, embed_fork_cb); - ev_fork_start (EV_A_ &w->fork); - - /*ev_idle_init (&w->idle, e,bed_idle_cb);*/ - - ev_start (EV_A_ (W)w, 1); - - EV_FREQUENT_CHECK; -} - -void -ev_embed_stop (EV_P_ ev_embed *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_io_stop (EV_A_ &w->io); - ev_prepare_stop (EV_A_ &w->prepare); - ev_fork_stop (EV_A_ &w->fork); - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_FORK_ENABLE -void -ev_fork_start (EV_P_ ev_fork *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, ++forkcnt); - array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2); - forks [forkcnt - 1] = w; - - EV_FREQUENT_CHECK; -} - -void -ev_fork_stop (EV_P_ ev_fork *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - forks [active - 1] = forks [--forkcnt]; - ev_active (forks [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_CLEANUP_ENABLE -void -ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, ++cleanupcnt); - array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, EMPTY2); - cleanups [cleanupcnt - 1] = w; - - /* cleanup watchers should never keep a refcount on the loop */ - ev_unref (EV_A); - EV_FREQUENT_CHECK; -} - -void -ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - ev_ref (EV_A); - - { - int active = ev_active (w); - - cleanups [active - 1] = cleanups [--cleanupcnt]; - ev_active (cleanups [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_ASYNC_ENABLE -void -ev_async_start (EV_P_ ev_async *w) EV_THROW -{ - if (expect_false (ev_is_active (w))) - return; - - w->sent = 0; - - evpipe_init (EV_A); - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, ++asynccnt); - array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2); - asyncs [asynccnt - 1] = w; - - EV_FREQUENT_CHECK; -} - -void -ev_async_stop (EV_P_ ev_async *w) EV_THROW -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - asyncs [active - 1] = asyncs [--asynccnt]; - ev_active (asyncs [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} - -void -ev_async_send (EV_P_ ev_async *w) EV_THROW -{ - w->sent = 1; - evpipe_write (EV_A_ &async_pending); -} -#endif - -/*****************************************************************************/ - -struct ev_once -{ - ev_io io; - ev_timer to; - void (*cb)(int revents, void *arg); - void *arg; -}; - -static void -once_cb (EV_P_ struct ev_once *once, int revents) -{ - void (*cb)(int revents, void *arg) = once->cb; - void *arg = once->arg; - - ev_io_stop (EV_A_ &once->io); - ev_timer_stop (EV_A_ &once->to); - ev_free (once); - - cb (revents, arg); -} - -static void -once_cb_io (EV_P_ ev_io *w, int revents) -{ - struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, io)); - - once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->to)); -} - -static void -once_cb_to (EV_P_ ev_timer *w, int revents) -{ - struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, to)); - - once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->io)); -} - -void -ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW -{ - struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once)); - - if (expect_false (!once)) - { - cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg); - return; - } - - once->cb = cb; - once->arg = arg; - - ev_init (&once->io, once_cb_io); - if (fd >= 0) - { - ev_io_set (&once->io, fd, events); - ev_io_start (EV_A_ &once->io); - } - - ev_init (&once->to, once_cb_to); - if (timeout >= 0.) - { - ev_timer_set (&once->to, timeout, 0.); - ev_timer_start (EV_A_ &once->to); - } -} - -/*****************************************************************************/ - -#if EV_WALK_ENABLE -void ecb_cold -ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW -{ - int i, j; - ev_watcher_list *wl, *wn; - - if (types & (EV_IO | EV_EMBED)) - for (i = 0; i < anfdmax; ++i) - for (wl = anfds [i].head; wl; ) - { - wn = wl->next; - -#if EV_EMBED_ENABLE - if (ev_cb ((ev_io *)wl) == embed_io_cb) - { - if (types & EV_EMBED) - cb (EV_A_ EV_EMBED, ((char *)wl) - offsetof (struct ev_embed, io)); - } - else -#endif -#if EV_USE_INOTIFY - if (ev_cb ((ev_io *)wl) == infy_cb) - ; - else -#endif - if ((ev_io *)wl != &pipe_w) - if (types & EV_IO) - cb (EV_A_ EV_IO, wl); - - wl = wn; - } - - if (types & (EV_TIMER | EV_STAT)) - for (i = timercnt + HEAP0; i-- > HEAP0; ) -#if EV_STAT_ENABLE - /*TODO: timer is not always active*/ - if (ev_cb ((ev_timer *)ANHE_w (timers [i])) == stat_timer_cb) - { - if (types & EV_STAT) - cb (EV_A_ EV_STAT, ((char *)ANHE_w (timers [i])) - offsetof (struct ev_stat, timer)); - } - else -#endif - if (types & EV_TIMER) - cb (EV_A_ EV_TIMER, ANHE_w (timers [i])); - -#if EV_PERIODIC_ENABLE - if (types & EV_PERIODIC) - for (i = periodiccnt + HEAP0; i-- > HEAP0; ) - cb (EV_A_ EV_PERIODIC, ANHE_w (periodics [i])); -#endif - -#if EV_IDLE_ENABLE - if (types & EV_IDLE) - for (j = NUMPRI; j--; ) - for (i = idlecnt [j]; i--; ) - cb (EV_A_ EV_IDLE, idles [j][i]); -#endif - -#if EV_FORK_ENABLE - if (types & EV_FORK) - for (i = forkcnt; i--; ) - if (ev_cb (forks [i]) != embed_fork_cb) - cb (EV_A_ EV_FORK, forks [i]); -#endif - -#if EV_ASYNC_ENABLE - if (types & EV_ASYNC) - for (i = asynccnt; i--; ) - cb (EV_A_ EV_ASYNC, asyncs [i]); -#endif - -#if EV_PREPARE_ENABLE - if (types & EV_PREPARE) - for (i = preparecnt; i--; ) -# if EV_EMBED_ENABLE - if (ev_cb (prepares [i]) != embed_prepare_cb) -# endif - cb (EV_A_ EV_PREPARE, prepares [i]); -#endif - -#if EV_CHECK_ENABLE - if (types & EV_CHECK) - for (i = checkcnt; i--; ) - cb (EV_A_ EV_CHECK, checks [i]); -#endif - -#if EV_SIGNAL_ENABLE - if (types & EV_SIGNAL) - for (i = 0; i < EV_NSIG - 1; ++i) - for (wl = signals [i].head; wl; ) - { - wn = wl->next; - cb (EV_A_ EV_SIGNAL, wl); - wl = wn; - } -#endif - -#if EV_CHILD_ENABLE - if (types & EV_CHILD) - for (i = (EV_PID_HASHSIZE); i--; ) - for (wl = childs [i]; wl; ) - { - wn = wl->next; - cb (EV_A_ EV_CHILD, wl); - wl = wn; - } -#endif -/* EV_STAT 0x00001000 * stat data changed */ -/* EV_EMBED 0x00010000 * embedded event loop needs sweep */ -} -#endif - -#if EV_MULTIPLICITY - #include "ev_wrap.h" -#endif - diff --git a/framework/src/audit/src/libev/ev.h b/framework/src/audit/src/libev/ev.h deleted file mode 100644 index 7c6e7eb8..00000000 --- a/framework/src/audit/src/libev/ev.h +++ /dev/null @@ -1,854 +0,0 @@ -/* - * libev native API header - * - * Copyright (c) 2007,2008,2009,2010,2011,2012,2015 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#ifndef EV_H_ -#define EV_H_ - -#ifdef __cplusplus -# define EV_CPP(x) x -# if __cplusplus >= 201103L -# define EV_THROW noexcept -# else -# define EV_THROW throw () -# endif -#else -# define EV_CPP(x) -# define EV_THROW -#endif - -EV_CPP(extern "C" {) - -/*****************************************************************************/ - -/* pre-4.0 compatibility */ -#ifndef EV_COMPAT3 -# define EV_COMPAT3 1 -#endif - -#ifndef EV_FEATURES -# if defined __OPTIMIZE_SIZE__ -# define EV_FEATURES 0x7c -# else -# define EV_FEATURES 0x7f -# endif -#endif - -#define EV_FEATURE_CODE ((EV_FEATURES) & 1) -#define EV_FEATURE_DATA ((EV_FEATURES) & 2) -#define EV_FEATURE_CONFIG ((EV_FEATURES) & 4) -#define EV_FEATURE_API ((EV_FEATURES) & 8) -#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 16) -#define EV_FEATURE_BACKENDS ((EV_FEATURES) & 32) -#define EV_FEATURE_OS ((EV_FEATURES) & 64) - -/* these priorities are inclusive, higher priorities will be invoked earlier */ -#ifndef EV_MINPRI -# define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0) -#endif -#ifndef EV_MAXPRI -# define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0) -#endif - -#ifndef EV_MULTIPLICITY -# define EV_MULTIPLICITY EV_FEATURE_CONFIG -#endif - -#ifndef EV_PERIODIC_ENABLE -# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_STAT_ENABLE -# define EV_STAT_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_PREPARE_ENABLE -# define EV_PREPARE_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_CHECK_ENABLE -# define EV_CHECK_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_IDLE_ENABLE -# define EV_IDLE_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_FORK_ENABLE -# define EV_FORK_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_CLEANUP_ENABLE -# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_SIGNAL_ENABLE -# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_CHILD_ENABLE -# ifdef _WIN32 -# define EV_CHILD_ENABLE 0 -# else -# define EV_CHILD_ENABLE EV_FEATURE_WATCHERS -#endif -#endif - -#ifndef EV_ASYNC_ENABLE -# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_EMBED_ENABLE -# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_WALK_ENABLE -# define EV_WALK_ENABLE 0 /* not yet */ -#endif - -/*****************************************************************************/ - -#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE -# undef EV_SIGNAL_ENABLE -# define EV_SIGNAL_ENABLE 1 -#endif - -/*****************************************************************************/ - -typedef double ev_tstamp; - -#include <string.h> /* for memmove */ - -#ifndef EV_ATOMIC_T -# include <signal.h> -# define EV_ATOMIC_T sig_atomic_t volatile -#endif - -#if EV_STAT_ENABLE -# ifdef _WIN32 -# include <time.h> -# include <sys/types.h> -# endif -# include <sys/stat.h> -#endif - -/* support multiple event loops? */ -#if EV_MULTIPLICITY -struct ev_loop; -# define EV_P struct ev_loop *loop /* a loop as sole parameter in a declaration */ -# define EV_P_ EV_P, /* a loop as first of multiple parameters */ -# define EV_A loop /* a loop as sole argument to a function call */ -# define EV_A_ EV_A, /* a loop as first of multiple arguments */ -# define EV_DEFAULT_UC ev_default_loop_uc_ () /* the default loop, if initialised, as sole arg */ -# define EV_DEFAULT_UC_ EV_DEFAULT_UC, /* the default loop as first of multiple arguments */ -# define EV_DEFAULT ev_default_loop (0) /* the default loop as sole arg */ -# define EV_DEFAULT_ EV_DEFAULT, /* the default loop as first of multiple arguments */ -#else -# define EV_P void -# define EV_P_ -# define EV_A -# define EV_A_ -# define EV_DEFAULT -# define EV_DEFAULT_ -# define EV_DEFAULT_UC -# define EV_DEFAULT_UC_ -# undef EV_EMBED_ENABLE -#endif - -/* EV_INLINE is used for functions in header files */ -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L || __GNUC__ >= 3 -# define EV_INLINE static inline -#else -# define EV_INLINE static -#endif - -#ifdef EV_API_STATIC -# define EV_API_DECL static -#else -# define EV_API_DECL extern -#endif - -/* EV_PROTOTYPES can be used to switch of prototype declarations */ -#ifndef EV_PROTOTYPES -# define EV_PROTOTYPES 1 -#endif - -/*****************************************************************************/ - -#define EV_VERSION_MAJOR 4 -#define EV_VERSION_MINOR 20 - -/* eventmask, revents, events... */ -enum { - EV_UNDEF = (int)0xFFFFFFFF, /* guaranteed to be invalid */ - EV_NONE = 0x00, /* no events */ - EV_READ = 0x01, /* ev_io detected read will not block */ - EV_WRITE = 0x02, /* ev_io detected write will not block */ - EV__IOFDSET = 0x80, /* internal use only */ - EV_IO = EV_READ, /* alias for type-detection */ - EV_TIMER = 0x00000100, /* timer timed out */ -#if EV_COMPAT3 - EV_TIMEOUT = EV_TIMER, /* pre 4.0 API compatibility */ -#endif - EV_PERIODIC = 0x00000200, /* periodic timer timed out */ - EV_SIGNAL = 0x00000400, /* signal was received */ - EV_CHILD = 0x00000800, /* child/pid had status change */ - EV_STAT = 0x00001000, /* stat data changed */ - EV_IDLE = 0x00002000, /* event loop is idling */ - EV_PREPARE = 0x00004000, /* event loop about to poll */ - EV_CHECK = 0x00008000, /* event loop finished poll */ - EV_EMBED = 0x00010000, /* embedded event loop needs sweep */ - EV_FORK = 0x00020000, /* event loop resumed in child */ - EV_CLEANUP = 0x00040000, /* event loop resumed in child */ - EV_ASYNC = 0x00080000, /* async intra-loop signal */ - EV_CUSTOM = 0x01000000, /* for use by user code */ - EV_ERROR = (int)0x80000000 /* sent when an error occurs */ -}; - -/* can be used to add custom fields to all watchers, while losing binary compatibility */ -#ifndef EV_COMMON -# define EV_COMMON void *data; -#endif - -#ifndef EV_CB_DECLARE -# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents); -#endif -#ifndef EV_CB_INVOKE -# define EV_CB_INVOKE(watcher,revents) (watcher)->cb (EV_A_ (watcher), (revents)) -#endif - -/* not official, do not use */ -#define EV_CB(type,name) void name (EV_P_ struct ev_ ## type *w, int revents) - -/* - * struct member types: - * private: you may look at them, but not change them, - * and they might not mean anything to you. - * ro: can be read anytime, but only changed when the watcher isn't active. - * rw: can be read and modified anytime, even when the watcher is active. - * - * some internal details that might be helpful for debugging: - * - * active is either 0, which means the watcher is not active, - * or the array index of the watcher (periodics, timers) - * or the array index + 1 (most other watchers) - * or simply 1 for watchers that aren't in some array. - * pending is either 0, in which case the watcher isn't, - * or the array index + 1 in the pendings array. - */ - -#if EV_MINPRI == EV_MAXPRI -# define EV_DECL_PRIORITY -#elif !defined (EV_DECL_PRIORITY) -# define EV_DECL_PRIORITY int priority; -#endif - -/* shared by all watchers */ -#define EV_WATCHER(type) \ - int active; /* private */ \ - int pending; /* private */ \ - EV_DECL_PRIORITY /* private */ \ - EV_COMMON /* rw */ \ - EV_CB_DECLARE (type) /* private */ - -#define EV_WATCHER_LIST(type) \ - EV_WATCHER (type) \ - struct ev_watcher_list *next; /* private */ - -#define EV_WATCHER_TIME(type) \ - EV_WATCHER (type) \ - ev_tstamp at; /* private */ - -/* base class, nothing to see here unless you subclass */ -typedef struct ev_watcher -{ - EV_WATCHER (ev_watcher) -} ev_watcher; - -/* base class, nothing to see here unless you subclass */ -typedef struct ev_watcher_list -{ - EV_WATCHER_LIST (ev_watcher_list) -} ev_watcher_list; - -/* base class, nothing to see here unless you subclass */ -typedef struct ev_watcher_time -{ - EV_WATCHER_TIME (ev_watcher_time) -} ev_watcher_time; - -/* invoked when fd is either EV_READable or EV_WRITEable */ -/* revent EV_READ, EV_WRITE */ -typedef struct ev_io -{ - EV_WATCHER_LIST (ev_io) - - int fd; /* ro */ - int events; /* ro */ -} ev_io; - -/* invoked after a specific time, repeatable (based on monotonic clock) */ -/* revent EV_TIMEOUT */ -typedef struct ev_timer -{ - EV_WATCHER_TIME (ev_timer) - - ev_tstamp repeat; /* rw */ -} ev_timer; - -/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */ -/* revent EV_PERIODIC */ -typedef struct ev_periodic -{ - EV_WATCHER_TIME (ev_periodic) - - ev_tstamp offset; /* rw */ - ev_tstamp interval; /* rw */ - ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now) EV_THROW; /* rw */ -} ev_periodic; - -/* invoked when the given signal has been received */ -/* revent EV_SIGNAL */ -typedef struct ev_signal -{ - EV_WATCHER_LIST (ev_signal) - - int signum; /* ro */ -} ev_signal; - -/* invoked when sigchld is received and waitpid indicates the given pid */ -/* revent EV_CHILD */ -/* does not support priorities */ -typedef struct ev_child -{ - EV_WATCHER_LIST (ev_child) - - int flags; /* private */ - int pid; /* ro */ - int rpid; /* rw, holds the received pid */ - int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */ -} ev_child; - -#if EV_STAT_ENABLE -/* st_nlink = 0 means missing file or other error */ -# ifdef _WIN32 -typedef struct _stati64 ev_statdata; -# else -typedef struct stat ev_statdata; -# endif - -/* invoked each time the stat data changes for a given path */ -/* revent EV_STAT */ -typedef struct ev_stat -{ - EV_WATCHER_LIST (ev_stat) - - ev_timer timer; /* private */ - ev_tstamp interval; /* ro */ - const char *path; /* ro */ - ev_statdata prev; /* ro */ - ev_statdata attr; /* ro */ - - int wd; /* wd for inotify, fd for kqueue */ -} ev_stat; -#endif - -#if EV_IDLE_ENABLE -/* invoked when the nothing else needs to be done, keeps the process from blocking */ -/* revent EV_IDLE */ -typedef struct ev_idle -{ - EV_WATCHER (ev_idle) -} ev_idle; -#endif - -/* invoked for each run of the mainloop, just before the blocking call */ -/* you can still change events in any way you like */ -/* revent EV_PREPARE */ -typedef struct ev_prepare -{ - EV_WATCHER (ev_prepare) -} ev_prepare; - -/* invoked for each run of the mainloop, just after the blocking call */ -/* revent EV_CHECK */ -typedef struct ev_check -{ - EV_WATCHER (ev_check) -} ev_check; - -#if EV_FORK_ENABLE -/* the callback gets invoked before check in the child process when a fork was detected */ -/* revent EV_FORK */ -typedef struct ev_fork -{ - EV_WATCHER (ev_fork) -} ev_fork; -#endif - -#if EV_CLEANUP_ENABLE -/* is invoked just before the loop gets destroyed */ -/* revent EV_CLEANUP */ -typedef struct ev_cleanup -{ - EV_WATCHER (ev_cleanup) -} ev_cleanup; -#endif - -#if EV_EMBED_ENABLE -/* used to embed an event loop inside another */ -/* the callback gets invoked when the event loop has handled events, and can be 0 */ -typedef struct ev_embed -{ - EV_WATCHER (ev_embed) - - struct ev_loop *other; /* ro */ - ev_io io; /* private */ - ev_prepare prepare; /* private */ - ev_check check; /* unused */ - ev_timer timer; /* unused */ - ev_periodic periodic; /* unused */ - ev_idle idle; /* unused */ - ev_fork fork; /* private */ -#if EV_CLEANUP_ENABLE - ev_cleanup cleanup; /* unused */ -#endif -} ev_embed; -#endif - -#if EV_ASYNC_ENABLE -/* invoked when somebody calls ev_async_send on the watcher */ -/* revent EV_ASYNC */ -typedef struct ev_async -{ - EV_WATCHER (ev_async) - - EV_ATOMIC_T sent; /* private */ -} ev_async; - -# define ev_async_pending(w) (+(w)->sent) -#endif - -/* the presence of this union forces similar struct layout */ -union ev_any_watcher -{ - struct ev_watcher w; - struct ev_watcher_list wl; - - struct ev_io io; - struct ev_timer timer; - struct ev_periodic periodic; - struct ev_signal signal; - struct ev_child child; -#if EV_STAT_ENABLE - struct ev_stat stat; -#endif -#if EV_IDLE_ENABLE - struct ev_idle idle; -#endif - struct ev_prepare prepare; - struct ev_check check; -#if EV_FORK_ENABLE - struct ev_fork fork; -#endif -#if EV_CLEANUP_ENABLE - struct ev_cleanup cleanup; -#endif -#if EV_EMBED_ENABLE - struct ev_embed embed; -#endif -#if EV_ASYNC_ENABLE - struct ev_async async; -#endif -}; - -/* flag bits for ev_default_loop and ev_loop_new */ -enum { - /* the default */ - EVFLAG_AUTO = 0x00000000U, /* not quite a mask */ - /* flag bits */ - EVFLAG_NOENV = 0x01000000U, /* do NOT consult environment */ - EVFLAG_FORKCHECK = 0x02000000U, /* check for a fork in each iteration */ - /* debugging/feature disable */ - EVFLAG_NOINOTIFY = 0x00100000U, /* do not attempt to use inotify */ -#if EV_COMPAT3 - EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */ -#endif - EVFLAG_SIGNALFD = 0x00200000U, /* attempt to use signalfd */ - EVFLAG_NOSIGMASK = 0x00400000U /* avoid modifying the signal mask */ -}; - -/* method bits to be ored together */ -enum { - EVBACKEND_SELECT = 0x00000001U, /* about anywhere */ - EVBACKEND_POLL = 0x00000002U, /* !win */ - EVBACKEND_EPOLL = 0x00000004U, /* linux */ - EVBACKEND_KQUEUE = 0x00000008U, /* bsd */ - EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */ - EVBACKEND_PORT = 0x00000020U, /* solaris 10 */ - EVBACKEND_ALL = 0x0000003FU, /* all known backends */ - EVBACKEND_MASK = 0x0000FFFFU /* all future backends */ -}; - -#if EV_PROTOTYPES -EV_API_DECL int ev_version_major (void) EV_THROW; -EV_API_DECL int ev_version_minor (void) EV_THROW; - -EV_API_DECL unsigned int ev_supported_backends (void) EV_THROW; -EV_API_DECL unsigned int ev_recommended_backends (void) EV_THROW; -EV_API_DECL unsigned int ev_embeddable_backends (void) EV_THROW; - -EV_API_DECL ev_tstamp ev_time (void) EV_THROW; -EV_API_DECL void ev_sleep (ev_tstamp delay) EV_THROW; /* sleep for a while */ - -/* Sets the allocation function to use, works like realloc. - * It is used to allocate and free memory. - * If it returns zero when memory needs to be allocated, the library might abort - * or take some potentially destructive action. - * The default is your system realloc function. - */ -EV_API_DECL void ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW; - -/* set the callback function to call on a - * retryable syscall error - * (such as failed select, poll, epoll_wait) - */ -EV_API_DECL void ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW; - -#if EV_MULTIPLICITY - -/* the default loop is the only one that handles signals and child watchers */ -/* you can call this as often as you like */ -EV_API_DECL struct ev_loop *ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_THROW; - -#ifdef EV_API_STATIC -EV_API_DECL struct ev_loop *ev_default_loop_ptr; -#endif - -EV_INLINE struct ev_loop * -ev_default_loop_uc_ (void) EV_THROW -{ - extern struct ev_loop *ev_default_loop_ptr; - - return ev_default_loop_ptr; -} - -EV_INLINE int -ev_is_default_loop (EV_P) EV_THROW -{ - return EV_A == EV_DEFAULT_UC; -} - -/* create and destroy alternative loops that don't handle signals */ -EV_API_DECL struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0)) EV_THROW; - -EV_API_DECL ev_tstamp ev_now (EV_P) EV_THROW; /* time w.r.t. timers and the eventloop, updated after each poll */ - -#else - -EV_API_DECL int ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_THROW; /* returns true when successful */ - -EV_API_DECL ev_tstamp ev_rt_now; - -EV_INLINE ev_tstamp -ev_now (void) EV_THROW -{ - return ev_rt_now; -} - -/* looks weird, but ev_is_default_loop (EV_A) still works if this exists */ -EV_INLINE int -ev_is_default_loop (void) EV_THROW -{ - return 1; -} - -#endif /* multiplicity */ - -/* destroy event loops, also works for the default loop */ -EV_API_DECL void ev_loop_destroy (EV_P); - -/* this needs to be called after fork, to duplicate the loop */ -/* when you want to re-use it in the child */ -/* you can call it in either the parent or the child */ -/* you can actually call it at any time, anywhere :) */ -EV_API_DECL void ev_loop_fork (EV_P) EV_THROW; - -EV_API_DECL unsigned int ev_backend (EV_P) EV_THROW; /* backend in use by loop */ - -EV_API_DECL void ev_now_update (EV_P) EV_THROW; /* update event loop time */ - -#if EV_WALK_ENABLE -/* walk (almost) all watchers in the loop of a given type, invoking the */ -/* callback on every such watcher. The callback might stop the watcher, */ -/* but do nothing else with the loop */ -EV_API_DECL void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW; -#endif - -#endif /* prototypes */ - -/* ev_run flags values */ -enum { - EVRUN_NOWAIT = 1, /* do not block/wait */ - EVRUN_ONCE = 2 /* block *once* only */ -}; - -/* ev_break how values */ -enum { - EVBREAK_CANCEL = 0, /* undo unloop */ - EVBREAK_ONE = 1, /* unloop once */ - EVBREAK_ALL = 2 /* unloop all loops */ -}; - -#if EV_PROTOTYPES -EV_API_DECL int ev_run (EV_P_ int flags EV_CPP (= 0)); -EV_API_DECL void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)) EV_THROW; /* break out of the loop */ - -/* - * ref/unref can be used to add or remove a refcount on the mainloop. every watcher - * keeps one reference. if you have a long-running watcher you never unregister that - * should not keep ev_loop from running, unref() after starting, and ref() before stopping. - */ -EV_API_DECL void ev_ref (EV_P) EV_THROW; -EV_API_DECL void ev_unref (EV_P) EV_THROW; - -/* - * convenience function, wait for a single event, without registering an event watcher - * if timeout is < 0, do wait indefinitely - */ -EV_API_DECL void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW; - -# if EV_FEATURE_API -EV_API_DECL unsigned int ev_iteration (EV_P) EV_THROW; /* number of loop iterations */ -EV_API_DECL unsigned int ev_depth (EV_P) EV_THROW; /* #ev_loop enters - #ev_loop leaves */ -EV_API_DECL void ev_verify (EV_P) EV_THROW; /* abort if loop data corrupted */ - -EV_API_DECL void ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW; /* sleep at least this time, default 0 */ -EV_API_DECL void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW; /* sleep at least this time, default 0 */ - -/* advanced stuff for threading etc. support, see docs */ -EV_API_DECL void ev_set_userdata (EV_P_ void *data) EV_THROW; -EV_API_DECL void *ev_userdata (EV_P) EV_THROW; -typedef void (*ev_loop_callback)(EV_P); -EV_API_DECL void ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW; -/* C++ doesn't allow the use of the ev_loop_callback typedef here, so we need to spell it out */ -EV_API_DECL void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW; - -EV_API_DECL unsigned int ev_pending_count (EV_P) EV_THROW; /* number of pending events, if any */ -EV_API_DECL void ev_invoke_pending (EV_P); /* invoke all pending watchers */ - -/* - * stop/start the timer handling. - */ -EV_API_DECL void ev_suspend (EV_P) EV_THROW; -EV_API_DECL void ev_resume (EV_P) EV_THROW; -#endif - -#endif - -/* these may evaluate ev multiple times, and the other arguments at most once */ -/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */ -#define ev_init(ev,cb_) do { \ - ((ev_watcher *)(void *)(ev))->active = \ - ((ev_watcher *)(void *)(ev))->pending = 0; \ - ev_set_priority ((ev), 0); \ - ev_set_cb ((ev), cb_); \ -} while (0) - -#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV__IOFDSET; } while (0) -#define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0) -#define ev_periodic_set(ev,ofs_,ival_,rcb_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0) -#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0) -#define ev_child_set(ev,pid_,trace_) do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0) -#define ev_stat_set(ev,path_,interval_) do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0) -#define ev_idle_set(ev) /* nop, yes, this is a serious in-joke */ -#define ev_prepare_set(ev) /* nop, yes, this is a serious in-joke */ -#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */ -#define ev_embed_set(ev,other_) do { (ev)->other = (other_); } while (0) -#define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */ -#define ev_cleanup_set(ev) /* nop, yes, this is a serious in-joke */ -#define ev_async_set(ev) /* nop, yes, this is a serious in-joke */ - -#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0) -#define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0) -#define ev_periodic_init(ev,cb,ofs,ival,rcb) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(ofs),(ival),(rcb)); } while (0) -#define ev_signal_init(ev,cb,signum) do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0) -#define ev_child_init(ev,cb,pid,trace) do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0) -#define ev_stat_init(ev,cb,path,interval) do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0) -#define ev_idle_init(ev,cb) do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0) -#define ev_prepare_init(ev,cb) do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0) -#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0) -#define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0) -#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0) -#define ev_cleanup_init(ev,cb) do { ev_init ((ev), (cb)); ev_cleanup_set ((ev)); } while (0) -#define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0) - -#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */ -#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */ - -#define ev_cb_(ev) (ev)->cb /* rw */ -#define ev_cb(ev) (memmove (&ev_cb_ (ev), &((ev_watcher *)(ev))->cb, sizeof (ev_cb_ (ev))), (ev)->cb) - -#if EV_MINPRI == EV_MAXPRI -# define ev_priority(ev) ((ev), EV_MINPRI) -# define ev_set_priority(ev,pri) ((ev), (pri)) -#else -# define ev_priority(ev) (+(((ev_watcher *)(void *)(ev))->priority)) -# define ev_set_priority(ev,pri) ( (ev_watcher *)(void *)(ev))->priority = (pri) -#endif - -#define ev_periodic_at(ev) (+((ev_watcher_time *)(ev))->at) - -#ifndef ev_set_cb -# define ev_set_cb(ev,cb_) (ev_cb_ (ev) = (cb_), memmove (&((ev_watcher *)(ev))->cb, &ev_cb_ (ev), sizeof (ev_cb_ (ev)))) -#endif - -/* stopping (enabling, adding) a watcher does nothing if it is already running */ -/* stopping (disabling, deleting) a watcher does nothing unless it's already running */ -#if EV_PROTOTYPES - -/* feeds an event into a watcher as if the event actually occurred */ -/* accepts any ev_watcher type */ -EV_API_DECL void ev_feed_event (EV_P_ void *w, int revents) EV_THROW; -EV_API_DECL void ev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW; -#if EV_SIGNAL_ENABLE -EV_API_DECL void ev_feed_signal (int signum) EV_THROW; -EV_API_DECL void ev_feed_signal_event (EV_P_ int signum) EV_THROW; -#endif -EV_API_DECL void ev_invoke (EV_P_ void *w, int revents); -EV_API_DECL int ev_clear_pending (EV_P_ void *w) EV_THROW; - -EV_API_DECL void ev_io_start (EV_P_ ev_io *w) EV_THROW; -EV_API_DECL void ev_io_stop (EV_P_ ev_io *w) EV_THROW; - -EV_API_DECL void ev_timer_start (EV_P_ ev_timer *w) EV_THROW; -EV_API_DECL void ev_timer_stop (EV_P_ ev_timer *w) EV_THROW; -/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */ -EV_API_DECL void ev_timer_again (EV_P_ ev_timer *w) EV_THROW; -/* return remaining time */ -EV_API_DECL ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW; - -#if EV_PERIODIC_ENABLE -EV_API_DECL void ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW; -EV_API_DECL void ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW; -EV_API_DECL void ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW; -#endif - -/* only supported in the default loop */ -#if EV_SIGNAL_ENABLE -EV_API_DECL void ev_signal_start (EV_P_ ev_signal *w) EV_THROW; -EV_API_DECL void ev_signal_stop (EV_P_ ev_signal *w) EV_THROW; -#endif - -/* only supported in the default loop */ -# if EV_CHILD_ENABLE -EV_API_DECL void ev_child_start (EV_P_ ev_child *w) EV_THROW; -EV_API_DECL void ev_child_stop (EV_P_ ev_child *w) EV_THROW; -# endif - -# if EV_STAT_ENABLE -EV_API_DECL void ev_stat_start (EV_P_ ev_stat *w) EV_THROW; -EV_API_DECL void ev_stat_stop (EV_P_ ev_stat *w) EV_THROW; -EV_API_DECL void ev_stat_stat (EV_P_ ev_stat *w) EV_THROW; -# endif - -# if EV_IDLE_ENABLE -EV_API_DECL void ev_idle_start (EV_P_ ev_idle *w) EV_THROW; -EV_API_DECL void ev_idle_stop (EV_P_ ev_idle *w) EV_THROW; -# endif - -#if EV_PREPARE_ENABLE -EV_API_DECL void ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW; -EV_API_DECL void ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW; -#endif - -#if EV_CHECK_ENABLE -EV_API_DECL void ev_check_start (EV_P_ ev_check *w) EV_THROW; -EV_API_DECL void ev_check_stop (EV_P_ ev_check *w) EV_THROW; -#endif - -# if EV_FORK_ENABLE -EV_API_DECL void ev_fork_start (EV_P_ ev_fork *w) EV_THROW; -EV_API_DECL void ev_fork_stop (EV_P_ ev_fork *w) EV_THROW; -# endif - -# if EV_CLEANUP_ENABLE -EV_API_DECL void ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW; -EV_API_DECL void ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW; -# endif - -# if EV_EMBED_ENABLE -/* only supported when loop to be embedded is in fact embeddable */ -EV_API_DECL void ev_embed_start (EV_P_ ev_embed *w) EV_THROW; -EV_API_DECL void ev_embed_stop (EV_P_ ev_embed *w) EV_THROW; -EV_API_DECL void ev_embed_sweep (EV_P_ ev_embed *w) EV_THROW; -# endif - -# if EV_ASYNC_ENABLE -EV_API_DECL void ev_async_start (EV_P_ ev_async *w) EV_THROW; -EV_API_DECL void ev_async_stop (EV_P_ ev_async *w) EV_THROW; -EV_API_DECL void ev_async_send (EV_P_ ev_async *w) EV_THROW; -# endif - -#if EV_COMPAT3 - #define EVLOOP_NONBLOCK EVRUN_NOWAIT - #define EVLOOP_ONESHOT EVRUN_ONCE - #define EVUNLOOP_CANCEL EVBREAK_CANCEL - #define EVUNLOOP_ONE EVBREAK_ONE - #define EVUNLOOP_ALL EVBREAK_ALL - #if EV_PROTOTYPES - EV_INLINE void ev_loop (EV_P_ int flags) { ev_run (EV_A_ flags); } - EV_INLINE void ev_unloop (EV_P_ int how ) { ev_break (EV_A_ how ); } - EV_INLINE void ev_default_destroy (void) { ev_loop_destroy (EV_DEFAULT); } - EV_INLINE void ev_default_fork (void) { ev_loop_fork (EV_DEFAULT); } - #if EV_FEATURE_API - EV_INLINE unsigned int ev_loop_count (EV_P) { return ev_iteration (EV_A); } - EV_INLINE unsigned int ev_loop_depth (EV_P) { return ev_depth (EV_A); } - EV_INLINE void ev_loop_verify (EV_P) { ev_verify (EV_A); } - #endif - #endif -#else - typedef struct ev_loop ev_loop; -#endif - -#endif - -EV_CPP(}) - -#endif - diff --git a/framework/src/audit/src/libev/ev_epoll.c b/framework/src/audit/src/libev/ev_epoll.c deleted file mode 100644 index 8a9b20f6..00000000 --- a/framework/src/audit/src/libev/ev_epoll.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * libev epoll fd activity backend - * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -/* - * general notes about epoll: - * - * a) epoll silently removes fds from the fd set. as nothing tells us - * that an fd has been removed otherwise, we have to continually - * "rearm" fds that we suspect *might* have changed (same - * problem with kqueue, but much less costly there). - * b) the fact that ADD != MOD creates a lot of extra syscalls due to a) - * and seems not to have any advantage. - * c) the inability to handle fork or file descriptors (think dup) - * limits the applicability over poll, so this is not a generic - * poll replacement. - * d) epoll doesn't work the same as select with many file descriptors - * (such as files). while not critical, no other advanced interface - * seems to share this (rather non-unixy) limitation. - * e) epoll claims to be embeddable, but in practise you never get - * a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32). - * f) epoll_ctl returning EPERM means the fd is always ready. - * - * lots of "weird code" and complication handling in this file is due - * to these design problems with epoll, as we try very hard to avoid - * epoll_ctl syscalls for common usage patterns and handle the breakage - * ensuing from receiving events for closed and otherwise long gone - * file descriptors. - */ - -#include <sys/epoll.h> - -#define EV_EMASK_EPERM 0x80 - -static void -epoll_modify (EV_P_ int fd, int oev, int nev) -{ - struct epoll_event ev; - unsigned char oldmask; - - /* - * we handle EPOLL_CTL_DEL by ignoring it here - * on the assumption that the fd is gone anyways - * if that is wrong, we have to handle the spurious - * event in epoll_poll. - * if the fd is added again, we try to ADD it, and, if that - * fails, we assume it still has the same eventmask. - */ - if (!nev) - return; - - oldmask = anfds [fd].emask; - anfds [fd].emask = nev; - - /* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */ - ev.data.u64 = (uint64_t)(uint32_t)fd - | ((uint64_t)(uint32_t)++anfds [fd].egen << 32); - ev.events = (nev & EV_READ ? EPOLLIN : 0) - | (nev & EV_WRITE ? EPOLLOUT : 0); - - if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) - return; - - if (expect_true (errno == ENOENT)) - { - /* if ENOENT then the fd went away, so try to do the right thing */ - if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev)) - return; - } - else if (expect_true (errno == EEXIST)) - { - /* EEXIST means we ignored a previous DEL, but the fd is still active */ - /* if the kernel mask is the same as the new mask, we assume it hasn't changed */ - if (oldmask == nev) - goto dec_egen; - - if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev)) - return; - } - else if (expect_true (errno == EPERM)) - { - /* EPERM means the fd is always ready, but epoll is too snobbish */ - /* to handle it, unlike select or poll. */ - anfds [fd].emask = EV_EMASK_EPERM; - - /* add fd to epoll_eperms, if not already inside */ - if (!(oldmask & EV_EMASK_EPERM)) - { - array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2); - epoll_eperms [epoll_epermcnt++] = fd; - } - - return; - } - - fd_kill (EV_A_ fd); - -dec_egen: - /* we didn't successfully call epoll_ctl, so decrement the generation counter again */ - --anfds [fd].egen; -} - -static void -epoll_poll (EV_P_ ev_tstamp timeout) -{ - int i; - int eventcnt; - - if (expect_false (epoll_epermcnt)) - timeout = 0.; - - /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */ - /* the default libev max wait time, however. */ - EV_RELEASE_CB; - eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, timeout * 1e3); - EV_ACQUIRE_CB; - - if (expect_false (eventcnt < 0)) - { - if (errno != EINTR) - ev_syserr ("(libev) epoll_wait"); - - return; - } - - for (i = 0; i < eventcnt; ++i) - { - struct epoll_event *ev = epoll_events + i; - - int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */ - int want = anfds [fd].events; - int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0) - | (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0); - - /* - * check for spurious notification. - * this only finds spurious notifications on egen updates - * other spurious notifications will be found by epoll_ctl, below - * we assume that fd is always in range, as we never shrink the anfds array - */ - if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32))) - { - /* recreate kernel state */ - postfork = 1; - continue; - } - - if (expect_false (got & ~want)) - { - anfds [fd].emask = want; - - /* - * we received an event but are not interested in it, try mod or del - * this often happens because we optimistically do not unregister fds - * when we are no longer interested in them, but also when we get spurious - * notifications for fds from another process. this is partially handled - * above with the gencounter check (== our fd is not the event fd), and - * partially here, when epoll_ctl returns an error (== a child has the fd - * but we closed it). - */ - ev->events = (want & EV_READ ? EPOLLIN : 0) - | (want & EV_WRITE ? EPOLLOUT : 0); - - /* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, */ - /* which is fortunately easy to do for us. */ - if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev)) - { - postfork = 1; /* an error occurred, recreate kernel state */ - continue; - } - } - - fd_event (EV_A_ fd, got); - } - - /* if the receive array was full, increase its size */ - if (expect_false (eventcnt == epoll_eventmax)) - { - ev_free (epoll_events); - epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1); - epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); - } - - /* now synthesize events for all fds where epoll fails, while select works... */ - for (i = epoll_epermcnt; i--; ) - { - int fd = epoll_eperms [i]; - unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE); - - if (anfds [fd].emask & EV_EMASK_EPERM && events) - fd_event (EV_A_ fd, events); - else - { - epoll_eperms [i] = epoll_eperms [--epoll_epermcnt]; - anfds [fd].emask = 0; - } - } -} - -int inline_size -epoll_init (EV_P_ int flags) -{ -#ifdef EPOLL_CLOEXEC - backend_fd = epoll_create1 (EPOLL_CLOEXEC); - - if (backend_fd < 0 && (errno == EINVAL || errno == ENOSYS)) -#endif - backend_fd = epoll_create (256); - - if (backend_fd < 0) - return 0; - - fcntl (backend_fd, F_SETFD, FD_CLOEXEC); - - backend_mintime = 1e-3; /* epoll does sometimes return early, this is just to avoid the worst */ - backend_modify = epoll_modify; - backend_poll = epoll_poll; - - epoll_eventmax = 64; /* initial number of events receivable per poll */ - epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); - - return EVBACKEND_EPOLL; -} - -void inline_size -epoll_destroy (EV_P) -{ - ev_free (epoll_events); - array_free (epoll_eperm, EMPTY); -} - -void inline_size -epoll_fork (EV_P) -{ - close (backend_fd); - - while ((backend_fd = epoll_create (256)) < 0) - ev_syserr ("(libev) epoll_create"); - - fcntl (backend_fd, F_SETFD, FD_CLOEXEC); - - fd_rearm_all (EV_A); -} - diff --git a/framework/src/audit/src/libev/ev_poll.c b/framework/src/audit/src/libev/ev_poll.c deleted file mode 100644 index 48323516..00000000 --- a/framework/src/audit/src/libev/ev_poll.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * libev poll fd activity backend - * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#include <poll.h> - -void inline_size -pollidx_init (int *base, int count) -{ - /* consider using memset (.., -1, ...), which is practically guaranteed - * to work on all systems implementing poll */ - while (count--) - *base++ = -1; -} - -static void -poll_modify (EV_P_ int fd, int oev, int nev) -{ - int idx; - - if (oev == nev) - return; - - array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init); - - idx = pollidxs [fd]; - - if (idx < 0) /* need to allocate a new pollfd */ - { - pollidxs [fd] = idx = pollcnt++; - array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2); - polls [idx].fd = fd; - } - - assert (polls [idx].fd == fd); - - if (nev) - polls [idx].events = - (nev & EV_READ ? POLLIN : 0) - | (nev & EV_WRITE ? POLLOUT : 0); - else /* remove pollfd */ - { - pollidxs [fd] = -1; - - if (expect_true (idx < --pollcnt)) - { - polls [idx] = polls [pollcnt]; - pollidxs [polls [idx].fd] = idx; - } - } -} - -static void -poll_poll (EV_P_ ev_tstamp timeout) -{ - struct pollfd *p; - int res; - - EV_RELEASE_CB; - res = poll (polls, pollcnt, timeout * 1e3); - EV_ACQUIRE_CB; - - if (expect_false (res < 0)) - { - if (errno == EBADF) - fd_ebadf (EV_A); - else if (errno == ENOMEM && !syserr_cb) - fd_enomem (EV_A); - else if (errno != EINTR) - ev_syserr ("(libev) poll"); - } - else - for (p = polls; res; ++p) - { - assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt)); - - if (expect_false (p->revents)) /* this expect is debatable */ - { - --res; - - if (expect_false (p->revents & POLLNVAL)) - fd_kill (EV_A_ p->fd); - else - fd_event ( - EV_A_ - p->fd, - (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) - | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) - ); - } - } -} - -int inline_size -poll_init (EV_P_ int flags) -{ - backend_mintime = 1e-3; - backend_modify = poll_modify; - backend_poll = poll_poll; - - pollidxs = 0; pollidxmax = 0; - polls = 0; pollmax = 0; pollcnt = 0; - - return EVBACKEND_POLL; -} - -void inline_size -poll_destroy (EV_P) -{ - ev_free (pollidxs); - ev_free (polls); -} - diff --git a/framework/src/audit/src/libev/ev_select.c b/framework/src/audit/src/libev/ev_select.c deleted file mode 100644 index f38d6ca3..00000000 --- a/framework/src/audit/src/libev/ev_select.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * libev select fd activity backend - * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#ifndef _WIN32 -/* for unix systems */ -# include <inttypes.h> -# ifndef __hpux -/* for REAL unix systems */ -# include <sys/select.h> -# endif -#endif - -#ifndef EV_SELECT_USE_FD_SET -# ifdef NFDBITS -# define EV_SELECT_USE_FD_SET 0 -# else -# define EV_SELECT_USE_FD_SET 1 -# endif -#endif - -#if EV_SELECT_IS_WINSOCKET -# undef EV_SELECT_USE_FD_SET -# define EV_SELECT_USE_FD_SET 1 -# undef NFDBITS -# define NFDBITS 0 -#endif - -#if !EV_SELECT_USE_FD_SET -# define NFDBYTES (NFDBITS / 8) -#endif - -#include <string.h> - -static void -select_modify (EV_P_ int fd, int oev, int nev) -{ - if (oev == nev) - return; - - { -#if EV_SELECT_USE_FD_SET - - #if EV_SELECT_IS_WINSOCKET - SOCKET handle = anfds [fd].handle; - #else - int handle = fd; - #endif - - assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE)); - - /* FD_SET is broken on windows (it adds the fd to a set twice or more, - * which eventually leads to overflows). Need to call it only on changes. - */ - #if EV_SELECT_IS_WINSOCKET - if ((oev ^ nev) & EV_READ) - #endif - if (nev & EV_READ) - FD_SET (handle, (fd_set *)vec_ri); - else - FD_CLR (handle, (fd_set *)vec_ri); - - #if EV_SELECT_IS_WINSOCKET - if ((oev ^ nev) & EV_WRITE) - #endif - if (nev & EV_WRITE) - FD_SET (handle, (fd_set *)vec_wi); - else - FD_CLR (handle, (fd_set *)vec_wi); - -#else - - int word = fd / NFDBITS; - fd_mask mask = 1UL << (fd % NFDBITS); - - if (expect_false (vec_max <= word)) - { - int new_max = word + 1; - - vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES); - vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */ - vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES); - vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */ - #ifdef _WIN32 - vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */ - #endif - - for (; vec_max < new_max; ++vec_max) - ((fd_mask *)vec_ri) [vec_max] = - ((fd_mask *)vec_wi) [vec_max] = 0; - } - - ((fd_mask *)vec_ri) [word] |= mask; - if (!(nev & EV_READ)) - ((fd_mask *)vec_ri) [word] &= ~mask; - - ((fd_mask *)vec_wi) [word] |= mask; - if (!(nev & EV_WRITE)) - ((fd_mask *)vec_wi) [word] &= ~mask; -#endif - } -} - -static void -select_poll (EV_P_ ev_tstamp timeout) -{ - struct timeval tv; - int res; - int fd_setsize; - - EV_RELEASE_CB; - EV_TV_SET (tv, timeout); - -#if EV_SELECT_USE_FD_SET - fd_setsize = sizeof (fd_set); -#else - fd_setsize = vec_max * NFDBYTES; -#endif - - memcpy (vec_ro, vec_ri, fd_setsize); - memcpy (vec_wo, vec_wi, fd_setsize); - -#ifdef _WIN32 - /* pass in the write set as except set. - * the idea behind this is to work around a windows bug that causes - * errors to be reported as an exception and not by setting - * the writable bit. this is so uncontrollably lame. - */ - memcpy (vec_eo, vec_wi, fd_setsize); - res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv); -#elif EV_SELECT_USE_FD_SET - fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE; - res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); -#else - res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); -#endif - EV_ACQUIRE_CB; - - if (expect_false (res < 0)) - { - #if EV_SELECT_IS_WINSOCKET - errno = WSAGetLastError (); - #endif - #ifdef WSABASEERR - /* on windows, select returns incompatible error codes, fix this */ - if (errno >= WSABASEERR && errno < WSABASEERR + 1000) - if (errno == WSAENOTSOCK) - errno = EBADF; - else - errno -= WSABASEERR; - #endif - - #ifdef _WIN32 - /* select on windows erroneously returns EINVAL when no fd sets have been - * provided (this is documented). what microsoft doesn't tell you that this bug - * exists even when the fd sets _are_ provided, so we have to check for this bug - * here and emulate by sleeping manually. - * we also get EINVAL when the timeout is invalid, but we ignore this case here - * and assume that EINVAL always means: you have to wait manually. - */ - if (errno == EINVAL) - { - if (timeout) - { - unsigned long ms = timeout * 1e3; - Sleep (ms ? ms : 1); - } - - return; - } - #endif - - if (errno == EBADF) - fd_ebadf (EV_A); - else if (errno == ENOMEM && !syserr_cb) - fd_enomem (EV_A); - else if (errno != EINTR) - ev_syserr ("(libev) select"); - - return; - } - -#if EV_SELECT_USE_FD_SET - - { - int fd; - - for (fd = 0; fd < anfdmax; ++fd) - if (anfds [fd].events) - { - int events = 0; - #if EV_SELECT_IS_WINSOCKET - SOCKET handle = anfds [fd].handle; - #else - int handle = fd; - #endif - - if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ; - if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE; - #ifdef _WIN32 - if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE; - #endif - - if (expect_true (events)) - fd_event (EV_A_ fd, events); - } - } - -#else - - { - int word, bit; - for (word = vec_max; word--; ) - { - fd_mask word_r = ((fd_mask *)vec_ro) [word]; - fd_mask word_w = ((fd_mask *)vec_wo) [word]; - #ifdef _WIN32 - word_w |= ((fd_mask *)vec_eo) [word]; - #endif - - if (word_r || word_w) - for (bit = NFDBITS; bit--; ) - { - fd_mask mask = 1UL << bit; - int events = 0; - - events |= word_r & mask ? EV_READ : 0; - events |= word_w & mask ? EV_WRITE : 0; - - if (expect_true (events)) - fd_event (EV_A_ word * NFDBITS + bit, events); - } - } - } - -#endif -} - -int inline_size -select_init (EV_P_ int flags) -{ - backend_mintime = 1e-6; - backend_modify = select_modify; - backend_poll = select_poll; - -#if EV_SELECT_USE_FD_SET - vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri); - vec_ro = ev_malloc (sizeof (fd_set)); - vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi); - vec_wo = ev_malloc (sizeof (fd_set)); - #ifdef _WIN32 - vec_eo = ev_malloc (sizeof (fd_set)); - #endif -#else - vec_max = 0; - vec_ri = 0; - vec_ro = 0; - vec_wi = 0; - vec_wo = 0; - #ifdef _WIN32 - vec_eo = 0; - #endif -#endif - - return EVBACKEND_SELECT; -} - -void inline_size -select_destroy (EV_P) -{ - ev_free (vec_ri); - ev_free (vec_ro); - ev_free (vec_wi); - ev_free (vec_wo); - #ifdef _WIN32 - ev_free (vec_eo); - #endif -} - diff --git a/framework/src/audit/src/libev/ev_vars.h b/framework/src/audit/src/libev/ev_vars.h deleted file mode 100644 index 04d4db16..00000000 --- a/framework/src/audit/src/libev/ev_vars.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * loop member variable declarations - * - * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#define VARx(type,name) VAR(name, type name) - -VARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */ -VARx(ev_tstamp, mn_now) /* monotonic clock "now" */ -VARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */ - -/* for reverse feeding of events */ -VARx(W *, rfeeds) -VARx(int, rfeedmax) -VARx(int, rfeedcnt) - -VAR (pendings, ANPENDING *pendings [NUMPRI]) -VAR (pendingmax, int pendingmax [NUMPRI]) -VAR (pendingcnt, int pendingcnt [NUMPRI]) -VARx(int, pendingpri) /* highest priority currently pending */ -VARx(ev_prepare, pending_w) /* dummy pending watcher */ - -VARx(ev_tstamp, io_blocktime) -VARx(ev_tstamp, timeout_blocktime) - -VARx(int, backend) -VARx(int, activecnt) /* total number of active events ("refcount") */ -VARx(EV_ATOMIC_T, loop_done) /* signal by ev_break */ - -VARx(int, backend_fd) -VARx(ev_tstamp, backend_mintime) /* assumed typical timer resolution */ -VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev)) -VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout)) - -VARx(ANFD *, anfds) -VARx(int, anfdmax) - -VAR (evpipe, int evpipe [2]) -VARx(ev_io, pipe_w) -VARx(EV_ATOMIC_T, pipe_write_wanted) -VARx(EV_ATOMIC_T, pipe_write_skipped) - -#if !defined(_WIN32) || EV_GENWRAP -VARx(pid_t, curpid) -#endif - -VARx(char, postfork) /* true if we need to recreate kernel state after fork */ - -#if EV_USE_SELECT || EV_GENWRAP -VARx(void *, vec_ri) -VARx(void *, vec_ro) -VARx(void *, vec_wi) -VARx(void *, vec_wo) -#if defined(_WIN32) || EV_GENWRAP -VARx(void *, vec_eo) -#endif -VARx(int, vec_max) -#endif - -#if EV_USE_POLL || EV_GENWRAP -VARx(struct pollfd *, polls) -VARx(int, pollmax) -VARx(int, pollcnt) -VARx(int *, pollidxs) /* maps fds into structure indices */ -VARx(int, pollidxmax) -#endif - -#if EV_USE_EPOLL || EV_GENWRAP -VARx(struct epoll_event *, epoll_events) -VARx(int, epoll_eventmax) -VARx(int *, epoll_eperms) -VARx(int, epoll_epermcnt) -VARx(int, epoll_epermmax) -#endif - -#if EV_USE_KQUEUE || EV_GENWRAP -VARx(pid_t, kqueue_fd_pid) -VARx(struct kevent *, kqueue_changes) -VARx(int, kqueue_changemax) -VARx(int, kqueue_changecnt) -VARx(struct kevent *, kqueue_events) -VARx(int, kqueue_eventmax) -#endif - -#if EV_USE_PORT || EV_GENWRAP -VARx(struct port_event *, port_events) -VARx(int, port_eventmax) -#endif - -#if EV_USE_IOCP || EV_GENWRAP -VARx(HANDLE, iocp) -#endif - -VARx(int *, fdchanges) -VARx(int, fdchangemax) -VARx(int, fdchangecnt) - -VARx(ANHE *, timers) -VARx(int, timermax) -VARx(int, timercnt) - -#if EV_PERIODIC_ENABLE || EV_GENWRAP -VARx(ANHE *, periodics) -VARx(int, periodicmax) -VARx(int, periodiccnt) -#endif - -#if EV_IDLE_ENABLE || EV_GENWRAP -VAR (idles, ev_idle **idles [NUMPRI]) -VAR (idlemax, int idlemax [NUMPRI]) -VAR (idlecnt, int idlecnt [NUMPRI]) -#endif -VARx(int, idleall) /* total number */ - -VARx(struct ev_prepare **, prepares) -VARx(int, preparemax) -VARx(int, preparecnt) - -VARx(struct ev_check **, checks) -VARx(int, checkmax) -VARx(int, checkcnt) - -#if EV_FORK_ENABLE || EV_GENWRAP -VARx(struct ev_fork **, forks) -VARx(int, forkmax) -VARx(int, forkcnt) -#endif - -#if EV_CLEANUP_ENABLE || EV_GENWRAP -VARx(struct ev_cleanup **, cleanups) -VARx(int, cleanupmax) -VARx(int, cleanupcnt) -#endif - -#if EV_ASYNC_ENABLE || EV_GENWRAP -VARx(EV_ATOMIC_T, async_pending) -VARx(struct ev_async **, asyncs) -VARx(int, asyncmax) -VARx(int, asynccnt) -#endif - -#if EV_USE_INOTIFY || EV_GENWRAP -VARx(int, fs_fd) -VARx(ev_io, fs_w) -VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */ -VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE]) -#endif - -VARx(EV_ATOMIC_T, sig_pending) -#if EV_USE_SIGNALFD || EV_GENWRAP -VARx(int, sigfd) -VARx(ev_io, sigfd_w) -VARx(sigset_t, sigfd_set) -#endif - -VARx(unsigned int, origflags) /* original loop flags */ - -#if EV_FEATURE_API || EV_GENWRAP -VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */ -VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */ - -VARx(void *, userdata) -/* C++ doesn't support the ev_loop_callback typedef here. stinks. */ -VAR (release_cb, void (*release_cb)(EV_P) EV_THROW) -VAR (acquire_cb, void (*acquire_cb)(EV_P) EV_THROW) -VAR (invoke_cb , ev_loop_callback invoke_cb) -#endif - -#undef VARx - diff --git a/framework/src/audit/src/libev/ev_wrap.h b/framework/src/audit/src/libev/ev_wrap.h deleted file mode 100644 index ad989ea7..00000000 --- a/framework/src/audit/src/libev/ev_wrap.h +++ /dev/null @@ -1,200 +0,0 @@ -/* DO NOT EDIT, automatically generated by update_ev_wrap */ -#ifndef EV_WRAP_H -#define EV_WRAP_H -#define acquire_cb ((loop)->acquire_cb) -#define activecnt ((loop)->activecnt) -#define anfdmax ((loop)->anfdmax) -#define anfds ((loop)->anfds) -#define async_pending ((loop)->async_pending) -#define asynccnt ((loop)->asynccnt) -#define asyncmax ((loop)->asyncmax) -#define asyncs ((loop)->asyncs) -#define backend ((loop)->backend) -#define backend_fd ((loop)->backend_fd) -#define backend_mintime ((loop)->backend_mintime) -#define backend_modify ((loop)->backend_modify) -#define backend_poll ((loop)->backend_poll) -#define checkcnt ((loop)->checkcnt) -#define checkmax ((loop)->checkmax) -#define checks ((loop)->checks) -#define cleanupcnt ((loop)->cleanupcnt) -#define cleanupmax ((loop)->cleanupmax) -#define cleanups ((loop)->cleanups) -#define curpid ((loop)->curpid) -#define epoll_epermcnt ((loop)->epoll_epermcnt) -#define epoll_epermmax ((loop)->epoll_epermmax) -#define epoll_eperms ((loop)->epoll_eperms) -#define epoll_eventmax ((loop)->epoll_eventmax) -#define epoll_events ((loop)->epoll_events) -#define evpipe ((loop)->evpipe) -#define fdchangecnt ((loop)->fdchangecnt) -#define fdchangemax ((loop)->fdchangemax) -#define fdchanges ((loop)->fdchanges) -#define forkcnt ((loop)->forkcnt) -#define forkmax ((loop)->forkmax) -#define forks ((loop)->forks) -#define fs_2625 ((loop)->fs_2625) -#define fs_fd ((loop)->fs_fd) -#define fs_hash ((loop)->fs_hash) -#define fs_w ((loop)->fs_w) -#define idleall ((loop)->idleall) -#define idlecnt ((loop)->idlecnt) -#define idlemax ((loop)->idlemax) -#define idles ((loop)->idles) -#define invoke_cb ((loop)->invoke_cb) -#define io_blocktime ((loop)->io_blocktime) -#define iocp ((loop)->iocp) -#define kqueue_changecnt ((loop)->kqueue_changecnt) -#define kqueue_changemax ((loop)->kqueue_changemax) -#define kqueue_changes ((loop)->kqueue_changes) -#define kqueue_eventmax ((loop)->kqueue_eventmax) -#define kqueue_events ((loop)->kqueue_events) -#define kqueue_fd_pid ((loop)->kqueue_fd_pid) -#define loop_count ((loop)->loop_count) -#define loop_depth ((loop)->loop_depth) -#define loop_done ((loop)->loop_done) -#define mn_now ((loop)->mn_now) -#define now_floor ((loop)->now_floor) -#define origflags ((loop)->origflags) -#define pending_w ((loop)->pending_w) -#define pendingcnt ((loop)->pendingcnt) -#define pendingmax ((loop)->pendingmax) -#define pendingpri ((loop)->pendingpri) -#define pendings ((loop)->pendings) -#define periodiccnt ((loop)->periodiccnt) -#define periodicmax ((loop)->periodicmax) -#define periodics ((loop)->periodics) -#define pipe_w ((loop)->pipe_w) -#define pipe_write_skipped ((loop)->pipe_write_skipped) -#define pipe_write_wanted ((loop)->pipe_write_wanted) -#define pollcnt ((loop)->pollcnt) -#define pollidxmax ((loop)->pollidxmax) -#define pollidxs ((loop)->pollidxs) -#define pollmax ((loop)->pollmax) -#define polls ((loop)->polls) -#define port_eventmax ((loop)->port_eventmax) -#define port_events ((loop)->port_events) -#define postfork ((loop)->postfork) -#define preparecnt ((loop)->preparecnt) -#define preparemax ((loop)->preparemax) -#define prepares ((loop)->prepares) -#define release_cb ((loop)->release_cb) -#define rfeedcnt ((loop)->rfeedcnt) -#define rfeedmax ((loop)->rfeedmax) -#define rfeeds ((loop)->rfeeds) -#define rtmn_diff ((loop)->rtmn_diff) -#define sig_pending ((loop)->sig_pending) -#define sigfd ((loop)->sigfd) -#define sigfd_set ((loop)->sigfd_set) -#define sigfd_w ((loop)->sigfd_w) -#define timeout_blocktime ((loop)->timeout_blocktime) -#define timercnt ((loop)->timercnt) -#define timermax ((loop)->timermax) -#define timers ((loop)->timers) -#define userdata ((loop)->userdata) -#define vec_eo ((loop)->vec_eo) -#define vec_max ((loop)->vec_max) -#define vec_ri ((loop)->vec_ri) -#define vec_ro ((loop)->vec_ro) -#define vec_wi ((loop)->vec_wi) -#define vec_wo ((loop)->vec_wo) -#else -#undef EV_WRAP_H -#undef acquire_cb -#undef activecnt -#undef anfdmax -#undef anfds -#undef async_pending -#undef asynccnt -#undef asyncmax -#undef asyncs -#undef backend -#undef backend_fd -#undef backend_mintime -#undef backend_modify -#undef backend_poll -#undef checkcnt -#undef checkmax -#undef checks -#undef cleanupcnt -#undef cleanupmax -#undef cleanups -#undef curpid -#undef epoll_epermcnt -#undef epoll_epermmax -#undef epoll_eperms -#undef epoll_eventmax -#undef epoll_events -#undef evpipe -#undef fdchangecnt -#undef fdchangemax -#undef fdchanges -#undef forkcnt -#undef forkmax -#undef forks -#undef fs_2625 -#undef fs_fd -#undef fs_hash -#undef fs_w -#undef idleall -#undef idlecnt -#undef idlemax -#undef idles -#undef invoke_cb -#undef io_blocktime -#undef iocp -#undef kqueue_changecnt -#undef kqueue_changemax -#undef kqueue_changes -#undef kqueue_eventmax -#undef kqueue_events -#undef kqueue_fd_pid -#undef loop_count -#undef loop_depth -#undef loop_done -#undef mn_now -#undef now_floor -#undef origflags -#undef pending_w -#undef pendingcnt -#undef pendingmax -#undef pendingpri -#undef pendings -#undef periodiccnt -#undef periodicmax -#undef periodics -#undef pipe_w -#undef pipe_write_skipped -#undef pipe_write_wanted -#undef pollcnt -#undef pollidxmax -#undef pollidxs -#undef pollmax -#undef polls -#undef port_eventmax -#undef port_events -#undef postfork -#undef preparecnt -#undef preparemax -#undef prepares -#undef release_cb -#undef rfeedcnt -#undef rfeedmax -#undef rfeeds -#undef rtmn_diff -#undef sig_pending -#undef sigfd -#undef sigfd_set -#undef sigfd_w -#undef timeout_blocktime -#undef timercnt -#undef timermax -#undef timers -#undef userdata -#undef vec_eo -#undef vec_max -#undef vec_ri -#undef vec_ro -#undef vec_wi -#undef vec_wo -#endif diff --git a/framework/src/audit/src/libev/event.c b/framework/src/audit/src/libev/event.c deleted file mode 100644 index 5586cd35..00000000 --- a/framework/src/audit/src/libev/event.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * libevent compatibility layer - * - * Copyright (c) 2007,2008,2009,2010,2012 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#include <stddef.h> -#include <stdlib.h> -#include <assert.h> - -#ifdef EV_EVENT_H -# include EV_EVENT_H -#else -# include "event.h" -#endif - -#if EV_MULTIPLICITY -# define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base -# define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base -#else -# define dLOOPev -# define dLOOPbase -#endif - -/* never accessed, will always be cast from/to ev_loop */ -struct event_base -{ - int dummy; -}; - -static struct event_base *ev_x_cur; - -static ev_tstamp -ev_tv_get (struct timeval *tv) -{ - if (tv) - { - ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6; - return after ? after : 1e-6; - } - else - return -1.; -} - -#define EVENT_STRINGIFY(s) # s -#define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b) - -const char * -event_get_version (void) -{ - /* returns ABI, not API or library, version */ - return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR); -} - -const char * -event_get_method (void) -{ - return "libev"; -} - -void *event_init (void) -{ -#if EV_MULTIPLICITY - if (ev_x_cur) - ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO); - else - ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO); -#else - assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur)); - - ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO); -#endif - - return ev_x_cur; -} - -const char * -event_base_get_method (const struct event_base *base) -{ - return "libev"; -} - -struct event_base * -event_base_new (void) -{ -#if EV_MULTIPLICITY - return (struct event_base *)ev_loop_new (EVFLAG_AUTO); -#else - assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY")); - return NULL; -#endif -} - -void event_base_free (struct event_base *base) -{ - dLOOPbase; - -#if EV_MULTIPLICITY - if (!ev_is_default_loop (loop)) - ev_loop_destroy (loop); -#endif -} - -int event_dispatch (void) -{ - return event_base_dispatch (ev_x_cur); -} - -#ifdef EV_STANDALONE -void event_set_log_callback (event_log_cb cb) -{ - /* nop */ -} -#endif - -int event_loop (int flags) -{ - return event_base_loop (ev_x_cur, flags); -} - -int event_loopexit (struct timeval *tv) -{ - return event_base_loopexit (ev_x_cur, tv); -} - -event_callback_fn event_get_callback -(const struct event *ev) -{ - return ev->ev_callback; -} - -static void -ev_x_cb (struct event *ev, int revents) -{ - revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL; - - ev->ev_res = revents; - ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg); -} - -static void -ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents) -{ - struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig)); - - if (revents & EV_ERROR) - event_del (ev); - - ev_x_cb (ev, revents); -} - -static void -ev_x_cb_io (EV_P_ struct ev_io *w, int revents) -{ - struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io)); - - if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST)) - event_del (ev); - - ev_x_cb (ev, revents); -} - -static void -ev_x_cb_to (EV_P_ struct ev_timer *w, int revents) -{ - struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to)); - - event_del (ev); - - ev_x_cb (ev, revents); -} - -void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg) -{ - if (events & EV_SIGNAL) - ev_init (&ev->iosig.sig, ev_x_cb_sig); - else - ev_init (&ev->iosig.io, ev_x_cb_io); - - ev_init (&ev->to, ev_x_cb_to); - - ev->ev_base = ev_x_cur; /* not threadsafe, but it's how libevent works */ - ev->ev_fd = fd; - ev->ev_events = events; - ev->ev_pri = 0; - ev->ev_callback = cb; - ev->ev_arg = arg; - ev->ev_res = 0; - ev->ev_flags = EVLIST_INIT; -} - -int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv) -{ - return event_base_once (ev_x_cur, fd, events, cb, arg, tv); -} - -int event_add (struct event *ev, struct timeval *tv) -{ - dLOOPev; - - if (ev->ev_events & EV_SIGNAL) - { - if (!ev_is_active (&ev->iosig.sig)) - { - ev_signal_set (&ev->iosig.sig, ev->ev_fd); - ev_signal_start (EV_A_ &ev->iosig.sig); - - ev->ev_flags |= EVLIST_SIGNAL; - } - } - else if (ev->ev_events & (EV_READ | EV_WRITE)) - { - if (!ev_is_active (&ev->iosig.io)) - { - ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE)); - ev_io_start (EV_A_ &ev->iosig.io); - - ev->ev_flags |= EVLIST_INSERTED; - } - } - - if (tv) - { - ev->to.repeat = ev_tv_get (tv); - ev_timer_again (EV_A_ &ev->to); - ev->ev_flags |= EVLIST_TIMEOUT; - } - else - { - ev_timer_stop (EV_A_ &ev->to); - ev->ev_flags &= ~EVLIST_TIMEOUT; - } - - ev->ev_flags |= EVLIST_ACTIVE; - - return 0; -} - -int event_del (struct event *ev) -{ - dLOOPev; - - if (ev->ev_events & EV_SIGNAL) - ev_signal_stop (EV_A_ &ev->iosig.sig); - else if (ev->ev_events & (EV_READ | EV_WRITE)) - ev_io_stop (EV_A_ &ev->iosig.io); - - if (ev_is_active (&ev->to)) - ev_timer_stop (EV_A_ &ev->to); - - ev->ev_flags = EVLIST_INIT; - - return 0; -} - -void event_active (struct event *ev, int res, short ncalls) -{ - dLOOPev; - - if (res & EV_TIMEOUT) - ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT); - - if (res & EV_SIGNAL) - ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL); - - if (res & (EV_READ | EV_WRITE)) - ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE)); -} - -int event_pending (struct event *ev, short events, struct timeval *tv) -{ - short revents = 0; - dLOOPev; - - if (ev->ev_events & EV_SIGNAL) - { - /* sig */ - if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig)) - revents |= EV_SIGNAL; - } - else if (ev->ev_events & (EV_READ | EV_WRITE)) - { - /* io */ - if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io)) - revents |= ev->ev_events & (EV_READ | EV_WRITE); - } - - if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to)) - { - revents |= EV_TIMEOUT; - - if (tv) - { - ev_tstamp at = ev_now (EV_A); - - tv->tv_sec = (long)at; - tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6); - } - } - - return events & revents; -} - -int event_priority_init (int npri) -{ - return event_base_priority_init (ev_x_cur, npri); -} - -int event_priority_set (struct event *ev, int pri) -{ - ev->ev_pri = pri; - - return 0; -} - -int event_base_set (struct event_base *base, struct event *ev) -{ - ev->ev_base = base; - - return 0; -} - -int event_base_loop (struct event_base *base, int flags) -{ - dLOOPbase; - - return !ev_run (EV_A_ flags); -} - -int event_base_dispatch (struct event_base *base) -{ - return event_base_loop (base, 0); -} - -static void -ev_x_loopexit_cb (int revents, void *base) -{ - dLOOPbase; - - ev_break (EV_A_ EVBREAK_ONE); -} - -int event_base_loopexit (struct event_base *base, struct timeval *tv) -{ - ev_tstamp after = ev_tv_get (tv); - dLOOPbase; - - ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base); - - return 0; -} - -struct ev_x_once -{ - int fd; - void (*cb)(int, short, void *); - void *arg; -}; - -static void -ev_x_once_cb (int revents, void *arg) -{ - struct ev_x_once *once = (struct ev_x_once *)arg; - - once->cb (once->fd, (short)revents, once->arg); - free (once); -} - -int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv) -{ - struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once)); - dLOOPbase; - - if (!once) - return -1; - - once->fd = fd; - once->cb = cb; - once->arg = arg; - - ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once); - - return 0; -} - -int event_base_priority_init (struct event_base *base, int npri) -{ - /*dLOOPbase;*/ - - return 0; -} - diff --git a/framework/src/audit/src/libev/event.h b/framework/src/audit/src/libev/event.h deleted file mode 100644 index aa81928f..00000000 --- a/framework/src/audit/src/libev/event.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * libevent compatibility header, only core events supported - * - * Copyright (c) 2007,2008,2010,2012 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#ifndef EVENT_H_ -#define EVENT_H_ - -#ifdef EV_H -# include EV_H -#else -# include "ev.h" -#endif - -#ifndef EVLOOP_NONBLOCK -# define EVLOOP_NONBLOCK EVRUN_NOWAIT -#endif -#ifndef EVLOOP_ONESHOT -# define EVLOOP_ONESHOT EVRUN_ONCE -#endif -#ifndef EV_TIMEOUT -# define EV_TIMEOUT EV_TIMER -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* we need sys/time.h for struct timeval only */ -#if !defined (WIN32) || defined (__MINGW32__) -# include <time.h> /* mingw seems to need this, for whatever reason */ -# include <sys/time.h> -#endif - -struct event_base; - -#define EVLIST_TIMEOUT 0x01 -#define EVLIST_INSERTED 0x02 -#define EVLIST_SIGNAL 0x04 -#define EVLIST_ACTIVE 0x08 -#define EVLIST_INTERNAL 0x10 -#define EVLIST_INIT 0x80 - -typedef void (*event_callback_fn)(int, short, void *); - -struct event -{ - /* libev watchers we map onto */ - union { - struct ev_io io; - struct ev_signal sig; - } iosig; - struct ev_timer to; - - /* compatibility slots */ - struct event_base *ev_base; - event_callback_fn ev_callback; - void *ev_arg; - int ev_fd; - int ev_pri; - int ev_res; - int ev_flags; - short ev_events; -}; - -event_callback_fn event_get_callback (const struct event *ev); - -#define EV_READ EV_READ -#define EV_WRITE EV_WRITE -#define EV_PERSIST 0x10 -#define EV_ET 0x20 /* nop */ - -#define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd) -#define EVENT_FD(ev) ((int) (ev)->ev_fd) - -#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) - -#define evtimer_add(ev,tv) event_add (ev, tv) -#define evtimer_set(ev,cb,data) event_set (ev, -1, 0, cb, data) -#define evtimer_del(ev) event_del (ev) -#define evtimer_pending(ev,tv) event_pending (ev, EV_TIMEOUT, tv) -#define evtimer_initialized(ev) event_initialized (ev) - -#define timeout_add(ev,tv) evtimer_add (ev, tv) -#define timeout_set(ev,cb,data) evtimer_set (ev, cb, data) -#define timeout_del(ev) evtimer_del (ev) -#define timeout_pending(ev,tv) evtimer_pending (ev, tv) -#define timeout_initialized(ev) evtimer_initialized (ev) - -#define signal_add(ev,tv) event_add (ev, tv) -#define signal_set(ev,sig,cb,data) event_set (ev, sig, EV_SIGNAL | EV_PERSIST, cb, data) -#define signal_del(ev) event_del (ev) -#define signal_pending(ev,tv) event_pending (ev, EV_SIGNAL, tv) -#define signal_initialized(ev) event_initialized (ev) - -const char *event_get_version (void); -const char *event_get_method (void); - -void *event_init (void); -void event_base_free (struct event_base *base); - -#define EVLOOP_ONCE EVLOOP_ONESHOT -int event_loop (int); -int event_loopexit (struct timeval *tv); -int event_dispatch (void); - -#define _EVENT_LOG_DEBUG 0 -#define _EVENT_LOG_MSG 1 -#define _EVENT_LOG_WARN 2 -#define _EVENT_LOG_ERR 3 -typedef void (*event_log_cb)(int severity, const char *msg); -void event_set_log_callback(event_log_cb cb); - -void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg); -int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv); - -int event_add (struct event *ev, struct timeval *tv); -int event_del (struct event *ev); -void event_active (struct event *ev, int res, short ncalls); /* ncalls is being ignored */ - -int event_pending (struct event *ev, short, struct timeval *tv); - -int event_priority_init (int npri); -int event_priority_set (struct event *ev, int pri); - -struct event_base *event_base_new (void); -const char *event_base_get_method (const struct event_base *); -int event_base_set (struct event_base *base, struct event *ev); -int event_base_loop (struct event_base *base, int); -int event_base_loopexit (struct event_base *base, struct timeval *tv); -int event_base_dispatch (struct event_base *base); -int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv); -int event_base_priority_init (struct event_base *base, int fd); - -/* next line is different in the libevent+libev version */ -/*libevent-include*/ - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/framework/src/audit/src/libev/libev.m4 b/framework/src/audit/src/libev/libev.m4 deleted file mode 100644 index 439fbde2..00000000 --- a/framework/src/audit/src/libev/libev.m4 +++ /dev/null @@ -1,42 +0,0 @@ -dnl this file is part of libev, do not make local modifications -dnl http://software.schmorp.de/pkg/libev - -dnl libev support -AC_CHECK_HEADERS(sys/inotify.h sys/epoll.h sys/event.h port.h poll.h sys/select.h sys/eventfd.h sys/signalfd.h) - -AC_CHECK_FUNCS(inotify_init epoll_ctl kqueue port_create poll select eventfd signalfd) - -AC_CHECK_FUNCS(clock_gettime, [], [ - dnl on linux, try syscall wrapper first - if test $(uname) = Linux; then - AC_MSG_CHECKING(for clock_gettime syscall) - AC_LINK_IFELSE([AC_LANG_PROGRAM( - [#include <unistd.h> - #include <sys/syscall.h> - #include <time.h>], - [struct timespec ts; int status = syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts)])], - [ac_have_clock_syscall=1 - AC_DEFINE(HAVE_CLOCK_SYSCALL, 1, Define to 1 to use the syscall interface for clock_gettime) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)]) - fi - if test -z "$LIBEV_M4_AVOID_LIBRT" && test -z "$ac_have_clock_syscall"; then - AC_CHECK_LIB(rt, clock_gettime) - unset ac_cv_func_clock_gettime - AC_CHECK_FUNCS(clock_gettime) - fi -]) - -AC_CHECK_FUNCS(nanosleep, [], [ - if test -z "$LIBEV_M4_AVOID_LIBRT"; then - AC_CHECK_LIB(rt, nanosleep) - unset ac_cv_func_nanosleep - AC_CHECK_FUNCS(nanosleep) - fi -]) - -if test -z "$LIBEV_M4_AVOID_LIBM"; then - LIBM=m -fi -AC_SEARCH_LIBS(floor, $LIBM, [AC_DEFINE(HAVE_FLOOR, 1, Define to 1 if the floor function is available)]) - diff --git a/framework/src/audit/src/mt/Makefile.am b/framework/src/audit/src/mt/Makefile.am deleted file mode 100644 index 1d613d79..00000000 --- a/framework/src/audit/src/mt/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -# Makefile.am -- -# Copyright 2005-06,2008,2012,2014-15 Red Hat Inc., Durham, North Carolina. -# All Rights Reserved. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Authors: -# Steve Grubb <sgrubb@redhat.com> -# -# This make file builds a static multi-threaded libary for the audit -# daemon's own use. - -AUTOMAKE_OPTIONS = no-dependencies -AM_CPPFLAGS = -I${top_srcdir}/lib -I${top_builddir}/lib -CONFIG_CLEAN_FILES = *.rej *.orig -AM_CFLAGS = -fPIC -DPIC -D_REENTRANT -D_GNU_SOURCE -DNO_TABLES - -noinst_LIBRARIES = libauditmt.a - -libauditmt_a_SOURCES = ${top_srcdir}/lib/libaudit.c \ - ${top_srcdir}/lib/message.c ${top_srcdir}/lib/netlink.c \ - ${top_srcdir}/lib/lookup_table.c ${top_srcdir}/lib/audit_logging.c \ - ${top_srcdir}/lib/deprecated.c ${top_srcdir}/lib/strsplit.c -libauditmt_a_HEADERS: ${top_builddir}/config.h ${top_srcdir}/lib/libaudit.h \ - ${top_srcdir}/lib/private.h -libauditmt_a_DEPENDENCIES = $(libaudit_a_SOURCES) ${top_builddir}/config.h \ - ${top_srcdir}/lib/gen_tables.h ${top_builddir}/lib/i386_tables.h \ - ${top_builddir}/lib/ia64_tables.h ${top_builddir}/lib/ppc_tables.h \ - ${top_builddir}/lib/s390_tables.h ${top_builddir}/lib/s390x_tables.h \ - ${top_builddir}/lib/x86_64_tables.h ${top_srcdir}/lib/private.h \ - ${top_builddir}/lib/actiontabs.h ${top_builddir}/lib/fieldtabs.h \ - ${top_builddir}/lib/flagtabs.h ${top_builddir}/lib/ftypetabs.h \ - ${top_builddir}/lib/machinetabs.h ${top_builddir}/lib/msg_typetabs.h \ - ${top_builddir}/lib/optabs.h -AM_LDFLAGS = -Wl,-z,relro - -lib_OBJECTS = $(libauditmt_a_OBJECTS) diff --git a/framework/src/audit/src/test/Makefile.am b/framework/src/audit/src/test/Makefile.am deleted file mode 100644 index b6f44edb..00000000 --- a/framework/src/audit/src/test/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2008,2014,2015 Red Hat Inc., Durham, North Carolina. -# All Rights Reserved. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Authors: -# Steve Grubb <sgrubb@redhat.com> -# - -AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/lib -I${top_srcdir}/src -check_PROGRAMS = ilist_test slist_test -TESTS = $(check_PROGRAMS) -ilist_test_LDADD = ${top_builddir}/src/ausearch-int.o -slist_test_LDADD = ${top_builddir}/src/ausearch-string.o diff --git a/framework/src/audit/src/test/ilist_test.c b/framework/src/audit/src/test/ilist_test.c deleted file mode 100644 index 85787126..00000000 --- a/framework/src/audit/src/test/ilist_test.c +++ /dev/null @@ -1,69 +0,0 @@ -#include <stdio.h> -#include "ausearch-int.h" - -int main(void) -{ - int i = 0; - ilist e; - int_node *node; - - ilist_create(&e); - - // This first test checks to see if list is - // created in a numeric order - ilist_add_if_uniq(&e, 6, 0); - ilist_add_if_uniq(&e, 5, 0); - ilist_add_if_uniq(&e, 7, 0); - ilist_add_if_uniq(&e, 1, 0); - ilist_add_if_uniq(&e, 8, 0); - ilist_add_if_uniq(&e, 2, 0); - ilist_add_if_uniq(&e, 9, 0); - ilist_add_if_uniq(&e, 0, 0); - ilist_add_if_uniq(&e, 4, 0); - ilist_add_if_uniq(&e, 3, 0); - - ilist_first(&e); - do { - node = ilist_get_cur(&e); - if (i != node->num) { - printf("Test failed - i:%d != num:%d\n", i, node->num); - return 1; - } - i++; - } while ((node = ilist_next(&e))); - - ilist_clear(&e); - puts("starting sort test"); - - // Now test to see if the sort function works - // Fill the list exactly backwards - ilist_add_if_uniq(&e, 3, 0); - ilist_add_if_uniq(&e, 3, 0); - ilist_add_if_uniq(&e, 4, 0); - ilist_add_if_uniq(&e, 3, 0); - ilist_add_if_uniq(&e, 4, 0); - ilist_add_if_uniq(&e, 2, 0); - ilist_add_if_uniq(&e, 4, 0); - ilist_add_if_uniq(&e, 2, 0); - ilist_add_if_uniq(&e, 4, 0); - ilist_add_if_uniq(&e, 1, 0); - - ilist_sort_by_hits(&e); - - i = 0; - ilist_first(&e); - do { - node = ilist_get_cur(&e); - if (node->hits != (4-i)) { - printf("Sort test failed - i:%d != ihits:%d\n", i, node->hits); - return 1; - } - i++; - } while ((node = ilist_next(&e))); - - ilist_clear(&e); - - printf("ilist tests passed\n"); - return 0; -} - diff --git a/framework/src/audit/src/test/slist_test.c b/framework/src/audit/src/test/slist_test.c deleted file mode 100644 index e0336149..00000000 --- a/framework/src/audit/src/test/slist_test.c +++ /dev/null @@ -1,98 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include "ausearch-string.h" - -slist s; - -int print_list(void) -{ - int cnt = 0; - slist_first(&s); - do { - snode *cur = slist_get_cur(&s); - if (cur) { - cnt++; - printf("%s\n", cur->str); - } - } while (slist_next(&s)); - return cnt; -} - -int main(void) -{ - snode n, *node; - int rc, i = 0; - - slist_create(&s); - - // This first test checks to see if list is - // created in a numeric order - slist_add_if_uniq(&s, "test1"); - slist_add_if_uniq(&s, "test2"); - slist_first(&s); - slist_add_if_uniq(&s, "test3"); - puts("should be 3"); - rc = print_list(); - if (s.cnt != 3 || rc !=3) { - puts("test count is wrong"); - return 1; - } - - n.str = strdup("test4"); - n.key = NULL; - n.hits = 1; - slist_append(&s, &n); - puts("should add a #4"); - rc = print_list(); - if (s.cnt != 4 || rc != 4) { - puts("test count is wrong"); - return 1; - } - - slist_add_if_uniq(&s, "test2"); - puts("should be same"); - rc = print_list(); - if (s.cnt != 4 || rc != 4) { - puts("test count is wrong"); - return 1; - } - - slist_clear(&s); - puts("should be empty"); - rc = print_list(); - if (s.cnt != 0 || rc != 0) { - puts("test count is wrong"); - return 1; - } - puts("starting sort test"); - - // Now test to see if the sort function works - // Fill the list exactly backwards - slist_add_if_uniq(&s, "test3"); - slist_add_if_uniq(&s, "test3"); - slist_add_if_uniq(&s, "test4"); - slist_add_if_uniq(&s, "test3"); - slist_add_if_uniq(&s, "test4"); - slist_add_if_uniq(&s, "test2"); - slist_add_if_uniq(&s, "test4"); - slist_add_if_uniq(&s, "test2"); - slist_add_if_uniq(&s, "test4"); - slist_add_if_uniq(&s, "test1"); - - slist_sort_by_hits(&s); - slist_first(&s); - do { - node = slist_get_cur(&s); - if (node->hits != (4-i)) { - printf("Sort test failed - i:%d != hits:%d\n", i, node->hits); - return 1; - } - i++; - } while ((node = slist_next(&s))); - puts("sort test passes"); - - slist_clear(&s); - - return 0; -} - |