]> git.ipfire.org Git - thirdparty/bird.git/blame - filter/config.Y
Added LSA hashing table (parts of code stolen from rt-fib.c, but
[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 *
c9f8c1a8 8 FIXME: define keyword
c9f8c1a8
PM
9 FIXME: create ip.mask(x) function
10 FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
11 FIXME: create community lists
91447965
PM
12 FIXME: enumerational types
13 FIXME: defined() keyword
b9d70dc8
PM
14 */
15
16CF_HDR
17
18#include "nest/bird.h"
b9d70dc8
PM
19#include "lib/resource.h"
20#include "lib/socket.h"
21#include "lib/timer.h"
22#include "nest/protocol.h"
23#include "nest/iface.h"
24#include "nest/route.h"
25
26CF_DECLS
27
d3dd620b 28CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST,
ba921648
PM
29 ACCEPT, REJECT, ERROR, QUITBIRD,
30 INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
7db7b7db 31 IF, THEN, ELSE, CASE,
23b1539b 32 TRUE, FALSE,
6dc7a0cb 33 RTA, FROM, GW, NET, MASK, RIP_METRIC, RIP_TAG,
36bbfc70
PM
34 LEN,
35 IMPOSSIBLE,
ba921648
PM
36 FILTER
37 )
b9d70dc8 38
6dc7a0cb 39%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list var_listn
e0f2e42f 40%type <f> filter filter_body
d3dd620b 41%type <i> type break_command pair
41be4444 42%type <e> set_item set_items switch_body
d3dd620b 43%type <v> set_atom prefix prefix_s ipa
6dc7a0cb 44%type <s> decls declsn one_decl function_params
b9d70dc8
PM
45
46CF_GRAMMAR
47
e0f2e42f
MM
48CF_ADDTO(conf, filter_def)
49filter_def:
ae3e1af2
PM
50 FILTER SYM { cf_push_scope( $2->name ); } filter_body {
51 cf_define_symbol($2, SYM_FILTER, $4);
52 $4->name = $2->name;
53 printf( "We have new filter defined (%s)\n", $2->name );
54 cf_pop_scope();
b9d70dc8
PM
55 }
56 ;
57
ba921648
PM
58type:
59 INT { $$ = T_INT; }
60 | BOOL { $$ = T_BOOL; }
61 | IP { $$ = T_IP; }
62 | PREFIX { $$ = T_PREFIX; }
63 | PAIR { $$ = T_PAIR; }
64 | STRING { $$ = T_STRING; }
65 | type SET {
66 switch ($1) {
67 default:
68 cf_error( "You can not create sets of this type\n" );
69 case T_INT: case T_IP: case T_PREFIX: case T_PAIR:
70 }
71 $$ = $1 | T_SET;
72 }
73 ;
74
6dc7a0cb
PM
75one_decl:
76 type SYM {
4107df1d 77 cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
ba921648 78 printf( "New variable %s type %x\n", $2->name, $1 );
6dc7a0cb 79 $2->aux = NULL;
d3dd620b
PM
80 {
81 struct f_val * val;
82 val = cfg_alloc(sizeof(struct f_val));
83 val->type = $1;
84 $2->aux2 = val;
85 }
6542ece9 86 $$=$2;
ba921648
PM
87 }
88 ;
89
6dc7a0cb
PM
90/* Decls with ';' at the end */
91decls: /* EMPTY */ { $$ = NULL; }
92 | one_decl ';' decls {
93 $$ = $1;
94 $$->aux = $3;
95 }
96 ;
97
3c989eb4 98/* Declarations that have no ';' at the end. */
6dc7a0cb
PM
99declsn: one_decl { $$ = $1; }
100 | declsn ';' one_decl {
101 $$ = $3;
102 $$->aux = $1;
103 }
104 ;
105
106
e0f2e42f 107filter_body:
ba921648 108 function_body {
e0f2e42f
MM
109 struct filter *f = cfg_alloc(sizeof(struct filter));
110 f->name = NULL;
ba921648 111 f->root = $1;
e0f2e42f
MM
112 $$ = f;
113 }
114 ;
115
116filter:
117 SYM {
118 if ($1->class != SYM_FILTER) cf_error("No such filter");
119 $$ = $1->def;
120 }
121 | filter_body
122 ;
123
ba921648 124function_params:
6dc7a0cb
PM
125 '(' declsn ')' { printf( "Have function parameters\n" ); $$=$2; }
126 | '(' ')' { $$=NULL; }
ba921648 127 ;
b9d70dc8 128
ba921648
PM
129function_body:
130 decls '{' cmds '}' {
131 $$ = $3;
84c7e194 132 }
ba921648
PM
133 ;
134
135CF_ADDTO(conf, function_def)
136function_def:
ae3e1af2 137 FUNCTION SYM { printf( "Begining of function %s\n", $2->name ); cf_push_scope($2->name); } function_params function_body {
ba921648 138 extern struct f_inst *startup_func;
ae3e1af2 139 cf_define_symbol($2, SYM_FUNCTION, $5);
ba921648 140 if (!strcasecmp($2->name, "startup"))
ae3e1af2
PM
141 startup_func = $5;
142 $2->aux = $4;
143 $2->aux2 = $5;
ba921648 144 printf("Hmm, we've got one function here - %s\n", $2->name);
ae3e1af2 145 cf_pop_scope();
ba921648
PM
146 }
147 ;
148
149/* Programs */
150
151cmds: /* EMPTY */ { $$ = NULL; }
152 | cmd cmds {
84c7e194 153 if ($1) {
7db7b7db
PM
154 if ($1->next)
155 bug("Command has next already set\n");
ba921648 156 $1->next = $2;
84c7e194 157 $$ = $1;
ba921648 158 } else $$ = $2;
84c7e194
PM
159 }
160 ;
161
2575593e 162block:
ba921648 163 cmd {
2575593e
PM
164 $$=$1;
165 }
166 | '{' cmds '}' {
167 $$=$2;
168 }
169 ;
170
d3dd620b
PM
171/*
172 * Simple types, their bison value is int
173 */
174pair:
175 '(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; }
176 ;
177
178/*
179 * Complex types, their bison value is struct f_val
180 */
181prefix_s:
182 IPA '/' NUM { $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; printf( "ook, we have prefix here\n" ); }
183 ;
184
185prefix:
186 prefix_s { $$ = $1; }
187 | prefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
188 | prefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
6dc7a0cb 189 | prefix_s '{' NUM ',' NUM '}' { $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); }
d3dd620b
PM
190 ;
191
192ipa:
6dc7a0cb 193 IPA { $$.type = T_IP; $$.val.px.ip = $1; }
d3dd620b
PM
194 ;
195
38506f71 196set_atom:
d3dd620b
PM
197 NUM { $$.type = T_INT; $$.val.i = $1; }
198 | pair { $$.type = T_PAIR; $$.val.i = $1; }
199 | ipa { $$ = $1; }
200 | prefix { $$ = $1; }
38506f71
PM
201 ;
202
203set_item:
204 set_atom { $$ = f_new_tree(); $$->from = $$->to = $1 }
205 | set_atom '.' '.' set_atom { $$ = f_new_tree(); $$->from = $1; $$->to = $4; }
206 ;
207
208set_items:
209 set_item { $$ = $1; }
210 | set_items ',' set_item { $$ = $3; $$->left = $1; }
211 ;
212
41be4444
PM
213/* 2 shift/reduce conflicts here. Curable by replacing cmds with block which breaks syntax */
214switch_body: /* EMPTY */ { $$ = NULL; }
215 | set_item ':' cmds switch_body {
216 $$ = $1;
217 $$->data = $3;
218 $$->left = $4;
219 }
220 | ELSE ':' cmds {
221 $$ = f_new_tree();
222 $$->from.type = T_VOID;
223 $$->to.type = T_VOID;
224 $$->data = $3;
225 }
226 ;
d3dd620b 227
23b1539b 228constant:
2db3b288
PM
229 CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; }
230 | NUM { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $1; }
231 | TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 1; }
232 | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 0; }
38506f71 233 | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_STRING; $$->a2.p = $1; }
d3dd620b
PM
234 | pair { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR; $$->a2.i = $1; }
235 | ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
6dc7a0cb 236 | prefix {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
38506f71 237 | '[' 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
238 ;
239
84c7e194 240term:
2db3b288 241 term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
2db3b288
PM
242 | term '=' term { $$ = f_new_inst(); $$->code = '=='; $$->a1.p = $1; $$->a2.p = $3; }
243 | term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->a1.p = $1; $$->a2.p = $4; }
244 | term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
245 | term '<' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $1; $$->a2.p = $4; }
246 | term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
247 | term '>' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $4; $$->a2.p = $1; }
38506f71 248 | term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
23b1539b 249
2575593e
PM
250 | SYM {
251 $$ = f_new_inst();
252 switch ($1->class) {
ba921648 253 case SYM_VARIABLE | T_INT:
d3dd620b
PM
254 case SYM_VARIABLE | T_PAIR:
255 case SYM_VARIABLE | T_PREFIX:
256 case SYM_VARIABLE | T_IP:
257 $$->code = 'C';
258 $$->a1.p = $1->aux2;
2575593e
PM
259 break;
260 default:
6542ece9 261 cf_error("Can not use this class of symbol as variable." );
2575593e
PM
262 }
263 }
23b1539b 264 | constant { $$ = $1; }
36bbfc70
PM
265 | RTA '.' FROM { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, from); }
266
267 | RTA '.' GW { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); }
6dc7a0cb
PM
268 | RTA '.' NET { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_PREFIX; $$->a2.i = 0x12345678; }
269
270 | RTA '.' RIP_METRIC { $$ = f_new_inst(); $$->code = 'ea'; $$->a1.i = T_INT; $$->a2.i = EA_RIP_METRIC; }
36bbfc70
PM
271
272 | term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_IP; }
273 | term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_INT; }
d3dd620b 274 | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = 'iM'; $$->a1.p = $1; $$->a2.p = $5; }
ba921648
PM
275 ;
276
277break_command:
278 QUITBIRD { $$ = F_QUITBIRD }
279 | ACCEPT { $$ = F_ACCEPT }
280 | REJECT { $$ = F_REJECT }
281 | ERROR { $$ = F_ERROR }
23b1539b 282 | PRINT { $$ = F_NOP }
d3dd620b 283 | PRINTN { $$ = F_NONL }
ba921648
PM
284 ;
285
23b1539b 286ifthen:
ba921648 287 IF term THEN block {
b7005824 288 $$ = f_new_inst();
ba921648 289 $$->code = '?';
2db3b288
PM
290 $$->a1.p = $2;
291 $$->a2.p = $4;
b7005824 292 }
23b1539b
PM
293 ;
294
295print_one:
2db3b288 296 term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
23b1539b
PM
297 ;
298
299print_list: /* EMPTY */ { $$ = NULL; }
300 | print_one print_list {
301 if ($1) {
302 $1->next = $2;
303 $$ = $1;
304 } else $$ = $2;
305 }
306 ;
307
6dc7a0cb 308var_listn: term {
d3dd620b
PM
309 $$ = f_new_inst();
310 $$->code = 's';
311 $$->a1.p = NULL;
312 $$->a2.p = $1;
313 $$->next = NULL;
314 }
6dc7a0cb 315 | term ',' var_listn {
6542ece9
PM
316 $$ = f_new_inst();
317 $$->code = 's';
318 $$->a1.p = NULL;
319 $$->a2.p = $1;
320 $$->next = $3;
321 }
322 ;
323
6dc7a0cb
PM
324var_list: /* EMPTY */ { $$ = NULL; }
325 | var_listn { $$ = $1; }
326 ;
327
23b1539b
PM
328cmd:
329 ifthen {
330 $$ = $1;
331 }
332 /* FIXME: this leads to shift/reduce conflict. */
333 | ifthen ELSE block {
334 $$ = f_new_inst();
335 $$->code = '?';
2db3b288
PM
336 $$->a1.p = $1;
337 $$->a2.p = $3;
23b1539b 338 }
ba921648 339 | SYM '=' term ';' {
84c7e194 340 $$ = f_new_inst();
b9d70dc8 341 printf( "Ook, we'll set value\n" );
ba921648
PM
342 if (($1->class & ~T_MASK) != SYM_VARIABLE)
343 cf_error( "You may only set variables, and this is %x.\n", $1->class );
23b1539b 344 $$->code = 's';
2db3b288
PM
345 $$->a1.p = $1;
346 $$->a2.p = $3;
b9d70dc8 347 }
2db3b288 348 | break_command print_list ';' { $$ = f_new_inst(); $$->code = 'p,'; $$->a1.p = $2; $$->a2.i = $1; }
6542ece9
PM
349 | SYM '(' var_list ')' ';' {
350 struct symbol *sym;
351 struct f_inst *inst = $3;
352 if ($1->class != SYM_FUNCTION)
353 cf_error("You can not call something which is not function. Really.");
354 printf("You are calling function %s\n", $1->name);
355 $$ = f_new_inst();
356 $$->code = 'ca';
357 $$->a1.p = inst;
358 $$->a2.p = $1->aux2;
359 sym = $1->aux;
360 while (sym || inst) {
361 if (!sym || !inst)
362 cf_error("wrong number of arguments for function %s.", $1->name);
363 printf( "You should pass parameter called %s\n", sym->name);
364 inst->a1.p = sym;
365 sym = sym->aux;
366 inst = inst->next;
367 }
368 }
7db7b7db
PM
369 | CASE term '{' switch_body '}' {
370 $$ = f_new_inst();
41be4444 371 $$->code = 'SW';
7db7b7db 372 $$->a1.p = $2;
41be4444 373 $$->a2.p = build_tree( $4 );
7db7b7db 374 }
b9d70dc8
PM
375 ;
376
377CF_END