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