summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/confbase.Y2
-rw-r--r--filter/config.Y234
-rw-r--r--filter/f-util.c44
-rw-r--r--filter/filter.c200
-rw-r--r--filter/filter.h83
5 files changed, 308 insertions, 255 deletions
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 9c08a41a..b8deed54 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -43,6 +43,8 @@ CF_DECLS
char *t;
struct rtable_config *r;
struct f_inst *x;
+ struct f_dynamic_attr fda;
+ struct f_static_attr fsa;
struct filter *f;
struct f_tree *e;
struct f_trie *trie;
diff --git a/filter/config.Y b/filter/config.Y
index c9f9c753..1ef5a3a8 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -12,8 +12,6 @@ CF_HDR
CF_DEFINES
-#define P(a,b) ((a << 8) | b)
-
static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; }
static inline u32 pair_a(u32 p) { return p >> 16; }
static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
@@ -157,12 +155,11 @@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3)
}
static inline struct f_inst *
-f_generate_empty(struct f_inst *dyn)
+f_generate_empty(struct f_dynamic_attr dyn)
{
- struct f_inst *e = f_new_inst();
- e->code = 'E';
+ struct f_inst *e = f_new_inst(FI_EMPTY);
- switch (dyn->aux & EAF_TYPE_MASK) {
+ switch (dyn.type & EAF_TYPE_MASK) {
case EAF_TYPE_AS_PATH:
e->aux = T_PATH;
break;
@@ -179,9 +176,9 @@ f_generate_empty(struct f_inst *dyn)
cf_error("Can't empty that attribute");
}
- dyn->code = P('e','S');
- dyn->a1.p = e;
- return dyn;
+ struct f_inst *s = f_new_inst_da(FI_EA_SET, dyn);
+ s->a1.p = e;
+ return s;
}
@@ -190,21 +187,19 @@ f_generate_dpair(struct f_inst *t1, struct f_inst *t2)
{
struct f_inst *rv;
- if ((t1->code == 'c') && (t2->code == 'c')) {
+ if ((t1->fi_code == FI_CONSTANT) && (t2->fi_code == FI_CONSTANT)) {
if ((t1->aux != T_INT) || (t2->aux != T_INT))
cf_error( "Can't operate with value of non-integer type in pair constructor");
check_u16(t1->a2.i);
check_u16(t2->a2.i);
- rv = f_new_inst();
- rv->code = 'c';
+ rv = f_new_inst(FI_CONSTANT);
rv->aux = T_PAIR;
rv->a2.i = pair(t1->a2.i, t2->a2.i);
}
else {
- rv = f_new_inst();
- rv->code = P('m', 'p');
+ rv = f_new_inst(FI_PAIR_CONSTRUCT);
rv->a1.p = t1;
rv->a2.p = t2;
}
@@ -219,7 +214,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
int c1 = 0, c2 = 0, ipv4_used = 0;
u32 key = 0, val2 = 0;
- if (tk->code == 'c') {
+ if (tk->fi_code == FI_CONSTANT) {
c1 = 1;
if (tk->aux == T_INT) {
@@ -234,7 +229,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
#ifndef IPV6
/* IP->Quad implicit conversion */
- else if (tk->code == 'C') {
+ else if (tk->fi_code == FI_CONSTANT_INDIRECT) {
c1 = 1;
struct f_val *val = tk->a1.p;
@@ -252,7 +247,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
}
#endif
- if (tv->code == 'c') {
+ if (tv->fi_code == FI_CONSTANT) {
if (tv->aux != T_INT)
cf_error("Can't operate with value of non-integer type in EC constructor");
c2 = 1;
@@ -278,15 +273,13 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
}
NEW_F_VAL;
- rv = f_new_inst();
- rv->code = 'C';
+ rv = f_new_inst(FI_CONSTANT_INDIRECT);
rv->a1.p = val;
val->type = T_EC;
val->val.ec = ec;
}
else {
- rv = f_new_inst();
- rv->code = P('m','c');
+ rv = f_new_inst(FI_EC_CONSTRUCT);
rv->aux = kind;
rv->a1.p = tk;
rv->a2.p = tv;
@@ -300,12 +293,11 @@ f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3)
{
struct f_inst *rv;
- if ((t1->code == 'c') && (t2->code == 'c') && (t3->code == 'c')) {
+ if ((t1->fi_code == FI_CONSTANT) && (t2->fi_code == FI_CONSTANT) && (t3->fi_code == FI_CONSTANT)) {
if ((t1->aux != T_INT) || (t2->aux != T_INT) || (t3->aux != T_INT))
cf_error( "LC - Can't operate with value of non-integer type in tuple constructor");
- rv = f_new_inst();
- rv->code = 'C';
+ rv = f_new_inst(FI_CONSTANT_INDIRECT);
NEW_F_VAL;
rv->a1.p = val;
@@ -316,7 +308,7 @@ f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3)
{
rv = cfg_allocz(sizeof(struct f_inst3));
rv->lineno = ifs->lino;
- rv->code = P('m','l');
+ rv->fi_code = FI_LC_CONSTRUCT;
rv->a1.p = t1;
rv->a2.p = t2;
INST3(rv).p = t3;
@@ -348,7 +340,9 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
%nonassoc THEN
%nonassoc ELSE
-%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr
+%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr
+%type <fda> dynamic_attr
+%type <fsa> static_attr
%type <f> filter filter_body where_filter
%type <i> type break_command ec_kind
%type <i32> cnum
@@ -461,16 +455,13 @@ where_filter:
/* Construct 'IF term THEN ACCEPT; REJECT;' */
struct filter *f = cfg_alloc(sizeof(struct filter));
struct f_inst *i, *acc, *rej;
- acc = f_new_inst(); /* ACCEPT */
- acc->code = P('p',',');
+ acc = f_new_inst(FI_PRINT_AND_DIE); /* ACCEPT */
acc->a1.p = NULL;
acc->a2.i = F_ACCEPT;
- rej = f_new_inst(); /* REJECT */
- rej->code = P('p',',');
+ rej = f_new_inst(FI_PRINT_AND_DIE); /* REJECT */
rej->a1.p = NULL;
rej->a2.i = F_REJECT;
- i = f_new_inst(); /* IF */
- i->code = '?';
+ i = f_new_inst(FI_CONDITION); /* IF */
i->a1.p = $2;
i->a2.p = acc;
i->next = rej;
@@ -489,8 +480,7 @@ function_body:
decls '{' cmds '}' {
if ($1) {
/* Prepend instruction to clear local variables */
- $$ = f_new_inst();
- $$->code = P('c','v');
+ $$ = f_new_inst(FI_CLEAR_LOCAL_VARS);
$$->a1.p = $1;
$$->next = $3;
} else
@@ -680,7 +670,7 @@ switch_body: /* EMPTY */ { $$ = NULL; }
}
;
-/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
+/* CONST '(' expr ')' { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_INT; $$->a2.i = $3; } */
bgp_path_expr:
symbol { $$ = $1; }
@@ -708,17 +698,17 @@ bgp_path_tail2:
;
constant:
- NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; }
- | TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; }
- | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; }
- | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
- | fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
- | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
- | RTRID { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD; $$->a2.i = $1; }
- | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
- | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; }
- | ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
- | bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; }
+ NUM { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_INT; $$->a2.i = $1; }
+ | TRUE { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_BOOL; $$->a2.i = 1; }
+ | FALSE { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_BOOL; $$->a2.i = 0; }
+ | TEXT { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_STRING; $$->a2.p = $1; }
+ | fipa { NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); $$->a1.p = val; *val = $1; }
+ | fprefix_s {NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); $$->a1.p = val; *val = $1; }
+ | RTRID { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_QUAD; $$->a2.i = $1; }
+ | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(FI_CONSTANT); $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
+ | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_PREFIX_SET; $$->a2.p = $2; }
+ | ENUM { $$ = f_new_inst(FI_CONSTANT); $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
+ | bgp_path { NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; }
;
constructor:
@@ -733,7 +723,7 @@ constructor:
* For such cases, we force the dynamic_attr list to contain
* at least an invalid token, so it is syntantically correct.
*/
-CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; })
+CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = (struct f_dynamic_attr) {}; })
rtadot: /* EMPTY, we are not permitted RTA. prefix */
;
@@ -745,8 +735,7 @@ function_call:
if ($1->class != SYM_FUNCTION)
cf_error("You can't call something which is not a function. Really.");
DBG("You are calling function %s\n", $1->name);
- $$ = f_new_inst();
- $$->code = P('c','a');
+ $$ = f_new_inst(FI_CALL);
$$->a1.p = inst;
$$->a2.p = $1->def;
sym = $1->aux2;
@@ -763,11 +752,9 @@ function_call:
symbol:
SYM {
- $$ = f_new_inst();
-
switch ($1->class & 0xff00) {
- case SYM_CONSTANT: $$->code = 'C'; break;
- case SYM_VARIABLE: $$->code = 'V'; break;
+ case SYM_CONSTANT: $$ = f_new_inst(FI_CONSTANT_INDIRECT); break;
+ case SYM_VARIABLE: $$ = f_new_inst(FI_VARIABLE); break;
default: cf_error("%s: variable expected.", $1->name);
}
@@ -776,53 +763,53 @@ symbol:
}
static_attr:
- FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_FROM; $$->a1.i = 1; }
- | GW { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_GW; $$->a1.i = 1; }
- | NET { $$ = f_new_inst(); $$->aux = T_PREFIX; $$->a2.i = SA_NET; }
- | PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_PROTO; }
- | SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = SA_SOURCE; }
- | SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE; $$->a1.i = 1; }
- | CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = SA_CAST; }
- | DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = SA_DEST; $$->a1.i = 1; }
- | IFNAME { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_IFNAME; }
- | IFINDEX { $$ = f_new_inst(); $$->aux = T_INT; $$->a2.i = SA_IFINDEX; }
+ FROM { $$ = f_new_static_attr(T_IP, SA_FROM, 1); }
+ | GW { $$ = f_new_static_attr(T_IP, SA_GW, 1); }
+ | NET { $$ = f_new_static_attr(T_PREFIX, SA_NET, 0); }
+ | PROTO { $$ = f_new_static_attr(T_STRING, SA_PROTO, 0); }
+ | SOURCE { $$ = f_new_static_attr(T_ENUM_RTS, SA_SOURCE, 0); }
+ | SCOPE { $$ = f_new_static_attr(T_ENUM_SCOPE, SA_SCOPE, 1); }
+ | CAST { $$ = f_new_static_attr(T_ENUM_RTC, SA_CAST, 0); }
+ | DEST { $$ = f_new_static_attr(T_ENUM_RTD, SA_DEST, 1); }
+ | IFNAME { $$ = f_new_static_attr(T_STRING, SA_IFNAME, 0); }
+ | IFINDEX { $$ = f_new_static_attr(T_INT, SA_IFINDEX, 0); }
;
term:
- '(' 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 = $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; }
- | term LEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $1; $$->a2.p = $3; }
- | term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
- | term GEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $3; $$->a2.p = $1; }
- | term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
- | term NMA term { $$ = f_new_inst(); $$->code = P('!','~'); $$->a1.p = $1; $$->a2.p = $3; }
- | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
- | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
+ '(' term ')' { $$ = $2; }
+ | term '+' term { $$ = f_new_inst(FI_ADD); $$->a1.p = $1; $$->a2.p = $3; }
+ | term '-' term { $$ = f_new_inst(FI_SUBTRACT); $$->a1.p = $1; $$->a2.p = $3; }
+ | term '*' term { $$ = f_new_inst(FI_MULTIPLY); $$->a1.p = $1; $$->a2.p = $3; }
+ | term '/' term { $$ = f_new_inst(FI_DIVIDE); $$->a1.p = $1; $$->a2.p = $3; }
+ | term AND term { $$ = f_new_inst(FI_AND); $$->a1.p = $1; $$->a2.p = $3; }
+ | term OR term { $$ = f_new_inst(FI_OR); $$->a1.p = $1; $$->a2.p = $3; }
+ | term '=' term { $$ = f_new_inst(FI_EQ); $$->a1.p = $1; $$->a2.p = $3; }
+ | term NEQ term { $$ = f_new_inst(FI_NEQ); $$->a1.p = $1; $$->a2.p = $3; }
+ | term '<' term { $$ = f_new_inst(FI_LT); $$->a1.p = $1; $$->a2.p = $3; }
+ | term LEQ term { $$ = f_new_inst(FI_LTE); $$->a1.p = $1; $$->a2.p = $3; }
+ | term '>' term { $$ = f_new_inst(FI_LT); $$->a1.p = $3; $$->a2.p = $1; }
+ | term GEQ term { $$ = f_new_inst(FI_LTE); $$->a1.p = $3; $$->a2.p = $1; }
+ | term '~' term { $$ = f_new_inst(FI_MATCH); $$->a1.p = $1; $$->a2.p = $3; }
+ | term NMA term { $$ = f_new_inst(FI_NOT_MATCH);$$->a1.p = $1; $$->a2.p = $3; }
+ | '!' term { $$ = f_new_inst(FI_NOT); $$->a1.p = $2; }
+ | DEFINED '(' term ')' { $$ = f_new_inst(FI_DEFINED); $$->a1.p = $3; }
| symbol { $$ = $1; }
| constant { $$ = $1; }
| constructor { $$ = $1; }
- | PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; }
+ | PREFERENCE { $$ = f_new_inst(FI_PREF_GET); }
- | rtadot static_attr { $$ = $2; $$->code = 'a'; }
+ | rtadot static_attr { $$ = f_new_inst_sa(FI_RTA_GET, $2); }
- | rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); }
+ | rtadot dynamic_attr { $$ = f_new_inst_da(FI_EA_GET, $2); }
- | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
- | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
- | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
- | term '.' FIRST { $$ = f_new_inst(); $$->code = P('a','f'); $$->a1.p = $1; }
- | term '.' LAST { $$ = f_new_inst(); $$->code = P('a','l'); $$->a1.p = $1; }
- | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(); $$->code = P('a','L'); $$->a1.p = $1; }
+ | term '.' IP { $$ = f_new_inst(FI_IP); $$->a1.p = $1; $$->aux = T_IP; }
+ | term '.' LEN { $$ = f_new_inst(FI_LENGTH); $$->a1.p = $1; }
+ | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK); $$->a1.p = $1; $$->a2.p = $5; }
+ | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST); $$->a1.p = $1; }
+ | term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST); $$->a1.p = $1; }
+ | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG); $$->a1.p = $1; }
/* Communities */
/* This causes one shift/reduce conflict
@@ -832,20 +819,18 @@ term:
| rtadot dynamic_attr '.' RESET{ }
*/
- | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; }
- | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; }
- | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; }
- | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_LCLIST; }
- | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }
- | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
- | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
- | FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
+ | '+' EMPTY '+' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_PATH; }
+ | '-' EMPTY '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_CLIST; }
+ | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_ECLIST; }
+ | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_LCLIST; }
+ | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND); $$->a1.p = $3; $$->a2.p = $5; }
+ | ADD '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
+ | DELETE '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
+ | FILTER '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
| ROA_CHECK '(' SYM ')' { $$ = f_generate_roa_check($3, NULL, NULL); }
| ROA_CHECK '(' SYM ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); }
-/* | term '.' LEN { $$->code = P('P','l'); } */
-
/* function_call is inlined here */
| SYM '(' var_list ')' {
struct symbol *sym;
@@ -853,8 +838,7 @@ term:
if ($1->class != SYM_FUNCTION)
cf_error("You can't call something which is not a function. Really.");
DBG("You are calling function %s\n", $1->name);
- $$ = f_new_inst();
- $$->code = P('c','a');
+ $$ = f_new_inst(FI_CALL);
$$->a1.p = inst;
$$->a2.p = $1->def;
sym = $1->aux2;
@@ -879,7 +863,7 @@ break_command:
;
print_one:
- term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
+ term { $$ = f_new_inst(FI_PRINT); $$->a1.p = $1; $$->a2.p = NULL; }
;
print_list: /* EMPTY */ { $$ = NULL; }
@@ -893,15 +877,13 @@ print_list: /* EMPTY */ { $$ = NULL; }
;
var_listn: term {
- $$ = f_new_inst();
- $$->code = 's';
+ $$ = f_new_inst(FI_SET);
$$->a1.p = NULL;
$$->a2.p = $1;
$$->next = NULL;
}
| term ',' var_listn {
- $$ = f_new_inst();
- $$->code = 's';
+ $$ = f_new_inst(FI_SET);
$$->a1.p = NULL;
$$->a2.p = $1;
$$->next = $3;
@@ -914,74 +896,64 @@ var_list: /* EMPTY */ { $$ = NULL; }
cmd:
IF term THEN block {
- $$ = f_new_inst();
- $$->code = '?';
+ $$ = f_new_inst(FI_CONDITION);
$$->a1.p = $2;
$$->a2.p = $4;
}
| IF term THEN block ELSE block {
- struct f_inst *i = f_new_inst();
- i->code = '?';
+ struct f_inst *i = f_new_inst(FI_CONDITION);
i->a1.p = $2;
i->a2.p = $4;
- $$ = f_new_inst();
- $$->code = '?';
+ $$ = f_new_inst(FI_CONDITION);
$$->a1.p = i;
$$->a2.p = $6;
}
| SYM '=' term ';' {
- $$ = f_new_inst();
DBG( "Ook, we'll set value\n" );
if (($1->class & ~T_MASK) != SYM_VARIABLE)
cf_error( "You may set only variables." );
- $$->code = 's';
+ $$ = f_new_inst(FI_SET);
$$->a1.p = $1;
$$->a2.p = $3;
}
| RETURN term ';' {
- $$ = f_new_inst();
DBG( "Ook, we'll return the value\n" );
- $$->code = 'r';
+ $$ = f_new_inst(FI_RETURN);
$$->a1.p = $2;
}
| rtadot dynamic_attr '=' term ';' {
- $$ = $2;
- $$->code = P('e','S');
+ $$ = f_new_inst_da(FI_EA_SET, $2);
$$->a1.p = $4;
}
| rtadot static_attr '=' term ';' {
- $$ = $2;
+ $$ = f_new_inst_sa(FI_RTA_SET, $2);
if (!$$->a1.i)
cf_error( "This static attribute is read-only.");
- $$->code = P('a','S');
$$->a1.p = $4;
}
| PREFERENCE '=' term ';' {
- $$ = f_new_inst();
- $$->code = P('P','S');
+ $$ = f_new_inst(FI_PREF_SET);
$$->a1.p = $3;
}
| UNSET '(' rtadot dynamic_attr ')' ';' {
- $$ = $4;
+ $$ = f_new_inst_da(FI_EA_SET, $4);
$$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
- $$->code = P('e','S');
$$->a1.p = NULL;
}
- | break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; }
+ | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE); $$->a1.p = $2; $$->a2.i = $1; }
| function_call ';' { $$ = $1; }
| CASE term '{' switch_body '}' {
- $$ = f_new_inst();
- $$->code = P('S','W');
+ $$ = f_new_inst(FI_SWITCH);
$$->a1.p = $2;
$$->a2.p = build_tree( $4 );
}
| rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); }
- | rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); }
- | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); }
- | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); }
- | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); }
+ | rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( FI_PATH_PREPEND, 'x', $2, $6 ); }
+ | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'a', $2, $6 ); }
+ | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'd', $2, $6 ); }
+ | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'f', $2, $6 ); }
;
CF_END
diff --git a/filter/f-util.c b/filter/f-util.c
index def2b248..42b08868 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -2,6 +2,7 @@
* Filters: utility functions
*
* Copyright 1998 Pavel Machek <pavel@ucw.cz>
+ * 2017 Jan Maria Matejka <mq@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -13,43 +14,48 @@
#define P(a,b) ((a<<8) | b)
struct f_inst *
-f_new_inst(void)
+f_new_inst(enum f_instruction_code fi_code)
{
struct f_inst * ret;
- ret = cfg_alloc(sizeof(struct f_inst));
- ret->code = ret->aux = 0;
- ret->arg1 = ret->arg2 = ret->next = NULL;
+ ret = cfg_allocz(sizeof(struct f_inst));
+ ret->fi_code = fi_code;
ret->lineno = ifs->lino;
return ret;
}
struct f_inst *
-f_new_dynamic_attr(int type, int f_type UNUSED, int code)
+f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da)
{
- /* FIXME: Remove the f_type parameter? */
- struct f_inst *f = f_new_inst();
- f->aux = type;
- f->a2.i = code;
- return f;
+ struct f_inst *ret = f_new_inst(fi_code);
+ ret->aux = da.type;
+ ret->a2.i = da.ea_code;
+ return ret;
+}
+
+struct f_inst *
+f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa)
+{
+ struct f_inst *ret = f_new_inst(fi_code);
+ ret->aux = sa.f_type;
+ ret->a2.i = sa.sa_code;
+ ret->a1.i = sa.readonly;
+ return ret;
}
/*
* Generate set_dynamic( operation( get_dynamic(), argument ) )
*/
struct f_inst *
-f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument)
+f_generate_complex(int operation, int operation_aux, struct f_dynamic_attr da, struct f_inst *argument)
{
- struct f_inst *set_dyn = f_new_inst(),
- *oper = f_new_inst(),
- *get_dyn = dyn;
+ struct f_inst *set_dyn = f_new_inst_da(FI_EA_SET, da),
+ *oper = f_new_inst(operation),
+ *get_dyn = f_new_inst_da(FI_EA_GET, da);
- *set_dyn = *get_dyn;
- get_dyn->code = P('e','a');
- oper->code = operation;
oper->aux = operation_aux;
oper->a1.p = get_dyn;
oper->a2.p = argument;
- set_dyn->code = P('e','S');
+
set_dyn->a1.p = oper;
return set_dyn;
}
@@ -59,7 +65,7 @@ struct f_inst *
f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *asn)
{
struct f_inst_roa_check *ret = cfg_allocz(sizeof(struct f_inst_roa_check));
- ret->i.code = P('R','C');
+ ret->i.fi_code = FI_ROA_CHECK;
ret->i.lineno = ifs->lino;
ret->i.arg1 = prefix;
ret->i.arg2 = asn;
diff --git a/filter/filter.c b/filter/filter.c
index b0c56046..db90941f 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -46,8 +46,6 @@
#include "conf/conf.h"
#include "filter/filter.h"
-#define P(a,b) ((a<<8) | b)
-
#define CMP_ERROR 999
static struct adata *
@@ -644,13 +642,13 @@ interpret(struct f_inst *what)
if (!what)
return res;
- switch(what->code) {
- case ',':
+ switch(what->fi_code) {
+ case FI_COMMA:
TWOARGS;
break;
/* Binary operators */
- case '+':
+ case FI_ADD:
TWOARGS_C;
switch (res.type = v1.type) {
case T_VOID: runtime( "Can't operate with values of type void" );
@@ -658,7 +656,7 @@ interpret(struct f_inst *what)
default: runtime( "Usage of unknown type" );
}
break;
- case '-':
+ case FI_SUBTRACT:
TWOARGS_C;
switch (res.type = v1.type) {
case T_VOID: runtime( "Can't operate with values of type void" );
@@ -666,7 +664,7 @@ interpret(struct f_inst *what)
default: runtime( "Usage of unknown type" );
}
break;
- case '*':
+ case FI_MULTIPLY:
TWOARGS_C;
switch (res.type = v1.type) {
case T_VOID: runtime( "Can't operate with values of type void" );
@@ -674,7 +672,7 @@ interpret(struct f_inst *what)
default: runtime( "Usage of unknown type" );
}
break;
- case '/':
+ case FI_DIVIDE:
TWOARGS_C;
switch (res.type = v1.type) {
case T_VOID: runtime( "Can't operate with values of type void" );
@@ -684,12 +682,12 @@ interpret(struct f_inst *what)
}
break;
- case '&':
- case '|':
+ case FI_AND:
+ case FI_OR:
ARG(v1, a1.p);
if (v1.type != T_BOOL)
runtime( "Can't do boolean operation on non-booleans" );
- if (v1.val.i == (what->code == '|')) {
+ if (v1.val.i == (what->fi_code == FI_OR)) {
res.type = T_BOOL;
res.val.i = v1.val.i;
break;
@@ -702,7 +700,7 @@ interpret(struct f_inst *what)
res.val.i = v2.val.i;
break;
- case P('m','p'):
+ case FI_PAIR_CONSTRUCT:
TWOARGS;
if ((v1.type != T_INT) || (v2.type != T_INT))
runtime( "Can't operate with value of non-integer type in pair constructor" );
@@ -714,7 +712,7 @@ interpret(struct f_inst *what)
res.type = T_PAIR;
break;
- case P('m','c'):
+ case FI_EC_CONSTRUCT:
{
TWOARGS;
@@ -762,7 +760,7 @@ interpret(struct f_inst *what)
break;
}
- case P('m','l'):
+ case FI_LC_CONSTRUCT:
{
TWOARGS;
@@ -798,12 +796,12 @@ interpret(struct f_inst *what)
res.val.i = (x); \
break;
- case P('!','='): SAME(!i);
- case P('=','='): SAME(i);
- case '<': COMPARE(i==-1);
- case P('<','='): COMPARE(i!=1);
+ case FI_NEQ: SAME(!i);
+ case FI_EQ: SAME(i);
+ case FI_LT: COMPARE(i==-1);
+ case FI_LTE: COMPARE(i!=1);
- case '!':
+ case FI_NOT:
ONEARG;
if (v1.type != T_BOOL)
runtime( "Not applied to non-boolean" );
@@ -811,7 +809,7 @@ interpret(struct f_inst *what)
res.val.i = !res.val.i;
break;
- case '~':
+ case FI_MATCH:
TWOARGS;
res.type = T_BOOL;
res.val.i = val_in_range(v1, v2);
@@ -820,7 +818,7 @@ interpret(struct f_inst *what)
res.val.i = !!res.val.i;
break;
- case P('!','~'):
+ case FI_NOT_MATCH:
TWOARGS;
res.type = T_BOOL;
res.val.i = val_in_range(v1, v2);
@@ -829,14 +827,14 @@ interpret(struct f_inst *what)
res.val.i = !res.val.i;
break;
- case P('d','e'):
+ case FI_DEFINED:
ONEARG;
res.type = T_BOOL;
res.val.i = (v1.type != T_VOID);
break;
/* Set to indirect value, a1 = variable, a2 = value */
- case 's':
+ case FI_SET:
ARG(v2, a2.p);
sym = what->a1.p;
vp = sym->def;
@@ -855,7 +853,7 @@ interpret(struct f_inst *what)
break;
/* some constants have value in a2, some in *a1.p, strange. */
- case 'c': /* integer (or simple type) constant, string, set, or prefix_set */
+ case FI_CONSTANT: /* integer (or simple type) constant, string, set, or prefix_set */
res.type = what->aux;
if (res.type == T_PREFIX_SET)
@@ -867,15 +865,15 @@ interpret(struct f_inst *what)
else
res.val.i = what->a2.i;
break;
- case 'V':
- case 'C':
+ case FI_VARIABLE:
+ case FI_CONSTANT_INDIRECT:
res = * ((struct f_val *) what->a1.p);
break;
- case 'p':
+ case FI_PRINT:
ONEARG;
val_format(v1, &f_buf);
break;
- case '?': /* ? has really strange error value, so we can implement if ... else nicely :-) */
+ case FI_CONDITION: /* ? has really strange error value, so we can implement if ... else nicely :-) */
ONEARG;
if (v1.type != T_BOOL)
runtime( "If requires boolean expression" );
@@ -885,10 +883,10 @@ interpret(struct f_inst *what)
} else res.val.i = 1;
res.type = T_BOOL;
break;
- case '0':
+ case FI_NOP:
debug( "No operation\n" );
break;
- case P('p',','):
+ case FI_PRINT_AND_DIE:
ONEARG;
if ((what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p)) &&
!(f_flags & FF_SILENT))
@@ -911,7 +909,7 @@ interpret(struct f_inst *what)
bug( "unknown return type: Can't happen");
}
break;
- case 'a': /* rta access */
+ case FI_RTA_GET: /* rta access */
{
ACCESS_RTE;
struct rta *rta = (*f_rte)->attrs;
@@ -936,7 +934,7 @@ interpret(struct f_inst *what)
}
}
break;
- case P('a','S'):
+ case FI_RTA_SET:
ACCESS_RTE;
ONEARG;
if (what->aux != v1.type)
@@ -988,7 +986,7 @@ interpret(struct f_inst *what)
}
}
break;
- case P('e','a'): /* Access to extended attributes */
+ case FI_EA_GET: /* Access to extended attributes */
ACCESS_RTE;
{
eattr *e = NULL;
@@ -1074,7 +1072,7 @@ interpret(struct f_inst *what)
}
}
break;
- case P('e','S'):
+ case FI_EA_SET:
ACCESS_RTE;
ONEARG;
{
@@ -1180,12 +1178,12 @@ interpret(struct f_inst *what)
}
}
break;
- case 'P':
+ case FI_PREF_GET:
ACCESS_RTE;
res.type = T_INT;
res.val.i = (*f_rte)->pref;
break;
- case P('P','S'):
+ case FI_PREF_SET:
ACCESS_RTE;
ONEARG;
if (v1.type != T_INT)
@@ -1195,7 +1193,7 @@ interpret(struct f_inst *what)
f_rte_cow();
(*f_rte)->pref = v1.val.i;
break;
- case 'L': /* Get length of */
+ case FI_LENGTH: /* Get length of */
ONEARG;
res.type = T_INT;
switch(v1.type) {
@@ -1207,7 +1205,7 @@ interpret(struct f_inst *what)
default: runtime( "Prefix, path, clist or eclist expected" );
}
break;
- case P('c','p'): /* Convert prefix to ... */
+ case FI_IP: /* Convert prefix to ... */
ONEARG;
if (v1.type != T_PREFIX)
runtime( "Prefix expected" );
@@ -1218,7 +1216,7 @@ interpret(struct f_inst *what)
default: bug( "Unknown prefix to conversion" );
}
break;
- case P('a','f'): /* Get first ASN from AS PATH */
+ case FI_AS_PATH_FIRST: /* Get first ASN from AS PATH */
ONEARG;
if (v1.type != T_PATH)
runtime( "AS path expected" );
@@ -1228,7 +1226,7 @@ interpret(struct f_inst *what)
res.type = T_INT;
res.val.i = as;
break;
- case P('a','l'): /* Get last ASN from AS PATH */
+ case FI_AS_PATH_LAST: /* Get last ASN from AS PATH */
ONEARG;
if (v1.type != T_PATH)
runtime( "AS path expected" );
@@ -1238,7 +1236,7 @@ interpret(struct f_inst *what)
res.type = T_INT;
res.val.i = as;
break;
- case P('a','L'): /* Get last ASN from non-aggregated part of AS PATH */
+ case FI_AS_PATH_LAST_NAG: /* Get last ASN from non-aggregated part of AS PATH */
ONEARG;
if (v1.type != T_PATH)
runtime( "AS path expected" );
@@ -1246,23 +1244,23 @@ interpret(struct f_inst *what)
res.type = T_INT;
res.val.i = as_path_get_last_nonaggregated(v1.val.ad);
break;
- case 'r':
+ case FI_RETURN:
ONEARG;
res = v1;
res.type |= T_RETURN;
return res;
- case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out */
+ case FI_CALL: /* CALL: this is special: if T_RETURN and returning some value, mask it out */
ONEARG;
res = interpret(what->a2.p);
if (res.type == T_RETURN)
return res;
res.type &= ~T_RETURN;
break;
- case P('c','v'): /* Clear local variables */
+ case FI_CLEAR_LOCAL_VARS: /* Clear local variables */
for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
((struct f_val *) sym->def)->type = T_VOID;
break;
- case P('S','W'):
+ case FI_SWITCH:
ONEARG;
{
struct f_tree *t = find_tree(what->a2.p, v1);
@@ -1281,7 +1279,7 @@ interpret(struct f_inst *what)
return res;
}
break;
- case P('i','M'): /* IP.MASK(val) */
+ case FI_IP_MASK: /* IP.MASK(val) */
TWOARGS;
if (v2.type != T_INT)
runtime( "Integer expected");
@@ -1294,11 +1292,11 @@ interpret(struct f_inst *what)
}
break;
- case 'E': /* Create empty attribute */
+ case FI_EMPTY: /* Create empty attribute */
res.type = what->aux;
res.val.ad = adata_empty(f_pool, 0);
break;
- case P('A','p'): /* Path prepend */
+ case FI_PATH_PREPEND: /* Path prepend */
TWOARGS;
if (v1.type != T_PATH)
runtime("Can't prepend to non-path");
@@ -1309,7 +1307,7 @@ interpret(struct f_inst *what)
res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
break;
- case P('C','a'): /* (Extended) Community list add or delete */
+ case FI_CLIST_ADD_DEL: /* (Extended) Community list add or delete */
TWOARGS;
if (v1.type == T_PATH)
{
@@ -1477,7 +1475,7 @@ interpret(struct f_inst *what)
break;
- case P('R','C'): /* ROA Check */
+ case FI_ROA_CHECK: /* ROA Check */
if (what->arg1)
{
TWOARGS;
@@ -1511,7 +1509,7 @@ interpret(struct f_inst *what)
break;
default:
- bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
+ bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff);
}
if (what->next)
return interpret(what->next);
@@ -1541,38 +1539,38 @@ i_same(struct f_inst *f1, struct f_inst *f2)
return 1;
if (f1->aux != f2->aux)
return 0;
- if (f1->code != f2->code)
+ if (f1->fi_code != f2->fi_code)
return 0;
if (f1 == f2) /* It looks strange, but it is possible with call rewriting trickery */
return 1;
- switch(f1->code) {
- case ',': /* fall through */
- case '+':
- case '-':
- case '*':
- case '/':
- case '|':
- case '&':
- case P('m','p'):
- case P('m','c'):
- case P('!','='):
- case P('=','='):
- case '<':
- case P('<','='): TWOARGS; break;
-
- case '!': ONEARG; break;
- case P('!', '~'):
- case '~': TWOARGS; break;
- case P('d','e'): ONEARG; break;
-
- case P('m','l'):
+ switch(f1->fi_code) {
+ case FI_COMMA: /* fall through */
+ case FI_ADD:
+ case FI_SUBTRACT:
+ case FI_MULTIPLY:
+ case FI_DIVIDE:
+ case FI_OR:
+ case FI_AND:
+ case FI_PAIR_CONSTRUCT:
+ case FI_EC_CONSTRUCT:
+ case FI_NEQ:
+ case FI_EQ:
+ case FI_LT:
+ case FI_LTE: TWOARGS; break;
+
+ case FI_NOT: ONEARG; break;
+ case FI_NOT_MATCH:
+ case FI_MATCH: TWOARGS; break;
+ case FI_DEFINED: ONEARG; break;
+
+ case FI_LC_CONSTRUCT:
TWOARGS;
if (!i_same(INST3(f1).p, INST3(f2).p))
return 0;
break;
- case 's':
+ case FI_SET:
ARG(v2, a2.p);
{
struct symbol *s1, *s2;
@@ -1585,7 +1583,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
}
break;
- case 'c':
+ case FI_CONSTANT:
switch (f1->aux) {
case T_PREFIX_SET:
@@ -1608,43 +1606,43 @@ i_same(struct f_inst *f1, struct f_inst *f2)
}
break;
- case 'C':
+ case FI_CONSTANT_INDIRECT:
if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
return 0;
break;
- case 'V':
+ case FI_VARIABLE:
if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
return 0;
break;
- case 'p': case 'L': ONEARG; break;
- case '?': TWOARGS; break;
- case '0': case 'E': break;
- case P('p',','): ONEARG; A2_SAME; break;
- case 'P':
- case 'a': A2_SAME; break;
- case P('e','a'): A2_SAME; break;
- case P('P','S'):
- case P('a','S'):
- case P('e','S'): ONEARG; A2_SAME; break;
-
- case 'r': ONEARG; break;
- case P('c','p'): ONEARG; break;
- case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
+ case FI_PRINT: case FI_LENGTH: ONEARG; break;
+ case FI_CONDITION: TWOARGS; break;
+ case FI_NOP: case FI_EMPTY: break;
+ case FI_PRINT_AND_DIE: ONEARG; A2_SAME; break;
+ case FI_PREF_GET:
+ case FI_RTA_GET: A2_SAME; break;
+ case FI_EA_GET: A2_SAME; break;
+ case FI_PREF_SET:
+ case FI_RTA_SET:
+ case FI_EA_SET: ONEARG; A2_SAME; break;
+
+ case FI_RETURN: ONEARG; break;
+ case FI_IP: ONEARG; break;
+ case FI_CALL: /* Call rewriting trickery to avoid exponential behaviour */
ONEARG;
if (!i_same(f1->a2.p, f2->a2.p))
return 0;
f2->a2.p = f1->a2.p;
break;
- case P('c','v'): break; /* internal instruction */
- case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
- case P('i','M'): TWOARGS; break;
- case P('A','p'): TWOARGS; break;
- case P('C','a'): TWOARGS; break;
- case P('a','f'):
- case P('a','l'):
- case P('a','L'): ONEARG; break;
- case P('R','C'):
+ case FI_CLEAR_LOCAL_VARS: break; /* internal instruction */
+ case FI_SWITCH: ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
+ case FI_IP_MASK: TWOARGS; break;
+ case FI_PATH_PREPEND: TWOARGS; break;
+ case FI_CLIST_ADD_DEL: TWOARGS; break;
+ case FI_AS_PATH_FIRST:
+ case FI_AS_PATH_LAST:
+ case FI_AS_PATH_LAST_NAG: ONEARG; break;
+ case FI_ROA_CHECK:
TWOARGS;
/* Does not really make sense - ROA check resuls may change anyway */
if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name,
@@ -1652,7 +1650,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
return 0;
break;
default:
- bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
+ bug( "Unknown instruction %d in same (%c)", f1->fi_code, f1->fi_code & 0xff);
}
return i_same(f1->next, f2->next);
}
diff --git a/filter/filter.h b/filter/filter.h
index efb4b978..09f96084 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -14,9 +14,67 @@
#include "nest/route.h"
#include "nest/attrs.h"
+/* Filter instruction types */
+
+#define FI__TWOCHAR(a,b) ((a<<8) | b)
+#define FI__LIST \
+ F(FI_COMMA, 0, ',') \
+ F(FI_ADD, 0, '+') \
+ F(FI_SUBTRACT, 0, '-') \
+ F(FI_MULTIPLY, 0, '*') \
+ F(FI_DIVIDE, 0, '/') \
+ F(FI_AND, 0, '&') \
+ F(FI_OR, 0, '|') \
+ F(FI_PAIR_CONSTRUCT, 'm', 'p') \
+ F(FI_EC_CONSTRUCT, 'm', 'c') \
+ F(FI_LC_CONSTRUCT, 'm', 'l') \
+ F(FI_NEQ, '!', '=') \
+ F(FI_EQ, '=', '=') \
+ F(FI_LT, 0, '<') \
+ F(FI_LTE, '<', '=') \
+ F(FI_NOT, 0, '!') \
+ F(FI_MATCH, 0, '~') \
+ F(FI_NOT_MATCH, '!', '~') \
+ F(FI_DEFINED, 'd', 'e') \
+ F(FI_SET, 0, 's') \
+ F(FI_CONSTANT, 0, 'c') \
+ F(FI_VARIABLE, 0, 'V') \
+ F(FI_CONSTANT_INDIRECT, 0, 'C') \
+ F(FI_PRINT, 0, 'p') \
+ F(FI_CONDITION, 0, '?') \
+ F(FI_NOP, 0, '0') \
+ F(FI_PRINT_AND_DIE, 'p', ',') \
+ F(FI_RTA_GET, 0, 'a') \
+ F(FI_RTA_SET, 'a', 'S') \
+ F(FI_EA_GET, 'e', 'a') \
+ F(FI_EA_SET, 'e', 'S') \
+ F(FI_PREF_GET, 0, 'P') \
+ F(FI_PREF_SET, 'P', 'S') \
+ F(FI_LENGTH, 0, 'L') \
+ F(FI_IP, 'c', 'p') \
+ F(FI_AS_PATH_FIRST, 'a', 'f') \
+ F(FI_AS_PATH_LAST, 'a', 'l') \
+ F(FI_AS_PATH_LAST_NAG, 'a', 'L') \
+ F(FI_RETURN, 0, 'r') \
+ F(FI_CALL, 'c', 'a') \
+ F(FI_CLEAR_LOCAL_VARS, 'c', 'V') \
+ F(FI_SWITCH, 'S', 'W') \
+ F(FI_IP_MASK, 'i', 'M') \
+ F(FI_EMPTY, 0, 'E') \
+ F(FI_PATH_PREPEND, 'A', 'p') \
+ F(FI_CLIST_ADD_DEL, 'C', 'a') \
+ F(FI_ROA_CHECK, 'R', 'C')
+
+enum f_instruction_code {
+#define F(c,a,b) \
+ c = FI__TWOCHAR(a,b),
+FI__LIST
+#undef F
+} PACKED;
+
struct f_inst { /* Instruction */
struct f_inst *next; /* Structure is 16 bytes, anyway */
- u16 code;
+ enum f_instruction_code fi_code;
u16 aux;
union {
int i;
@@ -75,15 +133,32 @@ struct f_val {
} val;
};
+struct f_dynamic_attr {
+ int type;
+ int f_type;
+ int ea_code;
+};
+
+struct f_static_attr {
+ int f_type;
+ int sa_code;
+ int readonly;
+};
+
struct filter {
char *name;
struct f_inst *root;
};
-struct f_inst *f_new_inst(void);
-struct f_inst *f_new_dynamic_attr(int type, int f_type, int code); /* Type as core knows it, type as filters know it, and code of dynamic attribute */
+struct f_inst *f_new_inst(enum f_instruction_code fi_code);
+struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da);
+struct f_inst *f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa);
+static inline struct f_dynamic_attr f_new_dynamic_attr(int type, int f_type, int code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
+{ return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
+static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly)
+{ return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; }
struct f_tree *f_new_tree(void);
-struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument);
+struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_dynamic_attr da, struct f_inst *argument);
struct f_inst *f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *asn);