Statistics
| Branch: | Revision:

iof-bird-daemon / filter / config.Y @ 2f702671

History | View | Annotate | Download (9.72 KB)

1
/*
2
 *	BIRD - filters
3
 *
4
 *	Copyright 1998,1999 Pavel Machek
5
 *
6
 *	Can be freely distributed and used under the terms of the GNU GPL.
7
 *
8
	FIXME (nonurgent): define keyword
9
	FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
10
	FIXME: create community lists
11
	FIXME: enumerational types
12
	FIXME: write access to dynamic attributes.
13
 */
14

    
15
CF_HDR
16

    
17
#include "nest/bird.h"
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"
24

    
25
CF_DECLS
26

    
27
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST,
28
	ACCEPT, REJECT, ERROR, QUITBIRD,
29
	INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
30
	IF, THEN, ELSE, CASE,
31
	TRUE, FALSE,
32
	RTA, FROM, GW, NET, MASK, RIP_METRIC, RIP_TAG,
33
	LEN,
34
	DEFINED,
35
	IMPOSSIBLE,
36
	FILTER
37
	)
38

    
39
%nonassoc ELSE
40
%nonassoc THEN
41

    
42
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn any_dynamic
43
%type <f> filter filter_body
44
%type <i> type break_command pair
45
%type <e> set_item set_items switch_body
46
%type <v> set_atom prefix prefix_s ipa
47
%type <s> decls declsn one_decl function_params 
48

    
49
CF_GRAMMAR
50

    
51
CF_ADDTO(conf, filter_def)
52
filter_def:
53
   FILTER SYM { cf_push_scope( $2->name ); } filter_body {
54
     cf_define_symbol($2, SYM_FILTER, $4);
55
     $4->name = $2->name;
56
     printf( "We have new filter defined (%s)\n", $2->name );
57
     cf_pop_scope();
58
   }
59
 ;
60

    
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

    
78
one_decl:
79
   type SYM {
80
     cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
81
     printf( "New variable %s type %x\n", $2->name, $1 );
82
     $2->aux = NULL;
83
     {
84
       struct f_val * val; 
85
       val = cfg_alloc(sizeof(struct f_val)); 
86
       val->type = $1; 
87
       $2->aux2 = val;
88
     }
89
     $$=$2;
90
   }
91
 ;
92

    
93
/* Decls with ';' at the end */
94
decls: /* EMPTY */ { $$ = NULL; }
95
 | one_decl ';' decls {
96
     $$ = $1;
97
     $$->aux = $3;
98
   }
99
 ;
100

    
101
/* Declarations that have no ';' at the end. */
102
declsn: one_decl { $$ = $1; }
103
 | declsn ';' one_decl {
104
     $$ = $3;
105
     $$->aux = $1;
106
   }
107
 ;
108

    
109

    
110
filter_body:
111
   function_body {
112
     struct filter *f = cfg_alloc(sizeof(struct filter));
113
     f->name = NULL;
114
     f->root = $1;
115
     $$ = f;
116
   }
117
 ;
118

    
119
filter:
120
   SYM {
121
     if ($1->class != SYM_FILTER) cf_error("No such filter");
122
     $$ = $1->def;
123
   }
124
 | filter_body
125
 ;
126

    
127
function_params:
128
   '(' declsn ')' { printf( "Have function parameters\n" ); $$=$2; }
129
 | '(' ')' { $$=NULL; }
130
 ;
131

    
132
function_body:
133
   decls '{' cmds '}' {
134
     $$ = $3;
135
   }
136
 ;
137

    
138
CF_ADDTO(conf, function_def)
139
function_def:
140
   FUNCTION SYM { printf( "Begining of function %s\n", $2->name ); cf_push_scope($2->name); } function_params function_body {
141
     extern struct f_inst *startup_func;
142
     cf_define_symbol($2, SYM_FUNCTION, $5);
143
     if (!strcasecmp($2->name, "startup"))
144
	startup_func = $5;
145
     $2->aux = $4;
146
     $2->aux2 = $5;
147
     printf("Hmm, we've got one function here - %s\n", $2->name); 
148
     cf_pop_scope();
149
   }
150
 ;
