summaryrefslogtreecommitdiffstats
path: root/filter
diff options
context:
space:
mode:
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y23
-rw-r--r--filter/filter.c19
-rw-r--r--filter/filter.h7
3 files changed, 40 insertions, 9 deletions
diff --git a/filter/config.Y b/filter/config.Y
index 1e4bafe..a12766e 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -5,12 +5,11 @@
*
* Can be freely distributed and used under the terms of the GNU GPL.
*
- FIXME: define keyword
- FIXME: create ip.mask(x) function
+ FIXME (nonurgent): define keyword
FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
FIXME: create community lists
FIXME: enumerational types
- FIXME: defined() keyword
+ FIXME: write access to dynamic attributes.
*/
CF_HDR
@@ -32,11 +31,15 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST,
TRUE, FALSE,
RTA, FROM, GW, NET, MASK, RIP_METRIC, RIP_TAG,
LEN,
+ DEFINED,
IMPOSSIBLE,
FILTER
)
-%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list var_listn
+%nonassoc THEN
+%nonassoc ELSE ';'
+
+%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list var_listn any_dynamic
%type <f> filter filter_body
%type <i> type break_command pair
%type <e> set_item set_items switch_body
@@ -237,8 +240,15 @@ constant:
| '[' set_items ']' { printf( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_SET; $$->a2.p = build_tree($2); printf( "ook\n" ); }
;
+any_dynamic:
+ RIP_METRIC { $$ = f_new_inst(); $$->a1.i = T_INT; $$->a2.i = EA_RIP_METRIC;}
+ | RIP_TAG { $$ = f_new_inst(); $$->a1.i = T_INT; $$->a2.i = EA_RIP_TAG; }
+ ;
+
+
term:
- term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
+ '(' term ')' { $$ = $2; }
+ | 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 = $4; }
| term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
@@ -246,6 +256,7 @@ term:
| term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
| term '>' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $4; $$->a2.p = $1; }
| term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
+ | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = 'de'; $$->a1.p = $3; }
| SYM {
$$ = f_new_inst();
@@ -267,7 +278,7 @@ term:
| RTA '.' GW { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); }
| RTA '.' NET { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_PREFIX; $$->a2.i = 0x12345678; }
- | RTA '.' RIP_METRIC { $$ = f_new_inst(); $$->code = 'ea'; $$->a1.i = T_INT; $$->a2.i = EA_RIP_METRIC; }
+ | RTA '.' any_dynamic { $$ = $3; $$->code = 'ea'; }
| term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_IP; }
| term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_INT; }
diff --git a/filter/filter.c b/filter/filter.c
index 99d47bc..a6030ae 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -62,6 +62,7 @@ val_compare(struct f_val v1, struct f_val v2)
if (v1.type != v2.type)
return CMP_ERROR;
switch (v1.type) {
+ case T_ENUM:
case T_INT:
case T_PAIR:
if (v1.val.i == v2.val.i) return 0;
@@ -219,6 +220,11 @@ interpret(struct f_inst *what)
if (res.val.i == CMP_ERROR)
runtime( "~ applied on unknown type pair" );
break;
+ case 'de':
+ ONEARG;
+ res.type = T_BOOL;
+ res.val.i = (v1.type != T_VOID);
+ break;
/* Set to indirect value, a1 = variable, a2 = value */
case 's':
@@ -226,6 +232,7 @@ interpret(struct f_inst *what)
sym = what->a1.p;
switch (res.type = v2.type) {
case T_VOID: runtime( "Can not assign void values" );
+ case T_ENUM:
case T_INT:
case T_IP:
case T_PREFIX:
@@ -352,8 +359,16 @@ interpret(struct f_inst *what)
}
break;
case 'iM': /* IP.MASK(val) */
- TWOARGS_C;
- bug( "Should implement ip.mask\n" );
+ TWOARGS;
+ if (v2.type != T_INT)
+ runtime( "Can not use this type for mask.");
+ if (v1.type != T_IP)
+ runtime( "You can mask only IP addresses." );
+ {
+ ip_addr mask = ipa_mkmask(v2.val.i);
+ res.type = T_IP;
+ res.val.px.ip = ipa_and(mask, v1.val.px.ip);
+ }
break;
default:
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
diff --git a/filter/filter.h b/filter/filter.h
index 4cdf8f6..ebb0925 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -92,7 +92,12 @@ void val_print(struct f_val v);
#define T_INT 0x10
#define T_BOOL 0x11
#define T_PAIR 0x12
-#define T_ENUM 0x13
+
+/* Put enumerational types in 0x30..0x7f range */
+#define T_ENUM_LO 0x30
+#define T_ENUM_HI 0x7f
+
+#define T_ENUM T_ENUM_LO ... T_ENUM_HI
/* Bigger ones */
#define T_IP 0x20