Statistics
| Branch: | Revision:

iof-bird-daemon / filter / config.Y @ c8cafc8e

History | View | Annotate | Download (27.3 KB)

1
/*
2
 *	BIRD - filters
3
 *
4
 *	Copyright 1998--2000 Pavel Machek
5
 *
6
 *	Can be freely distributed and used under the terms of the GNU GPL.
7
 *
8
	FIXME: priority of ! should be lower
9
 */
10

    
11
CF_HDR
12

    
13
CF_DEFINES
14

    
15
#define P(a,b) ((a << 8) | b)
16

    
17
static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; }
18
static inline u32 pair_a(u32 p) { return p >> 16; }
19
static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
20

    
21

    
22
/*
23
 * Sets and their items are during parsing handled as lists, linked
24
 * through left ptr. The first item in a list also contains a pointer
25
 * to the last item in a list (right ptr). For convenience, even items
26
 * are handled as one-item lists. Lists are merged by f_merge_items().
27
 */
28
static int
29
f_valid_set_type(int type)
30
{
31
  switch (type)
32
  {
33
  case T_INT:
34
  case T_PAIR:
35
  case T_QUAD:
36
  case T_ENUM:
37
  case T_IP:
38
  case T_EC:
39
  case T_LC:
40
    return 1;
41

    
42
  default:
43
    return 0;
44
  }
45
}
46

    
47
static inline struct f_tree *
48
f_new_item(struct f_val from, struct f_val to)
49
{
50
  struct f_tree *t = f_new_tree();
51
  t->right = t;
52
  t->from = from;
53
  t->to = to;
54
  return t;
55
}
56

    
57
static inline struct f_tree *
58
f_merge_items(struct f_tree *a, struct f_tree *b)
59
{
60
  if (!a) return b;
61
  a->right->left = b;
62
  a->right = b->right;
63
  b->right = NULL;
64
  return a;
65
}
66

    
67
static inline struct f_tree *
68
f_new_pair_item(int fa, int ta, int fb, int tb)
69
{
70
  check_u16(fa);
71
  check_u16(ta);
72
  check_u16(fb);
73
  check_u16(tb);
74

    
75
  if ((ta < fa) || (tb < fb))
76
    cf_error( "From value cannot be higher that To value in pair sets");
77

    
78
  struct f_tree *t = f_new_tree();
79
  t->right = t;
80
  t->from.type = t->to.type = T_PAIR;
81
  t->from.val.i = pair(fa, fb);
82
  t->to.val.i = pair(ta, tb);
83
  return t;
84
}
85

    
86
static inline struct f_tree *
87
f_new_pair_set(int fa, int ta, int fb, int tb)
88
{
89
  check_u16(fa);
90
  check_u16(ta);
91
  check_u16(fb);
92
  check_u16(tb);
93

    
94
  if ((ta < fa) || (tb < fb))
95
    cf_error( "From value cannot be higher that To value in pair sets");
96

    
97
  struct f_tree *lst = NULL;
98
  int i;
99

    
100
  for (i = fa; i <= ta; i++)
101
    lst = f_merge_items(lst, f_new_pair_item(i, i, fb, tb));
102

    
103
  return lst;
104
}
105

    
106
#define CC_ALL 0xFFFF
107
#define EC_ALL 0xFFFFFFFF
108
#define LC_ALL 0xFFFFFFFF
109

    
110
static struct f_tree *
111
f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt)
112
{
113
  u64 fm, to;
114

    
115
  if (ipv4_used || (key >= 0x10000)) {
116
    check_u16(vf);
117
    if (vt == EC_ALL)
118
      vt = 0xFFFF;
119
    else
120
      check_u16(vt);
121
  }
122

    
123
  if (kind == EC_GENERIC) {
124
    fm = ec_generic(key, vf);
125
    to = ec_generic(key, vt);
126
  }
127
  else if (ipv4_used) {
128
    fm = ec_ip4(kind, key, vf);
129
    to = ec_ip4(kind, key, vt);
130
  }
131
  else if (key < 0x10000) {
132
    fm = ec_as2(kind, key, vf);
133
    to = ec_as2(kind, key, vt);
134
  }
135
  else {
136
    fm = ec_as4(kind, key, vf);
137
    to = ec_as4(kind, key, vt);
138
  }
139

    
140
  struct f_tree *t = f_new_tree();
141
  t->right = t;
142
  t->from.type = t->to.type = T_EC;
143
  t->from.val.ec = fm;
144
  t->to.val.ec = to;
145
  return t;
146
}
147

    
148
static struct f_tree *
149
f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3)
150
{
151
  struct f_tree *t = f_new_tree();
152
  t->right = t;
153
  t->from.type = t->to.type = T_LC;
154
  t->from.val.lc = (lcomm) {f1, f2, f3};
155
  t->to.val.lc = (lcomm) {t1, t2, t3};
156
  return t;
157
}
158

    
159
static inline struct f_inst *
160
f_generate_empty(struct f_inst *dyn)
161
{
162
  struct f_inst *e = f_new_inst();
163
  e->code = 'E';
164

    
165
  switch (dyn->aux & EAF_TYPE_MASK) {
166
    case EAF_TYPE_AS_PATH:
167
      e->aux = T_PATH;
168
      break;
169
    case EAF_TYPE_INT_SET:
170
      e->aux = T_CLIST;
171
      break;
172
    case EAF_TYPE_EC_SET:
173
      e->aux = T_ECLIST;
174
      break;
175
    case EAF_TYPE_LC_SET:
176
      e->aux = T_LCLIST;
177
      break;
178
    default:
179
      cf_error("Can't empty that attribute");
180
  }
181

    
182
  dyn->code = P('e','S');
183
  dyn->a1.p = e;
184
  return dyn;
185
}
186

    
187

    
188
static inline struct f_inst *
189
f_generate_dpair(struct f_inst *t1, struct f_inst *t2)
190
{
191
  struct f_inst *rv;
192

    
193
  if ((t1->code == 'c') && (t2->code == 'c')) {
194
    if ((t1->aux != T_INT) || (t2->aux != T_INT))
195
      cf_error( "Can't operate with value of non-integer type in pair constructor");
196

    
197
    check_u16(t1->a2.i);
198
    check_u16(t2->a2.i);
199

    
200
    rv = f_new_inst();
201
    rv->code = 'c';
202
    rv->aux = T_PAIR;
203
    rv->a2.i = pair(t1->a2.i, t2->a2.i);
204
  }
205
  else {
206
    rv = f_new_inst();
207
    rv->code = P('m', 'p');
208
    rv->a1.p = t1;
209
    rv->a2.p = t2;
210
  }
211

    
212
  return rv;
213
}
214

    
215
static inline struct f_inst *
216
f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
217
{
218
  struct f_inst *rv;
219
  int c1 = 0, c2 = 0, ipv4_used = 0;
220
  u32 key = 0, val2 = 0;
221

    
222
  if (tk->code == 'c') {
223
    c1 = 1;
224

    
225
    if (tk->aux == T_INT) {
226
      ipv4_used = 0; key = tk->a2.i;
227
    }
228
    else if (tk->aux == T_QUAD) {
229
      ipv4_used = 1; key = tk->a2.i;
230
    }
231
    else
232
      cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
233
  }
234

    
235
#ifndef IPV6
236
  /* IP->Quad implicit conversion */
237
  else if (tk->code == 'C') {
238
    c1 = 1;
239
    struct f_val *val = tk->a1.p;
240

    
241
    if (val->type == T_INT) {
242
      ipv4_used = 0; key = val->val.i;
243
    }
244
    else if (val->type == T_QUAD) {
245
      ipv4_used = 1; key = val->val.i;
246
    }
247
    else if (val->type == T_IP) {
248
      ipv4_used = 1; key = ipa_to_u32(val->val.px.ip);
249
    }
250
    else
251
      cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
252
  }
253
#endif
254

    
255
  if (tv->code == 'c') {
256
    if (tv->aux != T_INT)
257
      cf_error("Can't operate with value of non-integer type in EC constructor");
258
    c2 = 1;
259
    val2 = tv->a2.i;
260
  }
261

    
262
  if (c1 && c2) {
263
    u64 ec;
264

    
265
    if (kind == EC_GENERIC) {
266
      ec = ec_generic(key, val2);
267
    }
268
    else if (ipv4_used) {
269
      check_u16(val2);
270
      ec = ec_ip4(kind, key, val2);
271
    }
272
    else if (key < 0x10000) {
273
      ec = ec_as2(kind, key, val2);
274
    }
275
    else {
276
      check_u16(val2);
277
      ec = ec_as4(kind, key, val2);
278
    }
279

    
280
    NEW_F_VAL;
281
    rv = f_new_inst();
282
    rv->code = 'C';
283
    rv->a1.p = val;
284
    val->type = T_EC;
285
    val->val.ec = ec;
286
  }
287
  else {
288
    rv = f_new_inst();
289
    rv->code = P('m','c');
290
    rv->aux = kind;
291
    rv->a1.p = tk;
292
    rv->a2.p = tv;
293
  }
294

    
295
  return rv;
296
}
297

    
298
static inline struct f_inst *
299
f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3)
300
{
301
  struct f_inst *rv;
302

    
303
  if ((t1->code == 'c') && (t2->code == 'c') && (t3->code == 'c')) {
304
    if ((t1->aux != T_INT) || (t2->aux != T_INT) || (t3->aux != T_INT))
305
      cf_error( "LC - Can't operate with value of non-integer type in tuple constructor");
306

    
307
    rv = f_new_inst();
308
    rv->code = 'C';
309

    
310
    NEW_F_VAL;
311
    rv->a1.p = val;
312
    val->type = T_LC;
313
    val->val.lc = (lcomm) { t1->a2.i, t2->a2.i, t3->a2.i };
314
  }
315
  else
316
  {
317
    rv = cfg_allocz(sizeof(struct f_inst3));
318
    rv->lineno = ifs->lino;
319
    rv->code = P('m','l');
320
    rv->a1.p = t1;
321
    rv->a2.p = t2;
322
    INST3(rv).p = t3;
323
  }
324

    
325
  return rv;
326
}
327

    
328

    
329

    
330
CF_DECLS
331

    
332
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
333
	ACCEPT, REJECT, ERROR, QUITBIRD,
