Statistics
| Branch: | Revision:

iof-bird-daemon / filter / filter.c @ 508d9360

History | View | Annotate | Download (37.9 KB)

1
/*
2
 *        Filters: utility functions
3
 *
4
 *        Copyright 1998 Pavel Machek <pavel@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 *
8
 */
9

    
10
/**
11
 * DOC: Filters
12
 *
13
 * You can find sources of the filter language in |filter/|
14
 * directory. File |filter/config.Y| contains filter grammar and basically translates
15
 * the source from user into a tree of &f_inst structures. These trees are
16
 * later interpreted using code in |filter/filter.c|.
17
 *
18
 * A filter is represented by a tree of &f_inst structures, one structure per
19
 * "instruction". Each &f_inst contains @code, @aux value which is
20
 * usually the data type this instruction operates on and two generic
21
 * arguments (@a1, @a2). Some instructions contain pointer(s) to other
22
 * instructions in their (@a1, @a2) fields.
23
 *
24
 * Filters use a &f_val structure for their data. Each &f_val
25
 * contains type and value (types are constants prefixed with %T_). Few
26
 * of the types are special; %T_RETURN can be or-ed with a type to indicate
27
 * that return from a function or from the whole filter should be
28
 * forced. Important thing about &f_val's is that they may be copied
29
 * with a simple |=|. That's fine for all currently defined types: strings
30
 * are read-only (and therefore okay), paths are copied for each
31
 * operation (okay too).
32
 */
33

    
34
#undef LOCAL_DEBUG
35

    
36
#include "nest/bird.h"
37
#include "lib/lists.h"
38
#include "lib/resource.h"
39
#include "lib/socket.h"
40
#include "lib/string.h"
41
#include "lib/unaligned.h"
42
#include "nest/route.h"
43
#include "nest/protocol.h"
44
#include "nest/iface.h"
45
#include "nest/attrs.h"
46
#include "conf/conf.h"
47
#include "filter/filter.h"
48

    
49
#define P(a,b) ((a<<8) | b)
50

    
51
#define CMP_ERROR 999
52

    
53
static struct adata *
54
adata_empty(struct linpool *pool, int l)
55
{
56
  struct adata *res = lp_alloc(pool, sizeof(struct adata) + l);
57
  res->length = l;
58
  return res;
59
}
60

    
61
static int
62
pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2)
63
{
64
  while (1) {
65
    if ((!m1) || (!m2))
66
      return !((!m1) && (!m2));
67

    
68
    /* FIXME: buggy, should return -1, 0, 1; but it doesn't matter */
69
    if ((m1->kind != m2->kind) || (m1->val != m2->val)) return 1;
70
    m1 = m1->next;
71
    m2 = m2->next;
72
  }
73
}
74

    
75
u32 f_eval_asn(struct f_inst *expr);
76

    
77
static void
78
pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
79
{
80
  byte *end = buf + size - 16;
81

    
82
  while (p)
83
    {
84
      if (buf > end)
85
        {
86
          strcpy(buf, " ...");
87
          return;
88
        }
89

    
90
      switch(p->kind)
91
        {
92
        case PM_ASN:
93
          buf += bsprintf(buf, " %u", p->val);
94
          break;
95

    
96
        case PM_QUESTION:
97
          buf += bsprintf(buf, " ?");
98
          break;
99

    
100
        case PM_ASTERISK:
101
          buf += bsprintf(buf, " *");
102
          break;
103

    
104
        case PM_ASN_EXPR:
105
          buf += bsprintf(buf, " %u", f_eval_asn((struct f_inst *) p->val));
106
          break;
107
        }
108

    
109
      p = p->next;
110
    }
111

    
112
  *buf = 0;
113
}
114

    
115
static inline int int_cmp(int i1, int i2)
116
{
117
  if (i1 == i2) return 0;
118
  if (i1 < i2) return -1;
119
  else return 1;
120
}
121

    
122
static inline int uint_cmp(unsigned int i1, unsigned int i2)
123
{
124
  if (i1 == i2) return 0;
125
  if (i1 < i2) return -1;
126
  else return 1;
127
}
128

    
129
static inline int u64_cmp(u64 i1, u64 i2)
130
{
131
  if (i1 == i2) return 0;
132
  if (i1 < i2) return -1;
133
  else return 1;
134
}
135

    
136
/**
137
 * val_compare - compare two values
138
 * @v1: first value
139
 * @v2: second value
140
 *
141
 * Compares two values and returns -1, 0, 1 on <, =, > or 999 on error.
142
 * Tree module relies on this giving consistent results so that it can
143
 * build balanced trees.
144
 */
145
int
146
val_compare(struct f_val v1, struct f_val v2)
147
{
148
  int rc;
149

    
150
  if ((v1.type == T_VOID) && (v2.type == T_VOID))
151
    return 0;
152
  if (v1.type == T_VOID)        /* Hack for else */
153
    return -1;
154
  if (v2.type == T_VOID)
155
    return 1;
156

    
157
  if (v1.type != v2.type) {
158
#ifndef IPV6
159
    /* IP->Quad implicit conversion */
160
    if ((v1.type == T_QUAD) && (v2.type == T_IP))
161
      return uint_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip));
162
    if ((v1.type == T_IP) && (v2.type == T_QUAD))
163
      return uint_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i);
164
#endif
165

    
166
    debug( "Types do not match in val_compare\n" );
167
    return CMP_ERROR;
168
  }
169
  switch (v1.type) {
170
  case T_ENUM:
171
  case T_INT:
172
  case T_BOOL:
173
    return int_cmp(v1.val.i, v2.val.i);
174
  case T_PAIR:
175
  case T_QUAD:
176
    return uint_cmp(v1.val.i, v2.val.i);
177
  case T_EC:
178
    return u64_cmp(v1.val.ec, v2.val.ec);
179
  case T_IP:
180
    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
181
  case T_PREFIX:
182
    if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
183
      return rc;
184
    if (v1.val.px.len < v2.val.px.len)
185
      return -1;
186
    if (v1.val.px.len > v2.val.px.len)
187
      return 1;
188
    return 0;
189
  case T_PATH_MASK:
190
    return pm_path_compare(v1.val.path_mask, v2.val.path_mask);
191
  case T_STRING:
192
    return strcmp(v1.val.s, v2.val.s);
193
  default:
194
    debug( "Compare of unknown entities: %x\n", v1.type );
195
    return CMP_ERROR;
196
  }
