Statistics
| Branch: | Revision:

iof-bird-daemon / filter / config.Y @ 758458be

History | View | Annotate | Download (14.3 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 (for BGP): whole system of paths, path ~ string, path.prepend(), path.originate
10
	FIXME: create community lists
11
	FIXME: IP addresses in ipv6
12

    
13

    
14
        FIXME: check messages for \n at the end
15
 */
16

    
17
CF_HDR
18

    
19
CF_DEFINES
20

    
21
#define P(a,b) ((a<<8) | b)
22

    
23
CF_DECLS
24

    
25
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
26
	ACCEPT, REJECT, ERROR, QUITBIRD,
27
	INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGPMASK, BGPPATH, CLIST,
28
	IF, THEN, ELSE, CASE,
29
	TRUE, FALSE,
30
	FROM, GW, NET, MASK, SOURCE,
31
	LEN,
32
	DEFINED,
33
	ADD, DELETE, CONTAINS, RESET,
34
	PREPEND, MATCH,
35
	EMPTY,
36
	FILTER, WHERE)
37

    
38
%nonassoc THEN
39
%nonassoc ELSE
40

    
41
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn dynamic_attr function_call
42
%type <f> filter filter_body where_filter
43
%type <i> type break_command pair
44
%type <e> set_item set_items switch_body
45
%type <v> set_atom fprefix fprefix_s ipa
46
%type <s> decls declsn one_decl function_params 
47
%type <h> bgp_path
48
%type <i> bgp_one
49

    
50
CF_GRAMMAR
51

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

    
62
type:
63
   INT { $$ = T_INT; }
64
 | BOOL { $$ = T_BOOL; }
65
 | IP { $$ = T_IP; }
66
 | PREFIX { $$ = T_PREFIX; }
67
 | PAIR { $$ = T_PAIR; }
68
 | STRING { $$ = T_STRING; }
69
 | BGPMASK { $$ = T_PATH_MASK; }
70
 | BGPPATH { $$ = T_PATH; }
71
 | CLIST { $$ = T_CLIST; }
72
 | type SET { 
73
	switch ($1) {
74
	  default:
75
		cf_error( "You can not create sets of this type\n" );
76
	  case T_INT: case T_IP: case T_PREFIX: case T_PAIR:
77
	}
78
	$$ = $1 | T_SET;
79
	}
80
 ;
81

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

    
97
/* Decls with ';' at the end */
98
decls: /* EMPTY */ { $$ = NULL; }
99
 | one_decl ';' decls {
100
     $$ = $1;
101
     $$->aux = (int) $3;
102
   }
103
 ;
104

    
105
/* Declarations that have no ';' at the end. */
106
declsn: one_decl { $$ = $1; }
107
 | declsn ';' one_decl {
108
     $$ = $1;
109
     $$->aux = (int) $3;
110
   }
111
 ;
112

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

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

    
130
where_filter:
131
   WHERE term {
132
     /* Construct 'IF term THEN ACCEPT; REJECT;' */
133
     struct filter *f = cfg_alloc(sizeof(struct filter));
134
     struct f_inst *i, *acc, *rej;
135
     acc = f_new_inst();		/* ACCEPT */
136
     acc->code = P('p',',');
137
     acc->a1.p = NULL;
138
     acc->a2.i = F_ACCEPT;
139
     rej = f_new_inst();		/* REJECT */
140
     rej->code = P('p',',');
141
     rej->a1.p = NULL;
142
     rej->a2.i = F_REJECT;
143
     i = f_new_inst();			/* IF */
144
     i->code = '?';
145
     i->a1.p = $2;
146
     i->a2.p = acc;
147
     i->next = rej;
148
     f->name = NULL;
149
     f->root = i;
150
     $$ = f;
151
  }
152
 ;
153

    
154
function_params:
155
   '(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; }
156
 | '(' ')' { $$=NULL; }
157
 ;
158

    
159
function_body:
160
   decls '{' cmds '}' {
161
     $$ = $3;
162
   }
163
 ;
