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