334
	INT, BOOL, IP, PREFIX, PAIR, QUAD, EC, LC,
335
	SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
336
	IF, THEN, ELSE, CASE,
337
	TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
338
	FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX,
339
	PREFERENCE,
340
	LEN,
341
	DEFINED,
342
	ADD, DELETE, CONTAINS, RESET,
343
	PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
344
	ROA_CHECK,
345
	EMPTY,
346
	FILTER, WHERE, EVAL)
347

    
348
%nonassoc THEN
349
%nonassoc ELSE
350

    
351
%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr
352
%type <f> filter filter_body where_filter
353
%type <i> type break_command ec_kind
354
%type <i32> cnum
355
%type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
356
%type <trie> fprefix_set
357
%type <v> set_atom switch_atom fprefix fprefix_s fipa
358
%type <s> decls declsn one_decl function_params
359
%type <h> bgp_path bgp_path_tail1 bgp_path_tail2
360

    
361
CF_GRAMMAR
362

    
363
CF_ADDTO(conf, filter_def)
364
filter_def:
365
   FILTER SYM { $2 = cf_define_symbol($2, SYM_FILTER, NULL); cf_push_scope( $2 ); }
366
     filter_body {
367
     $2->def = $4;
368
     $4->name = $2->name;
369
     DBG( "We have new filter defined (%s)\n", $2->name );
370
     cf_pop_scope();
371
   }