164

    
165
CF_ADDTO(conf, function_def)
166
function_def:
167
   FUNCTION SYM { DBG( "Begining of function %s\n", $2->name ); cf_push_scope($2); } function_params function_body {
168
     extern struct f_inst *startup_func, *test1_func, *test2_func;
169
     cf_define_symbol($2, SYM_FUNCTION, $5);
170
     if (!strcasecmp($2->name, "__startup"))
171
	startup_func = $5;
172
     if (!strcasecmp($2->name, "__test1"))
173
	test1_func = $5;
174
     if (!strcasecmp($2->name, "__test2"))
175
	test2_func = $5;
176
     $2->aux = (int) $4;
177
     $2->aux2 = $5;
178
     DBG("Hmm, we've got one function here - %s\n", $2->name); 
179
     cf_pop_scope();
180
   }
181
 ;
182

    
183
/* Programs */
184

    
185
cmds: /* EMPTY */ { $$ = NULL; }
186
 | cmd cmds {
187
     if ($1) {
188
       if ($1->next)
189
	 bug("Command has next already set\n");
190
       $1->next = $2;
191
       $$ = $1;
192
     } else $$ = $2;
193
   }
194
 ;
195

    
196
block:
197
   cmd {
198
     $$=$1;
199
   }
200
 | '{' cmds '}' {
201
     $$=$2;
202
   }
203
 ;
204

    
205
/*
206
 * Simple types, their bison value is int
207
 */
208
pair:
209
   '(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; }
210
 ;
211

    
212
/*
213
 * Complex types, their bison value is struct f_val
214
 */
215
fprefix_s:
216
   IPA '/' NUM {
217
     if (!ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d", $1, $3);
218
     $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3;
219
   }
220
 ;
221

    
222
fprefix:
223
   fprefix_s { $$ = $1; }
224
 | fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
225
 | fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
226
 | fprefix_s '{' NUM ',' NUM '}' { $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); }
227
 ;
228

    
229
ipa:
230
   IPA  { $$.type = T_IP; $$.val.px.ip = $1; }
231
 ;
232

    
233
set_atom:
234
   NUM  { $$.type = T_INT; $$.val.i = $1; }
235
 | pair { $$.type = T_PAIR; $$.val.i = $1; }
236
 | ipa  { $$ = $1; }
237
 | fprefix { $$ = $1; }
238
 ; 
239

    
240
set_item:
241
   set_atom { 
242
	$$ = f_new_tree(); 
243
	$$->from = $1; 
244
	if ($1.type != T_PREFIX)
245
		$$->to = $1;
246
	else {
247
		$$->to = $1;
248
		$$->to.val.px.ip = ipa_or( $$->to.val.px.ip, ipa_not( ipa_mkmask( $$->to.val.px.len ) ));
249
	}
250
   }
251
 | set_atom '.' '.' set_atom { 
252
	$$ = f_new_tree(); 
253
	$$->from = $1; 
254
	$$->to = $4; 
255
	if (($1.type == T_PREFIX) || ($4.type == T_PREFIX)) cf_error( "You can not use prefixes for range" ); 
256
   }
257
 ;
258

    
259
set_items:
260
   set_item { $$ = $1; }
261
 | set_items ',' set_item { $$ = $3; $$->left = $1; }
262
 ;
263

    
264
switch_body: /* EMPTY */ { $$ = NULL; }
265
 | set_item ':' cmds switch_body {
266
     $$ = $1;
267
     $$->data = $3;
268
     $$->left = $4;
269
   }
270
 | ELSE ':' cmds {
271
     $$ = f_new_tree(); 
272
     $$->from.type = T_VOID; 
273
     $$->to.type = T_VOID;
274
     $$->data = $3;
275
   }
276
 ;
277

    
278
/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
279

    
280
bgp_one:
281
   NUM { $$ = $1; }
282
 | '*' { $$ = PM_ANY; }
283
 ;
284

    
285
bgp_path: 
286
   bgp_one          { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = NULL; $$->val  = $1; }
287
 | bgp_one bgp_path { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2;   $$->val  = $1; }
288
 ;
289

    
290
constant:
291
   NUM    { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT;  $$->a2.i = $1; }
292
 | TRUE   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1;  }
293
 | FALSE  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0;  }
294
 | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
295
 | pair   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR;  $$->a2.i = $1; }
