From 19d701ddf07d855128ded0cf2b573ce468e3bdd6 Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Wed, 20 Jan 2016 01:10:01 +0000 Subject: Removing Suricata and Audit from source repo, and updated build.sh to avoid building suricata. Will re-address this in C release via tar balls. Change-Id: I3710076f8b7f3313cb3cb5260c4eb0a6834d4f6e Signed-off-by: Ashlee Young --- framework/src/audit/auparse/expression.c | 1111 ------------------------------ 1 file changed, 1111 deletions(-) delete mode 100644 framework/src/audit/auparse/expression.c (limited to 'framework/src/audit/auparse/expression.c') diff --git a/framework/src/audit/auparse/expression.c b/framework/src/audit/auparse/expression.c deleted file mode 100644 index 6bed45ba..00000000 --- a/framework/src/audit/auparse/expression.c +++ /dev/null @@ -1,1111 +0,0 @@ -/* -* expression.c - Expression parsing and handling -* Copyright (C) 2008,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: -* Miloslav Trmač -* Steve Grubb extended timestamp -*/ - -#include -#include -#include -#include -#include - -#include "expression.h" - - /* Utilities */ - -/* Free EXPR and all its subexpressions. */ -void -expr_free(struct expr *expr) -{ - switch (expr->op) { - case EO_NOT: - expr_free(expr->v.sub[0]); - break; - - case EO_AND: case EO_OR: - expr_free(expr->v.sub[0]); - expr_free(expr->v.sub[1]); - break; - - case EO_RAW_EQ: case EO_RAW_NE: case EO_INTERPRETED_EQ: - case EO_INTERPRETED_NE: case EO_VALUE_EQ: case EO_VALUE_NE: - case EO_VALUE_LT: case EO_VALUE_LE: case EO_VALUE_GT: case EO_VALUE_GE: - if (expr->virtual_field == 0) - free(expr->v.p.field.name); - if (expr->precomputed_value == 0) - free(expr->v.p.value.string); - break; - - case EO_FIELD_EXISTS: - assert(expr->virtual_field == 0); - free(expr->v.p.field.name); - break; - - case EO_REGEXP_MATCHES: - regfree(expr->v.regexp); - free(expr->v.regexp); - break; - - default: - abort(); - } - free(expr); -} - - /* Expression parsing. */ - -/* The formal grammar: - - start: or-expression - - or-expression: and-expression - or-expression: or-expression || and-expression - - and-expression: primary-expression - and-expression: and-expression && primary-expression - - primary-expression: ! primary-expression - primary-expression: ( or-expression ) - primary-expression: comparison-expression - - comparison-expression: field op value - comparison-expression: field-escape "regexp" regexp-value - field: string - field: field-escape string - value: string - regexp-value: string - regexp-value: regexp */ - -/* Token types */ -enum token_type { - /* EO_* */ - T_LEFT_PAREN = NUM_EO_VALUES, T_RIGHT_PAREN, T_STRING, T_REGEXP, - T_FIELD_ESCAPE, T_UNKNOWN, T_EOF -}; - -/* Expression parsing status */ -struct parsing { - char **error; /* Error message destination. */ - enum token_type token; - const char *token_start; /* Original "src" value */ - int token_len; /* int because it must be usable in %.*s */ - char *token_value; /* Non-NULL only for T_STRING, until used */ - const char *src; /* Expression source, after the current token */ -}; - -static struct expr *parse_or(struct parsing *p); - -/* Allocate SIZE bytes. - On error, return NULL and try to set *P->ERROR. */ -static void * -parser_malloc(struct parsing *p, size_t size) -{ - void *res; - - res = malloc(size); - if (res != NULL || size == 0) - return res; - *p->error = strdup("Out of memory"); - return NULL; -} - -/* Reallocate PTR to SIZE bytes. - On error, free(PTR), return NULL and try to set *P->ERROR. - NOTE: realloc() does not free(PTR), this function does. */ -static void * -parser_realloc(struct parsing *p, void *ptr, size_t size) -{ - void *res; - - res = realloc(ptr, size); - if (res != NULL || size == 0) - return res; - free(ptr); - *p->error = strdup("Out of memory"); - return NULL; -} - -/* Discard P->token_value, if any, and parse the next token in P->src. - On success, return 0. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - -1. */ -static int -lex(struct parsing *p) -{ - free(p->token_value); - p->token_value = NULL; - while (*p->src == ' ' || *p->src == '\t' || *p->src == '\n') - p->src++; - p->token_start = p->src; - switch (*p->src) { - case '\0': - p->token = T_EOF; - break; - - case '!': - p->src++; - if (*p->src == '=' && p->src[1] == '=') { - p->src += 2; - p->token = EO_VALUE_NE; - break; - } - p->token = EO_NOT; - break; - - case '"': case '/': { - char *buf, delimiter; - size_t dest, buf_size; - - delimiter = *p->src; - buf_size = 8; - buf = parser_malloc(p, buf_size); - if (buf == NULL) - return -1; - p->src++; - dest = 0; - while (*p->src != delimiter) { - if (*p->src == '\0') { - *p->error = strdup("Terminating delimiter " - "missing"); - free(buf); - return -1; - } - if (*p->src == '\\') { - p->src++; - if (*p->src != '\\' && *p->src != delimiter) { - if (asprintf(p->error, "Unknown escape " - "sequence ``\\%c''", - *p->src) < 0) - *p->error = NULL; - free(buf); - return -1; - } - } - /* +1: make sure there is space for the terminating - NUL. */ - if (dest + 1 >= buf_size) { - if (buf_size > SIZE_MAX / 2) { - *p->error = strdup("Delimited string " - "too long"); - free(buf); - return -1; - } - buf_size *= 2; - buf = parser_realloc(p, buf, buf_size); - if (buf == NULL) { - *p->error = strdup("Out of memory"); - return -1; - } - } - buf[dest] = *p->src; - dest++; - p->src++; - } - p->src++; - buf[dest] = '\0'; - p->token_value = parser_realloc(p, buf, dest + 1); - if (p->token_value == NULL) - return -1; - p->token = delimiter == '/' ? T_REGEXP : T_STRING; - break; - } - - case '&': - p->src++; - if (*p->src == '&') { - p->src++; - p->token = EO_AND; - break; - } - p->token = T_UNKNOWN; - break; - - case '(': - p->src++; - p->token = T_LEFT_PAREN; - break; - - case ')': - p->src++; - p->token = T_RIGHT_PAREN; - break; - - case '<': - p->src++; - if (*p->src == '=') { - p->src++; - p->token = EO_VALUE_LE; - break; - } - p->token = EO_VALUE_LT; - break; - - case '=': - p->src++; - if (*p->src == '=') { - p->src++; - p->token = EO_VALUE_EQ; - break; - } - p->token = T_UNKNOWN; - break; - - case '>': - p->src++; - if (*p->src == '=') { - p->src++; - p->token = EO_VALUE_GE; - break; - } - p->token = EO_VALUE_GT; - break; - - case '\\': - p->src++; - p->token = T_FIELD_ESCAPE; - break; - - case '|': - p->src++; - if (*p->src == '|') { - p->src++; - p->token = EO_OR; - break; - } - p->token = T_UNKNOWN; - break; - - case 'i': - if (p->src[1] == '=') { - p->src += 2; - p->token = EO_INTERPRETED_EQ; - break; - } else if (p->src[1] == '!' && p->src[2] == '=') { - p->src += 3; - p->token = EO_INTERPRETED_NE; - break; - } - goto unquoted_string; - - case 'r': - if (p->src[1] == '=') { - p->src += 2; - p->token = EO_RAW_EQ; - break; - } else if (p->src[1] == '!' && p->src[2] == '=') { - p->src += 3; - p->token = EO_RAW_NE; - break; - } - goto unquoted_string; - - default: - /* This assumes ASCII */ - assert ('Z' == 'A' + 25 && 'z' == 'a' + 25); -#define IS_UNQUOTED_STRING_CHAR(C) \ - (((C) >= 'a' && (C) <= 'z') \ - || ((C) >= 'A' && (C) <= 'Z') \ - || ((C) >= '0' && (C) <= '9') \ - || (C) == '_') - if (IS_UNQUOTED_STRING_CHAR(*p->src)) { - size_t len; - - unquoted_string: - do - p->src++; - while (IS_UNQUOTED_STRING_CHAR(*p->src)); - len = p->src - p->token_start; - p->token_value = parser_malloc(p, len + 1); - if (p->token_value == NULL) - return -1; - memcpy(p->token_value, p->token_start, len); - p->token_value[len] = '\0'; - p->token = T_STRING; - break; - } - p->src++; - p->token = T_UNKNOWN; - break; - } - if (p->src - p->token_start > INT_MAX) { - *p->error = strdup("Token too long"); - return -1; - } - p->token_len = p->src - p->token_start; - return 0; -} - -/* Parse an escaped field NAME to DEST. - Return 0 on success, -1 if NAME is unknown. */ -static int -parse_escaped_field_name(enum field_id *dest, const char *name) -{ - if (strcmp(name, "timestamp") == 0) - *dest = EF_TIMESTAMP; - else if (strcmp(name, "record_type") == 0) - *dest = EF_RECORD_TYPE; - else if (strcmp(name, "timestamp_ex") == 0) - *dest = EF_TIMESTAMP_EX; - else - return -1; - return 0; -} - -/* Parse a \timestamp field value in P->token_value to DEST. - On success, return 0. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - -1. */ -static int -parse_timestamp_value(struct expr *dest, struct parsing *p) -{ - intmax_t sec; - - assert(p->token == T_STRING); - /* FIXME: other formats? */ - if (sscanf(p->token_value, "ts:%jd.%u:%u", &sec, - &dest->v.p.value.timestamp_ex.milli, - &dest->v.p.value.timestamp_ex.serial) != 3) { - if (sscanf(p->token_value, "ts:%jd.%u", &sec, - &dest->v.p.value.timestamp.milli) != 2) { - if (asprintf(p->error, "Invalid timestamp value `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - return -1; - } - } - /* FIXME: validate milli */ - dest->v.p.value.timestamp.sec = sec; - if (dest->v.p.value.timestamp.sec != sec) { - if (asprintf(p->error, "Timestamp overflow in `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - return -1; - } - dest->precomputed_value = 1; - return 0; -} - -/* Parse a \record_type field value in P->token_value to DEST. - On success, return 0. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - -1. */ -static int -parse_record_type_value(struct expr *dest, struct parsing *p) -{ - int type; - - assert(p->token == T_STRING); - type = audit_name_to_msg_type(p->token_value); - if (type < 0) { - if (asprintf(p->error, "Invalid record type `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - return -1; - } - dest->v.p.value.int_value = type; - dest->precomputed_value = 1; - return 0; -} - -/* Parse a virtual field value in P->token_value to DEST. - On success, return 0. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - NULL. */ -static int -parse_virtual_field_value(struct expr *dest, struct parsing *p) -{ - switch (dest->v.p.field.id) { - case EF_TIMESTAMP: - return parse_timestamp_value(dest, p); - - case EF_RECORD_TYPE: - return parse_record_type_value(dest, p); - - case EF_TIMESTAMP_EX: - return parse_timestamp_value(dest, p); - - default: - abort(); - } -} - -/* Parse a \regexp comparison-expression string in *P, with \regexp parsed. - Use or free EXPR. - On success, return the parsed comparison-expression. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - NULL. */ -static struct expr * -parse_comparison_regexp(struct parsing *p, struct expr *res) -{ - int err; - - if (lex(p) != 0) - goto err_res; - if (p->token != T_STRING && p->token != T_REGEXP) { - if (asprintf(p->error, "Regexp expected, got `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - goto err_res; - } - res->v.regexp = parser_malloc(p, sizeof(*res->v.regexp)); - if (res->v.regexp == NULL) - goto err_res; - err = regcomp(res->v.regexp, p->token_value, REG_EXTENDED | REG_NOSUB); - if (err != 0) { - size_t err_size; - char *err_msg; - - err_size = regerror(err, res->v.regexp, NULL, 0); - err_msg = parser_malloc(p, err_size); - if (err_msg == NULL) - goto err_res_regexp; - regerror(err, res->v.regexp, err_msg, err_size); - if (asprintf(p->error, "Invalid regexp: %s", err_msg) < 0) - *p->error = NULL; - free(err_msg); - goto err_res_regexp; - } - res->op = EO_REGEXP_MATCHES; - if (lex(p) != 0) { - expr_free(res); - return NULL; - } - return res; - -err_res_regexp: - free(res->v.regexp); -err_res: - free(res); - return NULL; -} - -/* Parse a comparison-expression string in *P. - On success, return the parsed comparison-expression. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - NULL. */ -static struct expr * -parse_comparison(struct parsing *p) -{ - struct expr *res; - - res = parser_malloc(p, sizeof(*res)); - if (res == NULL) - return NULL; - if (p->token == T_FIELD_ESCAPE) { - if (lex(p) != 0) - goto err_res; - if (p->token != T_STRING) { - *p->error = strdup("Field name expected after field " - "escape"); - goto err_res; - } - if (strcmp(p->token_value, "regexp") == 0) - return parse_comparison_regexp(p, res); - res->virtual_field = 1; - if (parse_escaped_field_name(&res->v.p.field.id, p->token_value) - != 0) { - if (asprintf(p->error, - "Unknown escaped field name `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - goto err_res; - } - } else { - assert(p->token == T_STRING); - res->virtual_field = 0; - res->v.p.field.name = p->token_value; - p->token_value = NULL; - } - if (lex(p) != 0) - goto err_field; - switch (p->token) { - case EO_RAW_EQ: case EO_RAW_NE: case EO_INTERPRETED_EQ: - case EO_INTERPRETED_NE: - res->op = p->token; - if (lex(p) != 0) - goto err_field; - if (p->token != T_STRING) { - if (asprintf(p->error, "Value expected, got `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - goto err_field; - } - res->precomputed_value = 0; - res->v.p.value.string = p->token_value; - p->token_value = NULL; - if (lex(p) != 0) { - expr_free(res); - return NULL; - } - break; - - case EO_VALUE_EQ: case EO_VALUE_NE: case EO_VALUE_LT: case EO_VALUE_LE: - case EO_VALUE_GT: case EO_VALUE_GE: - res->op = p->token; - if (lex(p) != 0) - goto err_field; - if (p->token != T_STRING) { - if (asprintf(p->error, "Value expected, got `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - goto err_field; - } - if (res->virtual_field == 0) { - if (asprintf(p->error, "Field `%s' does not support " - "value comparison", - res->v.p.field.name) < 0) - *p->error = NULL; - goto err_field; - } else { - if (parse_virtual_field_value(res, p) != 0) - goto err_field; - } - if (lex(p) != 0) { - expr_free(res); - return NULL; - } - break; - - default: - if (asprintf(p->error, "Operator expected, got `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - goto err_field; - } - return res; - -err_field: - if (res->virtual_field == 0) - free(res->v.p.field.name); -err_res: - free(res); - return NULL; -} - -/* Parse a primary-expression string in *P. - On success, return the parsed primary-expression. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - NULL. */ -static struct expr * -parse_primary(struct parsing *p) -{ - struct expr *e; - - switch (p->token) { - case EO_NOT: { - struct expr *res; - - if (lex(p) != 0) - return NULL; - e = parse_primary(p); - if (e == NULL) - return NULL; - res = parser_malloc(p, sizeof(*res)); - if (res == NULL) - goto err_e; - res->op = EO_NOT; - res->v.sub[0] = e; - return res; - } - - case T_LEFT_PAREN: { - if (lex(p) != 0) - return NULL; - e = parse_or(p); - if (e == NULL) - return NULL; - if (p->token != T_RIGHT_PAREN) { - if (asprintf(p->error, - "Right paren expected, got `%.*s'", - p->token_len, p->token_start) < 0) - *p->error = NULL; - goto err_e; - } - if (lex(p) != 0) - goto err_e; - return e; - } - - case T_FIELD_ESCAPE: case T_STRING: - return parse_comparison(p); - - default: - if (asprintf(p->error, "Unexpected token `%.*s'", p->token_len, - p->token_start) < 0) - *p->error = NULL; - return NULL; - } -err_e: - expr_free(e); - return NULL; -} - -/* Parse an and-expression string in *P. - On success, return the parsed and-expression. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - NULL. */ -static struct expr * -parse_and(struct parsing *p) -{ - struct expr *res; - - res = parse_primary(p); - if (res == NULL) - return NULL; - while (p->token == EO_AND) { - struct expr *e2, *e; - - if (lex(p) != 0) - goto err_res; - e2 = parse_primary(p); - if (e2 == NULL) - goto err_res; - e = parser_malloc(p, sizeof(*e)); - if (e == NULL) { - expr_free(e2); - goto err_res; - } - e->op = EO_AND; - e->v.sub[0] = res; - e->v.sub[1] = e2; - res = e; - } - return res; - -err_res: - expr_free(res); - return NULL; -} - -/* Parse an or-expression string in *P. - On success, return the parsed or-expression. - On error, set *P->ERROR to an error string (for free()) or NULL, and return - NULL. */ -static struct expr * -parse_or(struct parsing *p) -{ - struct expr *res; - - res = parse_and(p); - if (res == NULL) - return NULL; - while (p->token == EO_OR) { - struct expr *e2, *e; - - if (lex(p) != 0) - goto err_res; - e2 = parse_and(p); - if (e2 == NULL) - goto err_res; - e = parser_malloc(p, sizeof(*e)); - if (e == NULL) { - expr_free(e2); - goto err_res; - } - e->op = EO_OR; - e->v.sub[0] = res; - e->v.sub[1] = e2; - res = e; - } - return res; - -err_res: - expr_free(res); - return NULL; -} - -/* Parse STRING. - On success, return the parsed expression tree. - On error, set *ERROR to an error string (for free()) or NULL, and return - NULL. (*ERROR == NULL is allowed to handle out-of-memory errors) */ -struct expr * -expr_parse(const char *string, char **error) -{ - struct parsing p; - struct expr *res; - - p.error = error; - p.token_value = NULL; - p.src = string; - if (lex(&p) != 0) - goto err; - if (p.token == T_EOF) { - *error = strdup("Empty expression"); - goto err; - } - res = parse_or(&p); - if (res != NULL && p.token != T_EOF) { - expr_free(res); - if (asprintf(error, "Unexpected trailing token `%.*s'", - p.token_len, p.token_start) < 0) - *error = NULL; - goto err; - } - free(p.token_value); - return res; - -err: - free(p.token_value); - return NULL; -} - - /* Manual expression creation */ - -/* Create a comparison-expression for FIELD, OP and VALUE. - On success, return the created expression. - On error, set errno and return NULL. */ -struct expr * -expr_create_comparison(const char *field, unsigned op, const char *value) -{ - struct expr *res; - - res = malloc(sizeof(*res)); - if (res == NULL) - goto err; - assert(op == EO_RAW_EQ || op == EO_RAW_NE || op == EO_INTERPRETED_EQ - || op == EO_INTERPRETED_NE); - res->op = op; - res->virtual_field = 0; - res->precomputed_value = 0; - res->v.p.field.name = strdup(field); - if (res->v.p.field.name == NULL) - goto err_res; - res->v.p.value.string = strdup(value); - if (res->v.p.value.string == NULL) - goto err_field; - return res; - -err_field: - free(res->v.p.field.name); -err_res: - free(res); -err: - return NULL; -} - -/* Create an extended timestamp comparison-expression for with OP, SEC, - MILLI, and SERIAL. - On success, return the created expression. - On error, set errno and return NULL. */ -struct expr * -expr_create_timestamp_comparison_ex(unsigned op, time_t sec, unsigned milli, - unsigned serial) -{ - struct expr *res; - - res = malloc(sizeof(*res)); - if (res == NULL) - return NULL; - assert(op == EO_VALUE_EQ || op == EO_VALUE_NE || op == EO_VALUE_LT - || op == EO_VALUE_LE || op == EO_VALUE_GT || op == EO_VALUE_GE); - res->op = op; - res->virtual_field = 1; - res->v.p.field.id = EF_TIMESTAMP_EX; - res->precomputed_value = 1; - res->v.p.value.timestamp_ex.sec = sec; - assert(milli < 1000); - res->v.p.value.timestamp_ex.milli = milli; - res->v.p.value.timestamp_ex.serial = serial; - return res; -} - -/* Create a timestamp comparison-expression for with OP, SEC, MILLI. - On success, return the created expression. - On error, set errno and return NULL. */ -struct expr * -expr_create_timestamp_comparison(unsigned op, time_t sec, unsigned milli) -{ - return expr_create_timestamp_comparison_ex(op, sec, milli, 0); -} - -/* Create an EO_FIELD_EXISTS-expression for FIELD. - On success, return the created expression. - On error, set errno and return NULL. */ -struct expr * -expr_create_field_exists(const char *field) -{ - struct expr *res; - - res = malloc(sizeof(*res)); - if (res == NULL) - goto err; - res->op = EO_FIELD_EXISTS; - res->virtual_field = 0; - res->v.p.field.name = strdup(field); - if (res->v.p.field.name == NULL) - goto err_res; - return res; - -err_res: - free(res); -err: - return NULL; -} - -/* Create a \regexp expression for regexp comparison. - On success, return the created expression. - On error, set errno and return NULL. */ -struct expr * -expr_create_regexp_expression(const char *regexp) -{ - struct expr *res; - - res = malloc(sizeof(*res)); - if (res == NULL) - goto err; - res->v.regexp = malloc(sizeof(*res->v.regexp)); - if (res->v.regexp == NULL) - goto err_res; - if (regcomp(res->v.regexp, regexp, REG_EXTENDED | REG_NOSUB) != 0) { - errno = EINVAL; - goto err_res_regexp; - } - res->op = EO_REGEXP_MATCHES; - return res; - -err_res_regexp: - free(res->v.regexp); -err_res: - free(res); -err: - return NULL; -} - -/* Create a binary expresion for OP and subexpressions E1 and E2. - On success, return the created expresion. - On error, set errno and return NULL. */ -struct expr * -expr_create_binary(unsigned op, struct expr *e1, struct expr *e2) -{ - struct expr *res; - - res = malloc(sizeof(*res)); - if (res == NULL) - return NULL; - assert(op == EO_AND || op ==EO_OR); - res->op = op; - res->v.sub[0] = e1; - res->v.sub[1] = e2; - return res; -} - - /* Expression evaluation */ - -/* Return the "raw" value of the field in EXPR for RECORD in AU->le. Set - *FREE_IT to 1 if the return value should free()'d. - Return NULL on error. */ -static char * -eval_raw_value(auparse_state_t *au, rnode *record, const struct expr *expr, - int *free_it) -{ - if (expr->virtual_field == 0) { - nvlist_first(&record->nv); - if (nvlist_find_name(&record->nv, expr->v.p.field.name) == 0) - return NULL; - *free_it = 0; - return (char *)nvlist_get_cur_val(&record->nv); - } - switch (expr->v.p.field.id) { - case EF_TIMESTAMP: case EF_RECORD_TYPE: case EF_TIMESTAMP_EX: - return NULL; - - default: - abort(); - } -} - -/* Return the "interpreted" value of the field in EXPR for RECORD in AU->le. - Set *FREE_IT to 1 if the return value should free()'d. - Return NULL on *error. */ -static char * -eval_interpreted_value(auparse_state_t *au, rnode *record, - const struct expr *expr, int *free_it) -{ - if (expr->virtual_field == 0) { - const char *res; - - nvlist_first(&record->nv); - if (nvlist_find_name(&record->nv, expr->v.p.field.name) == 0) - return NULL; - *free_it = 0; - res = nvlist_interp_cur_val(record); - if (res == NULL) - res = nvlist_get_cur_val(&record->nv); - return (char *)res; - } - switch (expr->v.p.field.id) { - case EF_TIMESTAMP: case EF_RECORD_TYPE: case EF_TIMESTAMP_EX: - return NULL; - - default: - abort(); - } -} - -/* Return -1, 0, 1 depending on comparing the field in EXPR with RECORD in AU. - Set *ERROR to 0 if OK, non-zero otherwise. */ -static int -compare_values(auparse_state_t *au, rnode *record, const struct expr *expr, - int *error) -{ - int res; - if (expr->virtual_field == 0) { - *error = 1; - return 0; - } - switch (expr->v.p.field.id) { - case EF_TIMESTAMP: - if (au->le.e.sec < expr->v.p.value.timestamp.sec) - res = -1; - else if (au->le.e.sec > expr->v.p.value.timestamp.sec) - res = 1; - else if (au->le.e.milli < expr->v.p.value.timestamp.milli) - res = -1; - else if (au->le.e.milli > expr->v.p.value.timestamp.milli) - res = 1; - else - res = 0; - break; - - case EF_RECORD_TYPE: - if (record->type < expr->v.p.value.int_value) - res = -1; - else if (record->type > expr->v.p.value.int_value) - res = 1; - else - res = 0; - break; - - case EF_TIMESTAMP_EX: - if (au->le.e.sec < expr->v.p.value.timestamp.sec) - res = -1; - else if (au->le.e.sec > expr->v.p.value.timestamp.sec) - res = 1; - else if (au->le.e.milli < expr->v.p.value.timestamp.milli) - res = -1; - else if (au->le.e.milli > expr->v.p.value.timestamp.milli) - res = 1; - else if (au->le.e.serial < expr->v.p.value.timestamp_ex.serial) - res = -1; - else if (au->le.e.serial > expr->v.p.value.timestamp_ex.serial) - res = 1; - else - res = 0; - break; - - default: - abort(); - } - *error = 0; - return res; -} - -/* Evaluate EXPR on RECORD in AU->le. - Return 1 if EXPR is true, 0 if it false or if it fails. - (No error reporting facility is provided; an invalid term is considered to - be false; e.g. !invalid is true.) */ -int -expr_eval(auparse_state_t *au, rnode *record, const struct expr *expr) -{ - switch (expr->op) { - case EO_NOT: - return !expr_eval(au, record, expr->v.sub[0]); - - case EO_AND: - return (expr_eval(au, record, expr->v.sub[0]) - && expr_eval(au, record, expr->v.sub[1])); - - case EO_OR: - return (expr_eval(au, record, expr->v.sub[0]) - || expr_eval(au, record, expr->v.sub[1])); - - case EO_RAW_EQ: case EO_RAW_NE: { - int free_it, ne; - char *value; - - value = eval_raw_value(au, record, expr, &free_it); - if (value == NULL) - return 0; - assert(expr->precomputed_value == 0); - ne = strcmp(expr->v.p.value.string, value); - if (free_it != 0) - free(value); - return expr->op == EO_RAW_EQ ? ne == 0 : ne != 0; - } - - case EO_INTERPRETED_EQ: case EO_INTERPRETED_NE: { - int free_it, ne; - char *value; - - value = eval_interpreted_value(au, record, expr, &free_it); - if (value == NULL) - return 0; - assert(expr->precomputed_value == 0); - ne = strcmp(expr->v.p.value.string, value); - if (free_it != 0) - free(value); - return expr->op == EO_INTERPRETED_EQ ? ne == 0 : ne != 0; - } - - case EO_VALUE_EQ: case EO_VALUE_NE: case EO_VALUE_LT: case EO_VALUE_LE: - case EO_VALUE_GT: case EO_VALUE_GE: { - int err, cmp; - - cmp = compare_values(au, record, expr, &err); - if (err != 0) - return 0; - switch (expr->op) { - case EO_VALUE_EQ: - return cmp == 0; - - case EO_VALUE_NE: - return cmp != 0; - - case EO_VALUE_LT: - return cmp < 0; - - case EO_VALUE_LE: - return cmp <= 0; - - case EO_VALUE_GT: - return cmp > 0; - - case EO_VALUE_GE: - return cmp >= 0; - - default: - abort(); - } - } - - case EO_FIELD_EXISTS: - assert(expr->virtual_field == 0); - nvlist_first(&record->nv); - return nvlist_find_name(&record->nv, expr->v.p.field.name) != 0; - - case EO_REGEXP_MATCHES: - return regexec(expr->v.regexp, record->record, 0, NULL, 0) == 0; - - default: - abort(); - } -} -- cgit 1.2.3-korg