372
 ;
373

    
374
CF_ADDTO(conf, filter_eval)
375
filter_eval:
376
   EVAL term { f_eval_int($2); }
377
 ;
378

    
379
type:
380
   INT { $$ = T_INT; }
381
 | BOOL { $$ = T_BOOL; }
382
 | IP { $$ = T_IP; }
383
 | PREFIX { $$ = T_PREFIX; }
384
 | PAIR { $$ = T_PAIR; }
385
 | QUAD { $$ = T_QUAD; }
386
 | EC { $$ = T_EC; }
387
 | LC { $$ = T_LC; }
388
 | STRING { $$ = T_STRING; }
389
 | BGPMASK { $$ = T_PATH_MASK; }
390
 | BGPPATH { $$ = T_PATH; }
391
 | CLIST { $$ = T_CLIST; }
392
 | ECLIST { $$ = T_ECLIST; }
393
 | LCLIST { $$ = T_LCLIST; }
394
 | type SET {
395
	switch ($1) {
396
	  case T_INT:
397
	  case T_PAIR:
398
	  case T_QUAD:
399
	  case T_EC:
400
	  case T_LC:
401
	  case T_IP:
402
	       $$ = T_SET;
403
	       break;
404

    
405
	  case T_PREFIX:
406
	       $$ = T_PREFIX_SET;
407
	    break;
408

    
409
	  default:
410
		cf_error( "You can't create sets of this type." );
411
	}
412
   }
413
 ;
414

    
415
one_decl:
416
   type SYM {
417
     struct f_val * val = cfg_alloc(sizeof(struct f_val));
418
     val->type = T_VOID;
419
     $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val);
420
     DBG( "New variable %s type %x\n", $2->name, $1 );
421
     $2->aux2 = NULL;
422
     $$=$2;
423
   }
424
 ;
425

    
426
/* Decls with ';' at the end */
427
decls: /* EMPTY */ { $$ = NULL; }
428
 | one_decl ';' decls {
429
     $$ = $1;
430
     $$->aux2 = $3;
431
   }
432
 ;