296
 | ipa	   { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
297
 | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
298
 | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
299
 | ENUM	  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
300
 | '/' bgp_path '/' { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $2; $$->a1.p = val; }
301
 ;
302

    
303
/*
304
 *  Maybe there are no dynamic attributes defined by protocols.
305
 *  For such cases, we force the dynamic_attr list to contain
306
 *  at least an invalid token, so it's syntantically correct.
307
 */
308
CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; })
309

    
310
rtadot: /* EMPTY, we are not permitted RTA. prefix */
311
 ;
312

    
313
function_call:
314
   SYM '(' var_list ')' {
315
     struct symbol *sym;
316
     struct f_inst *inst = $3;
317
     if ($1->class != SYM_FUNCTION)
318
       cf_error("You can not call something which is not function. Really.");
319
     DBG("You are calling function %s\n", $1->name);
320
     $$ = f_new_inst();
321
     $$->code = P('c','a');
322
     $$->a1.p = inst;
323
     $$->a2.p = $1->aux2;
324
     sym = (void *) $1->aux;
325
     while (sym || inst) {
326
       if (!sym || !inst)
327
	 cf_error("wrong number of arguments for function %s.", $1->name);
328
       DBG( "You should pass parameter called %s\n", sym->name);
329
       inst->a1.p = sym;
330
       sym = (void *) sym->aux;
331
       inst = inst->next;
332
     }
333
   }
334
 ;
335

    
336
term:
337
   '(' term ')'      { $$ = $2; }
338
 | term '+' term     { $$ = f_new_inst(); $$->code = '+';        $$->a1.p = $1; $$->a2.p = $3; }
339
 | term '=' term     { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; }
340
 | term NEQ term { $$ = f_new_inst(); $$->code = P('!','=');     $$->a1.p = $1; $$->a2.p = $3; }
341
 | term '<' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $1; $$->a2.p = $3; }
342
 | term LEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $1; $$->a2.p = $3; }
343
 | term '>' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $3; $$->a2.p = $1; }
344
 | term GEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $3; $$->a2.p = $1; }
345
 | term '~' term     { $$ = f_new_inst(); $$->code = '~';        $$->a1.p = $1; $$->a2.p = $3; }
346
 | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
347
 | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e');  $$->a1.p = $3; }
348

    
349
 | constant { $$ = $1; }
350
 | SYM {
351
     $$ = f_new_inst();
352
     switch ($1->class) {
353
       case SYM_VARIABLE | T_INT:
354
       case SYM_VARIABLE | T_PAIR:
355
       case SYM_VARIABLE | T_PREFIX:
356
       case SYM_VARIABLE | T_IP:
357
       case SYM_VARIABLE | T_PATH_MASK:
358
       case SYM_VARIABLE | T_PATH:
359
       case SYM_VARIABLE | T_CLIST:
360
	 $$->code = 'C';
361
	 $$->a1.p = $1->aux2;
362
	 break;
363
       default:
364
	 cf_error("Can not use this class of symbol (%s,%x) as variable.", $1->name, $1->class );
365
     }
366
   }
367

    
368
 | rtadot FROM    { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, from); }
369

    
370
 | rtadot GW      { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); }
371
 | rtadot NET     { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_PREFIX; $$->a2.i = 0x12345678; }
372
 | rtadot SOURCE  { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, source); }
373

    
374
 | rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); }
375

    
376
 | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
377
 | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
378
 | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
379

    
380
/* Communities */
381
/* This causes one shift/reduce conflict
382
 | rtadot dynamic_attr '.' ADD '(' term ')' { }
383
 | rtadot dynamic_attr '.' DELETE '(' term ')' { }
384
 | rtadot dynamic_attr '.' CONTAINS '(' term ')' { }
385
 | rtadot dynamic_attr '.' RESET{ }
386
*/
387

    
388
/* Paths */
389
 | term '.' PREPEND '(' term ')' { }
390
 | term '.' RESET { }
391

    
392
 | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; }
393
 | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; }
394
 | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; } 
395
 | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } 
396
 | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
397
 
398

    
399
/* | term '.' LEN { $$->code = P('P','l'); } */
400

    
401
/* function_call is inlined here */
402
 | SYM '(' var_list ')' {
403
     struct symbol *sym;
404
     struct f_inst *inst = $3;
405
     if ($1->class != SYM_FUNCTION)
406
       cf_error("You can not call something which is not function. Really.");
407
     DBG("You are calling function %s\n", $1->name);
408
     $$ = f_new_inst();
409
     $$->code = P('c','a');
410
     $$->a1.p = inst;
411
     $$->a2.p = $1->aux2;
412
     sym = (void *) $1->aux;
413
     while (sym || inst) {
414
       if (!sym || !inst)
415
	 cf_error("wrong number of arguments for function %s.", $1->name);
416
       DBG( "You should pass parameter called %s\n", sym->name);
417
       inst->a1.p = sym;
418
       sym = (void *) sym->aux;
419
       inst = inst->next;
420
     }
421
   }
