]>
Commit | Line | Data |
---|---|---|
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 | ||
15 | CF_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 | |
26 | CF_DECLS | |
27 | ||
d3dd620b | 28 | CF_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 | |
51 | CF_GRAMMAR | |
52 | ||
e0f2e42f MM |
53 | CF_ADDTO(conf, filter_def) |
54 | filter_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 |
63 | type: |
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 |
80 | one_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 */ |
96 | decls: /* 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 |
104 | declsn: one_decl { $$ = $1; } |
105 | | declsn ';' one_decl { | |
106 | $$ = $3; | |
cb8034f4 | 107 | $$->aux = (int) $1; |
6dc7a0cb PM |
108 | } |
109 | ; | |
110 | ||
111 | ||
e0f2e42f | 112 | filter_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 | ||
121 | filter: | |
122 | SYM { | |
123 | if ($1->class != SYM_FILTER) cf_error("No such filter"); | |
124 | $$ = $1->def; | |
125 | } | |
126 | | filter_body | |
127 | ; | |
128 | ||
ba921648 | 129 | function_params: |
6dc7a0cb PM |
130 | '(' declsn ')' { printf( "Have function parameters\n" ); $$=$2; } |
131 | | '(' ')' { $$=NULL; } | |
ba921648 | 132 | ; |
b9d70dc8 | 133 | |
ba921648 PM |
134 | function_body: |
135 | decls '{' cmds '}' { | |
136 | $$ = $3; | |
84c7e194 | 137 | } |
ba921648 PM |
138 | ; |
139 | ||
140 | CF_ADDTO(conf, function_def) | |
141 | function_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 | ||
156 | cmds: /* 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 | 167 | block: |
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 | */ | |
179 | pair: | |
180 | '(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; } | |
181 | ; | |
182 | ||
183 | /* | |
184 | * Complex types, their bison value is struct f_val | |
185 | */ | |
186 | prefix_s: | |
187 | IPA '/' NUM { $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; printf( "ook, we have prefix here\n" ); } | |
188 | ; | |
189 | ||
190 | prefix: | |
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 | ||
197 | ipa: | |
6dc7a0cb | 198 | IPA { $$.type = T_IP; $$.val.px.ip = $1; } |
d3dd620b PM |
199 | ; |
200 | ||
38506f71 | 201 | set_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 | ||
208 | set_item: | |
209 | set_atom { $$ = f_new_tree(); $$->from = $$->to = $1 } | |
210 | | set_atom '.' '.' set_atom { $$ = f_new_tree(); $$->from = $1; $$->to = $4; } | |
211 | ; | |
212 | ||
213 | set_items: | |
214 | set_item { $$ = $1; } | |
215 | | set_items ',' set_item { $$ = $3; $$->left = $1; } | |
216 | ; | |
217 | ||
41be4444 PM |
218 | switch_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 |
232 | enum_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 |
249 | enums: |
250 | enum_rts { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_ENUM_RTS; $$->a2.i = $1; } | |
251 | ; | |
252 | ||
23b1539b | 253 | constant: |
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 |
266 | any_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 | 272 | term: |
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 | ||
311 | break_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 | 320 | print_one: |
2db3b288 | 321 | term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; } |
23b1539b PM |
322 | ; |
323 | ||
324 | print_list: /* EMPTY */ { $$ = NULL; } | |
325 | | print_one print_list { | |
326 | if ($1) { | |
327 | $1->next = $2; | |
328 | $$ = $1; | |
329 | } else $$ = $2; | |
330 | } | |
331 | ; | |
332 | ||
6dc7a0cb | 333 | var_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 |
349 | var_list: /* EMPTY */ { $$ = NULL; } |
350 | | var_listn { $$ = $1; } | |
351 | ; | |
352 | ||
23b1539b | 353 | cmd: |
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 | ||
408 | CF_END |