197
}
198

    
199
int 
200
tree_compare(const void *p1, const void *p2)
201
{
202
  return val_compare((* (struct f_tree **) p1)->from, (* (struct f_tree **) p2)->from);
203
}
204

    
205
void
206
fprefix_get_bounds(struct f_prefix *px, int *l, int *h)
207
{
208
  *l = *h = px->len & LEN_MASK;
209

    
210
  if (px->len & LEN_MINUS)
211
    *l = 0;
212

    
213
  else if (px->len & LEN_PLUS)
214
    *h = MAX_PREFIX_LENGTH;
215

    
216
  else if (px->len & LEN_RANGE)
217
    {
218
      *l = 0xff & (px->len >> 16);
219
      *h = 0xff & (px->len >> 8);
220
    }
221
}
222

    
223
/*
224
 * val_simple_in_range - check if @v1 ~ @v2 for everything except sets
225
 */ 
226
static int
227
val_simple_in_range(struct f_val v1, struct f_val v2)
228
{
229
  if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
230
    return as_path_match(v1.val.ad, v2.val.path_mask);
231
  if ((v1.type == T_INT) && (v2.type == T_PATH))
232
    return as_path_is_member(v2.val.ad, v1.val.i);
233

    
234
  if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
235
    return int_set_contains(v2.val.ad, v1.val.i);
236
#ifndef IPV6
237
  /* IP->Quad implicit conversion */
238
  if ((v1.type == T_IP) && (v2.type == T_CLIST))
239
    return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
240
#endif
241
  if ((v1.type == T_EC) && (v2.type == T_ECLIST))
242
    return ec_set_contains(v2.val.ad, v1.val.ec);
243

    
244
  if ((v1.type == T_STRING) && (v2.type == T_STRING))
245
    return patmatch(v2.val.s, v1.val.s);
246

    
247
  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
248
    return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);
249

    
250
  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX))
251
    return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);
252

    
253
  return CMP_ERROR;
254
}
255

    
256
static int
257
clist_set_type(struct f_tree *set, struct f_val *v)
258
{
259
 switch (set->from.type) {
260
  case T_PAIR:
261
    v->type = T_PAIR;
262
    return 1;
263
  case T_QUAD:
264
#ifndef IPV6
265
  case T_IP:
266
#endif
267
    v->type = T_QUAD;
268
    return 1;
269
    break;
270
  default:
271
    v->type = T_VOID;
272
    return 0;
273
  }
274
}
275

    
276
static inline int
277
eclist_set_type(struct f_tree *set)
278
{ return set->from.type == T_EC; }
279

    
280
static int
281
clist_match_set(struct adata *clist, struct f_tree *set)
282
{
283
  if (!clist)
284
    return 0;
285

    
286
  struct f_val v;
287
  if (!clist_set_type(set, &v))
288
    return CMP_ERROR;
289

    
290
  u32 *l = (u32 *) clist->data;
291
  u32 *end = l + clist->length/4;
292

    
293
  while (l < end) {
294
    v.val.i = *l++;
295
    if (find_tree(set, v))
296
      return 1;
297
  }
298
  return 0;
299
}
300

    
301
static int
302
eclist_match_set(struct adata *list, struct f_tree *set)
303
{
304
  if (!list)
305
    return 0;
306

    
307
  if (!eclist_set_type(set))
308
    return CMP_ERROR;
309

    
310
  struct f_val v;
311
  u32 *l = int_set_get_data(list);
312
  int len = int_set_get_size(list);
313
  int i;
314

    
315
  v.type = T_EC;
316
  for (i = 0; i < len; i += 2) {
317
    v.val.ec = ec_get(l, i);
318
    if (find_tree(set, v))
319
      return 1;
320
  }
321

    
322
  return 0;
323
}
324

    
325
static struct adata *
326
clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
327
{
328
  if (!list)
329
    return NULL;
330

    
331
  int tree = (set.type == T_SET);        /* 1 -> set is T_SET, 0 -> set is T_CLIST */
332
  struct f_val v;
333
  if (tree)
334
    clist_set_type(set.val.t, &v);
335
  else
336
    v.type = T_PAIR;
337

    
338
  int len = int_set_get_size(list);
339
  u32 *l = int_set_get_data(list);
340
  u32 tmp[len];
341
  u32 *k = tmp;
342
  u32 *end = l + len;
343

    
344
  while (l < end) {
345
    v.val.i = *l++;
346
    /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
347
    if ((tree ? !!find_tree(set.val.t, v) : int_set_contains(set.val.ad, v.val.i)) == pos)
348
      *k++ = v.val.i;
349
  }
350

    
351
  int nl = (k - tmp) * 4;
352
  if (nl == list->length)
353
    return list;
354

    
355
  struct adata *res = adata_empty(pool, nl);
356
  memcpy(res->data, tmp, nl);
357
  return res;
358
}
359

    
360
static struct adata *
361
eclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
362
{
363
  if (!list)
364
    return NULL;
365

    
366
  int tree = (set.type == T_SET);        /* 1 -> set is T_SET, 0 -> set is T_CLIST */
367
  struct f_val v;
368

    
369
  int len = int_set_get_size(list);
370
  u32 *l = int_set_get_data(list);
371
  u32 tmp[len];
372
  u32 *k = tmp;
373
  int i;
374

    
375
  v.type = T_EC;
376
  for (i = 0; i < len; i += 2) {
377
    v.val.ec = ec_get(l, i);
378
    /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
379
    if ((tree ? !!find_tree(set.val.t, v) : ec_set_contains(set.val.ad, v.val.ec)) == pos) {
380
      *k++ = l[i];
381
      *k++ = l[i+1];
382
    }
383
  }
384

    
385
  int nl = (k - tmp) * 4;
386
  if (nl == list->length)
387
    return list;
388

    
389
  struct adata *res = adata_empty(pool, nl);
390
  memcpy(res->data, tmp, nl);
391
  return res;
392
}
393

    
394
/**
395
 * val_in_range - implement |~| operator
396
 * @v1: element
397
 * @v2: set
398
 *
399
 * Checks if @v1 is element (|~| operator) of @v2. Sets are internally represented as balanced trees, see
400
 * |tree.c| module (this is not limited to sets, but for non-set cases, val_simple_in_range() is called early).
401
 */
402
static int
403
val_in_range(struct f_val v1, struct f_val v2)
404
{
405
  int res;
406

    
407
  res = val_simple_in_range(v1, v2);
408

    
409
  if (res != CMP_ERROR)
410
    return res;
411
  
412
  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX_SET))
413
    return trie_match_fprefix(v2.val.ti, &v1.val.px);
414

    
415
  if ((v1.type == T_CLIST) && (v2.type == T_SET))
416
    return clist_match_set(v1.val.ad, v2.val.t);
417

    
418
  if ((v1.type == T_ECLIST) && (v2.type == T_SET))
