]> git.ipfire.org Git - thirdparty/bird.git/blame - filter/config.Y
Split inst->code into inst->code and inst->aux. Both are only 16 bit,
[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
f4536657 11 FIXME: write access to dynamic attributes.
346a12c2 12 FIXME: '! =' should not be permitted. Ze `!=' by nemelo byt totez jako `! =' Nadefinujes si pres %token novy token a do cf-lex.l pridas nove pravidlo, ktere jej rozpoznava. Napriklad != return NEQ;
c7b43f33 13 FIXME: write access to static attribute: Z rte ma byt read/write: pref, attrs (neprimo).
346a12c2 14
b9d70dc8
PM
15 */
16
17CF_HDR
18
19#include "nest/bird.h"
b9d70dc8
PM
20#include "lib/resource.h"
21#include "lib/socket.h"
22#include "lib/timer.h"
23#include "nest/protocol.h"
24#include "nest/iface.h"
25#include "nest/route.h"
cb8034f4 26#include <string.h>
b9d70dc8
PM
27
28CF_DECLS
29
d3dd620b 30CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST,
ba921648
PM
31 ACCEPT, REJECT, ERROR, QUITBIRD,
32 INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
7db7b7db 33 IF, THEN, ELSE, CASE,
23b1539b 34 TRUE, FALSE,
346a12c2 35 RTA, FROM, GW, NET, MASK, RIP_METRIC, RIP_TAG, SOURCE,
36bbfc70 36 LEN,
f4536657 37 DEFINED,
36bbfc70 38 IMPOSSIBLE,
fd54b602 39 FILTER)
b9d70dc8 40
f4536657 41%nonassoc THEN
4ed8718a 42%nonassoc ELSE
f4536657 43
4515bdba 44%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn any_dynamic
e0f2e42f 45%type <f> filter filter_body
4515bdba 46%type <i> type break_command pair
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 {
4515bdba
PM
106 $$ = $1;
107 $$->aux = (int) $3;
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
23b1539b 232constant:
c7b43f33
PM
233 CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; }
234 | NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; }
235 | TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; }
236 | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; }
237 | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
238 | pair { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR; $$->a2.i = $1; }
d3dd620b 239 | ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
2f702671 240 | prefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
c7b43f33
PM
241 | '[' set_items ']' { printf( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); printf( "ook\n" ); }
242 | ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
23b1539b
PM
243 ;
244
f4536657 245any_dynamic:
c7b43f33
PM
246 RIP_METRIC { $$ = f_new_inst(); $$->aux = T_INT; $$->a2.i = EA_RIP_METRIC;}
247 | RIP_TAG { $$ = f_new_inst(); $$->aux = T_INT; $$->a2.i = EA_RIP_TAG; }
f4536657
PM
248 ;
249
250
84c7e194 251term:
f4536657
PM
252 '(' term ')' { $$ = $2; }
253 | term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
2db3b288
PM
254 | term '=' term { $$ = f_new_inst(); $$->code = '=='; $$->a1.p = $1; $$->a2.p = $3; }
255 | term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->a1.p = $1; $$->a2.p = $4; }
256 | term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
257 | term '<' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $1; $$->a2.p = $4; }
258 | term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
259 | term '>' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $4; $$->a2.p = $1; }
38506f71 260 | term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
f4536657 261 | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = 'de'; $$->a1.p = $3; }
23b1539b 262
1183b6b2 263 | constant { $$ = $1; }
2575593e
PM
264 | SYM {
265 $$ = f_new_inst();
266 switch ($1->class) {
ba921648 267 case SYM_VARIABLE | T_INT:
d3dd620b
PM
268 case SYM_VARIABLE | T_PAIR:
269 case SYM_VARIABLE | T_PREFIX:
270 case SYM_VARIABLE | T_IP:
271 $$->code = 'C';
272 $$->a1.p = $1->aux2;
2575593e
PM
273 break;
274 default:
1183b6b2 275 cf_error("Can not use this class of symbol (%s,%x) as variable.", $1->name, $1->class );
2575593e
PM
276 }
277 }
4515bdba 278
346a12c2 279 | RTA '.' FROM { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, from); }
36bbfc70 280
346a12c2
PM
281 | RTA '.' GW { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); }
282 | RTA '.' NET { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_PREFIX; $$->a2.i = 0x12345678; }
283 | RTA '.' SOURCE { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, gw); }
6dc7a0cb 284
f4536657 285 | RTA '.' any_dynamic { $$ = $3; $$->code = 'ea'; }
36bbfc70 286
c7b43f33
PM
287 | term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->aux = T_IP; }
288 | term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->aux = T_INT; }
d3dd620b 289 | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = 'iM'; $$->a1.p = $1; $$->a2.p = $5; }
ba921648
PM
290 ;
291
292break_command:
293 QUITBIRD { $$ = F_QUITBIRD }
294 | ACCEPT { $$ = F_ACCEPT }
295 | REJECT { $$ = F_REJECT }
296 | ERROR { $$ = F_ERROR }
23b1539b 297 | PRINT { $$ = F_NOP }
d3dd620b 298 | PRINTN { $$ = F_NONL }
ba921648
PM
299 ;
300
23b1539b 301print_one:
2db3b288 302 term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
23b1539b
PM
303 ;
304
305print_list: /* EMPTY */ { $$ = NULL; }
306 | print_one print_list {
307 if ($1) {
308 $1->next = $2;
309 $$ = $1;
310 } else $$ = $2;
311 }
312 ;
313
6dc7a0cb 314var_listn: term {
d3dd620b
PM
315 $$ = f_new_inst();
316 $$->code = 's';
317 $$->a1.p = NULL;
318 $$->a2.p = $1;
319 $$->next = NULL;
320 }
6dc7a0cb 321 | term ',' var_listn {
6542ece9
PM
322 $$ = f_new_inst();
323 $$->code = 's';
324 $$->a1.p = NULL;
325 $$->a2.p = $1;
326 $$->next = $3;
327 }
328 ;
329
6dc7a0cb
PM
330var_list: /* EMPTY */ { $$ = NULL; }
331 | var_listn { $$ = $1; }
332 ;
333
23b1539b 334cmd:
49955645
MM
335 IF term THEN block {
336 $$ = f_new_inst();
337 $$->code = '?';
338 $$->a1.p = $2;
339 $$->a2.p = $4;
23b1539b 340 }
49955645
MM
341 | IF term THEN block ELSE block {
342 struct f_inst *i = f_new_inst();
343 i->code = '?';
344 i->a1.p = $2;
345 i->a2.p = $4;
23b1539b
PM
346 $$ = f_new_inst();
347 $$->code = '?';
49955645
MM
348 $$->a1.p = i;
349 $$->a2.p = $6;
23b1539b 350 }
ba921648 351 | SYM '=' term ';' {
84c7e194 352 $$ = f_new_inst();
b9d70dc8 353 printf( "Ook, we'll set value\n" );
ba921648
PM
354 if (($1->class & ~T_MASK) != SYM_VARIABLE)
355 cf_error( "You may only set variables, and this is %x.\n", $1->class );
23b1539b 356 $$->code = 's';
2db3b288
PM
357 $$->a1.p = $1;
358 $$->a2.p = $3;
b9d70dc8 359 }
c7b43f33
PM
360 | RTA '.' any_dynamic '=' term ';' {
361 $$ = $3;
362 $$->code = 'eS';
363
364 }
2db3b288 365 | break_command print_list ';' { $$ = f_new_inst(); $$->code = 'p,'; $$->a1.p = $2; $$->a2.i = $1; }
6542ece9
PM
366 | SYM '(' var_list ')' ';' {
367 struct symbol *sym;
368 struct f_inst *inst = $3;
369 if ($1->class != SYM_FUNCTION)
370 cf_error("You can not call something which is not function. Really.");
371 printf("You are calling function %s\n", $1->name);
372 $$ = f_new_inst();
373 $$->code = 'ca';
374 $$->a1.p = inst;
375 $$->a2.p = $1->aux2;
cb8034f4 376 sym = (void *) $1->aux;
6542ece9
PM
377 while (sym || inst) {
378 if (!sym || !inst)
379 cf_error("wrong number of arguments for function %s.", $1->name);
380 printf( "You should pass parameter called %s\n", sym->name);
381 inst->a1.p = sym;
cb8034f4 382 sym = (void *) sym->aux;
6542ece9
PM
383 inst = inst->next;
384 }
385 }
7db7b7db
PM
386 | CASE term '{' switch_body '}' {
387 $$ = f_new_inst();
41be4444 388 $$->code = 'SW';
7db7b7db 389 $$->a1.p = $2;
41be4444 390 $$->a2.p = build_tree( $4 );
7db7b7db 391 }
b9d70dc8
PM
392 ;
393
394CF_END