151

    
152
/* Programs */
153

    
154
cmds: /* EMPTY */ { $$ = NULL; }
155
 | cmd cmds {
156
     if ($1) {
157
       if ($1->next)
158
	 bug("Command has next already set\n");
159
       $1->next = $2;
160
       $$ = $1;
161
     } else $$ = $2;
162
   }
163
 ;
164

    
165
block:
166
   cmd {
167
     $$=$1;
168
   }
169
 | '{' cmds '}' {
170
     $$=$2;
171
   }
172
 ;
173

    
174
/*
175
 * Simple types, their bison value is int
176
 */
177
pair:
178
   '(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; }
179
 ;
180

    
181
/*
182
 * Complex types, their bison value is struct f_val
183
 */
184
prefix_s:
185
   IPA '/' NUM { $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; printf( "ook, we have prefix here\n" ); }
186
 ;
187

    
188
prefix:
189
   prefix_s { $$ = $1; }
190
 | prefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
191
 | prefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
192
 | prefix_s '{' NUM ',' NUM '}' { $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); }
193
 ;
194

    
195
ipa:
196
   IPA  { $$.type = T_IP; $$.val.px.ip = $1; }
197
 ;
198

    
199
set_atom:
200
   NUM  { $$.type = T_INT; $$.val.i = $1; }
201
 | pair { $$.type = T_PAIR; $$.val.i = $1; }
202
 | ipa  { $$ = $1; }
203
 | prefix { $$ = $1; }
204
 ; 
205

    
206
set_item:
207
   set_atom { $$ = f_new_tree(); $$->from = $$->to = $1 }
208
 | set_atom '.' '.' set_atom { $$ = f_new_tree(); $$->from = $1; $$->to = $4; }
209
 ;
210

    
211
set_items:
212
   set_item { $$ = $1; }
213
 | set_items ',' set_item { $$ = $3; $$->left = $1; }
214
 ;
215

    
216
switch_body: /* EMPTY */ { $$ = NULL; }
217
 | set_item ':' cmds switch_body {
218
     $$ = $1;
219
     $$->data = $3;
220
     $$->left = $4;
221
   }
222
 | ELSE ':' cmds {
223
     $$ = f_new_tree(); 
224
     $$->from.type = T_VOID; 
225
     $$->to.type = T_VOID;
226
     $$->data = $3;
227
   }
228
 ;
229

    
230
constant:
231
   CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; }
232
 | NUM    { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT;  $$->a2.i = $1; }
233
 | TRUE   { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 1;  }
234
 | FALSE  { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 0;  }
235
 | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_STRING; $$->a2.p = $1; }
236
 | pair   { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR;  $$->a2.i = $1; }
237
 | ipa	   { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
238
 | prefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
239
 | '[' 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" ); }
240
 ;
241

    
242
any_dynamic:
243
   RIP_METRIC { $$ = f_new_inst(); $$->a1.i = T_INT; $$->a2.i = EA_RIP_METRIC;}
244
 | RIP_TAG    { $$ = f_new_inst(); $$->a1.i = T_INT; $$->a2.i = EA_RIP_TAG; }
245
 ;
246

    
247

    
248
term:
249
   '(' term ')'      { $$ = $2; }
250
 | term '+' term     { $$ = f_new_inst(); $$->code = '+';  $$->a1.p = $1; $$->a2.p = $3; }
251
 | term '=' term     { $$ = f_new_inst(); $$->code = '=='; $$->a1.p = $1; $$->a2.p = $3; }
252
 | term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->a1.p = $1; $$->a2.p = $4; }
253
 | term '<' term     { $$ = f_new_inst(); $$->code = '<';  $$->a1.p = $1; $$->a2.p = $3; }
254
 | term '<' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $1; $$->a2.p = $4; }
255
 | term '>' term     { $$ = f_new_inst(); $$->code = '<';  $$->a1.p = $3; $$->a2.p = $1; }
256
 | term '>' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $4; $$->a2.p = $1; }
257
 | term '~' term     { $$ = f_new_inst(); $$->code = '~';  $$->a1.p = $1; $$->a2.p = $3; }
258
 | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = 'de';  $$->a1.p = $3; }