419
    return eclist_match_set(v1.val.ad, v2.val.t);
420

    
421
  if ((v1.type == T_PATH) && (v2.type == T_SET))
422
    return as_path_match_set(v1.val.ad, v2.val.t);
423

    
424
  if (v2.type == T_SET)
425
    switch (v1.type) {
426
    case T_ENUM:
427
    case T_INT:
428
    case T_PAIR:
429
    case T_QUAD:
430
    case T_IP:
431
    case T_EC:
432
      {
433
        struct f_tree *n;
434
        n = find_tree(v2.val.t, v1);
435
        if (!n)
436
          return 0;
437
        return !! (val_simple_in_range(v1, n->from));        /* We turn CMP_ERROR into compared ok, and that's fine */
438
      }
439
    }
440
  return CMP_ERROR;
441
}
442

    
443
static void
444
tree_node_print(struct f_tree *t, char **sep)
445
{
446
  if (t == NULL)
447
    return;
448

    
449
  tree_node_print(t->left, sep);
450

    
451
  logn(*sep);
452
  val_print(t->from);
453
  if (val_compare(t->from, t->to) != 0)
454
    {
455
      logn( ".." );
456
      val_print(t->to);
457
    }
458
  *sep = ", ";
459

    
460
  tree_node_print(t->right, sep);
461
}
462

    
463
static void
464
tree_print(struct f_tree *t)
465
{
466
  char *sep = "";
467
  logn( "[" );
468
  tree_node_print(t, &sep);
469
  logn( "] " );
470
}
471

    
472
/*
473
 * val_print - format filter value
474
 */
475
void
476
val_print(struct f_val v)
477
{
478
  char buf2[1024];
479
  switch (v.type) {
480
  case T_VOID: logn("(void)"); return;
481
  case T_BOOL: logn(v.val.i ? "TRUE" : "FALSE"); return;
482
  case T_INT: logn("%d", v.val.i); return;
483
  case T_STRING: logn("%s", v.val.s); return;
484
  case T_IP: logn("%I", v.val.px.ip); return;
485
  case T_PREFIX: logn("%I/%d", v.val.px.ip, v.val.px.len); return;
486
  case T_PAIR: logn("(%d,%d)", v.val.i >> 16, v.val.i & 0xffff); return;
487
  case T_QUAD: logn("%R", v.val.i); return;
488
  case T_EC: ec_format(buf2, v.val.ec); logn("%s", buf2); return;
489
  case T_PREFIX_SET: trie_print(v.val.ti); return;
490
  case T_SET: tree_print(v.val.t); return;
491
  case T_ENUM: logn("(enum %x)%d", v.type, v.val.i); return;
492
  case T_PATH: as_path_format(v.val.ad, buf2, 1000); logn("(path %s)", buf2); return;
493
  case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); logn("(clist %s)", buf2); return;
494
  case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); logn("(eclist %s)", buf2); return;
495
  case T_PATH_MASK: pm_format(v.val.path_mask, buf2, 1000); logn("(pathmask%s)", buf2); return;
496
  default: logn( "[unknown type %x]", v.type ); return;
497
  }
498
}
499

    
500
static struct rte **f_rte;
501
static struct rta *f_old_rta;
502
static struct ea_list **f_tmp_attrs;
503
static struct linpool *f_pool;
504
static int f_flags;
505

    
506
static inline void f_rte_cow(void)
507
{
508
  *f_rte = rte_cow(*f_rte); 
509
}
510

    
511
/*
512
 * rta_cow - prepare rta for modification by filter
513
 */
514
static void
515
f_rta_cow(void)
516
{
517
  if ((*f_rte)->attrs->aflags & RTAF_CACHED) {
518

    
519
    /* Prepare to modify rte */
520
    f_rte_cow();
521

    
522
    /* Store old rta to free it later */
523
    f_old_rta = (*f_rte)->attrs;
524

    
525
    /* 
526
     * Alloc new rta, do shallow copy and update rte. Fields eattrs
527
     * and nexthops of rta are shared with f_old_rta (they will be
528
     * copied when the cached rta will be obtained at the end of
529
     * f_run()), also the lock of hostentry is inherited (we suppose
530
     * hostentry is not changed by filters).
531
     */
532
    rta *ra = lp_alloc(f_pool, sizeof(rta));
533
    memcpy(ra, f_old_rta, sizeof(rta));
534
    ra->aflags = 0;
535
    (*f_rte)->attrs = ra;
536
  }
537
}
538

    
539
static struct rate_limit rl_runtime_err;
540

    
541
#define runtime(x) do { \
542
    log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \
543
    res.type = T_RETURN; \
544
    res.val.i = F_ERROR; \
545
    return res; \
546
  } while(0)
547

    
548
#define ARG(x,y) \
549
        x = interpret(what->y); \
550
        if (x.type & T_RETURN) \
551
                return x;
552

    
553
#define ONEARG ARG(v1, a1.p)
554
#define TWOARGS ARG(v1, a1.p) \
555
                ARG(v2, a2.p)
556
#define TWOARGS_C TWOARGS \
557
                  if (v1.type != v2.type) \
558
                    runtime( "Can't operate with values of incompatible types" );
559
#define ACCESS_RTE \
560
  do { if (!f_rte) runtime("No route to access"); } while (0)
561

    
562
/**
563
 * interpret
564
 * @what: filter to interpret
565
 *
566
 * Interpret given tree of filter instructions. This is core function
567
 * of filter system and does all the hard work.
568
 *
569
 * Each instruction has 4 fields: code (which is instruction code),
570
 * aux (which is extension to instruction code, typically type),
571
 * arg1 and arg2 - arguments. Depending on instruction, arguments
572
 * are either integers, or pointers to instruction trees. Common 
573
 * instructions like +, that have two expressions as arguments use
574
 * TWOARGS macro to get both of them evaluated.
575
 *
576
 * &f_val structures are copied around, so there are no problems with
577
 * memory managment.
578
 */
