diff --git a/src/expression.c b/src/expression.c index 4f1e87d..354b805 100644 --- a/src/expression.c +++ b/src/expression.c @@ -1,11 +1,17 @@ #include "expression.h" +#include "fieldset.H" #include "../lib/xalloc.h" /* Static helper functions */ static node_t* alloc_node(); -static int eval_single_node(node_t* node); +static int eval_gt_node(node_t *node, fieldset_t *fields); +static int eval_lt_node(node_t *node, fieldset_t *fields); +static int eval_eq_node(node_t *node, fieldset_t *fields); +static int eval_lt_eq_node(node_t *node, fieldset_t *fields); +static int eval_gt_eq_node(node_t *node, fieldset_t *fields); + static node_t* alloc_node() { @@ -14,6 +20,54 @@ static node_t* alloc_node() return node; } +static int eval_gt_node(node_t *node, fieldset_t *fields) +{ + int index = node->left_child->value.field.index; + uint64_t expected = node->right_child->value.int_literal; + uint64_t actual = fs_get_uint64_by_index(fields, index); + return (actual > expected); +} + +static int eval_lt_node(node_t *node, fieldset_t *fields) +{ + int index = node->left_child->value.field.index; + uint64_t expected = node->right_child->value.int_literal; + uint64_t actual = fs_get_uint64_by_index(fields, index); + return (actual < expected); +} + +static int eval_eq_node(node_t *node, fieldset_t *fields) +{ + node_t *literal = node->right_child; + int index = node->left_child->value.field.index; + char *expected, *actual; + switch (literal->type) { + case STRING: + expected = literal->value.string_literal; + actual = fs_get_string_by_index(fields, index); + return (strcmp(expected, actual) == 0); + break; + case INT: + return (fs_get_uint64_by_index(fields, index) == literal->value.int_literal); + break; + default: + printf("wat\n"); + break; + } + return 0; +} + +static int eval_lt_eq_node(node_t *node, fieldset_t *fields) +{ + return !(eval_gt_node(node, fields)); +} + +static int eval_gt_eq_node(node_t *node, fieldset_t *fields) +{ + return !(eval_lt_node(node, fields)); +} + + /* Exposed functions */ node_t* make_op_node(enum operation op) @@ -48,10 +102,37 @@ node_t* make_int_node(int literal) return node; } -int evaluate_expression(node_t *root) { - if (!root) return 0; - int result = 1; - return result; +int evaluate_expression(node_t *root, fieldset_t *fields) { + if (!root) return 1; + switch (root->type) { /* XXX Not sure if runs */ + case FIELD: + case STRING: + case INT: + return 1; + case OP: + break; + } + switch (root->value.op) { + case GT: + return eval_gt_node(root, fields); + case LT: + return eval_lt_node(root, fields); + case EQ: + return eval_eq_node(root, fields); + case NEQ: + return (!eval_eq_node(root, fields)); + case LT_EQ: + return eval_lt_eq_node(root, fields); + case GT_EQ: + return eval_gt_eq_node(root, fields); + case AND: + return (evaluate_expression(root->left_child, fields) + && evaluate_expression(root->right_child, fields)); + case OR: + return (evaluate_expression(root->left_child, fields) + || evaluate_expression(root->right_child, fields)); + } + return 0; } void print_expression(node_t *root) { @@ -69,7 +150,7 @@ void print_expression(node_t *root) { printf("%s) ", root->value.string_literal); break; case INT: - printf(" %d) ", root->value.int_literal); + printf(" %llu) ", (long long unsigned) root->value.int_literal); break; default: break; diff --git a/src/expression.h b/src/expression.h index 1c58f68..7ff5068 100644 --- a/src/expression.h +++ b/src/expression.h @@ -1,9 +1,12 @@ #ifndef ZMAP_TREE_H #define ZMAP_TREE_H +#include "fieldset.h" + #include #include #include +#include enum operation { GT, LT, EQ, NEQ, AND, OR, LT_EQ, GT_EQ @@ -21,7 +24,7 @@ struct field_id { union node_value { struct field_id field; char *string_literal; - int int_literal; + uint64_t int_literal; enum operation op; }; @@ -40,8 +43,6 @@ node_t* make_string_node(char *literal); node_t* make_int_node(int literal); -int evaluate_expression(node_t *root); - -void print_expression(node_t *root); +int evaluate_expression(node_t *root, fieldset_t *fields); #endif /* ZMAP_TREE_H */ \ No newline at end of file diff --git a/src/filter.c b/src/filter.c index 19ac3ae..49165f3 100644 --- a/src/filter.c +++ b/src/filter.c @@ -4,10 +4,32 @@ #include "y.tab.h" #include "../lib/logger.h" +#include + extern int yyparse(); node_t *zfilter; +static int validate_node(node_t *node, fielddefset_t *fields) +{ + int i; + if (node->type != FIELD) { + return 1; + } + + for (i = 0; i < MAX_FIELDS; i++) { + if (fields->fielddefs[i].name) { + if (strcmp(fields->fielddefs[i].name, node->value.field.fieldname) == 0) { + node->value.field.index = i; + return 1; + } + } + } + // Didn't find it + return 0; + +} + int parse_filter_string(char *filter) { YY_BUFFER_STATE buffer_state = yy_scan_string(filter); @@ -23,4 +45,18 @@ int parse_filter_string(char *filter) printf("%s\n", ""); fflush(stdout); return 1; -} \ No newline at end of file +} + +int validate_filter(node_t *root, fielddefset_t *fields) +{ + int valid; + if (!root) { + return 1; + } + valid = validate_node(root, fields); + if (!valid) { + return 0; + } + return (validate_filter(root->left_child, fields) && validate_filter(root->right_child, fields)); + +} diff --git a/src/filter.h b/src/filter.h index 4de684c..f42af6d 100644 --- a/src/filter.h +++ b/src/filter.h @@ -2,6 +2,7 @@ #define ZMAP_FILTER_H #include "expression.h" +#include "fieldset.h" struct output_filter { node_t *expression; @@ -9,4 +10,6 @@ struct output_filter { int parse_filter_string(char *filter); +int validate_filter(node_t *root, fielddefset_t *fields); + #endif /* ZMAP_FILTER_H */ \ No newline at end of file diff --git a/src/lexer.c b/src/lexer.c index 7172b5b..b5be489 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -745,7 +745,7 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP #line 10 "lexer.l" -yylval.int_literal = atoi(yytext); return T_NUMBER; +yylval.int_literal = (uint64_t) atoll(yytext); return T_NUMBER; YY_BREAK case 2: /* rule 2 can match eol */ diff --git a/src/lexer.l b/src/lexer.l index 63696b2..0fa3b90 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -7,7 +7,7 @@ %option noinput %option nounput %% -[0-9]+ yylval.int_literal = atoi(yytext); return T_NUMBER; +[0-9]+ yylval.int_literal = (uint64_t) atoll(yytext); return T_NUMBER; \n /* Ignore end of line */ [ \t]+ /* Ignore whitespace */ != return T_NOT_EQ; diff --git a/src/zmap.c b/src/zmap.c index ae30562..e61ae65 100644 --- a/src/zmap.c +++ b/src/zmap.c @@ -501,9 +501,15 @@ int main(int argc, char *argv[]) // Parse and validate the output filter, if any if (args.output_filter_arg) { + // Run it through yyparse to build the expression tree if (!parse_filter_string(args.output_filter_arg)) { log_fatal("zmap", "Unable to parse filter expression"); } + + // Check the fields used against the fieldset in use + if (!validate_filter(zconf.filter.expression, &zconf.fsconf.defs)) { + log_fatal("zmap", "Field does not exist"); + } } SET_BOOL(zconf.dryrun, dryrun);