433

    
434
/* Declarations that have no ';' at the end. */
435
declsn: one_decl { $$ = $1; }
436
 | one_decl ';' declsn {
437
     $$ = $1;
438
     $$->aux2 = $3;
439
   }
440
 ;
441

    
442
filter_body:
443
   function_body {
444
     struct filter *f = cfg_alloc(sizeof(struct filter));
445
     f->name = NULL;
446
     f->root = $1;
447
     $$ = f;
448
   }
449
 ;
450

    
451
filter:
452
   SYM {
453
     if ($1->class != SYM_FILTER) cf_error("No such filter.");
454
     $$ = $1->def;
455
   }
456
 | filter_body
457
 ;
458

    
459
where_filter:
460
   WHERE term {
461
     /* Construct 'IF term THEN ACCEPT; REJECT;' */
462
     struct filter *f = cfg_alloc(sizeof(struct filter));
463
     struct f_inst *i, *acc, *rej;
464
     acc = f_new_inst();		/* ACCEPT */
465
     acc->code = P('p',',');
466
     acc->a1.p = NULL;
467
     acc->a2.i = F_ACCEPT;
468
     rej = f_new_inst();		/* REJECT */
469
     rej->code = P('p',',');
470
     rej->a1.p = NULL;
471
     rej->a2.i = F_REJECT;
472
     i = f_new_inst();			/* IF */
473
     i->code = '?';
474
     i->a1.p = $2;
475
     i->a2.p = acc;
476
     i->next = rej;
477
     f->name = NULL;
478
     f->root = i;
479
     $$ = f;
480
  }
481
 ;
482

    
483
function_params:
484
   '(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; }
485
 | '(' ')' { $$=NULL; }
486
 ;
487

    
488
function_body:
489
   decls '{' cmds '}' {
490
     if ($1) {
491
       /* Prepend instruction to clear local variables */
492
       $$ = f_new_inst();
493
       $$->code = P('c','v');
494
       $$->a1.p = $1;
495
       $$->next = $3;
496
     } else
497
       $$ = $3;
498
   }
499
 ;
500

    
501
CF_ADDTO(conf, function_def)
502
function_def:
503
   FUNCTION SYM { DBG( "Beginning of function %s\n", $2->name );
504
     $2 = cf_define_symbol($2, SYM_FUNCTION, NULL);
505
     cf_push_scope($2);
506
   } function_params function_body {
507
     $2->def = $5;
508
     $2->aux2 = $4;
509
     DBG("Hmm, we've got one function here - %s\n", $2->name);
510
     cf_pop_scope();
511
   }
512
 ;
513

    
514
/* Programs */
515

    
516
/* Hack: $$ of cmds_int is the last node.
517
   $$->next of cmds_int is temporary used for the first node */
518

    
519
cmds: /* EMPTY */ { $$ = NULL; }
520
 | cmds_int { $$ = $1->next; $1->next = NULL; }
521
 ;
522

    
523
cmds_int: cmd { $$ = $1; $1->next = $1; }
524
 | cmds_int cmd { $$ = $2; $2->next = $1->next ; $1->next = $2; }
525
 ;
526

    
527
block:
528
   cmd {
529
     $$=$1;
530
   }
531
 | '{' cmds '}' {
532
     $$=$2;
533
   }
534
 ;
535

    
536
/*
537
 * Complex types, their bison value is struct f_val
538
 */
539
fipa:
540
   IPA %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; }
541
 ;
542

    
543

    
544

    
545
/*
546
 * Set constants. They are also used in switch cases. We use separate
547
 * nonterminals for switch (set_atom/switch_atom, set_item/switch_item ...)
548
 * to elude a collision between symbol (in expr) in set_atom and symbol
549
 * as a function call in switch case cmds.
550
 */
551

    
552
set_atom:
553
   NUM   { $$.type = T_INT; $$.val.i = $1; }
554
 | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
555
 | fipa  { $$ = $1; }
556
 | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
557
 | '(' term ')' {
558
     $$ = f_eval($2, cfg_mem);
559
     if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
560
   }
561
 | SYM {
562
     if (!cf_symbol_is_constant($1)) cf_error("%s: constant expected", $1->name);
563
     if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name);
564
     $$ = *(struct f_val *)($1->def);
565
   }
566
 ;
567

    
568
switch_atom:
569
   NUM   { $$.type = T_INT; $$.val.i = $1; }
570
 | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2); }
571
 | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
572
 | fipa  { $$ = $1; }
573
 | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
574
 ;
575

    
576
cnum:
577
   term { $$ = f_eval_int($1); }
578

    
579
pair_item:
580
   '(' cnum ',' cnum ')'		{ $$ = f_new_pair_item($2, $2, $4, $4); }