422
 ;
423

    
424
break_command:
425
   QUITBIRD { $$ = F_QUITBIRD }
426
 | ACCEPT { $$ = F_ACCEPT }
427
 | REJECT { $$ = F_REJECT }
428
 | ERROR { $$ = F_ERROR }
429
 | PRINT { $$ = F_NOP }
430
 | PRINTN { $$ = F_NONL }
431
 ;
432

    
433
print_one:
434
   term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
435
 ;
436

    
437
print_list: /* EMPTY */ { $$ = NULL; }
438
 | print_one { $$ = $1; }
439
 | print_one ',' print_list {
440
     if ($1) {
441
       $1->next = $3;
442
       $$ = $1;
443
     } else $$ = $3;
444
   }
445
 
446
 ;
447

    
448
var_listn: term { 
449
     $$ = f_new_inst();
450
     $$->code = 's';
451
     $$->a1.p = NULL;
452
     $$->a2.p = $1;
453
     $$->next = NULL;
454
   }
455
 | term ',' var_listn {
456
     $$ = f_new_inst();
457
     $$->code = 's';
458
     $$->a1.p = NULL;
459
     $$->a2.p = $1;
460
     $$->next = $3;
461
   }
462
 ;
463

    
464
var_list: /* EMPTY */ { $$ = NULL; }
465
 | var_listn { $$ = $1; }
466
 ;
467

    
468
cmd:
469
   IF term THEN block {
470
     $$ = f_new_inst();
471
     $$->code = '?';
472
     $$->a1.p = $2;
473
     $$->a2.p = $4;
474
   }
475
 | IF term THEN block ELSE block {
476
     struct f_inst *i = f_new_inst();
477
     i->code = '?';
478
     i->a1.p = $2;
479
     i->a2.p = $4;
480
     $$ = f_new_inst();
481
     $$->code = '?';
482
     $$->a1.p = i;
483
     $$->a2.p = $6;
484
   }
485
 | SYM '=' term ';' {
486
     $$ = f_new_inst();
487
     DBG( "Ook, we'll set value\n" );
488
     if (($1->class & ~T_MASK) != SYM_VARIABLE)
489
       cf_error( "You may only set variables, and this is %x.\n", $1->class );
490
     $$->code = 's';
491
     $$->a1.p = $1;
492
     $$->a2.p = $3;
493
   }
494
 | RETURN term ';' {
495
     $$ = f_new_inst();
496
     DBG( "Ook, we'll return the value\n" );
497
     $$->code = 'r';
498
     $$->a1.p = $2;
499
   }
500
 | rtadot dynamic_attr '=' term ';' {
501
     $$ = $2;
502
     $$->code  = P('e','S');
503
     $$->a1.p = $4;
504
   }
505
 | UNSET '(' rtadot dynamic_attr ')' ';' {
506
     $$ = $4;
507
     $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
508
     $$->code = P('e','S');
509
     $$->a1.p = NULL;
510
   }
511
 | break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; }
512
 | function_call ';' { $$ = $1; }
513
 | CASE term '{' switch_body '}' {
514
      $$ = f_new_inst();
515
      $$->code = P('S','W');
516
      $$->a1.p = $2;
517
      $$->a2.p = build_tree( $4 );
518
   }
519

    
520

    
521
 | rtadot dynamic_attr '.' EMPTY ';' 
522
  { struct f_inst *i = f_new_inst(); i->code = 'E'; i->aux = T_CLIST; $$ = $2; $$->code = P('e','S'); $$->a1.p = i; }
523
 | rtadot dynamic_attr '.' PREPEND '(' term ')' ';'   { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); }
524
 | rtadot dynamic_attr '.' ADD '(' term ')' ';'       { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); } 
525
 | rtadot dynamic_attr '.' DELETE '(' term ')' ';'    { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); } 
526
 ;
527

    
528
CF_END