diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 22f02959..a30ddfbd 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -179,6 +179,8 @@ WHITE [ \t] \!\= return NEQ; \<\= return LEQ; \>\= return GEQ; +\&\& return AND; +\|\| return OR; %% diff --git a/conf/confbase.Y b/conf/confbase.Y index b48a9290..5da84b1e 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -44,7 +44,7 @@ CF_DECLS } %token END CLI_MARKER INVALID_TOKEN -%token GEQ LEQ NEQ +%token GEQ LEQ NEQ AND OR %token NUM ENUM %token RTRID %token IPA @@ -57,7 +57,7 @@ CF_DECLS %type prefix prefix_or_ipa %nonassoc PREFIX_DUMMY -%nonassoc '=' '<' '>' '~' '.' GEQ LEQ NEQ +%nonassoc '=' '<' '>' '~' '.' GEQ LEQ NEQ AND OR %left '+' '-' %left '*' '/' '%' %left '!' diff --git a/filter/config.Y b/filter/config.Y index 1ab43058..545b5e32 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -343,6 +343,8 @@ term: | term '-' term { $$ = f_new_inst(); $$->code = '-'; $$->a1.p = $1; $$->a2.p = $3; } | term '*' term { $$ = f_new_inst(); $$->code = '*'; $$->a1.p = $1; $$->a2.p = $3; } | term '/' term { $$ = f_new_inst(); $$->code = '/'; $$->a1.p = $1; $$->a2.p = $3; } + | term AND term { $$ = f_new_inst(); $$->code = '&'; $$->a1.p = $1; $$->a2.p = $3; } + | term OR term { $$ = f_new_inst(); $$->code = '|'; $$->a1.p = $1; $$->a2.p = $3; } | term '=' term { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; } | term NEQ term { $$ = f_new_inst(); $$->code = P('!','='); $$->a1.p = $1; $$->a2.p = $3; } | term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; } diff --git a/filter/filter.c b/filter/filter.c index 6a4778b9..232a2d2c 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -290,6 +290,19 @@ interpret(struct f_inst *what) default: runtime( "Usage of unknown type" ); } break; + + case '&': + TWOARGS_C; + res.type = v1.type; + if (res.type != T_BOOL) runtime( "Can not do boolean operation on non-booleans" ); + res.val.i = v1.val.i && v2.val.i; + break; + case '|': + TWOARGS_C; + res.type = v1.type; + if (res.type != T_BOOL) runtime( "Can not do boolean operation on non-booleans" ); + res.val.i = v1.val.i || v2.val.i; + break; /* Relational operators */ @@ -665,6 +678,8 @@ i_same(struct f_inst *f1, struct f_inst *f2) case '-': case '*': case '/': + case '|': + case '&': case P('!','='): case P('=','='): case '<': diff --git a/filter/test.conf b/filter/test.conf index 7e674647..c1d5977d 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -88,9 +88,10 @@ ip p; if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok"; print " must be true: ", 1.2.0.0/16 ~ [ 1.0.0.0/8{ 15 , 17 } ]; print " data types; must be true: ", 1.2.3.4 = 1.2.3.4, ",", 1 ~ [1,2,3], ",", 5 ~ [1..20], ",", 2 ~ [ 1, 2, 3 ], ",", 5 ~ [ 4 .. 7 ], ",", 1.2.3.4 ~ [ 1.2.3.3..1.2.3.5 ], ",", 1.2.3.4 ~ 1.0.0.0/8, ",", 1.0.0.0/8 ~ 1.0.0.0/8, ",", 1.0.0.0/8 ~ [ 1.0.0.0/8+ ]; + print " must be true: ", true && true, ",", true || false; # print " must be true: ", defined(1), ",", defined(1.2.3.4), ",", 1 != 2, ",", 1 <= 2; - print " data types: must be false: ", 1 ~ [ 2, 3, 4 ], ",", 5 ~ [ 2, 3, 4, 7..11 ], ",", 1.2.3.4 ~ [ 1.2.3.3, 1.2.3.5 ], ",", (1,2) > (2,2), ",", (1,1) > (1,1), ",", 1.0.0.0/8 ~ [ 1.0.0.0/8- ], ",", 1.2.0.0/17 ~ [ 1.0.0.0/8{ 15 , 16 } ]; + print " data types: must be false: ", 1 ~ [ 2, 3, 4 ], ",", 5 ~ [ 2, 3, 4, 7..11 ], ",", 1.2.3.4 ~ [ 1.2.3.3, 1.2.3.5 ], ",", (1,2) > (2,2), ",", (1,1) > (1,1), ",", 1.0.0.0/8 ~ [ 1.0.0.0/8- ], ",", 1.2.0.0/17 ~ [ 1.0.0.0/8{ 15 , 16 } ], ",", true && false; px = 1.2.0.0/18; print "Testing prefixes: 1.2.0.0/18 = ", px;