581
 | '(' cnum ',' cnum DDOT cnum ')'	{ $$ = f_new_pair_item($2, $2, $4, $6); }
582
 | '(' cnum ',' '*' ')'			{ $$ = f_new_pair_item($2, $2, 0, CC_ALL); }
583
 | '(' cnum DDOT cnum ',' cnum ')'	{ $$ = f_new_pair_set($2, $4, $6, $6); }
584
 | '(' cnum DDOT cnum ',' cnum DDOT cnum ')' { $$ = f_new_pair_set($2, $4, $6, $8); }
585
 | '(' cnum DDOT cnum ',' '*' ')'	{ $$ = f_new_pair_item($2, $4, 0, CC_ALL); }
586
 | '(' '*' ',' cnum ')'			{ $$ = f_new_pair_set(0, CC_ALL, $4, $4); }
587
 | '(' '*' ',' cnum DDOT cnum ')'	{ $$ = f_new_pair_set(0, CC_ALL, $4, $6); }
588
 | '(' '*' ',' '*' ')'			{ $$ = f_new_pair_item(0, CC_ALL, 0, CC_ALL); }
589
 | '(' cnum ',' cnum ')' DDOT '(' cnum ',' cnum ')'
590
   { $$ = f_new_pair_item($2, $8, $4, $10); }
591
 ;
592

    
593
ec_kind:
594
   RT { $$ = EC_RT; }
595
 | RO { $$ = EC_RO; }
596
 | UNKNOWN NUM { $$ = $2; }
597
 | GENERIC { $$ = EC_GENERIC; }
598
 ;
599

    
600
ec_item:
601
   '(' ec_kind ',' cnum ',' cnum ')'		{ $$ = f_new_ec_item($2, 0, $4, $6, $6); }
602
 | '(' ec_kind ',' cnum ',' cnum DDOT cnum ')'	{ $$ = f_new_ec_item($2, 0, $4, $6, $8); }
603
 | '(' ec_kind ',' cnum ',' '*' ')'		{ $$ = f_new_ec_item($2, 0, $4, 0, EC_ALL); }
604
 ;
605

    
606
lc_item:
607
   '(' cnum ',' cnum ',' cnum ')'	    { $$ = f_new_lc_item($2, $2, $4, $4, $6, $6); }
608
 | '(' cnum ',' cnum ',' cnum DDOT cnum ')' { $$ = f_new_lc_item($2, $2, $4, $4, $6, $8); }
609
 | '(' cnum ',' cnum ',' '*' ')'	    { $$ = f_new_lc_item($2, $2, $4, $4, 0, LC_ALL); }
610
 | '(' cnum ',' cnum DDOT cnum ',' '*' ')'  { $$ = f_new_lc_item($2, $2, $4, $6, 0, LC_ALL); }
611
 | '(' cnum ',' '*' ',' '*' ')'		    { $$ = f_new_lc_item($2, $2, 0, LC_ALL, 0, LC_ALL); }
612
 | '(' cnum DDOT cnum ',' '*' ',' '*' ')'   { $$ = f_new_lc_item($2, $4, 0, LC_ALL, 0, LC_ALL); }
613
 | '(' '*' ',' '*' ',' '*' ')'		    { $$ = f_new_lc_item(0, LC_ALL, 0, LC_ALL, 0, LC_ALL); }
614
 | '(' cnum ',' cnum ',' cnum ')' DDOT '(' cnum ',' cnum ',' cnum ')'
615
   { $$ = f_new_lc_item($2, $10, $4, $12, $6, $14); }
616
;
617

    
618
set_item:
619
   pair_item
620
 | ec_item
621
 | lc_item
622
 | set_atom { $$ = f_new_item($1, $1); }
623
 | set_atom DDOT set_atom { $$ = f_new_item($1, $3); }
624
 ;
625

    
626
switch_item:
627
   pair_item
628
 | ec_item
629
 | lc_item
630
 | switch_atom { $$ = f_new_item($1, $1); }
631
 | switch_atom DDOT switch_atom { $$ = f_new_item($1, $3); }
632
 ;
633

    
634
set_items:
635
   set_item
636
 | set_items ',' set_item { $$ = f_merge_items($1, $3); }
637
 ;
638

    
639
switch_items:
640
   switch_item
641
 | switch_items ',' switch_item { $$ = f_merge_items($1, $3); }
642
 ;
643

    
644
fprefix_s:
645
   IPA '/' NUM %prec '/' {
646
     if (($3 < 0) || ($3 > MAX_PREFIX_LENGTH) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3);
647
     $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3;
648
   }
649
 ;
650

    
651
fprefix:
652
   fprefix_s { $$ = $1; }