579
static struct f_val
580
interpret(struct f_inst *what)
581
{
582
  struct symbol *sym;
583
  struct f_val v1, v2, res, *vp;
584
  unsigned u1, u2;
585
  int i;
586
  u32 as;
587

    
588
  res.type = T_VOID;
589
  if (!what)
590
    return res;
591

    
592
  switch(what->code) {
593
  case ',':
594
    TWOARGS;
595
    break;
596

    
597
/* Binary operators */
598
  case '+':
599
    TWOARGS_C;
600
    switch (res.type = v1.type) {
601
    case T_VOID: runtime( "Can't operate with values of type void" );
602
    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
603
    default: runtime( "Usage of unknown type" );
604
    }
605
    break;
606
  case '-':
607
    TWOARGS_C;
608
    switch (res.type = v1.type) {
609
    case T_VOID: runtime( "Can't operate with values of type void" );
610
    case T_INT: res.val.i = v1.val.i - v2.val.i; break;
611
    default: runtime( "Usage of unknown type" );
612
    }
613
    break;
614
  case '*':
615
    TWOARGS_C;
616
    switch (res.type = v1.type) {
617
    case T_VOID: runtime( "Can't operate with values of type void" );
618
    case T_INT: res.val.i = v1.val.i * v2.val.i; break;
619
    default: runtime( "Usage of unknown type" );
620
    }
621
    break;
622
  case '/':
623
    TWOARGS_C;
624
    switch (res.type = v1.type) {
625
    case T_VOID: runtime( "Can't operate with values of type void" );
626
    case T_INT: if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" );
627
                      res.val.i = v1.val.i / v2.val.i; break;
628
    default: runtime( "Usage of unknown type" );
629
    }
630
    break;
631
    
632
  case '&':
633
  case '|':
634
    ARG(v1, a1.p);
635
    if (v1.type != T_BOOL)
636
      runtime( "Can't do boolean operation on non-booleans" );
637
    if (v1.val.i == (what->code == '|')) {
638
      res.type = T_BOOL;
639
      res.val.i = v1.val.i;
640
      break;
641
    }
642

    
643
    ARG(v2, a2.p);
644
    if (v2.type != T_BOOL)
645
      runtime( "Can't do boolean operation on non-booleans" );
646
    res.type = T_BOOL;
647
    res.val.i = v2.val.i;
648
    break;
649

    
650
  case P('m','p'):
651
    TWOARGS;
652
    if ((v1.type != T_INT) || (v2.type != T_INT))
653
      runtime( "Can't operate with value of non-integer type in pair constructor" );
654
    u1 = v1.val.i;
655
    u2 = v2.val.i;
656
    if ((u1 > 0xFFFF) || (u2 > 0xFFFF))
657
      runtime( "Can't operate with value out of bounds in pair constructor" );
658
    res.val.i = (u1 << 16) | u2;
659
    res.type = T_PAIR;
660
    break;
661

    
662
  case P('m','c'):
663
    {
664
      TWOARGS;
665

    
666
      int check, ipv4_used;
667
      u32 key, val;
668

    
669
      if (v1.type == T_INT) {
670
        ipv4_used = 0; key = v1.val.i;
671
      } 
672
      else if (v1.type == T_QUAD) {
673
        ipv4_used = 1; key = v1.val.i;
674
      }
675
#ifndef IPV6
676
      /* IP->Quad implicit conversion */
677
      else if (v1.type == T_IP) {
678
        ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip);
679
      }
680
#endif
681
      else
682
        runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
683

    
684
      if (v2.type != T_INT)
685
        runtime("Can't operate with value of non-integer type in EC constructor");
686
      val = v2.val.i;
687

    
688
      res.type = T_EC;
689

    
690
      if (what->aux == EC_GENERIC) {
691
        check = 0; res.val.ec = ec_generic(key, val);
692
      }
693
      else if (ipv4_used) {
694
        check = 1; res.val.ec = ec_ip4(what->aux, key, val);
695
      }
696
      else if (key < 0x10000) {
697
        check = 0; res.val.ec = ec_as2(what->aux, key, val);
698
      }
699
      else {
700
        check = 1; res.val.ec = ec_as4(what->aux, key, val);
701
      }
702

    
703
      if (check && (val > 0xFFFF))
704
        runtime("Can't operate with value out of bounds in EC constructor");
705

    
706
      break;
707
    }
708

    
709
/* Relational operators */
710

    
711
#define COMPARE(x) \
712
    TWOARGS; \
713
    i = val_compare(v1, v2); \
714
    if (i==CMP_ERROR) \
715
      runtime( "Can't compare values of incompatible types" ); \
716
    res.type = T_BOOL; \
717
    res.val.i = (x); \
718
    break;
719

    
720
  case P('!','='): COMPARE(i!=0);
721
  case P('=','='): COMPARE(i==0);
722
  case '<': COMPARE(i==-1);
723
  case P('<','='): COMPARE(i!=1);
724

    
725
  case '!':
726
    ONEARG;
727
    if (v1.type != T_BOOL)
728
      runtime( "Not applied to non-boolean" );
729
    res = v1;
730
    res.val.i = !res.val.i;
731
    break;
732

    
733
  case '~':
734
    TWOARGS;
735
    res.type = T_BOOL;
736
    res.val.i = val_in_range(v1, v2);
737
    if (res.val.i == CMP_ERROR)
738
      runtime( "~ applied on unknown type pair" );
739
    res.val.i = !!res.val.i;
740
    break;
741
  case P('d','e'):
742
    ONEARG;
743
    res.type = T_BOOL;
744
    res.val.i = (v1.type != T_VOID);
745
    break;
746

    
747
  /* Set to indirect value, a1 = variable, a2 = value */
748
  case 's':
749
    ARG(v2, a2.p);
750
    sym = what->a1.p;
751
    vp = sym->def;
752
    if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
753
#ifndef IPV6
754
      /* IP->Quad implicit conversion */
755
      if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) {
756
        vp->type = T_QUAD;
757
        vp->val.i = ipa_to_u32(v2.val.px.ip);
758
        break;
759
      }
760
#endif
761
      runtime( "Assigning to variable of incompatible type" );
762
    }
763
    *vp = v2; 
764
    break;
765

    
766
    /* some constants have value in a2, some in *a1.p, strange. */
767
  case 'c':        /* integer (or simple type) constant, string, set, or prefix_set */
768
    res.type = what->aux;
769

    
770
    if (res.type == T_PREFIX_SET)
771
      res.val.ti = what->a2.p;
772
    else if (res.type == T_SET)
773
      res.val.t = what->a2.p;
774
    else if (res.type == T_STRING)
775
      res.val.s = what->a2.p;
776
    else
777
      res.val.i = what->a2.i;
778
    break;
779
  case 'V':
780
  case 'C':
781
    res = * ((struct f_val *) what->a1.p);
782
    break;
783
  case 'p':
784
    ONEARG;
785
    val_print(v1);
786
    break;
787
  case '?':        /* ? has really strange error value, so we can implement if ... else nicely :-) */
788
    ONEARG;
789
    if (v1.type != T_BOOL)
790
      runtime( "If requires boolean expression" );
791
    if (v1.val.i) {
792
      ARG(res,a2.p);
793
      res.val.i = 0;
794
    } else res.val.i = 1;
