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