653
 | fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
654
 | fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
655
 | fprefix_s '{' NUM ',' NUM '}' {
656
     if (! ((0 <= $3) && ($3 <= $5) && ($5 <= MAX_PREFIX_LENGTH))) cf_error("Invalid prefix pattern range: {%d, %d}.", $3, $5);
657
     $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8);
658
   }
659
 ;
660

    
661
fprefix_set:
662
   fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_fprefix($$, &($1.val.px)); }
663
 | fprefix_set ',' fprefix { $$ = $1; trie_add_fprefix($$, &($3.val.px)); }
664
 ;
665

    
666
switch_body: /* EMPTY */ { $$ = NULL; }
667
 | switch_body switch_items ':' cmds  {
668
     /* Fill data fields */
669
     struct f_tree *t;
670
     for (t = $2; t; t = t->left)
671
       t->data = $4;
672
     $$ = f_merge_items($1, $2);
673
   }
674
 | switch_body ELSECOL cmds {
675
     struct f_tree *t = f_new_tree();
676
     t->from.type = t->to.type = T_VOID;
677
     t->right = t;
678
     t->data = $3;
679
     $$ = f_merge_items($1, t);
680
 }
681
 ;
682

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

    
685
bgp_path_expr:
686
   symbol       { $$ = $1; }
687
 | '(' term ')' { $$ = $2; }
688
 ;
689

    
690
bgp_path:
691
   PO  bgp_path_tail1 PC  { $$ = $2; }
692
 | '/' bgp_path_tail2 '/' { $$ = $2; }
693
 ;
694

    
695
bgp_path_tail1:
696
   NUM bgp_path_tail1		{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
697
 | NUM DDOT NUM bgp_path_tail1	{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $4; $$->kind = PM_ASN_RANGE; $$->val = $1; $$->val2 = $3; }
698
 | '*' bgp_path_tail1		{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; }
699
 | '?' bgp_path_tail1		{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; }
700
 | bgp_path_expr bgp_path_tail1	{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN_EXPR; $$->val = (uintptr_t) $1; }
701
 | 				{ $$ = NULL; }
702
 ;
703

    
704
bgp_path_tail2:
705
   NUM bgp_path_tail2 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
706
 | '?' bgp_path_tail2 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; }
707
 | 		      { $$ = NULL; }
708
 ;
709

    
710
constant:
711
   NUM    { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT;  $$->a2.i = $1; }
712
 | TRUE   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1;  }
713
 | FALSE  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0;  }
714
 | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
715
 | fipa	   { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
716
 | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
717
 | RTRID  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD;  $$->a2.i = $1; }
718
 | '[' 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" ); }
719
 | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET;  $$->a2.p = $2; }
720
 | ENUM	  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
721
 | bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; }
722
 ;
723

    
724
constructor:
725
   '(' term ',' term ')' { $$ = f_generate_dpair($2, $4); }
726
 | '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); }
727
 | '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); }
728
 ;
729

    
730

    
731
/*
732
 *  Maybe there are no dynamic attributes defined by protocols.
733
 *  For such cases, we force the dynamic_attr list to contain
734
 *  at least an invalid token, so it is syntantically correct.
735
 */
736
CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; })
737

    
738
rtadot: /* EMPTY, we are not permitted RTA. prefix */
739
 ;
740

    
741
function_call:
742
   SYM '(' var_list ')' {
743
     struct symbol *sym;
744
     struct f_inst *inst = $3;
745
     if ($1->class != SYM_FUNCTION)
746
       cf_error("You can't call something which is not a function. Really.");
747
     DBG("You are calling function %s\n", $1->name);
748
     $$ = f_new_inst();
749
     $$->code = P('c','a');
750
     $$->a1.p = inst;
751
     $$->a2.p = $1->def;
752
     sym = $1->aux2;
753
     while (sym || inst) {
754
       if (!sym || !inst)
755
	 cf_error("Wrong number of arguments for function %s.", $1->name);
756
       DBG( "You should pass parameter called %s\n", sym->name);
757
       inst->a1.p = sym;
758
       sym = sym->aux2;
759
       inst = inst->next;
760
     }
761
   }
762
 ;
763

    
764
symbol:
765
   SYM {
766
     $$ = f_new_inst();
767

    
768
     switch ($1->class & 0xff00) {
769
       case SYM_CONSTANT: $$->code = 'C'; break;
770
       case SYM_VARIABLE: $$->code = 'V'; break;
771
       default: cf_error("%s: variable expected.", $1->name);
772
     }
773

    
774
     $$->a1.p = $1->def;
775
     $$->a2.p = $1->name;
776
   }