795
    res.type = T_BOOL;
796
    break;
797
  case '0':
798
    debug( "No operation\n" );
799
    break;
800
  case P('p',','):
801
    ONEARG;
802
    if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
803
      log_commit(*L_INFO);
804

    
805
    switch (what->a2.i) {
806
    case F_QUITBIRD:
807
      die( "Filter asked me to die" );
808
    case F_ACCEPT:
809
      /* Should take care about turning ACCEPT into MODIFY */
810
    case F_ERROR:
811
    case F_REJECT:        /* FIXME (noncritical) Should print complete route along with reason to reject route */
812
      res.type = T_RETURN;
813
      res.val.i = what->a2.i;
814
      return res;        /* We have to return now, no more processing. */
815
    case F_NONL:
816
    case F_NOP:
817
      break;
818
    default:
819
      bug( "unknown return type: Can't happen");
820
    }
821
    break;
822
  case 'a':        /* rta access */
823
    {
824
      ACCESS_RTE;
825
      struct rta *rta = (*f_rte)->attrs;
826
      res.type = what->aux;
827
      switch(res.type) {
828
      case T_IP:
829
        res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
830
        break;
831
      case T_ENUM:
832
        res.val.i = * ((char *) rta + what->a2.i);
833
        break;
834
      case T_STRING:        /* Warning: this is a special case for proto attribute */
835
        res.val.s = rta->proto->name;
836
        break;
837
      case T_PREFIX:        /* Warning: this works only for prefix of network */
838
        {
839
          res.val.px.ip = (*f_rte)->net->n.prefix;
840
          res.val.px.len = (*f_rte)->net->n.pxlen;
841
          break;
842
        }
843
      default:
844
        bug( "Invalid type for rta access (%x)", res.type );
845
      }
846
    }
847
    break;
848
  case P('a','S'):
849
    ACCESS_RTE;
850
    ONEARG;
851
    if (what->aux != v1.type)
852
      runtime( "Attempt to set static attribute to incompatible type" );
853
    f_rta_cow();
854
    {
855
      struct rta *rta = (*f_rte)->attrs;
856
      switch (what->aux) {
857

    
858
      case T_IP:
859
        * (ip_addr *) ((char *) rta + what->a2.i) = v1.val.px.ip;
860
        break;
861

    
862
      case T_ENUM_SCOPE:
863
        rta->scope = v1.val.i;
864
        break;
865

    
866
      case T_ENUM_RTD:
867
        i = v1.val.i;
868
        if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
869
          runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
870
        rta->dest = i;
871
        rta->gw = IPA_NONE;
872
        rta->iface = NULL;
873
        rta->nexthops = NULL;
874
        break;
875

    
876
      default:
877
        bug( "Unknown type in set of static attribute" );
878
      }
879
    }
880
    break;
881
  case P('e','a'):        /* Access to extended attributes */
882
    ACCESS_RTE;
883
    {
884
      eattr *e = NULL;
885
      if (!(f_flags & FF_FORCE_TMPATTR))
886
        e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
887
      if (!e) 
888
        e = ea_find( (*f_tmp_attrs), what->a2.i );
889
      if ((!e) && (f_flags & FF_FORCE_TMPATTR))
890
        e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
891

    
892
      if (!e) {
893
        /* A special case: undefined int_set looks like empty int_set */
894
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) {
895
          res.type = T_CLIST;
896
          res.val.ad = adata_empty(f_pool, 0);
897
          break;
898
        }
899
        /* The same special case for ec_set */
900
        else if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
901
          res.type = T_ECLIST;
902
          res.val.ad = adata_empty(f_pool, 0);
903
          break;
904
        }
905

    
906
        /* Undefined value */
907
        res.type = T_VOID;
908
        break;
909
      }
910

    
911
      switch (what->aux & EAF_TYPE_MASK) {
912
      case EAF_TYPE_INT:
913
        res.type = T_INT;
914
        res.val.i = e->u.data;
915
        break;
916
      case EAF_TYPE_ROUTER_ID:
917
        res.type = T_QUAD;
918
        res.val.i = e->u.data;
919
        break;
920
      case EAF_TYPE_OPAQUE:
921
        res.type = T_ENUM_EMPTY;
922
        res.val.i = 0;
923
        break;
924
      case EAF_TYPE_IP_ADDRESS:
925
        res.type = T_IP;
926
        struct adata * ad = e->u.ptr;
927
        res.val.px.ip = * (ip_addr *) ad->data;
928
        break;
929
      case EAF_TYPE_AS_PATH:
930
        res.type = T_PATH;
931
        res.val.ad = e->u.ptr;
932
        break;
933
      case EAF_TYPE_INT_SET:
934
        res.type = T_CLIST;
935
        res.val.ad = e->u.ptr;
936
        break;
937
      case EAF_TYPE_EC_SET:
938
        res.type = T_ECLIST;
939
        res.val.ad = e->u.ptr;
940
        break;
941
      case EAF_TYPE_UNDEF:
942
        res.type = T_VOID;
943
        break;
944
      default:
945
        bug("Unknown type in e,a");
946
      }
947
    }
948
    break;
949
  case P('e','S'):
950
    ACCESS_RTE;
951
    ONEARG;
