]> git.ipfire.org Git - thirdparty/bird.git/blame - filter/config.Y
Untested IPv6 support added. I do not know if it compiles in IPV6 mode.
[thirdparty/bird.git] / filter / config.Y
CommitLineData
b9d70dc8
PM
1/*
2 * BIRD - filters
3 *
6542ece9 4 * Copyright 1998,1999 Pavel Machek
b9d70dc8
PM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
c9f8c1a8 7 *
720d911d 8 FIXME: prefix variables, make prefix.ip and prefix.length work
c9f8c1a8
PM
9 FIXME: define keyword
10 FIXME: case without { }'s
11 FIXME: allow px+, px- px^pair in prefix sets
12 FIXME: create ip.mask(x) function
13 FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
14 FIXME: create community lists
15 FIXME: access to dynamic attributes
720d911d
PM
16 FIXME: do not allow function call by callme(1,2,)
17 FIXME: pairs of integers: define compare
b9d70dc8
PM
18 */
19
20CF_HDR
21
22#include "nest/bird.h"
b9d70dc8
PM
23#include "lib/resource.h"
24#include "lib/socket.h"
25#include "lib/timer.h"
26#include "nest/protocol.h"
27#include "nest/iface.h"
28#include "nest/route.h"
29
30CF_DECLS
31
38506f71 32CF_KEYWORDS(FUNCTION, PRINT, CONST,
ba921648
PM
33 ACCEPT, REJECT, ERROR, QUITBIRD,
34 INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
7db7b7db 35 IF, THEN, ELSE, CASE,
23b1539b 36 TRUE, FALSE,
36bbfc70
PM
37 RTA, FROM, GW, NET,
38 LEN,
39 IMPOSSIBLE,
ba921648
PM
40 FILTER
41 )
b9d70dc8 42
7db7b7db 43%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list switch_body
e0f2e42f 44%type <f> filter filter_body
ba921648 45%type <i> type break_command
38506f71
PM
46%type <e> set_item set_items
47%type <v> set_atom
6542ece9 48%type <s> decls function_params
b9d70dc8
PM
49
50CF_GRAMMAR
51
e0f2e42f
MM
52CF_ADDTO(conf, filter_def)
53filter_def:
54 FILTER SYM filter_body {
4107df1d 55 cf_define_symbol($2, SYM_FILTER, $3);
e0f2e42f 56 $3->name = $2->name;
b9d70dc8
PM
57 printf( "We have new filter defined (%s)\n", $2->name )
58 }
59 ;
60
ba921648
PM
61type:
62 INT { $$ = T_INT; }
63 | BOOL { $$ = T_BOOL; }
64 | IP { $$ = T_IP; }
65 | PREFIX { $$ = T_PREFIX; }
66 | PAIR { $$ = T_PAIR; }
67 | STRING { $$ = T_STRING; }
68 | type SET {
69 switch ($1) {
70 default:
71 cf_error( "You can not create sets of this type\n" );
72 case T_INT: case T_IP: case T_PREFIX: case T_PAIR:
73 }
74 $$ = $1 | T_SET;
75 }
76 ;
77
6542ece9 78decls: /* EMPTY */ { $$ = NULL; }
ba921648 79 | type SYM ';' decls {
4107df1d 80 cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
ba921648 81 printf( "New variable %s type %x\n", $2->name, $1 );
6542ece9
PM
82 $2->aux = $4;
83 $$=$2;
ba921648
PM
84 }
85 ;
86
e0f2e42f 87filter_body:
ba921648 88 function_body {
e0f2e42f
MM
89 struct filter *f = cfg_alloc(sizeof(struct filter));
90 f->name = NULL;
ba921648 91 f->root = $1;
e0f2e42f
MM
92 $$ = f;
93 }
94 ;
95
96filter:
97 SYM {
98 if ($1->class != SYM_FILTER) cf_error("No such filter");
99 $$ = $1->def;
100 }
101 | filter_body
102 ;
103
ba921648 104function_params:
6542ece9 105 '(' decls ')' { printf( "Have function parameters\n" ); $$=$2; }
ba921648 106 ;
b9d70dc8 107
ba921648
PM
108function_body:
109 decls '{' cmds '}' {
110 $$ = $3;
84c7e194 111 }
ba921648
PM
112 ;
113
114CF_ADDTO(conf, function_def)
115function_def:
116 FUNCTION SYM function_params function_body {
117 extern struct f_inst *startup_func;
4107df1d 118 cf_define_symbol($2, SYM_FUNCTION, $4);
ba921648
PM
119 if (!strcasecmp($2->name, "startup"))
120 startup_func = $4;
6542ece9
PM
121 $2->aux = $3;
122 $2->aux2 = $4;
ba921648
PM
123 printf("Hmm, we've got one function here - %s\n", $2->name);
124 }
125 ;
126
127/* Programs */
128
129cmds: /* EMPTY */ { $$ = NULL; }
130 | cmd cmds {
84c7e194 131 if ($1) {
7db7b7db
PM
132 if ($1->next)
133 bug("Command has next already set\n");
ba921648 134 $1->next = $2;
84c7e194 135 $$ = $1;
ba921648 136 } else $$ = $2;
84c7e194
PM
137 }
138 ;
139
2575593e 140block:
ba921648 141 cmd {
2575593e
PM
142 $$=$1;
143 }
144 | '{' cmds '}' {
145 $$=$2;
146 }
147 ;
148
38506f71
PM
149set_atom:
150 NUM { $$.type = T_INT; $$.val.i = $1; }
151 | IPA { $$.type = T_IP; $$.val.ip = $1; }
720d911d 152
38506f71
PM
153 ;
154
155set_item:
156 set_atom { $$ = f_new_tree(); $$->from = $$->to = $1 }
157 | set_atom '.' '.' set_atom { $$ = f_new_tree(); $$->from = $1; $$->to = $4; }
158 ;
159
160set_items:
161 set_item { $$ = $1; }
162 | set_items ',' set_item { $$ = $3; $$->left = $1; }
163 ;
164
23b1539b 165constant:
2db3b288
PM
166 CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; }
167 | NUM { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $1; }
168 | TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 1; }
169 | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 0; }
38506f71 170 | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_STRING; $$->a2.p = $1; }
720d911d 171 | '(' NUM ',' NUM ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR; $$->a2.i = $2 << 16 | $4; }
38506f71 172 | IPA { struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_IP; val->val.ip = $1; }
720d911d 173 | IPA '/' NUM { struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_PREFIX; val->val.px.ip = $1; val->val.px.len = $3; printf( "ook, we have prefix here\n" ); }
38506f71 174 | '[' 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" ); }
23b1539b
PM
175 ;
176
84c7e194 177term:
2db3b288 178 term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
2db3b288
PM
179 | term '=' term { $$ = f_new_inst(); $$->code = '=='; $$->a1.p = $1; $$->a2.p = $3; }
180 | term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->a1.p = $1; $$->a2.p = $4; }
181 | term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
182 | term '<' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $1; $$->a2.p = $4; }
183 | term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
184 | term '>' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $4; $$->a2.p = $1; }
38506f71 185 | term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
23b1539b 186
2575593e
PM
187 | SYM {
188 $$ = f_new_inst();
189 switch ($1->class) {
ba921648 190 case SYM_VARIABLE | T_INT:
2575593e 191 $$->code = 'i';
2db3b288
PM
192 $$->a1.i = T_INT;
193 $$->a2.p = &($1->aux);
2575593e
PM
194 break;
195 default:
6542ece9 196 cf_error("Can not use this class of symbol as variable." );
2575593e
PM
197 }
198 }
23b1539b 199 | constant { $$ = $1; }
36bbfc70
PM
200 | RTA '.' FROM { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, from); }
201
202 | RTA '.' GW { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); }
203 | RTA '.' NET { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_PREFIX; $$->a2.i = 0x12345678; }
204
205 | term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_IP; }
206 | term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_INT; }
ba921648
PM
207 ;
208
209break_command:
210 QUITBIRD { $$ = F_QUITBIRD }
211 | ACCEPT { $$ = F_ACCEPT }
212 | REJECT { $$ = F_REJECT }
213 | ERROR { $$ = F_ERROR }
23b1539b 214 | PRINT { $$ = F_NOP }
ba921648
PM
215 ;
216
23b1539b 217ifthen:
ba921648 218 IF term THEN block {
b7005824 219 $$ = f_new_inst();
ba921648 220 $$->code = '?';
2db3b288
PM
221 $$->a1.p = $2;
222 $$->a2.p = $4;
b7005824 223 }
23b1539b
PM
224 ;
225
226print_one:
2db3b288 227 term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
23b1539b
PM
228 ;
229
230print_list: /* EMPTY */ { $$ = NULL; }
231 | print_one print_list {
232 if ($1) {
233 $1->next = $2;
234 $$ = $1;
235 } else $$ = $2;
236 }
237 ;
238
6542ece9
PM
239var_list: /* EMPTY */ { $$ = NULL; }
240 | term ',' var_list {
241 $$ = f_new_inst();
242 $$->code = 's';
243 $$->a1.p = NULL;
244 $$->a2.p = $1;
245 $$->next = $3;
246 }
247 ;
248
7db7b7db
PM
249switch_body: /* EMPTY */ { $$ = NULL; }
250 | term ':' block switch_body {
251 $$ = f_new_inst();
252 $$->code = 'of';
253 $$->a1.p = $1;
254 $$->a2.p = $3;
255 $$->next = $4;
256 }
257 | ELSE ':' block {
258 $$ = f_new_inst();
259 $$->code = 'el';
260 $$->a1.p = NULL;
261 $$->a2.p = $3;
262 }
263 ;
264
23b1539b
PM
265cmd:
266 ifthen {
267 $$ = $1;
268 }
269 /* FIXME: this leads to shift/reduce conflict. */
270 | ifthen ELSE block {
271 $$ = f_new_inst();
272 $$->code = '?';
2db3b288
PM
273 $$->a1.p = $1;
274 $$->a2.p = $3;
23b1539b 275 }
ba921648 276 | SYM '=' term ';' {
84c7e194 277 $$ = f_new_inst();
b9d70dc8 278 printf( "Ook, we'll set value\n" );
ba921648
PM
279 if (($1->class & ~T_MASK) != SYM_VARIABLE)
280 cf_error( "You may only set variables, and this is %x.\n", $1->class );
23b1539b 281 $$->code = 's';
2db3b288
PM
282 $$->a1.p = $1;
283 $$->a2.p = $3;
b9d70dc8 284 }
2db3b288 285 | break_command print_list ';' { $$ = f_new_inst(); $$->code = 'p,'; $$->a1.p = $2; $$->a2.i = $1; }
6542ece9
PM
286 | SYM '(' var_list ')' ';' {
287 struct symbol *sym;
288 struct f_inst *inst = $3;
289 if ($1->class != SYM_FUNCTION)
290 cf_error("You can not call something which is not function. Really.");
291 printf("You are calling function %s\n", $1->name);
292 $$ = f_new_inst();
293 $$->code = 'ca';
294 $$->a1.p = inst;
295 $$->a2.p = $1->aux2;
296 sym = $1->aux;
297 while (sym || inst) {
298 if (!sym || !inst)
299 cf_error("wrong number of arguments for function %s.", $1->name);
300 printf( "You should pass parameter called %s\n", sym->name);
301 inst->a1.p = sym;
302 sym = sym->aux;
303 inst = inst->next;
304 }
305 }
7db7b7db
PM
306 | CASE term '{' switch_body '}' {
307 $$ = f_new_inst();
308 $$->code = 'sw';
309 $$->a1.p = $2;
310 $$->a2.p = $4;
311 }
b9d70dc8
PM
312 ;
313
314CF_END