259

    
260
 | SYM {
261
     $$ = f_new_inst();
262
     switch ($1->class) {
263
       case SYM_VARIABLE | T_INT:
264
       case SYM_VARIABLE | T_PAIR:
265
       case SYM_VARIABLE | T_PREFIX:
266
       case SYM_VARIABLE | T_IP:
267
	 $$->code = 'C';
268
	 $$->a1.p = $1->aux2;
269
	 break;
270
       default:
271
	 cf_error("Can not use this class of symbol as variable." );
272
     }
273
   }
274
 | constant { $$ = $1; }
275
 | RTA '.' FROM { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, from); }
276

    
277
 | RTA '.' GW { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); }
278
 | RTA '.' NET { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_PREFIX; $$->a2.i = 0x12345678; }
279

    
280
 | RTA '.' any_dynamic { $$ = $3; $$->code = 'ea'; }
281

    
282
 | term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_IP; }
283
 | term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_INT; }
284
 | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = 'iM'; $$->a1.p = $1; $$->a2.p = $5; }
285
 ;
286

    
287
break_command:
288
   QUITBIRD { $$ = F_QUITBIRD }
289
 | ACCEPT { $$ = F_ACCEPT }
290
 | REJECT { $$ = F_REJECT }
291
 | ERROR { $$ = F_ERROR }
292
 | PRINT { $$ = F_NOP }
293
 | PRINTN { $$ = F_NONL }
294
 ;
295

    
296
print_one:
297
   term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
298
 ;
299

    
300
print_list: /* EMPTY */ { $$ = NULL; }
301
 | print_one print_list {
302
     if ($1) {
303
       $1->next = $2;
304
       $$ = $1;
305
     } else $$ = $2;
306
   }
307
 ;
308

    
309
var_listn: term { 
310
     $$ = f_new_inst();
311
     $$->code = 's';
312
     $$->a1.p = NULL;
313
     $$->a2.p = $1;
314
     $$->next = NULL;
315
   }
316
 | term ',' var_listn {
317
     $$ = f_new_inst();
318
     $$->code = 's';
319
     $$->a1.p = NULL;
320
     $$->a2.p = $1;
321
     $$->next = $3;
322
   }
323
 ;
324

    
325
var_list: /* EMPTY */ { $$ = NULL; }
326
 | var_listn { $$ = $1; }
327
 ;
328

    
329
cmd:
330
   IF term THEN block {
331
     $$ = f_new_inst();
332
     $$->code = '?';
333
     $$->a1.p = $2;
334
     $$->a2.p = $4;
335
   }
336
 | IF term THEN block ELSE block {
337
     struct f_inst *i = f_new_inst();
338
     i->code = '?';
339
     i->a1.p = $2;
340
     i->a2.p = $4;
341
     $$ = f_new_inst();
342
     $$->code = '?';
343
     $$->a1.p = i;
344
     $$->a2.p = $6;
345
   }
346
 | SYM '=' term ';' {
347
     $$ = f_new_inst();
348
     printf( "Ook, we'll set value\n" );
349
     if (($1->class & ~T_MASK) != SYM_VARIABLE)
350
       cf_error( "You may only set variables, and this is %x.\n", $1->class );
351
     $$->code = 's';
352
     $$->a1.p = $1;
353
     $$->a2.p = $3;
354
   }
355
 | break_command print_list ';' { $$ = f_new_inst(); $$->code = 'p,'; $$->a1.p = $2; $$->a2.i = $1; }
356
 | SYM '(' var_list ')' ';' {
357
     struct symbol *sym;
358
     struct f_inst *inst = $3;
359
     if ($1->class != SYM_FUNCTION)
360
       cf_error("You can not call something which is not function. Really.");
361
     printf("You are calling function %s\n", $1->name);
362
     $$ = f_new_inst();
363
     $$->code = 'ca';
364
     $$->a1.p = inst;
365
     $$->a2.p = $1->aux2;
366
     sym = $1->aux;
367
     while (sym || inst) {
368
       if (!sym || !inst)
369
	 cf_error("wrong number of arguments for function %s.", $1->name);
370
       printf( "You should pass parameter called %s\n", sym->name);
371
       inst->a1.p = sym;
372
       sym = sym->aux;
373
       inst = inst->next;
374
     }
375
   }
376
 | CASE term '{' switch_body '}' {
377
      $$ = f_new_inst();
378
      $$->code = 'SW';
379
      $$->a1.p = $2;
380
      $$->a2.p = build_tree( $4 );
381
   }
382
 ;
383

    
384
CF_END