952
    {
953
      struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
954

    
955
      l->next = NULL;
956
      l->flags = EALF_SORTED;
957
      l->count = 1;
958
      l->attrs[0].id = what->a2.i;
959
      l->attrs[0].flags = 0;
960
      l->attrs[0].type = what->aux | EAF_ORIGINATED;
961
      switch (what->aux & EAF_TYPE_MASK) {
962
      case EAF_TYPE_INT:
963
        if (v1.type != T_INT)
964
          runtime( "Setting int attribute to non-int value" );
965
        l->attrs[0].u.data = v1.val.i;
966
        break;
967

    
968
      case EAF_TYPE_ROUTER_ID:
969
#ifndef IPV6
970
        /* IP->Quad implicit conversion */
971
        if (v1.type == T_IP) {
972
          l->attrs[0].u.data = ipa_to_u32(v1.val.px.ip);
973
          break;
974
        }
975
#endif
976
        /* T_INT for backward compatibility */
977
        if ((v1.type != T_QUAD) && (v1.type != T_INT))
978
          runtime( "Setting quad attribute to non-quad value" );
979
        l->attrs[0].u.data = v1.val.i;
980
        break;
981

    
982
      case EAF_TYPE_OPAQUE:
983
        runtime( "Setting opaque attribute is not allowed" );
984
        break;
985
      case EAF_TYPE_IP_ADDRESS:
986
        if (v1.type != T_IP)
987
          runtime( "Setting ip attribute to non-ip value" );
988
        int len = sizeof(ip_addr);
989
        struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
990
        ad->length = len;
991
        (* (ip_addr *) ad->data) = v1.val.px.ip;
992
        l->attrs[0].u.ptr = ad;
993
        break;
994
      case EAF_TYPE_AS_PATH:
995
        if (v1.type != T_PATH)
996
          runtime( "Setting path attribute to non-path value" );
997
        l->attrs[0].u.ptr = v1.val.ad;
998
        break;
999
      case EAF_TYPE_INT_SET:
1000
        if (v1.type != T_CLIST)
1001
          runtime( "Setting clist attribute to non-clist value" );
1002
        l->attrs[0].u.ptr = v1.val.ad;
1003
        break;
1004
      case EAF_TYPE_EC_SET:
1005
        if (v1.type != T_ECLIST)
1006
          runtime( "Setting eclist attribute to non-eclist value" );
1007
        l->attrs[0].u.ptr = v1.val.ad;
1008
        break;
1009
      case EAF_TYPE_UNDEF:
1010
        if (v1.type != T_VOID)
1011
          runtime( "Setting void attribute to non-void value" );
1012
        l->attrs[0].u.data = 0;
1013
        break;
1014
      default: bug("Unknown type in e,S");
1015
      }
1016

    
1017
      if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
1018
        f_rta_cow();
1019
        l->next = (*f_rte)->attrs->eattrs;
1020
        (*f_rte)->attrs->eattrs = l;
1021
      } else {
1022
        l->next = (*f_tmp_attrs);
1023
        (*f_tmp_attrs) = l;
1024
      }
1025
    }
1026
    break;
1027
  case 'P':
1028
    ACCESS_RTE;
1029
    res.type = T_INT;
1030
    res.val.i = (*f_rte)->pref;
1031
    break;
1032
  case P('P','S'):
1033
    ACCESS_RTE;
1034
    ONEARG;
1035
    if (v1.type != T_INT)
1036
      runtime( "Can't set preference to non-integer" );
1037
    if ((v1.val.i < 0) || (v1.val.i > 0xFFFF))
1038
      runtime( "Setting preference value out of bounds" );
1039
    f_rte_cow();
1040
    (*f_rte)->pref = v1.val.i;
1041
    break;
1042
  case 'L':        /* Get length of */
1043
    ONEARG;
1044
    res.type = T_INT;
1045
    switch(v1.type) {
1046
    case T_PREFIX: res.val.i = v1.val.px.len; break;
1047
    case T_PATH:   res.val.i = as_path_getlen(v1.val.ad); break;
1048
    default: runtime( "Prefix or path expected" );
1049
    }
1050
    break;
1051
  case P('c','p'):        /* Convert prefix to ... */
1052
    ONEARG;
1053
    if (v1.type != T_PREFIX)
1054
      runtime( "Prefix expected" );
1055
    res.type = what->aux;
1056
    switch(res.type) {
1057
      /*    case T_INT:        res.val.i = v1.val.px.len; break; Not needed any more */
1058
    case T_IP: res.val.px.ip = v1.val.px.ip; break;
1059
    default: bug( "Unknown prefix to conversion" );
1060
    }
1061
    break;
1062
  case P('a','f'):        /* Get first ASN from AS PATH */
1063
    ONEARG;
1064
    if (v1.type != T_PATH)
1065
      runtime( "AS path expected" );
1066

    
1067
    as = 0;
1068
    as_path_get_first(v1.val.ad, &as);
1069
    res.type = T_INT;
1070
    res.val.i = as;
1071
    break;
1072
  case P('a','l'):        /* Get last ASN from AS PATH */
1073
    ONEARG;
1074
    if (v1.type != T_PATH)
1075
      runtime( "AS path expected" );
1076

    
1077
    as = 0;
1078
    as_path_get_last(v1.val.ad, &as);
1079
    res.type = T_INT;
1080
    res.val.i = as;
1081
    break;
1082
  case 'r':
1083
    ONEARG;
1084
    res = v1;
1085
    res.type |= T_RETURN;
1086
    return res;
1087
  case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
1088
    ONEARG;
1089
    res = interpret(what->a2.p);
1090
    if (res.type == T_RETURN)
1091
      return res;
1092
    res.type &= ~T_RETURN;    
1093
    break;
1094
  case P('c','v'):        /* Clear local variables */
1095
    for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
1096
      ((struct f_val *) sym->def)->type = T_VOID;
1097
    break;
1098
  case P('S','W'):
1099
    ONEARG;
1100
    {
1101
      struct f_tree *t = find_tree(what->a2.p, v1);
1102
      if (!t) {
1103
        v1.type = T_VOID;
1104
        t = find_tree(what->a2.p, v1);
1105
        if (!t) {
1106
          debug( "No else statement?\n");
1107
          break;
1108
        }
1109
      }        
1110
      /* It is actually possible to have t->data NULL */
1111

    
1112
      res = interpret(t->data);
1113
      if (res.type & T_RETURN)
1114
        return res;
1115
    }
1116
    break;
1117
  case P('i','M'): /* IP.MASK(val) */
1118
    TWOARGS;
1119
    if (v2.type != T_INT)
1120
      runtime( "Integer expected");
1121
    if (v1.type != T_IP)
1122
      runtime( "You can mask only IP addresses" );
1123
    {
1124
      ip_addr mask = ipa_mkmask(v2.val.i);
1125
      res.type = T_IP;
1126
      res.val.px.ip = ipa_and(mask, v1.val.px.ip);
1127
    }
1128
    break;
1129

    
1130
  case 'E':        /* Create empty attribute */
1131
    res.type = what->aux;
1132
    res.val.ad = adata_empty(f_pool, 0);
1133
    break;
1134
  case P('A','p'):        /* Path prepend */
1135
    TWOARGS;
1136
    if (v1.type != T_PATH)
1137
      runtime("Can't prepend to non-path");
1138
    if (v2.type != T_INT)
1139
      runtime("Can't prepend non-integer");
1140

    
1141
    res.type = T_PATH;
1142
    res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
1143
    break;
1144

    
1145
  case P('C','a'):        /* (Extended) Community list add or delete */
1146
    TWOARGS;
1147
    if (v1.type == T_CLIST)