777

    
778
static_attr:
779
   FROM    { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = SA_FROM;	$$->a1.i = 1; }
780
 | GW      { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = SA_GW;	$$->a1.i = 1; }
781
 | NET     { $$ = f_new_inst(); $$->aux = T_PREFIX;     $$->a2.i = SA_NET; }
782
 | PROTO   { $$ = f_new_inst(); $$->aux = T_STRING;     $$->a2.i = SA_PROTO; }
783
 | SOURCE  { $$ = f_new_inst(); $$->aux = T_ENUM_RTS;   $$->a2.i = SA_SOURCE; }
784
 | SCOPE   { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE;	$$->a1.i = 1; }
785
 | CAST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTC;   $$->a2.i = SA_CAST; }
786
 | DEST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTD;   $$->a2.i = SA_DEST;	$$->a1.i = 1; }
787
 | IFNAME  { $$ = f_new_inst(); $$->aux = T_STRING;     $$->a2.i = SA_IFNAME; }
788
 | IFINDEX { $$ = f_new_inst(); $$->aux = T_INT;        $$->a2.i = SA_IFINDEX; }
789
 ;
790

    
791
term:
792
   '(' term ')'      { $$ = $2; }
793
 | term '+' term     { $$ = f_new_inst(); $$->code = '+';        $$->a1.p = $1; $$->a2.p = $3; }
794
 | term '-' term     { $$ = f_new_inst(); $$->code = '-';        $$->a1.p = $1; $$->a2.p = $3; }
795
 | term '*' term     { $$ = f_new_inst(); $$->code = '*';        $$->a1.p = $1; $$->a2.p = $3; }
796
 | term '/' term     { $$ = f_new_inst(); $$->code = '/';        $$->a1.p = $1; $$->a2.p = $3; }
797
 | term AND term     { $$ = f_new_inst(); $$->code = '&';        $$->a1.p = $1; $$->a2.p = $3; }
798
 | term OR  term     { $$ = f_new_inst(); $$->code = '|';        $$->a1.p = $1; $$->a2.p = $3; }
799
 | term '=' term     { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; }
800
 | term NEQ term { $$ = f_new_inst(); $$->code = P('!','=');     $$->a1.p = $1; $$->a2.p = $3; }
801
 | term '<' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $1; $$->a2.p = $3; }
802
 | term LEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $1; $$->a2.p = $3; }
803
 | term '>' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $3; $$->a2.p = $1; }
804
 | term GEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $3; $$->a2.p = $1; }
805
 | term '~' term     { $$ = f_new_inst(); $$->code = '~';        $$->a1.p = $1; $$->a2.p = $3; }
806
 | term NMA term { $$ = f_new_inst(); $$->code = P('!','~');     $$->a1.p = $1; $$->a2.p = $3; }
807
 | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
808
 | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e');  $$->a1.p = $3; }
809

    
810
 | symbol   { $$ = $1; }
811
 | constant { $$ = $1; }
812
 | constructor { $$ = $1; }
813

    
814
 | PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; }
815

    
816
 | rtadot static_attr { $$ = $2; $$->code = 'a'; }
817

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

    
820
 | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
821
 | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
822
 | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
823
 | term '.' FIRST { $$ = f_new_inst(); $$->code = P('a','f'); $$->a1.p = $1; }
824
 | term '.' LAST  { $$ = f_new_inst(); $$->code = P('a','l'); $$->a1.p = $1; }
825
 | term '.' LAST_NONAGGREGATED  { $$ = f_new_inst(); $$->code = P('a','L'); $$->a1.p = $1; }
826

    
827
/* Communities */
828
/* This causes one shift/reduce conflict
829
 | rtadot dynamic_attr '.' ADD '(' term ')' { }
830
 | rtadot dynamic_attr '.' DELETE '(' term ')' { }
831
 | rtadot dynamic_attr '.' CONTAINS '(' term ')' { }
832
 | rtadot dynamic_attr '.' RESET{ }
833
*/
834

    
835
 | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; }
836
 | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; }
837
 | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; }
838
 | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_LCLIST; }
839
 | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }
840
 | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
841
 | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
842
 | FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
843

    
844
 | ROA_CHECK '(' SYM ')' { $$ = f_generate_roa_check($3, NULL, NULL); }
845
 | ROA_CHECK '(' SYM ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); }
