Filters now do not allow function (int arg; int arg2; ).
This commit is contained in:
parent
e5005be2b4
commit
6dc7a0cb39
4 changed files with 100 additions and 30 deletions
10
bird.conf
10
bird.conf
|
@ -8,7 +8,9 @@ router id 62.168.0.1;
|
||||||
|
|
||||||
define xyzzy = 120+10;
|
define xyzzy = 120+10;
|
||||||
|
|
||||||
function callme (int arg1; int arg2;)
|
function callme ( int arg1; int arg2 )
|
||||||
|
int local1;
|
||||||
|
int local2;
|
||||||
{
|
{
|
||||||
print "Function callme called arguments " arg1 " and " arg2;
|
print "Function callme called arguments " arg1 " and " arg2;
|
||||||
|
|
||||||
|
@ -33,8 +35,8 @@ prefix px;
|
||||||
if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
|
if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
|
||||||
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
|
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
|
||||||
|
|
||||||
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 ];
|
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.2.3.4/8 "," 1.2.3.4/8 ~ 1.2.3.4/8 "," 1.2.3.4/8 ~ 1.2.3.4/8+ "," 1.2.3.4/16 ~ 1.2.3.4/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);
|
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.2.3.4/8 ~ 1.2.3.4/8- "," 1.2.3.4/17 ~ 1.2.3.4/8{ 15 , 16 };
|
||||||
|
|
||||||
px = 1.2.3.4/18;
|
px = 1.2.3.4/18;
|
||||||
print "Testing prefixes: 1.2.3.4/18 = " px;
|
print "Testing prefixes: 1.2.3.4/18 = " px;
|
||||||
|
@ -60,6 +62,8 @@ int j;
|
||||||
{
|
{
|
||||||
print "Heya, filtering route to " rta.net.ip " prefixlen " rta.net.len;
|
print "Heya, filtering route to " rta.net.ip " prefixlen " rta.net.len;
|
||||||
print "This route was from " rta.from;
|
print "This route was from " rta.from;
|
||||||
|
j = 7;
|
||||||
|
j = 17;
|
||||||
accept;
|
accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*
|
*
|
||||||
FIXME: define keyword
|
FIXME: define keyword
|
||||||
FIXME: make px+, px- px^pair work in prefix sets
|
|
||||||
FIXME: create ip.mask(x) function
|
FIXME: create ip.mask(x) function
|
||||||
FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
|
FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
|
||||||
FIXME: create community lists
|
FIXME: create community lists
|
||||||
FIXME: access to dynamic attributes
|
FIXME: access to dynamic attributes
|
||||||
|
FIXME: local namespace for functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CF_HDR
|
CF_HDR
|
||||||
|
@ -30,18 +30,18 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST,
|
||||||
INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
|
INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
|
||||||
IF, THEN, ELSE, CASE,
|
IF, THEN, ELSE, CASE,
|
||||||
TRUE, FALSE,
|
TRUE, FALSE,
|
||||||
RTA, FROM, GW, NET, MASK,
|
RTA, FROM, GW, NET, MASK, RIP_METRIC, RIP_TAG,
|
||||||
LEN,
|
LEN,
|
||||||
IMPOSSIBLE,
|
IMPOSSIBLE,
|
||||||
FILTER
|
FILTER
|
||||||
)
|
)
|
||||||
|
|
||||||
%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list
|
%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list var_listn
|
||||||
%type <f> filter filter_body
|
%type <f> filter filter_body
|
||||||
%type <i> type break_command pair
|
%type <i> type break_command pair
|
||||||
%type <e> set_item set_items switch_body
|
%type <e> set_item set_items switch_body
|
||||||
%type <v> set_atom prefix prefix_s ipa
|
%type <v> set_atom prefix prefix_s ipa
|
||||||
%type <s> decls function_params
|
%type <s> decls declsn one_decl function_params
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
|
@ -71,11 +71,11 @@ type:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
decls: /* EMPTY */ { $$ = NULL; }
|
one_decl:
|
||||||
| type SYM ';' decls {
|
type SYM {
|
||||||
cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
|
cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
|
||||||
printf( "New variable %s type %x\n", $2->name, $1 );
|
printf( "New variable %s type %x\n", $2->name, $1 );
|
||||||
$2->aux = $4;
|
$2->aux = NULL;
|
||||||
{
|
{
|
||||||
struct f_val * val;
|
struct f_val * val;
|
||||||
val = cfg_alloc(sizeof(struct f_val));
|
val = cfg_alloc(sizeof(struct f_val));
|
||||||
|
@ -86,6 +86,24 @@ decls: /* EMPTY */ { $$ = NULL; }
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Decls with ';' at the end */
|
||||||
|
decls: /* EMPTY */ { $$ = NULL; }
|
||||||
|
| one_decl ';' decls {
|
||||||
|
$$ = $1;
|
||||||
|
$$->aux = $3;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Declarations that have no ';' at the end.
|
||||||
|
Ouch, this is responsible for 13 or so shift/reduce conflicts. */
|
||||||
|
declsn: one_decl { $$ = $1; }
|
||||||
|
| declsn ';' one_decl {
|
||||||
|
$$ = $3;
|
||||||
|
$$->aux = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
filter_body:
|
filter_body:
|
||||||
function_body {
|
function_body {
|
||||||
struct filter *f = cfg_alloc(sizeof(struct filter));
|
struct filter *f = cfg_alloc(sizeof(struct filter));
|
||||||
|
@ -104,7 +122,8 @@ filter:
|
||||||
;
|
;
|
||||||
|
|
||||||
function_params:
|
function_params:
|
||||||
'(' decls ')' { printf( "Have function parameters\n" ); $$=$2; }
|
'(' declsn ')' { printf( "Have function parameters\n" ); $$=$2; }
|
||||||
|
| '(' ')' { $$=NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
function_body:
|
function_body:
|
||||||
|
@ -166,11 +185,11 @@ prefix:
|
||||||
prefix_s { $$ = $1; }
|
prefix_s { $$ = $1; }
|
||||||
| prefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
|
| prefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
|
||||||
| prefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
|
| prefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
|
||||||
/* | prefix_s '{' NUM ',' NUM '}' How should this be done? */
|
| prefix_s '{' NUM ',' NUM '}' { $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); }
|
||||||
;
|
;
|
||||||
|
|
||||||
ipa:
|
ipa:
|
||||||
IPA { $$.type = T_IP; $$.val.ip = $1; }
|
IPA { $$.type = T_IP; $$.val.px.ip = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
set_atom:
|
set_atom:
|
||||||
|
@ -213,7 +232,8 @@ constant:
|
||||||
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_STRING; $$->a2.p = $1; }
|
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_STRING; $$->a2.p = $1; }
|
||||||
| pair { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR; $$->a2.i = $1; }
|
| pair { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR; $$->a2.i = $1; }
|
||||||
| ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
| ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
||||||
| prefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
/* Replace with prefix_s to get rid of shift/reduce conflicts. */
|
||||||
|
| prefix {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
||||||
| '[' 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" ); }
|
| '[' 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" ); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -247,6 +267,8 @@ term:
|
||||||
| RTA '.' GW { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); }
|
| 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 '.' 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; }
|
||||||
|
|
||||||
| term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_IP; }
|
| 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; }
|
| term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_INT; }
|
||||||
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = 'iM'; $$->a1.p = $1; $$->a2.p = $5; }
|
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = 'iM'; $$->a1.p = $1; $$->a2.p = $5; }
|
||||||
|
@ -283,14 +305,14 @@ print_list: /* EMPTY */ { $$ = NULL; }
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
var_list: term {
|
var_listn: term {
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
$$->code = 's';
|
$$->code = 's';
|
||||||
$$->a1.p = NULL;
|
$$->a1.p = NULL;
|
||||||
$$->a2.p = $1;
|
$$->a2.p = $1;
|
||||||
$$->next = NULL;
|
$$->next = NULL;
|
||||||
}
|
}
|
||||||
| term ',' var_list {
|
| term ',' var_listn {
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
$$->code = 's';
|
$$->code = 's';
|
||||||
$$->a1.p = NULL;
|
$$->a1.p = NULL;
|
||||||
|
@ -299,6 +321,10 @@ var_list: term {
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
var_list: /* EMPTY */ { $$ = NULL; }
|
||||||
|
| var_listn { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
cmd:
|
cmd:
|
||||||
ifthen {
|
ifthen {
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
*
|
*
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*
|
*
|
||||||
* FIXME: local namespace for functions
|
|
||||||
*
|
|
||||||
* Notice that pair is stored as integer: first << 16 | second
|
* Notice that pair is stored as integer: first << 16 | second
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -70,16 +68,55 @@ val_compare(struct f_val v1, struct f_val v2)
|
||||||
if (v1.val.i < v2.val.i) return -1;
|
if (v1.val.i < v2.val.i) return -1;
|
||||||
return 1;
|
return 1;
|
||||||
case T_IP:
|
case T_IP:
|
||||||
return ipa_compare(v1.val.ip, v2.val.ip);
|
case T_PREFIX:
|
||||||
|
return ipa_compare(v1.val.px.ip, v2.val.px.ip);
|
||||||
default: { printf( "Error comparing\n" ); return CMP_ERROR; }
|
default: { printf( "Error comparing\n" ); return CMP_ERROR; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
val_simple_in_range(struct f_val v1, struct f_val v2)
|
||||||
|
{
|
||||||
|
if ((v1.type == T_IP) && (v2.type == T_PREFIX))
|
||||||
|
return !(ipa_compare(ipa_and(v2.val.px.ip, ipa_mkmask(v2.val.px.len)), ipa_and(v1.val.px.ip, ipa_mkmask(v2.val.px.len))));
|
||||||
|
|
||||||
|
if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX)) {
|
||||||
|
ip_addr mask;
|
||||||
|
if (v1.val.px.len & (LEN_PLUS | LEN_MINUS | LEN_RANGE))
|
||||||
|
return CMP_ERROR;
|
||||||
|
mask = ipa_mkmask( v2.val.px.len & LEN_MASK );
|
||||||
|
if (ipa_compare(ipa_and(v2.val.px.ip, mask), ipa_and(v1.val.px.ip, mask)))
|
||||||
|
return 0;
|
||||||
|
/* FIXME: read rpsl or better ask mj: is it really like this? */
|
||||||
|
if ((v2.val.px.len & LEN_MINUS) && (v1.val.px.len <= (v2.val.px.len & LEN_MASK)))
|
||||||
|
return 0;
|
||||||
|
if ((v2.val.px.len & LEN_PLUS) && (v1.val.px.len < (v2.val.px.len & LEN_MASK)))
|
||||||
|
return 0;
|
||||||
|
if ((v2.val.px.len & LEN_RANGE) && ((v1.val.px.len < (0xff & (v2.val.px.len >> 16)))
|
||||||
|
|| (v1.val.px.len > (0xff & (v2.val.px.len >> 8)))))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return CMP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
val_in_range(struct f_val v1, struct f_val v2)
|
val_in_range(struct f_val v1, struct f_val v2)
|
||||||
{
|
{
|
||||||
if (((v1.type == T_INT) || (v1.type == T_IP)) && (v2.type == T_SET))
|
int res;
|
||||||
return !! find_tree(v2.val.t, v1);
|
|
||||||
|
res = val_simple_in_range(v1, v2);
|
||||||
|
|
||||||
|
if (res != CMP_ERROR)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (((v1.type == T_INT) || (v1.type == T_IP)) && (v2.type == T_SET)) {
|
||||||
|
struct f_tree *n;
|
||||||
|
n = find_tree(v2.val.t, v1);
|
||||||
|
if (!n)
|
||||||
|
return 0;
|
||||||
|
return !! (val_simple_in_range(v1, n->from)); /* We turn CMP_ERROR into compared ok, and that's fine */
|
||||||
|
}
|
||||||
return CMP_ERROR;
|
return CMP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +145,7 @@ val_print(struct f_val v)
|
||||||
case T_BOOL: PRINTF( v.val.i ? "TRUE" : "FALSE" ); break;
|
case T_BOOL: PRINTF( v.val.i ? "TRUE" : "FALSE" ); break;
|
||||||
case T_INT: PRINTF( "%d ", v.val.i ); break;
|
case T_INT: PRINTF( "%d ", v.val.i ); break;
|
||||||
case T_STRING: PRINTF( "%s", v.val.s ); break;
|
case T_STRING: PRINTF( "%s", v.val.s ); break;
|
||||||
case T_IP: PRINTF( "%I", v.val.ip ); break;
|
case T_IP: PRINTF( "%I", v.val.px.ip ); break;
|
||||||
case T_PREFIX: PRINTF( "%I/%d", v.val.px.ip, v.val.px.len ); break;
|
case T_PREFIX: PRINTF( "%I/%d", v.val.px.ip, v.val.px.len ); break;
|
||||||
case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
|
case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
|
||||||
case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
|
case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
|
||||||
|
@ -254,7 +291,7 @@ interpret(struct f_inst *what)
|
||||||
res.type = what->a1.i;
|
res.type = what->a1.i;
|
||||||
switch(res.type) {
|
switch(res.type) {
|
||||||
case T_IP:
|
case T_IP:
|
||||||
res.val.ip = * (ip_addr *) ((char *) rta + what->a2.i);
|
res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
|
||||||
break;
|
break;
|
||||||
case T_PREFIX: /* Warning: this works only for prefix of network */
|
case T_PREFIX: /* Warning: this works only for prefix of network */
|
||||||
{
|
{
|
||||||
|
@ -267,6 +304,9 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'ea': /* Access to extended attributes [hmm, but we need it read/write, do we?] */
|
||||||
|
bug( "Implement me" );
|
||||||
|
break;
|
||||||
case 'cp': /* Convert prefix to ... */
|
case 'cp': /* Convert prefix to ... */
|
||||||
ONEARG;
|
ONEARG;
|
||||||
if (v1.type != T_PREFIX)
|
if (v1.type != T_PREFIX)
|
||||||
|
@ -274,7 +314,7 @@ interpret(struct f_inst *what)
|
||||||
res.type = what->a2.i;
|
res.type = what->a2.i;
|
||||||
switch(res.type) {
|
switch(res.type) {
|
||||||
case T_INT: res.val.i = v1.val.px.len; break;
|
case T_INT: res.val.i = v1.val.px.len; break;
|
||||||
case T_IP: res.val.ip = v1.val.px.ip; break;
|
case T_IP: res.val.px.ip = v1.val.px.ip; break;
|
||||||
default: bug( "Unknown prefix to conversion\n" );
|
default: bug( "Unknown prefix to conversion\n" );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -32,17 +32,17 @@ struct prefix {
|
||||||
ip_addr ip;
|
ip_addr ip;
|
||||||
int len;
|
int len;
|
||||||
#define LEN_MASK 0xff
|
#define LEN_MASK 0xff
|
||||||
#define LEN_PLUS 0x10000
|
#define LEN_PLUS 0x1000000
|
||||||
#define LEN_MINUS 0x20000
|
#define LEN_MINUS 0x2000000
|
||||||
#define LEN_RANGE 0x40000
|
#define LEN_RANGE 0x4000000
|
||||||
/* If range then prefix must be in range (len >> 8 & 0xff, len & 0xff) */
|
/* If range then prefix must be in range (len >> 16 & 0xff, len >> 8 & 0xff) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct f_val {
|
struct f_val {
|
||||||
int type;
|
int type;
|
||||||
union {
|
union {
|
||||||
int i;
|
int i;
|
||||||
ip_addr ip;
|
/* ip_addr ip; Folded into prefix */
|
||||||
struct prefix px;
|
struct prefix px;
|
||||||
char *s;
|
char *s;
|
||||||
struct f_tree *t;
|
struct f_tree *t;
|
||||||
|
|
Loading…
Reference in a new issue