1148
    {
1149
      /* Community (or cluster) list */
1150
      struct f_val dummy;
1151
      int arg_set = 0;
1152
      i = 0;
1153

    
1154
      if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
1155
        i = v2.val.i;
1156
#ifndef IPV6
1157
      /* IP->Quad implicit conversion */
1158
      else if (v2.type == T_IP)
1159
        i = ipa_to_u32(v2.val.px.ip);
1160
#endif
1161
      else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
1162
        arg_set = 1;
1163
      else if (v2.type == T_CLIST)
1164
        arg_set = 2;
1165
      else
1166
        runtime("Can't add/delete non-pair");
1167

    
1168
      res.type = T_CLIST;
1169
      switch (what->aux)
1170
      {
1171
      case 'a':
1172
        if (arg_set == 1)
1173
          runtime("Can't add set");
1174
        else if (!arg_set)
1175
          res.val.ad = int_set_add(f_pool, v1.val.ad, i);
1176
        else 
1177
          res.val.ad = int_set_union(f_pool, v1.val.ad, v2.val.ad);
1178
        break;
1179
      
1180
      case 'd':
1181
        if (!arg_set)
1182
          res.val.ad = int_set_del(f_pool, v1.val.ad, i);
1183
        else
1184
          res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 0);
1185
        break;
1186

    
1187
      case 'f':
1188
        if (!arg_set)
1189
          runtime("Can't filter pair");
1190
        res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 1);
1191
        break;
1192

    
1193
      default:
1194
        bug("unknown Ca operation");
1195
      }
1196
    }
1197
    else if (v1.type == T_ECLIST)
1198
    {
1199
      /* Extended community list */
1200
      int arg_set = 0;
1201
      
1202
      /* v2.val is either EC or EC-set */
1203
      if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
1204
        arg_set = 1;
1205
      else if (v2.type == T_ECLIST)
1206
        arg_set = 2;
1207
      else if (v2.type != T_EC)
1208
        runtime("Can't add/delete non-pair");
1209

    
1210
      res.type = T_ECLIST;
1211
      switch (what->aux)
1212
      {
1213
      case 'a':
1214
        if (arg_set == 1)
1215
          runtime("Can't add set");
1216
        else if (!arg_set)
1217
          res.val.ad = ec_set_add(f_pool, v1.val.ad, v2.val.ec);
1218
        else 
1219
          res.val.ad = ec_set_union(f_pool, v1.val.ad, v2.val.ad);
1220
        break;
1221
      
1222
      case 'd':
1223
        if (!arg_set)
1224
          res.val.ad = ec_set_del(f_pool, v1.val.ad, v2.val.ec);
1225
        else
1226
          res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 0);
1227
        break;
1228

    
1229
      case 'f':
1230
        if (!arg_set)
1231
          runtime("Can't filter ec");
1232
        res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 1);
1233
        break;
1234

    
1235
      default:
1236
        bug("unknown Ca operation");
1237
      }
1238
    }
1239
    else
1240
      runtime("Can't add/delete to non-(e)clist");
1241

    
1242
    break;
1243

    
1244
  case P('R','C'):        /* ROA Check */
1245
    if (what->arg1)
1246
    {
1247
      TWOARGS;
1248
      if ((v1.type != T_PREFIX) || (v2.type != T_INT))
1249
        runtime("Invalid argument to roa_check()");
1250

    
1251
      as = v2.val.i;
1252
    }
1253
    else
1254
    {
1255
      ACCESS_RTE;
1256
      v1.val.px.ip = (*f_rte)->net->n.prefix;
1257
      v1.val.px.len = (*f_rte)->net->n.pxlen;
1258

    
1259
      /* We ignore temporary attributes, probably not a problem here */
1260
      /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
1261
      eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(EAP_BGP, 0x02));
1262

    
1263
      if (!e || e->type != EAF_TYPE_AS_PATH)
1264
        runtime("Missing AS_PATH attribute");
1265

    
1266
      as_path_get_last(e->u.ptr, &as);
1267
    }
1268

    
1269
    struct roa_table_config *rtc = ((struct f_inst_roa_check *) what)->rtc;
1270
    if (!rtc->table)
1271
      runtime("Missing ROA table");
1272

    
1273
    res.type = T_ENUM_ROA;
1274
    res.val.i = roa_check(rtc->table, v1.val.px.ip, v1.val.px.len, as);
1275
    break;
1276

    
1277
  default:
1278
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
1279
  }
1280
  if (what->next)
1281
    return interpret(what->next);
1282
  return res;
1283
}
1284

    
1285
#undef ARG
1286
#define ARG(x,y) \
1287
        if (!i_same(f1->y, f2->y)) \
1288
                return 0;
1289

    
1290
#define ONEARG ARG(v1, a1.p)
1291
#define TWOARGS ARG(v1, a1.p) \
1292
                ARG(v2, a2.p)
1293

    
1294
#define A2_SAME if (f1->a2.i != f2->a2.i) return 0;
1295

    
1296
/*
1297
 * i_same - function that does real comparing of instruction trees, you should call filter_same from outside
1298
 */