846

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

    
849
/* function_call is inlined here */
850
 | SYM '(' var_list ')' {
851
     struct symbol *sym;
852
     struct f_inst *inst = $3;
853
     if ($1->class != SYM_FUNCTION)
854
       cf_error("You can't call something which is not a function. Really.");
855
     DBG("You are calling function %s\n", $1->name);
856
     $$ = f_new_inst();
857
     $$->code = P('c','a');
858
     $$->a1.p = inst;
859
     $$->a2.p = $1->def;
860
     sym = $1->aux2;
861
     while (sym || inst) {
862
       if (!sym || !inst)
863
	 cf_error("Wrong number of arguments for function %s.", $1->name);
864
       DBG( "You should pass parameter called %s\n", sym->name);
865
       inst->a1.p = sym;
866
       sym = sym->aux2;
867
       inst = inst->next;
868
     }
869
   }
870
 ;
871

    
872
break_command:
873
   QUITBIRD { $$ = F_QUITBIRD; }
874
 | ACCEPT { $$ = F_ACCEPT; }
875
 | REJECT { $$ = F_REJECT; }
876
 | ERROR { $$ = F_ERROR; }
877
 | PRINT { $$ = F_NOP; }
878
 | PRINTN { $$ = F_NONL; }
879
 ;
880

    
881
print_one:
882
   term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
883
 ;
884

    
885
print_list: /* EMPTY */ { $$ = NULL; }
886
 | print_one { $$ = $1; }
887
 | print_one ',' print_list {
888
     if ($1) {
889
       $1->next = $3;
890
       $$ = $1;
891
     } else $$ = $3;
892
   }
893
 ;
894

    
895
var_listn: term {
896
     $$ = f_new_inst();
897
     $$->code = 's';
898
     $$->a1.p = NULL;
899
     $$->a2.p = $1;
900
     $$->next = NULL;
901
   }
902
 | term ',' var_listn {
903
     $$ = f_new_inst();
904
     $$->code = 's';
905
     $$->a1.p = NULL;
906
     $$->a2.p = $1;
907
     $$->next = $3;
908
   }
909
 ;
910

    
911
var_list: /* EMPTY */ { $$ = NULL; }
912
 | var_listn { $$ = $1; }
913
 ;
914

    
915
cmd:
916
   IF term THEN block {
917
     $$ = f_new_inst();
918
     $$->code = '?';
919
     $$->a1.p = $2;
920
     $$->a2.p = $4;
921
   }
922
 | IF term THEN block ELSE block {
923
     struct f_inst *i = f_new_inst();
924
     i->code = '?';
925
     i->a1.p = $2;
926
     i->a2.p = $4;
927
     $$ = f_new_inst();
928
     $$->code = '?';
929
     $$->a1.p = i;
930
     $$->a2.p = $6;
931
   }
932
 | SYM '=' term ';' {
933
     $$ = f_new_inst();
934
     DBG( "Ook, we'll set value\n" );
935
     if (($1->class & ~T_MASK) != SYM_VARIABLE)
936
       cf_error( "You may set only variables." );
937
     $$->code = 's';
938
     $$->a1.p = $1;
939
     $$->a2.p = $3;
940
   }
941
 | RETURN term ';' {
942
     $$ = f_new_inst();
943
     DBG( "Ook, we'll return the value\n" );
944
     $$->code = 'r';
945
     $$->a1.p = $2;
946
   }
947
 | rtadot dynamic_attr '=' term ';' {
948
     $$ = $2;
949
     $$->code = P('e','S');
950
     $$->a1.p = $4;
951
   }
952
 | rtadot static_attr '=' term ';' {
953
     $$ = $2;
954
     if (!$$->a1.i)
955
       cf_error( "This static attribute is read-only.");
956
     $$->code = P('a','S');
957
     $$->a1.p = $4;
958
   }
959
 | PREFERENCE '=' term ';' {
960
     $$ = f_new_inst();
961
     $$->code = P('P','S');
962
     $$->a1.p = $3;
963
   }
964
 | UNSET '(' rtadot dynamic_attr ')' ';' {
965
     $$ = $4;
966
     $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
967
     $$->code = P('e','S');
968
     $$->a1.p = NULL;
969
   }
970
 | break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; }
971
 | function_call ';' { $$ = $1; }
972
 | CASE term '{' switch_body '}' {
973
      $$ = f_new_inst();
974
      $$->code = P('S','W');
975
      $$->a1.p = $2;
976
      $$->a2.p = build_tree( $4 );
977
   }
978

    
979

    
980
 | rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); }
981
 | rtadot dynamic_attr '.' PREPEND '(' term ')' ';'   { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); }
982
 | rtadot dynamic_attr '.' ADD '(' term ')' ';'       { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); }
983
 | rtadot dynamic_attr '.' DELETE '(' term ')' ';'    { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); }
984
 | rtadot dynamic_attr '.' FILTER '(' term ')' ';'    { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); }
985
 ;
986

    
987
CF_END