1299
int
1300
i_same(struct f_inst *f1, struct f_inst *f2)
1301
{
1302
  if ((!!f1) != (!!f2))
1303
    return 0;
1304
  if (!f1)
1305
    return 1;
1306
  if (f1->aux != f2->aux)
1307
    return 0;
1308
  if (f1->code != f2->code)
1309
    return 0;
1310
  if (f1 == f2)                /* It looks strange, but it is possible with call rewriting trickery */
1311
    return 1;
1312

    
1313
  switch(f1->code) {
1314
  case ',': /* fall through */
1315
  case '+':
1316
  case '-':
1317
  case '*':
1318
  case '/':
1319
  case '|':
1320
  case '&':
1321
  case P('m','p'):
1322
  case P('m','c'):
1323
  case P('!','='):
1324
  case P('=','='):
1325
  case '<':
1326
  case P('<','='): TWOARGS; break;
1327

    
1328
  case '!': ONEARG; break;
1329
  case '~': TWOARGS; break;
1330
  case P('d','e'): ONEARG; break;
1331

    
1332
  case 's':
1333
    ARG(v2, a2.p);
1334
    {
1335
      struct symbol *s1, *s2;
1336
      s1 = f1->a1.p;
1337
      s2 = f2->a1.p;
1338
      if (strcmp(s1->name, s2->name))
1339
        return 0;
1340
      if (s1->class != s2->class)
1341
        return 0;
1342
    }
1343
    break;
1344

    
1345
  case 'c': 
1346
    switch (f1->aux) {
1347

    
1348
    case T_PREFIX_SET:
1349
      if (!trie_same(f1->a2.p, f2->a2.p))
1350
        return 0;
1351
      break;
1352

    
1353
    case T_SET:
1354
      if (!same_tree(f1->a2.p, f2->a2.p))
1355
        return 0;
1356
      break;
1357

    
1358
    case T_STRING:
1359
      if (strcmp(f1->a2.p, f2->a2.p))
1360
        return 0;
1361
      break;
1362

    
1363
    default:
1364
      A2_SAME;
1365
    }
1366
    break;
1367
  case 'C': 
1368
    if (val_compare(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
1369
      return 0;
1370
    break;
1371
  case 'V': 
1372
    if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
1373
      return 0;
1374
    break;
1375
  case 'p': case 'L': ONEARG; break;
1376
  case '?': TWOARGS; break;
1377
  case '0': case 'E': break;
1378
  case P('p',','): ONEARG; A2_SAME; break;
1379
  case 'P':
1380
  case 'a': A2_SAME; break;
1381
  case P('e','a'): A2_SAME; break;
1382
  case P('P','S'):
1383
  case P('a','S'):
1384
  case P('e','S'): ONEARG; A2_SAME; break;
1385

    
1386
  case 'r': ONEARG; break;
1387
  case P('c','p'): ONEARG; break;
1388
  case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
1389
             ONEARG; 
1390
             if (!i_same(f1->a2.p, f2->a2.p))
1391
               return 0; 
1392
             f2->a2.p = f1->a2.p;
1393
             break;
1394
  case P('c','v'): break; /* internal instruction */ 
1395
  case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
1396
  case P('i','M'): TWOARGS; break;
1397
  case P('A','p'): TWOARGS; break;
1398
  case P('C','a'): TWOARGS; break;
1399
  case P('a','f'):
1400
  case P('a','l'): ONEARG; break;
1401
  case P('R','C'):
1402
    TWOARGS;
1403
    /* Does not really make sense - ROA check resuls may change anyway */
1404
    if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name, 
1405
               ((struct f_inst_roa_check *) f2)->rtc->name))
1406
      return 0;
1407
    break;
1408
  default:
1409
    bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
1410
  }
1411
  return i_same(f1->next, f2->next);
1412
}
1413

    
1414
/**
1415
 * f_run - run a filter for a route
1416
 * @filter: filter to run
1417
 * @rte: route being filtered, may be modified
1418
 * @tmp_attrs: temporary attributes, prepared by caller or generated by f_run()
1419
 * @tmp_pool: all filter allocations go from this pool
1420
 * @flags: flags
1421
 *
1422
 * If filter needs to modify the route, there are several
1423
 * posibilities. @rte might be read-only (with REF_COW flag), in that
1424
 * case rw copy is obtained by rte_cow() and @rte is replaced. If
1425
 * @rte is originally rw, it may be directly modified (and it is never
1426
 * copied).
1427
 *
1428
 * The returned rte may reuse the (possibly cached, cloned) rta, or
1429
 * (if rta was modificied) contains a modified uncached rta, which
1430
 * uses parts allocated from @tmp_pool and parts shared from original
1431
 * rta. There is one exception - if @rte is rw but contains a cached
1432
 * rta and that is modified, rta in returned rte is also cached.
1433
 *
1434
 * Ownership of cached rtas is consistent with rte, i.e.
1435
 * if a new rte is returned, it has its own clone of cached rta
1436
 * (and cached rta of read-only source rte is intact), if rte is
1437
 * modified in place, old cached rta is possibly freed.
1438
 */
1439
int
1440
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
1441
{
1442
  if (filter == FILTER_ACCEPT)
1443
    return F_ACCEPT;
1444

    
1445
  if (filter == FILTER_REJECT)
1446
    return F_REJECT;
1447

    
1448
  int rte_cow = ((*rte)->flags & REF_COW);
1449
  DBG( "Running filter `%s'...", filter->name );
1450

    
1451
  f_rte = rte;
1452
  f_old_rta = NULL;
1453
  f_tmp_attrs = tmp_attrs;
1454
  f_pool = tmp_pool;
1455
  f_flags = flags;
1456

    
1457
  log_reset();
1458
  struct f_val res = interpret(filter->root);
1459

    
1460
  if (f_old_rta) {
1461
    /*
1462
     * Cached rta was modified and f_rte contains now an uncached one,
1463
     * sharing some part with the cached one. The cached rta should
1464
     * be freed (if rte was originally COW, f_old_rta is a clone
1465
     * obtained during rte_cow()).
1466
     *
1467
     * This also implements the exception mentioned in f_run()
1468
     * description. The reason for this is that rta reuses parts of
1469
     * f_old_rta, and these may be freed during rta_free(f_old_rta).
1470
     * This is not the problem if rte was COW, because original rte
1471
     * also holds the same rta.
1472
     */
1473
    if (!rte_cow)
1474
      (*f_rte)->attrs = rta_lookup((*f_rte)->attrs);
1475

    
1476
    rta_free(f_old_rta);
1477
  }
1478

    
1479

    
1480
  if (res.type != T_RETURN) {
1481
    log( L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name); 
1482
    return F_ERROR;
1483
  }
1484
  DBG( "done (%d)\n", res.val.i );
1485
  return res.val.i;
1486
}
1487

    
1488
struct f_val
1489
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
1490
{
1491
  f_flags = 0;
1492
  f_tmp_attrs = NULL;
1493
  f_rte = NULL;
1494
  f_pool = tmp_pool;
1495

    
1496
  log_reset();
1497
  return interpret(expr);
1498
}
1499

    
1500
int
1501
f_eval_int(struct f_inst *expr)
1502
{
1503
  /* Called independently in parse-time to eval expressions */
1504
  struct f_val res = f_eval(expr, cfg_mem);
1505

    
1506
  if (res.type != T_INT)
1507
    cf_error("Integer expression expected");
1508

    
1509
  return res.val.i;
1510
}
1511

    
1512
u32
1513
f_eval_asn(struct f_inst *expr)
1514
{
1515
  /* Called as a part of another interpret call, therefore no log_reset() */
1516
  struct f_val res = interpret(expr);
1517
  return (res.type == T_INT) ? res.val.i : 0;
1518
}
1519

    
1520
/**
1521
 * filter_same - compare two filters
1522
 * @new: first filter to be compared
1523
 * @old: second filter to be compared, notice that this filter is
1524
 * damaged while comparing.
1525
 *
1526
 * Returns 1 in case filters are same, otherwise 0. If there are
1527
 * underlying bugs, it will rather say 0 on same filters than say
1528
 * 1 on different.
1529
 */
1530
int
1531
filter_same(struct filter *new, struct filter *old)
1532
{
1533
  if (old == new)        /* Handle FILTER_ACCEPT and FILTER_REJECT */
1534
    return 1;
1535
  if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
1536
      new == FILTER_ACCEPT || new == FILTER_REJECT)
1537
    return 0;
1538
  return i_same(new->root, old->root);
1539
}